141687f09Smrg==========
241687f09Smrgdrm-memory
341687f09Smrg==========
441687f09Smrg
541687f09Smrg---------------------
641687f09SmrgDRM Memory Management
741687f09Smrg---------------------
841687f09Smrg
941687f09Smrg:Date: September 2012
1041687f09Smrg:Manual section: 7
1141687f09Smrg:Manual group: Direct Rendering Manager
1241687f09Smrg
1341687f09SmrgSynopsis
1441687f09Smrg========
1541687f09Smrg
1641687f09Smrg``#include <xf86drm.h>``
1741687f09Smrg
1841687f09SmrgDescription
1941687f09Smrg===========
2041687f09Smrg
2141687f09SmrgMany modern high-end GPUs come with their own memory managers. They even
2241687f09Smrginclude several different caches that need to be synchronized during access.
2341687f09SmrgTextures, framebuffers, command buffers and more need to be stored in memory
2441687f09Smrgthat can be accessed quickly by the GPU. Therefore, memory management on GPUs
2541687f09Smrgis highly driver- and hardware-dependent.
2641687f09Smrg
2741687f09SmrgHowever, there are several frameworks in the kernel that are used by more than
2841687f09Smrgone driver. These can be used for trivial mode-setting without requiring
2941687f09Smrgdriver-dependent code. But for hardware-accelerated rendering you need to read
3041687f09Smrgthe manual pages for the driver you want to work with.
3141687f09Smrg
3241687f09SmrgDumb-Buffers
3341687f09Smrg------------
3441687f09Smrg
3541687f09SmrgAlmost all in-kernel DRM hardware drivers support an API called *Dumb-Buffers*.
3641687f09SmrgThis API allows to create buffers of arbitrary size that can be used for
3741687f09Smrgscanout. These buffers can be memory mapped via **mmap**\ (2) so you can render
3841687f09Smrginto them on the CPU. However, GPU access to these buffers is often not
3941687f09Smrgpossible. Therefore, they are fine for simple tasks but not suitable for
4041687f09Smrgcomplex compositions and renderings.
4141687f09Smrg
4241687f09SmrgThe ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl can be used to create a dumb buffer.
4341687f09SmrgThe kernel will return a 32-bit handle that can be used to manage the buffer
4441687f09Smrgwith the DRM API. You can create framebuffers with **drmModeAddFB**\ (3) and
4541687f09Smrguse it for mode-setting and scanout. To access the buffer, you first need to
4641687f09Smrgretrieve the offset of the buffer. The ``DRM_IOCTL_MODE_MAP_DUMB`` ioctl
4741687f09Smrgrequests the DRM subsystem to prepare the buffer for memory-mapping and returns
4841687f09Smrga fake-offset that can be used with **mmap**\ (2).
4941687f09Smrg
5041687f09SmrgThe ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl takes as argument a structure of type
5141687f09Smrg``struct drm_mode_create_dumb``:
5241687f09Smrg
5341687f09Smrg::
5441687f09Smrg
5541687f09Smrg   struct drm_mode_create_dumb {
5641687f09Smrg       __u32 height;
5741687f09Smrg       __u32 width;
5841687f09Smrg       __u32 bpp;
5941687f09Smrg       __u32 flags;
6041687f09Smrg
6141687f09Smrg       __u32 handle;
6241687f09Smrg       __u32 pitch;
6341687f09Smrg       __u64 size;
6441687f09Smrg   };
6541687f09Smrg
6641687f09SmrgThe fields *height*, *width*, *bpp* and *flags* have to be provided by the
6741687f09Smrgcaller. The other fields are filled by the kernel with the return values.
6841687f09Smrg*height* and *width* are the dimensions of the rectangular buffer that is
6941687f09Smrgcreated. *bpp* is the number of bits-per-pixel and must be a multiple of 8. You
7041687f09Smrgmost commonly want to pass 32 here. The flags field is currently unused and
7141687f09Smrgmust be zeroed. Different flags to modify the behavior may be added in the
7241687f09Smrgfuture. After calling the ioctl, the handle, pitch and size fields are filled
7341687f09Smrgby the kernel. *handle* is a 32-bit gem handle that identifies the buffer. This
7441687f09Smrgis used by several other calls that take a gem-handle or memory-buffer as
7541687f09Smrgargument. The *pitch* field is the pitch (or stride) of the new buffer. Most
7641687f09Smrgdrivers use 32-bit or 64-bit aligned stride-values. The size field contains the
7741687f09Smrgabsolute size in bytes of the buffer. This can normally also be computed with
7841687f09Smrg``(height * pitch + width) * bpp / 4``.
7941687f09Smrg
8041687f09SmrgTo prepare the buffer for **mmap**\ (2) you need to use the
8141687f09Smrg``DRM_IOCTL_MODE_MAP_DUMB`` ioctl. It takes as argument a structure of type
8241687f09Smrg``struct drm_mode_map_dumb``:
8341687f09Smrg
8441687f09Smrg::
8541687f09Smrg
8641687f09Smrg   struct drm_mode_map_dumb {
8741687f09Smrg       __u32 handle;
8841687f09Smrg       __u32 pad;
8941687f09Smrg
9041687f09Smrg       __u64 offset;
9141687f09Smrg   };
9241687f09Smrg
9341687f09SmrgYou need to put the gem-handle that was previously retrieved via
9441687f09Smrg``DRM_IOCTL_MODE_CREATE_DUMB`` into the *handle* field. The *pad* field is
9541687f09Smrgunused padding and must be zeroed. After completion, the *offset* field will
9641687f09Smrgcontain an offset that can be used with **mmap**\ (2) on the DRM
9741687f09Smrgfile-descriptor.
9841687f09Smrg
9941687f09SmrgIf you don't need your dumb-buffer, anymore, you have to destroy it with
10041687f09Smrg``DRM_IOCTL_MODE_DESTROY_DUMB``. If you close the DRM file-descriptor, all open
10141687f09Smrgdumb-buffers are automatically destroyed. This ioctl takes as argument a
10241687f09Smrgstructure of type ``struct drm_mode_destroy_dumb``:
10341687f09Smrg
10441687f09Smrg::
10541687f09Smrg
10641687f09Smrg   struct drm_mode_destroy_dumb {
10741687f09Smrg       __u32 handle;
10841687f09Smrg   };
10941687f09Smrg
11041687f09SmrgYou only need to put your handle into the *handle* field. After this call, the
11141687f09Smrghandle is invalid and may be reused for new buffers by the dumb-API.
11241687f09Smrg
11341687f09SmrgTTM
11441687f09Smrg---
11541687f09Smrg
11641687f09Smrg*TTM* stands for *Translation Table Manager* and is a generic memory-manager
11741687f09Smrgprovided by the kernel. It does not provide a common user-space API so you need
11841687f09Smrgto look at each driver interface if you want to use it. See for instance the
11941687f09Smrgradeon man pages for more information on memory-management with radeon and TTM.
12041687f09Smrg
12141687f09SmrgGEM
12241687f09Smrg---
12341687f09Smrg
12441687f09Smrg*GEM* stands for *Graphics Execution Manager* and is a generic DRM
12541687f09Smrgmemory-management framework in the kernel, that is used by many different
12641687f09Smrgdrivers. GEM is designed to manage graphics memory, control access to the
12741687f09Smrggraphics device execution context and handle essentially NUMA environment
12841687f09Smrgunique to modern graphics hardware. GEM allows multiple applications to share
12941687f09Smrggraphics device resources without the need to constantly reload the entire
13041687f09Smrggraphics card. Data may be shared between multiple applications with gem
13141687f09Smrgensuring that the correct memory synchronization occurs.
13241687f09Smrg
13341687f09SmrgGEM provides simple mechanisms to manage graphics data and control execution
13441687f09Smrgflow within the linux DRM subsystem. However, GEM is not a complete framework
13541687f09Smrgthat is fully driver independent. Instead, if provides many functions that are
13641687f09Smrgshared between many drivers, but each driver has to implement most of
13741687f09Smrgmemory-management with driver-dependent ioctls. This manpage tries to describe
13841687f09Smrgthe semantics (and if it applies, the syntax) that is shared between all
13941687f09Smrgdrivers that use GEM.
14041687f09Smrg
14141687f09SmrgAll GEM APIs are defined as **ioctl**\ (2) on the DRM file descriptor. An
14241687f09Smrgapplication must be authorized via **drmAuthMagic**\ (3) to the current
14341687f09SmrgDRM-Master to access the GEM subsystem. A driver that does not support GEM will
14441687f09Smrgreturn ``ENODEV`` for all these ioctls. Invalid object handles return
14541687f09Smrg``EINVAL`` and invalid object names return ``ENOENT``.
14641687f09Smrg
14741687f09SmrgGem provides explicit memory management primitives. System pages are allocated
14841687f09Smrgwhen the object is created, either as the fundamental storage for hardware
14941687f09Smrgwhere system memory is used by the graphics processor directly, or as backing
15041687f09Smrgstore for graphics-processor resident memory.
15141687f09Smrg
15241687f09SmrgObjects are referenced from user-space using handles. These are, for all
15341687f09Smrgintents and purposes, equivalent to file descriptors but avoid the overhead.
15441687f09SmrgNewer kernel drivers also support the **drm-prime** (7) infrastructure which
15541687f09Smrgcan return real file-descriptor for GEM-handles using the linux DMA-BUF API.
15641687f09SmrgObjects may be published with a name so that other applications and processes
15741687f09Smrgcan access them. The name remains valid as long as the object exists.
15841687f09SmrgGEM-objects are reference counted in the kernel. The object is only destroyed
15941687f09Smrgwhen all handles from user-space were closed.
16041687f09Smrg
16141687f09SmrgGEM-buffers cannot be created with a generic API. Each driver provides its own
16241687f09SmrgAPI to create GEM-buffers. See for example ``DRM_I915_GEM_CREATE``,
16341687f09Smrg``DRM_NOUVEAU_GEM_NEW`` or ``DRM_RADEON_GEM_CREATE``. Each of these ioctls
16441687f09Smrgreturns a GEM-handle that can be passed to different generic ioctls. The
16541687f09Smrg*libgbm* library from the *mesa3D* distribution tries to provide a
16641687f09Smrgdriver-independent API to create GBM buffers and retrieve a GBM-handle to them.
16741687f09SmrgIt allows to create buffers for different use-cases including scanout,
16841687f09Smrgrendering, cursors and CPU-access. See the libgbm library for more information
16941687f09Smrgor look at the driver-dependent man-pages (for example **drm-intel**\ (7) or
17041687f09Smrg**drm-radeon**\ (7)).
17141687f09Smrg
17249ef06a4SmrgGEM-buffers can be closed with **drmCloseBufferHandle**\ (3). It takes as
17349ef06a4Smrgargument the GEM-handle to be closed. After this call the GEM handle cannot be
17449ef06a4Smrgused by this process anymore and may be reused for new GEM objects by the GEM
17549ef06a4SmrgAPI.
17641687f09Smrg
17741687f09SmrgIf you want to share GEM-objects between different processes, you can create a
17841687f09Smrgname for them and pass this name to other processes which can then open this
17941687f09SmrgGEM-object. Names are currently 32-bit integer IDs and have no special
18041687f09Smrgprotection. That is, if you put a name on your GEM-object, every other client
18141687f09Smrgthat has access to the DRM device and is authenticated via
18241687f09Smrg**drmAuthMagic**\ (3) to the current DRM-Master, can *guess* the name and open
18341687f09Smrgor access the GEM-object. If you want more fine-grained access control, you can
18441687f09Smrguse the new **drm-prime**\ (7) API to retrieve file-descriptors for
18541687f09SmrgGEM-handles. To create a name for a GEM-handle, you use the
18641687f09Smrg``DRM_IOCTL_GEM_FLINK`` ioctl. It takes as argument a structure of type
18741687f09Smrg``struct drm_gem_flink``:
18841687f09Smrg
18941687f09Smrg::
19041687f09Smrg
19141687f09Smrg   struct drm_gem_flink {
19241687f09Smrg       __u32 handle;
19341687f09Smrg       __u32 name;
19441687f09Smrg   };
19541687f09Smrg
19641687f09SmrgYou have to put your handle into the *handle* field. After completion, the
19741687f09Smrgkernel has put the new unique name into the name field. You can now pass
19841687f09Smrgthis name to other processes which can then import the name with the
19941687f09Smrg``DRM_IOCTL_GEM_OPEN`` ioctl. It takes as argument a structure of type
20041687f09Smrg``struct drm_gem_open``:
20141687f09Smrg
20241687f09Smrg::
20341687f09Smrg
20441687f09Smrg   struct drm_gem_open {
20541687f09Smrg       __u32 name;
20641687f09Smrg
20741687f09Smrg       __u32 handle;
20841687f09Smrg       __u32 size;
20941687f09Smrg   };
21041687f09Smrg
21141687f09SmrgYou have to fill in the *name* field with the name of the GEM-object that you
21241687f09Smrgwant to open. The kernel will fill in the *handle* and *size* fields with the
21341687f09Smrgnew handle and size of the GEM-object. You can now access the GEM-object via
21441687f09Smrgthe handle as if you created it with the GEM API.
21541687f09Smrg
21641687f09SmrgBesides generic buffer management, the GEM API does not provide any generic
21741687f09Smrgaccess. Each driver implements its own functionality on top of this API. This
21841687f09Smrgincludes execution-buffers, GTT management, context creation, CPU access, GPU
21941687f09SmrgI/O and more. The next higher-level API is *OpenGL*. So if you want to use more
22041687f09SmrgGPU features, you should use the *mesa3D* library to create OpenGL contexts on
22141687f09SmrgDRM devices. This does *not* require any windowing-system like X11, but can
22241687f09Smrgalso be done on raw DRM devices. However, this is beyond the scope of this
22341687f09Smrgman-page. You may have a look at other mesa3D man pages, including libgbm and
22441687f09SmrglibEGL. 2D software-rendering (rendering with the CPU) can be achieved with the
22541687f09Smrgdumb-buffer-API in a driver-independent fashion, however, for
22641687f09Smrghardware-accelerated 2D or 3D rendering you must use OpenGL. Any other API that
22741687f09Smrgtries to abstract the driver-internals to access GEM-execution-buffers and
22841687f09Smrgother GPU internals, would simply reinvent OpenGL so it is not provided. But if
22941687f09Smrgyou need more detailed information for a specific driver, you may have a look
23041687f09Smrginto the driver-manpages, including **drm-intel**\ (7), **drm-radeon**\ (7) and
23141687f09Smrg**drm-nouveau**\ (7). However, the **drm-prime**\ (7) infrastructure and the
23241687f09Smrggeneric GEM API as described here allow display-managers to handle
23341687f09Smrggraphics-buffers and render-clients without any deeper knowledge of the GPU
23441687f09Smrgthat is used. Moreover, it allows to move objects between GPUs and implement
23541687f09Smrgcomplex display-servers that don't do any rendering on their own. See its
23641687f09Smrgman-page for more information.
23741687f09Smrg
23841687f09SmrgExamples
23941687f09Smrg========
24041687f09Smrg
24141687f09SmrgThis section includes examples for basic memory-management tasks.
24241687f09Smrg
24341687f09SmrgDumb-Buffers
24441687f09Smrg------------
24541687f09Smrg
24641687f09SmrgThis examples shows how to create a dumb-buffer via the generic DRM API.
24741687f09SmrgThis is driver-independent (as long as the driver supports dumb-buffers)
24841687f09Smrgand provides memory-mapped buffers that can be used for scanout. This
24941687f09Smrgexample creates a full-HD 1920x1080 buffer with 32 bits-per-pixel and a
25041687f09Smrgcolor-depth of 24 bits. The buffer is then bound to a framebuffer which
25141687f09Smrgcan be used for scanout with the KMS API (see **drm-kms**\ (7)).
25241687f09Smrg
25341687f09Smrg::
25441687f09Smrg
25541687f09Smrg   struct drm_mode_create_dumb creq;
25641687f09Smrg   struct drm_mode_destroy_dumb dreq;
25741687f09Smrg   struct drm_mode_map_dumb mreq;
25841687f09Smrg   uint32_t fb;
25941687f09Smrg   int ret;
26041687f09Smrg   void *map;
26141687f09Smrg
26241687f09Smrg   /* create dumb buffer */
26341687f09Smrg   memset(&creq, 0, sizeof(creq));
26441687f09Smrg   creq.width = 1920;
26541687f09Smrg   creq.height = 1080;
26641687f09Smrg   creq.bpp = 32;
26741687f09Smrg   ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
26841687f09Smrg   if (ret < 0) {
26941687f09Smrg       /* buffer creation failed; see "errno" for more error codes */
27041687f09Smrg       ...
27141687f09Smrg   }
27241687f09Smrg   /* creq.pitch, creq.handle and creq.size are filled by this ioctl with
27341687f09Smrg    * the requested values and can be used now. */
27441687f09Smrg
27541687f09Smrg   /* create framebuffer object for the dumb-buffer */
27641687f09Smrg   ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb);
27741687f09Smrg   if (ret) {
27841687f09Smrg       /* frame buffer creation failed; see "errno" */
27941687f09Smrg       ...
28041687f09Smrg   }
28141687f09Smrg   /* the framebuffer "fb" can now used for scanout with KMS */
28241687f09Smrg
28341687f09Smrg   /* prepare buffer for memory mapping */
28441687f09Smrg   memset(&mreq, 0, sizeof(mreq));
28541687f09Smrg   mreq.handle = creq.handle;
28641687f09Smrg   ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
28741687f09Smrg   if (ret) {
28841687f09Smrg       /* DRM buffer preparation failed; see "errno" */
28941687f09Smrg       ...
29041687f09Smrg   }
29141687f09Smrg   /* mreq.offset now contains the new offset that can be used with mmap() */
29241687f09Smrg
29341687f09Smrg   /* perform actual memory mapping */
29441687f09Smrg   map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
29541687f09Smrg   if (map == MAP_FAILED) {
29641687f09Smrg       /* memory-mapping failed; see "errno" */
29741687f09Smrg       ...
29841687f09Smrg   }
29941687f09Smrg
30041687f09Smrg   /* clear the framebuffer to 0 */
30141687f09Smrg   memset(map, 0, creq.size);
30241687f09Smrg
30341687f09SmrgReporting Bugs
30441687f09Smrg==============
30541687f09Smrg
30641687f09SmrgBugs in this manual should be reported to
30741687f09Smrghttps://gitlab.freedesktop.org/mesa/drm/-/issues
30841687f09Smrg
30941687f09SmrgSee Also
31041687f09Smrg========
31141687f09Smrg
31241687f09Smrg**drm**\ (7), **drm-kms**\ (7), **drm-prime**\ (7), **drmAvailable**\ (3),
31341687f09Smrg**drmOpen**\ (3), **drm-intel**\ (7), **drm-radeon**\ (7), **drm-nouveau**\ (7)
314