radeon_bo_gem.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright © 2008 Dave Airlie
  3. * Copyright © 2008 Jérôme Glisse
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
  18. * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. * The above copyright notice and this permission notice (including the
  24. * next paragraph) shall be included in all copies or substantial portions
  25. * of the Software.
  26. */
  27. /*
  28. * Authors:
  29. * Dave Airlie
  30. * Jérôme Glisse <glisse@freedesktop.org>
  31. */
  32. #include <stdio.h>
  33. #include <stdint.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <errno.h>
  37. #include "libdrm_macros.h"
  38. #include "xf86drm.h"
  39. #include "xf86atomic.h"
  40. #include "drm.h"
  41. #include "radeon_drm.h"
  42. #include "radeon_bo.h"
  43. #include "radeon_bo_int.h"
  44. #include "radeon_bo_gem.h"
  45. #include <fcntl.h>
  46. struct radeon_bo_gem {
  47. struct radeon_bo_int base;
  48. uint32_t name;
  49. int map_count;
  50. atomic_t reloc_in_cs;
  51. void *priv_ptr;
  52. };
  53. struct bo_manager_gem {
  54. struct radeon_bo_manager base;
  55. };
  56. static int bo_wait(struct radeon_bo_int *boi);
  57. static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
  58. uint32_t handle,
  59. uint32_t size,
  60. uint32_t alignment,
  61. uint32_t domains,
  62. uint32_t flags)
  63. {
  64. struct radeon_bo_gem *bo;
  65. int r;
  66. bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
  67. if (bo == NULL) {
  68. return NULL;
  69. }
  70. bo->base.bom = bom;
  71. bo->base.handle = 0;
  72. bo->base.size = size;
  73. bo->base.alignment = alignment;
  74. bo->base.domains = domains;
  75. bo->base.flags = flags;
  76. bo->base.ptr = NULL;
  77. atomic_set(&bo->reloc_in_cs, 0);
  78. bo->map_count = 0;
  79. if (handle) {
  80. struct drm_gem_open open_arg;
  81. memset(&open_arg, 0, sizeof(open_arg));
  82. open_arg.name = handle;
  83. r = drmIoctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
  84. if (r != 0) {
  85. free(bo);
  86. return NULL;
  87. }
  88. bo->base.handle = open_arg.handle;
  89. bo->base.size = open_arg.size;
  90. bo->name = handle;
  91. } else {
  92. struct drm_radeon_gem_create args;
  93. args.size = size;
  94. args.alignment = alignment;
  95. args.initial_domain = bo->base.domains;
  96. args.flags = flags;
  97. args.handle = 0;
  98. r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
  99. &args, sizeof(args));
  100. bo->base.handle = args.handle;
  101. if (r) {
  102. fprintf(stderr, "Failed to allocate :\n");
  103. fprintf(stderr, " size : %d bytes\n", size);
  104. fprintf(stderr, " alignment : %d bytes\n", alignment);
  105. fprintf(stderr, " domains : %d\n", bo->base.domains);
  106. free(bo);
  107. return NULL;
  108. }
  109. }
  110. radeon_bo_ref((struct radeon_bo*)bo);
  111. return (struct radeon_bo*)bo;
  112. }
  113. static void bo_ref(struct radeon_bo_int *boi)
  114. {
  115. }
  116. static struct radeon_bo *bo_unref(struct radeon_bo_int *boi)
  117. {
  118. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
  119. if (boi->cref) {
  120. return (struct radeon_bo *)boi;
  121. }
  122. if (bo_gem->priv_ptr) {
  123. drm_munmap(bo_gem->priv_ptr, boi->size);
  124. }
  125. /* close object */
  126. drmCloseBufferHandle(boi->bom->fd, boi->handle);
  127. memset(bo_gem, 0, sizeof(struct radeon_bo_gem));
  128. free(bo_gem);
  129. return NULL;
  130. }
  131. static int bo_map(struct radeon_bo_int *boi, int write)
  132. {
  133. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
  134. struct drm_radeon_gem_mmap args;
  135. int r;
  136. void *ptr;
  137. if (bo_gem->map_count++ != 0) {
  138. return 0;
  139. }
  140. if (bo_gem->priv_ptr) {
  141. goto wait;
  142. }
  143. boi->ptr = NULL;
  144. /* Zero out args to make valgrind happy */
  145. memset(&args, 0, sizeof(args));
  146. args.handle = boi->handle;
  147. args.offset = 0;
  148. args.size = (uint64_t)boi->size;
  149. r = drmCommandWriteRead(boi->bom->fd,
  150. DRM_RADEON_GEM_MMAP,
  151. &args,
  152. sizeof(args));
  153. if (r) {
  154. fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
  155. boi, boi->handle, r);
  156. return r;
  157. }
  158. ptr = drm_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, boi->bom->fd, args.addr_ptr);
  159. if (ptr == MAP_FAILED)
  160. return -errno;
  161. bo_gem->priv_ptr = ptr;
  162. wait:
  163. boi->ptr = bo_gem->priv_ptr;
  164. r = bo_wait(boi);
  165. if (r)
  166. return r;
  167. return 0;
  168. }
  169. static int bo_unmap(struct radeon_bo_int *boi)
  170. {
  171. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
  172. if (--bo_gem->map_count > 0) {
  173. return 0;
  174. }
  175. //drm_munmap(bo->ptr, bo->size);
  176. boi->ptr = NULL;
  177. return 0;
  178. }
  179. static int bo_wait(struct radeon_bo_int *boi)
  180. {
  181. struct drm_radeon_gem_wait_idle args;
  182. int ret;
  183. /* Zero out args to make valgrind happy */
  184. memset(&args, 0, sizeof(args));
  185. args.handle = boi->handle;
  186. do {
  187. ret = drmCommandWrite(boi->bom->fd, DRM_RADEON_GEM_WAIT_IDLE,
  188. &args, sizeof(args));
  189. } while (ret == -EBUSY);
  190. return ret;
  191. }
  192. static int bo_is_busy(struct radeon_bo_int *boi, uint32_t *domain)
  193. {
  194. struct drm_radeon_gem_busy args;
  195. int ret;
  196. args.handle = boi->handle;
  197. args.domain = 0;
  198. ret = drmCommandWriteRead(boi->bom->fd, DRM_RADEON_GEM_BUSY,
  199. &args, sizeof(args));
  200. *domain = args.domain;
  201. return ret;
  202. }
  203. static int bo_set_tiling(struct radeon_bo_int *boi, uint32_t tiling_flags,
  204. uint32_t pitch)
  205. {
  206. struct drm_radeon_gem_set_tiling args;
  207. int r;
  208. args.handle = boi->handle;
  209. args.tiling_flags = tiling_flags;
  210. args.pitch = pitch;
  211. r = drmCommandWriteRead(boi->bom->fd,
  212. DRM_RADEON_GEM_SET_TILING,
  213. &args,
  214. sizeof(args));
  215. return r;
  216. }
  217. static int bo_get_tiling(struct radeon_bo_int *boi, uint32_t *tiling_flags,
  218. uint32_t *pitch)
  219. {
  220. struct drm_radeon_gem_set_tiling args = {};
  221. int r;
  222. args.handle = boi->handle;
  223. r = drmCommandWriteRead(boi->bom->fd,
  224. DRM_RADEON_GEM_GET_TILING,
  225. &args,
  226. sizeof(args));
  227. if (r)
  228. return r;
  229. *tiling_flags = args.tiling_flags;
  230. *pitch = args.pitch;
  231. return r;
  232. }
  233. static const struct radeon_bo_funcs bo_gem_funcs = {
  234. .bo_open = bo_open,
  235. .bo_ref = bo_ref,
  236. .bo_unref = bo_unref,
  237. .bo_map = bo_map,
  238. .bo_unmap = bo_unmap,
  239. .bo_wait = bo_wait,
  240. .bo_is_static = NULL,
  241. .bo_set_tiling = bo_set_tiling,
  242. .bo_get_tiling = bo_get_tiling,
  243. .bo_is_busy = bo_is_busy,
  244. .bo_is_referenced_by_cs = NULL,
  245. };
  246. drm_public struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
  247. {
  248. struct bo_manager_gem *bomg;
  249. bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
  250. if (bomg == NULL) {
  251. return NULL;
  252. }
  253. bomg->base.funcs = &bo_gem_funcs;
  254. bomg->base.fd = fd;
  255. return (struct radeon_bo_manager*)bomg;
  256. }
  257. drm_public void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
  258. {
  259. struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
  260. if (bom == NULL) {
  261. return;
  262. }
  263. free(bomg);
  264. }
  265. drm_public uint32_t
  266. radeon_gem_name_bo(struct radeon_bo *bo)
  267. {
  268. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
  269. return bo_gem->name;
  270. }
  271. drm_public void *
  272. radeon_gem_get_reloc_in_cs(struct radeon_bo *bo)
  273. {
  274. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
  275. return &bo_gem->reloc_in_cs;
  276. }
  277. drm_public int
  278. radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
  279. {
  280. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
  281. struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
  282. struct drm_gem_flink flink;
  283. int r;
  284. if (bo_gem->name) {
  285. *name = bo_gem->name;
  286. return 0;
  287. }
  288. flink.handle = bo->handle;
  289. r = drmIoctl(boi->bom->fd, DRM_IOCTL_GEM_FLINK, &flink);
  290. if (r) {
  291. return r;
  292. }
  293. bo_gem->name = flink.name;
  294. *name = flink.name;
  295. return 0;
  296. }
  297. drm_public int
  298. radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
  299. {
  300. struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
  301. struct drm_radeon_gem_set_domain args;
  302. int r;
  303. args.handle = bo->handle;
  304. args.read_domains = read_domains;
  305. args.write_domain = write_domain;
  306. r = drmCommandWriteRead(boi->bom->fd,
  307. DRM_RADEON_GEM_SET_DOMAIN,
  308. &args,
  309. sizeof(args));
  310. return r;
  311. }
  312. drm_public int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle)
  313. {
  314. struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
  315. int ret;
  316. ret = drmPrimeHandleToFD(bo_gem->base.bom->fd, bo->handle, DRM_CLOEXEC, handle);
  317. return ret;
  318. }
  319. drm_public struct radeon_bo *
  320. radeon_gem_bo_open_prime(struct radeon_bo_manager *bom, int fd_handle, uint32_t size)
  321. {
  322. struct radeon_bo_gem *bo;
  323. int r;
  324. uint32_t handle;
  325. bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
  326. if (bo == NULL) {
  327. return NULL;
  328. }
  329. bo->base.bom = bom;
  330. bo->base.handle = 0;
  331. bo->base.size = size;
  332. bo->base.alignment = 0;
  333. bo->base.domains = RADEON_GEM_DOMAIN_GTT;
  334. bo->base.flags = 0;
  335. bo->base.ptr = NULL;
  336. atomic_set(&bo->reloc_in_cs, 0);
  337. bo->map_count = 0;
  338. r = drmPrimeFDToHandle(bom->fd, fd_handle, &handle);
  339. if (r != 0) {
  340. free(bo);
  341. return NULL;
  342. }
  343. bo->base.handle = handle;
  344. bo->name = handle;
  345. radeon_bo_ref((struct radeon_bo *)bo);
  346. return (struct radeon_bo *)bo;
  347. }