swrast.c revision c73245882c7ff1277b190b97f093f7b423a22f10
1/*
2 * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
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/formats.h"
37#include "main/framebuffer.h"
38#include "main/imports.h"
39#include "main/renderbuffer.h"
40#include "swrast/swrast.h"
41#include "swrast/s_renderbuffer.h"
42#include "swrast_setup/swrast_setup.h"
43#include "tnl/tnl.h"
44#include "tnl/t_context.h"
45#include "tnl/t_pipeline.h"
46#include "vbo/vbo.h"
47#include "drivers/common/driverfuncs.h"
48#include "drivers/common/meta.h"
49#include "utils.h"
50
51#include "main/teximage.h"
52#include "main/texformat.h"
53#include "main/texstate.h"
54
55#include "swrast_priv.h"
56#include "swrast/s_context.h"
57
58
59/**
60 * Screen and config-related functions
61 */
62
63static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
64				GLint texture_format, __DRIdrawable *dPriv)
65{
66    struct dri_context *dri_ctx;
67    int x, y, w, h;
68    __DRIscreen *sPriv = dPriv->driScreenPriv;
69    struct gl_texture_unit *texUnit;
70    struct gl_texture_object *texObj;
71    struct gl_texture_image *texImage;
72    struct swrast_texture_image *swImage;
73    uint32_t internalFormat;
74    gl_format texFormat;
75
76    dri_ctx = pDRICtx->driverPrivate;
77
78    internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
79
80    texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base);
81    texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target);
82    texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
83    swImage = swrast_texture_image(texImage);
84
85    _mesa_lock_texture(&dri_ctx->Base, texObj);
86
87    sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);
88
89    if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
90	texFormat = MESA_FORMAT_XRGB8888;
91    else
92	texFormat = MESA_FORMAT_ARGB8888;
93
94    _mesa_init_teximage_fields(&dri_ctx->Base, texImage,
95			       w, h, 1, 0, internalFormat, texFormat);
96
97    sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer,
98				   dPriv->loaderPrivate);
99
100    _mesa_unlock_texture(&dri_ctx->Base, texObj);
101}
102
103static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
104			       __DRIdrawable *dPriv)
105{
106    swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
107}
108
109static const __DRItexBufferExtension swrastTexBufferExtension = {
110    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
111    swrastSetTexBuffer,
112    swrastSetTexBuffer2,
113};
114
115static const __DRIextension *dri_screen_extensions[] = {
116    &swrastTexBufferExtension.base,
117    NULL
118};
119
120static __DRIconfig **
121swrastFillInModes(__DRIscreen *psp,
122		  unsigned pixel_bits, unsigned depth_bits,
123		  unsigned stencil_bits, GLboolean have_back_buffer)
124{
125    __DRIconfig **configs;
126    unsigned depth_buffer_factor;
127    unsigned back_buffer_factor;
128    gl_format format;
129
130    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
131     * support pageflipping at all.
132     */
133    static const GLenum back_buffer_modes[] = {
134	GLX_NONE, GLX_SWAP_UNDEFINED_OML
135    };
136
137    uint8_t depth_bits_array[4];
138    uint8_t stencil_bits_array[4];
139    uint8_t msaa_samples_array[1];
140
141    (void) psp;
142    (void) have_back_buffer;
143
144    depth_bits_array[0] = 0;
145    depth_bits_array[1] = 0;
146    depth_bits_array[2] = depth_bits;
147    depth_bits_array[3] = depth_bits;
148
149    /* Just like with the accumulation buffer, always provide some modes
150     * with a stencil buffer.
151     */
152    stencil_bits_array[0] = 0;
153    stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
154    stencil_bits_array[2] = 0;
155    stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
156
157    msaa_samples_array[0] = 0;
158
159    depth_buffer_factor = 4;
160    back_buffer_factor = 2;
161
162    switch (pixel_bits) {
163    case 16:
164	format = MESA_FORMAT_RGB565;
165	break;
166    case 24:
167        format = MESA_FORMAT_XRGB8888;
168	break;
169    case 32:
170	format = MESA_FORMAT_ARGB8888;
171	break;
172    default:
173	fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
174		pixel_bits);
175	return NULL;
176    }
177
178    configs = driCreateConfigs(format,
179			       depth_bits_array, stencil_bits_array,
180			       depth_buffer_factor, back_buffer_modes,
181			       back_buffer_factor, msaa_samples_array, 1,
182			       GL_TRUE);
183    if (configs == NULL) {
184	fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
185		__LINE__);
186	return NULL;
187    }
188
189    return configs;
190}
191
192static const __DRIconfig **
193dri_init_screen(__DRIscreen * psp)
194{
195    __DRIconfig **configs16, **configs24, **configs32;
196
197    TRACE;
198
199    psp->extensions = dri_screen_extensions;
200
201    configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
202    configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
203    configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
204
205    configs24 = driConcatConfigs(configs16, configs24);
206    configs32 = driConcatConfigs(configs24, configs32);
207
208    return (const __DRIconfig **)configs32;
209}
210
211static void
212dri_destroy_screen(__DRIscreen * sPriv)
213{
214    TRACE;
215    (void) sPriv;
216}
217
218
219/**
220 * Framebuffer and renderbuffer-related functions.
221 */
222
223static GLuint
224choose_pixel_format(const struct gl_config *v)
225{
226    int depth = v->rgbBits;
227
228    if (depth == 32
229	&& v->redMask   == 0xff0000
230	&& v->greenMask == 0x00ff00
231	&& v->blueMask  == 0x0000ff)
232	return PF_A8R8G8B8;
233    else if (depth == 24
234	     && v->redMask   == 0xff0000
235	     && v->greenMask == 0x00ff00
236	     && v->blueMask  == 0x0000ff)
237	return PF_X8R8G8B8;
238    else if (depth == 16
239	     && v->redMask   == 0xf800
240	     && v->greenMask == 0x07e0
241	     && v->blueMask  == 0x001f)
242	return PF_R5G6B5;
243    else if (depth == 8
244	     && v->redMask   == 0x07
245	     && v->greenMask == 0x38
246	     && v->blueMask  == 0xc0)
247	return PF_R3G3B2;
248
249    _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
250    return 0;
251}
252
253static void
254swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
255{
256    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
257
258    TRACE;
259
260    free(xrb->Base.Buffer);
261    _mesa_delete_renderbuffer(ctx, rb);
262}
263
264/* see bytes_per_line in libGL */
265static INLINE int
266bytes_per_line(unsigned pitch_bits, unsigned mul)
267{
268   unsigned mask = mul - 1;
269
270   return ((pitch_bits + mask) & ~mask) / 8;
271}
272
273static GLboolean
274swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
275			   GLenum internalFormat, GLuint width, GLuint height)
276{
277    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
278
279    TRACE;
280
281    (void) ctx;
282    (void) internalFormat;
283
284    xrb->Base.Buffer = NULL;
285    rb->Width = width;
286    rb->Height = height;
287    xrb->pitch = bytes_per_line(width * xrb->bpp, 32);
288
289    return GL_TRUE;
290}
291
292static GLboolean
293swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
294			  GLenum internalFormat, GLuint width, GLuint height)
295{
296    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
297
298    TRACE;
299
300    free(xrb->Base.Buffer);
301
302    swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
303
304    xrb->Base.Buffer = malloc(height * xrb->pitch);
305
306    return GL_TRUE;
307}
308
309static struct dri_swrast_renderbuffer *
310swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv,
311			GLboolean front)
312{
313    struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
314    struct gl_renderbuffer *rb;
315    GLuint pixel_format;
316
317    TRACE;
318
319    if (!xrb)
320	return NULL;
321
322    rb = &xrb->Base.Base;
323
324    _mesa_init_renderbuffer(rb, 0);
325
326    pixel_format = choose_pixel_format(visual);
327
328    xrb->dPriv = dPriv;
329    xrb->Base.Base.Delete = swrast_delete_renderbuffer;
330    if (front) {
331        rb->AllocStorage = swrast_alloc_front_storage;
332    }
333    else {
334	rb->AllocStorage = swrast_alloc_back_storage;
335    }
336
337    switch (pixel_format) {
338    case PF_A8R8G8B8:
339	rb->Format = MESA_FORMAT_ARGB8888;
340	rb->InternalFormat = GL_RGBA;
341	rb->_BaseFormat = GL_RGBA;
342	xrb->bpp = 32;
343	break;
344    case PF_X8R8G8B8:
345	rb->Format = MESA_FORMAT_ARGB8888; /* XXX */
346	rb->InternalFormat = GL_RGB;
347	rb->_BaseFormat = GL_RGB;
348	xrb->bpp = 32;
349	break;
350    case PF_R5G6B5:
351	rb->Format = MESA_FORMAT_RGB565;
352	rb->InternalFormat = GL_RGB;
353	rb->_BaseFormat = GL_RGB;
354	xrb->bpp = 16;
355	break;
356    case PF_R3G3B2:
357	rb->Format = MESA_FORMAT_RGB332;
358	rb->InternalFormat = GL_RGB;
359	rb->_BaseFormat = GL_RGB;
360	xrb->bpp = 8;
361	break;
362    default:
363	return NULL;
364    }
365
366    return xrb;
367}
368
369static void
370swrast_map_renderbuffer(struct gl_context *ctx,
371			struct gl_renderbuffer *rb,
372			GLuint x, GLuint y, GLuint w, GLuint h,
373			GLbitfield mode,
374			GLubyte **out_map,
375			GLint *out_stride)
376{
377   struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
378   GLubyte *map = xrb->Base.Buffer;
379   int cpp = _mesa_get_format_bytes(rb->Format);
380   int stride = rb->Width * cpp;
381
382   if (rb->AllocStorage == swrast_alloc_front_storage) {
383      __DRIdrawable *dPriv = xrb->dPriv;
384      __DRIscreen *sPriv = dPriv->driScreenPriv;
385
386      xrb->map_mode = mode;
387      xrb->map_x = x;
388      xrb->map_y = y;
389      xrb->map_w = w;
390      xrb->map_h = h;
391
392      stride = w * cpp;
393      xrb->Base.Buffer = malloc(h * stride);
394
395      sPriv->swrast_loader->getImage(dPriv, x, y, w, h,
396				     (char *) xrb->Base.Buffer,
397				     dPriv->loaderPrivate);
398
399      *out_map = xrb->Base.Buffer;
400      *out_stride = stride;
401      return;
402   }
403
404   ASSERT(xrb->Base.Buffer);
405
406   if (rb->AllocStorage == swrast_alloc_back_storage) {
407      map += (rb->Height - 1) * stride;
408      stride = -stride;
409   }
410
411   map += (GLsizei)y * stride;
412   map += (GLsizei)x * cpp;
413
414   *out_map = map;
415   *out_stride = stride;
416}
417
418static void
419swrast_unmap_renderbuffer(struct gl_context *ctx,
420			  struct gl_renderbuffer *rb)
421{
422   struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
423
424   if (rb->AllocStorage == swrast_alloc_front_storage) {
425      __DRIdrawable *dPriv = xrb->dPriv;
426      __DRIscreen *sPriv = dPriv->driScreenPriv;
427
428      if (xrb->map_mode & GL_MAP_WRITE_BIT) {
429	 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW,
430					xrb->map_x, xrb->map_y,
431					xrb->map_w, xrb->map_h,
432					(char *) xrb->Base.Buffer,
433					dPriv->loaderPrivate);
434      }
435
436      free(xrb->Base.Buffer);
437      xrb->Base.Buffer = NULL;
438   }
439}
440
441static GLboolean
442dri_create_buffer(__DRIscreen * sPriv,
443		  __DRIdrawable * dPriv,
444		  const struct gl_config * visual, GLboolean isPixmap)
445{
446    struct dri_drawable *drawable = NULL;
447    struct gl_framebuffer *fb;
448    struct dri_swrast_renderbuffer *frontrb, *backrb;
449
450    TRACE;
451
452    (void) sPriv;
453    (void) isPixmap;
454
455    drawable = CALLOC_STRUCT(dri_drawable);
456    if (drawable == NULL)
457	goto drawable_fail;
458
459    dPriv->driverPrivate = drawable;
460    drawable->dPriv = dPriv;
461
462    drawable->row = malloc(SWRAST_MAX_WIDTH * 4);
463    if (drawable->row == NULL)
464	goto drawable_fail;
465
466    fb = &drawable->Base;
467
468    /* basic framebuffer setup */
469    _mesa_initialize_window_framebuffer(fb, visual);
470
471    /* add front renderbuffer */
472    frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE);
473    _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base);
474
475    /* add back renderbuffer */
476    if (visual->doubleBufferMode) {
477	backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE);
478	_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base);
479    }
480
481    /* add software renderbuffers */
482    _swrast_add_soft_renderbuffers(fb,
483                                   GL_FALSE, /* color */
484                                   visual->haveDepthBuffer,
485                                   visual->haveStencilBuffer,
486                                   visual->haveAccumBuffer,
487                                   GL_FALSE, /* alpha */
488                                   GL_FALSE /* aux bufs */);
489
490    return GL_TRUE;
491
492drawable_fail:
493
494    if (drawable)
495	free(drawable->row);
496
497    free(drawable);
498
499    return GL_FALSE;
500}
501
502static void
503dri_destroy_buffer(__DRIdrawable * dPriv)
504{
505    TRACE;
506
507    if (dPriv) {
508	struct dri_drawable *drawable = dri_drawable(dPriv);
509	struct gl_framebuffer *fb;
510
511	free(drawable->row);
512
513	fb = &drawable->Base;
514
515	fb->DeletePending = GL_TRUE;
516	_mesa_reference_framebuffer(&fb, NULL);
517    }
518}
519
520static void
521dri_swap_buffers(__DRIdrawable * dPriv)
522{
523    __DRIscreen *sPriv = dPriv->driScreenPriv;
524
525    GET_CURRENT_CONTEXT(ctx);
526
527    struct dri_drawable *drawable = dri_drawable(dPriv);
528    struct gl_framebuffer *fb;
529    struct dri_swrast_renderbuffer *frontrb, *backrb;
530
531    TRACE;
532
533    fb = &drawable->Base;
534
535    frontrb =
536	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
537    backrb =
538	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
539
540    /* check for signle-buffered */
541    if (backrb == NULL)
542	return;
543
544    /* check if swapping currently bound buffer */
545    if (ctx && ctx->DrawBuffer == fb) {
546	/* flush pending rendering */
547	_mesa_notifySwapBuffers(ctx);
548    }
549
550    sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
551				   0, 0,
552				   frontrb->Base.Base.Width,
553				   frontrb->Base.Base.Height,
554				   (char *) backrb->Base.Buffer,
555				   dPriv->loaderPrivate);
556}
557
558
559/**
560 * General device driver functions.
561 */
562
563static void
564get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h )
565{
566    __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
567    __DRIscreen *sPriv = dPriv->driScreenPriv;
568    int x, y;
569
570    sPriv->swrast_loader->getDrawableInfo(dPriv,
571					  &x, &y, w, h,
572					  dPriv->loaderPrivate);
573}
574
575static void
576swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb )
577{
578    GLsizei width, height;
579
580    get_window_size(fb, &width, &height);
581    if (fb->Width != width || fb->Height != height) {
582	_mesa_resize_framebuffer(ctx, fb, width, height);
583    }
584}
585
586static const GLubyte *
587get_string(struct gl_context *ctx, GLenum pname)
588{
589    (void) ctx;
590    switch (pname) {
591	case GL_VENDOR:
592	    return (const GLubyte *) "Mesa Project";
593	case GL_RENDERER:
594	    return (const GLubyte *) "Software Rasterizer";
595	default:
596	    return NULL;
597    }
598}
599
600static void
601update_state( struct gl_context *ctx, GLuint new_state )
602{
603    /* not much to do here - pass it on */
604    _swrast_InvalidateState( ctx, new_state );
605    _swsetup_InvalidateState( ctx, new_state );
606    _vbo_InvalidateState( ctx, new_state );
607    _tnl_InvalidateState( ctx, new_state );
608}
609
610static void
611viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
612{
613    struct gl_framebuffer *draw = ctx->WinSysDrawBuffer;
614    struct gl_framebuffer *read = ctx->WinSysReadBuffer;
615
616    (void) x;
617    (void) y;
618    (void) w;
619    (void) h;
620    swrast_check_and_update_window_size(ctx, draw);
621    swrast_check_and_update_window_size(ctx, read);
622}
623
624static gl_format swrastChooseTextureFormat(struct gl_context * ctx,
625                                           GLenum target,
626					   GLint internalFormat,
627					   GLenum format,
628					   GLenum type)
629{
630    if (internalFormat == GL_RGB)
631	return MESA_FORMAT_XRGB8888;
632    return _mesa_choose_tex_format(ctx, target, internalFormat, format, type);
633}
634
635static void
636swrast_init_driver_functions(struct dd_function_table *driver)
637{
638    driver->GetString = get_string;
639    driver->UpdateState = update_state;
640    driver->GetBufferSize = NULL;
641    driver->Viewport = viewport;
642    driver->ChooseTextureFormat = swrastChooseTextureFormat;
643    driver->MapRenderbuffer = swrast_map_renderbuffer;
644    driver->UnmapRenderbuffer = swrast_unmap_renderbuffer;
645}
646
647static const char *es2_extensions[] = {
648   /* Used by mesa internally (cf all_mesa_extensions in ../common/utils.c) */
649   "GL_EXT_blend_func_separate",
650   "GL_EXT_framebuffer_blit",
651   "GL_MESA_window_pos",
652
653   /* Required by GLES2 */
654   "GL_ARB_fragment_program",
655   "GL_ARB_fragment_shader",
656   "GL_ARB_shader_objects",
657   "GL_ARB_texture_cube_map",
658   "GL_ARB_texture_non_power_of_two",
659   "GL_ARB_vertex_shader",
660   "GL_EXT_blend_color",
661   "GL_EXT_blend_equation_separate",
662   "GL_EXT_blend_minmax",
663
664   /* Optional GLES2 */
665   "GL_ARB_framebuffer_object",
666   "GL_EXT_texture_filter_anisotropic",
667   "GL_ARB_depth_texture",
668   "GL_EXT_packed_depth_stencil",
669   "GL_EXT_framebuffer_object",
670   NULL,
671};
672
673static void
674InitExtensionsES2(struct gl_context *ctx)
675{
676   int i;
677
678   for (i = 0; es2_extensions[i]; i++)
679      _mesa_enable_extension(ctx, es2_extensions[i]);
680}
681
682/**
683 * Context-related functions.
684 */
685
686static GLboolean
687dri_create_context(gl_api api,
688		   const struct gl_config * visual,
689		   __DRIcontext * cPriv,
690		   unsigned major_version,
691		   unsigned minor_version,
692		   uint32_t flags,
693		   unsigned *error,
694		   void *sharedContextPrivate)
695{
696    struct dri_context *ctx = NULL;
697    struct dri_context *share = (struct dri_context *)sharedContextPrivate;
698    struct gl_context *mesaCtx = NULL;
699    struct gl_context *sharedCtx = NULL;
700    struct dd_function_table functions;
701
702    TRACE;
703
704    /* Flag filtering is handled in dri2CreateContextAttribs.
705     */
706    (void) flags;
707
708    switch (api) {
709    case API_OPENGL_COMPAT:
710        if (major_version > 2
711	    || (major_version == 2 && minor_version > 1)) {
712            *error = __DRI_CTX_ERROR_BAD_VERSION;
713            return GL_FALSE;
714        }
715        break;
716    case API_OPENGLES:
717    case API_OPENGLES2:
718        break;
719    case API_OPENGL_CORE:
720        *error = __DRI_CTX_ERROR_BAD_API;
721        return GL_FALSE;
722    }
723
724    ctx = CALLOC_STRUCT(dri_context);
725    if (ctx == NULL) {
726	*error = __DRI_CTX_ERROR_NO_MEMORY;
727	goto context_fail;
728    }
729
730    cPriv->driverPrivate = ctx;
731    ctx->cPriv = cPriv;
732
733    /* build table of device driver functions */
734    _mesa_init_driver_functions(&functions);
735    swrast_init_driver_functions(&functions);
736
737    if (share) {
738	sharedCtx = &share->Base;
739    }
740
741    mesaCtx = &ctx->Base;
742
743    /* basic context setup */
744    if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) {
745	*error = __DRI_CTX_ERROR_NO_MEMORY;
746	goto context_fail;
747    }
748
749    /* do bounds checking to prevent segfaults and server crashes! */
750    mesaCtx->Const.CheckArrayBounds = GL_TRUE;
751
752    /* create module contexts */
753    _swrast_CreateContext( mesaCtx );
754    _vbo_CreateContext( mesaCtx );
755    _tnl_CreateContext( mesaCtx );
756    _swsetup_CreateContext( mesaCtx );
757    _swsetup_Wakeup( mesaCtx );
758
759    /* use default TCL pipeline */
760    {
761       TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
762       tnl->Driver.RunPipeline = _tnl_run_pipeline;
763    }
764
765    _mesa_meta_init(mesaCtx);
766    _mesa_enable_sw_extensions(mesaCtx);
767
768    switch (api) {
769    case API_OPENGL_CORE:
770        /* XXX fix me, fall-through for now */
771    case API_OPENGL_COMPAT:
772        _mesa_enable_1_3_extensions(mesaCtx);
773        _mesa_enable_1_4_extensions(mesaCtx);
774        _mesa_enable_1_5_extensions(mesaCtx);
775        _mesa_enable_2_0_extensions(mesaCtx);
776        _mesa_enable_2_1_extensions(mesaCtx);
777        break;
778    case API_OPENGLES:
779        _mesa_enable_1_3_extensions(mesaCtx);
780        _mesa_enable_1_4_extensions(mesaCtx);
781        _mesa_enable_1_5_extensions(mesaCtx);
782
783        break;
784    case API_OPENGLES2:
785        InitExtensionsES2( mesaCtx);
786        break;
787    }
788
789    *error = __DRI_CTX_ERROR_SUCCESS;
790    return GL_TRUE;
791
792context_fail:
793
794    free(ctx);
795
796    return GL_FALSE;
797}
798
799static void
800dri_destroy_context(__DRIcontext * cPriv)
801{
802    TRACE;
803
804    if (cPriv) {
805	struct dri_context *ctx = dri_context(cPriv);
806	struct gl_context *mesaCtx;
807
808	mesaCtx = &ctx->Base;
809
810        _mesa_meta_free(mesaCtx);
811	_swsetup_DestroyContext( mesaCtx );
812	_swrast_DestroyContext( mesaCtx );
813	_tnl_DestroyContext( mesaCtx );
814	_vbo_DestroyContext( mesaCtx );
815	_mesa_destroy_context( mesaCtx );
816    }
817}
818
819static GLboolean
820dri_make_current(__DRIcontext * cPriv,
821		 __DRIdrawable * driDrawPriv,
822		 __DRIdrawable * driReadPriv)
823{
824    struct gl_context *mesaCtx;
825    struct gl_framebuffer *mesaDraw;
826    struct gl_framebuffer *mesaRead;
827    TRACE;
828
829    if (cPriv) {
830	struct dri_context *ctx = dri_context(cPriv);
831	struct dri_drawable *draw;
832	struct dri_drawable *read;
833
834	if (!driDrawPriv || !driReadPriv)
835	    return GL_FALSE;
836
837	draw = dri_drawable(driDrawPriv);
838	read = dri_drawable(driReadPriv);
839	mesaCtx = &ctx->Base;
840	mesaDraw = &draw->Base;
841	mesaRead = &read->Base;
842
843	/* check for same context and buffer */
844	if (mesaCtx == _mesa_get_current_context()
845	    && mesaCtx->DrawBuffer == mesaDraw
846	    && mesaCtx->ReadBuffer == mesaRead) {
847	    return GL_TRUE;
848	}
849
850	_glapi_check_multithread();
851
852	swrast_check_and_update_window_size(mesaCtx, mesaDraw);
853	if (mesaRead != mesaDraw)
854	    swrast_check_and_update_window_size(mesaCtx, mesaRead);
855
856	_mesa_make_current( mesaCtx,
857			    mesaDraw,
858			    mesaRead );
859    }
860    else {
861	/* unbind */
862	_mesa_make_current( NULL, NULL, NULL );
863    }
864
865    return GL_TRUE;
866}
867
868static GLboolean
869dri_unbind_context(__DRIcontext * cPriv)
870{
871    TRACE;
872    (void) cPriv;
873
874    /* Unset current context and dispath table */
875    _mesa_make_current(NULL, NULL, NULL);
876
877    return GL_TRUE;
878}
879
880
881const struct __DriverAPIRec driDriverAPI = {
882    .InitScreen = dri_init_screen,
883    .DestroyScreen = dri_destroy_screen,
884    .CreateContext = dri_create_context,
885    .DestroyContext = dri_destroy_context,
886    .CreateBuffer = dri_create_buffer,
887    .DestroyBuffer = dri_destroy_buffer,
888    .SwapBuffers = dri_swap_buffers,
889    .MakeCurrent = dri_make_current,
890    .UnbindContext = dri_unbind_context,
891};
892
893/* This is the table of extensions that the loader will dlsym() for. */
894PUBLIC const __DRIextension *__driDriverExtensions[] = {
895    &driCoreExtension.base,
896    &driSWRastExtension.base,
897    NULL
898};
899