diff mbox

[libdrm,3/4] man: add drm-kms overview page

Message ID 1348868662-25509-4-git-send-email-dh.herrmann@googlemail.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

David Herrmann Sept. 28, 2012, 9:44 p.m. UTC
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 <dh.herrmann@googlemail.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 man/Makefile.am |   1 +
 man/drm-kms.xml | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 343 insertions(+)
 create mode 100644 man/drm-kms.xml
diff mbox

Patch

diff --git a/man/Makefile.am b/man/Makefile.am
index d55f444..ae02728 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 <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 &lt;xf86drm.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;xf86drmMode.h&gt;</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 &lt; 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 &lt; res->count_crtcs; ++j) {
+			/* check whether this CRTC works with the encoder */
+			if (!(enc->possible_crtcs &amp; (1 &lt;&lt; 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>