diff options
| -rw-r--r-- | man/Makefile.am | 9 | ||||
| -rw-r--r-- | man/drm-memory.xml | 430 | 
2 files changed, 437 insertions, 2 deletions
| diff --git a/man/Makefile.am b/man/Makefile.am index b393072a..32acd076 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -7,10 +7,14 @@  MANPAGES = \  	drm.7 \  	drm-kms.7 \ +	drm-memory.7 \  	drmAvailable.3 \  	drmHandleEvent.3 \  	drmModeGetResources.3 -MANPAGES_ALIASES = +MANPAGES_ALIASES = \ +	drm-mm.7 \ +	drm-gem.7 \ +	drm-ttm.7  XML_FILES = \  	${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubs %.7,%.xml,$(MANPAGES)}}}} @@ -32,7 +36,8 @@ XSLTPROC_FLAGS = \  XSLTPROC_PROCESS_MAN = \  	$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ -	$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< +	$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< && \ +	$(SED) -i -e 's/^\.so \(.*\)\.\(.\)$$/\.so man\2\/\1\.\2/' $(MANPAGES_ALIASES)  %.1: %.xml  	$(XSLTPROC_PROCESS_MAN) diff --git a/man/drm-memory.xml b/man/drm-memory.xml new file mode 100644 index 00000000..6b4f0759 --- /dev/null +++ b/man/drm-memory.xml @@ -0,0 +1,430 @@ +<?xml version='1.0'?> <!--*-nxml-*--> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" +          "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> + +<!-- +  Written 2012 by David Herrmann <dh.herrmann@googlemail.com> +  Dedicated to the Public Domain +--> + +<refentry id="drm-memory"> +  <refentryinfo> +    <title>Direct Rendering Manager</title> +    <productname>libdrm</productname> +    <date>September 2012</date> +    <authorgroup> +      <author> +        <contrib>Developer</contrib> +        <firstname>David</firstname> +        <surname>Herrmann</surname> +        <email>dh.herrmann@googlemail.com</email> +      </author> +    </authorgroup> +  </refentryinfo> + +  <refmeta> +    <refentrytitle>drm-memory</refentrytitle> +    <manvolnum>7</manvolnum> +  </refmeta> + +  <refnamediv> +    <refname>drm-memory</refname> +    <refname>drm-mm</refname> +    <refname>drm-gem</refname> +    <refname>drm-ttm</refname> +    <refpurpose>DRM Memory Management</refpurpose> +  </refnamediv> + +  <refsynopsisdiv> +    <funcsynopsis> +      <funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo> +    </funcsynopsis> +  </refsynopsisdiv> + +  <refsect1> +    <title>Description</title> +      <para>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.</para> + +      <para>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.</para> + +    <refsect2> +      <title>Dumb-Buffers</title> +      <para>Almost all in-kernel DRM hardware drivers support an API called +            <emphasis>Dumb-Buffers</emphasis>. This API allows to create buffers +            of arbitrary size that can be used for scanout. These buffers can be +            memory mapped via +            <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> +            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.</para> + +      <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> 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 +            <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry> +            and use it for mode-setting and scanout. To access the buffer, you +            first need to retrieve the offset of the buffer. The +            <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> ioctl requests the DRM +            subsystem to prepare the buffer for memory-mapping and returns a +            fake-offset that can be used with +            <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para> + +      <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl takes as +            argument a structure of type +            <structname>struct drm_mode_create_dumb</structname>: + +<programlisting> +struct drm_mode_create_dumb { +	__u32 height; +	__u32 width; +	__u32 bpp; +	__u32 flags; + +	__u32 handle; +	__u32 pitch; +	__u64 size; +}; +</programlisting> + +            The fields <structfield>height</structfield>, +            <structfield>width</structfield>, <structfield>bpp</structfield> and +            <structfield>flags</structfield> have to be provided by the caller. +            The other fields are filled by the kernel with the return values. +            <structfield>height</structfield> and +            <structfield>width</structfield> are the dimensions of the +            rectangular buffer that is created. <structfield>bpp</structfield> +            is the number of bits-per-pixel and must be a multiple of +            <literal>8</literal>. You most commonly want to pass +            <literal>32</literal> here. The <structfield>flags</structfield> +            field is currently unused and must be zeroed. Different flags to +            modify the behavior may be added in the future. After calling the +            ioctl, the <structfield>handle</structfield>, +            <structfield>pitch</structfield> and <structfield>size</structfield> +            fields are filled by the kernel. <structfield>handle</structfield> +            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 <structfield>pitch</structfield> field is the +            pitch (or stride) of the new buffer. Most drivers use 32bit or 64bit +            aligned stride-values. The <structfield>size</structfield> field +            contains the absolute size in bytes of the buffer. This can normally +            also be computed with +            <emphasis>(height * pitch + width) * bpp / 4</emphasis>.</para> + +      <para>To prepare the buffer for +            <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> +            you need to use the <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> +            ioctl. It takes as argument a structure of type +            <structname>struct drm_mode_map_dumb</structname>: + +<programlisting> +struct drm_mode_map_dumb { +	__u32 handle; +	__u32 pad; + +	__u64 offset; +}; +</programlisting> + +            You need to put the gem-handle that was previously retrieved via +            <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> into the +            <structfield>handle</structfield> field. The +            <structfield>pad</structfield> field is unused padding and must be +            zeroed. After completion, the <structfield>offset</structfield> +            field will contain an offset that can be used with +            <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> +            on the DRM file-descriptor.</para> + +      <para>If you don't need your dumb-buffer, anymore, you have to destroy it +            with <constant>DRM_IOCTL_MODE_DESTROY_DUMB</constant>. If you close +            the DRM file-descriptor, all open dumb-buffers are automatically +            destroyed. This ioctl takes as argument a structure of type +            <structname>struct drm_mode_destroy_dumb</structname>: + +<programlisting> +struct drm_mode_destroy_dumb { +	__u32 handle; +}; +</programlisting> + +            You only need to put your handle into the +            <structfield>handle</structfield> field. After this call, the handle +            is invalid and may be reused for new buffers by the dumb-API.</para> + +    </refsect2> + +    <refsect2> +      <title>TTM</title> +      <para><emphasis>TTM</emphasis> stands for +            <emphasis>Translation Table Manager</emphasis> and is a generic +            memory-manager provided by the kernel. It does not provide a common +            user-space API so you need to look at each driver interface if you +            want to use it. See for instance the radeon manpages for more +            information on memory-management with radeon and TTM.</para> +    </refsect2> + +    <refsect2> +      <title>GEM</title> +      <para><emphasis>GEM</emphasis> stands for +            <emphasis>Graphics Execution Manager</emphasis> 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.</para> + +      <para>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.</para> + +      <para>All GEM APIs are defined as +            <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> +            on the DRM file descriptor. An application must be authorized via +            <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry> +            to the current DRM-Master to access the GEM subsystem. A driver that +            does not support gem will return <constant>ENODEV</constant> for all +            these ioctls. Invalid object handles return +            <constant>EINVAL</constant> and invalid object names return +            <constant>ENOENT</constant>.</para> + +      <para>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.</para> + +      <para>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 +            <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> +            infrastructure which can return real file-descriptor for gem-handles +            using the linux dma-buf API. 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. Gem-objects are +            reference counted in the kernel. The object is only destroyed when +            all handles from user-space were closed.</para> + +      <para>Gem-buffers cannot be created with a generic API. Each driver +            provides its own API to create gem-buffers. See for example +            <constant>DRM_I915_GEM_CREATE</constant>, +            <constant>DRM_NOUVEAU_GEM_NEW</constant> or +            <constant>DRM_RADEON_GEM_CREATE</constant>. Each of these ioctls +            returns a gem-handle that can be passed to different generic ioctls. +            The <emphasis>libgbm</emphasis> library from the +            <emphasis>mesa3D</emphasis> 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 (for example +            <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry> +            or +            <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para> + +      <para>Gem-buffers can be closed with the +            <constant>DRM_IOCTL_GEM_CLOSE</constant> ioctl. It takes as argument +            a structure of type <structname>struct drm_gem_close</structname>: + +<programlisting> +struct drm_gem_close { +	__u32 handle; +	__u32 pad; +}; +</programlisting> + +            The <structfield>handle</structfield> field is the gem-handle to be +            closed. The <structfield>pad</structfield> 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.</para> + +      <para>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 +            <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry> +            to the current DRM-Master, can <emphasis>guess</emphasis> the name +            and open or access the gem-object. If you want more fine-grained +            access control, you can use the new +            <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> +            API to retrieve file-descriptors for gem-handles. To create a name +            for a gem-handle, you use the +            <constant>DRM_IOCTL_GEM_FLINK</constant> ioctl. It takes as argument +            a structure of type <structname>struct drm_gem_flink</structname>: + +<programlisting> +struct drm_gem_flink { +	__u32 handle; +	__u32 name; +}; +</programlisting> + +            You have to put your handle into the +            <structfield>handle</structfield> field. After completion, the +            kernel has put the new unique name into the +            <structfield>name</structfield> field. You can now pass this name to +            other processes which can then import the name with the +            <constant>DRM_IOCTL_GEM_OPEN</constant> ioctl. It takes as argument +            a structure of type <structname>struct drm_gem_open</structname>: + +<programlisting> +struct drm_gem_open { +	__u32 name; + +	__u32 handle; +	__u32 size; +}; +</programlisting> + +            You have to fill in the <structfield>name</structfield> field with +            the name of the gem-object that you want to open. The kernel will +            fill in the <structfield>handle</structfield> and +            <structfield>size</structfield> 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.</para> + +      <para>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. The next +            higher-level API is <emphasis>OpenGL</emphasis>. So if you want to +            use more GPU features, you should use the +            <emphasis>mesa3D</emphasis> library to create OpenGL contexts on DRM +            devices. This does <emphasis>not</emphasis> 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 +            <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +            <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry> +            and +            <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>. +            However, the +            <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> +            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.</para> +    </refsect2> +  </refsect1> + +  <refsect1> +    <title>Examples</title> +      <para>This section includes examples for basic memory-management +            tasks.</para> + +    <refsect2> +      <title>Dumb-Buffers</title> +        <para>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. 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 (see +              <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para> + +<programlisting> +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); +</programlisting> + +    </refsect2> + +  </refsect1> + +  <refsect1> +    <title>Reporting Bugs</title> +    <para>Bugs in this manual should be reported to +          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or +          "libdrm" as the component.</para> +  </refsect1> + +  <refsect1> +    <title>See Also</title> +    <para> +      <citerefentry><refentrytitle>drm</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>, +      <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry> +    </para> +  </refsect1> +</refentry> | 
