Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

nv30_vbo.c 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #include "pipe/p_context.h"
  2. #include "pipe/p_state.h"
  3. #include "pipe/p_util.h"
  4. #include "nv30_context.h"
  5. #include "nv30_state.h"
  6. #include "nouveau/nouveau_channel.h"
  7. #include "nouveau/nouveau_pushbuf.h"
  8. static INLINE int
  9. nv30_vbo_ncomp(uint format)
  10. {
  11. int ncomp = 0;
  12. if (pf_size_x(format)) ncomp++;
  13. if (pf_size_y(format)) ncomp++;
  14. if (pf_size_z(format)) ncomp++;
  15. if (pf_size_w(format)) ncomp++;
  16. return ncomp;
  17. }
  18. static INLINE int
  19. nv30_vbo_type(uint format)
  20. {
  21. switch (pf_type(format)) {
  22. case PIPE_FORMAT_TYPE_FLOAT:
  23. return NV34TCL_VERTEX_ARRAY_FORMAT_TYPE_FLOAT;
  24. case PIPE_FORMAT_TYPE_UNORM:
  25. return NV34TCL_VERTEX_ARRAY_FORMAT_TYPE_UBYTE;
  26. default:
  27. NOUVEAU_ERR("Unknown format 0x%08x\n", format);
  28. return NV40TCL_VTXFMT_TYPE_FLOAT;
  29. }
  30. }
  31. static boolean
  32. nv30_vbo_static_attrib(struct nv30_context *nv30, int attrib,
  33. struct pipe_vertex_element *ve,
  34. struct pipe_vertex_buffer *vb)
  35. {
  36. struct pipe_winsys *ws = nv30->pipe.winsys;
  37. int type, ncomp;
  38. void *map;
  39. type = nv30_vbo_type(ve->src_format);
  40. ncomp = nv30_vbo_ncomp(ve->src_format);
  41. map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
  42. map += vb->buffer_offset + ve->src_offset;
  43. switch (type) {
  44. case NV34TCL_VERTEX_ARRAY_FORMAT_TYPE_FLOAT:
  45. {
  46. float *v = map;
  47. BEGIN_RING(rankine, NV34TCL_VERTEX_ATTR_4F_X(attrib), 4);
  48. switch (ncomp) {
  49. case 4:
  50. OUT_RINGf(v[0]);
  51. OUT_RINGf(v[1]);
  52. OUT_RINGf(v[2]);
  53. OUT_RINGf(v[3]);
  54. break;
  55. case 3:
  56. OUT_RINGf(v[0]);
  57. OUT_RINGf(v[1]);
  58. OUT_RINGf(v[2]);
  59. OUT_RINGf(1.0);
  60. break;
  61. case 2:
  62. OUT_RINGf(v[0]);
  63. OUT_RINGf(v[1]);
  64. OUT_RINGf(0.0);
  65. OUT_RINGf(1.0);
  66. break;
  67. case 1:
  68. OUT_RINGf(v[0]);
  69. OUT_RINGf(0.0);
  70. OUT_RINGf(0.0);
  71. OUT_RINGf(1.0);
  72. break;
  73. default:
  74. ws->buffer_unmap(ws, vb->buffer);
  75. return FALSE;
  76. }
  77. }
  78. break;
  79. default:
  80. ws->buffer_unmap(ws, vb->buffer);
  81. return FALSE;
  82. }
  83. ws->buffer_unmap(ws, vb->buffer);
  84. return TRUE;
  85. }
  86. static void
  87. nv30_vbo_arrays_update(struct nv30_context *nv30)
  88. {
  89. struct nv30_vertex_program *vp = nv30->vertprog.active;
  90. uint32_t inputs, vtxfmt[16];
  91. int hw, num_hw = 0;
  92. nv30->vb_enable = 0;
  93. inputs = vp->ir;
  94. for (hw = 0; hw < 16 && inputs; hw++) {
  95. if (inputs & (1 << hw)) {
  96. num_hw = hw;
  97. inputs &= ~(1 << hw);
  98. }
  99. }
  100. num_hw++;
  101. inputs = vp->ir;
  102. for (hw = 0; hw < num_hw; hw++) {
  103. struct pipe_vertex_element *ve;
  104. struct pipe_vertex_buffer *vb;
  105. if (!(inputs & (1 << hw))) {
  106. vtxfmt[hw] = NV34TCL_VERTEX_ARRAY_FORMAT_TYPE_FLOAT;
  107. continue;
  108. }
  109. ve = &nv30->vtxelt[hw];
  110. vb = &nv30->vtxbuf[ve->vertex_buffer_index];
  111. if (vb->pitch == 0) {
  112. vtxfmt[hw] = NV34TCL_VERTEX_ARRAY_FORMAT_TYPE_FLOAT;
  113. if (nv30_vbo_static_attrib(nv30, hw, ve, vb) == TRUE)
  114. continue;
  115. }
  116. nv30->vb_enable |= (1 << hw);
  117. nv30->vb[hw].delta = vb->buffer_offset + ve->src_offset;
  118. nv30->vb[hw].buffer = vb->buffer;
  119. vtxfmt[hw] = ((vb->pitch << NV34TCL_VERTEX_ARRAY_FORMAT_STRIDE_SHIFT) |
  120. (nv30_vbo_ncomp(ve->src_format) <<
  121. NV34TCL_VERTEX_ARRAY_FORMAT_SIZE_SHIFT) |
  122. nv30_vbo_type(ve->src_format));
  123. }
  124. BEGIN_RING(rankine, NV34TCL_VERTEX_ARRAY_FORMAT(0), num_hw);
  125. OUT_RINGp (vtxfmt, num_hw);
  126. }
  127. static boolean
  128. nv30_vbo_validate_state(struct nv30_context *nv30,
  129. struct pipe_buffer *ib, unsigned ib_format)
  130. {
  131. unsigned inputs;
  132. nv30_emit_hw_state(nv30);
  133. if (nv30->dirty & NV30_NEW_ARRAYS) {
  134. nv30_vbo_arrays_update(nv30);
  135. nv30->dirty &= ~NV30_NEW_ARRAYS;
  136. }
  137. inputs = nv30->vb_enable;
  138. while (inputs) {
  139. unsigned a = ffs(inputs) - 1;
  140. inputs &= ~(1 << a);
  141. BEGIN_RING(rankine, NV34TCL_VERTEX_BUFFER_ADDRESS(a), 1);
  142. OUT_RELOC (nv30->vb[a].buffer, nv30->vb[a].delta,
  143. NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_LOW |
  144. NOUVEAU_BO_OR | NOUVEAU_BO_RD, 0,
  145. NV34TCL_VERTEX_BUFFER_ADDRESS_DMA1);
  146. }
  147. if (ib) {
  148. BEGIN_RING(rankine, NV40TCL_IDXBUF_ADDRESS, 2);
  149. OUT_RELOCl(ib, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
  150. NOUVEAU_BO_RD);
  151. OUT_RELOCd(ib, ib_format, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
  152. NOUVEAU_BO_RD | NOUVEAU_BO_OR,
  153. 0, NV40TCL_IDXBUF_FORMAT_DMA1);
  154. }
  155. BEGIN_RING(rankine, 0x1710, 1);
  156. OUT_RING (0); /* vtx cache flush */
  157. return TRUE;
  158. }
  159. boolean
  160. nv30_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
  161. unsigned count)
  162. {
  163. struct nv30_context *nv30 = nv30_context(pipe);
  164. unsigned nr;
  165. boolean ret;
  166. ret = nv30_vbo_validate_state(nv30, NULL, 0);
  167. if (!ret) {
  168. NOUVEAU_ERR("state validate failed\n");
  169. return FALSE;
  170. }
  171. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  172. OUT_RING (nvgl_primitive(mode));
  173. nr = (count & 0xff);
  174. if (nr) {
  175. BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
  176. OUT_RING (((nr - 1) << 24) | start);
  177. start += nr;
  178. }
  179. nr = count >> 8;
  180. while (nr) {
  181. unsigned push = nr > 2047 ? 2047 : nr;
  182. nr -= push;
  183. BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
  184. while (push--) {
  185. OUT_RING(((0x100 - 1) << 24) | start);
  186. start += 0x100;
  187. }
  188. }
  189. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  190. OUT_RING (0);
  191. pipe->flush(pipe, 0);
  192. return TRUE;
  193. }
  194. static INLINE void
  195. nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
  196. unsigned start, unsigned count)
  197. {
  198. uint8_t *elts = (uint8_t *)ib + start;
  199. int push, i;
  200. if (count & 1) {
  201. BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
  202. OUT_RING (elts[0]);
  203. elts++; count--;
  204. }
  205. while (count) {
  206. push = MIN2(count, 2047 * 2);
  207. BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
  208. for (i = 0; i < push; i+=2)
  209. OUT_RING((elts[i+1] << 16) | elts[i]);
  210. count -= push;
  211. elts += push;
  212. }
  213. }
  214. static INLINE void
  215. nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
  216. unsigned start, unsigned count)
  217. {
  218. uint16_t *elts = (uint16_t *)ib + start;
  219. int push, i;
  220. if (count & 1) {
  221. BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
  222. OUT_RING (elts[0]);
  223. elts++; count--;
  224. }
  225. while (count) {
  226. push = MIN2(count, 2047 * 2);
  227. BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
  228. for (i = 0; i < push; i+=2)
  229. OUT_RING((elts[i+1] << 16) | elts[i]);
  230. count -= push;
  231. elts += push;
  232. }
  233. }
  234. static INLINE void
  235. nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
  236. unsigned start, unsigned count)
  237. {
  238. uint32_t *elts = (uint32_t *)ib + start;
  239. int push;
  240. while (count) {
  241. push = MIN2(count, 2047);
  242. BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
  243. OUT_RINGp (elts, push);
  244. count -= push;
  245. elts += push;
  246. }
  247. }
  248. static boolean
  249. nv30_draw_elements_inline(struct pipe_context *pipe,
  250. struct pipe_buffer *ib, unsigned ib_size,
  251. unsigned mode, unsigned start, unsigned count)
  252. {
  253. struct nv30_context *nv30 = nv30_context(pipe);
  254. struct pipe_winsys *ws = pipe->winsys;
  255. boolean ret;
  256. void *map;
  257. ret = nv30_vbo_validate_state(nv30, NULL, 0);
  258. if (!ret) {
  259. NOUVEAU_ERR("state validate failed\n");
  260. return FALSE;
  261. }
  262. map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
  263. if (!ib) {
  264. NOUVEAU_ERR("failed mapping ib\n");
  265. return FALSE;
  266. }
  267. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  268. OUT_RING (nvgl_primitive(mode));
  269. switch (ib_size) {
  270. case 1:
  271. nv30_draw_elements_u08(nv30, map, start, count);
  272. break;
  273. case 2:
  274. nv30_draw_elements_u16(nv30, map, start, count);
  275. break;
  276. case 4:
  277. nv30_draw_elements_u32(nv30, map, start, count);
  278. break;
  279. default:
  280. NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
  281. break;
  282. }
  283. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  284. OUT_RING (0);
  285. ws->buffer_unmap(ws, ib);
  286. return TRUE;
  287. }
  288. static boolean
  289. nv30_draw_elements_vbo(struct pipe_context *pipe,
  290. struct pipe_buffer *ib, unsigned ib_size,
  291. unsigned mode, unsigned start, unsigned count)
  292. {
  293. struct nv30_context *nv30 = nv30_context(pipe);
  294. unsigned nr, type;
  295. boolean ret;
  296. switch (ib_size) {
  297. case 2:
  298. type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
  299. break;
  300. case 4:
  301. type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
  302. break;
  303. default:
  304. NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
  305. return FALSE;
  306. }
  307. ret = nv30_vbo_validate_state(nv30, ib, type);
  308. if (!ret) {
  309. NOUVEAU_ERR("failed state validation\n");
  310. return FALSE;
  311. }
  312. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  313. OUT_RING (nvgl_primitive(mode));
  314. nr = (count & 0xff);
  315. if (nr) {
  316. BEGIN_RING(rankine, NV40TCL_VB_INDEX_BATCH, 1);
  317. OUT_RING (((nr - 1) << 24) | start);
  318. start += nr;
  319. }
  320. nr = count >> 8;
  321. while (nr) {
  322. unsigned push = nr > 2047 ? 2047 : nr;
  323. nr -= push;
  324. BEGIN_RING_NI(rankine, NV40TCL_VB_INDEX_BATCH, push);
  325. while (push--) {
  326. OUT_RING(((0x100 - 1) << 24) | start);
  327. start += 0x100;
  328. }
  329. }
  330. BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
  331. OUT_RING (0);
  332. return TRUE;
  333. }
  334. boolean
  335. nv30_draw_elements(struct pipe_context *pipe,
  336. struct pipe_buffer *indexBuffer, unsigned indexSize,
  337. unsigned mode, unsigned start, unsigned count)
  338. {
  339. /* if (indexSize != 1) {
  340. nv30_draw_elements_vbo(pipe, indexBuffer, indexSize,
  341. mode, start, count);
  342. } else */{
  343. nv30_draw_elements_inline(pipe, indexBuffer, indexSize,
  344. mode, start, count);
  345. }
  346. pipe->flush(pipe, 0);
  347. return TRUE;
  348. }