1 /*
2 * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL), available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32 #include <libdrm/drm_mode.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <stddef.h>
36 #include <xf86drmMode.h>
37 #include <sys/mman.h>
38 #include <unistd.h>
39 #include "rkdrm_display.h"
40
41 #define IS_SUPPORT_WINID_PROPERTY 0
42 #define INT_MAX 0xff
43 #define COLOR_KEY 0xFFFFFFFF
44
drm_plane_set_property(int fd,drmModePlane * plane,const char * prop_name,uint64_t prop_value)45 static bool drm_plane_set_property (int fd, drmModePlane * plane,
46 const char *prop_name, uint64_t prop_value)
47 {
48 drmModeObjectPropertiesPtr props;
49 drmModePropertyPtr prop;
50 int i, ret = -1;
51
52 props = drmModeObjectGetProperties (fd, plane->plane_id,
53 DRM_MODE_OBJECT_PLANE);
54 if (!props)
55 return false;
56
57 for (i = 0; i < props->count_props; i++) {
58 prop = drmModeGetProperty (fd, props->props[i]);
59 if (prop && !strcmp (prop->name, prop_name)) {
60 ret = drmModeObjectSetProperty (fd, plane->plane_id,
61 DRM_MODE_OBJECT_PLANE, props->props[i], prop_value);
62 }
63 drmModeFreeProperty (prop);
64 }
65
66 drmModeFreeObjectProperties (props);
67 return ret < 0 ? false : true;
68 }
69
70 /**
71 * drm_fb_get_bpp_depth - get the bpp/depth values for format
72 * @format: pixel format (DRM_FORMAT_*)
73 * @depth: storage for the depth value
74 * @bpp: storage for the bpp value
75 *
76 * This only supports RGB formats here for compat with code that doesn't use
77 * pixel formats directly yet.
78 */
drm_fb_get_bpp_depth(uint32_t format,unsigned int * depth,int * bpp)79 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp)
80 {
81 switch (format) {
82 case DRM_FORMAT_C8:
83 case DRM_FORMAT_RGB332:
84 case DRM_FORMAT_BGR233:
85 *depth = 8;
86 *bpp = 8;
87 break;
88 case DRM_FORMAT_XRGB1555:
89 case DRM_FORMAT_XBGR1555:
90 case DRM_FORMAT_RGBX5551:
91 case DRM_FORMAT_BGRX5551:
92 case DRM_FORMAT_ARGB1555:
93 case DRM_FORMAT_ABGR1555:
94 case DRM_FORMAT_RGBA5551:
95 case DRM_FORMAT_BGRA5551:
96 *depth = 15;
97 *bpp = 16;
98 break;
99 case DRM_FORMAT_RGB565:
100 case DRM_FORMAT_BGR565:
101 *depth = 16;
102 *bpp = 16;
103 break;
104 case DRM_FORMAT_RGB888:
105 case DRM_FORMAT_BGR888:
106 *depth = 24;
107 *bpp = 24;
108 break;
109 case DRM_FORMAT_XRGB8888:
110 case DRM_FORMAT_XBGR8888:
111 case DRM_FORMAT_RGBX8888:
112 case DRM_FORMAT_BGRX8888:
113 *depth = 24;
114 *bpp = 32;
115 break;
116 case DRM_FORMAT_XRGB2101010:
117 case DRM_FORMAT_XBGR2101010:
118 case DRM_FORMAT_RGBX1010102:
119 case DRM_FORMAT_BGRX1010102:
120 case DRM_FORMAT_ARGB2101010:
121 case DRM_FORMAT_ABGR2101010:
122 case DRM_FORMAT_RGBA1010102:
123 case DRM_FORMAT_BGRA1010102:
124 *depth = 30;
125 *bpp = 32;
126 break;
127 case DRM_FORMAT_ARGB8888:
128 case DRM_FORMAT_ABGR8888:
129 case DRM_FORMAT_RGBA8888:
130 case DRM_FORMAT_BGRA8888:
131 *depth = 32;
132 *bpp = 32;
133 break;
134 default:
135 printf("unsupported pixel format %d\n", format);
136 *depth = 0;
137 *bpp = 0;
138 break;
139 }
140 }
141
drm_format_to_bpp(uint32_t format)142 int drm_format_to_bpp(uint32_t format)
143 {
144 unsigned int depth;
145 int bpp;
146
147 switch(format) {
148 case DRM_FORMAT_NV12:
149 case DRM_FORMAT_NV21:
150 case DRM_FORMAT_YUV420:
151 case DRM_FORMAT_YUV422:
152 case DRM_FORMAT_YUV444:
153 return 8;
154 default:
155 drm_fb_get_bpp_depth(format, &depth, &bpp);
156 return bpp;
157 }
158 }
159
drmGetBuffer(int fd,int width,int height,int format,struct drm_buf * buffer)160 int drmGetBuffer(int fd, int width, int height, int format,
161 struct drm_buf *buffer)
162 {
163 struct drm_mode_create_dumb alloc_arg;
164 struct drm_mode_map_dumb mmap_arg;
165 struct drm_mode_destroy_dumb destory_arg;
166 uint32_t handles[4], pitches[4], offsets[4];
167 int bpp, ret;
168 void *map;
169
170 if (fd < 0 || !width || !height) {
171 printf("%s: invalid parameters\n", __func__);
172 return -EINVAL;
173 }
174
175 bpp = drm_format_to_bpp(format);
176
177 memset(&alloc_arg, 0, sizeof(alloc_arg));
178 alloc_arg.bpp = bpp;
179 alloc_arg.width = width;
180 if (format == DRM_FORMAT_NV12)
181 alloc_arg.height = height * 3 / 2;
182 else
183 alloc_arg.height = height;
184
185 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
186 if (ret) {
187 printf("failed to create dumb buffer: %s\n", strerror(errno));
188 return ret;
189 }
190 //HACK of gpu 64 bytes align?
191 if (format == DRM_FORMAT_NV12)
192 alloc_arg.pitch = width;
193
194 memset(&mmap_arg, 0, sizeof(mmap_arg));
195 mmap_arg.handle = alloc_arg.handle;
196
197 ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
198 if (ret) {
199 printf("failed to create map dumb: %s\n", strerror(errno));
200 ret = -EINVAL;
201 goto destory_dumb;
202 }
203
204 map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_arg.offset);
205 if (map == MAP_FAILED) {
206 printf("failed to mmap buffer: %s\n", strerror(errno));
207 ret = -EINVAL;
208 goto destory_dumb;
209 }
210
211 ret = drmPrimeHandleToFD(fd, alloc_arg.handle, 0, &buffer->dmabuf_fd);
212 if (ret) {
213 printf("failed to get dmabuf fd: %s\n", strerror(errno));
214 munmap(map, alloc_arg.size);
215 ret = -EINVAL;
216 goto destory_dumb;
217 }
218
219 handles[0] = alloc_arg.handle;
220 pitches[0] = alloc_arg.pitch;
221 offsets[0] = 0;
222
223 if (format == DRM_FORMAT_NV12) {
224 handles[1] = alloc_arg.handle;
225 pitches[1] = pitches[0];
226 offsets[1] = pitches[0] * height;
227 }
228
229 ret = drmModeAddFB2(fd, width, height, format, handles,
230 pitches, offsets, (uint32_t*) &buffer->fb_id, 0);
231 if (ret)
232 printf("failed to create fb_id %d\n", ret);
233
234 buffer->handle = alloc_arg.handle;
235 buffer->pitch = alloc_arg.pitch;
236 buffer->size = alloc_arg.size;
237 buffer->map = map;
238
239 destory_dumb:
240 memset(&destory_arg, 0, sizeof(destory_arg));
241 destory_arg.handle = alloc_arg.handle;
242 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
243
244 return ret;
245 }
246
drmPutBuffer(int fd,struct drm_buf * buffer)247 int drmPutBuffer(int fd, struct drm_buf *buffer)
248 {
249 if (buffer) {
250 drmModeRmFB(fd, buffer->fb_id);
251 close(buffer->dmabuf_fd);
252 return munmap(buffer->map, buffer->size);
253 }
254
255 return -EINVAL;
256 }
257
drmSetDpmsMode(uint32_t dpms_mode,struct drm_dev * dev)258 int drmSetDpmsMode(uint32_t dpms_mode, struct drm_dev *dev)
259 {
260 uint32_t connector_id;
261 uint32_t dpms_prop_id;
262 int ret = 0;
263
264 if (dev->drm_fd < 0 || !dev->dpms_prop)
265 return -ENODEV;
266
267 connector_id = dev->connector->connector_id;
268 dpms_prop_id = dev->dpms_prop->prop_id;
269
270 ret = drmModeConnectorSetProperty(dev->drm_fd, connector_id, dpms_prop_id, dpms_mode);
271 if (ret) {
272 printf("Failed to set dpms mode %d ret=%d\n", dpms_mode, ret);
273 return ret;
274 }
275
276 return 0;
277 }
278
drmGetPlaneType(int fd,drmModePlanePtr p)279 static int drmGetPlaneType(int fd, drmModePlanePtr p)
280 {
281 drmModeObjectPropertiesPtr props;
282 drmModePropertyPtr prop;
283 int i, type = -1;
284
285 props = drmModeObjectGetProperties(fd, p->plane_id,
286 DRM_MODE_OBJECT_PLANE);
287 if (!props) {
288 printf("failed to found props plane[%d] %s\n",
289 p->plane_id, strerror(errno));
290 return -errno;
291 }
292
293 for (i = 0; i < props->count_props; i++) {
294 prop = drmModeGetProperty(fd, props->props[i]);
295 if (!strcmp(prop->name, "type")) {
296 type = props->prop_values[i];
297 drmModeFreeProperty(prop);
298 break;
299 }
300 drmModeFreeProperty(prop);
301 }
302
303 drmModeFreeObjectProperties(props);
304 return type;
305 }
306
drmFillPlaneProp(int fd,struct drm_dev_plane * pp)307 static int drmFillPlaneProp(int fd, struct drm_dev_plane *pp)
308 {
309 drmModeObjectPropertiesPtr props;
310 drmModePropertyPtr prop;
311 struct plane_prop *plane_prop = &pp->plane_prop;
312 drmModePlanePtr p = pp->p;
313 int i;
314
315 props = drmModeObjectGetProperties(fd, p->plane_id,
316 DRM_MODE_OBJECT_PLANE);
317 if (!props) {
318 printf("failed to found props plane[%d] %s\n",
319 p->plane_id, strerror(errno));
320 return -errno;
321 }
322
323 pp->zpos_max = INT_MAX;
324 for (i = 0; i < props->count_props; i++) {
325 prop = drmModeGetProperty(fd, props->props[i]);
326 if (!strcmp(prop->name, "CRTC_ID"))
327 plane_prop->crtc_id = prop->prop_id;
328 else if (!strcmp(prop->name, "FB_ID"))
329 plane_prop->fb_id = prop->prop_id;
330 else if (!strcmp(prop->name, "SRC_X"))
331 plane_prop->src_x = prop->prop_id;
332 else if (!strcmp(prop->name, "SRC_Y"))
333 plane_prop->src_y = prop->prop_id;
334 else if (!strcmp(prop->name, "SRC_W"))
335 plane_prop->src_w = prop->prop_id;
336 else if (!strcmp(prop->name, "SRC_H"))
337 plane_prop->src_h = prop->prop_id;
338 else if (!strcmp(prop->name, "CRTC_X"))
339 plane_prop->crtc_x = prop->prop_id;
340 else if (!strcmp(prop->name, "CRTC_Y"))
341 plane_prop->crtc_y = prop->prop_id;
342 else if (!strcmp(prop->name, "CRTC_W"))
343 plane_prop->crtc_w = prop->prop_id;
344 else if (!strcmp(prop->name, "CRTC_H"))
345 plane_prop->crtc_h = prop->prop_id;
346 else if (!strcmp(prop->name, "ZPOS")) {
347 plane_prop->zpos = prop->prop_id;
348 pp->zpos_max = prop->values[1];
349 }
350
351 drmModeFreeProperty(prop);
352 }
353 drmModeFreeObjectProperties(props);
354
355 return 0;
356 }
357
drmGetPlaneByType(int fd,int crtc_index,int type)358 static drmModePlanePtr drmGetPlaneByType(int fd, int crtc_index, int type)
359 {
360 drmModePlanePtr plane = NULL;
361 drmModePlaneResPtr plane_res;
362 int i;
363
364 plane_res = drmModeGetPlaneResources(fd);
365 for (i = 0; i < plane_res->count_planes; i++) {
366 drmModePlanePtr p = drmModeGetPlane(fd, plane_res->planes[i]);
367
368 if (!(p->possible_crtcs & (1 << crtc_index))) {
369 drmModeFreePlane(p);
370 continue;
371 }
372 if (drmGetPlaneType(fd, p) == type) {
373 plane = p;
374 break;
375 }
376 drmModeFreePlane(p);
377 }
378
379 drmModeFreePlaneResources(plane_res);
380
381 return plane;
382 }
383
drmFoundConn(int fd,drmModeResPtr res)384 drmModeConnectorPtr drmFoundConn(int fd, drmModeResPtr res)
385 {
386 drmModeConnectorPtr connector = NULL;
387 int i;
388
389 for (i = 0; i < res->count_connectors; ++i) {
390 drmModeConnectorPtr c;
391 c = drmModeGetConnector(fd, res->connectors[i]);
392 if (!c)
393 continue;
394 if (c->connector_type == DRM_MODE_CONNECTOR_DSI ||
395 c->connector_type == DRM_MODE_CONNECTOR_eDP ||
396 c->connector_type == DRM_MODE_CONNECTOR_LVDS) {
397 connector = c;
398 break;
399 }
400 drmModeFreeConnector(c);
401 }
402
403 return connector;
404 }
405
drmFoundDPMS(int fd,drmModeConnectorPtr connector)406 static drmModePropertyPtr drmFoundDPMS(int fd, drmModeConnectorPtr connector)
407 {
408 drmModePropertyPtr dpms_prop = NULL;
409 drmModeObjectPropertiesPtr props;
410 int i;
411
412 props = drmModeObjectGetProperties(fd, connector->connector_id,
413 DRM_MODE_OBJECT_CONNECTOR);
414 if (!props) {
415 printf("failed to found props connector[%d] %s\n",
416 connector->connector_id, strerror(errno));
417 goto out;
418 }
419 for (i = 0; i < props->count_props; i++) {
420 drmModePropertyPtr prop;
421 prop = drmModeGetProperty(fd, props->props[i]);
422 if (!strcmp(prop->name, "DPMS")) {
423 dpms_prop = prop;
424 goto out;
425 }
426 drmModeFreeProperty(prop);
427 }
428
429 out:
430 drmModeFreeObjectProperties(props);
431 return dpms_prop;
432 }
433
drmFoundCrtc(int fd,drmModeResPtr res,drmModeConnector * conn,int * crtc_index)434 static drmModeCrtcPtr drmFoundCrtc(int fd, drmModeResPtr res,
435 drmModeConnector * conn, int *crtc_index)
436 {
437 int i;
438 int crtc_id;
439 drmModeEncoder *enc;
440 drmModeCrtc *crtc;
441 uint32_t crtcs_for_connector = 0;
442
443 crtc_id = -1;
444 for (i = 0; i < res->count_encoders; i++) {
445 enc = drmModeGetEncoder (fd, res->encoders[i]);
446 if (enc) {
447 if (enc->encoder_id == conn->encoder_id) {
448 crtc_id = enc->crtc_id;
449 drmModeFreeEncoder (enc);
450 break;
451 }
452 drmModeFreeEncoder (enc);
453 }
454 }
455
456 /* If no active crtc was found, pick the first possible crtc */
457 if (crtc_id == -1) {
458 for (i = 0; i < conn->count_encoders; i++) {
459 enc = drmModeGetEncoder (fd, conn->encoders[i]);
460 crtcs_for_connector |= enc->possible_crtcs;
461 drmModeFreeEncoder (enc);
462 }
463
464 if (crtcs_for_connector != 0)
465 crtc_id = res->crtcs[ffs (crtcs_for_connector) - 1];
466 }
467
468 if (crtc_id == -1)
469 return NULL;
470
471 for (i = 0; i < res->count_crtcs; i++) {
472 crtc = drmModeGetCrtc (fd, res->crtcs[i]);
473 if (crtc) {
474 if (crtc_id == crtc->crtc_id) {
475 if (crtc_index)
476 *crtc_index= i;
477 return crtc;
478 }
479 drmModeFreeCrtc (crtc);
480 }
481 }
482
483 return NULL;
484 }
485
drmInit(struct drm_dev * dev)486 int drmInit(struct drm_dev *dev)
487 {
488 drmModeResPtr res;
489 drmModeCrtcPtr crtc = NULL;
490 drmModeConnectorPtr connector = NULL;
491 drmModePlanePtr plane = NULL;
492 int fd, ret;
493 int crtc_index;
494
495 fd = drmOpen("rockchip", NULL);
496 if (fd < 0) {
497 printf("failed to open rockchip drm: %s\n",
498 strerror(errno));
499 return fd;
500 }
501 dev->drm_fd = fd;
502
503 ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
504 if (ret) {
505 printf("Failed to set atomic cap %s", strerror(errno));
506 return ret;
507 }
508
509 ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
510 if (ret) {
511 printf("Failed to set atomic cap %s", strerror(errno));
512 return ret;
513 }
514
515 res = drmModeGetResources(fd);
516 if (!res) {
517 printf("Failed to get resources: %s\n",
518 strerror(errno));
519 return -ENODEV;
520 }
521
522 /* found connector */
523 connector = drmFoundConn(fd, res);
524 if (!connector) {
525 printf("failed to find connector\n");
526 ret = -ENODEV;
527 goto err_conn;
528 }
529 /* found connector dpms prop */
530 dev->dpms_prop = drmFoundDPMS(fd, connector);
531 if (!dev->dpms_prop) {
532 ret = -ENODEV;
533 goto err_dpms;
534 }
535
536 /* found crtc that connect to connector */
537 crtc = drmFoundCrtc(fd, res, connector, &crtc_index);
538 if (!crtc) {
539 printf("failed to find crtc connect to connector \n");
540 ret = -ENODEV;
541 goto err_crtc;
542 }
543
544 plane = drmGetPlaneByType(fd, crtc_index, DRM_PLANE_TYPE_PRIMARY);
545 if (!plane) {
546 printf("failed to found expected plane\n");
547 ret = -ENODEV;
548 goto err_plane_primary;
549 }
550 dev->plane_primary.p = plane;
551
552 plane = drmGetPlaneByType(fd, crtc_index, DRM_PLANE_TYPE_OVERLAY);
553 if (!plane) {
554 printf("failed to found expected plane\n");
555 ret = -ENODEV;
556 goto err_plane_overlay;
557 }
558 dev->plane_overlay.p = plane;
559
560 drmModeFreeResources(res);
561
562 drmFillPlaneProp(fd, &dev->plane_primary);
563 drmFillPlaneProp(fd, &dev->plane_overlay);
564 dev->crtc_index = crtc_index;
565 dev->crtc = crtc;
566 dev->connector = connector;
567
568 if (!drm_plane_set_property(fd, dev->plane_primary.p, "ZPOS", 0)) {
569 printf("%s: set ZPOS property failed!\n", __func__);
570 goto err_plane_overlay;
571 }
572 if (!drm_plane_set_property(fd, dev->plane_overlay.p, "ZPOS", 1)) {
573 printf("%s: set ZPOS property failed!\n", __func__);
574 goto err_plane_overlay;
575 }
576
577 return 0;
578
579 err_plane_overlay:
580 drmModeFreePlane(dev->plane_primary.p);
581 err_plane_primary:
582 drmModeFreeCrtc(crtc);
583 err_crtc:
584 drmModeFreeProperty(dev->dpms_prop);
585 err_dpms:
586 drmModeFreeConnector(connector);
587 err_conn:
588 drmModeFreeResources(res);
589
590 return ret;
591 }
592
drmDeinit(struct drm_dev * dev)593 int drmDeinit(struct drm_dev *dev)
594 {
595 if (dev->plane_primary.p)
596 drmModeFreePlane(dev->plane_primary.p);
597 if (dev->plane_overlay.p)
598 drmModeFreePlane(dev->plane_overlay.p);
599 if (dev->dpms_prop)
600 drmModeFreeProperty(dev->dpms_prop);
601 if (dev->crtc)
602 drmModeFreeCrtc(dev->crtc);
603 if (dev->connector)
604 drmModeFreeConnector(dev->connector);
605 if (dev->drm_fd > 0)
606 drmClose(dev->drm_fd);
607
608 return 0;
609 }
610
drmCommit(struct drm_buf * buffer,int width,int height,int x_off,int y_off,struct drm_dev * dev,int plane_type)611 int drmCommit(struct drm_buf *buffer, int width, int height,
612 int x_off, int y_off, struct drm_dev *dev, int plane_type)
613 {
614 drmModeAtomicReq *req;
615 drmModeCrtcPtr crtc = dev->crtc;
616 drmModePlanePtr plane;
617 struct plane_prop *plane_prop;
618 int plane_zpos;
619 uint32_t flags = 0;
620 int ret;
621
622 if (dev->drm_fd < 0 || !buffer) {
623 printf("%s: invalid parameters\n", __func__);
624 return -EINVAL;
625 }
626
627 if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
628 plane = dev->plane_primary.p;
629 plane_zpos = dev->plane_primary.zpos_max;
630 plane_prop = &dev->plane_primary.plane_prop;
631 } else {
632 plane = dev->plane_overlay.p;
633 plane_zpos = dev->plane_overlay.zpos_max;
634 plane_prop = &dev->plane_overlay.plane_prop;
635 }
636
637 width = width == 0 ? crtc->mode.hdisplay : width;
638 height = height == 0? crtc->mode.vdisplay : height;
639
640 req = drmModeAtomicAlloc();
641
642 #define DRM_ATOMIC_ADD_PROP(object_id, value) \
643 ret = drmModeAtomicAddProperty(req, plane->plane_id, object_id, value); \
644 if (ret < 0) \
645 printf("Failed to add prop[%d] to [%d]", value, object_id);
646 DRM_ATOMIC_ADD_PROP(plane_prop->crtc_id, crtc->crtc_id);
647 DRM_ATOMIC_ADD_PROP(plane_prop->fb_id, buffer->fb_id);
648 DRM_ATOMIC_ADD_PROP(plane_prop->src_x, 0);
649 DRM_ATOMIC_ADD_PROP(plane_prop->src_y, 0);
650 DRM_ATOMIC_ADD_PROP(plane_prop->src_w, width << 16);
651 DRM_ATOMIC_ADD_PROP(plane_prop->src_h, height << 16);
652 DRM_ATOMIC_ADD_PROP(plane_prop->crtc_x, x_off);
653 DRM_ATOMIC_ADD_PROP(plane_prop->crtc_y, y_off);
654 DRM_ATOMIC_ADD_PROP(plane_prop->crtc_w, width);
655 DRM_ATOMIC_ADD_PROP(plane_prop->crtc_h, height);
656 //DRM_ATOMIC_ADD_PROP(plane_prop->zpos, plane_zpos);
657
658 // flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
659 ret = drmModeAtomicCommit(dev->drm_fd, req, flags, NULL);
660 if (ret)
661 printf("atomic: couldn't commit new state: %s\n", strerror(errno));
662
663 drmModeAtomicFree(req);
664
665 return ret;
666 }
667