1 <?xml version='1.0'?> <!--*-nxml-*--> 2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 3 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 4 5 <!-- 6 Written 2012 by David Herrmann <dh.herrmann (a] googlemail.com> 7 Dedicated to the Public Domain 8 --> 9 10 <refentry id="drm-memory"> 11 <refentryinfo> 12 <title>Direct Rendering Manager</title> 13 <productname>libdrm</productname> 14 <date>September 2012</date> 15 <authorgroup> 16 <author> 17 <contrib>Developer</contrib> 18 <firstname>David</firstname> 19 <surname>Herrmann</surname> 20 <email>dh.herrmann (a] googlemail.com</email> 21 </author> 22 </authorgroup> 23 </refentryinfo> 24 25 <refmeta> 26 <refentrytitle>drm-memory</refentrytitle> 27 <manvolnum>7</manvolnum> 28 </refmeta> 29 30 <refnamediv> 31 <refname>drm-memory</refname> 32 <refname>drm-mm</refname> 33 <refname>drm-gem</refname> 34 <refname>drm-ttm</refname> 35 <refpurpose>DRM Memory Management</refpurpose> 36 </refnamediv> 37 38 <refsynopsisdiv> 39 <funcsynopsis> 40 <funcsynopsisinfo>#include <xf86drm.h></funcsynopsisinfo> 41 </funcsynopsis> 42 </refsynopsisdiv> 43 44 <refsect1> 45 <title>Description</title> 46 <para>Many modern high-end GPUs come with their own memory managers. They 47 even include several different caches that need to be synchronized 48 during access. Textures, framebuffers, command buffers and more need 49 to be stored in memory that can be accessed quickly by the GPU. 50 Therefore, memory management on GPUs is highly driver- and 51 hardware-dependent.</para> 52 53 <para>However, there are several frameworks in the kernel that are used by 54 more than one driver. These can be used for trivial mode-setting 55 without requiring driver-dependent code. But for 56 hardware-accelerated rendering you need to read the manual pages for 57 the driver you want to work with.</para> 58 59 <refsect2> 60 <title>Dumb-Buffers</title> 61 <para>Almost all in-kernel DRM hardware drivers support an API called 62 <emphasis>Dumb-Buffers</emphasis>. This API allows to create buffers 63 of arbitrary size that can be used for scanout. These buffers can be 64 memory mapped via 65 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> 66 so you can render into them on the CPU. However, GPU access to these 67 buffers is often not possible. Therefore, they are fine for simple 68 tasks but not suitable for complex compositions and 69 renderings.</para> 70 71 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl can be 72 used to create a dumb buffer. The kernel will return a 32bit handle 73 that can be used to manage the buffer with the DRM API. You can 74 create framebuffers with 75 <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry> 76 and use it for mode-setting and scanout. To access the buffer, you 77 first need to retrieve the offset of the buffer. The 78 <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> ioctl requests the DRM 79 subsystem to prepare the buffer for memory-mapping and returns a 80 fake-offset that can be used with 81 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para> 82 83 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl takes as 84 argument a structure of type 85 <structname>struct drm_mode_create_dumb</structname>: 86 87 <programlisting> 88 struct drm_mode_create_dumb { 89 __u32 height; 90 __u32 width; 91 __u32 bpp; 92 __u32 flags; 93 94 __u32 handle; 95 __u32 pitch; 96 __u64 size; 97 }; 98 </programlisting> 99 100 The fields <structfield>height</structfield>, 101 <structfield>width</structfield>, <structfield>bpp</structfield> and 102 <structfield>flags</structfield> have to be provided by the caller. 103 The other fields are filled by the kernel with the return values. 104 <structfield>height</structfield> and 105 <structfield>width</structfield> are the dimensions of the 106 rectangular buffer that is created. <structfield>bpp</structfield> 107 is the number of bits-per-pixel and must be a multiple of 108 <literal>8</literal>. You most commonly want to pass 109 <literal>32</literal> here. The <structfield>flags</structfield> 110 field is currently unused and must be zeroed. Different flags to 111 modify the behavior may be added in the future. After calling the 112 ioctl, the <structfield>handle</structfield>, 113 <structfield>pitch</structfield> and <structfield>size</structfield> 114 fields are filled by the kernel. <structfield>handle</structfield> 115 is a 32bit gem handle that identifies the buffer. This is used by 116 several other calls that take a gem-handle or memory-buffer as 117 argument. The <structfield>pitch</structfield> field is the 118 pitch (or stride) of the new buffer. Most drivers use 32bit or 64bit 119 aligned stride-values. The <structfield>size</structfield> field 120 contains the absolute size in bytes of the buffer. This can normally 121 also be computed with 122 <emphasis>(height * pitch + width) * bpp / 4</emphasis>.</para> 123 124 <para>To prepare the buffer for 125 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> 126 you need to use the <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> 127 ioctl. It takes as argument a structure of type 128 <structname>struct drm_mode_map_dumb</structname>: 129 130 <programlisting> 131 struct drm_mode_map_dumb { 132 __u32 handle; 133 __u32 pad; 134 135 __u64 offset; 136 }; 137 </programlisting> 138 139 You need to put the gem-handle that was previously retrieved via 140 <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> into the 141 <structfield>handle</structfield> field. The 142 <structfield>pad</structfield> field is unused padding and must be 143 zeroed. After completion, the <structfield>offset</structfield> 144 field will contain an offset that can be used with 145 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> 146 on the DRM file-descriptor.</para> 147 148 <para>If you don't need your dumb-buffer, anymore, you have to destroy it 149 with <constant>DRM_IOCTL_MODE_DESTROY_DUMB</constant>. If you close 150 the DRM file-descriptor, all open dumb-buffers are automatically 151 destroyed. This ioctl takes as argument a structure of type 152 <structname>struct drm_mode_destroy_dumb</structname>: 153 154 <programlisting> 155 struct drm_mode_destroy_dumb { 156 __u32 handle; 157 }; 158 </programlisting> 159 160 You only need to put your handle into the 161 <structfield>handle</structfield> field. After this call, the handle 162 is invalid and may be reused for new buffers by the dumb-API.</para> 163 164 </refsect2> 165 166 <refsect2> 167 <title>TTM</title> 168 <para><emphasis>TTM</emphasis> stands for 169 <emphasis>Translation Table Manager</emphasis> and is a generic 170 memory-manager provided by the kernel. It does not provide a common 171 user-space API so you need to look at each driver interface if you 172 want to use it. See for instance the radeon manpages for more 173 information on memory-management with radeon and TTM.</para> 174 </refsect2> 175 176 <refsect2> 177 <title>GEM</title> 178 <para><emphasis>GEM</emphasis> stands for 179 <emphasis>Graphics Execution Manager</emphasis> and is a generic DRM 180 memory-management framework in the kernel, that is used by many 181 different drivers. Gem is designed to manage graphics memory, 182 control access to the graphics device execution context and handle 183 essentially NUMA environment unique to modern graphics hardware. Gem 184 allows multiple applications to share graphics device resources 185 without the need to constantly reload the entire graphics card. Data 186 may be shared between multiple applications with gem ensuring that 187 the correct memory synchronization occurs.</para> 188 189 <para>Gem provides simple mechanisms to manage graphics data and control 190 execution flow within the linux DRM subsystem. However, gem is not a 191 complete framework that is fully driver independent. Instead, if 192 provides many functions that are shared between many drivers, but 193 each driver has to implement most of memory-management with 194 driver-dependent ioctls. This manpage tries to describe the 195 semantics (and if it applies, the syntax) that is shared between all 196 drivers that use gem.</para> 197 198 <para>All GEM APIs are defined as 199 <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> 200 on the DRM file descriptor. An application must be authorized via 201 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry> 202 to the current DRM-Master to access the GEM subsystem. A driver that 203 does not support gem will return <constant>ENODEV</constant> for all 204 these ioctls. Invalid object handles return 205 <constant>EINVAL</constant> and invalid object names return 206 <constant>ENOENT</constant>.</para> 207 208 <para>Gem provides explicit memory management primitives. System pages are 209 allocated when the object is created, either as the fundamental 210 storage for hardware where system memory is used by the graphics 211 processor directly, or as backing store for graphics-processor 212 resident memory.</para> 213 214 <para>Objects are referenced from user-space using handles. These are, for 215 all intents and purposes, equivalent to file descriptors but avoid 216 the overhead. Newer kernel drivers also support the 217 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> 218 infrastructure which can return real file-descriptor for gem-handles 219 using the linux dma-buf API. Objects may be published with a name so 220 that other applications and processes can access them. The name 221 remains valid as long as the object exists. Gem-objects are 222 reference counted in the kernel. The object is only destroyed when 223 all handles from user-space were closed.</para> 224 225 <para>Gem-buffers cannot be created with a generic API. Each driver 226 provides its own API to create gem-buffers. See for example 227 <constant>DRM_I915_GEM_CREATE</constant>, 228 <constant>DRM_NOUVEAU_GEM_NEW</constant> or 229 <constant>DRM_RADEON_GEM_CREATE</constant>. Each of these ioctls 230 returns a gem-handle that can be passed to different generic ioctls. 231 The <emphasis>libgbm</emphasis> library from the 232 <emphasis>mesa3D</emphasis> distribution tries to provide a 233 driver-independent API to create gbm buffers and retrieve a 234 gbm-handle to them. It allows to create buffers for different 235 use-cases including scanout, rendering, cursors and CPU-access. See 236 the libgbm library for more information or look at the 237 driver-dependent man-pages (for example 238 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry> 239 or 240 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para> 241 242 <para>Gem-buffers can be closed with the 243 <constant>DRM_IOCTL_GEM_CLOSE</constant> ioctl. It takes as argument 244 a structure of type <structname>struct drm_gem_close</structname>: 245 246 <programlisting> 247 struct drm_gem_close { 248 __u32 handle; 249 __u32 pad; 250 }; 251 </programlisting> 252 253 The <structfield>handle</structfield> field is the gem-handle to be 254 closed. The <structfield>pad</structfield> field is unused padding. 255 It must be zeroed. After this call the gem handle cannot be used by 256 this process anymore and may be reused for new gem objects by the 257 gem API.</para> 258 259 <para>If you want to share gem-objects between different processes, you 260 can create a name for them and pass this name to other processes 261 which can then open this gem-object. Names are currently 32bit 262 integer IDs and have no special protection. That is, if you put a 263 name on your gem-object, every other client that has access to the 264 DRM device and is authenticated via 265 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry> 266 to the current DRM-Master, can <emphasis>guess</emphasis> the name 267 and open or access the gem-object. If you want more fine-grained 268 access control, you can use the new 269 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> 270 API to retrieve file-descriptors for gem-handles. To create a name 271 for a gem-handle, you use the 272 <constant>DRM_IOCTL_GEM_FLINK</constant> ioctl. It takes as argument 273 a structure of type <structname>struct drm_gem_flink</structname>: 274 275 <programlisting> 276 struct drm_gem_flink { 277 __u32 handle; 278 __u32 name; 279 }; 280 </programlisting> 281 282 You have to put your handle into the 283 <structfield>handle</structfield> field. After completion, the 284 kernel has put the new unique name into the 285 <structfield>name</structfield> field. You can now pass this name to 286 other processes which can then import the name with the 287 <constant>DRM_IOCTL_GEM_OPEN</constant> ioctl. It takes as argument 288 a structure of type <structname>struct drm_gem_open</structname>: 289 290 <programlisting> 291 struct drm_gem_open { 292 __u32 name; 293 294 __u32 handle; 295 __u32 size; 296 }; 297 </programlisting> 298 299 You have to fill in the <structfield>name</structfield> field with 300 the name of the gem-object that you want to open. The kernel will 301 fill in the <structfield>handle</structfield> and 302 <structfield>size</structfield> fields with the new handle and size 303 of the gem-object. You can now access the gem-object via the handle 304 as if you created it with the gem API.</para> 305 306 <para>Besides generic buffer management, the GEM API does not provide any 307 generic access. Each driver implements its own functionality on top 308 of this API. This includes execution-buffers, GTT management, 309 context creation, CPU access, GPU I/O and more. The next 310 higher-level API is <emphasis>OpenGL</emphasis>. So if you want to 311 use more GPU features, you should use the 312 <emphasis>mesa3D</emphasis> library to create OpenGL contexts on DRM 313 devices. This does <emphasis>not</emphasis> require any 314 windowing-system like X11, but can also be done on raw DRM devices. 315 However, this is beyond the scope of this man-page. You may have a 316 look at other mesa3D manpages, including libgbm and libEGL. 2D 317 software-rendering (rendering with the CPU) can be achieved with the 318 dumb-buffer-API in a driver-independent fashion, however, for 319 hardware-accelerated 2D or 3D rendering you must use OpenGL. Any 320 other API that tries to abstract the driver-internals to access 321 GEM-execution-buffers and other GPU internals, would simply reinvent 322 OpenGL so it is not provided. But if you need more detailed 323 information for a specific driver, you may have a look into the 324 driver-manpages, including 325 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 326 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry> 327 and 328 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>. 329 However, the 330 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry> 331 infrastructure and the generic gem API as described here allow 332 display-managers to handle graphics-buffers and render-clients 333 without any deeper knowledge of the GPU that is used. Moreover, it 334 allows to move objects between GPUs and implement complex 335 display-servers that don't do any rendering on their own. See its 336 man-page for more information.</para> 337 </refsect2> 338 </refsect1> 339 340 <refsect1> 341 <title>Examples</title> 342 <para>This section includes examples for basic memory-management 343 tasks.</para> 344 345 <refsect2> 346 <title>Dumb-Buffers</title> 347 <para>This examples shows how to create a dumb-buffer via the generic 348 DRM API. This is driver-independent (as long as the driver 349 supports dumb-buffers) and provides memory-mapped buffers that can 350 be used for scanout. This example creates a full-HD 1920x1080 351 buffer with 32 bits-per-pixel and a color-depth of 24 bits. The 352 buffer is then bound to a framebuffer which can be used for 353 scanout with the KMS API (see 354 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para> 355 356 <programlisting> 357 struct drm_mode_create_dumb creq; 358 struct drm_mode_destroy_dumb dreq; 359 struct drm_mode_map_dumb mreq; 360 uint32_t fb; 361 int ret; 362 void *map; 363 364 /* create dumb buffer */ 365 memset(&creq, 0, sizeof(creq)); 366 creq.width = 1920; 367 creq.height = 1080; 368 creq.bpp = 32; 369 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); 370 if (ret < 0) { 371 /* buffer creation failed; see "errno" for more error codes */ 372 ... 373 } 374 /* creq.pitch, creq.handle and creq.size are filled by this ioctl with 375 * the requested values and can be used now. */ 376 377 /* create framebuffer object for the dumb-buffer */ 378 ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb); 379 if (ret) { 380 /* frame buffer creation failed; see "errno" */ 381 ... 382 } 383 /* the framebuffer "fb" can now used for scanout with KMS */ 384 385 /* prepare buffer for memory mapping */ 386 memset(&mreq, 0, sizeof(mreq)); 387 mreq.handle = creq.handle; 388 ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); 389 if (ret) { 390 /* DRM buffer preparation failed; see "errno" */ 391 ... 392 } 393 /* mreq.offset now contains the new offset that can be used with mmap() */ 394 395 /* perform actual memory mapping */ 396 map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); 397 if (map == MAP_FAILED) { 398 /* memory-mapping failed; see "errno" */ 399 ... 400 } 401 402 /* clear the framebuffer to 0 */ 403 memset(map, 0, creq.size); 404 </programlisting> 405 406 </refsect2> 407 408 </refsect1> 409 410 <refsect1> 411 <title>Reporting Bugs</title> 412 <para>Bugs in this manual should be reported to 413 http://bugs.freedesktop.org under the "Mesa" product, with "Other" or 414 "libdrm" as the component.</para> 415 </refsect1> 416 417 <refsect1> 418 <title>See Also</title> 419 <para> 420 <citerefentry><refentrytitle>drm</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 421 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 422 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 423 <citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>, 424 <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>, 425 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 426 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>, 427 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry> 428 </para> 429 </refsect1> 430 </refentry> 431