Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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