.gitignore | 4 Makefile.am | 2 configure.ac | 26 -- intel/intel_bufmgr_gem.c | 10 - libkms/intel.c | 1 libkms/linux.c | 2 libkms/nouveau.c | 1 man/Makefile.am | 65 +++++- man/drm-kms.xml | 342 ++++++++++++++++++++++++++++++++++ man/drm-memory.xml | 430 +++++++++++++++++++++++++++++++++++++++++++ man/drm.xml | 137 +++++++++++++ man/drmAvailable.man | 25 -- man/drmAvailable.xml | 75 +++++++ man/drmHandleEvent.man | 45 ---- man/drmHandleEvent.xml | 102 ++++++++++ man/drmModeGetResources.man | 79 ------- man/drmModeGetResources.xml | 139 +++++++++++++ nouveau/abi16.c | 28 ++ nouveau/libdrm_nouveau.pc.in | 2 nouveau/nouveau.c | 3 nouveau/nouveau.h | 16 + nouveau/private.h | 1 nouveau/pushbuf.c | 8 radeon/r600_pci_ids.h | 1 radeon/radeon_bo_gem.c | 16 + 25 files changed, 1363 insertions(+), 197 deletions(-)
New commits: commit 007bff7a034741dcf9d1716583f91fc4453d4112 Author: Maarten Lankhorst <[email protected]> Date: Wed Jan 16 13:06:52 2013 +0100 configure.ac: bump version to 2.4.41 for release diff --git a/configure.ac b/configure.ac index 0e6db86..10cc9a4 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.63]) AC_INIT([libdrm], - [2.4.40], + [2.4.41], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], [libdrm]) commit c41b494c47f8e514e69cb8c2f2ace41d5fa17c94 Author: Ben Skeggs <[email protected]> Date: Fri Nov 23 12:40:30 2012 +1000 nouveau: expose channel engine selection on kepler chipsets v2: Take Maarten Lankhorst's suggestion of nesting the struct to prevent sizeof() issues due to padding on older revisions. Signed-off-by: Ben Skeggs <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]> diff --git a/nouveau/abi16.c b/nouveau/abi16.c index a67fbc1..f34175e 100644 --- a/nouveau/abi16.c +++ b/nouveau/abi16.c @@ -24,9 +24,11 @@ #include <stdlib.h> #include <stdint.h> +#include <stddef.h> #include "private.h" + int abi16_chan_nv04(struct nouveau_object *obj) { @@ -70,6 +72,32 @@ abi16_chan_nvc0(struct nouveau_object *obj) } int +abi16_chan_nve0(struct nouveau_object *obj) +{ + struct nouveau_device *dev = (struct nouveau_device *)obj->parent; + struct drm_nouveau_channel_alloc req = {}; + struct nve0_fifo *nve0 = obj->data; + int ret; + + if (obj->length > offsetof(struct nve0_fifo, engine)) { + req.fb_ctxdma_handle = 0xffffffff; + req.tt_ctxdma_handle = nve0->engine; + } + + ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, + &req, sizeof(req)); + if (ret) + return ret; + + nve0->base.channel = req.channel; + nve0->base.pushbuf = req.pushbuf_domains; + nve0->notify = req.notifier_handle; + nve0->base.object->handle = req.channel; + nve0->base.object->length = sizeof(*nve0); + return 0; +} + +int abi16_engobj(struct nouveau_object *obj) { struct drm_nouveau_grobj_alloc req = { diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index 940d933..9b32e31 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c @@ -247,7 +247,10 @@ nouveau_object_new(struct nouveau_object *parent, uint64_t handle, if (dev->chipset < 0xc0) ret = abi16_chan_nv04(obj); else + if (dev->chipset < 0xe0) ret = abi16_chan_nvc0(obj); + else + ret = abi16_chan_nve0(obj); } break; default: diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h index c42eea7..a55e2b0 100644 --- a/nouveau/nouveau.h +++ b/nouveau/nouveau.h @@ -41,6 +41,22 @@ struct nvc0_fifo { uint32_t notify; }; +#define NVE0_FIFO_ENGINE_GR 0x00000001 +#define NVE0_FIFO_ENGINE_VP 0x00000002 +#define NVE0_FIFO_ENGINE_PPP 0x00000004 +#define NVE0_FIFO_ENGINE_BSP 0x00000008 +#define NVE0_FIFO_ENGINE_CE0 0x00000010 +#define NVE0_FIFO_ENGINE_CE1 0x00000020 +#define NVE0_FIFO_ENGINE_ENC 0x00000040 + +struct nve0_fifo { + struct { + struct nouveau_fifo base; + uint32_t notify; + }; + uint32_t engine; +}; + struct nv04_notify { struct nouveau_object *object; uint32_t offset; diff --git a/nouveau/private.h b/nouveau/private.h index b409cc8..8a5cb26 100644 --- a/nouveau/private.h +++ b/nouveau/private.h @@ -113,6 +113,7 @@ nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t); /* abi16.c */ int abi16_chan_nv04(struct nouveau_object *); int abi16_chan_nvc0(struct nouveau_object *); +int abi16_chan_nve0(struct nouveau_object *); int abi16_engobj(struct nouveau_object *); int abi16_ntfy(struct nouveau_object *); void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *); commit 9e6f96a579fc2ed241e9a31a35a5995129ee8f7a Author: Marcin Slusarz <[email protected]> Date: Sun Dec 16 19:28:24 2012 +0100 libdrm_nouveau.pc: don't include I${includedir}/nouveau Nouveau headers are installed in I${includedir}/libdrm. diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in index 6170613..454fc87 100644 --- a/nouveau/libdrm_nouveau.pc.in +++ b/nouveau/libdrm_nouveau.pc.in @@ -7,5 +7,5 @@ Name: libdrm_nouveau Description: Userspace interface to nouveau kernel DRM services Version: 2.4.33 Libs: -L${libdir} -ldrm_nouveau -Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau +Cflags: -I${includedir} -I${includedir}/libdrm Requires.private: libdrm commit fdda97007b1dbf95beb16a0e3510fd36c89e8c33 Author: Chris Wilson <[email protected]> Date: Fri Jan 11 00:55:12 2013 +0000 intel: Remove the fence count contributions when clearing relocs As we clear the relocs from the bo, we also need to clear the contribution of the reloc_target_bo from the fence count. Otherwise they are leaked and prevent any further relocations being added to the bo. diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 512bc6f..294e575 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -1733,9 +1733,10 @@ drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) assert(bo_gem->reloc_count >= start); /* Unreference the cleared target buffers */ for (i = start; i < bo_gem->reloc_count; i++) { - if (bo_gem->reloc_target_info[i].bo != bo) { - drm_intel_gem_bo_unreference_locked_timed(bo_gem-> - reloc_target_info[i].bo, + drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo; + if (&target_bo_gem->bo != bo) { + bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences; + drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec); } } commit 1dbd873700f281d9773e64931ff0c1cf96e13793 Author: Jesse Barnes <[email protected]> Date: Wed Jan 9 17:28:41 2013 -0800 man: disable man page building until David saves us all I must have botched something in the push of the xml switchover, since I now get errors when building the pages and aliases. Just disable for now. diff --git a/Makefile.am b/Makefile.am index 8ecd9d9..9f106d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,7 @@ if HAVE_EXYNOS EXYNOS_SUBDIR = exynos endif -SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man +SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) commit fd6b369d39bc710acf56632a292308eb4e23d6db Author: David Herrmann <[email protected]> Date: Fri Sep 28 23:44:22 2012 +0200 man: add drm-memory overview page This adds an overview page that describes Dumb-Buffers, TTM and GEM. It does not describe chipset-specific features. You should do that in the driver-manpages. Signed-off-by: David Herrmann <[email protected]> Reviewed-by: Jesse Barnes <[email protected]> diff --git a/man/Makefile.am b/man/Makefile.am index b393072..32acd07 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 0000000..6b4f075 --- /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 <[email protected]> + 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>[email protected]</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> commit 8cd0c131df20d983657c4e205493109a8c71624e Author: David Herrmann <[email protected]> Date: Fri Sep 28 23:44:21 2012 +0200 man: add drm-kms overview page This is an overview page for KMS. It is again targeted at novice users that need redirection to the correct function man-pages. Signed-off-by: David Herrmann <[email protected]> Reviewed-by: Jesse Barnes <[email protected]> diff --git a/man/Makefile.am b/man/Makefile.am index 01b5699..b393072 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -6,6 +6,7 @@ MANPAGES = \ drm.7 \ + drm-kms.7 \ drmAvailable.3 \ drmHandleEvent.3 \ drmModeGetResources.3 diff --git a/man/drm-kms.xml b/man/drm-kms.xml new file mode 100644 index 0000000..5f04157 --- /dev/null +++ b/man/drm-kms.xml @@ -0,0 +1,342 @@ +<?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 <[email protected]> + Dedicated to the Public Domain +--> + +<refentry id="drm-kms"> + <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>[email protected]</email> + </author> + </authorgroup> + </refentryinfo> + + <refmeta> + <refentrytitle>drm-kms</refentrytitle> + <manvolnum>7</manvolnum> + </refmeta> + + <refnamediv> + <refname>drm-kms</refname> + <refpurpose>Kernel Mode-Setting</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <funcsynopsis> + <funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo> + <funcsynopsisinfo>#include <xf86drmMode.h></funcsynopsisinfo> + </funcsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + <para>Each DRM device provides access to manage which monitors and displays + are currently used and what frames to be displayed. This task is + called <emphasis>Kernel Mode-Setting</emphasis> (KMS). Historically, + this was done in user-space and called + <emphasis>User-space Mode-Setting</emphasis> (UMS). Almost all + open-source drivers now provide the KMS kernel API to do this in the + kernel, however, many non-open-source binary drivers from different + vendors still do not support this. You can use + <citerefentry><refentrytitle>drmModeSettingSupported</refentrytitle><manvolnum>3</manvolnum></citerefentry> + to check whether your driver supports this. To understand how KMS + works, we need to introduce 5 objects: <emphasis>CRTCs</emphasis>, + <emphasis>Planes</emphasis>, <emphasis>Encoders</emphasis>, + <emphasis>Connectors</emphasis> and + <emphasis>Framebuffers</emphasis>. + + <variablelist> + <varlistentry> + <term>CRTCs</term> + <listitem> + <para>A <emphasis>CRTC</emphasis> short for + <emphasis>CRT Controller</emphasis> is an abstraction + representing a part of the chip that contains a pointer to a + scanout buffer. Therefore, the number of CRTCs available + determines how many independent scanout buffers can be active + at any given time. The CRTC structure contains several fields + to support this: a pointer to some video memory (abstracted as + a frame-buffer object), a list of driven connectors, a display + mode and an (x, y) offset into the video memory to support + panning or configurations where one piece of video memory + spans multiple CRTCs. A CRTC is the central point where + configuration of displays happens. You select which objects to + use, which modes and which parameters and then configure each + CRTC via + <citerefentry><refentrytitle>drmModeCrtcSet</refentrytitle><manvolnum>3</manvolnum></citerefentry> + to drive the display devices.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>Planes</term> + <listitem> + <para>A <emphasis>plane</emphasis> respresents an image source that + can be blended with or overlayed on top of a CRTC during the + scanout process. Planes are associated with a frame-buffer to + crop a portion of the image memory (source) and optionally + scale it to a destination size. The result is then blended + with or overlayed on top of a CRTC. Planes are not provided by + all hardware and the number of available planes is limited. If + planes are not available or if not enough planes are + available, the user should fall back to normal software + blending (via GPU or CPU).</para> + </listitem> + </varlistentry> + <varlistentry> + <term>Encoders</term> + <listitem> + <para>An <emphasis>encoder</emphasis> takes pixel data from a CRTC + and converts it to a format suitable for any attached + connectors. On some devices, it may be possible to have a CRTC + send data to more than one encoder. In that case, both + encoders would receive data from the same scanout buffer, + resulting in a <emphasis>cloned</emphasis> display + configuration across the connectors attached to each + encoder.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>Connectors</term> + <listitem> + <para>A <emphasis>connector</emphasis> is the final destination of + pixel-data on a device, and usually connects directly to an + external display device like a monitor or laptop panel. A + connector can only be attached to one encoder at a time. The + connector is also the structure where information about the + attached display is kept, so it contains fields for display + data, <emphasis>EDID</emphasis> data, + <emphasis>DPMS</emphasis> and + <emphasis>connection status</emphasis>, and information about + modes supported on the attached displays.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>Framebuffers</term> + <listitem> + <para><emphasis>Framebuffers</emphasis> are abstract memory objects + that provide a source of pixel data to scanout to a CRTC. + Applications explicitely request the creation of framebuffers + and can control their behavior. Framebuffers rely on the + underneath memory manager for low-level memory operations. + When creating a framebuffer, applications pass a memory handle + through the API which is used as backing storage. The + framebuffer itself is only an abstract object with no data. It + just refers to memory buffers that must be created with the + <citerefentry><refentrytitle>drm-memory</refentrytitle><manvolnum>7</manvolnum></citerefentry> + API.</para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <refsect2> + <title>Mode-Setting</title> + <para>Before mode-setting can be performed, an application needs to call + <citerefentry><refentrytitle>drmSetMaster</refentrytitle><manvolnum>3</manvolnum></citerefentry> + to become <emphasis>DRM-Master</emphasis>. It then has exclusive + access to the KMS API. A call to + <citerefentry><refentrytitle>drmModeGetResources</refentrytitle><manvolnum>3</manvolnum></citerefentry> + returns a list of <emphasis>CRTCs</emphasis>, + <emphasis>Connectors</emphasis>, <emphasis>Encoders</emphasis> and + <emphasis>Planes</emphasis>.</para> + + <para>Normal procedure now includes: First, you select which connectors + you want to use. Users are mostly interested in which monitor or + display-panel is active so you need to make sure to arrange them in + the correct logical order and select the correct ones to use. For + each connector, you need to find a CRTC to drive this connector. If + you want to clone output to two or more connectors, you may use a + single CRTC for all cloned connectors (if the hardware supports + this). To find a suitable CRTC, you need to iterate over the list of + encoders that are available for each connector. Each encoder + contains a list of CRTCs that it can work with and you simply select + one of these CRTCs. If you later program the CRTC to control a + connector, it automatically selects the best encoder. However, this + procedure is needed so your CRTC has at least one working encoder + for the selected connector. See the <emphasis>Examples</emphasis> + section below for more information.</para> + + <para>All valid modes for a connector can be retrieved with a call to + <citerefentry><refentrytitle>drmModeGetConnector</refentrytitle><manvolnum>3</manvolnum></citerefentry> + You need to select the mode you want to use and save it. The first + mode in the list is the default mode with the highest resolution + possible and often a suitable choice.</para> + + <para>After you have a working connector+CRTC+mode combination, you need + to create a framebuffer that is used for scanout. Memory buffer + allocation is driver-depedent and described in + <citerefentry><refentrytitle>drm-memory</refentrytitle><manvolnum>7</manvolnum></citerefentry>. + You need to create a buffer big enough for your selected mode. Now + you can create a framebuffer object that uses your memory-buffer as + scanout buffer. You can do this with + <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry> + and + <citerefentry><refentrytitle>drmModeAddFB2</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para> + + <para>As a last step, you want to program your CRTC to drive your selected + connector. You can do this with a call to + <citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para> + </refsect2> + + <refsect2> + <title>Page-Flipping</title> + <para>A call to + <citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry> + is executed immediately and forces the CRTC to use the new scanout + buffer. If you want smooth-transitions without tearing, you probably + use double-buffering. You need to create one framebuffer object for + each buffer you use. You can then call + <citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry> + on the next buffer to flip. If you want to synchronize your flips + with <emphasis>vertical-blanks</emphasis>, you can use + <citerefentry><refentrytitle>drmModePageFlip</refentrytitle><manvolnum>3</manvolnum></citerefentry> + which schedules your page-flip for the next + <emphasis>vblank</emphasis>.</para> + </refsect2> + + <refsect2> + <title>Planes</title> + <para>Planes are controlled independently from CRTCs. That is, a call to + <citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry> + does not affect planes. Instead, you need to call + <citerefentry><refentrytitle>drmModeSetPlane</refentrytitle><manvolnum>3</manvolnum></citerefentry> + to configure a plane. This requires the plane ID, a CRTC, a + framebuffer and offsets into the plane-framebuffer and the + CRTC-framebuffer. The CRTC then blends the content from the plane + over the CRTC framebuffer buffer during scanout. As this does not + involve any software-blending, it is way faster than traditional + blending. However, plane resources are limited. See + <citerefentry><refentrytitle>drmModeGetPlaneResources</refentrytitle><manvolnum>3</manvolnum></citerefentry> + for more information.</para> + </refsect2> + + <refsect2> + <title>Cursors</title> + <para>Similar to planes, many hardware also supports cursors. A cursor is + a very small buffer with an image that is blended over the CRTC + framebuffer. You can set a different cursor for each CRTC with + <citerefentry><refentrytitle>drmModeSetCursor</refentrytitle><manvolnum>3</manvolnum></citerefentry> + and move it on the screen with + <citerefentry><refentrytitle>drmModeMoveCursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>. + This allows to move the cursor on the screen without rerendering. If + no hardware cursors are supported, you need to rerender for each + frame the cursor is moved.</para> + </refsect2> + + </refsect1> + + <refsect1> + <title>Examples</title> + <para>Some examples of how basic mode-setting can be done. See the man-page + of each DRM function for more information.</para> + + <refsect2> + <title>CRTC/Encoder Selection</title> + <para>If you retrieved all display configuration information via + <citerefentry><refentrytitle>drmModeGetResources</refentrytitle><manvolnum>3</manvolnum></citerefentry> + as <structname>drmModeRes</structname> *<varname>res</varname>, + selected a connector from the list in + <varname>res</varname>-><structfield>connectors</structfield> + and retrieved the connector-information as + <structname>drmModeConnector</structname> *<varname>conn</varname> + via -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected] Archive: http://lists.debian.org/[email protected]

