aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä2015-06-22 11:26:02 -0500
committerEmil Velikov2015-06-29 13:01:19 -0500
commited44e0b9585c563905447eceed12af9c1c7ca8d4 (patch)
tree99c759a7b1e2e24875ec32bef4d45115c891ea40 /xf86drmMode.c
parent5b0e76f143887c4ec7db45c54a7ba27a58f59227 (diff)
downloadexternal-libdrm-ed44e0b9585c563905447eceed12af9c1c7ca8d4.tar.gz
external-libdrm-ed44e0b9585c563905447eceed12af9c1c7ca8d4.tar.xz
external-libdrm-ed44e0b9585c563905447eceed12af9c1c7ca8d4.zip
Support atomic modesetting ioctl
Add support for the atomic modesetting ioctl through a property-set API. v1: Squashed intermediate patches from Ville, Rob and myself. Updated for current kernel interface (no blobs). v2: Rewrite user-facing API to provide transactional/cursor interface. Use memclear to zero out ioctl. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Rob Clark <robclark@freedesktop.org> Signed-off-by: Daniel Stone <daniels@collabora.com> v3 [Emil Velikov]: Remove DRM_CAP_ATOMIC - superseded by DRM_CLIENT_CAP_ATOMIC. Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Diffstat (limited to 'xf86drmMode.c')
-rw-r--r--xf86drmMode.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 1333da48..a75eca33 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -37,9 +37,12 @@
37 * TODO the types we are after are defined in diffrent headers on diffrent 37 * TODO the types we are after are defined in diffrent headers on diffrent
38 * platforms find which headers to include to get uint32_t 38 * platforms find which headers to include to get uint32_t
39 */ 39 */
40#include <limits.h>
40#include <stdint.h> 41#include <stdint.h>
42#include <stdlib.h>
41#include <sys/ioctl.h> 43#include <sys/ioctl.h>
42#include <stdio.h> 44#include <stdio.h>
45#include <stdbool.h>
43 46
44#ifdef HAVE_CONFIG_H 47#ifdef HAVE_CONFIG_H
45#include "config.h" 48#include "config.h"
@@ -1147,3 +1150,240 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
1147 1150
1148 return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); 1151 return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
1149} 1152}
1153
1154typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr;
1155
1156struct _drmModeAtomicReqItem {
1157 uint32_t object_id;
1158 uint32_t property_id;
1159 uint64_t value;
1160};
1161
1162struct _drmModeAtomicReq {
1163 uint32_t cursor;
1164 uint32_t size_items;
1165 drmModeAtomicReqItemPtr items;
1166};
1167
1168drmModeAtomicReqPtr drmModeAtomicAlloc(void)
1169{
1170 drmModeAtomicReqPtr req;
1171
1172 req = drmMalloc(sizeof *req);
1173 if (!req)
1174 return NULL;
1175
1176 req->items = NULL;
1177 req->cursor = 0;
1178 req->size_items = 0;
1179
1180 return req;
1181}
1182
1183drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old)
1184{
1185 drmModeAtomicReqPtr new;
1186
1187 new = drmMalloc(sizeof *new);
1188 if (!new)
1189 return NULL;
1190
1191 new->cursor = old->cursor;
1192 new->size_items = old->size_items;
1193
1194 if (old->size_items) {
1195 new->items = drmMalloc(old->size_items * sizeof(*new->items));
1196 if (!new->items) {
1197 free(new);
1198 return NULL;
1199 }
1200 memcpy(new->items, old->items,
1201 old->size_items * sizeof(*new->items));
1202 } else {
1203 new->items = NULL;
1204 }
1205
1206 return new;
1207}
1208
1209int drmModeAtomicMerge(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment)
1210{
1211 if (!augment || augment->cursor == 0)
1212 return 0;
1213
1214 if (base->cursor + augment->cursor >= base->size_items) {
1215 drmModeAtomicReqItemPtr new;
1216 int saved_size = base->size_items;
1217
1218 base->size_items = base->cursor + augment->cursor;
1219 new = realloc(base->items,
1220 base->size_items * sizeof(*base->items));
1221 if (!new) {
1222 base->size_items = saved_size;
1223 return -ENOMEM;
1224 }
1225 base->items = new;
1226 }
1227
1228 memcpy(&base->items[base->cursor], augment->items,
1229 augment->cursor * sizeof(*augment->items));
1230 base->cursor += augment->cursor;
1231
1232 return 0;
1233}
1234
1235int drmModeAtomicGetCursor(drmModeAtomicReqPtr req)
1236{
1237 return req->cursor;
1238}
1239
1240void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor)
1241{
1242 req->cursor = cursor;
1243}
1244
1245int drmModeAtomicAddProperty(drmModeAtomicReqPtr req,
1246 uint32_t object_id,
1247 uint32_t property_id,
1248 uint64_t value)
1249{
1250 if (req->cursor >= req->size_items) {
1251 drmModeAtomicReqItemPtr new;
1252
1253 req->size_items += 16;
1254 new = realloc(req->items, req->size_items * sizeof(*req->items));
1255 if (!new) {
1256 req->size_items -= 16;
1257 return -ENOMEM;
1258 }
1259 req->items = new;
1260 }
1261
1262 req->items[req->cursor].object_id = object_id;
1263 req->items[req->cursor].property_id = property_id;
1264 req->items[req->cursor].value = value;
1265 req->cursor++;
1266
1267 return req->cursor;
1268}
1269
1270void drmModeAtomicFree(drmModeAtomicReqPtr req)
1271{
1272 if (!req)
1273 return;
1274
1275 if (req->items)
1276 drmFree(req->items);
1277 drmFree(req);
1278}
1279
1280static int sort_req_list(const void *misc, const void *other)
1281{
1282 const drmModeAtomicReqItem *first = misc;
1283 const drmModeAtomicReqItem *second = other;
1284
1285 if (first->object_id < second->object_id)
1286 return -1;
1287 else if (first->object_id > second->object_id)
1288 return 1;
1289 else
1290 return second->property_id - first->property_id;
1291}
1292
1293int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, uint32_t flags,
1294 void *user_data)
1295{
1296 drmModeAtomicReqPtr sorted = drmModeAtomicDuplicate(req);
1297 struct drm_mode_atomic atomic;
1298 uint32_t *objs_ptr = NULL;
1299 uint32_t *count_props_ptr = NULL;
1300 uint32_t *props_ptr = NULL;
1301 uint64_t *prop_values_ptr = NULL;
1302 uint32_t last_obj_id = 0;
1303 uint32_t i;
1304 int obj_idx = -1;
1305 int ret = -1;
1306
1307 if (!sorted)
1308 return -ENOMEM;
1309
1310 memclear(atomic);
1311
1312 /* Sort the list by object ID, then by property ID. */
1313 qsort(sorted->items, sorted->cursor, sizeof(*sorted->items),
1314 sort_req_list);
1315
1316 /* Now the list is sorted, eliminate duplicate property sets. */
1317 for (i = 0; i < sorted->cursor; i++) {
1318 if (sorted->items[i].object_id != last_obj_id) {
1319 atomic.count_objs++;
1320 last_obj_id = sorted->items[i].object_id;
1321 }
1322
1323 if (i == sorted->cursor - 1)
1324 continue;
1325
1326 if (sorted->items[i].object_id != sorted->items[i + 1].object_id ||
1327 sorted->items[i].property_id != sorted->items[i + 1].property_id)
1328 continue;
1329
1330 memmove(&sorted->items[i], &sorted->items[i + 1],
1331 (sorted->cursor - i - 1) * sizeof(*sorted->items));
1332 sorted->cursor--;
1333 }
1334
1335 objs_ptr = drmMalloc(atomic.count_objs * sizeof objs_ptr[0]);
1336 if (!objs_ptr) {
1337 errno = ENOMEM;
1338 goto out;
1339 }
1340
1341 count_props_ptr = drmMalloc(atomic.count_objs * sizeof count_props_ptr[0]);
1342 if (!count_props_ptr) {
1343 errno = ENOMEM;
1344 goto out;
1345 }
1346
1347 props_ptr = drmMalloc(sorted->cursor * sizeof props_ptr[0]);
1348 if (!props_ptr) {
1349 errno = ENOMEM;
1350 goto out;
1351 }
1352
1353 prop_values_ptr = drmMalloc(sorted->cursor * sizeof prop_values_ptr[0]);
1354 if (!prop_values_ptr) {
1355 errno = ENOMEM;
1356 goto out;
1357 }
1358
1359 for (i = 0, last_obj_id = 0; i < sorted->cursor; i++) {
1360 if (sorted->items[i].object_id != last_obj_id) {
1361 obj_idx++;
1362 objs_ptr[obj_idx] = sorted->items[i].object_id;
1363 last_obj_id = objs_ptr[obj_idx];
1364 }
1365
1366 count_props_ptr[obj_idx]++;
1367 props_ptr[i] = sorted->items[i].property_id;
1368 prop_values_ptr[i] = sorted->items[i].value;
1369
1370 }
1371
1372 atomic.flags = flags;
1373 atomic.objs_ptr = VOID2U64(objs_ptr);
1374 atomic.count_props_ptr = VOID2U64(count_props_ptr);
1375 atomic.props_ptr = VOID2U64(props_ptr);
1376 atomic.prop_values_ptr = VOID2U64(prop_values_ptr);
1377 atomic.user_data = VOID2U64(user_data);
1378
1379 ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
1380
1381out:
1382 drmFree(objs_ptr);
1383 drmFree(count_props_ptr);
1384 drmFree(props_ptr);
1385 drmFree(prop_values_ptr);
1386 drmModeAtomicFree(sorted);
1387
1388 return ret;
1389}