1DRM-MEMORY(7)              Direct Rendering Manager              DRM-MEMORY(7)
2
3
4

NAME

6       drm-memory - DRM Memory Management
7

SYNOPSIS

9       #include <xf86drm.h>
10

DESCRIPTION

12       Many  modern  high-end  GPUs  come with their own memory managers. They
13       even include several different caches that need to be synchronized dur‐
14       ing  access.   Textures, framebuffers, command buffers and more need to
15       be stored in memory that can be accessed quickly by the GPU. Therefore,
16       memory management on GPUs is highly driver- and hardware-dependent.
17
18       However,  there  are  several frameworks in the kernel that are used by
19       more than one driver. These can be used for trivial mode-setting  with‐
20       out  requiring driver-dependent code. But for hardware-accelerated ren‐
21       dering you need to read the manual pages for the  driver  you  want  to
22       work with.
23
24   Dumb-Buffers
25       Almost  all  in-kernel  DRM  hardware  drivers  support  an  API called
26       Dumb-Buffers.  This API allows to create buffers of arbitrary size that
27       can be used for scanout. These buffers can be memory mapped via mmap(2)
28       so you can render into them on the CPU. However, GPU  access  to  these
29       buffers  is  often  not  possible.  Therefore, they are fine for simple
30       tasks but not suitable for complex compositions and renderings.
31
32       The DRM_IOCTL_MODE_CREATE_DUMB ioctl can be used to create a dumb  buf‐
33       fer.  The kernel will return a 32-bit handle that can be used to manage
34       the buffer with the DRM API. You can create framebuffers  with  drmMod‐
35       eAddFB(3)  and  use it for mode-setting and scanout. To access the buf‐
36       fer, you  first  need  to  retrieve  the  offset  of  the  buffer.  The
37       DRM_IOCTL_MODE_MAP_DUMB ioctl requests the DRM subsystem to prepare the
38       buffer for memory-mapping and returns a fake-offset that  can  be  used
39       with mmap(2).
40
41       The  DRM_IOCTL_MODE_CREATE_DUMB  ioctl takes as argument a structure of
42       type struct drm_mode_create_dumb:
43
44          struct drm_mode_create_dumb {
45              __u32 height;
46              __u32 width;
47              __u32 bpp;
48              __u32 flags;
49
50              __u32 handle;
51              __u32 pitch;
52              __u64 size;
53          };
54
55       The fields height, width, bpp and flags have  to  be  provided  by  the
56       caller.  The other fields are filled by the kernel with the return val‐
57       ues.  height and width are the dimensions  of  the  rectangular  buffer
58       that is created. bpp is the number of bits-per-pixel and must be a mul‐
59       tiple of 8. You most commonly want to pass 32 here. The flags field  is
60       currently  unused and must be zeroed. Different flags to modify the be‐
61       havior may be added in the future. After calling the ioctl, the handle,
62       pitch  and size fields are filled by the kernel. handle is a 32-bit gem
63       handle that identifies the buffer. This is used by several other  calls
64       that take a gem-handle or memory-buffer as argument. The pitch field is
65       the pitch (or stride) of the new buffer. Most  drivers  use  32-bit  or
66       64-bit aligned stride-values. The size field contains the absolute size
67       in bytes of the buffer. This can normally also be computed with (height
68       * pitch + width) * bpp / 4.
69
70       To   prepare   the   buffer   for   mmap(2)   you   need   to  use  the
71       DRM_IOCTL_MODE_MAP_DUMB ioctl. It takes as argument a structure of type
72       struct drm_mode_map_dumb:
73
74          struct drm_mode_map_dumb {
75              __u32 handle;
76              __u32 pad;
77
78              __u64 offset;
79          };
80
81       You  need  to  put  the  gem-handle  that  was previously retrieved via
82       DRM_IOCTL_MODE_CREATE_DUMB into the handle field. The pad field is  un‐
83       used  padding  and  must  be zeroed. After completion, the offset field
84       will contain an offset that  can  be  used  with  mmap(2)  on  the  DRM
85       file-descriptor.
86
87       If  you  don't  need  your dumb-buffer, anymore, you have to destroy it
88       with DRM_IOCTL_MODE_DESTROY_DUMB. If you close the DRM file-descriptor,
89       all  open dumb-buffers are automatically destroyed. This ioctl takes as
90       argument a structure of type struct drm_mode_destroy_dumb:
91
92          struct drm_mode_destroy_dumb {
93              __u32 handle;
94          };
95
96       You only need to put your handle into  the  handle  field.  After  this
97       call,  the  handle  is invalid and may be reused for new buffers by the
98       dumb-API.
99
100   TTM
101       TTM stands for Translation Table Manager and is a  generic  memory-man‐
102       ager  provided  by  the kernel. It does not provide a common user-space
103       API so you need to look at each driver interface if you want to use it.
104       See  for  instance  the  radeon  man pages for more information on mem‐
105       ory-management with radeon and TTM.
106
107   GEM
108       GEM stands for Graphics Execution Manager and is  a  generic  DRM  mem‐
109       ory-management  framework in the kernel, that is used by many different
110       drivers. GEM is designed to manage graphics memory, control  access  to
111       the graphics device execution context and handle essentially NUMA envi‐
112       ronment unique to modern graphics hardware. GEM allows multiple  appli‐
113       cations  to  share  graphics  device resources without the need to con‐
114       stantly reload the entire graphics card. Data  may  be  shared  between
115       multiple  applications  with  gem ensuring that the correct memory syn‐
116       chronization occurs.
117
118       GEM provides simple mechanisms to manage graphics data and control exe‐
119       cution  flow within the linux DRM subsystem. However, GEM is not a com‐
120       plete framework that is fully driver independent. Instead, if  provides
121       many  functions  that  are shared between many drivers, but each driver
122       has  to  implement  most  of  memory-management  with  driver-dependent
123       ioctls.  This  manpage  tries  to describe the semantics (and if it ap‐
124       plies, the syntax) that is shared between all drivers that use GEM.
125
126       All GEM APIs are defined as ioctl(2) on the DRM file descriptor. An ap‐
127       plication  must  be  authorized  via  drmAuthMagic(3)  to  the  current
128       DRM-Master to access the GEM subsystem. A driver that does not  support
129       GEM will return ENODEV for all these ioctls. Invalid object handles re‐
130       turn EINVAL and invalid object names return ENOENT.
131
132       Gem provides explicit memory management primitives.  System  pages  are
133       allocated when the object is created, either as the fundamental storage
134       for hardware where system memory is used by the graphics processor  di‐
135       rectly, or as backing store for graphics-processor resident memory.
136
137       Objects  are  referenced  from user-space using handles. These are, for
138       all intents and purposes, equivalent to file descriptors but avoid  the
139       overhead.   Newer  kernel drivers also support the drm-prime (7) infra‐
140       structure which can return real file-descriptor for  GEM-handles  using
141       the  linux  DMA-BUF  API.  Objects may be published with a name so that
142       other applications and processes can  access  them.  The  name  remains
143       valid  as long as the object exists.  GEM-objects are reference counted
144       in the kernel. The object is  only  destroyed  when  all  handles  from
145       user-space were closed.
146
147       GEM-buffers  cannot be created with a generic API. Each driver provides
148       its own API to create GEM-buffers. See for example DRM_I915_GEM_CREATE,
149       DRM_NOUVEAU_GEM_NEW  or DRM_RADEON_GEM_CREATE. Each of these ioctls re‐
150       turns a GEM-handle that can be passed to different generic ioctls.  The
151       libgbm  library  from  the  mesa3D  distribution  tries  to  provide  a
152       driver-independent API to create GBM buffers and retrieve a  GBM-handle
153       to them.  It allows to create buffers for different use-cases including
154       scanout, rendering, cursors and CPU-access. See the libgbm library  for
155       more information or look at the driver-dependent man-pages (for example
156       drm-intel(7) or drm-radeon(7)).
157
158       GEM-buffers can be closed with the DRM_IOCTL_GEM_CLOSE ioctl. It  takes
159       as argument a structure of type struct drm_gem_close:
160
161          struct drm_gem_close {
162              __u32 handle;
163              __u32 pad;
164          };
165
166       The  handle  field is the GEM-handle to be closed. The pad field is un‐
167       used padding. It must be zeroed. After this call the GEM handle  cannot
168       be  used  by this process anymore and may be reused for new GEM objects
169       by the GEM API.
170
171       If you want to share GEM-objects between different processes,  you  can
172       create  a name for them and pass this name to other processes which can
173       then open this GEM-object. Names are currently 32-bit integer  IDs  and
174       have  no special protection. That is, if you put a name on your GEM-ob‐
175       ject, every other client that has access to the DRM device and  is  au‐
176       thenticated  via  drmAuthMagic(3)  to the current DRM-Master, can guess
177       the  name  and  open  or  access  the  GEM-object.  If  you  want  more
178       fine-grained  access  control,  you can use the new drm-prime(7) API to
179       retrieve file-descriptors for GEM-handles.  To  create  a  name  for  a
180       GEM-handle, you use the DRM_IOCTL_GEM_FLINK ioctl. It takes as argument
181       a structure of type struct drm_gem_flink:
182
183          struct drm_gem_flink {
184              __u32 handle;
185              __u32 name;
186          };
187
188       You have to put your handle into the handle  field.  After  completion,
189       the kernel has put the new unique name into the name field. You can now
190       pass this name to other processes which can then import the  name  with
191       the  DRM_IOCTL_GEM_OPEN ioctl. It takes as argument a structure of type
192       struct drm_gem_open:
193
194          struct drm_gem_open {
195              __u32 name;
196
197              __u32 handle;
198              __u32 size;
199          };
200
201       You have to fill in the name field with the name of the GEM-object that
202       you  want  to  open. The kernel will fill in the handle and size fields
203       with the new handle and size of the GEM-object. You can now access  the
204       GEM-object via the handle as if you created it with the GEM API.
205
206       Besides  generic  buffer  management,  the GEM API does not provide any
207       generic access. Each driver implements its own functionality on top  of
208       this API. This includes execution-buffers, GTT management, context cre‐
209       ation, CPU access, GPU I/O and  more.  The  next  higher-level  API  is
210       OpenGL.  So  if  you  want to use more GPU features, you should use the
211       mesa3D library to create OpenGL contexts on DRM devices. This does  not
212       require  any windowing-system like X11, but can also be done on raw DRM
213       devices. However, this is beyond the scope of this  man-page.  You  may
214       have  a look at other mesa3D man pages, including libgbm and libEGL. 2D
215       software-rendering (rendering with the CPU) can be  achieved  with  the
216       dumb-buffer-API  in  a  driver-independent  fashion, however, for hard‐
217       ware-accelerated 2D or 3D rendering you must use OpenGL. Any other  API
218       that  tries  to  abstract  the  driver-internals  to  access GEM-execu‐
219       tion-buffers and other GPU internals, would simply reinvent  OpenGL  so
220       it  is  not  provided.  But if you need more detailed information for a
221       specific driver, you may have a look into the driver-manpages,  includ‐
222       ing   drm-intel(7),  drm-radeon(7)  and  drm-nouveau(7).  However,  the
223       drm-prime(7) infrastructure and the generic GEM API as  described  here
224       allow  display-managers  to  handle graphics-buffers and render-clients
225       without any deeper knowledge of the GPU that is used. Moreover, it  al‐
226       lows to move objects between GPUs and implement complex display-servers
227       that don't do any rendering on their own. See its man-page for more in‐
228       formation.
229

EXAMPLES

231       This section includes examples for basic memory-management tasks.
232
233   Dumb-Buffers
234       This  examples  shows  how  to create a dumb-buffer via the generic DRM
235       API.  This is  driver-independent  (as  long  as  the  driver  supports
236       dumb-buffers)  and  provides memory-mapped buffers that can be used for
237       scanout. This example  creates  a  full-HD  1920x1080  buffer  with  32
238       bits-per-pixel  and  a color-depth of 24 bits. The buffer is then bound
239       to a framebuffer which can be used for scanout with the  KMS  API  (see
240       drm-kms(7)).
241
242          struct drm_mode_create_dumb creq;
243          struct drm_mode_destroy_dumb dreq;
244          struct drm_mode_map_dumb mreq;
245          uint32_t fb;
246          int ret;
247          void *map;
248
249          /* create dumb buffer */
250          memset(&creq, 0, sizeof(creq));
251          creq.width = 1920;
252          creq.height = 1080;
253          creq.bpp = 32;
254          ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
255          if (ret < 0) {
256              /* buffer creation failed; see "errno" for more error codes */
257              ...
258          }
259          /* creq.pitch, creq.handle and creq.size are filled by this ioctl with
260           * the requested values and can be used now. */
261
262          /* create framebuffer object for the dumb-buffer */
263          ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb);
264          if (ret) {
265              /* frame buffer creation failed; see "errno" */
266              ...
267          }
268          /* the framebuffer "fb" can now used for scanout with KMS */
269
270          /* prepare buffer for memory mapping */
271          memset(&mreq, 0, sizeof(mreq));
272          mreq.handle = creq.handle;
273          ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
274          if (ret) {
275              /* DRM buffer preparation failed; see "errno" */
276              ...
277          }
278          /* mreq.offset now contains the new offset that can be used with mmap() */
279
280          /* perform actual memory mapping */
281          map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
282          if (map == MAP_FAILED) {
283              /* memory-mapping failed; see "errno" */
284              ...
285          }
286
287          /* clear the framebuffer to 0 */
288          memset(map, 0, creq.size);
289

REPORTING BUGS

291       Bugs      in      this     manual     should     be     reported     to
292       https://gitlab.freedesktop.org/mesa/drm/-/issues
293

SEE ALSO

295       drm(7), drm-kms(7), drm-prime(7), drmAvailable(3), drmOpen(3),  drm-in‐
296       tel(7), drm-radeon(7), drm-nouveau(7)
297
298
299
300
301                                September 2012                   DRM-MEMORY(7)
Impressum