svga_screen.c revision 6c403750d6515f8b2f333d995c87676016e1883d
1/********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26#include "util/u_memory.h" 27#include "pipe/p_inlines.h" 28#include "util/u_string.h" 29#include "util/u_math.h" 30 31#include "svga_winsys.h" 32#include "svga_context.h" 33#include "svga_screen.h" 34#include "svga_screen_texture.h" 35#include "svga_screen_buffer.h" 36#include "svga_debug.h" 37 38#include "svga3d_shaderdefs.h" 39 40 41#ifdef DEBUG 42int SVGA_DEBUG = 0; 43 44static const struct debug_named_value svga_debug_flags[] = { 45 { "dma", DEBUG_DMA }, 46 { "tgsi", DEBUG_TGSI }, 47 { "pipe", DEBUG_PIPE }, 48 { "state", DEBUG_STATE }, 49 { "screen", DEBUG_SCREEN }, 50 { "tex", DEBUG_TEX }, 51 { "swtnl", DEBUG_SWTNL }, 52 { "const", DEBUG_CONSTS }, 53 { "viewport", DEBUG_VIEWPORT }, 54 { "views", DEBUG_VIEWS }, 55 { "perf", DEBUG_PERF }, 56 { "flush", DEBUG_FLUSH }, 57 { "sync", DEBUG_SYNC }, 58 { "cache", DEBUG_CACHE }, 59 {NULL, 0} 60}; 61#endif 62 63static const char * 64svga_get_vendor( struct pipe_screen *pscreen ) 65{ 66 return "VMware, Inc."; 67} 68 69 70static const char * 71svga_get_name( struct pipe_screen *pscreen ) 72{ 73#ifdef DEBUG 74 /* Only return internal details in the DEBUG version: 75 */ 76 return "SVGA3D; build: DEBUG; mutex: " PIPE_ATOMIC; 77#else 78 return "SVGA3D; build: RELEASE; "; 79#endif 80} 81 82 83 84 85static float 86svga_get_paramf(struct pipe_screen *screen, int param) 87{ 88 struct svga_screen *svgascreen = svga_screen(screen); 89 struct svga_winsys_screen *sws = svgascreen->sws; 90 SVGA3dDevCapResult result; 91 92 switch (param) { 93 case PIPE_CAP_MAX_LINE_WIDTH: 94 /* fall-through */ 95 case PIPE_CAP_MAX_LINE_WIDTH_AA: 96 return 7.0; 97 98 case PIPE_CAP_MAX_POINT_WIDTH: 99 /* fall-through */ 100 case PIPE_CAP_MAX_POINT_WIDTH_AA: 101 /* Keep this to a reasonable size to avoid failures in 102 * conform/pntaa.c: 103 */ 104 return 80.0; 105 106 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: 107 return 4.0; 108 109 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: 110 return 16.0; 111 112 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: 113 return 16; 114 case PIPE_CAP_NPOT_TEXTURES: 115 return 1; 116 case PIPE_CAP_TWO_SIDED_STENCIL: 117 return 1; 118 case PIPE_CAP_GLSL: 119 return svgascreen->use_ps30 && svgascreen->use_vs30; 120 case PIPE_CAP_ANISOTROPIC_FILTER: 121 return 1; 122 case PIPE_CAP_POINT_SPRITE: 123 return 1; 124 case PIPE_CAP_MAX_RENDER_TARGETS: 125 if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_RENDER_TARGETS, &result)) 126 return 1; 127 if(!result.u) 128 return 1; 129 return MIN2(result.u, PIPE_MAX_COLOR_BUFS); 130 case PIPE_CAP_OCCLUSION_QUERY: 131 return 1; 132 case PIPE_CAP_TEXTURE_SHADOW_MAP: 133 return 1; 134 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: 135 return SVGA_MAX_TEXTURE_LEVELS; 136 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 137 return 8; /* max 128x128x128 */ 138 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 139 return SVGA_MAX_TEXTURE_LEVELS; 140 141 case PIPE_CAP_TEXTURE_MIRROR_REPEAT: /* req. for GL 1.4 */ 142 return 1; 143 144 case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */ 145 return 1; 146 147 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 148 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 149 return 1; 150 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 151 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 152 return 0; 153 154 default: 155 return 0; 156 } 157} 158 159 160/* This is a fairly pointless interface 161 */ 162static int 163svga_get_param(struct pipe_screen *screen, int param) 164{ 165 return (int) svga_get_paramf( screen, param ); 166} 167 168 169static INLINE SVGA3dDevCapIndex 170svga_translate_format_cap(enum pipe_format format) 171{ 172 switch(format) { 173 174 case PIPE_FORMAT_A8R8G8B8_UNORM: 175 return SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8; 176 case PIPE_FORMAT_X8R8G8B8_UNORM: 177 return SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8; 178 179 case PIPE_FORMAT_R5G6B5_UNORM: 180 return SVGA3D_DEVCAP_SURFACEFMT_R5G6B5; 181 case PIPE_FORMAT_A1R5G5B5_UNORM: 182 return SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5; 183 case PIPE_FORMAT_A4R4G4B4_UNORM: 184 return SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4; 185 186 case PIPE_FORMAT_Z16_UNORM: 187 return SVGA3D_DEVCAP_SURFACEFMT_Z_D16; 188 case PIPE_FORMAT_Z24S8_UNORM: 189 return SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8; 190 case PIPE_FORMAT_Z24X8_UNORM: 191 return SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8; 192 193 case PIPE_FORMAT_A8_UNORM: 194 return SVGA3D_DEVCAP_SURFACEFMT_ALPHA8; 195 case PIPE_FORMAT_L8_UNORM: 196 return SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8; 197 198 case PIPE_FORMAT_DXT1_RGB: 199 case PIPE_FORMAT_DXT1_RGBA: 200 return SVGA3D_DEVCAP_SURFACEFMT_DXT1; 201 case PIPE_FORMAT_DXT3_RGBA: 202 return SVGA3D_DEVCAP_SURFACEFMT_DXT3; 203 case PIPE_FORMAT_DXT5_RGBA: 204 return SVGA3D_DEVCAP_SURFACEFMT_DXT5; 205 206 default: 207 return SVGA3D_DEVCAP_MAX; 208 } 209} 210 211 212static boolean 213svga_is_format_supported( struct pipe_screen *screen, 214 enum pipe_format format, 215 enum pipe_texture_target target, 216 unsigned tex_usage, 217 unsigned geom_flags ) 218{ 219 struct svga_winsys_screen *sws = svga_screen(screen)->sws; 220 SVGA3dDevCapIndex index; 221 SVGA3dDevCapResult result; 222 223 assert(tex_usage); 224 225 /* Override host capabilities */ 226 if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { 227 switch(format) { 228 229 /* Often unsupported/problematic. This means we end up with the same 230 * visuals for all virtual hardware implementations. 231 */ 232 case PIPE_FORMAT_A4R4G4B4_UNORM: 233 case PIPE_FORMAT_A1R5G5B5_UNORM: 234 return FALSE; 235 236 /* Simulate ability to render into compressed textures */ 237 case PIPE_FORMAT_DXT1_RGB: 238 case PIPE_FORMAT_DXT1_RGBA: 239 case PIPE_FORMAT_DXT3_RGBA: 240 case PIPE_FORMAT_DXT5_RGBA: 241 return TRUE; 242 243 default: 244 break; 245 } 246 } 247 248 /* Try to query the host */ 249 index = svga_translate_format_cap(format); 250 if( index < SVGA3D_DEVCAP_MAX && 251 sws->get_cap(sws, index, &result) ) 252 { 253 SVGA3dSurfaceFormatCaps mask; 254 255 mask.value = 0; 256 if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) 257 mask.offscreenRenderTarget = 1; 258 if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) 259 mask.zStencil = 1; 260 if (tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) 261 mask.texture = 1; 262 263 if ((result.u & mask.value) == mask.value) 264 return TRUE; 265 else 266 return FALSE; 267 } 268 269 /* Use our translate functions directly rather than relying on a 270 * duplicated list of supported formats which is prone to getting 271 * out of sync: 272 */ 273 if(tex_usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) 274 return svga_translate_format_render(format) != SVGA3D_FORMAT_INVALID; 275 else 276 return svga_translate_format(format) != SVGA3D_FORMAT_INVALID; 277} 278 279 280static void 281svga_fence_reference(struct pipe_screen *screen, 282 struct pipe_fence_handle **ptr, 283 struct pipe_fence_handle *fence) 284{ 285 struct svga_winsys_screen *sws = svga_screen(screen)->sws; 286 sws->fence_reference(sws, ptr, fence); 287} 288 289 290static int 291svga_fence_signalled(struct pipe_screen *screen, 292 struct pipe_fence_handle *fence, 293 unsigned flag) 294{ 295 struct svga_winsys_screen *sws = svga_screen(screen)->sws; 296 return sws->fence_signalled(sws, fence, flag); 297} 298 299 300static int 301svga_fence_finish(struct pipe_screen *screen, 302 struct pipe_fence_handle *fence, 303 unsigned flag) 304{ 305 struct svga_winsys_screen *sws = svga_screen(screen)->sws; 306 307 SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n", 308 __FUNCTION__, fence); 309 310 return sws->fence_finish(sws, fence, flag); 311} 312 313 314static void 315svga_destroy_screen( struct pipe_screen *screen ) 316{ 317 struct svga_screen *svgascreen = svga_screen(screen); 318 319 svga_screen_cache_cleanup(svgascreen); 320 321 pipe_mutex_destroy(svgascreen->swc_mutex); 322 pipe_mutex_destroy(svgascreen->tex_mutex); 323 324 svgascreen->swc->destroy(svgascreen->swc); 325 326 svgascreen->sws->destroy(svgascreen->sws); 327 328 FREE(svgascreen); 329} 330 331 332/** 333 * Create a new svga_screen object 334 */ 335struct pipe_screen * 336svga_screen_create(struct svga_winsys_screen *sws) 337{ 338 struct svga_screen *svgascreen; 339 struct pipe_screen *screen; 340 SVGA3dDevCapResult result; 341 342#ifdef DEBUG 343 SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 ); 344#endif 345 346 svgascreen = CALLOC_STRUCT(svga_screen); 347 if (!svgascreen) 348 goto error1; 349 350 svgascreen->debug.force_level_surface_view = 351 debug_get_bool_option("SVGA_FORCE_LEVEL_SURFACE_VIEW", FALSE); 352 svgascreen->debug.force_surface_view = 353 debug_get_bool_option("SVGA_FORCE_SURFACE_VIEW", FALSE); 354 svgascreen->debug.force_sampler_view = 355 debug_get_bool_option("SVGA_FORCE_SAMPLER_VIEW", FALSE); 356 svgascreen->debug.no_surface_view = 357 debug_get_bool_option("SVGA_NO_SURFACE_VIEW", FALSE); 358 svgascreen->debug.no_sampler_view = 359 debug_get_bool_option("SVGA_NO_SAMPLER_VIEW", FALSE); 360 361 screen = &svgascreen->screen; 362 363 screen->destroy = svga_destroy_screen; 364 screen->get_name = svga_get_name; 365 screen->get_vendor = svga_get_vendor; 366 screen->get_param = svga_get_param; 367 screen->get_paramf = svga_get_paramf; 368 screen->is_format_supported = svga_is_format_supported; 369 screen->fence_reference = svga_fence_reference; 370 screen->fence_signalled = svga_fence_signalled; 371 screen->fence_finish = svga_fence_finish; 372 svgascreen->sws = sws; 373 374 svga_screen_init_texture_functions(screen); 375 svga_screen_init_buffer_functions(screen); 376 377 svgascreen->use_ps30 = 378 sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) && 379 result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE; 380 381 svgascreen->use_vs30 = 382 sws->get_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, &result) && 383 result.u >= SVGA3DVSVERSION_30 ? TRUE : FALSE; 384 385#if 1 386 /* Shader model 2.0 is unsupported at the moment. */ 387 if(!svgascreen->use_ps30 || !svgascreen->use_vs30) 388 goto error2; 389#else 390 if(debug_get_bool_option("SVGA_NO_SM30", FALSE)) 391 svgascreen->use_vs30 = svgascreen->use_ps30 = FALSE; 392#endif 393 394 svgascreen->swc = sws->context_create(sws); 395 if(!svgascreen->swc) 396 goto error2; 397 398 pipe_mutex_init(svgascreen->tex_mutex); 399 pipe_mutex_init(svgascreen->swc_mutex); 400 401 svga_screen_cache_init(svgascreen); 402 403 return screen; 404error2: 405 FREE(svgascreen); 406error1: 407 return NULL; 408} 409 410void svga_screen_flush( struct svga_screen *svgascreen, 411 struct pipe_fence_handle **pfence ) 412{ 413 struct pipe_fence_handle *fence = NULL; 414 415 SVGA_DBG(DEBUG_PERF, "%s\n", __FUNCTION__); 416 417 pipe_mutex_lock(svgascreen->swc_mutex); 418 svgascreen->swc->flush(svgascreen->swc, &fence); 419 pipe_mutex_unlock(svgascreen->swc_mutex); 420 421 svga_screen_cache_flush(svgascreen, fence); 422 423 if(pfence) 424 *pfence = fence; 425 else 426 svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL); 427} 428 429struct svga_winsys_screen * 430svga_winsys_screen(struct pipe_screen *screen) 431{ 432 return svga_screen(screen)->sws; 433} 434 435#ifdef DEBUG 436struct svga_screen * 437svga_screen(struct pipe_screen *screen) 438{ 439 assert(screen); 440 assert(screen->destroy == svga_destroy_screen); 441 return (struct svga_screen *)screen; 442} 443#endif 444