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