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_ADDRS, 1), 201 UTIL_CHECK_SHADER(FRAGMENT, MAX_CONSTS, 224), 202 203 UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512), 204 UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16), 205 UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32), 206 UTIL_CHECK_SHADER(VERTEX, MAX_ADDRS, 2), 207 UTIL_CHECK_SHADER(VERTEX, MAX_CONSTS, 256), 208 209 UTIL_CHECK_TERMINATE 210 }; 211 212 /** 213 * Demo function which checks against theoretical caps needed for different APIs. 214 */ 215 void util_caps_demo_print(struct pipe_screen *screen) 216 { 217 struct { 218 char* name; 219 unsigned *list; 220 } list[] = { 221 {"DX 9.1", caps_dx_9_1}, 222 {"DX 9.2", caps_dx_9_2}, 223 {"DX 9.3", caps_dx_9_3}, 224 {"DX 10", caps_dx_10}, 225 {"DX 11", caps_dx_11}, 226 {"OpenGL 2.1", caps_opengl_2_1}, 227 /* {"OpenGL 3.0", caps_opengl_3_0},*/ 228 {"SM3", caps_sm3}, 229 {NULL, NULL} 230 }; 231 int i, out = 0; 232 233 for (i = 0; list[i].name; i++) { 234 if (util_check_caps_out(screen, list[i].list, &out)) { 235 debug_printf("%s: %s yes\n", __FUNCTION__, list[i].name); 236 continue; 237 } 238 switch (list[i].list[out]) { 239 case UTIL_CAPS_CHECK_CAP: 240 debug_printf("%s: %s no (cap %u not supported)\n", __FUNCTION__, 241 list[i].name, 242 list[i].list[out + 1]); 243 break; 244 case UTIL_CAPS_CHECK_INT: 245 debug_printf("%s: %s no (cap %u less then %u)\n", __FUNCTION__, 246 list[i].name, 247 list[i].list[out + 1], 248 list[i].list[out + 2]); 249 break; 250 case UTIL_CAPS_CHECK_FLOAT: 251 debug_printf("%s: %s no (cap %u less then %f)\n", __FUNCTION__, 252 list[i].name, 253 list[i].list[out + 1], 254 (double)(int)list[i].list[out + 2]); 255 break; 256 case UTIL_CAPS_CHECK_FORMAT: 257 debug_printf("%s: %s no (format %s not supported)\n", __FUNCTION__, 258 list[i].name, 259 util_format_name(list[i].list[out + 1]) + 12); 260 break; 261 case UTIL_CAPS_CHECK_UNIMPLEMENTED: 262 debug_printf("%s: %s no (not implemented in gallium or state tracker)\n", 263 __FUNCTION__, list[i].name); 264 break; 265 default: 266 assert(!"Unsupported check"); 267 } 268 } 269 } 270