nv50_screen.c revision b0036f391a1862c15c4e33d221314926dba3213b
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_X8R8G8B8_UNORM: 39 case PIPE_FORMAT_A8R8G8B8_UNORM: 40 case PIPE_FORMAT_R5G6B5_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_Z24S8_UNORM: 55 case PIPE_FORMAT_X8Z24_UNORM: 56 case PIPE_FORMAT_S8Z24_UNORM: 57 return TRUE; 58 default: 59 break; 60 } 61 } else { 62 switch (format) { 63 case PIPE_FORMAT_A8R8G8B8_UNORM: 64 case PIPE_FORMAT_X8R8G8B8_UNORM: 65 case PIPE_FORMAT_A8R8G8B8_SRGB: 66 case PIPE_FORMAT_X8R8G8B8_SRGB: 67 case PIPE_FORMAT_A1R5G5B5_UNORM: 68 case PIPE_FORMAT_A4R4G4B4_UNORM: 69 case PIPE_FORMAT_R5G6B5_UNORM: 70 case PIPE_FORMAT_L8_UNORM: 71 case PIPE_FORMAT_A8_UNORM: 72 case PIPE_FORMAT_I8_UNORM: 73 case PIPE_FORMAT_A8L8_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_Z24S8_UNORM: 79 case PIPE_FORMAT_S8Z24_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 0; 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 0; 138 default: 139 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); 140 return 0; 141 } 142} 143 144static float 145nv50_screen_get_paramf(struct pipe_screen *pscreen, int param) 146{ 147 switch (param) { 148 case PIPE_CAP_MAX_LINE_WIDTH: 149 case PIPE_CAP_MAX_LINE_WIDTH_AA: 150 return 10.0; 151 case PIPE_CAP_MAX_POINT_WIDTH: 152 case PIPE_CAP_MAX_POINT_WIDTH_AA: 153 return 64.0; 154 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: 155 return 16.0; 156 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: 157 return 4.0; 158 default: 159 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); 160 return 0.0; 161 } 162} 163 164static void 165nv50_screen_destroy(struct pipe_screen *pscreen) 166{ 167 struct nv50_screen *screen = nv50_screen(pscreen); 168 169 nouveau_notifier_free(&screen->sync); 170 nouveau_grobj_free(&screen->tesla); 171 nouveau_grobj_free(&screen->eng2d); 172 nouveau_grobj_free(&screen->m2mf); 173 nouveau_screen_fini(&screen->base); 174 FREE(screen); 175} 176 177struct pipe_screen * 178nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) 179{ 180 struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); 181 struct nouveau_channel *chan; 182 struct pipe_screen *pscreen; 183 struct nouveau_stateobj *so; 184 unsigned chipset = dev->chipset; 185 unsigned tesla_class = 0; 186 int ret, i; 187 188 if (!screen) 189 return NULL; 190 pscreen = &screen->base.base; 191 192 ret = nouveau_screen_init(&screen->base, dev); 193 if (ret) { 194 nv50_screen_destroy(pscreen); 195 return NULL; 196 } 197 chan = screen->base.channel; 198 199 pscreen->winsys = ws; 200 pscreen->destroy = nv50_screen_destroy; 201 pscreen->get_param = nv50_screen_get_param; 202 pscreen->get_paramf = nv50_screen_get_paramf; 203 pscreen->is_format_supported = nv50_screen_is_format_supported; 204 205 nv50_screen_init_miptree_functions(pscreen); 206 nv50_transfer_init_screen_functions(pscreen); 207 208 /* DMA engine object */ 209 ret = nouveau_grobj_alloc(chan, 0xbeef5039, 210 NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf); 211 if (ret) { 212 NOUVEAU_ERR("Error creating M2MF object: %d\n", ret); 213 nv50_screen_destroy(pscreen); 214 return NULL; 215 } 216 BIND_RING(chan, screen->m2mf, 1); 217 218 /* 2D object */ 219 ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d); 220 if (ret) { 221 NOUVEAU_ERR("Error creating 2D object: %d\n", ret); 222 nv50_screen_destroy(pscreen); 223 return NULL; 224 } 225 BIND_RING(chan, screen->eng2d, 2); 226 227 /* 3D object */ 228 switch (chipset & 0xf0) { 229 case 0x50: 230 tesla_class = NV50TCL; 231 break; 232 case 0x80: 233 case 0x90: 234 /* this stupid name should be corrected. */ 235 tesla_class = NV54TCL; 236 break; 237 case 0xa0: 238 switch (chipset) { 239 case 0xa0: 240 case 0xaa: 241 case 0xac: 242 tesla_class = NVA0TCL; 243 break; 244 default: 245 tesla_class = 0x8597; 246 break; 247 } 248 break; 249 default: 250 NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset); 251 nv50_screen_destroy(pscreen); 252 return NULL; 253 } 254 255 ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class, 256 &screen->tesla); 257 if (ret) { 258 NOUVEAU_ERR("Error creating 3D object: %d\n", ret); 259 nv50_screen_destroy(pscreen); 260 return NULL; 261 } 262 BIND_RING(chan, screen->tesla, 3); 263 264 /* Sync notifier */ 265 ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); 266 if (ret) { 267 NOUVEAU_ERR("Error creating notifier object: %d\n", ret); 268 nv50_screen_destroy(pscreen); 269 return NULL; 270 } 271 272 /* Static M2MF init */ 273 so = so_new(32, 0); 274 so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); 275 so_data (so, screen->sync->handle); 276 so_data (so, chan->vram->handle); 277 so_data (so, chan->vram->handle); 278 so_emit(chan, so); 279 so_ref (NULL, &so); 280 281 /* Static 2D init */ 282 so = so_new(64, 0); 283 so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4); 284 so_data (so, screen->sync->handle); 285 so_data (so, chan->vram->handle); 286 so_data (so, chan->vram->handle); 287 so_data (so, chan->vram->handle); 288 so_method(so, screen->eng2d, NV50_2D_OPERATION, 1); 289 so_data (so, NV50_2D_OPERATION_SRCCOPY); 290 so_method(so, screen->eng2d, 0x0290, 1); 291 so_data (so, 0); 292 so_method(so, screen->eng2d, 0x0888, 1); 293 so_data (so, 1); 294 so_emit(chan, so); 295 so_ref(NULL, &so); 296 297 /* Static tesla init */ 298 so = so_new(256, 20); 299 300 so_method(so, screen->tesla, 0x1558, 1); 301 so_data (so, 1); 302 so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1); 303 so_data (so, screen->sync->handle); 304 so_method(so, screen->tesla, NV50TCL_DMA_UNK0(0), 305 NV50TCL_DMA_UNK0__SIZE); 306 for (i = 0; i < NV50TCL_DMA_UNK0__SIZE; i++) 307 so_data(so, chan->vram->handle); 308 so_method(so, screen->tesla, NV50TCL_DMA_UNK1(0), 309 NV50TCL_DMA_UNK1__SIZE); 310 for (i = 0; i < NV50TCL_DMA_UNK1__SIZE; i++) 311 so_data(so, chan->vram->handle); 312 so_method(so, screen->tesla, 0x121c, 1); 313 so_data (so, 1); 314 315 /* activate all 32 lanes (threads) in a warp */ 316 so_method(so, screen->tesla, 0x19a0, 1); 317 so_data (so, 0x2); 318 so_method(so, screen->tesla, 0x1400, 1); 319 so_data (so, 0xf); 320 321 /* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */ 322 so_method(so, screen->tesla, 0x13b4, 1); 323 so_data (so, 0x54); 324 so_method(so, screen->tesla, 0x13bc, 1); 325 so_data (so, 0x54); 326 /* origin is top left (set to 1 for bottom left) */ 327 so_method(so, screen->tesla, 0x13ac, 1); 328 so_data (so, 0); 329 so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1); 330 so_data (so, 8); 331 332 /* constant buffers for immediates and VP/FP parameters */ 333 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4, 334 &screen->constbuf_misc[0]); 335 if (ret) { 336 nv50_screen_destroy(pscreen); 337 return NULL; 338 } 339 340 for (i = 0; i < 2; i++) { 341 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4, 342 &screen->constbuf_parm[i]); 343 if (ret) { 344 nv50_screen_destroy(pscreen); 345 return NULL; 346 } 347 } 348 349 if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) || 350 nouveau_resource_init(&screen->parm_heap[0], 0, 512) || 351 nouveau_resource_init(&screen->parm_heap[1], 0, 512)) 352 { 353 NOUVEAU_ERR("Error initialising constant buffers.\n"); 354 nv50_screen_destroy(pscreen); 355 return NULL; 356 } 357 358 /* 359 // map constant buffers: 360 // B = buffer ID (maybe more than 1 byte) 361 // N = CB index used in shader instruction 362 // P = program type (0 = VP, 2 = GP, 3 = FP) 363 so_method(so, screen->tesla, 0x1694, 1); 364 so_data (so, 0x000BBNP1); 365 */ 366 367 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 368 so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | 369 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 370 so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | 371 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 372 so_data (so, (NV50_CB_PMISC << 16) | 0x00000200); 373 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 374 so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); 375 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 376 so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); 377 378 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 379 so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | 380 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 381 so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | 382 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 383 so_data (so, (NV50_CB_PVP << 16) | 0x00000800); 384 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 385 so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); 386 387 so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); 388 so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | 389 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 390 so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | 391 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 392 so_data (so, (NV50_CB_PFP << 16) | 0x00000800); 393 so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); 394 so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); 395 396 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, 397 &screen->tic); 398 if (ret) { 399 nv50_screen_destroy(pscreen); 400 return NULL; 401 } 402 403 so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3); 404 so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | 405 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 406 so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | 407 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 408 so_data (so, PIPE_SHADER_TYPES * 32 - 1); 409 410 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, 411 &screen->tsc); 412 if (ret) { 413 nv50_screen_destroy(pscreen); 414 return NULL; 415 } 416 417 so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3); 418 so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | 419 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); 420 so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | 421 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); 422 so_data (so, 0x00000000); 423 424 425 /* Vertex array limits - max them out */ 426 for (i = 0; i < 16; i++) { 427 so_method(so, screen->tesla, NV50TCL_UNK1080_OFFSET_HIGH(i), 2); 428 so_data (so, 0x000000ff); 429 so_data (so, 0xffffffff); 430 } 431 432 so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR, 2); 433 so_data (so, fui(0.0)); 434 so_data (so, fui(1.0)); 435 436 so_method(so, screen->tesla, 0x1234, 1); 437 so_data (so, 1); 438 439 /* activate first scissor rectangle */ 440 so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1); 441 so_data (so, 1); 442 443 so_emit(chan, so); 444 so_ref (so, &screen->static_init); 445 so_ref (NULL, &so); 446 nouveau_pushbuf_flush(chan, 0); 447 448 return pscreen; 449} 450 451