Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 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 #include "pipe/p_screen.h"
     29 #include "util/u_format.h"
     30 #include "util/u_debug.h"
     31 #include "u_caps.h"
     32 
     33 /**
     34  * Iterates over a list of caps checks as defined in u_caps.h. Should
     35  * all checks pass returns TRUE and out is set to the last element of
     36  * the list (TERMINATE). Should any check fail returns FALSE and set
     37  * out to the index of the start of the first failing check.
     38  */
     39 boolean
     40 util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out)
     41 {
     42    int i, tmpi;
     43    float tmpf;
     44 
     45    for (i = 0; list[i];) {
     46       switch(list[i++]) {
     47       case UTIL_CAPS_CHECK_CAP:
     48          if (!screen->get_param(screen, list[i++])) {
     49             *out = i - 2;
     50             return FALSE;
     51          }
     52          break;
     53       case UTIL_CAPS_CHECK_INT:
     54          tmpi = screen->get_param(screen, list[i++]);
     55          if (tmpi < (int)list[i++]) {
     56             *out = i - 3;
     57             return FALSE;
     58          }
     59          break;
     60       case UTIL_CAPS_CHECK_FLOAT:
     61          tmpf = screen->get_paramf(screen, list[i++]);
     62          if (tmpf < (float)list[i++]) {
     63             *out = i - 3;
     64             return FALSE;
     65          }
     66          break;
     67       case UTIL_CAPS_CHECK_FORMAT:
     68          if (!screen->is_format_supported(screen,
     69                                           list[i++],
     70                                           PIPE_TEXTURE_2D,
     71                                           0,
     72                                           PIPE_BIND_SAMPLER_VIEW)) {
     73             *out = i - 2;
     74             return FALSE;
     75          }
     76          break;
     77       case UTIL_CAPS_CHECK_SHADER:
     78          tmpi = screen->get_shader_param(screen, list[i] >> 24, list[i] & ((1 << 24) - 1));
     79          ++i;
     80          if (tmpi < (int)list[i++]) {
     81             *out = i - 3;
     82             return FALSE;
     83          }
     84          break;
     85       case UTIL_CAPS_CHECK_UNIMPLEMENTED:
     86          *out = i - 1;
     87          return FALSE;
     88       default:
     89          assert(!"Unsupported check");
     90          return FALSE;
     91       }
     92    }
     93 
     94    *out = i;
     95    return TRUE;
     96 }
     97 
     98 /**
     99  * Iterates over a list of caps checks as defined in u_caps.h.
    100  * Returns TRUE if all caps checks pass returns FALSE otherwise.
    101  */
    102 boolean
    103 util_check_caps(struct pipe_screen *screen, const unsigned *list)
    104 {
    105    int out;
    106    return util_check_caps_out(screen, list, &out);
    107 }
    108 
    109 
    110 /*
    111  * Below follows some demo lists.
    112  *
    113  * None of these lists are exhausting lists of what is
    114  * actually needed to support said API and more here for
    115  * as example on how to uses the above functions. Especially
    116  * for DX10 and DX11 where Gallium is missing features.
    117  */
    118 
    119 /* DX 9_1 */
    120 static unsigned caps_dx_9_1[] = {
    121    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
    122    UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),    /* 2048 */
    123    UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),     /* 256 */
    124    UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10),  /* 512 */
    125    UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 2),
    126    UTIL_CHECK_TERMINATE
    127 };
    128 
    129 /* DX 9_2 */
    130 static unsigned caps_dx_9_2[] = {
    131    UTIL_CHECK_CAP(OCCLUSION_QUERY),
    132    UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
    133    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
    134    UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),    /* 2048 */
    135    UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),     /* 256 */
    136    UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10),  /* 512 */
    137    UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
    138    UTIL_CHECK_TERMINATE
    139 };
    140 
    141 /* DX 9_3 */
    142 static unsigned caps_dx_9_3[] = {
    143    UTIL_CHECK_CAP(SM3),
    144  //UTIL_CHECK_CAP(INSTANCING),
    145    UTIL_CHECK_CAP(OCCLUSION_QUERY),
    146    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
    147    UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),    /* 4096 */
    148    UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),     /* 256 */
    149    UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10),  /* 512 */
    150    UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
    151    UTIL_CHECK_TERMINATE
    152 };
    153 
    154 /* DX 10 */
    155 static unsigned caps_dx_10[] = {
    156    UTIL_CHECK_CAP(SM3),
    157  //UTIL_CHECK_CAP(INSTANCING),
    158    UTIL_CHECK_CAP(OCCLUSION_QUERY),
    159    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
    160    UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14),    /* 8192 */
    161    UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12),    /* 2048 */
    162    UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14),  /* 8192 */
    163    UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
    164    UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
    165    UTIL_CHECK_TERMINATE
    166 };
    167 
    168 /* DX11 */
    169 static unsigned caps_dx_11[] = {
    170    UTIL_CHECK_CAP(SM3),
    171  //UTIL_CHECK_CAP(INSTANCING),
    172    UTIL_CHECK_CAP(OCCLUSION_QUERY),
    173    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
    174    UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14),    /* 16384 */
    175    UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12),    /* 2048 */
    176    UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14),  /* 16384 */
    177    UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
    178    UTIL_CHECK_FORMAT(B8G8R8A8_UNORM),
    179    UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
    180    UTIL_CHECK_TERMINATE
    181 };
    182 
    183 /* OpenGL 2.1 */
    184 static unsigned caps_opengl_2_1[] = {
    185    UTIL_CHECK_CAP(OCCLUSION_QUERY),
    186    UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
    187    UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
    188    UTIL_CHECK_INT(MAX_RENDER_TARGETS, 2),
    189    UTIL_CHECK_TERMINATE
    190 };
    191 
    192 /* OpenGL 3.0 */
    193 /* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */
    194 
    195 /* Shader Model 3 */
    196 static unsigned caps_sm3[] = {
    197     UTIL_CHECK_SHADER(FRAGMENT, MAX_INSTRUCTIONS, 512),
    198     UTIL_CHECK_SHADER(FRAGMENT, MAX_INPUTS, 10),
    199     UTIL_CHECK_SHADER(FRAGMENT, MAX_TEMPS, 32),
    200     UTIL_CHECK_SHADER(FRAGMENT, MAX_CONST_BUFFER_SIZE, 224 * 16),
    201 
    202     UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512),
    203     UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
    204     UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32),
    205     UTIL_CHECK_SHADER(VERTEX, MAX_CONST_BUFFER_SIZE, 256 * 16),
    206 
    207     UTIL_CHECK_TERMINATE
    208 };
    209 
    210 /**
    211  * Demo function which checks against theoretical caps needed for different APIs.
    212  */
    213 void util_caps_demo_print(struct pipe_screen *screen)
    214 {
    215    struct {
    216       char* name;
    217       unsigned *list;
    218    } list[] = {
    219       {"DX 9.1", caps_dx_9_1},
    220       {"DX 9.2", caps_dx_9_2},
    221       {"DX 9.3", caps_dx_9_3},
    222       {"DX 10", caps_dx_10},
    223       {"DX 11", caps_dx_11},
    224       {"OpenGL 2.1", caps_opengl_2_1},
    225 /*    {"OpenGL 3.0", caps_opengl_3_0},*/
    226       {"SM3", caps_sm3},
    227       {NULL, NULL}
    228    };
    229    int i, out = 0;
    230 
    231    for (i = 0; list[i].name; i++) {
    232       if (util_check_caps_out(screen, list[i].list, &out)) {
    233          debug_printf("%s: %s yes\n", __FUNCTION__, list[i].name);
    234          continue;
    235       }
    236       switch (list[i].list[out]) {
    237       case UTIL_CAPS_CHECK_CAP:
    238          debug_printf("%s: %s no (cap %u not supported)\n", __FUNCTION__,
    239                       list[i].name,
    240                       list[i].list[out + 1]);
    241          break;
    242       case UTIL_CAPS_CHECK_INT:
    243          debug_printf("%s: %s no (cap %u less then %u)\n", __FUNCTION__,
    244                       list[i].name,
    245                       list[i].list[out + 1],
    246                       list[i].list[out + 2]);
    247          break;
    248       case UTIL_CAPS_CHECK_FLOAT:
    249          debug_printf("%s: %s no (cap %u less then %f)\n", __FUNCTION__,
    250                       list[i].name,
    251                       list[i].list[out + 1],
    252                       (double)(int)list[i].list[out + 2]);
    253          break;
    254       case UTIL_CAPS_CHECK_FORMAT:
    255          debug_printf("%s: %s no (format %s not supported)\n", __FUNCTION__,
    256                       list[i].name,
    257                       util_format_name(list[i].list[out + 1]) + 12);
    258          break;
    259       case UTIL_CAPS_CHECK_UNIMPLEMENTED:
    260          debug_printf("%s: %s no (not implemented in gallium or state tracker)\n",
    261                       __FUNCTION__, list[i].name);
    262          break;
    263       default:
    264             assert(!"Unsupported check");
    265       }
    266    }
    267 }
    268