1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index c1d173c..67bea37 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -667,4 +667,22 @@ extern void drmMsg(const char *format, ...);
extern int drmSetMaster(int fd);
extern int drmDropMaster(int fd);
+#define DRM_EVENT_CONTEXT_VERSION 1
+
+typedef struct _drmEventContext {
+
+ /* This struct is versioned so we can add more pointers if we
+ * add more events. */
+ int version;
+
+ void (*page_flip_handler)(int fd,
+ unsigned int frame,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
+
+} drmEventContext, *drmEventContextPtr;
+
+extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
+
#endif
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index ea11207..f601a00 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -664,3 +664,56 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
return 0;
}
+
+int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, void *user_data)
+{
+ struct drm_mode_page_flip flip;
+
+ flip.fb_id = fb_id;
+ flip.crtc_id = crtc_id;
+ flip.user_data = VOID2U64(user_data);
+ flip.flags = 0;
+
+ return drmIoctl(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
+}
+
+int drmHandleEvent(int fd, drmEventContextPtr evctx)
+{
+ char buffer[1024];
+ int len, i;
+ struct drm_event *e;
+ struct drm_event_page_flip *page_flip;
+
+ /* The DRM read semantics guarantees that we always get only
+ * complete events. */
+
+ len = read(fd, buffer, sizeof buffer);
+ if (len == 0)
+ return 0;
+ if (len < sizeof *e)
+ return -1;
+
+ i = 0;
+ while (i < len) {
+ e = (struct drm_event *) &buffer[i];
+ switch (e->type) {
+ case DRM_EVENT_MODE_PAGE_FLIP:
+ if (evctx->version < 1 ||
+ evctx->page_flip_handler == NULL)
+ break;
+ page_flip = (struct drm_event_page_flip *) e;
+ evctx->page_flip_handler(fd,
+ page_flip->frame,
+ page_flip->tv_sec,
+ page_flip->tv_usec,
+ U642VOID (page_flip->user_data));
+ break;
+
+ default:
+ break;
+ }
+ i += e->length;
+ }
+
+ return 0;
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index 62304bb..fe64707 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -259,8 +259,6 @@ typedef struct _drmModeConnector {
uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;
-
-
extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
extern void drmModeFreeResources( drmModeResPtr ptr );
extern void drmModeFreeFB( drmModeFBPtr ptr );
@@ -362,3 +360,4 @@ extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue);
extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue);
+extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, void *user_data);
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 97fab9a..8b504cb 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -1113,6 +1113,7 @@ struct drm_gem_open {
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, uint32_t)
+#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOW( 0xB0, struct drm_mode_page_flip)
/*@}*/
@@ -1128,6 +1129,30 @@ struct drm_gem_open {
#define DRM_COMMAND_BASE 0x40
#define DRM_COMMAND_END 0xA0
+/**
+ * Header for events written back to userspace on the drm fd. The
+ * type defines the type of event, the length specifies the total
+ * length of the event (including the header), and user_data is
+ * typically a 64 bit value passed with the ioctl that triggered the
+ * event. A read on the drm fd will always only return complete
+ * events, that is, if for example the read buffer is 100 bytes, and
+ * there are two 64 byte events pending, only one will be returned.
+ */
+struct drm_event {
+ uint32_t type;
+ uint32_t length;
+};
+
+#define DRM_EVENT_MODE_PAGE_FLIP 0x01
+
+struct drm_event_page_flip {
+ struct drm_event base;
+ uint64_t user_data;
+ uint32_t tv_sec;
+ uint32_t tv_usec;
+ uint32_t frame;
+};
+
/* typedef area */
#ifndef __KERNEL__
typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/shared-core/drm_mode.h b/shared-core/drm_mode.h
index 9b92733..bebe4e7 100644
--- a/shared-core/drm_mode.h
+++ b/shared-core/drm_mode.h
@@ -270,4 +270,20 @@ struct drm_mode_crtc_lut {
uint64_t blue;
};
+#define DRM_MODE_PAGE_FLIP_WAIT (1<<0) /* block on previous page flip */
+#define DRM_MODE_PAGE_FLIP_FLAGS_MASK (DRM_MODE_PAGE_FLIP_WAIT)
+
+struct drm_mode_page_flip {
+ /** Handle of new front buffer */
+ uint32_t fb_id;
+ uint32_t crtc_id;
+
+ /* 64 bit cookie returned to userspace in the page flip event. */
+ uint64_t user_data;
+ /**
+ * page flip flags (wait on flip only for now)
+ */
+ uint32_t flags;
+};
+
#endif
|