On Sun, 23 Sep 2012 16:40:07 +0200 David Herrmann <dh.herrmann at googlemail.com> wrote:
> The drm-memory man-page (aliased as drm-gem, drm-mm and drm-ttm) describes > the high-level overview of different memory-management frameworks used in > the DRM subsystem. It is really targeted at driver-independent semantics > (and where it applies, syntax). It links to all other man-pages if more > driver-dependent information is needed. > > Signed-off-by: David Herrmann <dh.herrmann at googlemail.com> > --- > man/Makefile.am | 4 + > man/drm-gem.7 | 1 + > man/drm-memory.7 | 412 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > man/drm-mm.7 | 1 + > man/drm-ttm.7 | 1 + > 5 files changed, 419 insertions(+) > create mode 100644 man/drm-gem.7 > create mode 100644 man/drm-memory.7 > create mode 100644 man/drm-mm.7 > create mode 100644 man/drm-ttm.7 > > diff --git a/man/Makefile.am b/man/Makefile.am > index 7ce7ac4..ded3b4a 100644 > --- a/man/Makefile.am > +++ b/man/Makefile.am > @@ -1,6 +1,10 @@ > man_MANS = \ > drm.7 \ > drm-kms.7 \ > + drm-memory.7 \ > + drm-mm.7 \ > + drm-gem.7 \ > + drm-ttm.7 \ > drmAvailable.3 \ > drmHandleEvent.3 \ > drmModeGetResources.3 > diff --git a/man/drm-gem.7 b/man/drm-gem.7 > new file mode 100644 > index 0000000..258b5a3 > --- /dev/null > +++ b/man/drm-gem.7 > @@ -0,0 +1 @@ > +.so man7/drm-memory.7 > diff --git a/man/drm-memory.7 b/man/drm-memory.7 > new file mode 100644 > index 0000000..1eff38a > --- /dev/null > +++ b/man/drm-memory.7 > @@ -0,0 +1,412 @@ > +.\" > +.\" Written 2012 by David Herrmann > +.\" Dedicated to the Public Domain > +.\" > +.TH "DRM-MEMORY" 7 "September 2012" "libdrm" "Direct Rendering Manager" > +.SH NAME > +DRM-Memory \- DRM Memory Management > + > +.SH SYNOPSIS > +.B #include <xf86drm.h> > + > +.SH DESCRIPTION > +Many modern high-end GPUs come with their own memory managers. They even > include > +several different caches that need to be synchronized during access. > Textures, > +framebuffers, command buffers and more need to be stored in memory that can > be > +accessed quickly by the GPU. Therefore, memory management on GPUs is highly > +driver\- and hardware\-dependent. > + > +However, there are several frameworks in the kernel that are used by more > than > +one driver. These can be used for trivial mode-setting without requiring > +driver-dependent code. But for hardware-accelerated rendering you need to > read > +the manual pages for the driver you want to work with. > + > +.SS Dumb-Buffers > +Almost all in-kernel DRM hardware drivers support an API called > +.BR "Dumb-Buffers" "." > +This API allows to create buffers of arbitrary size that can be used for > +scanout. These buffers can be memory mapped via > +.BR mmap (2) > +so you can render into them on the CPU. However, GPU access to these buffers > is > +often not possible. Therefore, they are fine for simple tasks but not > suitable > +for complex compositions and renderings. > + > +The > +.B DRM_IOCTL_MODE_CREATE_DUMB > +ioctl can be used to create a dumb buffer. The kernel will return a 32bit > handle > +that can be used to manage the buffer with the DRM API. You can create > +framebuffers with > +.BR drmModeAddFB (3) > +and use it for mode-setting and scanout. > +.br > +To access the buffer, you first need to retrieve the offset of the buffer. > The > +.B DRM_IOCTL_MODE_MAP_DUMB > +ioctl requests the DRM subsystem to prepare the buffer for memory-mapping and > +returns a fake-offset that can be used with > +.BR mmap "(2)." > + > +The > +.B DRM_IOCTL_MODE_CREATE_DUMB > +ioctl takes as argument a structure of type > +.IR "struct drm_mode_create_dumb" : > + > +.in +4n > +.nf > +struct drm_mode_create_dumb { > + __u32 height; > + __u32 width; > + __u32 bpp; > + __u32 flags; > + > + __u32 handle; > + __u32 pitch; > + __u64 size; > +}; > +.fi > +.in > + > +The fields > +.IR "height" ", " "width" ", " "bpp" " and " "flags" > +have to be provided by the caller. The other fields are filled by the kernel > +with the return values. > +.IR "height" " and " "width" > +are the dimensions of the rectangular buffer that is created. > +.I "bpp" > +is the number of bits-per-pixel and must be a multiple of > +.IR 8 "." > +You most commonly want to pass > +.I 32 > +here. The > +.I "flags" > +field is currently unused and must be zeroed. Different flags to modify the > +behavior may be added in the future. > +.br > +After calling the ioctl, the > +.IR "handle" ", " "pitch" " and " "size" > +fields are filled by the kernel. > +.I "handle" > +is a 32bit gem handle that identifies the buffer. This is used by several > other > +calls that take a gem-handle or memory-buffer as argument. The > +.I "pitch" > +field is the > +.IR pitch " or " stride > +of the new buffer. Most drivers use 32bit or 64bit aligned stride-values. The > +.I "size" > +field contains the absolute size in bytes of the buffer. This can normally > also > +be computed with > +"(height * pitch + width) * bpp / 4". > + > +To prepare the buffer for > +.BR mmap (2) > +you need to use the > +.B DRM_IOCTL_MODE_MAP_DUMB > +ioctl. It takes as argument a structure of type > +.IR "struct drm_mode_map_dumb" : > + > +.in +4n > +.nf > +struct drm_mode_map_dumb { > + __u32 handle; > + __u32 pad; > + > + __u64 offset; > +}; > +.fi > +.in > + > +You need to put the gem-handle that was previously retrieved via > +.B DRM_IOCTL_MODE_CREATE_DUMB > +into the > +.I "handle" > +field. The > +.I "pad" > +field is unused padding and must be zeroed. After completion, the > +.I offset > +field will contain an offset that can be used with > +.BR mmap (2) > +on the DRM file-descriptor. > + > +If you don't need your dumb-buffer, anymore, you have to destroy it with > +.BR DRM_IOCTL_MODE_DESTROY_DUMB "." > +If you close the DRM file-descriptor, all open dumb-buffers are automatically > +destroyed. > +.br > +This ioctl takes as argument a structure of type > +.IR "struct drm_mode_destroy_dumb" : > + > +.in +4n > +.nf > +struct drm_mode_destroy_dumb { > + __u32 handle; > +}; > +.fi > +.in > + > +You only need to put your handle into the > +.I handle > +field. After this call, the handle is invalid and may be reused for new > buffers > +by the dumb-API. > + > +.SS TTM > +.B TTM > +stands for > +.B Translation Table Manager > +and is another generic memory-manager provided by the kernel. Only the radeon > +driver uses it. See the radeon manpages for more information on > +memory-management with radeon and TTM. > + > +.SS GEM > +.B GEM > +stands for > +.B Graphics Execution Manager > +and is a generic DRM memory-management framework in the kernel, that is used > by > +many different drivers. Gem is designed to manage graphics memory, control > +access to the graphics device execution context and handle essentially NUMA > +environment unique to modern graphics hardware. Gem allows multiple > applications > +to share graphics device resources without the need to constantly reload the > +entire graphics card. Data may be shared between multiple applications with > gem > +ensuring that the correct memory synchronization occurs. > + > +Gem provides simple mechanisms to manage graphics data and control execution > +flow within the linux DRM subsystem. However, gem is not a complete framework > +that is fully driver independent. Instead, if provides many functions that > are > +shared between many drivers, but each driver has to implement most of > +memory-management with driver-dependent ioctls. This manpage tries to > describe > +the semantics (and if it applies, the syntax) that is shared between all > drivers > +that use gem. > + > +All GEM APIs are defined as > +.BR ioctl (2) > +on the DRM file descriptor. An application must be authorized via > +.BR drmAuthMagic (2) > +to the current DRM-Master to access the GEM subsystem. A driver that does not > +support gem will return > +.I ENODEV > +for all these ioctls. Invalid object handles return > +.I EINVAL > +and invalid object names return > +.IR ENOENT "." > + > +Gem provides explicit memory management primitives. System pages are > allocated > +when the object is created, either as the fundamental storage for hardware > where > +system memory is used by the graphics processor directly, or as backing store > +for graphics-processor resident memory. > + > +Objects are referenced from user-space using handles. These are, for all > intents > +and purposes, equivalent to file descriptors but avoid the overhead. Newer > +kernel drivers also support the > +.BR drm-prime (7) > +infrastructure which can return real file-descriptor for gem-handles using > the > +linux dma-buf API. > +.br > +Objects may be published with a name so that other applications and processes > +can access them. The name remains valid as long as the object exists. > +.br > +Gem-objects are reference counted in the kernel. The object is only destroyed > +when all handles from user-space were closed. > + > +Gem-buffers cannot be created with a generic API. Each driver provides its > own > +API to create gem-buffers. See for example > +.BR DRM_I915_GEM_CREATE ", " DRM_NOUVEAU_GEM_NEW " or " > DRM_RADEON_GEM_CREATE . > +Each of these ioctls returns a gem-handle that can be passed to different > +generic ioctls. > +.br > +The > +.I libgbm > +library from the > +.I mesa3D > +distribution tries to provide a driver-independent API to create gbm buffers > and > +retrieve a gbm-handle to them. It allows to create buffers for different > +use-cases including scanout, rendering, cursors and CPU-access. See the > libgbm > +library for more information or look at the driver-dependent man-pages > +.RI "(for example " drm-intel "(7) or " drm-radeon "(7))." > + > +Gem-buffers can be closed with the > +.B DRM_IOCTL_GEM_CLOSE > +ioctl. It takes as argument a structure of type > +.IR "struct drm_gem_close" : > + > +.in +4n > +.nf > +struct drm_gem_close { > + __u32 handle; > + __u32 pad; > +}; > +.fi > +.in > + > +The > +.I handle > +field is the gem-handle to be closed. The > +.I pad > +field is unused padding. It must be zeroed. After this call the gem handle > +cannot be used by this process anymore and may be reused for new gem objects > by > +the gem API. > + > +If you want to share gem-objects between different processes, you can create > a > +name for them and pass this name to other processes which can then open this > +gem-object. Names are currently 32bit integer IDs and have no special > +protection. That is, if you put a name on your gem-object, every other client > +that has access to the DRM device and is authenticated via > +.BR drmAuthMagic (3) > +to the current DRM-Master, can > +.I guess > +the name and open or access the gem-object. If you want more fine-grained > access > +control, you can use the new > +.BR drm-prime (7) > +API to retrieve file-descriptors for gem-handles. > +.br > +To create a name for a gem-handle, you use the > +.B DRM_IOCTL_GEM_FLINK > +ioctl. It takes as argument a structure of type > +.IR "struct drm_gem_flink" : > + > +.in +4n > +.nf > +struct drm_gem_flink { > + __u32 handle; > + __u32 name; > +}; > +.fi > +.in > + > +You have to put your handle into the > +.I handle > +field. After completion, the kernel has put the new unique name into the > +.I name > +field. You can now pass this name to other processes which can then import > the > +name with the > +.B DRM_IOCTL_GEM_OPEN > +ioctl. It takes as argument a structure of type > +.IR "struct drm_gem_open" : > + > +.in +4n > +.nf > +struct drm_gem_open { > + __u32 name; > + > + __u32 handle; > + __u32 size; > +}; > +.fi > +.in > + > +You have to fill in the > +.I name > +field with the name of the gem-object that you want to open. The kernel will > +fill in the > +.I handle > +and > +.I size > +fields with the new handle and size of the gem-object. You can now access the > +gem-object via the handle as if you created it with the gem API. > + > +Besides generic buffer management, the GEM API does not provide any generic > +access. Each driver implements its own functionality on top of this API. This > +includes execution-buffers, GTT management, context creation, CPU access, GPU > +I/O and more. > +.br > +The next higher-level API is > +.BR OpenGL . > +So if you want to use more GPU features, you should use the > +.I mesa3D > +library to create OpenGL contexts on DRM devices. This does > +.I not > +require any windowing-system like X11, but can also be done on raw DRM > devices. > +However, this is beyond the scope of this man-page. You may have a look at > other > +mesa3D manpages, including libgbm and libEGL. > +2D software-rendering (rendering with the CPU) can be achieved with the > +dumb-buffer-API in a driver-independent fashion, however, for > +hardware-accelerated 2D or 3D rendering you must use OpenGL. Any other API > that > +tries to abstract the driver-internals to access GEM-execution-buffers and > other > +GPU internals, would simply reinvent OpenGL so it is not provided. But if you > +need more detailed information for a specific driver, you may have a look > into > +the driver-manpages, including > +.BR drm-intel "(7), " drm-radeon "(7) and " drm-nouveau (7). > +.br > +However, the > +.BR drm-prime (7) > +infrastructure and the generic gem API as described here allow > display-managers > +to handle graphics-buffers and render-clients without any deeper knowledge of > +the GPU that is used. Moreover, it allows to move objects between GPUs and > +implement complex display-servers that don't do any rendering on their own. > See > +its man-page for more information. > + > +.SH EXAMPLES > +This section includes examples for basic memory-management tasks. > + > +.SS Dumb-Buffers > +This examples shows how to create a dumb-buffer via the generic DRM API. > This is > +driver-independent (as long as the driver supports dumb-buffers) and provides > +memory-mapped buffers that can be used for scanout. > +.br > +This example creates a full-HD 1920x1080 buffer with 32 bits-per-pixel and a > +color-depth of 24 bits. The buffer is then bound to a framebuffer which can > be > +used for scanout with the KMS API > +.RB "(see " drm-kms "(7))." > + > +.in +4n > +.nf > + struct drm_mode_create_dumb creq; > + struct drm_mode_destroy_dumb dreq; > + struct drm_mode_map_dumb mreq; > + uint32_t fb; > + int ret; > + void *map; > + > + /* create dumb buffer */ > + memset(&creq, 0, sizeof(creq)); > + creq.width = 1920; > + creq.height = 1080; > + creq.bpp = 32; > + ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); > + if (ret < 0) { > + /* buffer creation failed; see "errno" for more error codes */ > + ... > + } > + /* creq.pitch, creq.handle and creq.size are filled by this ioctl with > + * the requested values and can be used now. */ > + > + /* create framebuffer object for the dumb-buffer */ > + ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, > &fb); > + if (ret) { > + /* frame buffer creation failed; see "errno" */ > + ... > + } > + /* the framebuffer "fb" can now used for scanout with KMS */ > + > + /* prepare buffer for memory mapping */ > + memset(&mreq, 0, sizeof(mreq)); > + mreq.handle = creq.handle; > + ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); > + if (ret) { > + /* DRM buffer preparation failed; see "errno" */ > + ... > + } > + /* mreq.offset now contains the new offset that can be used with mmap() > */ > + > + /* perform actual memory mapping */ > + map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, > mreq.offset); > + if (map == MAP_FAILED) { > + /* memory-mapping failed; see "errno" */ > + ... > + } > + > + /* clear the framebuffer to 0 */ > + memset(map, 0, creq.size); > +.fi > +.in > + > +.SH REPORTING BUGS > +Bugs in this manual should be reported to http://bugs.freedesktop.org under > +the "Mesa" product, with "Other" or "libdrm" as the component. > + > +.SH "SEE ALSO" > +.BR drm (7), > +.BR drm-kms (7), > +.BR drmAvailable (3), > +.BR drmOpen (3), > +.BR drm-intel (7), > +.BR drm-radeon (7), > +.BR drm-nouveau (7), > +.BR drm-prime (7) > diff --git a/man/drm-mm.7 b/man/drm-mm.7 > new file mode 100644 > index 0000000..258b5a3 > --- /dev/null > +++ b/man/drm-mm.7 > @@ -0,0 +1 @@ > +.so man7/drm-memory.7 > diff --git a/man/drm-ttm.7 b/man/drm-ttm.7 > new file mode 100644 > index 0000000..258b5a3 > --- /dev/null > +++ b/man/drm-ttm.7 > @@ -0,0 +1 @@ > +.so man7/drm-memory.7 Heh, this one highlights the lack of documentation we have for other libs like Mesa and libgbm. :) Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org> -- Jesse Barnes, Intel Open Source Technology Center