Home | History | Annotate | Download | only in sw
      1 /**************************************************************************
      2  *
      3  * Copyright 2009, VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 /*
     28  * Author: Keith Whitwell <keithw (at) vmware.com>
     29  * Author: Jakob Bornecrantz <wallbraker (at) gmail.com>
     30  */
     31 
     32 #include "utils.h"
     33 #include "xmlpool.h"
     34 
     35 #include "dri_screen.h"
     36 
     37 #include "util/u_inlines.h"
     38 #include "pipe/p_screen.h"
     39 #include "pipe/p_format.h"
     40 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
     41 
     42 #include "util/u_debug.h"
     43 
     44 #define MSAA_VISUAL_MAX_SAMPLES 8
     45 
     46 #undef false
     47 
     48 PUBLIC const char __driConfigOptions[] =
     49    DRI_CONF_BEGIN
     50       DRI_CONF_SECTION_PERFORMANCE
     51          DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
     52          DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
     53       DRI_CONF_SECTION_END
     54 
     55       DRI_CONF_SECTION_QUALITY
     56 /*       DRI_CONF_FORCE_S3TC_ENABLE(false) */
     57          DRI_CONF_ALLOW_LARGE_TEXTURES(1)
     58          DRI_CONF_PP_CELSHADE(0)
     59          DRI_CONF_PP_NORED(0)
     60          DRI_CONF_PP_NOGREEN(0)
     61          DRI_CONF_PP_NOBLUE(0)
     62          DRI_CONF_PP_JIMENEZMLAA(0, 0, 32)
     63          DRI_CONF_PP_JIMENEZMLAA_COLOR(0, 0, 32)
     64       DRI_CONF_SECTION_END
     65 
     66       DRI_CONF_SECTION_DEBUG
     67          DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(false)
     68       DRI_CONF_SECTION_END
     69 
     70    DRI_CONF_END;
     71 
     72 #define false 0
     73 
     74 static const uint __driNConfigOptions = 10;
     75 
     76 static const __DRIconfig **
     77 dri_fill_in_modes(struct dri_screen *screen,
     78 		  unsigned pixel_bits)
     79 {
     80    __DRIconfig **configs = NULL;
     81    __DRIconfig **configs_r5g6b5 = NULL;
     82    __DRIconfig **configs_a8r8g8b8 = NULL;
     83    __DRIconfig **configs_x8r8g8b8 = NULL;
     84    uint8_t depth_bits_array[5];
     85    uint8_t stencil_bits_array[5];
     86    uint8_t msaa_samples_array[MSAA_VISUAL_MAX_SAMPLES];
     87    unsigned depth_buffer_factor;
     88    unsigned back_buffer_factor;
     89    unsigned msaa_samples_factor, msaa_samples_max;
     90    unsigned i;
     91    struct pipe_screen *p_screen = screen->base.screen;
     92    boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8;
     93    boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
     94 
     95    static const GLenum back_buffer_modes[] = {
     96       GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
     97    };
     98 
     99    depth_bits_array[0] = 0;
    100    stencil_bits_array[0] = 0;
    101    depth_buffer_factor = 1;
    102 
    103    msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS)
    104       ? MSAA_VISUAL_MAX_SAMPLES : 1;
    105 
    106    pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
    107 					    PIPE_TEXTURE_2D, 0,
    108                                             PIPE_BIND_DEPTH_STENCIL);
    109    pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
    110 					    PIPE_TEXTURE_2D, 0,
    111                                             PIPE_BIND_DEPTH_STENCIL);
    112    pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT,
    113 					    PIPE_TEXTURE_2D, 0,
    114                                             PIPE_BIND_DEPTH_STENCIL);
    115    pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM,
    116 					    PIPE_TEXTURE_2D, 0,
    117                                             PIPE_BIND_DEPTH_STENCIL);
    118    pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
    119 					       PIPE_TEXTURE_2D, 0,
    120                                                PIPE_BIND_RENDER_TARGET);
    121    pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
    122 					       PIPE_TEXTURE_2D, 0,
    123                                                PIPE_BIND_RENDER_TARGET);
    124    pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
    125 					     PIPE_TEXTURE_2D, 0,
    126                                              PIPE_BIND_RENDER_TARGET);
    127 
    128    /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */
    129    if (dri_with_format(screen->sPriv)) {
    130       pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
    131                                              PIPE_TEXTURE_2D, 0,
    132                                              PIPE_BIND_DEPTH_STENCIL);
    133       pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
    134                                              PIPE_TEXTURE_2D, 0,
    135                                              PIPE_BIND_DEPTH_STENCIL);
    136    } else {
    137       pf_z16 = FALSE;
    138       pf_z32 = FALSE;
    139    }
    140 
    141    if (pf_z16) {
    142       depth_bits_array[depth_buffer_factor] = 16;
    143       stencil_bits_array[depth_buffer_factor++] = 0;
    144    }
    145    if (pf_x8z24 || pf_z24x8) {
    146       depth_bits_array[depth_buffer_factor] = 24;
    147       stencil_bits_array[depth_buffer_factor++] = 0;
    148       screen->d_depth_bits_last = pf_x8z24;
    149    }
    150    if (pf_s8z24 || pf_z24s8) {
    151       depth_bits_array[depth_buffer_factor] = 24;
    152       stencil_bits_array[depth_buffer_factor++] = 8;
    153       screen->sd_depth_bits_last = pf_s8z24;
    154    }
    155    if (pf_z32) {
    156       depth_bits_array[depth_buffer_factor] = 32;
    157       stencil_bits_array[depth_buffer_factor++] = 0;
    158    }
    159 
    160    msaa_samples_array[0] = 0;
    161    back_buffer_factor = 3;
    162 
    163    /* Also test for color multisample support - just assume it'll work
    164     * for all depth buffers.
    165     */
    166    if (pf_r5g6b5) {
    167       msaa_samples_factor = 1;
    168       for (i = 2; i <= msaa_samples_max; i++) {
    169          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM,
    170 						   PIPE_TEXTURE_2D, i,
    171                                                    PIPE_BIND_RENDER_TARGET)) {
    172             msaa_samples_array[msaa_samples_factor] = i;
    173             msaa_samples_factor++;
    174          }
    175       }
    176 
    177       configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
    178                                         depth_bits_array, stencil_bits_array,
    179                                         depth_buffer_factor, back_buffer_modes,
    180                                         back_buffer_factor,
    181                                         msaa_samples_array, msaa_samples_factor,
    182                                         GL_TRUE);
    183    }
    184 
    185    if (pf_a8r8g8b8) {
    186       msaa_samples_factor = 1;
    187       for (i = 2; i <= msaa_samples_max; i++) {
    188          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM,
    189 						   PIPE_TEXTURE_2D, i,
    190                                                    PIPE_BIND_RENDER_TARGET)) {
    191             msaa_samples_array[msaa_samples_factor] = i;
    192             msaa_samples_factor++;
    193          }
    194       }
    195 
    196       configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
    197                                           depth_bits_array,
    198                                           stencil_bits_array,
    199                                           depth_buffer_factor,
    200                                           back_buffer_modes,
    201                                           back_buffer_factor,
    202                                           msaa_samples_array,
    203                                           msaa_samples_factor,
    204                                           GL_TRUE);
    205    }
    206 
    207    if (pf_x8r8g8b8) {
    208       msaa_samples_factor = 1;
    209       for (i = 2; i <= msaa_samples_max; i++) {
    210          if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM,
    211 						   PIPE_TEXTURE_2D, i,
    212                                                    PIPE_BIND_RENDER_TARGET)) {
    213             msaa_samples_array[msaa_samples_factor] = i;
    214             msaa_samples_factor++;
    215          }
    216       }
    217 
    218       configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
    219                                           depth_bits_array,
    220                                           stencil_bits_array,
    221                                           depth_buffer_factor,
    222                                           back_buffer_modes,
    223                                           back_buffer_factor,
    224                                           msaa_samples_array,
    225                                           msaa_samples_factor,
    226                                           GL_TRUE);
    227    }
    228 
    229    if (pixel_bits == 16) {
    230       configs = configs_r5g6b5;
    231       configs = driConcatConfigs(configs, configs_a8r8g8b8);
    232       configs = driConcatConfigs(configs, configs_x8r8g8b8);
    233    } else {
    234       configs = configs_a8r8g8b8;
    235       configs = driConcatConfigs(configs, configs_x8r8g8b8);
    236       configs = driConcatConfigs(configs, configs_r5g6b5);
    237    }
    238 
    239    if (configs == NULL) {
    240       debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__);
    241       return NULL;
    242    }
    243 
    244    return (const __DRIconfig **)configs;
    245 }
    246 
    247 /**
    248  * Roughly the converse of dri_fill_in_modes.
    249  */
    250 void
    251 dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
    252                    const struct gl_config *mode)
    253 {
    254    memset(stvis, 0, sizeof(*stvis));
    255 
    256    if (!mode)
    257       return;
    258 
    259    stvis->samples = mode->samples;
    260 
    261    if (mode->redBits == 8) {
    262       if (mode->alphaBits == 8)
    263          stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
    264       else
    265          stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
    266    } else {
    267       stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
    268    }
    269 
    270    switch (mode->depthBits) {
    271    default:
    272    case 0:
    273       stvis->depth_stencil_format = PIPE_FORMAT_NONE;
    274       break;
    275    case 16:
    276       stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
    277       break;
    278    case 24:
    279       if (mode->stencilBits == 0) {
    280 	 stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
    281                                           PIPE_FORMAT_Z24X8_UNORM:
    282                                           PIPE_FORMAT_X8Z24_UNORM;
    283       } else {
    284 	 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
    285                                           PIPE_FORMAT_Z24_UNORM_S8_UINT:
    286                                           PIPE_FORMAT_S8_UINT_Z24_UNORM;
    287       }
    288       break;
    289    case 32:
    290       stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
    291       break;
    292    }
    293 
    294    stvis->accum_format = (mode->haveAccumBuffer) ?
    295       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
    296 
    297    stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
    298    stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
    299    if (mode->doubleBufferMode) {
    300       stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
    301       stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT;
    302    }
    303    if (mode->stereoMode) {
    304       stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
    305       if (mode->doubleBufferMode)
    306          stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
    307    }
    308 
    309    if (mode->haveDepthBuffer || mode->haveStencilBuffer)
    310       stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
    311    /* let the state tracker allocate the accum buffer */
    312 }
    313 
    314 static boolean
    315 dri_get_egl_image(struct st_manager *smapi,
    316                   void *egl_image,
    317                   struct st_egl_image *stimg)
    318 {
    319    struct dri_screen *screen = (struct dri_screen *)smapi;
    320    __DRIimage *img = NULL;
    321 
    322    if (screen->lookup_egl_image) {
    323       img = screen->lookup_egl_image(screen, egl_image);
    324    }
    325 
    326    if (!img)
    327       return FALSE;
    328 
    329    stimg->texture = NULL;
    330    pipe_resource_reference(&stimg->texture, img->texture);
    331    stimg->level = img->level;
    332    stimg->layer = img->layer;
    333 
    334    return TRUE;
    335 }
    336 
    337 static int
    338 dri_get_param(struct st_manager *smapi,
    339               enum st_manager_param param)
    340 {
    341    struct dri_screen *screen = (struct dri_screen *)smapi;
    342 
    343    switch(param) {
    344    case ST_MANAGER_BROKEN_INVALIDATE:
    345       return screen->broken_invalidate;
    346    default:
    347       return 0;
    348    }
    349 }
    350 
    351 static void
    352 dri_destroy_option_cache(struct dri_screen * screen)
    353 {
    354    int i;
    355 
    356    if (screen->optionCache.info) {
    357       for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
    358          FREE(screen->optionCache.info[i].name);
    359          FREE(screen->optionCache.info[i].ranges);
    360       }
    361       FREE(screen->optionCache.info);
    362    }
    363 
    364    FREE(screen->optionCache.values);
    365 }
    366 
    367 void
    368 dri_destroy_screen_helper(struct dri_screen * screen)
    369 {
    370    if (screen->st_api && screen->st_api->destroy)
    371       screen->st_api->destroy(screen->st_api);
    372 
    373    if (screen->base.screen)
    374       screen->base.screen->destroy(screen->base.screen);
    375 
    376    dri_destroy_option_cache(screen);
    377 }
    378 
    379 void
    380 dri_destroy_screen(__DRIscreen * sPriv)
    381 {
    382    struct dri_screen *screen = dri_screen(sPriv);
    383 
    384    dri_destroy_screen_helper(screen);
    385 
    386    FREE(screen);
    387    sPriv->driverPrivate = NULL;
    388    sPriv->extensions = NULL;
    389 }
    390 
    391 const __DRIconfig **
    392 dri_init_screen_helper(struct dri_screen *screen,
    393                        struct pipe_screen *pscreen,
    394                        unsigned pixel_bits)
    395 {
    396    screen->base.screen = pscreen;
    397    if (!screen->base.screen) {
    398       debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
    399       return NULL;
    400    }
    401 
    402    screen->base.get_egl_image = dri_get_egl_image;
    403    screen->base.get_param = dri_get_param;
    404 
    405    screen->st_api = st_gl_api_create();
    406    if (!screen->st_api)
    407       return NULL;
    408 
    409    if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES))
    410       screen->target = PIPE_TEXTURE_2D;
    411    else
    412       screen->target = PIPE_TEXTURE_RECT;
    413 
    414    driParseOptionInfo(&screen->optionCache,
    415                       __driConfigOptions, __driNConfigOptions);
    416 
    417    return dri_fill_in_modes(screen, pixel_bits);
    418 }
    419 
    420 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    421