diff options
Diffstat (limited to 'man')
-rw-r--r-- | man/Makefile.am | 1 | ||||
-rw-r--r-- | man/drm-kms.xml | 342 |
2 files changed, 343 insertions, 0 deletions
diff --git a/man/Makefile.am b/man/Makefile.am index 01b56994..b393072a 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 00000000..5f041578 --- /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 <dh.herrmann@googlemail.com> + 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>dh.herrmann@googlemail.com</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 + <citerefentry><refentrytitle>drmModeGetConnector</refentrytitle><manvolnum>3</manvolnum></citerefentry> + then this example shows, how you can find a suitable CRTC id to + drive this connector. This function takes a file-descriptor to the + DRM device (see + <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>) + as <varname>fd</varname>, a pointer to the retrieved resources as + <varname>res</varname> and a pointer to the selected connector as + <varname>conn</varname>. It returns an integer smaller than 0 on + failure, otherwise, a valid CRTC id is returned.</para> + +<programlisting> +static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) +{ + drmModeEncoder *enc; + unsigned int i, j; + + /* iterate all encoders of this connector */ + for (i = 0; i < conn->count_encoders; ++i) { + enc = drmModeGetEncoder(fd, conn->encoders[i]); + if (!enc) { + /* cannot retrieve encoder, ignoring... */ + continue; + } + + /* iterate all global CRTCs */ + for (j = 0; j < res->count_crtcs; ++j) { + /* check whether this CRTC works with the encoder */ + if (!(enc->possible_crtcs & (1 << j))) + continue; + + + /* Here you need to check that no other connector + * currently uses the CRTC with id "crtc". If you intend + * to drive one connector only, then you can skip this + * step. Otherwise, simply scan your list of configured + * connectors and CRTCs whether this CRTC is already + * used. If it is, then simply continue the search here. */ + if (res->crtcs[j] "is unused") { + drmModeFreeEncoder(enc); + return res->crtcs[j]; + } + } + + drmModeFreeEncoder(enc); + } + + /* cannot find a suitable CRTC */ + return -ENOENT; +} +</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-memory</refentrytitle><manvolnum>7</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetResources</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetConnector</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetEncoder</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeAddFB2</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeRmFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModePageFlip</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetPlaneResources</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeGetPlane</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeSetPlane</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeSetCursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmModeMoveCursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmSetMaster</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmCheckModesettingSupported</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry> + </para> + </refsect1> +</refentry> |