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