Clone of mesa.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

nv50_transfer.c 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include "pipe/p_context.h"
  2. #include "util/u_inlines.h"
  3. #include "util/u_format.h"
  4. #include "util/u_math.h"
  5. #include "nv50_context.h"
  6. struct nv50_transfer {
  7. struct pipe_transfer base;
  8. struct nouveau_bo *bo;
  9. unsigned level_offset;
  10. unsigned level_tiling;
  11. int level_pitch;
  12. int level_width;
  13. int level_height;
  14. int level_depth;
  15. int level_x;
  16. int level_y;
  17. int level_z;
  18. unsigned nblocksx;
  19. unsigned nblocksy;
  20. };
  21. static void
  22. nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
  23. struct nouveau_bo *src_bo, unsigned src_offset,
  24. int src_pitch, unsigned src_tile_mode,
  25. int sx, int sy, int sz, int sw, int sh, int sd,
  26. struct nouveau_bo *dst_bo, unsigned dst_offset,
  27. int dst_pitch, unsigned dst_tile_mode,
  28. int dx, int dy, int dz, int dw, int dh, int dd,
  29. int cpp, int width, int height,
  30. unsigned src_reloc, unsigned dst_reloc)
  31. {
  32. struct nv50_screen *screen = nv50_screen(pscreen);
  33. struct nouveau_channel *chan = screen->m2mf->channel;
  34. struct nouveau_grobj *m2mf = screen->m2mf;
  35. src_reloc |= NOUVEAU_BO_RD;
  36. dst_reloc |= NOUVEAU_BO_WR;
  37. WAIT_RING (chan, 14);
  38. if (!src_bo->tile_flags) {
  39. BEGIN_RING(chan, m2mf,
  40. NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
  41. OUT_RING (chan, 1);
  42. BEGIN_RING(chan, m2mf,
  43. NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN, 1);
  44. OUT_RING (chan, src_pitch);
  45. src_offset += (sy * src_pitch) + (sx * cpp);
  46. } else {
  47. BEGIN_RING(chan, m2mf,
  48. NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 6);
  49. OUT_RING (chan, 0);
  50. OUT_RING (chan, src_tile_mode << 4);
  51. OUT_RING (chan, sw * cpp);
  52. OUT_RING (chan, sh);
  53. OUT_RING (chan, sd);
  54. OUT_RING (chan, sz); /* copying only 1 zslice per call */
  55. }
  56. if (!dst_bo->tile_flags) {
  57. BEGIN_RING(chan, m2mf,
  58. NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1);
  59. OUT_RING (chan, 1);
  60. BEGIN_RING(chan, m2mf,
  61. NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT, 1);
  62. OUT_RING (chan, dst_pitch);
  63. dst_offset += (dy * dst_pitch) + (dx * cpp);
  64. } else {
  65. BEGIN_RING(chan, m2mf,
  66. NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 6);
  67. OUT_RING (chan, 0);
  68. OUT_RING (chan, dst_tile_mode << 4);
  69. OUT_RING (chan, dw * cpp);
  70. OUT_RING (chan, dh);
  71. OUT_RING (chan, dd);
  72. OUT_RING (chan, dz); /* copying only 1 zslice per call */
  73. }
  74. while (height) {
  75. int line_count = height > 2047 ? 2047 : height;
  76. MARK_RING (chan, 15, 4); /* flush on lack of space or relocs */
  77. BEGIN_RING(chan, m2mf,
  78. NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
  79. OUT_RELOCh(chan, src_bo, src_offset, src_reloc);
  80. OUT_RELOCh(chan, dst_bo, dst_offset, dst_reloc);
  81. BEGIN_RING(chan, m2mf,
  82. NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 2);
  83. OUT_RELOCl(chan, src_bo, src_offset, src_reloc);
  84. OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc);
  85. if (src_bo->tile_flags) {
  86. BEGIN_RING(chan, m2mf,
  87. NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN, 1);
  88. OUT_RING (chan, (sy << 16) | (sx * cpp));
  89. } else {
  90. src_offset += (line_count * src_pitch);
  91. }
  92. if (dst_bo->tile_flags) {
  93. BEGIN_RING(chan, m2mf,
  94. NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT, 1);
  95. OUT_RING (chan, (dy << 16) | (dx * cpp));
  96. } else {
  97. dst_offset += (line_count * dst_pitch);
  98. }
  99. BEGIN_RING(chan, m2mf,
  100. NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN, 4);
  101. OUT_RING (chan, width * cpp);
  102. OUT_RING (chan, line_count);
  103. OUT_RING (chan, 0x00000101);
  104. OUT_RING (chan, 0);
  105. FIRE_RING (chan);
  106. height -= line_count;
  107. sy += line_count;
  108. dy += line_count;
  109. }
  110. }
  111. static struct pipe_transfer *
  112. nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt,
  113. unsigned face, unsigned level, unsigned zslice,
  114. enum pipe_transfer_usage usage,
  115. unsigned x, unsigned y, unsigned w, unsigned h)
  116. {
  117. struct pipe_screen *pscreen = pcontext->screen;
  118. struct nouveau_device *dev = nouveau_screen(pscreen)->device;
  119. struct nv50_miptree *mt = nv50_miptree(pt);
  120. struct nv50_miptree_level *lvl = &mt->level[level];
  121. struct nv50_transfer *tx;
  122. unsigned nx, ny, image = 0;
  123. int ret;
  124. if (pt->target == PIPE_TEXTURE_CUBE)
  125. image = face;
  126. tx = CALLOC_STRUCT(nv50_transfer);
  127. if (!tx)
  128. return NULL;
  129. pipe_texture_reference(&tx->base.texture, pt);
  130. tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, level));
  131. tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, level));
  132. tx->base.width = w;
  133. tx->base.height = h;
  134. tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format);
  135. tx->base.usage = usage;
  136. tx->level_pitch = lvl->pitch;
  137. tx->level_width = u_minify(mt->base.base.width0, level);
  138. tx->level_height = u_minify(mt->base.base.height0, level);
  139. tx->level_depth = u_minify(mt->base.base.depth0, level);
  140. tx->level_offset = lvl->image_offset[image];
  141. tx->level_tiling = lvl->tile_mode;
  142. tx->level_z = zslice;
  143. tx->level_x = util_format_get_nblocksx(pt->format, x);
  144. tx->level_y = util_format_get_nblocksy(pt->format, y);
  145. ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
  146. tx->nblocksy * tx->base.stride, &tx->bo);
  147. if (ret) {
  148. FREE(tx);
  149. return NULL;
  150. }
  151. if (usage & PIPE_TRANSFER_READ) {
  152. nx = util_format_get_nblocksx(pt->format, tx->base.width);
  153. ny = util_format_get_nblocksy(pt->format, tx->base.height);
  154. nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
  155. tx->level_pitch, tx->level_tiling,
  156. x, y, zslice,
  157. tx->nblocksx, tx->nblocksy,
  158. tx->level_depth,
  159. tx->bo, 0,
  160. tx->base.stride, tx->bo->tile_mode,
  161. 0, 0, 0,
  162. tx->nblocksx, tx->nblocksy, 1,
  163. util_format_get_blocksize(pt->format), nx, ny,
  164. NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
  165. NOUVEAU_BO_GART);
  166. }
  167. return &tx->base;
  168. }
  169. static void
  170. nv50_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx)
  171. {
  172. struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
  173. struct nv50_miptree *mt = nv50_miptree(ptx->texture);
  174. struct pipe_texture *pt = ptx->texture;
  175. unsigned nx = util_format_get_nblocksx(pt->format, tx->base.width);
  176. unsigned ny = util_format_get_nblocksy(pt->format, tx->base.height);
  177. if (ptx->usage & PIPE_TRANSFER_WRITE) {
  178. struct pipe_screen *pscreen = pcontext->screen;
  179. nv50_transfer_rect_m2mf(pscreen, tx->bo, 0,
  180. tx->base.stride, tx->bo->tile_mode,
  181. 0, 0, 0,
  182. tx->nblocksx, tx->nblocksy, 1,
  183. mt->base.bo, tx->level_offset,
  184. tx->level_pitch, tx->level_tiling,
  185. tx->level_x, tx->level_y, tx->level_z,
  186. tx->nblocksx, tx->nblocksy,
  187. tx->level_depth,
  188. util_format_get_blocksize(pt->format), nx, ny,
  189. NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
  190. NOUVEAU_BO_GART);
  191. }
  192. nouveau_bo_ref(NULL, &tx->bo);
  193. pipe_texture_reference(&ptx->texture, NULL);
  194. FREE(ptx);
  195. }
  196. static void *
  197. nv50_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx)
  198. {
  199. struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
  200. unsigned flags = 0;
  201. int ret;
  202. if (ptx->usage & PIPE_TRANSFER_WRITE)
  203. flags |= NOUVEAU_BO_WR;
  204. if (ptx->usage & PIPE_TRANSFER_READ)
  205. flags |= NOUVEAU_BO_RD;
  206. ret = nouveau_bo_map(tx->bo, flags);
  207. if (ret)
  208. return NULL;
  209. return tx->bo->map;
  210. }
  211. static void
  212. nv50_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx)
  213. {
  214. struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
  215. nouveau_bo_unmap(tx->bo);
  216. }
  217. void
  218. nv50_init_transfer_functions(struct nv50_context *nv50)
  219. {
  220. nv50->pipe.get_tex_transfer = nv50_transfer_new;
  221. nv50->pipe.tex_transfer_destroy = nv50_transfer_del;
  222. nv50->pipe.transfer_map = nv50_transfer_map;
  223. nv50->pipe.transfer_unmap = nv50_transfer_unmap;
  224. }
  225. void
  226. nv50_upload_sifc(struct nv50_context *nv50,
  227. struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc,
  228. unsigned dst_format, int dst_w, int dst_h, int dst_pitch,
  229. void *src, unsigned src_format, int src_pitch,
  230. int x, int y, int w, int h, int cpp)
  231. {
  232. struct nouveau_channel *chan = nv50->screen->base.channel;
  233. struct nouveau_grobj *eng2d = nv50->screen->eng2d;
  234. struct nouveau_grobj *tesla = nv50->screen->tesla;
  235. unsigned line_dwords = (w * cpp + 3) / 4;
  236. reloc |= NOUVEAU_BO_WR;
  237. MARK_RING (chan, 32, 2); /* flush on lack of space or relocs */
  238. if (bo->tile_flags) {
  239. BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5);
  240. OUT_RING (chan, dst_format);
  241. OUT_RING (chan, 0);
  242. OUT_RING (chan, bo->tile_mode << 4);
  243. OUT_RING (chan, 1);
  244. OUT_RING (chan, 0);
  245. } else {
  246. BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2);
  247. OUT_RING (chan, dst_format);
  248. OUT_RING (chan, 1);
  249. BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 1);
  250. OUT_RING (chan, dst_pitch);
  251. }
  252. BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 4);
  253. OUT_RING (chan, dst_w);
  254. OUT_RING (chan, dst_h);
  255. OUT_RELOCh(chan, bo, dst_offset, reloc);
  256. OUT_RELOCl(chan, bo, dst_offset, reloc);
  257. /* NV50_2D_OPERATION_SRCCOPY assumed already set */
  258. BEGIN_RING(chan, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2);
  259. OUT_RING (chan, 0);
  260. OUT_RING (chan, src_format);
  261. BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10);
  262. OUT_RING (chan, w);
  263. OUT_RING (chan, h);
  264. OUT_RING (chan, 0);
  265. OUT_RING (chan, 1);
  266. OUT_RING (chan, 0);
  267. OUT_RING (chan, 1);
  268. OUT_RING (chan, 0);
  269. OUT_RING (chan, x);
  270. OUT_RING (chan, 0);
  271. OUT_RING (chan, y);
  272. while (h--) {
  273. const uint32_t *p = src;
  274. unsigned count = line_dwords;
  275. while (count) {
  276. unsigned nr = MIN2(count, 1792);
  277. if (AVAIL_RING(chan) <= nr) {
  278. FIRE_RING (chan);
  279. BEGIN_RING(chan, eng2d,
  280. NV50_2D_DST_ADDRESS_HIGH, 2);
  281. OUT_RELOCh(chan, bo, dst_offset, reloc);
  282. OUT_RELOCl(chan, bo, dst_offset, reloc);
  283. }
  284. assert(AVAIL_RING(chan) > nr);
  285. BEGIN_RING(chan, eng2d,
  286. NV50_2D_SIFC_DATA | (2 << 29), nr);
  287. OUT_RINGp (chan, p, nr);
  288. p += nr;
  289. count -= nr;
  290. }
  291. src += src_pitch;
  292. }
  293. BEGIN_RING(chan, tesla, NV50TCL_CODE_CB_FLUSH, 1);
  294. OUT_RING (chan, 0);
  295. }