rbo.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright © 2011 Red Hat
  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 (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. *
  23. * Authors:
  24. * Jerome Glisse <j.glisse@gmail.com>
  25. */
  26. #define _FILE_OFFSET_BITS 64
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/mman.h>
  31. #include <errno.h>
  32. #include "xf86drm.h"
  33. #include "radeon_drm.h"
  34. #include "rbo.h"
  35. struct rbo *rbo(int fd, unsigned handle, unsigned size,
  36. unsigned alignment, void *ptr)
  37. {
  38. struct rbo *bo;
  39. int r;
  40. bo = calloc(1, sizeof(*bo));
  41. if (bo == NULL) {
  42. return NULL;
  43. }
  44. list_inithead(&bo->list);
  45. bo->fd = fd;
  46. bo->size = size;
  47. bo->handle = handle;
  48. bo->refcount = 1;
  49. bo->alignment = alignment;
  50. if (handle) {
  51. struct drm_gem_open open_arg;
  52. memset(&open_arg, 0, sizeof(open_arg));
  53. open_arg.name = handle;
  54. r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg);
  55. if (r != 0) {
  56. free(bo);
  57. return NULL;
  58. }
  59. bo->handle = open_arg.handle;
  60. } else {
  61. struct drm_radeon_gem_create args;
  62. args.size = size;
  63. args.alignment = alignment;
  64. args.initial_domain = RADEON_GEM_DOMAIN_CPU;
  65. args.flags = 0;
  66. args.handle = 0;
  67. r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE,
  68. &args, sizeof(args));
  69. bo->handle = args.handle;
  70. if (r) {
  71. fprintf(stderr, "Failed to allocate :\n");
  72. fprintf(stderr, " size : %d bytes\n", size);
  73. fprintf(stderr, " alignment : %d bytes\n", alignment);
  74. free(bo);
  75. return NULL;
  76. }
  77. }
  78. if (ptr) {
  79. if (rbo_map(bo)) {
  80. fprintf(stderr, "%s failed to copy data into bo\n", __func__);
  81. return rbo_decref(bo);
  82. }
  83. memcpy(bo->data, ptr, size);
  84. rbo_unmap(bo);
  85. }
  86. return bo;
  87. }
  88. int rbo_map(struct rbo *bo)
  89. {
  90. struct drm_radeon_gem_mmap args;
  91. void *ptr;
  92. int r;
  93. if (bo->mapcount++ != 0) {
  94. return 0;
  95. }
  96. /* Zero out args to make valgrind happy */
  97. memset(&args, 0, sizeof(args));
  98. args.handle = bo->handle;
  99. args.offset = 0;
  100. args.size = (uint64_t)bo->size;
  101. r = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_MMAP,
  102. &args, sizeof(args));
  103. if (r) {
  104. fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
  105. bo, bo->handle, r);
  106. return r;
  107. }
  108. ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->fd, args.addr_ptr);
  109. if (ptr == MAP_FAILED) {
  110. fprintf(stderr, "%s failed to map bo\n", __func__);
  111. return -errno;
  112. }
  113. bo->data = ptr;
  114. return 0;
  115. }
  116. void rbo_unmap(struct rbo *bo)
  117. {
  118. if (--bo->mapcount > 0) {
  119. return;
  120. }
  121. munmap(bo->data, bo->size);
  122. bo->data = NULL;
  123. }
  124. struct rbo *rbo_incref(struct rbo *bo)
  125. {
  126. bo->refcount++;
  127. return bo;
  128. }
  129. struct rbo *rbo_decref(struct rbo *bo)
  130. {
  131. struct drm_gem_close args;
  132. if (bo == NULL)
  133. return NULL;
  134. if (--bo->refcount > 0) {
  135. return NULL;
  136. }
  137. munmap(bo->data, bo->size);
  138. memset(&args, 0, sizeof(args));
  139. args.handle = bo->handle;
  140. drmIoctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &args);
  141. memset(bo, 0, sizeof(struct rbo));
  142. free(bo);
  143. return NULL;
  144. }
  145. int rbo_wait(struct rbo *bo)
  146. {
  147. struct drm_radeon_gem_wait_idle args;
  148. int ret;
  149. /* Zero out args to make valgrind happy */
  150. memset(&args, 0, sizeof(args));
  151. args.handle = bo->handle;
  152. do {
  153. ret = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_WAIT_IDLE,
  154. &args, sizeof(args));
  155. } while (ret == -EBUSY);
  156. return ret;
  157. }