nv30_vbo.c revision f302fca5eb63e4bca8af5b35c585451486143e6a
1#include "pipe/p_context.h" 2#include "pipe/p_state.h" 3 4#include "nv30_context.h" 5#include "nv30_state.h" 6 7#include "nouveau/nouveau_channel.h" 8#include "nouveau/nouveau_pushbuf.h" 9#include "nouveau/nouveau_util.h" 10 11#define FORCE_SWTNL 0 12 13static INLINE int 14nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) 15{ 16 switch (pipe) { 17 case PIPE_FORMAT_R32_FLOAT: 18 case PIPE_FORMAT_R32G32_FLOAT: 19 case PIPE_FORMAT_R32G32B32_FLOAT: 20 case PIPE_FORMAT_R32G32B32A32_FLOAT: 21 *fmt = NV34TCL_VTXFMT_TYPE_FLOAT; 22 break; 23 case PIPE_FORMAT_R8_UNORM: 24 case PIPE_FORMAT_R8G8_UNORM: 25 case PIPE_FORMAT_R8G8B8_UNORM: 26 case PIPE_FORMAT_R8G8B8A8_UNORM: 27 *fmt = NV34TCL_VTXFMT_TYPE_UBYTE; 28 break; 29 case PIPE_FORMAT_R16_SSCALED: 30 case PIPE_FORMAT_R16G16_SSCALED: 31 case PIPE_FORMAT_R16G16B16_SSCALED: 32 case PIPE_FORMAT_R16G16B16A16_SSCALED: 33 *fmt = NV34TCL_VTXFMT_TYPE_USHORT; 34 break; 35 default: 36 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe)); 37 return 1; 38 } 39 40 switch (pipe) { 41 case PIPE_FORMAT_R8_UNORM: 42 case PIPE_FORMAT_R32_FLOAT: 43 case PIPE_FORMAT_R16_SSCALED: 44 *ncomp = 1; 45 break; 46 case PIPE_FORMAT_R8G8_UNORM: 47 case PIPE_FORMAT_R32G32_FLOAT: 48 case PIPE_FORMAT_R16G16_SSCALED: 49 *ncomp = 2; 50 break; 51 case PIPE_FORMAT_R8G8B8_UNORM: 52 case PIPE_FORMAT_R32G32B32_FLOAT: 53 case PIPE_FORMAT_R16G16B16_SSCALED: 54 *ncomp = 3; 55 break; 56 case PIPE_FORMAT_R8G8B8A8_UNORM: 57 case PIPE_FORMAT_R32G32B32A32_FLOAT: 58 case PIPE_FORMAT_R16G16B16A16_SSCALED: 59 *ncomp = 4; 60 break; 61 default: 62 NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe)); 63 return 1; 64 } 65 66 return 0; 67} 68 69static boolean 70nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, 71 unsigned ib_size) 72{ 73 struct pipe_screen *pscreen = &nv30->screen->pipe; 74 unsigned type; 75 76 if (!ib) { 77 nv30->idxbuf = NULL; 78 nv30->idxbuf_format = 0xdeadbeef; 79 return FALSE; 80 } 81 82 if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) 83 return FALSE; 84 85 switch (ib_size) { 86 case 2: 87 type = NV34TCL_IDXBUF_FORMAT_TYPE_U16; 88 break; 89 case 4: 90 type = NV34TCL_IDXBUF_FORMAT_TYPE_U32; 91 break; 92 default: 93 return FALSE; 94 } 95 96 if (ib != nv30->idxbuf || 97 type != nv30->idxbuf_format) { 98 nv30->dirty |= NV30_NEW_ARRAYS; 99 nv30->idxbuf = ib; 100 nv30->idxbuf_format = type; 101 } 102 103 return TRUE; 104} 105 106static boolean 107nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, 108 int attrib, struct pipe_vertex_element *ve, 109 struct pipe_vertex_buffer *vb) 110{ 111 struct pipe_winsys *ws = nv30->pipe.winsys; 112 struct nouveau_grobj *rankine = nv30->screen->rankine; 113 unsigned type, ncomp; 114 void *map; 115 116 if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) 117 return FALSE; 118 119 map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); 120 map += vb->buffer_offset + ve->src_offset; 121 122 switch (type) { 123 case NV34TCL_VTXFMT_TYPE_FLOAT: 124 { 125 float *v = map; 126 127 switch (ncomp) { 128 case 4: 129 so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4); 130 so_data (so, fui(v[0])); 131 so_data (so, fui(v[1])); 132 so_data (so, fui(v[2])); 133 so_data (so, fui(v[3])); 134 break; 135 case 3: 136 so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3); 137 so_data (so, fui(v[0])); 138 so_data (so, fui(v[1])); 139 so_data (so, fui(v[2])); 140 break; 141 case 2: 142 so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2); 143 so_data (so, fui(v[0])); 144 so_data (so, fui(v[1])); 145 break; 146 case 1: 147 so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1); 148 so_data (so, fui(v[0])); 149 break; 150 default: 151 ws->buffer_unmap(ws, vb->buffer); 152 return FALSE; 153 } 154 } 155 break; 156 default: 157 ws->buffer_unmap(ws, vb->buffer); 158 return FALSE; 159 } 160 161 ws->buffer_unmap(ws, vb->buffer); 162 163 return TRUE; 164} 165 166boolean 167nv30_draw_arrays(struct pipe_context *pipe, 168 unsigned mode, unsigned start, unsigned count) 169{ 170 struct nv30_context *nv30 = nv30_context(pipe); 171 struct nouveau_channel *chan = nv30->nvws->channel; 172 unsigned restart = 0; 173 174 nv30_vbo_set_idxbuf(nv30, NULL, 0); 175 if (FORCE_SWTNL || !nv30_state_validate(nv30)) { 176 /*return nv30_draw_elements_swtnl(pipe, NULL, 0, 177 mode, start, count);*/ 178 return FALSE; 179 } 180 181 while (count) { 182 unsigned vc, nr; 183 184 nv30_state_emit(nv30); 185 186 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, 187 mode, start, count, &restart); 188 if (!vc) { 189 FIRE_RING(NULL); 190 continue; 191 } 192 193 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 194 OUT_RING (nvgl_primitive(mode)); 195 196 nr = (vc & 0xff); 197 if (nr) { 198 BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1); 199 OUT_RING (((nr - 1) << 24) | start); 200 start += nr; 201 } 202 203 nr = vc >> 8; 204 while (nr) { 205 unsigned push = nr > 2047 ? 2047 : nr; 206 207 nr -= push; 208 209 BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push); 210 while (push--) { 211 OUT_RING(((0x100 - 1) << 24) | start); 212 start += 0x100; 213 } 214 } 215 216 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 217 OUT_RING (0); 218 219 count -= vc; 220 start = restart; 221 } 222 223 pipe->flush(pipe, 0, NULL); 224 return TRUE; 225} 226 227static INLINE void 228nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, 229 unsigned mode, unsigned start, unsigned count) 230{ 231 struct nouveau_channel *chan = nv30->nvws->channel; 232 233 while (count) { 234 uint8_t *elts = (uint8_t *)ib + start; 235 unsigned vc, push, restart = 0; 236 237 nv30_state_emit(nv30); 238 239 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, 240 mode, start, count, &restart); 241 if (vc == 0) { 242 FIRE_RING(NULL); 243 continue; 244 } 245 count -= vc; 246 247 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 248 OUT_RING (nvgl_primitive(mode)); 249 250 if (vc & 1) { 251 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1); 252 OUT_RING (elts[0]); 253 elts++; vc--; 254 } 255 256 while (vc) { 257 unsigned i; 258 259 push = MIN2(vc, 2047 * 2); 260 261 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); 262 for (i = 0; i < push; i+=2) 263 OUT_RING((elts[i+1] << 16) | elts[i]); 264 265 vc -= push; 266 elts += push; 267 } 268 269 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 270 OUT_RING (0); 271 272 start = restart; 273 } 274} 275 276static INLINE void 277nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, 278 unsigned mode, unsigned start, unsigned count) 279{ 280 struct nouveau_channel *chan = nv30->nvws->channel; 281 282 while (count) { 283 uint16_t *elts = (uint16_t *)ib + start; 284 unsigned vc, push, restart = 0; 285 286 nv30_state_emit(nv30); 287 288 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, 289 mode, start, count, &restart); 290 if (vc == 0) { 291 FIRE_RING(NULL); 292 continue; 293 } 294 count -= vc; 295 296 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 297 OUT_RING (nvgl_primitive(mode)); 298 299 if (vc & 1) { 300 BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1); 301 OUT_RING (elts[0]); 302 elts++; vc--; 303 } 304 305 while (vc) { 306 unsigned i; 307 308 push = MIN2(vc, 2047 * 2); 309 310 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); 311 for (i = 0; i < push; i+=2) 312 OUT_RING((elts[i+1] << 16) | elts[i]); 313 314 vc -= push; 315 elts += push; 316 } 317 318 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 319 OUT_RING (0); 320 321 start = restart; 322 } 323} 324 325static INLINE void 326nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, 327 unsigned mode, unsigned start, unsigned count) 328{ 329 struct nouveau_channel *chan = nv30->nvws->channel; 330 331 while (count) { 332 uint32_t *elts = (uint32_t *)ib + start; 333 unsigned vc, push, restart = 0; 334 335 nv30_state_emit(nv30); 336 337 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1, 338 mode, start, count, &restart); 339 if (vc == 0) { 340 FIRE_RING(NULL); 341 continue; 342 } 343 count -= vc; 344 345 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 346 OUT_RING (nvgl_primitive(mode)); 347 348 while (vc) { 349 push = MIN2(vc, 2047); 350 351 BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push); 352 OUT_RINGp (elts, push); 353 354 vc -= push; 355 elts += push; 356 } 357 358 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 359 OUT_RING (0); 360 361 start = restart; 362 } 363} 364 365static boolean 366nv30_draw_elements_inline(struct pipe_context *pipe, 367 struct pipe_buffer *ib, unsigned ib_size, 368 unsigned mode, unsigned start, unsigned count) 369{ 370 struct nv30_context *nv30 = nv30_context(pipe); 371 struct pipe_winsys *ws = pipe->winsys; 372 void *map; 373 374 map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); 375 if (!ib) { 376 NOUVEAU_ERR("failed mapping ib\n"); 377 return FALSE; 378 } 379 380 switch (ib_size) { 381 case 1: 382 nv30_draw_elements_u08(nv30, map, mode, start, count); 383 break; 384 case 2: 385 nv30_draw_elements_u16(nv30, map, mode, start, count); 386 break; 387 case 4: 388 nv30_draw_elements_u32(nv30, map, mode, start, count); 389 break; 390 default: 391 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); 392 break; 393 } 394 395 ws->buffer_unmap(ws, ib); 396 return TRUE; 397} 398 399static boolean 400nv30_draw_elements_vbo(struct pipe_context *pipe, 401 unsigned mode, unsigned start, unsigned count) 402{ 403 struct nv30_context *nv30 = nv30_context(pipe); 404 struct nouveau_channel *chan = nv30->nvws->channel; 405 unsigned restart = 0; 406 407 while (count) { 408 unsigned nr, vc; 409 410 nv30_state_emit(nv30); 411 412 vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, 413 mode, start, count, &restart); 414 if (!vc) { 415 FIRE_RING(NULL); 416 continue; 417 } 418 419 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 420 OUT_RING (nvgl_primitive(mode)); 421 422 nr = (vc & 0xff); 423 if (nr) { 424 BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1); 425 OUT_RING (((nr - 1) << 24) | start); 426 start += nr; 427 } 428 429 nr = vc >> 8; 430 while (nr) { 431 unsigned push = nr > 2047 ? 2047 : nr; 432 433 nr -= push; 434 435 BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push); 436 while (push--) { 437 OUT_RING(((0x100 - 1) << 24) | start); 438 start += 0x100; 439 } 440 } 441 442 BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); 443 OUT_RING (0); 444 445 count -= vc; 446 start = restart; 447 } 448 449 return TRUE; 450} 451 452boolean 453nv30_draw_elements(struct pipe_context *pipe, 454 struct pipe_buffer *indexBuffer, unsigned indexSize, 455 unsigned mode, unsigned start, unsigned count) 456{ 457 struct nv30_context *nv30 = nv30_context(pipe); 458 boolean idxbuf; 459 460 idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize); 461 if (FORCE_SWTNL || !nv30_state_validate(nv30)) { 462 /*return nv30_draw_elements_swtnl(pipe, NULL, 0, 463 mode, start, count);*/ 464 return FALSE; 465 } 466 467 if (idxbuf) { 468 nv30_draw_elements_vbo(pipe, mode, start, count); 469 } else { 470 nv30_draw_elements_inline(pipe, indexBuffer, indexSize, 471 mode, start, count); 472 } 473 474 pipe->flush(pipe, 0, NULL); 475 return TRUE; 476} 477 478static boolean 479nv30_vbo_validate(struct nv30_context *nv30) 480{ 481 struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; 482 struct nouveau_grobj *rankine = nv30->screen->rankine; 483 struct pipe_buffer *ib = nv30->idxbuf; 484 unsigned ib_format = nv30->idxbuf_format; 485 unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; 486 int hw; 487 488 if (nv30->edgeflags) { 489 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ 490 return FALSE; 491 } 492 493 vtxbuf = so_new(20, 18); 494 so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr); 495 vtxfmt = so_new(17, 0); 496 so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr); 497 498 for (hw = 0; hw < nv30->vtxelt_nr; hw++) { 499 struct pipe_vertex_element *ve; 500 struct pipe_vertex_buffer *vb; 501 unsigned type, ncomp; 502 503 ve = &nv30->vtxelt[hw]; 504 vb = &nv30->vtxbuf[ve->vertex_buffer_index]; 505 506 if (!vb->pitch) { 507 if (!sattr) 508 sattr = so_new(16 * 5, 0); 509 510 if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) { 511 so_data(vtxbuf, 0); 512 so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); 513 continue; 514 } 515 } 516 517 if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { 518 /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ 519 so_ref(NULL, &vtxbuf); 520 so_ref(NULL, &vtxfmt); 521 return FALSE; 522 } 523 524 so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset, 525 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, 526 0, NV34TCL_VTXBUF_ADDRESS_DMA1); 527 so_data (vtxfmt, ((vb->pitch << NV34TCL_VTXFMT_STRIDE_SHIFT) | 528 (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); 529 } 530 531 if (ib) { 532 so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2); 533 so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); 534 so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, 535 0, NV34TCL_IDXBUF_FORMAT_DMA1); 536 } 537 538 so_method(vtxbuf, rankine, 0x1710, 1); 539 so_data (vtxbuf, 0); 540 541 so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]); 542 nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF); 543 so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]); 544 nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT); 545 so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]); 546 nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR); 547 return FALSE; 548} 549 550struct nv30_state_entry nv30_state_vbo = { 551 .validate = nv30_vbo_validate, 552 .dirty = { 553 .pipe = NV30_NEW_ARRAYS, 554 .hw = 0, 555 } 556}; 557