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