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