drm-memory.7.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. ==========
  2. drm-memory
  3. ==========
  4. ---------------------
  5. DRM Memory Management
  6. ---------------------
  7. :Date: September 2012
  8. :Manual section: 7
  9. :Manual group: Direct Rendering Manager
  10. Synopsis
  11. ========
  12. ``#include <xf86drm.h>``
  13. Description
  14. ===========
  15. Many modern high-end GPUs come with their own memory managers. They even
  16. include several different caches that need to be synchronized during access.
  17. Textures, framebuffers, command buffers and more need to be stored in memory
  18. that can be accessed quickly by the GPU. Therefore, memory management on GPUs
  19. is highly driver- and hardware-dependent.
  20. However, there are several frameworks in the kernel that are used by more than
  21. one driver. These can be used for trivial mode-setting without requiring
  22. driver-dependent code. But for hardware-accelerated rendering you need to read
  23. the manual pages for the driver you want to work with.
  24. Dumb-Buffers
  25. ------------
  26. Almost all in-kernel DRM hardware drivers support an API called *Dumb-Buffers*.
  27. This API allows to create buffers of arbitrary size that can be used for
  28. scanout. These buffers can be memory mapped via **mmap**\ (2) so you can render
  29. into them on the CPU. However, GPU access to these buffers is often not
  30. possible. Therefore, they are fine for simple tasks but not suitable for
  31. complex compositions and renderings.
  32. The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl can be used to create a dumb buffer.
  33. The kernel will return a 32-bit handle that can be used to manage the buffer
  34. with the DRM API. You can create framebuffers with **drmModeAddFB**\ (3) and
  35. use it for mode-setting and scanout. To access the buffer, you first need to
  36. retrieve the offset of the buffer. The ``DRM_IOCTL_MODE_MAP_DUMB`` ioctl
  37. requests the DRM subsystem to prepare the buffer for memory-mapping and returns
  38. a fake-offset that can be used with **mmap**\ (2).
  39. The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl takes as argument a structure of type
  40. ``struct drm_mode_create_dumb``:
  41. ::
  42. struct drm_mode_create_dumb {
  43. __u32 height;
  44. __u32 width;
  45. __u32 bpp;
  46. __u32 flags;
  47. __u32 handle;
  48. __u32 pitch;
  49. __u64 size;
  50. };
  51. The fields *height*, *width*, *bpp* and *flags* have to be provided by the
  52. caller. The other fields are filled by the kernel with the return values.
  53. *height* and *width* are the dimensions of the rectangular buffer that is
  54. created. *bpp* is the number of bits-per-pixel and must be a multiple of 8. You
  55. most commonly want to pass 32 here. The flags field is currently unused and
  56. must be zeroed. Different flags to modify the behavior may be added in the
  57. future. After calling the ioctl, the handle, pitch and size fields are filled
  58. by the kernel. *handle* is a 32-bit gem handle that identifies the buffer. This
  59. is used by several other calls that take a gem-handle or memory-buffer as
  60. argument. The *pitch* field is the pitch (or stride) of the new buffer. Most
  61. drivers use 32-bit or 64-bit aligned stride-values. The size field contains the
  62. absolute size in bytes of the buffer. This can normally also be computed with
  63. ``(height * pitch + width) * bpp / 4``.
  64. To prepare the buffer for **mmap**\ (2) you need to use the
  65. ``DRM_IOCTL_MODE_MAP_DUMB`` ioctl. It takes as argument a structure of type
  66. ``struct drm_mode_map_dumb``:
  67. ::
  68. struct drm_mode_map_dumb {
  69. __u32 handle;
  70. __u32 pad;
  71. __u64 offset;
  72. };
  73. You need to put the gem-handle that was previously retrieved via
  74. ``DRM_IOCTL_MODE_CREATE_DUMB`` into the *handle* field. The *pad* field is
  75. unused padding and must be zeroed. After completion, the *offset* field will
  76. contain an offset that can be used with **mmap**\ (2) on the DRM
  77. file-descriptor.
  78. If you don't need your dumb-buffer, anymore, you have to destroy it with
  79. ``DRM_IOCTL_MODE_DESTROY_DUMB``. If you close the DRM file-descriptor, all open
  80. dumb-buffers are automatically destroyed. This ioctl takes as argument a
  81. structure of type ``struct drm_mode_destroy_dumb``:
  82. ::
  83. struct drm_mode_destroy_dumb {
  84. __u32 handle;
  85. };
  86. You only need to put your handle into the *handle* field. After this call, the
  87. handle is invalid and may be reused for new buffers by the dumb-API.
  88. TTM
  89. ---
  90. *TTM* stands for *Translation Table Manager* and is a generic memory-manager
  91. provided by the kernel. It does not provide a common user-space API so you need
  92. to look at each driver interface if you want to use it. See for instance the
  93. radeon man pages for more information on memory-management with radeon and TTM.
  94. GEM
  95. ---
  96. *GEM* stands for *Graphics Execution Manager* and is a generic DRM
  97. memory-management framework in the kernel, that is used by many different
  98. drivers. GEM is designed to manage graphics memory, control access to the
  99. graphics device execution context and handle essentially NUMA environment
  100. unique to modern graphics hardware. GEM allows multiple applications to share
  101. graphics device resources without the need to constantly reload the entire
  102. graphics card. Data may be shared between multiple applications with gem
  103. ensuring that the correct memory synchronization occurs.
  104. GEM provides simple mechanisms to manage graphics data and control execution
  105. flow within the linux DRM subsystem. However, GEM is not a complete framework
  106. that is fully driver independent. Instead, if provides many functions that are
  107. shared between many drivers, but each driver has to implement most of
  108. memory-management with driver-dependent ioctls. This manpage tries to describe
  109. the semantics (and if it applies, the syntax) that is shared between all
  110. drivers that use GEM.
  111. All GEM APIs are defined as **ioctl**\ (2) on the DRM file descriptor. An
  112. application must be authorized via **drmAuthMagic**\ (3) to the current
  113. DRM-Master to access the GEM subsystem. A driver that does not support GEM will
  114. return ``ENODEV`` for all these ioctls. Invalid object handles return
  115. ``EINVAL`` and invalid object names return ``ENOENT``.
  116. Gem provides explicit memory management primitives. System pages are allocated
  117. when the object is created, either as the fundamental storage for hardware
  118. where system memory is used by the graphics processor directly, or as backing
  119. store for graphics-processor resident memory.
  120. Objects are referenced from user-space using handles. These are, for all
  121. intents and purposes, equivalent to file descriptors but avoid the overhead.
  122. Newer kernel drivers also support the **drm-prime** (7) infrastructure which
  123. can return real file-descriptor for GEM-handles using the linux DMA-BUF API.
  124. Objects may be published with a name so that other applications and processes
  125. can access them. The name remains valid as long as the object exists.
  126. GEM-objects are reference counted in the kernel. The object is only destroyed
  127. when all handles from user-space were closed.
  128. GEM-buffers cannot be created with a generic API. Each driver provides its own
  129. API to create GEM-buffers. See for example ``DRM_I915_GEM_CREATE``,
  130. ``DRM_NOUVEAU_GEM_NEW`` or ``DRM_RADEON_GEM_CREATE``. Each of these ioctls
  131. returns a GEM-handle that can be passed to different generic ioctls. The
  132. *libgbm* library from the *mesa3D* distribution tries to provide a
  133. driver-independent API to create GBM buffers and retrieve a GBM-handle to them.
  134. It allows to create buffers for different use-cases including scanout,
  135. rendering, cursors and CPU-access. See the libgbm library for more information
  136. or look at the driver-dependent man-pages (for example **drm-intel**\ (7) or
  137. **drm-radeon**\ (7)).
  138. GEM-buffers can be closed with **drmCloseBufferHandle**\ (3). It takes as
  139. argument the GEM-handle to be closed. After this call the GEM handle cannot be
  140. used by this process anymore and may be reused for new GEM objects by the GEM
  141. API.
  142. If you want to share GEM-objects between different processes, you can create a
  143. name for them and pass this name to other processes which can then open this
  144. GEM-object. Names are currently 32-bit integer IDs and have no special
  145. protection. That is, if you put a name on your GEM-object, every other client
  146. that has access to the DRM device and is authenticated via
  147. **drmAuthMagic**\ (3) to the current DRM-Master, can *guess* the name and open
  148. or access the GEM-object. If you want more fine-grained access control, you can
  149. use the new **drm-prime**\ (7) API to retrieve file-descriptors for
  150. GEM-handles. To create a name for a GEM-handle, you use the
  151. ``DRM_IOCTL_GEM_FLINK`` ioctl. It takes as argument a structure of type
  152. ``struct drm_gem_flink``:
  153. ::
  154. struct drm_gem_flink {
  155. __u32 handle;
  156. __u32 name;
  157. };
  158. You have to put your handle into the *handle* field. After completion, the
  159. kernel has put the new unique name into the name field. You can now pass
  160. this name to other processes which can then import the name with the
  161. ``DRM_IOCTL_GEM_OPEN`` ioctl. It takes as argument a structure of type
  162. ``struct drm_gem_open``:
  163. ::
  164. struct drm_gem_open {
  165. __u32 name;
  166. __u32 handle;
  167. __u32 size;
  168. };
  169. You have to fill in the *name* field with the name of the GEM-object that you
  170. want to open. The kernel will fill in the *handle* and *size* fields with the
  171. new handle and size of the GEM-object. You can now access the GEM-object via
  172. the handle as if you created it with the GEM API.
  173. Besides generic buffer management, the GEM API does not provide any generic
  174. access. Each driver implements its own functionality on top of this API. This
  175. includes execution-buffers, GTT management, context creation, CPU access, GPU
  176. I/O and more. The next higher-level API is *OpenGL*. So if you want to use more
  177. GPU features, you should use the *mesa3D* library to create OpenGL contexts on
  178. DRM devices. This does *not* require any windowing-system like X11, but can
  179. also be done on raw DRM devices. However, this is beyond the scope of this
  180. man-page. You may have a look at other mesa3D man pages, including libgbm and
  181. libEGL. 2D software-rendering (rendering with the CPU) can be achieved with the
  182. dumb-buffer-API in a driver-independent fashion, however, for
  183. hardware-accelerated 2D or 3D rendering you must use OpenGL. Any other API that
  184. tries to abstract the driver-internals to access GEM-execution-buffers and
  185. other GPU internals, would simply reinvent OpenGL so it is not provided. But if
  186. you need more detailed information for a specific driver, you may have a look
  187. into the driver-manpages, including **drm-intel**\ (7), **drm-radeon**\ (7) and
  188. **drm-nouveau**\ (7). However, the **drm-prime**\ (7) infrastructure and the
  189. generic GEM API as described here allow display-managers to handle
  190. graphics-buffers and render-clients without any deeper knowledge of the GPU
  191. that is used. Moreover, it allows to move objects between GPUs and implement
  192. complex display-servers that don't do any rendering on their own. See its
  193. man-page for more information.
  194. Examples
  195. ========
  196. This section includes examples for basic memory-management tasks.
  197. Dumb-Buffers
  198. ------------
  199. This examples shows how to create a dumb-buffer via the generic DRM API.
  200. This is driver-independent (as long as the driver supports dumb-buffers)
  201. and provides memory-mapped buffers that can be used for scanout. This
  202. example creates a full-HD 1920x1080 buffer with 32 bits-per-pixel and a
  203. color-depth of 24 bits. The buffer is then bound to a framebuffer which
  204. can be used for scanout with the KMS API (see **drm-kms**\ (7)).
  205. ::
  206. struct drm_mode_create_dumb creq;
  207. struct drm_mode_destroy_dumb dreq;
  208. struct drm_mode_map_dumb mreq;
  209. uint32_t fb;
  210. int ret;
  211. void *map;
  212. /* create dumb buffer */
  213. memset(&creq, 0, sizeof(creq));
  214. creq.width = 1920;
  215. creq.height = 1080;
  216. creq.bpp = 32;
  217. ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
  218. if (ret < 0) {
  219. /* buffer creation failed; see "errno" for more error codes */
  220. ...
  221. }
  222. /* creq.pitch, creq.handle and creq.size are filled by this ioctl with
  223. * the requested values and can be used now. */
  224. /* create framebuffer object for the dumb-buffer */
  225. ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb);
  226. if (ret) {
  227. /* frame buffer creation failed; see "errno" */
  228. ...
  229. }
  230. /* the framebuffer "fb" can now used for scanout with KMS */
  231. /* prepare buffer for memory mapping */
  232. memset(&mreq, 0, sizeof(mreq));
  233. mreq.handle = creq.handle;
  234. ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
  235. if (ret) {
  236. /* DRM buffer preparation failed; see "errno" */
  237. ...
  238. }
  239. /* mreq.offset now contains the new offset that can be used with mmap() */
  240. /* perform actual memory mapping */
  241. map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
  242. if (map == MAP_FAILED) {
  243. /* memory-mapping failed; see "errno" */
  244. ...
  245. }
  246. /* clear the framebuffer to 0 */
  247. memset(map, 0, creq.size);
  248. Reporting Bugs
  249. ==============
  250. Bugs in this manual should be reported to
  251. https://gitlab.freedesktop.org/mesa/libdrm/-/issues
  252. See Also
  253. ========
  254. **drm**\ (7), **drm-kms**\ (7), **drm-prime**\ (7), **drmAvailable**\ (3),
  255. **drmOpen**\ (3), **drm-intel**\ (7), **drm-radeon**\ (7), **drm-nouveau**\ (7)