Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  * 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);
  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 = y;
  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, rb->Height - y - h, 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.