5 #include <drm_fourcc.h>
6 #include <tdm_helper.h>
9 #include "tdm_drm_pp.h"
13 typedef struct _tdm_drm_output_data tdm_drm_output_data;
14 typedef struct _tdm_drm_layer_data tdm_drm_layer_data;
15 typedef struct _tdm_drm_event_data tdm_drm_event_data;
18 TDM_DRM_EVENT_TYPE_WAIT,
19 TDM_DRM_EVENT_TYPE_COMMIT,
20 TDM_DRM_EVENT_TYPE_PAGEFLIP,
23 typedef struct _tdm_drm_display_buffer {
24 struct list_head link;
29 } tdm_drm_display_buffer;
31 struct _tdm_drm_event_data {
32 tdm_drm_event_type type;
33 tdm_drm_output_data *output_data;
37 struct _tdm_drm_output_data {
38 struct list_head link;
40 /* data which are fixed at initializing */
41 tdm_drm_data *drm_data;
42 uint32_t connector_id;
46 uint32_t dpms_prop_id;
48 drmModeModeInfoPtr drm_modes;
49 tdm_output_mode *output_modes;
50 tdm_output_type connector_type;
51 unsigned int connector_type_id;
52 struct list_head layer_list;
53 tdm_drm_layer_data *primary_layer;
55 /* not fixed data below */
56 tdm_output_vblank_handler vblank_func;
57 tdm_output_commit_handler commit_func;
59 tdm_output_conn_status status;
60 tdm_output_status_handler status_func;
61 void *status_user_data;
64 const tdm_output_mode *current_mode;
67 struct _tdm_drm_layer_data {
68 struct list_head link;
70 /* data which are fixed at initializing */
71 tdm_drm_data *drm_data;
72 tdm_drm_output_data *output_data;
74 tdm_layer_capability capabilities;
77 /* not fixed data below */
81 tdm_drm_display_buffer *display_buffer;
82 int display_buffer_changed;
85 static drmModeModeInfoPtr
86 _tdm_drm_display_get_mode(tdm_drm_output_data *output_data)
90 if (!output_data->current_mode) {
91 TDM_ERR("no output_data->current_mode");
95 for (i = 0; i < output_data->count_modes; i++) {
96 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
97 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
98 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
99 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
100 (drm_mode->flags == output_data->current_mode->flags) &&
101 (drm_mode->type == output_data->current_mode->type) &&
102 !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
109 static tdm_drm_display_buffer *
110 _tdm_drm_display_find_buffer(tdm_drm_data *drm_data, tbm_surface_h buffer)
112 tdm_drm_display_buffer *display_buffer = NULL;
114 LIST_FOR_EACH_ENTRY(display_buffer, &drm_data->buffer_list, link) {
115 if (display_buffer->buffer == buffer)
116 return display_buffer;
123 _tdm_drm_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
124 tdm_output_mode *tdm_mode)
126 tdm_mode->clock = drm_mode->clock;
127 tdm_mode->hdisplay = drm_mode->hdisplay;
128 tdm_mode->hsync_start = drm_mode->hsync_start;
129 tdm_mode->hsync_end = drm_mode->hsync_end;
130 tdm_mode->htotal = drm_mode->htotal;
131 tdm_mode->hskew = drm_mode->hskew;
132 tdm_mode->vdisplay = drm_mode->vdisplay;
133 tdm_mode->vsync_start = drm_mode->vsync_start;
134 tdm_mode->vsync_end = drm_mode->vsync_end;
135 tdm_mode->vtotal = drm_mode->vtotal;
136 tdm_mode->vscan = drm_mode->vscan;
137 tdm_mode->vrefresh = drm_mode->vrefresh;
138 tdm_mode->flags = drm_mode->flags;
139 tdm_mode->type = drm_mode->type;
140 snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name);
144 _tdm_drm_display_get_cur_msc (int fd, int pipe, uint *msc)
148 vbl.request.type = DRM_VBLANK_RELATIVE;
150 vbl.request.type |= DRM_VBLANK_SECONDARY;
152 vbl.request.sequence = 0;
153 if (drmWaitVBlank(fd, &vbl)) {
154 TDM_ERR("get vblank counter failed: %m");
156 return TDM_ERROR_OPERATION_FAILED;
159 *msc = vbl.reply.sequence;
161 return TDM_ERROR_NONE;
165 _tdm_drm_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
169 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
171 vbl.request.type |= DRM_VBLANK_SECONDARY;
173 vbl.request.sequence = *target_msc;
174 vbl.request.signal = (unsigned long)(uintptr_t)data;
176 if (drmWaitVBlank(fd, &vbl)) {
178 TDM_ERR("wait vblank failed: %m");
179 return TDM_ERROR_OPERATION_FAILED;
182 *target_msc = vbl.reply.sequence;
184 return TDM_ERROR_NONE;
188 _tdm_drm_output_update_status(tdm_drm_output_data *output_data,
189 tdm_output_conn_status status)
191 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
193 if (output_data->status == status)
194 return TDM_ERROR_NONE;
196 output_data->status = status;
198 if (output_data->status_func)
199 output_data->status_func(output_data, status,
200 output_data->status_user_data);
202 return TDM_ERROR_NONE;
206 _tdm_drm_display_commit_primary_layer(tdm_drm_layer_data *layer_data,
207 void *user_data, int *do_waitvblank)
209 tdm_drm_data *drm_data = layer_data->drm_data;
210 tdm_drm_output_data *output_data = layer_data->output_data;
212 if (output_data->mode_changed && layer_data->display_buffer_changed) {
213 drmModeModeInfoPtr mode;
215 if (!layer_data->display_buffer) {
216 TDM_ERR("primary layer should have a buffer for modestting");
217 return TDM_ERROR_BAD_REQUEST;
220 output_data->mode_changed = 0;
221 layer_data->display_buffer_changed = 0;
222 layer_data->info_changed = 0;
224 mode = _tdm_drm_display_get_mode(output_data);
226 TDM_ERR("couldn't find proper mode");
227 return TDM_ERROR_BAD_REQUEST;
230 if (drmModeSetCrtc(drm_data->drm_fd, output_data->crtc_id,
231 layer_data->display_buffer->fb_id, 0, 0,
232 &output_data->connector_id, 1, mode)) {
233 TDM_ERR("set crtc failed: %m");
234 return TDM_ERROR_OPERATION_FAILED;
237 _tdm_drm_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
240 return TDM_ERROR_NONE;
241 } else if (layer_data->display_buffer_changed) {
242 layer_data->display_buffer_changed = 0;
244 if (!layer_data->display_buffer) {
245 if (drmModeSetCrtc(drm_data->drm_fd, output_data->crtc_id,
246 0, 0, 0, NULL, 0, NULL)) {
247 TDM_ERR("unset crtc failed: %m");
248 return TDM_ERROR_OPERATION_FAILED;
251 if (output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
252 _tdm_drm_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_CONNECTED);
256 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
259 TDM_ERR("alloc failed");
260 return TDM_ERROR_OUT_OF_MEMORY;
263 event_data->type = TDM_DRM_EVENT_TYPE_PAGEFLIP;
264 event_data->output_data = output_data;
265 event_data->user_data = user_data;
266 if (drmModePageFlip(drm_data->drm_fd, output_data->crtc_id,
267 layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
268 TDM_ERR("pageflip failed: %m");
269 return TDM_ERROR_OPERATION_FAILED;
275 return TDM_ERROR_NONE;
279 _tdm_drm_display_commit_layer(tdm_drm_layer_data *layer_data)
281 tdm_drm_data *drm_data = layer_data->drm_data;
282 tdm_drm_output_data *output_data = layer_data->output_data;
283 uint32_t fx, fy, fw, fh;
286 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
287 return TDM_ERROR_NONE;
289 if (output_data->current_mode)
290 crtc_w = output_data->current_mode->hdisplay;
292 drmModeCrtcPtr crtc = drmModeGetCrtc(drm_data->drm_fd, output_data->crtc_id);
294 TDM_ERR("getting crtc failed");
295 return TDM_ERROR_OPERATION_FAILED;
297 crtc_w = crtc->width;
299 TDM_ERR("getting crtc width failed");
300 return TDM_ERROR_OPERATION_FAILED;
304 layer_data->display_buffer_changed = 0;
305 layer_data->info_changed = 0;
307 if (!layer_data->display_buffer) {
308 if (drmModeSetPlane(drm_data->drm_fd, layer_data->plane_id,
309 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
310 TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
312 return TDM_ERROR_NONE;
315 /* Source values are 16.16 fixed point */
316 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
317 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
318 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
319 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
321 if (drmModeSetPlane(drm_data->drm_fd, layer_data->plane_id,
322 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
323 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
324 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
325 fx, fy, fw, fh) < 0) {
326 TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
327 return TDM_ERROR_OPERATION_FAILED;
330 TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
331 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
332 layer_data->display_buffer->fb_id,
333 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
334 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
335 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
336 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
338 return TDM_ERROR_NONE;
342 _tdm_drm_display_cb_event(int fd, unsigned int sequence,
343 unsigned int tv_sec, unsigned int tv_usec,
346 tdm_drm_event_data *event_data = user_data;
347 tdm_drm_output_data *output_data;
350 TDM_ERR("no event data");
354 output_data = event_data->output_data;
356 switch (event_data->type) {
357 case TDM_DRM_EVENT_TYPE_PAGEFLIP:
358 if (output_data->commit_func)
359 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
360 event_data->user_data);
362 case TDM_DRM_EVENT_TYPE_WAIT:
363 if (output_data->vblank_func)
364 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
365 event_data->user_data);
367 case TDM_DRM_EVENT_TYPE_COMMIT:
368 if (output_data->commit_func)
369 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
370 event_data->user_data);
380 _tdm_drm_display_create_layer_list(tdm_drm_data *drm_data)
382 tdm_drm_output_data *output_data = NULL;
385 if (LIST_IS_EMPTY(&drm_data->output_list)) {
386 TDM_ERR("no output");
387 return TDM_ERROR_OPERATION_FAILED;
390 /* The TDM drm backend only support one output. */
391 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
395 if (drm_data->plane_res->count_planes == 0) {
396 TDM_ERR("no layer error");
397 return TDM_ERROR_OPERATION_FAILED;
400 for (i = 0; i < drm_data->plane_res->count_planes; i++) {
401 tdm_drm_layer_data *layer_data;
402 drmModePlanePtr plane;
404 plane = drmModeGetPlane(drm_data->drm_fd, drm_data->plane_res->planes[i]);
410 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
411 drmModeFreePlane(plane);
415 layer_data = calloc(1, sizeof(tdm_drm_layer_data));
417 TDM_ERR("alloc failed");
418 drmModeFreePlane(plane);
422 layer_data->drm_data = drm_data;
423 layer_data->output_data = output_data;
424 layer_data->plane_id = drm_data->plane_res->planes[i];
426 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
427 TDM_LAYER_CAPABILITY_GRAPHIC;
428 output_data->primary_layer = layer_data;
430 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
431 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
432 layer_data->capabilities);
434 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
436 drmModeFreePlane(plane);
438 /* can't take care of other planes for various hardware devices */
442 return TDM_ERROR_NONE;
445 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
448 _tdm_drm_display_get_property(tdm_drm_data *drm_data,
449 unsigned int obj_id, unsigned int obj_type,
450 const char *name, unsigned int *value,
453 drmModeObjectPropertiesPtr props = NULL;
456 props = drmModeObjectGetProperties(drm_data->drm_fd, obj_id, obj_type);
458 return TDM_ERROR_OPERATION_FAILED;
460 for (i = 0; i < props->count_props; i++) {
461 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd,
467 if (!strcmp(prop->name, name)) {
469 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
471 *value = (unsigned int)props->prop_values[i];
472 drmModeFreeProperty(prop);
473 drmModeFreeObjectProperties(props);
474 return TDM_ERROR_NONE;
477 drmModeFreeProperty(prop);
479 drmModeFreeObjectProperties(props);
480 TDM_DBG("coundn't find '%s' property", name);
481 return TDM_ERROR_OPERATION_FAILED;
485 _tdm_drm_display_create_layer_list_type(tdm_drm_data *drm_data)
487 tdm_drm_output_data *output_data = NULL;
488 drmModePlanePtr *planes = NULL;
489 unsigned int *types = NULL;
490 unsigned int type = 0;
491 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
492 int opos_next, cpos_next;
496 if (LIST_IS_EMPTY(&drm_data->output_list)) {
497 TDM_ERR("no output");
498 return TDM_ERROR_OPERATION_FAILED;
501 /* The TDM drm backend only support one output. */
502 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
506 ret = _tdm_drm_display_get_property(drm_data,
507 drm_data->plane_res->planes[0],
508 DRM_MODE_OBJECT_PLANE, "type", &type,
510 if (ret != TDM_ERROR_NONE) {
511 TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
513 /* if a plane doesn't have "type" property, we call a fallback function
516 return _tdm_drm_display_create_layer_list(drm_data);
519 planes = calloc(drm_data->plane_res->count_planes, sizeof(drmModePlanePtr));
521 TDM_ERR("alloc failed");
525 types = calloc(drm_data->plane_res->count_planes, sizeof(unsigned int));
527 TDM_ERR("alloc failed");
532 for (i = 0; i < drm_data->plane_res->count_planes; i++) {
533 drmModePlanePtr plane;
535 plane = drmModeGetPlane(drm_data->drm_fd, drm_data->plane_res->planes[i]);
537 TDM_ERR("no plane(%d)", drm_data->plane_res->planes[i]);
541 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
542 drmModeFreePlane(plane);
546 ret = _tdm_drm_display_get_property(drm_data,
547 drm_data->plane_res->planes[i],
548 DRM_MODE_OBJECT_PLANE, "type", &type,
550 if (ret != TDM_ERROR_NONE) {
551 drmModeFreePlane(plane);
552 TDM_ERR("plane(%d) doesn't have 'type' info",
553 drm_data->plane_res->planes[i]);
557 planes[plane_cnt] = plane;
558 types[plane_cnt] = type;
562 primary_cnt = ovl_cnt = cursor_cnt = 0;
563 for (i = 0; i < plane_cnt; i++) {
564 if (types[i] == DRM_PLANE_TYPE_CURSOR)
566 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
568 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
571 TDM_ERR("invalid type(%d)", types[i]);
574 if (primary_cnt != 1) {
575 TDM_ERR("primary layer count(%d) should be one", primary_cnt);
581 for (i = 0; i < plane_cnt; i++) {
582 tdm_drm_layer_data *layer_data;
584 layer_data = calloc(1, sizeof(tdm_drm_layer_data));
586 TDM_ERR("alloc failed");
590 layer_data->drm_data = drm_data;
591 layer_data->output_data = output_data;
592 layer_data->plane_id = planes[i]->plane_id;
594 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
595 layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
596 TDM_LAYER_CAPABILITY_GRAPHIC;
597 layer_data->zpos = cpos_next++;
598 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
599 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
600 TDM_LAYER_CAPABILITY_GRAPHIC;
601 layer_data->zpos = opos_next++;
602 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
603 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
604 TDM_LAYER_CAPABILITY_GRAPHIC;
605 layer_data->zpos = 0;
606 output_data->primary_layer = layer_data;
612 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
613 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
614 layer_data->zpos, layer_data->capabilities);
616 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
619 for (i = 0; i < plane_cnt; i++)
621 drmModeFreePlane(planes[i]);
626 return TDM_ERROR_NONE;
630 for (i = 0; i < drm_data->plane_res->count_planes; i++)
632 drmModeFreePlane(planes[i]);
638 return TDM_ERROR_OPERATION_FAILED;
643 _tdm_drm_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
645 tdm_drm_data *drm_data;
646 tdm_drm_display_buffer *display_buffer;
650 TDM_ERR("no user_data");
654 TDM_ERR("no buffer");
658 drm_data = (tdm_drm_data *)user_data;
660 display_buffer = _tdm_drm_display_find_buffer(drm_data, buffer);
661 if (!display_buffer) {
662 TDM_ERR("no display_buffer");
665 LIST_DEL(&display_buffer->link);
667 if (display_buffer->fb_id > 0) {
668 ret = drmModeRmFB(drm_data->drm_fd, display_buffer->fb_id);
670 TDM_ERR("rm fb failed");
673 TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id);
675 TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id);
677 free(display_buffer);
681 tdm_drm_display_create_layer_list(tdm_drm_data *drm_data)
683 tdm_drm_output_data *output_data = NULL;
686 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
687 if (drm_data->has_universal_plane)
688 ret = _tdm_drm_display_create_layer_list_type(drm_data);
691 ret = _tdm_drm_display_create_layer_list(drm_data);
693 if (ret != TDM_ERROR_NONE)
696 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
697 if (!output_data->primary_layer) {
698 TDM_ERR("output(%d) no primary layer", output_data->pipe);
699 return TDM_ERROR_OPERATION_FAILED;
703 return TDM_ERROR_NONE;
707 tdm_drm_display_destroy_output_list(tdm_drm_data *drm_data)
709 tdm_drm_output_data *o = NULL, *oo = NULL;
711 if (LIST_IS_EMPTY(&drm_data->output_list))
714 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &drm_data->output_list, link) {
716 if (!LIST_IS_EMPTY(&o->layer_list)) {
717 tdm_drm_layer_data *l = NULL, *ll = NULL;
718 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
724 free(o->output_modes);
730 tdm_drm_display_update_output_status(tdm_drm_data *drm_data)
732 tdm_drm_output_data *output_data = NULL;
734 if (LIST_IS_EMPTY(&drm_data->output_list))
737 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
738 drmModeConnectorPtr connector;
739 tdm_output_conn_status new_status;
741 connector = drmModeGetConnector(drm_data->drm_fd,
742 output_data->connector_id);
744 TDM_ERR("no connector: %d", output_data->connector_id);
748 if (connector->connection == DRM_MODE_CONNECTED)
749 new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
751 new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
753 _tdm_drm_output_update_status(output_data, new_status);
755 drmModeFreeConnector(connector);
760 tdm_drm_display_create_output_list(tdm_drm_data *drm_data)
762 tdm_drm_output_data *output_data;
767 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&drm_data->output_list),
768 TDM_ERROR_OPERATION_FAILED);
770 for (i = 0; i < drm_data->mode_res->count_connectors; i++) {
771 drmModeConnectorPtr connector;
772 drmModeEncoderPtr encoder;
773 int crtc_id = 0, c, j;
775 connector = drmModeGetConnector(drm_data->drm_fd,
776 drm_data->mode_res->connectors[i]);
778 TDM_ERR("no connector");
779 ret = TDM_ERROR_OPERATION_FAILED;
783 /* The TDM drm backend is not interested with disconnected connectors.
784 * And it only considers 1 connected connector because it is the TDM
785 * reference backend and can't take care of all hardware devices.
786 * To support various connectors, planes and crtcs, the new TDM backend
787 * should be implemented.
789 if (connector->connection != DRM_MODE_CONNECTED) {
790 drmModeFreeConnector(connector);
794 if (connector->count_encoders != 1) {
795 TDM_ERR("too many encoders: %d", connector->count_encoders);
796 drmModeFreeConnector(connector);
797 ret = TDM_ERROR_OPERATION_FAILED;
801 encoder = drmModeGetEncoder(drm_data->drm_fd, connector->encoders[0]);
803 TDM_ERR("no encoder");
804 drmModeFreeConnector(connector);
805 ret = TDM_ERROR_OPERATION_FAILED;
809 for (c = 0; c < drm_data->mode_res->count_crtcs; c++) {
810 if (allocated & (1 << c))
813 if ((encoder->possible_crtcs & (1 << c)) == 0)
816 crtc_id = drm_data->mode_res->crtcs[c];
817 allocated |= (1 << c);
822 TDM_ERR("no possible crtc");
823 drmModeFreeConnector(connector);
824 ret = TDM_ERROR_OPERATION_FAILED;
828 output_data = calloc(1, sizeof(tdm_drm_output_data));
830 TDM_ERR("alloc failed");
831 drmModeFreeConnector(connector);
832 drmModeFreeEncoder(encoder);
833 ret = TDM_ERROR_OUT_OF_MEMORY;
837 LIST_INITHEAD(&output_data->layer_list);
839 output_data->drm_data = drm_data;
840 output_data->connector_id = drm_data->mode_res->connectors[i];
841 output_data->encoder_id = encoder->encoder_id;
842 output_data->crtc_id = crtc_id;
843 output_data->pipe = c;
844 output_data->connector_type = connector->connector_type;
845 output_data->connector_type_id = connector->connector_type_id;
847 if (connector->connection == DRM_MODE_CONNECTED)
848 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
850 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
852 for (j = 0; j < connector->count_props; j++) {
853 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd,
854 connector->props[j]);
857 if (!strcmp(prop->name, "DPMS")) {
858 output_data->dpms_prop_id = connector->props[j];
859 drmModeFreeProperty(prop);
862 drmModeFreeProperty(prop);
865 if (output_data->dpms_prop_id == 0)
866 TDM_WRN("not support DPMS");
868 output_data->count_modes = connector->count_modes;
869 output_data->drm_modes = calloc(connector->count_modes,
870 sizeof(drmModeModeInfo));
871 if (!output_data->drm_modes) {
872 TDM_ERR("alloc failed");
874 drmModeFreeConnector(connector);
875 drmModeFreeEncoder(encoder);
876 ret = TDM_ERROR_OUT_OF_MEMORY;
879 output_data->output_modes = calloc(connector->count_modes,
880 sizeof(tdm_output_mode));
881 if (!output_data->output_modes) {
882 TDM_ERR("alloc failed");
883 free(output_data->drm_modes);
885 drmModeFreeConnector(connector);
886 drmModeFreeEncoder(encoder);
887 ret = TDM_ERROR_OUT_OF_MEMORY;
890 for (j = 0; j < connector->count_modes; j++) {
891 output_data->drm_modes[j] = connector->modes[j];
892 _tdm_drm_display_to_tdm_mode(&output_data->drm_modes[j],
893 &output_data->output_modes[j]);
896 LIST_ADDTAIL(&output_data->link, &drm_data->output_list);
898 TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
899 output_data, output_data->connector_id, output_data->status,
900 output_data->connector_type,
901 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
902 output_data->pipe, output_data->dpms_prop_id);
904 drmModeFreeEncoder(encoder);
905 drmModeFreeConnector(connector);
907 /* The TDM drm backend is not interested with disconnected connectors.
908 * And it only considers 1 connected connector because it is the TDM
909 * reference backend and can't take care of all hardware devices.
910 * To support various connectors, planes and crtcs, the new TDM backend
911 * should be implemented.
916 TDM_DBG("output count: %d", drm_data->mode_res->count_connectors);
918 return TDM_ERROR_NONE;
920 tdm_drm_display_destroy_output_list(drm_data);
925 drm_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
927 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
929 caps->max_layer_count = -1; /* not defined */
931 return TDM_ERROR_NONE;
935 drm_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
937 return tdm_drm_pp_get_capability(bdata, caps);
941 drm_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
943 tdm_drm_data *drm_data = bdata;
944 tdm_drm_output_data *output_data = NULL;
945 tdm_output **outputs;
949 RETURN_VAL_IF_FAIL(drm_data, NULL);
950 RETURN_VAL_IF_FAIL(count, NULL);
953 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link)
957 ret = TDM_ERROR_NONE;
961 /* will be freed in frontend */
962 outputs = calloc(*count, sizeof(tdm_drm_output_data *));
964 TDM_ERR("failed: alloc memory");
966 ret = TDM_ERROR_OUT_OF_MEMORY;
971 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link)
972 outputs[i++] = output_data;
975 *error = TDM_ERROR_NONE;
985 drm_display_get_fd(tdm_backend_data *bdata, int *fd)
987 tdm_drm_data *drm_data = bdata;
989 RETURN_VAL_IF_FAIL(drm_data, TDM_ERROR_INVALID_PARAMETER);
990 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
992 *fd = drm_data->drm_fd;
994 return TDM_ERROR_NONE;
998 drm_display_handle_events(tdm_backend_data *bdata)
1000 tdm_drm_data *drm_data = bdata;
1001 drmEventContext ctx;
1003 RETURN_VAL_IF_FAIL(drm_data, TDM_ERROR_INVALID_PARAMETER);
1005 memset(&ctx, 0, sizeof(drmEventContext));
1007 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1008 ctx.page_flip_handler = _tdm_drm_display_cb_event;
1009 ctx.vblank_handler = _tdm_drm_display_cb_event;
1011 drmHandleEvent(drm_data->drm_fd, &ctx);
1013 return TDM_ERROR_NONE;
1017 drm_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1019 tdm_drm_data *drm_data = bdata;
1021 RETURN_VAL_IF_FAIL(drm_data, NULL);
1023 return tdm_drm_pp_create(drm_data, error);
1027 drm_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1029 tdm_drm_output_data *output_data = output;
1030 tdm_drm_data *drm_data;
1031 drmModeConnectorPtr connector = NULL;
1032 drmModeCrtcPtr crtc = NULL;
1033 drmModeObjectPropertiesPtr props = NULL;
1037 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1038 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1040 memset(caps, 0, sizeof(tdm_caps_output));
1042 drm_data = output_data->drm_data;
1044 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1045 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1046 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1048 caps->status = output_data->status;
1049 caps->type = output_data->connector_type;
1050 caps->type_id = output_data->connector_type_id;
1052 connector = drmModeGetConnector(drm_data->drm_fd, output_data->connector_id);
1053 RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
1055 caps->mode_count = connector->count_modes;
1056 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1058 ret = TDM_ERROR_OUT_OF_MEMORY;
1059 TDM_ERR("alloc failed\n");
1062 for (i = 0; i < caps->mode_count; i++)
1063 caps->modes[i] = output_data->output_modes[i];
1065 caps->mmWidth = connector->mmWidth;
1066 caps->mmHeight = connector->mmHeight;
1067 caps->subpixel = connector->subpixel;
1069 caps->min_w = drm_data->mode_res->min_width;
1070 caps->min_h = drm_data->mode_res->min_height;
1071 caps->max_w = drm_data->mode_res->max_width;
1072 caps->max_h = drm_data->mode_res->max_height;
1073 caps->preferred_align = -1;
1075 crtc = drmModeGetCrtc(drm_data->drm_fd, output_data->crtc_id);
1077 ret = TDM_ERROR_OPERATION_FAILED;
1078 TDM_ERR("get crtc failed: %m\n");
1082 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->crtc_id,
1083 DRM_MODE_OBJECT_CRTC);
1085 ret = TDM_ERROR_OPERATION_FAILED;
1086 TDM_ERR("get crtc properties failed: %m\n");
1090 caps->prop_count = props->count_props;
1091 caps->props = calloc(1, sizeof(tdm_prop) * caps->prop_count);
1093 ret = TDM_ERROR_OUT_OF_MEMORY;
1094 TDM_ERR("alloc failed\n");
1098 for (i = 0; i < caps->prop_count; i++) {
1099 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd, props->props[i]);
1102 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1103 caps->props[i].id = props->props[i];
1104 drmModeFreeProperty(prop);
1107 drmModeFreeObjectProperties(props);
1108 drmModeFreeCrtc(crtc);
1109 drmModeFreeConnector(connector);
1111 return TDM_ERROR_NONE;
1113 drmModeFreeCrtc(crtc);
1114 drmModeFreeObjectProperties(props);
1115 drmModeFreeConnector(connector);
1118 memset(caps, 0, sizeof(tdm_caps_output));
1123 drm_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1125 tdm_drm_output_data *output_data = output;
1126 tdm_drm_layer_data *layer_data = NULL;
1131 RETURN_VAL_IF_FAIL(output_data, NULL);
1132 RETURN_VAL_IF_FAIL(count, NULL);
1135 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1139 ret = TDM_ERROR_NONE;
1143 /* will be freed in frontend */
1144 layers = calloc(*count, sizeof(tdm_drm_layer_data *));
1146 TDM_ERR("failed: alloc memory");
1148 ret = TDM_ERROR_OUT_OF_MEMORY;
1153 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1154 layers[i++] = layer_data;
1157 *error = TDM_ERROR_NONE;
1167 drm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1169 tdm_drm_output_data *output_data = output;
1170 tdm_drm_data *drm_data;
1173 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1174 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1176 drm_data = output_data->drm_data;
1177 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1178 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1181 TDM_ERR("set property failed: %m");
1182 return TDM_ERROR_OPERATION_FAILED;
1185 return TDM_ERROR_NONE;
1189 drm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1191 tdm_drm_output_data *output_data = output;
1192 tdm_drm_data *drm_data;
1193 drmModeObjectPropertiesPtr props;
1196 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1197 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1198 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1200 drm_data = output_data->drm_data;
1201 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->crtc_id,
1202 DRM_MODE_OBJECT_CRTC);
1203 if (props == NULL) {
1204 TDM_ERR("get property failed: %m");
1205 return TDM_ERROR_OPERATION_FAILED;
1208 for (i = 0; i < props->count_props; i++)
1209 if (props->props[i] == id) {
1210 (*value).u32 = (uint)props->prop_values[i];
1214 drmModeFreeObjectProperties(props);
1216 return TDM_ERROR_NONE;
1220 drm_output_wait_vblank(tdm_output *output, int interval, int sync,
1223 tdm_drm_output_data *output_data = output;
1224 tdm_drm_data *drm_data;
1225 tdm_drm_event_data *event_data;
1229 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1231 event_data = calloc(1, sizeof(tdm_drm_event_data));
1233 TDM_ERR("alloc failed");
1234 return TDM_ERROR_OUT_OF_MEMORY;
1237 drm_data = output_data->drm_data;
1239 ret = _tdm_drm_display_get_cur_msc(drm_data->drm_fd, output_data->pipe,
1241 if (ret != TDM_ERROR_NONE)
1244 target_msc += interval;
1246 event_data->type = TDM_DRM_EVENT_TYPE_WAIT;
1247 event_data->output_data = output_data;
1248 event_data->user_data = user_data;
1250 ret = _tdm_drm_display_wait_vblank(drm_data->drm_fd, output_data->pipe,
1251 &target_msc, event_data);
1252 if (ret != TDM_ERROR_NONE)
1255 return TDM_ERROR_NONE;
1262 drm_output_set_vblank_handler(tdm_output *output,
1263 tdm_output_vblank_handler func)
1265 tdm_drm_output_data *output_data = output;
1267 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1268 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1270 output_data->vblank_func = func;
1272 return TDM_ERROR_NONE;
1276 drm_output_commit(tdm_output *output, int sync, void *user_data)
1278 tdm_drm_output_data *output_data = output;
1279 tdm_drm_data *drm_data;
1280 tdm_drm_layer_data *layer_data = NULL;
1282 int do_waitvblank = 1;
1284 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1286 drm_data = output_data->drm_data;
1288 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1289 if (layer_data == output_data->primary_layer) {
1290 ret = _tdm_drm_display_commit_primary_layer(layer_data, user_data,
1292 if (ret != TDM_ERROR_NONE)
1295 ret = _tdm_drm_display_commit_layer(layer_data);
1296 if (ret != TDM_ERROR_NONE)
1301 if (do_waitvblank == 1) {
1302 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
1306 TDM_ERR("alloc failed");
1307 return TDM_ERROR_OUT_OF_MEMORY;
1310 ret = _tdm_drm_display_get_cur_msc(drm_data->drm_fd, output_data->pipe,
1312 if (ret != TDM_ERROR_NONE) {
1319 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1320 event_data->output_data = output_data;
1321 event_data->user_data = user_data;
1323 ret = _tdm_drm_display_wait_vblank(drm_data->drm_fd, output_data->pipe,
1324 &target_msc, event_data);
1325 if (ret != TDM_ERROR_NONE) {
1331 return TDM_ERROR_NONE;
1335 drm_output_set_commit_handler(tdm_output *output,
1336 tdm_output_commit_handler func)
1338 tdm_drm_output_data *output_data = output;
1340 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1341 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1343 output_data->commit_func = func;
1345 return TDM_ERROR_NONE;
1349 drm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1351 tdm_drm_output_data *output_data = output;
1352 tdm_drm_data *drm_data;
1355 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1357 if (output_data->dpms_prop_id == 0) {
1358 TDM_WRN("not support DPMS");
1359 return TDM_ERROR_OPERATION_FAILED;
1362 drm_data = output_data->drm_data;
1363 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1364 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1365 output_data->dpms_prop_id, dpms_value);
1367 TDM_ERR("set dpms failed: %m");
1368 return TDM_ERROR_OPERATION_FAILED;
1371 return TDM_ERROR_NONE;
1375 drm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1377 tdm_drm_output_data *output_data = output;
1378 tdm_drm_data *drm_data;
1379 drmModeObjectPropertiesPtr props;
1382 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1383 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1385 drm_data = output_data->drm_data;
1386 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->connector_id,
1387 DRM_MODE_OBJECT_CONNECTOR);
1388 if (props == NULL) {
1389 TDM_ERR("get property failed: %m");
1390 return TDM_ERROR_OPERATION_FAILED;
1393 for (i = 0; i < props->count_props; i++)
1394 if (props->props[i] == output_data->dpms_prop_id) {
1395 *dpms_value = (uint)props->prop_values[i];
1399 drmModeFreeObjectProperties(props);
1401 return TDM_ERROR_NONE;
1405 drm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1407 tdm_drm_output_data *output_data = output;
1409 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1410 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1412 output_data->current_mode = mode;
1413 output_data->mode_changed = 1;
1415 return TDM_ERROR_NONE;
1419 drm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1421 tdm_drm_output_data *output_data = output;
1423 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1424 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1426 *mode = output_data->current_mode;
1428 return TDM_ERROR_NONE;
1432 drm_output_set_status_handler(tdm_output *output,
1433 tdm_output_status_handler func,
1436 tdm_drm_output_data *output_data = output;
1438 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1439 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1441 output_data->status_func = func;
1442 output_data->status_user_data = user_data;
1444 return TDM_ERROR_NONE;
1448 drm_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1450 tdm_drm_layer_data *layer_data = layer;
1451 tdm_drm_data *drm_data;
1452 drmModePlanePtr plane = NULL;
1453 drmModeObjectPropertiesPtr props = NULL;
1454 int i, format_count = 0;
1457 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1458 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1460 memset(caps, 0, sizeof(tdm_caps_layer));
1462 drm_data = layer_data->drm_data;
1463 plane = drmModeGetPlane(drm_data->drm_fd, layer_data->plane_id);
1465 TDM_ERR("get plane failed: %m");
1466 ret = TDM_ERROR_OPERATION_FAILED;
1470 caps->capabilities = layer_data->capabilities;
1471 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1473 caps->format_count = plane->count_formats;
1474 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1475 if (!caps->formats) {
1476 ret = TDM_ERROR_OUT_OF_MEMORY;
1477 TDM_ERR("alloc failed\n");
1481 for (i = 0; i < caps->format_count; i++) {
1482 /* TODO: kernel reports wrong formats */
1483 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1484 plane->formats[i] != DRM_FORMAT_ARGB8888)
1486 caps->formats[i] = tdm_drm_format_to_tbm_format(plane->formats[i]);
1490 caps->format_count = format_count;
1492 props = drmModeObjectGetProperties(drm_data->drm_fd, layer_data->plane_id,
1493 DRM_MODE_OBJECT_PLANE);
1495 ret = TDM_ERROR_OPERATION_FAILED;
1496 TDM_ERR("get plane properties failed: %m\n");
1500 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1502 ret = TDM_ERROR_OUT_OF_MEMORY;
1503 TDM_ERR("alloc failed\n");
1507 caps->prop_count = 0;
1508 for (i = 0; i < props->count_props; i++) {
1509 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd, props->props[i]);
1512 if (!strncmp(prop->name, "type", TDM_NAME_LEN))
1514 if (!strncmp(prop->name, "zpos", TDM_NAME_LEN))
1516 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1517 caps->props[i].id = props->props[i];
1519 drmModeFreeProperty(prop);
1522 drmModeFreeObjectProperties(props);
1523 drmModeFreePlane(plane);
1525 return TDM_ERROR_NONE;
1527 drmModeFreeObjectProperties(props);
1528 drmModeFreePlane(plane);
1529 free(caps->formats);
1531 memset(caps, 0, sizeof(tdm_caps_layer));
1536 drm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1538 tdm_drm_layer_data *layer_data = layer;
1539 tdm_drm_data *drm_data;
1542 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1543 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1545 drm_data = layer_data->drm_data;
1546 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1547 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1550 TDM_ERR("set property failed: %m");
1551 return TDM_ERROR_OPERATION_FAILED;
1554 return TDM_ERROR_NONE;
1558 drm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1560 tdm_drm_layer_data *layer_data = layer;
1561 tdm_drm_data *drm_data;
1562 drmModeObjectPropertiesPtr props;
1565 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1566 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1567 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1569 drm_data = layer_data->drm_data;
1570 props = drmModeObjectGetProperties(drm_data->drm_fd, layer_data->plane_id,
1571 DRM_MODE_OBJECT_PLANE);
1572 if (props == NULL) {
1573 TDM_ERR("get property failed: %m");
1574 return TDM_ERROR_OPERATION_FAILED;
1577 for (i = 0; i < props->count_props; i++)
1578 if (props->props[i] == id) {
1579 (*value).u32 = (uint)props->prop_values[i];
1583 drmModeFreeObjectProperties(props);
1585 return TDM_ERROR_NONE;
1589 drm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1591 tdm_drm_layer_data *layer_data = layer;
1593 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1594 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1596 layer_data->info = *info;
1597 layer_data->info_changed = 1;
1599 return TDM_ERROR_NONE;
1603 drm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1605 tdm_drm_layer_data *layer_data = layer;
1607 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1608 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1610 *info = layer_data->info;
1612 return TDM_ERROR_NONE;
1616 drm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1618 tdm_drm_layer_data *layer_data = layer;
1619 tdm_drm_data *drm_data;
1620 tdm_drm_display_buffer *display_buffer;
1621 tdm_error err = TDM_ERROR_NONE;
1624 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1625 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
1627 drm_data = layer_data->drm_data;
1629 display_buffer = _tdm_drm_display_find_buffer(drm_data, buffer);
1630 if (!display_buffer) {
1631 display_buffer = calloc(1, sizeof(tdm_drm_display_buffer));
1632 if (!display_buffer) {
1633 TDM_ERR("alloc failed");
1634 return TDM_ERROR_OUT_OF_MEMORY;
1636 display_buffer->buffer = buffer;
1638 err = tdm_buffer_add_destroy_handler(buffer, _tdm_drm_display_cb_destroy_buffer,
1640 if (err != TDM_ERROR_NONE) {
1641 TDM_ERR("add destroy handler fail");
1642 free(display_buffer);
1643 return TDM_ERROR_OPERATION_FAILED;
1646 LIST_ADDTAIL(&display_buffer->link, &drm_data->buffer_list);
1649 if (display_buffer->fb_id == 0) {
1651 unsigned int height;
1652 unsigned int format;
1653 unsigned int handles[4] = {0,};
1654 unsigned int pitches[4] = {0,};
1655 unsigned int offsets[4] = {0,};
1658 width = tbm_surface_get_width(buffer);
1659 height = tbm_surface_get_height(buffer);
1660 format = tbm_surface_get_format(buffer);
1661 count = tbm_surface_internal_get_num_bos(buffer);
1662 for (i = 0; i < count; i++) {
1663 tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
1664 handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1666 count = tbm_surface_internal_get_num_planes(format);
1667 for (i = 0; i < count; i++)
1668 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
1670 ret = drmModeAddFB2(drm_data->drm_fd, width, height, format,
1671 handles, pitches, offsets, &display_buffer->fb_id, 0);
1673 TDM_ERR("add fb failed: %m");
1674 return TDM_ERROR_OPERATION_FAILED;
1676 TDM_DBG("drm_data->drm_fd : %d, display_buffer->fb_id:%u", drm_data->drm_fd,
1677 display_buffer->fb_id);
1680 display_buffer->width = pitches[0] >> 2;
1682 display_buffer->width = pitches[0];
1685 layer_data->display_buffer = display_buffer;
1686 layer_data->display_buffer_changed = 1;
1688 return TDM_ERROR_NONE;
1692 drm_layer_unset_buffer(tdm_layer *layer)
1694 tdm_drm_layer_data *layer_data = layer;
1696 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1698 layer_data->display_buffer = NULL;
1699 layer_data->display_buffer_changed = 1;
1701 return TDM_ERROR_NONE;