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