1 <?xml version='1.0'?> <!--*-nxml-*-->
2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
6 Written 2012 by David Herrmann <dh.herrmann@googlemail.com>
7 Dedicated to the Public Domain
10 <refentry id="drm-memory">
12 <title>Direct Rendering Manager</title>
13 <productname>libdrm</productname>
14 <date>September 2012</date>
17 <contrib>Developer</contrib>
18 <firstname>David</firstname>
19 <surname>Herrmann</surname>
20 <email>dh.herrmann@googlemail.com</email>
26 <refentrytitle>drm-memory</refentrytitle>
27 <manvolnum>7</manvolnum>
31 <refname>drm-memory</refname>
32 <refname>drm-mm</refname>
33 <refname>drm-gem</refname>
34 <refname>drm-ttm</refname>
35 <refpurpose>DRM Memory Management</refpurpose>
40 <funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo>
45 <title>Description</title>
46 <para>Many modern high-end GPUs come with their own memory managers. They
47 even include several different caches that need to be synchronized
48 during access. Textures, framebuffers, command buffers and more need
49 to be stored in memory that can be accessed quickly by the GPU.
50 Therefore, memory management on GPUs is highly driver- and
51 hardware-dependent.</para>
53 <para>However, there are several frameworks in the kernel that are used by
54 more than one driver. These can be used for trivial mode-setting
55 without requiring driver-dependent code. But for
56 hardware-accelerated rendering you need to read the manual pages for
57 the driver you want to work with.</para>
60 <title>Dumb-Buffers</title>
61 <para>Almost all in-kernel DRM hardware drivers support an API called
62 <emphasis>Dumb-Buffers</emphasis>. This API allows to create buffers
63 of arbitrary size that can be used for scanout. These buffers can be
65 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
66 so you can render into them on the CPU. However, GPU access to these
67 buffers is often not possible. Therefore, they are fine for simple
68 tasks but not suitable for complex compositions and
71 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl can be
72 used to create a dumb buffer. The kernel will return a 32bit handle
73 that can be used to manage the buffer with the DRM API. You can
74 create framebuffers with
75 <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>
76 and use it for mode-setting and scanout. To access the buffer, you
77 first need to retrieve the offset of the buffer. The
78 <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> ioctl requests the DRM
79 subsystem to prepare the buffer for memory-mapping and returns a
80 fake-offset that can be used with
81 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
83 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl takes as
84 argument a structure of type
85 <structname>struct drm_mode_create_dumb</structname>:
88 struct drm_mode_create_dumb {
100 The fields <structfield>height</structfield>,
101 <structfield>width</structfield>, <structfield>bpp</structfield> and
102 <structfield>flags</structfield> have to be provided by the caller.
103 The other fields are filled by the kernel with the return values.
104 <structfield>height</structfield> and
105 <structfield>width</structfield> are the dimensions of the
106 rectangular buffer that is created. <structfield>bpp</structfield>
107 is the number of bits-per-pixel and must be a multiple of
108 <literal>8</literal>. You most commonly want to pass
109 <literal>32</literal> here. The <structfield>flags</structfield>
110 field is currently unused and must be zeroed. Different flags to
111 modify the behavior may be added in the future. After calling the
112 ioctl, the <structfield>handle</structfield>,
113 <structfield>pitch</structfield> and <structfield>size</structfield>
114 fields are filled by the kernel. <structfield>handle</structfield>
115 is a 32bit gem handle that identifies the buffer. This is used by
116 several other calls that take a gem-handle or memory-buffer as
117 argument. The <structfield>pitch</structfield> field is the
118 pitch (or stride) of the new buffer. Most drivers use 32bit or 64bit
119 aligned stride-values. The <structfield>size</structfield> field
120 contains the absolute size in bytes of the buffer. This can normally
121 also be computed with
122 <emphasis>(height * pitch + width) * bpp / 4</emphasis>.</para>
124 <para>To prepare the buffer for
125 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
126 you need to use the <constant>DRM_IOCTL_MODE_MAP_DUMB</constant>
127 ioctl. It takes as argument a structure of type
128 <structname>struct drm_mode_map_dumb</structname>:
131 struct drm_mode_map_dumb {
139 You need to put the gem-handle that was previously retrieved via
140 <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> into the
141 <structfield>handle</structfield> field. The
142 <structfield>pad</structfield> field is unused padding and must be
143 zeroed. After completion, the <structfield>offset</structfield>
144 field will contain an offset that can be used with
145 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
146 on the DRM file-descriptor.</para>
148 <para>If you don't need your dumb-buffer, anymore, you have to destroy it
149 with <constant>DRM_IOCTL_MODE_DESTROY_DUMB</constant>. If you close
150 the DRM file-descriptor, all open dumb-buffers are automatically
151 destroyed. This ioctl takes as argument a structure of type
152 <structname>struct drm_mode_destroy_dumb</structname>:
155 struct drm_mode_destroy_dumb {
160 You only need to put your handle into the
161 <structfield>handle</structfield> field. After this call, the handle
162 is invalid and may be reused for new buffers by the dumb-API.</para>
168 <para><emphasis>TTM</emphasis> stands for
169 <emphasis>Translation Table Manager</emphasis> and is a generic
170 memory-manager provided by the kernel. It does not provide a common
171 user-space API so you need to look at each driver interface if you
172 want to use it. See for instance the radeon manpages for more
173 information on memory-management with radeon and TTM.</para>
178 <para><emphasis>GEM</emphasis> stands for
179 <emphasis>Graphics Execution Manager</emphasis> and is a generic DRM
180 memory-management framework in the kernel, that is used by many
181 different drivers. Gem is designed to manage graphics memory,
182 control access to the graphics device execution context and handle
183 essentially NUMA environment unique to modern graphics hardware. Gem
184 allows multiple applications to share graphics device resources
185 without the need to constantly reload the entire graphics card. Data
186 may be shared between multiple applications with gem ensuring that
187 the correct memory synchronization occurs.</para>
189 <para>Gem provides simple mechanisms to manage graphics data and control
190 execution flow within the linux DRM subsystem. However, gem is not a
191 complete framework that is fully driver independent. Instead, if
192 provides many functions that are shared between many drivers, but
193 each driver has to implement most of memory-management with
194 driver-dependent ioctls. This manpage tries to describe the
195 semantics (and if it applies, the syntax) that is shared between all
196 drivers that use gem.</para>
198 <para>All GEM APIs are defined as
199 <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
200 on the DRM file descriptor. An application must be authorized via
201 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
202 to the current DRM-Master to access the GEM subsystem. A driver that
203 does not support gem will return <constant>ENODEV</constant> for all
204 these ioctls. Invalid object handles return
205 <constant>EINVAL</constant> and invalid object names return
206 <constant>ENOENT</constant>.</para>
208 <para>Gem provides explicit memory management primitives. System pages are
209 allocated when the object is created, either as the fundamental
210 storage for hardware where system memory is used by the graphics
211 processor directly, or as backing store for graphics-processor
212 resident memory.</para>
214 <para>Objects are referenced from user-space using handles. These are, for
215 all intents and purposes, equivalent to file descriptors but avoid
216 the overhead. Newer kernel drivers also support the
217 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
218 infrastructure which can return real file-descriptor for gem-handles
219 using the linux dma-buf API. Objects may be published with a name so
220 that other applications and processes can access them. The name
221 remains valid as long as the object exists. Gem-objects are
222 reference counted in the kernel. The object is only destroyed when
223 all handles from user-space were closed.</para>
225 <para>Gem-buffers cannot be created with a generic API. Each driver
226 provides its own API to create gem-buffers. See for example
227 <constant>DRM_I915_GEM_CREATE</constant>,
228 <constant>DRM_NOUVEAU_GEM_NEW</constant> or
229 <constant>DRM_RADEON_GEM_CREATE</constant>. Each of these ioctls
230 returns a gem-handle that can be passed to different generic ioctls.
231 The <emphasis>libgbm</emphasis> library from the
232 <emphasis>mesa3D</emphasis> distribution tries to provide a
233 driver-independent API to create gbm buffers and retrieve a
234 gbm-handle to them. It allows to create buffers for different
235 use-cases including scanout, rendering, cursors and CPU-access. See
236 the libgbm library for more information or look at the
237 driver-dependent man-pages (for example
238 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>
240 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para>
242 <para>Gem-buffers can be closed with the
243 <constant>DRM_IOCTL_GEM_CLOSE</constant> ioctl. It takes as argument
244 a structure of type <structname>struct drm_gem_close</structname>:
247 struct drm_gem_close {
253 The <structfield>handle</structfield> field is the gem-handle to be
254 closed. The <structfield>pad</structfield> field is unused padding.
255 It must be zeroed. After this call the gem handle cannot be used by
256 this process anymore and may be reused for new gem objects by the
259 <para>If you want to share gem-objects between different processes, you
260 can create a name for them and pass this name to other processes
261 which can then open this gem-object. Names are currently 32bit
262 integer IDs and have no special protection. That is, if you put a
263 name on your gem-object, every other client that has access to the
264 DRM device and is authenticated via
265 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
266 to the current DRM-Master, can <emphasis>guess</emphasis> the name
267 and open or access the gem-object. If you want more fine-grained
268 access control, you can use the new
269 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
270 API to retrieve file-descriptors for gem-handles. To create a name
271 for a gem-handle, you use the
272 <constant>DRM_IOCTL_GEM_FLINK</constant> ioctl. It takes as argument
273 a structure of type <structname>struct drm_gem_flink</structname>:
276 struct drm_gem_flink {
282 You have to put your handle into the
283 <structfield>handle</structfield> field. After completion, the
284 kernel has put the new unique name into the
285 <structfield>name</structfield> field. You can now pass this name to
286 other processes which can then import the name with the
287 <constant>DRM_IOCTL_GEM_OPEN</constant> ioctl. It takes as argument
288 a structure of type <structname>struct drm_gem_open</structname>:
291 struct drm_gem_open {
299 You have to fill in the <structfield>name</structfield> field with
300 the name of the gem-object that you want to open. The kernel will
301 fill in the <structfield>handle</structfield> and
302 <structfield>size</structfield> fields with the new handle and size
303 of the gem-object. You can now access the gem-object via the handle
304 as if you created it with the gem API.</para>
306 <para>Besides generic buffer management, the GEM API does not provide any
307 generic access. Each driver implements its own functionality on top
308 of this API. This includes execution-buffers, GTT management,
309 context creation, CPU access, GPU I/O and more. The next
310 higher-level API is <emphasis>OpenGL</emphasis>. So if you want to
311 use more GPU features, you should use the
312 <emphasis>mesa3D</emphasis> library to create OpenGL contexts on DRM
313 devices. This does <emphasis>not</emphasis> require any
314 windowing-system like X11, but can also be done on raw DRM devices.
315 However, this is beyond the scope of this man-page. You may have a
316 look at other mesa3D manpages, including libgbm and libEGL. 2D
317 software-rendering (rendering with the CPU) can be achieved with the
318 dumb-buffer-API in a driver-independent fashion, however, for
319 hardware-accelerated 2D or 3D rendering you must use OpenGL. Any
320 other API that tries to abstract the driver-internals to access
321 GEM-execution-buffers and other GPU internals, would simply reinvent
322 OpenGL so it is not provided. But if you need more detailed
323 information for a specific driver, you may have a look into the
324 driver-manpages, including
325 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
326 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>
328 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
330 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
331 infrastructure and the generic gem API as described here allow
332 display-managers to handle graphics-buffers and render-clients
333 without any deeper knowledge of the GPU that is used. Moreover, it
334 allows to move objects between GPUs and implement complex
335 display-servers that don't do any rendering on their own. See its
336 man-page for more information.</para>
341 <title>Examples</title>
342 <para>This section includes examples for basic memory-management
346 <title>Dumb-Buffers</title>
347 <para>This examples shows how to create a dumb-buffer via the generic
348 DRM API. This is driver-independent (as long as the driver
349 supports dumb-buffers) and provides memory-mapped buffers that can
350 be used for scanout. This example creates a full-HD 1920x1080
351 buffer with 32 bits-per-pixel and a color-depth of 24 bits. The
352 buffer is then bound to a framebuffer which can be used for
353 scanout with the KMS API (see
354 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para>
357 struct drm_mode_create_dumb creq;
358 struct drm_mode_destroy_dumb dreq;
359 struct drm_mode_map_dumb mreq;
364 /* create dumb buffer */
365 memset(&creq, 0, sizeof(creq));
369 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
371 /* buffer creation failed; see "errno" for more error codes */
374 /* creq.pitch, creq.handle and creq.size are filled by this ioctl with
375 * the requested values and can be used now. */
377 /* create framebuffer object for the dumb-buffer */
378 ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb);
380 /* frame buffer creation failed; see "errno" */
383 /* the framebuffer "fb" can now used for scanout with KMS */
385 /* prepare buffer for memory mapping */
386 memset(&mreq, 0, sizeof(mreq));
387 mreq.handle = creq.handle;
388 ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
390 /* DRM buffer preparation failed; see "errno" */
393 /* mreq.offset now contains the new offset that can be used with mmap() */
395 /* perform actual memory mapping */
396 map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
397 if (map == MAP_FAILED) {
398 /* memory-mapping failed; see "errno" */
402 /* clear the framebuffer to 0 */
403 memset(map, 0, creq.size);
411 <title>Reporting Bugs</title>
412 <para>Bugs in this manual should be reported to
413 https://gitlab.freedesktop.org/mesa/drm/-/issues</para>
417 <title>See Also</title>
419 <citerefentry><refentrytitle>drm</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
420 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
421 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
422 <citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
423 <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
424 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
425 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
426 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>