nv50_screen.c revision 2a84db24b33993844ba5e5c036edca78718d2425
1/* 2 * Copyright 2008 Ben Skeggs 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#include "pipe/p_screen.h" 24 25#include "nv50_context.h" 26#include "nv50_screen.h" 27 28#include "nouveau/nouveau_stateobj.h" 29 30static boolean 31nv50_screen_is_format_supported(struct pipe_screen *pscreen, 32 enum pipe_format format, 33 enum pipe_texture_target target, 34 unsigned tex_usage, unsigned geom_flags) 35{ 36 if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { 37 switch (format) { 38 case PIPE_FORMAT_B8G8R8X8_UNORM: 39 case PIPE_FORMAT_B8G8R8A8_UNORM: 40 case PIPE_FORMAT_B5G6R5_UNORM: 41 case PIPE_FORMAT_R16G16B16A16_SNORM: 42 case PIPE_FORMAT_R16G16B16A16_UNORM: 43 case PIPE_FORMAT_R32G32B32A32_FLOAT: 44 case PIPE_FORMAT_R16G16_SNORM: 45 case PIPE_FORMAT_R16G16_UNORM: 46 return TRUE; 47 default: 48 break; 49 } 50 } else 51 if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { 52 switch (format) { 53 case PIPE_FORMAT_Z32_FLOAT: 54 case PIPE_FORMAT_S8Z24_UNORM: 55 case PIPE_FORMAT_Z24X8_UNORM: 56 case PIPE_FORMAT_Z24S8_UNORM: 57 return TRUE; 58 default: 59 break; 60 } 61 } else { 62 switch (format) { 63 case PIPE_FORMAT_B8G8R8A8_UNORM: 64 case PIPE_FORMAT_B8G8R8X8_UNORM: 65 case PIPE_FORMAT_B8G8R8A8_SRGB: 66 case PIPE_FORMAT_B8G8R8X8_SRGB: 67 case PIPE_FORMAT_B5G5R5A1_UNORM: 68 case PIPE_FORMAT_B4G4R4A4_UNORM: 69 case PIPE_FORMAT_B5G6R5_UNORM: 70 case PIPE_FORMAT_L8_UNORM: 71 case PIPE_FORMAT_A8_UNORM: 72 case PIPE_FORMAT_I8_UNORM: 73 case PIPE_FORMAT_L8A8_UNORM: 74 case PIPE_FORMAT_DXT1_RGB: 75 case PIPE_FORMAT_DXT1_RGBA: 76 case PIPE_FORMAT_DXT3_RGBA: 77 case PIPE_FORMAT_DXT5_RGBA: 78 case PIPE_FORMAT_S8Z24_UNORM: 79 case PIPE_FORMAT_Z24S8_UNORM: 80 case PIPE_FORMAT_Z32_FLOAT: 81 case PIPE_FORMAT_R16G16B16A16_SNORM: 82 case PIPE_FORMAT_R16G16B16A16_UNORM: 83 case PIPE_FORMAT_R32G32B32A32_FLOAT: 84 case PIPE_FORMAT_R16G16_SNORM: 85 case PIPE_FORMAT_R16G16_UNORM: 86 return TRUE; 87 default: 88 break; 89 } 90 } 91 92 return FALSE; 93} 94 95static int 96nv50_screen_get_param(struct pipe_screen *pscreen, int param) 97{ 98 switch (param) { 99 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: 100 return 32; 101 case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: 102 return 32; 103 case PIPE_CAP_MAX_COMBINED_SAMPLERS: 104 return 64; 105 case PIPE_CAP_NPOT_TEXTURES: 106 return 1; 107 case PIPE_CAP_TWO_SIDED_STENCIL: 108 return 1; 109 case PIPE_CAP_GLSL: 110 return 0; 111 case PIPE_CAP_ANISOTROPIC_FILTER: 112 return 1; 113 case PIPE_CAP_POINT_SPRITE: 114 return 1; 115 case PIPE_CAP_MAX_RENDER_TARGETS: 116 return 8; 117 case PIPE_CAP_OCCLUSION_QUERY: 118 return 1; 119 case PIPE_CAP_TEXTURE_SHADOW_MAP: 120 return 1; 121 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: 122 return 13; 123 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 124 return 10; 125 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 126 return 13; 127 case PIPE_CAP_TEXTURE_MIRROR_CLAMP: 128 case PIPE_CAP_TEXTURE_MIRROR_REPEAT: 129 return 1; 130 case PIPE_CAP_TGSI_CONT_SUPPORTED: 131 return 1; 132 case PIPE_CAP_BLEND_EQUATION_SEPARATE: 133 return 1; 134 case NOUVEAU_CAP_HW_VTXBUF: 135 return 1; 136 case NOUVEAU_CAP_HW_IDXBUF: 137 return 1; 138 case PIPE_CAP_INDEP_BLEND_ENABLE: 139 return 1; 140 case PIPE_CAP_INDEP_BLEND_FUNC: 141 return 0; 142 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 143 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 144 return 1; 145 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 146 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 147 return 0; 148 default: 149 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); 150 return 0; 151 } 152} 153 154static float 155nv50_screen_get_paramf(struct pipe_screen *pscreen, int param) 156{ 157 switch (param) { 158 case PIPE_CAP_MAX_LINE_WIDTH: 159 case PIPE_CAP_MAX_LINE_WIDTH_AA: 160 return 10.0; 161 case PIPE_CAP_MAX_POINT_WIDTH: 162 case PIPE_CAP_MAX_POINT_WIDTH_AA: 163 return 64.0; 164 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: 165 return 16.0; 166 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: 167 return 4.0; 168 default: 169 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); 170 return 0.0; 171 } 172} 173 174static void 175nv50_screen_destroy(struct pipe_screen *pscreen) 176{ 177 struct nv50_screen *screen = nv50_screen(pscreen); 178 unsigned i; 179 180 for (i = 0; i < 3; i++) { 181 if (screen->constbuf_parm[i]) 182 nouveau_bo_ref(NULL, &screen->constbuf_parm[i]); 183 } 184 185 if (screen->constbuf_misc[0]) 186 nouveau_bo_ref(NULL, &screen->constbuf_misc[0]); 187 if (screen->tic) 188 nouveau_bo_ref(NULL, &screen->tic); 189 if (screen->tsc) 190 nouveau_bo_ref(NULL, &screen->tsc); 191 if (screen->static_init) 192 so_ref(NULL, &screen->static_init); 193 194 nouveau_notifier_free(&screen->sync); 195 nouveau_grobj_free(&screen->tesla); 196 nouveau_grobj_free(&screen->eng2d); 197 nouveau_grobj_free(&screen->m2mf); 198 nouveau_resource_destroy(&screen->immd_heap[0]); 199 nouveau_resource_destroy(&screen->parm_heap[0]); 200 nouveau_resource_destroy(&screen->parm_heap[1]); 201 nouveau_screen_fini(&screen->base); 202 FREE(screen); 203} 204 205struct pipe_screen * 206nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) 207{ 208 struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); 209 struct nouveau_channel *chan; 210 struct pipe_screen *pscreen; 211 struct nouveau_stateobj *so; 212 unsigned chipset = dev->chipset; 213 unsigned tesla_class = 0; 214 int ret, i; 215 216 if (!screen) 217 return NULL; 218 pscreen = &screen->base.base; 219 220 ret = nouveau_screen_init(&screen->base, dev); 221 if (ret) { 222 nv50_screen_destroy(pscreen); 223 return NULL; 224 } 225 chan = screen->base.channel; 226 227 pscreen->winsys = ws; 228 pscreen->destroy = nv50_screen_destroy; 229 pscreen->get_param = nv50_screen_get_param; 230 pscreen->get_paramf = nv50_screen_get_paramf; 231 pscreen->is_format_supported = nv50_screen_is_format_supported; 232 pscreen->context_create = nv50_create; 233 234 nv50_screen_init_miptree_functions(pscreen); 235 nv50_transfer_init_screen_functions(pscreen); 236 237 /* DMA engine object */ 238 ret = nouveau_grobj_alloc(chan, 0xbeef5039, 239 NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf); 240 if (ret) { 241 NOUVEAU_ERR("Error creating M2MF object: %d\n", ret); 242 nv50_screen_destroy(pscreen); 243 return NULL; 244 } 245 246 /* 2D object */ 247 ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d); 248 if (ret) { 249 NOUVEAU_ERR("Error creating 2D object: %d\n", ret); 250 nv50_screen_destroy(pscreen); 251 return NULL; 252 } 253 254 /* 3D object */ 255 switch (chipset & 0xf0) { 256 case 0x50: 257 tesla_class = NV50TCL; 258 break; 259 case 0x80: 260 case 0x90: 261 tesla_class = NV84TCL; 262 break; 263 case 0xa0: 264 switch (chipset) { 265 case 0xa0: 266 case 0xaa: 267 case 0xac: 268 tesla_class = NVA0TCL; 269 break; 270 default: 271 tesla_class = NVA8TCL; 272 break; 273 } 274 break; 275 default: 276 NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset); 277 nv50_screen_destroy(pscreen); 278 return NULL; 279 } 280 281 ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class, 282 &screen->tesla); 283 if (ret) { 284 NOUVEAU_ERR("Error creating 3D object: %d\n", ret); 285 nv50_screen_destroy(pscreen); 286 return NULL; 287 } 288 289 /* Sync notifier */ 290 ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); 291 if (ret) { 292 NOUVEAU_ERR("Error creating notifier object: %d\n", ret); 293 nv50_screen_destroy(pscreen); 294 return NULL; 295 } 296 297 /* Static M2MF init */ 298 so = so_new(1, 3, 0); 299 so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); 300 so_data (so, screen->sync->handle); 301 so_data (so, chan->vram->handle); 302 so_data (so, chan->vram->handle); 303 so_emit(chan, so); 304 so_ref (NULL, &so); 305 306 /* Static 2D init */ 307 so = so_new(4, 7, 0); 308 so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4); 309 so_data (so, screen->sync->handle); 310 so_data (so, chan->vram->handle); 311 so_data (so, chan->vram->handle); 312 so_data (so, chan->vram->handle); 313 so_method(so, screen->eng2d, NV50_2D_OPERATION, 1); 314 so_data (so, NV50_2D_OPERATION_SRCCOPY); 315 so_method(so, screen->eng2d, NV50_2D_CLIP_ENABLE, 1); 316 so_data (so, 0); 317 so_method(so, screen->eng2d, 0x0888, 1); 318 so_data (so, 1); 319 so_emit(chan, so); 320 so_ref(NULL, &so); 321 322 /* Static tesla init */ 323 so = so_new(47, 95, 24); 324 325 so_method(so, screen->tesla, NV50TCL_COND_MODE, 1); 326 so_data (so, NV50TCL_COND_MODE_ALWAYS); 327 so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1); 328 so_data (so, screen->sync->handle); 329 so_method(so, screen->tesla, NV50TCL_DMA_ZETA, 11); 330 for (i = 0; i < 11; i++) 331 so_data(so, chan->vram->handle); 332 so_method(so, screen->tesla, NV50TCL_DMA_COLOR(0), 333 NV50TCL_DMA_COLOR__SIZE); 334 for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++) 335 so_data(so, chan->vram->handle); 336 so_method(so, screen->tesla, NV50TCL_RT_CONTROL, 1); 337 so_data (so, 1); 338 339 /* activate all 32 lanes (threads) in a warp */ 340 so_method(so, screen->tesla, NV50TCL_WARP_HALVES, 1); 341 so_data (so, 0x2); 342 so_method(so, screen->tesla, 0x1400, 1); 343 so_data (so, 0xf); 344 345 /* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */ 346 for (i = 0; i < 3; ++i) { 347 so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1); 348 so_data (so, 0x54); 349 } 350 351 /* origin is top left (set to 1 for bottom left) */ 352 so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1); 353 so_data (so, 0); 354 so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1); 355 so_data (so, 8); 356 357 /* constant buffers for immediates and VP/FP parameters */ 358 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4, 359 &screen->constbuf_misc[0]); 360 if (ret) { 361 nv50_screen_destroy(pscreen); 362 return NULL; 363 } 364 365 for (i = 0; i < 3; i++) { 366 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4, 367 &screen->constbuf_parm[i]); 368 if (ret) { 369 nv50_screen_destroy(pscreen); 370 return NULL; 371 } 372 } 373 374 if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) || 375 nouveau_resource_init(&screen->parm_heap[0], 0, 512) || 376 nouveau_resource_init(&screen->parm_heap[1], 0, 512)) 377 { 378 NOUVEAU_ERR("Error initialising constant buffers.\n"); 379 nv50_screen_destroy(pscreen); 380 return NULL; 381 } 382 383 /* 384 // map constant buffers: 385 // B = buffer ID (maybe more than 1 byte) 386 // N = CB index used in shader instruction 387 // P = program type (0 = VP, 2 = GP, 3 = FP) 388 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 389 so_data (so, 0x000BBNP1); 390 */ 391 392 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 393 so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | 394 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 395 so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | 396 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 397 so_data (so, (NV50_CB_PMISC << 16) | 0x00000200); 398 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 399 so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); 400 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 401 so_data (so, 0x00000021 | (NV50_CB_PMISC << 12)); 402 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 403 so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); 404 405 /* bind auxiliary constbuf to immediate data bo */ 406 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 407 so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, 408 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 409 so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, 410 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 411 so_data (so, (NV50_CB_AUX << 16) | 0x00000200); 412 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 413 so_data (so, 0x00000201 | (NV50_CB_AUX << 12)); 414 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 415 so_data (so, 0x00000221 | (NV50_CB_AUX << 12)); 416 417 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 418 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, 419 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 420 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, 421 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 422 so_data (so, (NV50_CB_PVP << 16) | 0x00000800); 423 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 424 so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); 425 426 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 427 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, 428 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 429 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, 430 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 431 so_data (so, (NV50_CB_PGP << 16) | 0x00000800); 432 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 433 so_data (so, 0x00000121 | (NV50_CB_PGP << 12)); 434 435 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 436 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0, 437 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 438 so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0, 439 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 440 so_data (so, (NV50_CB_PFP << 16) | 0x00000800); 441 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 442 so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); 443 444 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, 445 &screen->tic); 446 if (ret) { 447 nv50_screen_destroy(pscreen); 448 return NULL; 449 } 450 451 so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3); 452 so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | 453 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 454 so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | 455 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 456 so_data (so, PIPE_SHADER_TYPES * 32 - 1); 457 458 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, 459 &screen->tsc); 460 if (ret) { 461 nv50_screen_destroy(pscreen); 462 return NULL; 463 } 464 465 so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3); 466 so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | 467 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 468 so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | 469 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 470 so_data (so, 0x00000000); /* ignored if TSC_LINKED (0x1234) = 1 */ 471 472 473 /* Vertex array limits - max them out */ 474 for (i = 0; i < 16; i++) { 475 so_method(so, screen->tesla, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2); 476 so_data (so, 0x000000ff); 477 so_data (so, 0xffffffff); 478 } 479 480 so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2); 481 so_data (so, fui(0.0)); 482 so_data (so, fui(1.0)); 483 484 /* no dynamic combination of TIC & TSC entries => only BIND_TIC used */ 485 so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1); 486 so_data (so, 1); 487 488 /* activate first scissor rectangle */ 489 so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE(0), 1); 490 so_data (so, 1); 491 492 so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1); 493 so_data (so, 1); /* default edgeflag to TRUE */ 494 495 so_emit(chan, so); 496 so_ref (so, &screen->static_init); 497 so_ref (NULL, &so); 498 nouveau_pushbuf_flush(chan, 0); 499 500 return pscreen; 501} 502 503