man: convert to reStructuredText
DocBook makes it hard to write and maintain docs. Hopefully reStructuredText can make this less painful. The man pages were converted from DocBook to reStructuredText via Pandoc: pandoc -s -f docbook -t rst -o man/drm.7.rst man/drm.xml And then manual editing to fixup e.g. references to other man pages. To compare the result with the DocBook version, this command was used: rst2man man/drm-kms.7.rst | man -l - Signed-off-by: Simon Ser <contact@emersion.fr> Reviewed-by: Eric Engestrom <eric@engestrom.ch>main
parent
9a7afcf198
commit
05b0a955d3
|
@ -14,7 +14,7 @@
|
||||||
# repository's registry will be used there as well.
|
# repository's registry will be used there as well.
|
||||||
variables:
|
variables:
|
||||||
UPSTREAM_REPO: mesa/drm
|
UPSTREAM_REPO: mesa/drm
|
||||||
DEBIAN_TAG: "2019-11-16"
|
DEBIAN_TAG: "2020-11-15"
|
||||||
DEBIAN_VERSION: buster-slim
|
DEBIAN_VERSION: buster-slim
|
||||||
DEBIAN_IMAGE: "$CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG"
|
DEBIAN_IMAGE: "$CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG"
|
||||||
|
|
||||||
|
@ -122,10 +122,9 @@ meson-arch-daily:
|
||||||
base-devel
|
base-devel
|
||||||
cairo
|
cairo
|
||||||
cunit
|
cunit
|
||||||
docbook-xsl
|
|
||||||
libatomic_ops
|
libatomic_ops
|
||||||
libpciaccess
|
libpciaccess
|
||||||
libxslt
|
|
||||||
meson
|
meson
|
||||||
valgrind
|
valgrind
|
||||||
|
python-docutils
|
||||||
extends: .meson-build
|
extends: .meson-build
|
||||||
|
|
|
@ -33,7 +33,6 @@ apt-get install -y --no-remove \
|
||||||
libcairo2-dev \
|
libcairo2-dev \
|
||||||
libcunit1-dev \
|
libcunit1-dev \
|
||||||
libpciaccess-dev \
|
libpciaccess-dev \
|
||||||
libxslt1-dev \
|
|
||||||
meson \
|
meson \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
|
@ -41,8 +40,8 @@ apt-get install -y --no-remove \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
python3-wheel \
|
python3-wheel \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
valgrind \
|
python3-docutils \
|
||||||
xsltproc
|
valgrind
|
||||||
|
|
||||||
for arch in ${CROSS_ARCHITECTURES[@]}; do
|
for arch in ${CROSS_ARCHITECTURES[@]}; do
|
||||||
cross_file=/cross_file-$arch.txt
|
cross_file=/cross_file-$arch.txt
|
||||||
|
|
|
@ -0,0 +1,229 @@
|
||||||
|
=======
|
||||||
|
drm-kms
|
||||||
|
=======
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
Kernel Mode-Setting
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 7
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
``#include <xf86drmMode.h>``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
Each DRM device provides access to manage which monitors and displays are
|
||||||
|
currently used and what frames to be displayed. This task is called *Kernel
|
||||||
|
Mode-Setting* (KMS). Historically, this was done in user-space and called
|
||||||
|
*User-space Mode-Setting* (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
|
||||||
|
**drmModeSettingSupported**\ (3) to check whether your driver supports this. To
|
||||||
|
understand how KMS works, we need to introduce 5 objects: *CRTCs*, *Planes*,
|
||||||
|
*Encoders*, *Connectors* and *Framebuffers*.
|
||||||
|
|
||||||
|
CRTCs
|
||||||
|
A *CRTC* short for *CRT Controller* 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
|
||||||
|
**drmModeCrtcSet**\ (3) to drive the display devices.
|
||||||
|
|
||||||
|
Planes
|
||||||
|
A *plane* 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).
|
||||||
|
|
||||||
|
Encoders
|
||||||
|
An *encoder* 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 *cloned*
|
||||||
|
display configuration across the connectors attached to each encoder.
|
||||||
|
|
||||||
|
Connectors
|
||||||
|
A *connector* 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, *EDID* data, *DPMS* and
|
||||||
|
*connection status*, and information about modes supported on the attached
|
||||||
|
displays.
|
||||||
|
|
||||||
|
Framebuffers
|
||||||
|
*Framebuffers* are abstract memory objects that provide a source of pixel
|
||||||
|
data to scanout to a CRTC. Applications explicitly 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
|
||||||
|
**drm-memory**\ (7) API.
|
||||||
|
|
||||||
|
Mode-Setting
|
||||||
|
------------
|
||||||
|
|
||||||
|
Before mode-setting can be performed, an application needs to call
|
||||||
|
**drmSetMaster**\ (3) to become *DRM-Master*. It then has exclusive access to
|
||||||
|
the KMS API. A call to **drmModeGetResources**\ (3) returns a list of *CRTCs*,
|
||||||
|
*Connectors*, *Encoders* and *Planes*.
|
||||||
|
|
||||||
|
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 *Examples* section below for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
All valid modes for a connector can be retrieved with a call to
|
||||||
|
drmModeGetConnector3 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.
|
||||||
|
|
||||||
|
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 **drm-memory**\ (7). 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
|
||||||
|
**drmModeAddFB**\ (3) and **drmModeAddFB2**\ (3).
|
||||||
|
|
||||||
|
As a last step, you want to program your CRTC to drive your selected connector.
|
||||||
|
You can do this with a call to **drmModeSetCrtc**\ (3).
|
||||||
|
|
||||||
|
Page-Flipping
|
||||||
|
-------------
|
||||||
|
|
||||||
|
A call to **drmModeSetCrtc**\ (3) 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 **drmModeSetCrtc**\ (3) on the next
|
||||||
|
buffer to flip. If you want to synchronize your flips with *vertical-blanks*,
|
||||||
|
you can use **drmModePageFlip**\ (3) which schedules your page-flip for the
|
||||||
|
next *vblank*.
|
||||||
|
|
||||||
|
Planes
|
||||||
|
------
|
||||||
|
|
||||||
|
Planes are controlled independently from CRTCs. That is, a call to
|
||||||
|
**drmModeSetCrtc**\ (3) does not affect planes. Instead, you need to call
|
||||||
|
**drmModeSetPlane**\ (3) 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 **drmModeGetPlaneResources**\ (3) for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
Cursors
|
||||||
|
-------
|
||||||
|
|
||||||
|
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 **drmModeSetCursor**\ (3) and move it
|
||||||
|
on the screen with **drmModeMoveCursor**\ (3). 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.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
Some examples of how basic mode-setting can be done. See the man-page of each
|
||||||
|
DRM function for more information.
|
||||||
|
|
||||||
|
CRTC/Encoder Selection
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
If you retrieved all display configuration information via
|
||||||
|
**drmModeGetResources**\ (3) as ``drmModeRes *res``, selected a connector from
|
||||||
|
the list in ``res->connectors`` and retrieved the connector-information as
|
||||||
|
``drmModeConnector *conn`` via **drmModeGetConnector**\ (3) 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 **drmOpen**\ (3)) as
|
||||||
|
``fd``, a pointer to the retrieved resources as ``res`` and a pointer to the
|
||||||
|
selected connector as ``conn``. It returns an integer smaller than 0 on
|
||||||
|
failure, otherwise, a valid CRTC id is returned.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this manual should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm**\ (7), **drm-memory**\ (7), **drmModeGetResources**\ (3),
|
||||||
|
**drmModeGetConnector**\ (3), **drmModeGetEncoder**\ (3),
|
||||||
|
**drmModeGetCrtc**\ (3), **drmModeSetCrtc**\ (3), **drmModeGetFB**\ (3),
|
||||||
|
**drmModeAddFB**\ (3), **drmModeAddFB2**\ (3), **drmModeRmFB**\ (3),
|
||||||
|
**drmModePageFlip**\ (3), **drmModeGetPlaneResources**\ (3),
|
||||||
|
**drmModeGetPlane**\ (3), **drmModeSetPlane**\ (3), **drmModeSetCursor**\ (3),
|
||||||
|
**drmModeMoveCursor**\ (3), **drmSetMaster**\ (3), **drmAvailable**\ (3),
|
||||||
|
**drmCheckModesettingSupported**\ (3), **drmOpen**\ (3)
|
341
man/drm-kms.xml
341
man/drm-kms.xml
|
@ -1,341 +0,0 @@
|
||||||
<?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 explicitly 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
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</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>
|
|
|
@ -0,0 +1,322 @@
|
||||||
|
==========
|
||||||
|
drm-memory
|
||||||
|
==========
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
DRM Memory Management
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 7
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
Many modern high-end GPUs come with their own memory managers. They even
|
||||||
|
include several different caches that need to be synchronized during access.
|
||||||
|
Textures, framebuffers, command buffers and more need to be stored in memory
|
||||||
|
that can be accessed quickly by the GPU. Therefore, memory management on GPUs
|
||||||
|
is highly driver- and hardware-dependent.
|
||||||
|
|
||||||
|
However, there are several frameworks in the kernel that are used by more than
|
||||||
|
one driver. These can be used for trivial mode-setting without requiring
|
||||||
|
driver-dependent code. But for hardware-accelerated rendering you need to read
|
||||||
|
the manual pages for the driver you want to work with.
|
||||||
|
|
||||||
|
Dumb-Buffers
|
||||||
|
------------
|
||||||
|
|
||||||
|
Almost all in-kernel DRM hardware drivers support an API called *Dumb-Buffers*.
|
||||||
|
This API allows to create buffers of arbitrary size that can be used for
|
||||||
|
scanout. These buffers can be memory mapped via **mmap**\ (2) so you can render
|
||||||
|
into them on the CPU. However, GPU access to these buffers is often not
|
||||||
|
possible. Therefore, they are fine for simple tasks but not suitable for
|
||||||
|
complex compositions and renderings.
|
||||||
|
|
||||||
|
The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl can be used to create a dumb buffer.
|
||||||
|
The kernel will return a 32-bit handle that can be used to manage the buffer
|
||||||
|
with the DRM API. You can create framebuffers with **drmModeAddFB**\ (3) and
|
||||||
|
use it for mode-setting and scanout. To access the buffer, you first need to
|
||||||
|
retrieve the offset of the buffer. The ``DRM_IOCTL_MODE_MAP_DUMB`` ioctl
|
||||||
|
requests the DRM subsystem to prepare the buffer for memory-mapping and returns
|
||||||
|
a fake-offset that can be used with **mmap**\ (2).
|
||||||
|
|
||||||
|
The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl takes as argument a structure of type
|
||||||
|
``struct drm_mode_create_dumb``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_mode_create_dumb {
|
||||||
|
__u32 height;
|
||||||
|
__u32 width;
|
||||||
|
__u32 bpp;
|
||||||
|
__u32 flags;
|
||||||
|
|
||||||
|
__u32 handle;
|
||||||
|
__u32 pitch;
|
||||||
|
__u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
The fields *height*, *width*, *bpp* and *flags* have to be provided by the
|
||||||
|
caller. The other fields are filled by the kernel with the return values.
|
||||||
|
*height* and *width* are the dimensions of the rectangular buffer that is
|
||||||
|
created. *bpp* is the number of bits-per-pixel and must be a multiple of 8. You
|
||||||
|
most commonly want to pass 32 here. The flags 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 handle, pitch and size fields are filled
|
||||||
|
by the kernel. *handle* is a 32-bit gem handle that identifies the buffer. This
|
||||||
|
is used by several other calls that take a gem-handle or memory-buffer as
|
||||||
|
argument. The *pitch* field is the pitch (or stride) of the new buffer. Most
|
||||||
|
drivers use 32-bit or 64-bit aligned stride-values. The size field contains the
|
||||||
|
absolute size in bytes of the buffer. This can normally also be computed with
|
||||||
|
``(height * pitch + width) * bpp / 4``.
|
||||||
|
|
||||||
|
To prepare the buffer for **mmap**\ (2) you need to use the
|
||||||
|
``DRM_IOCTL_MODE_MAP_DUMB`` ioctl. It takes as argument a structure of type
|
||||||
|
``struct drm_mode_map_dumb``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_mode_map_dumb {
|
||||||
|
__u32 handle;
|
||||||
|
__u32 pad;
|
||||||
|
|
||||||
|
__u64 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
You need to put the gem-handle that was previously retrieved via
|
||||||
|
``DRM_IOCTL_MODE_CREATE_DUMB`` into the *handle* field. The *pad* field is
|
||||||
|
unused padding and must be zeroed. After completion, the *offset* field will
|
||||||
|
contain an offset that can be used with **mmap**\ (2) on the DRM
|
||||||
|
file-descriptor.
|
||||||
|
|
||||||
|
If you don't need your dumb-buffer, anymore, you have to destroy it with
|
||||||
|
``DRM_IOCTL_MODE_DESTROY_DUMB``. If you close the DRM file-descriptor, all open
|
||||||
|
dumb-buffers are automatically destroyed. This ioctl takes as argument a
|
||||||
|
structure of type ``struct drm_mode_destroy_dumb``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_mode_destroy_dumb {
|
||||||
|
__u32 handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
You only need to put your handle into the *handle* field. After this call, the
|
||||||
|
handle is invalid and may be reused for new buffers by the dumb-API.
|
||||||
|
|
||||||
|
TTM
|
||||||
|
---
|
||||||
|
|
||||||
|
*TTM* stands for *Translation Table Manager* 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 man pages for more information on memory-management with radeon and TTM.
|
||||||
|
|
||||||
|
GEM
|
||||||
|
---
|
||||||
|
|
||||||
|
*GEM* stands for *Graphics Execution Manager* and is a generic DRM
|
||||||
|
memory-management framework in the kernel, that is used by many different
|
||||||
|
drivers. GEM is designed to manage graphics memory, control access to the
|
||||||
|
graphics device execution context and handle essentially NUMA environment
|
||||||
|
unique to modern graphics hardware. GEM allows multiple applications to share
|
||||||
|
graphics device resources without the need to constantly reload the entire
|
||||||
|
graphics card. Data may be shared between multiple applications with gem
|
||||||
|
ensuring that the correct memory synchronization occurs.
|
||||||
|
|
||||||
|
GEM provides simple mechanisms to manage graphics data and control execution
|
||||||
|
flow within the linux DRM subsystem. However, GEM is not a complete framework
|
||||||
|
that is fully driver independent. Instead, if provides many functions that are
|
||||||
|
shared between many drivers, but each driver has to implement most of
|
||||||
|
memory-management with driver-dependent ioctls. This manpage tries to describe
|
||||||
|
the semantics (and if it applies, the syntax) that is shared between all
|
||||||
|
drivers that use GEM.
|
||||||
|
|
||||||
|
All GEM APIs are defined as **ioctl**\ (2) on the DRM file descriptor. An
|
||||||
|
application must be authorized via **drmAuthMagic**\ (3) to the current
|
||||||
|
DRM-Master to access the GEM subsystem. A driver that does not support GEM will
|
||||||
|
return ``ENODEV`` for all these ioctls. Invalid object handles return
|
||||||
|
``EINVAL`` and invalid object names return ``ENOENT``.
|
||||||
|
|
||||||
|
Gem provides explicit memory management primitives. System pages are allocated
|
||||||
|
when the object is created, either as the fundamental storage for hardware
|
||||||
|
where system memory is used by the graphics processor directly, or as backing
|
||||||
|
store for graphics-processor resident memory.
|
||||||
|
|
||||||
|
Objects are referenced from user-space using handles. These are, for all
|
||||||
|
intents and purposes, equivalent to file descriptors but avoid the overhead.
|
||||||
|
Newer kernel drivers also support the **drm-prime** (7) 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.
|
||||||
|
|
||||||
|
GEM-buffers cannot be created with a generic API. Each driver provides its own
|
||||||
|
API to create GEM-buffers. See for example ``DRM_I915_GEM_CREATE``,
|
||||||
|
``DRM_NOUVEAU_GEM_NEW`` or ``DRM_RADEON_GEM_CREATE``. Each of these ioctls
|
||||||
|
returns a GEM-handle that can be passed to different generic ioctls. The
|
||||||
|
*libgbm* library from the *mesa3D* distribution tries to provide a
|
||||||
|
driver-independent API to create GBM buffers and retrieve a GBM-handle to them.
|
||||||
|
It allows to create buffers for different use-cases including scanout,
|
||||||
|
rendering, cursors and CPU-access. See the libgbm library for more information
|
||||||
|
or look at the driver-dependent man-pages (for example **drm-intel**\ (7) or
|
||||||
|
**drm-radeon**\ (7)).
|
||||||
|
|
||||||
|
GEM-buffers can be closed with the ``DRM_IOCTL_GEM_CLOSE`` ioctl. It takes as
|
||||||
|
argument a structure of type ``struct drm_gem_close``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_gem_close {
|
||||||
|
__u32 handle;
|
||||||
|
__u32 pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
The *handle* field is the GEM-handle to be closed. The *pad* field is unused
|
||||||
|
padding. It must be zeroed. After this call the GEM handle cannot be used by
|
||||||
|
this process anymore and may be reused for new GEM objects by the GEM API.
|
||||||
|
|
||||||
|
If you want to share GEM-objects between different processes, you can create a
|
||||||
|
name for them and pass this name to other processes which can then open this
|
||||||
|
GEM-object. Names are currently 32-bit 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
|
||||||
|
**drmAuthMagic**\ (3) to the current DRM-Master, can *guess* the name and open
|
||||||
|
or access the GEM-object. If you want more fine-grained access control, you can
|
||||||
|
use the new **drm-prime**\ (7) API to retrieve file-descriptors for
|
||||||
|
GEM-handles. To create a name for a GEM-handle, you use the
|
||||||
|
``DRM_IOCTL_GEM_FLINK`` ioctl. It takes as argument a structure of type
|
||||||
|
``struct drm_gem_flink``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_gem_flink {
|
||||||
|
__u32 handle;
|
||||||
|
__u32 name;
|
||||||
|
};
|
||||||
|
|
||||||
|
You have to put your handle into the *handle* field. After completion, the
|
||||||
|
kernel has put the new unique name into the name field. You can now pass
|
||||||
|
this name to other processes which can then import the name with the
|
||||||
|
``DRM_IOCTL_GEM_OPEN`` ioctl. It takes as argument a structure of type
|
||||||
|
``struct drm_gem_open``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct drm_gem_open {
|
||||||
|
__u32 name;
|
||||||
|
|
||||||
|
__u32 handle;
|
||||||
|
__u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
You have to fill in the *name* field with the name of the GEM-object that you
|
||||||
|
want to open. The kernel will fill in the *handle* and *size* fields with the
|
||||||
|
new handle and size of the GEM-object. You can now access the GEM-object via
|
||||||
|
the handle as if you created it with the GEM API.
|
||||||
|
|
||||||
|
Besides generic buffer management, the GEM API does not provide any generic
|
||||||
|
access. Each driver implements its own functionality on top of this API. This
|
||||||
|
includes execution-buffers, GTT management, context creation, CPU access, GPU
|
||||||
|
I/O and more. The next higher-level API is *OpenGL*. So if you want to use more
|
||||||
|
GPU features, you should use the *mesa3D* library to create OpenGL contexts on
|
||||||
|
DRM devices. This does *not* require any windowing-system like X11, but can
|
||||||
|
also be done on raw DRM devices. However, this is beyond the scope of this
|
||||||
|
man-page. You may have a look at other mesa3D man pages, 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 **drm-intel**\ (7), **drm-radeon**\ (7) and
|
||||||
|
**drm-nouveau**\ (7). However, the **drm-prime**\ (7) infrastructure and the
|
||||||
|
generic GEM API as described here allow display-managers to handle
|
||||||
|
graphics-buffers and render-clients without any deeper knowledge of the GPU
|
||||||
|
that is used. Moreover, it allows to move objects between GPUs and implement
|
||||||
|
complex display-servers that don't do any rendering on their own. See its
|
||||||
|
man-page for more information.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
This section includes examples for basic memory-management tasks.
|
||||||
|
|
||||||
|
Dumb-Buffers
|
||||||
|
------------
|
||||||
|
|
||||||
|
This examples shows how to create a dumb-buffer via the generic DRM API.
|
||||||
|
This is driver-independent (as long as the driver supports dumb-buffers)
|
||||||
|
and provides memory-mapped buffers that can be used for scanout. 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 **drm-kms**\ (7)).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this manual should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm**\ (7), **drm-kms**\ (7), **drm-prime**\ (7), **drmAvailable**\ (3),
|
||||||
|
**drmOpen**\ (3), **drm-intel**\ (7), **drm-radeon**\ (7), **drm-nouveau**\ (7)
|
|
@ -1,429 +0,0 @@
|
||||||
<?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
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</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>
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
===
|
||||||
|
drm
|
||||||
|
===
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
Direct Rendering Manager
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 7
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
The *Direct Rendering Manager* (DRM) is a framework to manage *Graphics
|
||||||
|
Processing Units* (GPUs). It is designed to support the needs of complex
|
||||||
|
graphics devices, usually containing programmable pipelines well suited
|
||||||
|
to 3D graphics acceleration. Furthermore, it is responsible for memory
|
||||||
|
management, interrupt handling and DMA to provide a uniform interface to
|
||||||
|
applications.
|
||||||
|
|
||||||
|
In earlier days, the kernel framework was solely used to provide raw
|
||||||
|
hardware access to privileged user-space processes which implement all
|
||||||
|
the hardware abstraction layers. But more and more tasks were moved into
|
||||||
|
the kernel. All these interfaces are based on **ioctl**\ (2) commands on
|
||||||
|
the DRM character device. The *libdrm* library provides wrappers for these
|
||||||
|
system-calls and many helpers to simplify the API.
|
||||||
|
|
||||||
|
When a GPU is detected, the DRM system loads a driver for the detected
|
||||||
|
hardware type. Each connected GPU is then presented to user-space via a
|
||||||
|
character-device that is usually available as ``/dev/dri/card0`` and can
|
||||||
|
be accessed with **open**\ (2) and **close**\ (2). However, it still
|
||||||
|
depends on the graphics driver which interfaces are available on these
|
||||||
|
devices. If an interface is not available, the syscalls will fail with
|
||||||
|
``EINVAL``.
|
||||||
|
|
||||||
|
Authentication
|
||||||
|
--------------
|
||||||
|
|
||||||
|
All DRM devices provide authentication mechanisms. Only a DRM master is
|
||||||
|
allowed to perform mode-setting or modify core state and only one user
|
||||||
|
can be DRM master at a time. See **drmSetMaster**\ (3) for information
|
||||||
|
on how to become DRM master and what the limitations are. Other DRM users
|
||||||
|
can be authenticated to the DRM-Master via **drmAuthMagic**\ (3) so they
|
||||||
|
can perform buffer allocations and rendering.
|
||||||
|
|
||||||
|
Mode-Setting
|
||||||
|
------------
|
||||||
|
|
||||||
|
Managing connected monitors and displays and changing the current modes
|
||||||
|
is called *Mode-Setting*. This is restricted to the current DRM master.
|
||||||
|
Historically, this was implemented in user-space, but new DRM drivers
|
||||||
|
implement a kernel interface to perform mode-setting called *Kernel Mode
|
||||||
|
Setting* (KMS). If your hardware-driver supports it, you can use the KMS
|
||||||
|
API provided by DRM. This includes allocating framebuffers, selecting
|
||||||
|
modes and managing CRTCs and encoders. See **drm-kms**\ (7) for more.
|
||||||
|
|
||||||
|
Memory Management
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The most sophisticated tasks for GPUs today is managing memory objects.
|
||||||
|
Textures, framebuffers, command-buffers and all other kinds of commands
|
||||||
|
for the GPU have to be stored in memory. The DRM driver takes care of
|
||||||
|
managing all memory objects, flushing caches, synchronizing access and
|
||||||
|
providing CPU access to GPU memory. All memory management is hardware
|
||||||
|
driver dependent. However, two generic frameworks are available that are
|
||||||
|
used by most DRM drivers. These are the *Translation Table Manager*
|
||||||
|
(TTM) and the *Graphics Execution Manager* (GEM). They provide generic
|
||||||
|
APIs to create, destroy and access buffers from user-space. However,
|
||||||
|
there are still many differences between the drivers so driver-depedent
|
||||||
|
code is still needed. Many helpers are provided in *libgbm* (Graphics
|
||||||
|
Buffer Manager) from the *Mesa* project. For more information on DRM
|
||||||
|
memory management, see **drm-memory**\ (7).
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this manual should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues.
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm-kms**\ (7), **drm-memory**\ (7), **drmSetMaster**\ (3),
|
||||||
|
**drmAuthMagic**\ (3), **drmAvailable**\ (3), **drmOpen**\ (3)
|
136
man/drm.xml
136
man/drm.xml
|
@ -1,136 +0,0 @@
|
||||||
<?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">
|
|
||||||
<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</refentrytitle>
|
|
||||||
<manvolnum>7</manvolnum>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>drm</refname>
|
|
||||||
<refpurpose>Direct Rendering Manager</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
<funcsynopsis>
|
|
||||||
<funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo>
|
|
||||||
</funcsynopsis>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para>The <emphasis>Direct Rendering Manager</emphasis> (DRM) is a framework
|
|
||||||
to manage <emphasis>Graphics Processing Units</emphasis> (GPUs). It is
|
|
||||||
designed to support the needs of complex graphics devices, usually
|
|
||||||
containing programmable pipelines well suited to 3D graphics
|
|
||||||
acceleration. Furthermore, it is responsible for memory management,
|
|
||||||
interrupt handling and DMA to provide a uniform interface to
|
|
||||||
applications.</para>
|
|
||||||
|
|
||||||
<para>In earlier days, the kernel framework was solely used to provide raw
|
|
||||||
hardware access to privileged user-space processes which implement
|
|
||||||
all the hardware abstraction layers. But more and more tasks were
|
|
||||||
moved into the kernel. All these interfaces are based on
|
|
||||||
<citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
||||||
commands on the DRM character device. The <emphasis>libdrm</emphasis>
|
|
||||||
library provides wrappers for these system-calls and many helpers to
|
|
||||||
simplify the API.</para>
|
|
||||||
|
|
||||||
<para>When a GPU is detected, the DRM system loads a driver for the detected
|
|
||||||
hardware type. Each connected GPU is then presented to user-space via
|
|
||||||
a character-device that is usually available as
|
|
||||||
<filename>/dev/dri/card0</filename> and can be accessed with
|
|
||||||
<citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
||||||
and
|
|
||||||
<citerefentry><refentrytitle>close</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
|
|
||||||
However, it still depends on the graphics driver which interfaces are
|
|
||||||
available on these devices. If an interface is not available, the
|
|
||||||
syscalls will fail with <literal>EINVAL</literal>.</para>
|
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>Authentication</title>
|
|
||||||
<para>All DRM devices provide authentication mechanisms. Only a DRM-Master
|
|
||||||
is allowed to perform mode-setting or modify core state and only one
|
|
||||||
user can be DRM-Master at a time. See
|
|
||||||
<citerefentry><refentrytitle>drmSetMaster</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
for information on how to become DRM-Master and what the limitations
|
|
||||||
are. Other DRM users can be authenticated to the DRM-Master via
|
|
||||||
<citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
so they can perform buffer allocations and rendering.</para>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>Mode-Setting</title>
|
|
||||||
<para>Managing connected monitors and displays and changing the current
|
|
||||||
modes is called <emphasis>Mode-Setting</emphasis>. This is
|
|
||||||
restricted to the current DRM-Master. Historically, this was
|
|
||||||
implemented in user-space, but new DRM drivers implement a kernel
|
|
||||||
interface to perform mode-setting called
|
|
||||||
<emphasis>Kernel Mode Setting</emphasis> (KMS). If your
|
|
||||||
hardware-driver supports it, you can use the KMS API provided by
|
|
||||||
DRM. This includes allocating framebuffers, selecting modes and
|
|
||||||
managing CRTCs and encoders. See
|
|
||||||
<citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
||||||
for more.</para>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>Memory Management</title>
|
|
||||||
<para>The most sophisticated tasks for GPUs today is managing memory
|
|
||||||
objects. Textures, framebuffers, command-buffers and all other kinds
|
|
||||||
of commands for the GPU have to be stored in memory. The DRM driver
|
|
||||||
takes care of managing all memory objects, flushing caches,
|
|
||||||
synchronizing access and providing CPU access to GPU memory. All
|
|
||||||
memory management is hardware driver dependent. However, two generic
|
|
||||||
frameworks are available that are used by most DRM drivers. These
|
|
||||||
are the <emphasis>Translation Table Manager</emphasis> (TTM) and the
|
|
||||||
<emphasis>Graphics Execution Manager</emphasis> (GEM). They provide
|
|
||||||
generic APIs to create, destroy and access buffers from user-space.
|
|
||||||
However, there are still many differences between the drivers so
|
|
||||||
driver-depedent code is still needed. Many helpers are provided in
|
|
||||||
<emphasis>libgbm</emphasis> (Graphics Buffer Manager) from the
|
|
||||||
<emphasis>mesa-project</emphasis>. For more information on DRM
|
|
||||||
memory-management, see
|
|
||||||
<citerefentry><refentrytitle>drm-memory</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Reporting Bugs</title>
|
|
||||||
<para>Bugs in this manual should be reported to
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See Also</title>
|
|
||||||
<para>
|
|
||||||
<citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drm-memory</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmSetMaster</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
============
|
||||||
|
drmAvailable
|
||||||
|
============
|
||||||
|
|
||||||
|
-----------------------------------------------------
|
||||||
|
determine whether a DRM kernel driver has been loaded
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 3
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
``int drmAvailable(void);``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
``drmAvailable`` allows the caller to determine whether a kernel DRM
|
||||||
|
driver is loaded.
|
||||||
|
|
||||||
|
Return Value
|
||||||
|
============
|
||||||
|
|
||||||
|
``drmAvailable`` returns 1 if a DRM driver is currently loaded.
|
||||||
|
Otherwise 0 is returned.
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this function should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm**\ (7), **drmOpen**\ (3)
|
|
@ -1,74 +0,0 @@
|
||||||
<?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="drmAvailable">
|
|
||||||
<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>drmAvailable</refentrytitle>
|
|
||||||
<manvolnum>3</manvolnum>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>drmAvailable</refname>
|
|
||||||
<refpurpose>determine whether a DRM kernel driver has been
|
|
||||||
loaded</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
<funcsynopsis>
|
|
||||||
|
|
||||||
<funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo>
|
|
||||||
|
|
||||||
<funcprototype>
|
|
||||||
<funcdef>int <function>drmAvailable</function></funcdef>
|
|
||||||
<paramdef>void</paramdef>
|
|
||||||
</funcprototype>
|
|
||||||
|
|
||||||
</funcsynopsis>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para><function>drmAvailable</function> allows the caller to determine
|
|
||||||
whether a kernel DRM driver is loaded.</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Return Value</title>
|
|
||||||
<para><function>drmAvailable</function> returns 1 if a DRM driver is
|
|
||||||
currently loaded. Otherwise 0 is returned.</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Reporting Bugs</title>
|
|
||||||
<para>Bugs in this function should be reported to
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See Also</title>
|
|
||||||
<para>
|
|
||||||
<citerefentry><refentrytitle>drm</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
==============
|
||||||
|
drmHandleEvent
|
||||||
|
==============
|
||||||
|
|
||||||
|
-----------------------------------
|
||||||
|
read and process pending DRM events
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 3
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
``int drmHandleEvent(int fd, drmEventContextPtr evctx);``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
``drmHandleEvent`` processes outstanding DRM events on the DRM
|
||||||
|
file-descriptor passed as ``fd``. This function should be called after
|
||||||
|
the DRM file-descriptor has polled readable; it will read the events and
|
||||||
|
use the passed-in ``evctx`` structure to call function pointers with the
|
||||||
|
parameters noted below:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
typedef struct _drmEventContext {
|
||||||
|
int version;
|
||||||
|
void (*vblank_handler) (int fd,
|
||||||
|
unsigned int sequence,
|
||||||
|
unsigned int tv_sec,
|
||||||
|
unsigned int tv_usec,
|
||||||
|
void *user_data)
|
||||||
|
void (*page_flip_handler) (int fd,
|
||||||
|
unsigned int sequence,
|
||||||
|
unsigned int tv_sec,
|
||||||
|
unsigned int tv_usec,
|
||||||
|
void *user_data)
|
||||||
|
} drmEventContext, *drmEventContextPtr;
|
||||||
|
|
||||||
|
Return Value
|
||||||
|
============
|
||||||
|
|
||||||
|
``drmHandleEvent`` returns 0 on success, or if there is no data to
|
||||||
|
read from the file-descriptor. Returns -1 if the read on the
|
||||||
|
file-descriptor fails or returns less than a full event record.
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this function should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm**\ (7), **drm-kms**\ (7), **drmModePageFlip**\ (3),
|
||||||
|
**drmWaitVBlank**\ (3)
|
|
@ -1,101 +0,0 @@
|
||||||
<?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="drmHandleEvent">
|
|
||||||
<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>drmHandleEvent</refentrytitle>
|
|
||||||
<manvolnum>3</manvolnum>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>drmHandleEvent</refname>
|
|
||||||
<refpurpose>read and process pending DRM events</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
|
|
||||||
<funcsynopsis>
|
|
||||||
<funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo>
|
|
||||||
|
|
||||||
<funcprototype>
|
|
||||||
<funcdef>int <function>drmHandleEvent</function></funcdef>
|
|
||||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
||||||
<paramdef>drmEventContextPtr <parameter>evctx</parameter></paramdef>
|
|
||||||
</funcprototype>
|
|
||||||
</funcsynopsis>
|
|
||||||
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para><function>drmHandleEvent</function> processes outstanding DRM events
|
|
||||||
on the DRM file-descriptor passed as <parameter>fd</parameter>. This
|
|
||||||
function should be called after the DRM file-descriptor has polled
|
|
||||||
readable; it will read the events and use the passed-in
|
|
||||||
<parameter>evctx</parameter> structure to call function pointers
|
|
||||||
with the parameters noted below:
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
typedef struct _drmEventContext {
|
|
||||||
int version;
|
|
||||||
void (*vblank_handler) (int fd,
|
|
||||||
unsigned int sequence,
|
|
||||||
unsigned int tv_sec,
|
|
||||||
unsigned int tv_usec,
|
|
||||||
void *user_data)
|
|
||||||
void (*page_flip_handler) (int fd,
|
|
||||||
unsigned int sequence,
|
|
||||||
unsigned int tv_sec,
|
|
||||||
unsigned int tv_usec,
|
|
||||||
void *user_data)
|
|
||||||
} drmEventContext, *drmEventContextPtr;
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Return Value</title>
|
|
||||||
<para><function>drmHandleEvent</function> returns <literal>0</literal> on
|
|
||||||
success, or if there is no data to read from the file-descriptor.
|
|
||||||
Returns <literal>-1</literal> if the read on the file-descriptor fails
|
|
||||||
or returns less than a full event record.</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Reporting Bugs</title>
|
|
||||||
<para>Bugs in this function should be reported to
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</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>drmModePageFlip</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmWaitVBlank</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
===================
|
||||||
|
drmModeGetResources
|
||||||
|
===================
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
retrieve current display configuration information
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
:Date: September 2012
|
||||||
|
:Manual section: 3
|
||||||
|
:Manual group: Direct Rendering Manager
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
``#include <xf86drm.h>``
|
||||||
|
|
||||||
|
``#include <xf86drmMode.h>``
|
||||||
|
|
||||||
|
``drmModeResPtr drmModeGetResources(int fd);``
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
``drmModeGetResources`` allocates, populates, and returns a drmModeRes
|
||||||
|
structure containing information about the current display
|
||||||
|
configuration. The structure contains the following fields:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
typedef struct _drmModeRes {
|
||||||
|
int count_fbs;
|
||||||
|
uint32_t *fbs;
|
||||||
|
|
||||||
|
int count_crtcs;
|
||||||
|
uint32_t *crtcs;
|
||||||
|
|
||||||
|
int count_connectors;
|
||||||
|
uint32_t *connectors;
|
||||||
|
|
||||||
|
int count_encoders;
|
||||||
|
uint32_t *encoders;
|
||||||
|
|
||||||
|
uint32_t min_width, max_width;
|
||||||
|
uint32_t min_height, max_height;
|
||||||
|
} drmModeRes, *drmModeResPtr;
|
||||||
|
|
||||||
|
The *count_fbs* and *fbs* fields indicate the number of currently allocated
|
||||||
|
framebuffer objects (i.e., objects that can be attached to a given CRTC
|
||||||
|
or sprite for display).
|
||||||
|
|
||||||
|
The *count_crtcs* and *crtcs* fields list the available CRTCs in the
|
||||||
|
configuration. A CRTC is simply an object that can scan out a
|
||||||
|
framebuffer to a display sink, and contains mode timing and relative
|
||||||
|
position information. CRTCs drive encoders, which are responsible for
|
||||||
|
converting the pixel stream into a specific display protocol (e.g., MIPI
|
||||||
|
or HDMI).
|
||||||
|
|
||||||
|
The *count_connectors* and *connectors* fields list the available physical
|
||||||
|
connectors on the system. Note that some of these may not be exposed
|
||||||
|
from the chassis (e.g., LVDS or eDP). Connectors are attached to
|
||||||
|
encoders and contain information about the attached display sink (e.g.,
|
||||||
|
width and height in mm, subpixel ordering, and various other
|
||||||
|
properties).
|
||||||
|
|
||||||
|
The *count_encoders* and *encoders* fields list the available encoders on
|
||||||
|
the device. Each encoder may be associated with a CRTC, and may be used
|
||||||
|
to drive a particular encoder.
|
||||||
|
|
||||||
|
The *min_\** and *max_\** fields indicate the maximum size of a framebuffer
|
||||||
|
for this device (i.e., the scanout size limit).
|
||||||
|
|
||||||
|
Return Value
|
||||||
|
============
|
||||||
|
|
||||||
|
``drmModeGetResources`` returns a drmModeRes structure pointer on
|
||||||
|
success, NULL on failure. The returned structure must be freed with
|
||||||
|
**drmModeFreeResources**\ (3).
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
Bugs in this function should be reported to
|
||||||
|
https://gitlab.freedesktop.org/mesa/drm/-/issues
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
**drm**\ (7), **drm-kms**\ (7), **drmModeGetFB**\ (3), **drmModeAddFB**\ (3),
|
||||||
|
**drmModeAddFB2**\ (3), **drmModeRmFB**\ (3), **drmModeDirtyFB**\ (3),
|
||||||
|
**drmModeGetCrtc**\ (3), **drmModeSetCrtc** (3), **drmModeGetEncoder** (3),
|
||||||
|
**drmModeGetConnector**\ (3)
|
|
@ -1,138 +0,0 @@
|
||||||
<?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="drmModeGetResources">
|
|
||||||
<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>drmModeGetResources</refentrytitle>
|
|
||||||
<manvolnum>3</manvolnum>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>drmModeGetResources</refname>
|
|
||||||
<refpurpose>retrieve current display configuration information</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
|
|
||||||
<funcsynopsis>
|
|
||||||
<funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo>
|
|
||||||
<funcsynopsisinfo>#include <xf86drmMode.h></funcsynopsisinfo>
|
|
||||||
|
|
||||||
<funcprototype>
|
|
||||||
<funcdef>drmModeResPtr <function>drmModeGetResources</function></funcdef>
|
|
||||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
||||||
</funcprototype>
|
|
||||||
</funcsynopsis>
|
|
||||||
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para><function>drmModeGetResources</function> allocates, populates, and
|
|
||||||
returns a <structname>drmModeRes</structname> structure containing
|
|
||||||
information about the current display configuration. The structure
|
|
||||||
contains the following fields:
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
typedef struct _drmModeRes {
|
|
||||||
int count_fbs;
|
|
||||||
uint32_t *fbs;
|
|
||||||
|
|
||||||
int count_crtcs;
|
|
||||||
uint32_t *crtcs;
|
|
||||||
|
|
||||||
int count_connectors;
|
|
||||||
uint32_t *connectors;
|
|
||||||
|
|
||||||
int count_encoders;
|
|
||||||
uint32_t *encoders;
|
|
||||||
|
|
||||||
uint32_t min_width, max_width;
|
|
||||||
uint32_t min_height, max_height;
|
|
||||||
} drmModeRes, *drmModeResPtr;
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>The <structfield>count_fbs</structfield> and
|
|
||||||
<structfield>fbs</structfield> fields indicate the number of currently
|
|
||||||
allocated framebuffer objects (i.e., objects that can be attached to
|
|
||||||
a given CRTC or sprite for display).</para>
|
|
||||||
|
|
||||||
<para>The <structfield>count_crtcs</structfield> and
|
|
||||||
<structfield>crtcs</structfield> fields list the available CRTCs in
|
|
||||||
the configuration. A CRTC is simply an object that can scan out a
|
|
||||||
framebuffer to a display sink, and contains mode timing and relative
|
|
||||||
position information. CRTCs drive encoders, which are responsible for
|
|
||||||
converting the pixel stream into a specific display protocol (e.g.,
|
|
||||||
MIPI or HDMI).</para>
|
|
||||||
|
|
||||||
<para>The <structfield>count_connectors</structfield> and
|
|
||||||
<structfield>connectors</structfield> fields list the available
|
|
||||||
physical connectors on the system. Note that some of these may not be
|
|
||||||
exposed from the chassis (e.g., LVDS or eDP). Connectors are attached
|
|
||||||
to encoders and contain information about the attached display sink
|
|
||||||
(e.g., width and height in mm, subpixel ordering, and various other
|
|
||||||
properties).</para>
|
|
||||||
|
|
||||||
<para>The <structfield>count_encoders</structfield> and
|
|
||||||
<structfield>encoders</structfield> fields list the available encoders
|
|
||||||
on the device. Each encoder may be associated with a CRTC, and may be
|
|
||||||
used to drive a particular encoder.</para>
|
|
||||||
|
|
||||||
<para>The <structfield>min*</structfield> and
|
|
||||||
<structfield>max*</structfield> fields indicate the maximum size of a
|
|
||||||
framebuffer for this device (i.e., the scanout size limit).</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Return Value</title>
|
|
||||||
<para><function>drmModeGetResources</function> returns a drmModeRes
|
|
||||||
structure pointer on success, <literal>NULL</literal> on failure. The
|
|
||||||
returned structure must be freed with
|
|
||||||
<citerefentry><refentrytitle>drmModeFreeResources</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Reporting Bugs</title>
|
|
||||||
<para>Bugs in this function should be reported to
|
|
||||||
https://gitlab.freedesktop.org/mesa/drm/-/issues</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>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>drmModeDirtyFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmModeGetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmModeSetCrtc</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmModeGetEncoder</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>drmModeGetConnector</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
|
@ -18,50 +18,23 @@
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
xsltproc_args = [
|
rst_pages = [
|
||||||
'--stringparam', 'man.authors.section.enabled', '0',
|
['drm', '7'],
|
||||||
'--stringparam', 'man.copyright.section.enabled', '0',
|
['drm-kms', '7'],
|
||||||
'--stringparam', 'funcsynopsis.style', 'ansi',
|
['drm-memory', '7'],
|
||||||
'--stringparam', 'man.output.quietly', '1',
|
['drmAvailable', '3'],
|
||||||
'--nonet', manpage_style,
|
['drmHandleEvent', '3'],
|
||||||
|
['drmModeGetResources', '3'],
|
||||||
]
|
]
|
||||||
|
foreach page : rst_pages
|
||||||
xmls = [
|
name = page[0] + '.' + page[1]
|
||||||
['drm', '7'], ['drm-kms', '7'], ['drm-memory', '7'], ['drmAvailable', '3'],
|
rst = files(name + '.rst')
|
||||||
['drmHandleEvent', '3'], ['drmModeGetResources', '3']
|
|
||||||
]
|
|
||||||
foreach x : xmls
|
|
||||||
m = x[0]
|
|
||||||
s = x[1]
|
|
||||||
custom_target(
|
custom_target(
|
||||||
m,
|
name,
|
||||||
input : files('@0@.xml'.format(m)),
|
input : rst,
|
||||||
output : '@0@.@1@'.format(m, s),
|
output : name,
|
||||||
command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT0@'],
|
command : [prog_rst2man, '@INPUT@', '@OUTPUT@'],
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : join_paths(get_option('mandir'), 'man@0@'.format(s)),
|
install_dir : join_paths(get_option('mandir'), 'man' + page[1]),
|
||||||
build_by_default : true,
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
foreach x : ['drm-mm', 'drm-gem', 'drm-ttm']
|
|
||||||
gen = custom_target(
|
|
||||||
'gen-@0@'.format(x),
|
|
||||||
input : 'drm-memory.xml',
|
|
||||||
output : '@0@.xml'.format(x),
|
|
||||||
command : [
|
|
||||||
prog_sed, '-e', 's@^\.so \([a-z_]\+\)\.\([0-9]\)$$@\.so man\2\/\1\.\2@',
|
|
||||||
'@INPUT@',
|
|
||||||
],
|
|
||||||
capture : true,
|
|
||||||
)
|
|
||||||
custom_target(
|
|
||||||
'@0@.7'.format(x),
|
|
||||||
input : gen,
|
|
||||||
output : '@0@.7'.format(x, '7'),
|
|
||||||
command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT@'],
|
|
||||||
install : true,
|
|
||||||
install_dir : join_paths(get_option('mandir'), 'man7'),
|
|
||||||
build_by_default : true,
|
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
14
meson.build
14
meson.build
|
@ -261,18 +261,8 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
with_man_pages = get_option('man-pages')
|
with_man_pages = get_option('man-pages')
|
||||||
prog_xslt = find_program('xsltproc', required : with_man_pages == 'true')
|
prog_rst2man = find_program('rst2man', required: with_man_pages == 'true')
|
||||||
prog_sed = find_program('sed', required : with_man_pages == 'true')
|
with_man_pages = with_man_pages != 'false' and prog_rst2man.found()
|
||||||
manpage_style = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
|
|
||||||
if prog_xslt.found()
|
|
||||||
if run_command(prog_xslt, '--nonet', manpage_style).returncode() != 0
|
|
||||||
if with_man_pages == 'true'
|
|
||||||
error('Manpage style sheet cannot be found')
|
|
||||||
endif
|
|
||||||
with_man_pages = 'false'
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
with_man_pages = with_man_pages != 'false' and prog_xslt.found() and prog_sed.found()
|
|
||||||
|
|
||||||
config.set10('HAVE_VISIBILITY',
|
config.set10('HAVE_VISIBILITY',
|
||||||
cc.compiles('''int foo_hidden(void) __attribute__((visibility(("hidden"))));''',
|
cc.compiles('''int foo_hidden(void) __attribute__((visibility(("hidden"))));''',
|
||||||
|
|
Loading…
Reference in New Issue