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