Why and How to use KMS as Your Userspace Display API of Choice · Why and How to use KMS as Your...

52
Why and How to use KMS as Your Userspace Display API of Choice LinuxCon Japan 2013 Tokyo – 2013/05/31 Laurent Pinchart [email protected]

Transcript of Why and How to use KMS as Your Userspace Display API of Choice · Why and How to use KMS as Your...

Why and How to use KMS asYour Userspace Display API of

Choice

LinuxCon Japan 2013Tokyo – 2013/05/31

Laurent [email protected]

FeaturesSource: http://xkcd.com/619/

Memory Management

DRM FB

Dynamic Allocation Yes No

Multiple Buffers Yes panning

Import dmabuf No

Exportdmabufmmap

mmap

Mode Setting

DRM FB

Formats 4CCRGB4CC

Enumeration Planes No

Negotiation No No

Atomicity Yes No

Transformations

DRM FB

Overlays Yes No

Rotation Yes No

Scaling Yes No

Cropping/Panning Yes Yes

Device Model – FBDEV

Frame Buffer(memory)

DisplayDevice

Device Model – DRM/KMS

Frame Buffer(memory) CRTC Encoder Connector

Plane(memory)

Activity – DRM/KMS

2000

DRM, L

inux 2

.2.1

8

2009

KMS, T

TM

2008

GEMPlan

es, D

MABUF

2011 2012

Dumb

Buffe

rs

2013

Atom

ic m

ode

settin

g

Sync &

fenc

es

Activity – FBDEV

FBDEV, L

inux 1

.3.9

4

1996 2012

4CC F

orm

ats

2000

Blankin

g

Activity – FBDEVSource: http://valdodge.com/2010/07/

2012

4CC F

orm

ats

Mailing List Traffic

2009-112010-01

2010-032010-05

2010-072010-09

2010-112011-01

2011-032011-05

2011-072011-09

2011-112012-01

2012-032012-05

2012-072012-09

2012-112013-01

2013-03

0

200

400

600

800

1000

1200

1400

1600

1800

drmfbdrm+bug

Cumulative Changes - API

v2.6.12v2.6.14

v2.6.16v2.6.18

v2.6.20v2.6.22

v2.6.24v2.6.26

v2.6.28v2.6.30

v2.6.32v2.6.34

v2.6.36v2.6.38

v3.0v3.2

v3.4v3.6

v3.8v3.10-rc2

0

200

400

600

800

1000

1200

1400

1600

1800

drm

fb

drmfb

Cumulative Changes - Core

v2.6.12v2.6.14

v2.6.16v2.6.18

v2.6.20v2.6.22

v2.6.24v2.6.26

v2.6.28v2.6.30

v2.6.32v2.6.34

v2.6.36v2.6.38

v3.0v3.2

v3.4v3.6

v3.8v3.10-rc2

0

5000

10000

15000

20000

25000

30000

35000

40000

drm

fb

drmfb

Cumulative Changes - Drivers

v2.6.12v2.6.14

v2.6.16v2.6.18

v2.6.20v2.6.22

v2.6.24v2.6.26

v2.6.28v2.6.30

v2.6.32v2.6.34

v2.6.36v2.6.38

v3.0v3.2

v3.4v3.6

v3.8v3.10-rc2

0

100000

200000

300000

400000

500000

600000

700000

800000

900000

drm

fb

drmfb

Use CasesSource: http://xkcd.com/927/

Use Cases - FBDEV

Use Cases - FBDEV

(that's it...)

Use Cases – DRM/KMS

Everything else

DRM KMS?

APIs

DRM

● Memory Management● Vertical Blanking● Version, Authentication,

Master, ...

KMS

● Device Model● Frame Buffer● Modes● Page Flip● Planes● Cursor, Gamma, ...

DRM/KMS API

drmkmsexynosi810i915mganouveaur128radeonsavagesisvia

Device Model

Frame Buffer(memory) CRTC Encoder Connector

Planes(memory)

Encoder

Connector

Connector

Device Model - SoC

Frame Buffer(memory) CRTC Encoder Connector

Plane(memory)

SoCMemory Off-Chip

Encoder Connector

KMS – Scanout

Frame Buffer

KMS – Composition

CRTC

Plane(s)

Composition

KMS – Frame Buffer

CRTC

Frame Buffer

GEMObject(s)

Memory

● width● height● format● pitches● offsets

Properties

DRM/KMS – GEM Object

CRTC

Frame Buffer

GEM Object

● width● height● bpp● pitch● size

Properties

Memory

DRM – Handles

Process A

LocalHandle

GEMObject

Process B

Send FDSCM_RIGHTS

GlobalFD

1 2Global

FD4

LocalHandle

3

ActiveArea

KMS – Modes (1/2)

sync

back porch

front porch

active area

ActiveArea

KMS – Modes (2/2)

sync

back porch

front porch

active area

hdisplayhsync_start

htotal

hsync_end

KMS – Mode Setting

crtc

fb

ActiveArea

x

y

mode.hdisplay

mo

de

. vdisp

l ay

*connectorsnum_connectors

mode

struct drm_mode_set { struct drm_framebuffer *fb; struct drm_crtc *crtc; struct drm_display_mode *mode; uint32_t x; uint32_t y; struct drm_connector **connectors; size_t num_connectors;};

Disclaimer

Code Ahead

Error handling omitted for readability

Skeleton

#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>

int main(int argc, char **argv){ return 0;}

Open

/* * Open * * #include <xf86drm.h> * * int drmOpen(const char *name, const char *busid); */int fd;

fd = drmOpen("rcar-du", NULL);

Get Resources

/* * Get resources * * #include <xf86drmMode.h> * * drmModeResPtr drmModeGetResources(int fd); * void drmModeFreeResources(drmModeResPtr ptr); */drmModeResPtr resources;uint32_t crtc_id;uint32_t connector_id;

resources = drmModeGetResources(fd);

crtc_id = resources->crtcs[0];connector_id = resources->connectors[0];

Get Modes

/* * Get modes * * #include <xf86drmMode.h> * * drmModeConnectorPtr drmModeGetConnector(int fd, * uint32_t connectorId); * void drmModeFreeConnector(drmModeConnectorPtr ptr); */drmModeConnectorPtr connector;drmModeModeInfo mode;uint32_t width;uint32_t height;

connector = drmModeGetConnector(fd, connector_id);

mode = connector->modes[0];width = mode.hdisplay;height = mode.vdisplay;

Initialize libkms

/* * Initialize libkms * * #include <libkms.h> * * int kms_create(int fd, struct kms_driver **out); * int kms_destroy(struct kms_driver **kms); */struct kms_driver *kms;

kms_create(fd, &kms);

Create Buffer

/* * Create buffer * * #include <libkms.h> * * int kms_bo_create(struct kms_driver *kms, * const unsigned *attr, struct kms_bo **out); * int kms_bo_destroy(struct kms_bo **bo); */unsigned bo_attribs[] = {

KMS_WIDTH, width,KMS_HEIGHT, height,KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,KMS_TERMINATE_PROP_LIST

};struct kms_bo *bo;

kms_bo_create(kms, bo_attribs, &bo);

Get Buffer Handle and Pitch

/* * Get buffer handle and pitch * * #include <libkms.h> * * int kms_bo_get_prop(struct kms_bo *bo, unsigned key, * unsigned *out); */uint32_t handles[4];uint32_t pitches[4];uint32_t offsets[4];

kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);offsets[0] = 0;

Fill Buffer

/* * Fill buffer * * #include <libkms.h> * * int kms_bo_map(struct kms_bo *bo, void **out); * int kms_bo_unmap(struct kms_bo *bo); */void *plane;

kms_bo_map(bo, &plane);fill_pattern(DRM_FORMAT_ARGB8888, plane, width, height, pitches[0]);kms_bo_unmap(bo);

Create Frame Buffer

/* * Create frame buffer * * #include <drm_fourcc.h> * #include <xf86drmMode.h> * * int drmModeAddFB2(int fd, uint32_t width, * uint32_t height, uint32_t pixel_format, * uint32_t bo_handles[4], uint32_t pitches[4], * uint32_t offsets[4], uint32_t *buf_id, * uint32_t flags); */uint32_t fb_id;

drmModeAddFB2(fd, width, height, DRM_FORMAT_ARGB8888, handles, pitches, offsets, &fb_id, 0);

Set the Mode

/* * Set the mode * * #include <xf86drmMode.h> * * int drmModeSetCrtc(int fd, uint32_t crtcId, * uint32_t bufferId, uint32_t x, uint32_t y, * uint32_t *connectors, int count, * drmModeModeInfoPtr mode); */drmModeSetCrtc(fd, crtc_id, fb_id, 0, 0, &connector_id, 1, &mode);

Get Plane Resources

/* * Get plane resources * * #include <xf86drmMode.h> * * drmModePlaneResPtr drmModeGetPlaneResources(int fd); * void drmModeFreePlaneResources(drmModePlaneResPtr ptr); */drmModePlaneResPtr planes;uint32_t plane_id;

planes = drmModeGetPlaneResources(fd);plane_id = planes->planes[0];

Set the Plane

/* * Set the plane * * #include <xf86drmMode.h> * * int drmModeSetPlane(int fd, * uint32_t plane_id, uint32_t crtc_id, * uint32_t fb_id, uint32_t flags, * uint32_t crtc_x, uint32_t crtc_y, * uint32_t crtc_w, uint32_t crtc_h, * uint32_t src_x, uint32_t src_y, * uint32_t src_w, uint32_t src_h); */drmModeSetPlane(fd, plane_id, crtc_id, fb_id, 0,

width / 4, height / 4, width / 2, height / 2,0, 0, (width / 2) << 16, (height / 2) << 16);

List Plane Properties

/* * List plane properties * * #include <drm_mode.h> * #include <xf86drmMode.h> * * drmModeObjectPropertiesPtr drmModeObjectGetProperties( * int fd, uint32_t object_id, uint32_t object_type); * void drmModeFreeObjectProperties( * drmModeObjectPropertiesPtr ptr); */drmModeObjectPropertiesPtr properties;

properties = drmModeObjectGetProperties(fd, plane_id, DRM_MODE_OBJECT_PLANE);

Find Color Keying Property

/* * Find color keying property * * #include <xf86drmMode.h> * * drmModePropertyPtr drmModeGetProperty(int fd, * uint32_t propertyId); * void drmModeFreeProperty(drmModePropertyPtr ptr); */drmModePropertyPtr property;unsigned int i;

for (i = 0; i < properties->count_props; ++i) { property = drmModeGetProperty(fd, properties->props[i]); if (!strcmp(property->name, "colorkey")) break;}

Turn Color Keying On

/* * Turn color keying on * * #include <xf86drmMode.h> * * int drmModeObjectSetProperty(int fd, uint32_t object_id, * uint32_t object_type, uint32_t property_id, * uint64_t value); */drmModeObjectSetProperty(fd, plane_id, DRM_MODE_OBJECT_PLANE, property->prop_id, 0x0100c0c0);

And Much More...

● Page Flip● Cursor● Events● ...

? !

thx.