~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/swrast/swrast.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

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