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

Reply via email to