5 #include <drm_fourcc.h>
6 #include <tdm_helper.h>
12 #define LIST_INSERT_AFTER(__after, __item) \
13 (__item)->prev = (__after); \
14 (__item)->next = (__after)->next; \
15 (__after)->next->prev = (__item); \
16 (__after)->next = (__item);
18 typedef struct _tdm_vc4_output_data tdm_vc4_output_data;
19 typedef struct _tdm_vc4_layer_data tdm_vc4_layer_data;
20 typedef struct _tdm_vc4_hwc_window_data tdm_vc4_hwc_window_data;
21 typedef struct _tdm_vc4_event_data tdm_vc4_event_data;
24 TDM_DRM_EVENT_TYPE_WAIT,
25 TDM_DRM_EVENT_TYPE_COMMIT,
26 TDM_DRM_EVENT_TYPE_PAGEFLIP,
29 typedef struct _tdm_vc4_display_buffer {
30 struct list_head link;
35 } tdm_vc4_display_buffer;
37 struct _tdm_vc4_event_data {
38 tdm_vc4_event_type type;
39 tdm_vc4_output_data *output_data;
43 struct _tdm_vc4_output_data {
44 struct list_head link;
46 /* data which are fixed at initializing */
47 tdm_vc4_data *vc4_data;
48 uint32_t connector_id;
52 uint32_t dpms_prop_id;
54 drmModeModeInfoPtr vc4_modes;
55 tdm_output_mode *output_modes;
56 tdm_output_type connector_type;
57 unsigned int connector_type_id;
58 struct list_head layer_list;
59 tdm_vc4_layer_data *primary_layer;
61 /* not fixed data below */
62 tdm_output_vblank_handler vblank_func;
63 tdm_output_commit_handler commit_func;
65 tdm_output_conn_status status;
66 tdm_output_status_handler status_func;
67 void *status_user_data;
70 const tdm_output_mode *current_mode;
72 tbm_surface_h crtc_buffer;
74 unsigned int crtc_fb_id;
76 tdm_vc4_hwc_window_data *target_hwc_window;
79 int need_target_buffer;
85 struct list_head hwc_window_list;
88 struct _tdm_vc4_layer_data {
89 struct list_head link;
91 /* data which are fixed at initializing */
92 tdm_vc4_data *vc4_data;
93 tdm_vc4_output_data *output_data;
95 tdm_layer_capability capabilities;
98 /* not fixed data below */
102 tdm_vc4_display_buffer *display_buffer;
103 int display_buffer_changed;
106 struct _tdm_vc4_hwc_window_data {
107 struct list_head link;
109 /* data which are fixed at initializing */
110 tdm_vc4_data *vc4_data;
111 tdm_vc4_output_data *output_data;
113 /* not fixed data below */
116 tdm_hwc_window_info info;
119 tbm_surface_h surface;
120 int display_buffer_changed;
123 /* client_type stores the initial type given to us by client(compositor) */
124 tdm_hwc_window_composition client_type;
125 /* validated_type stores the type after running Validate */
126 tdm_hwc_window_composition validated_type;
130 _vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info,
133 static drmModeModeInfoPtr
134 _tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data)
138 if (!output_data->current_mode) {
139 TDM_ERR("no output_data->current_mode");
143 for (i = 0; i < output_data->count_modes; i++) {
144 drmModeModeInfoPtr vc4_mode = &output_data->vc4_modes[i];
145 if ((vc4_mode->hdisplay == output_data->current_mode->hdisplay) &&
146 (vc4_mode->vdisplay == output_data->current_mode->vdisplay) &&
147 (vc4_mode->vrefresh == output_data->current_mode->vrefresh) &&
148 (vc4_mode->flags == output_data->current_mode->flags) &&
149 (vc4_mode->type == output_data->current_mode->type) &&
150 !(strncmp(vc4_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
158 _tdm_vc4_display_set_fb(tdm_vc4_data *vc4_data, tbm_surface_h buffer, unsigned int *id)
163 unsigned int handles[4] = {0,};
164 unsigned int pitches[4] = {0,};
165 unsigned int offsets[4] = {0,};
170 width = tbm_surface_get_width(buffer);
171 height = tbm_surface_get_height(buffer);
172 format = tbm_surface_get_format(buffer);
173 count = tbm_surface_internal_get_num_bos(buffer);
174 for (i = 0; i < count; i++) {
175 tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
176 handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
178 count = tbm_surface_internal_get_num_planes(format);
179 for (i = 0; i < count; i++)
180 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
182 TDM_DBG("AddFB2: drm_fd(%d) size(%dx%d) format(%c%c%c%c) handles(%d,%d,%d) pitches(%d,%d,%d) offsets(%d,%d,%d) buffer(%p)",
183 vc4_data->drm_fd, width, height, FOURCC_STR(format),
184 handles[0], handles[1], handles[2], pitches[0], pitches[1], pitches[2],
185 offsets[0], offsets[1], offsets[2], buffer);
187 ret = drmModeAddFB2(vc4_data->drm_fd, width, height, format,
188 handles, pitches, offsets, &fb_id, 0);
190 TDM_ERR("add fb failed: %m");
191 return TDM_ERROR_OPERATION_FAILED;
193 TDM_DBG("AddFB2 success: drm_fd(%d) fb_id(%u)", vc4_data->drm_fd, fb_id);
196 return TDM_ERROR_NONE;
200 _tdm_vc4_display_set_crtc(tdm_vc4_data *vc4_data, tdm_vc4_output_data *output_data, int set)
204 output_data->mode_changed = 0;
207 tbm_surface_h buffer = NULL;
208 tbm_surface_info_s info;
209 drmModeModeInfoPtr mode;
210 unsigned int fb_id = 0;
212 if (!output_data->current_mode)
213 return TDM_ERROR_OPERATION_FAILED;
215 mode = _tdm_vc4_display_get_mode(output_data);
217 TDM_ERR("couldn't find proper mode");
218 return TDM_ERROR_BAD_REQUEST;
221 buffer = tbm_surface_create(output_data->current_mode->hdisplay,
222 output_data->current_mode->vdisplay,
223 TBM_FORMAT_XRGB8888);
224 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_OPERATION_FAILED);
226 tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &info);
227 memset(info.planes[0].ptr, 0x0, info.size);
229 tbm_surface_unmap(buffer);
231 if (_tdm_vc4_display_set_fb(vc4_data, buffer, &fb_id) != TDM_ERROR_NONE) {
232 tbm_surface_destroy(buffer);
233 return TDM_ERROR_OPERATION_FAILED;
236 TDM_DBG("drmModeSetCrtc drm_fd(%d) crtc_id(%u) fb_id(%u) mode(%u,%u)",
237 vc4_data->drm_fd, output_data->crtc_id, fb_id,
238 mode->hdisplay, mode->vdisplay);
239 if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
241 &output_data->connector_id, 1, mode)) {
242 TDM_ERR("set crtc failed: %m");
243 ret = drmModeRmFB(vc4_data->drm_fd, fb_id);
245 TDM_ERR("rm fb failed fb_id(%u)", fb_id);
246 tbm_surface_destroy(buffer);
247 return TDM_ERROR_OPERATION_FAILED;
250 if (output_data->crtc_buffer) {
251 ret = drmModeRmFB(vc4_data->drm_fd, output_data->crtc_fb_id);
253 TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
254 tbm_surface_destroy(output_data->crtc_buffer);
256 output_data->crtc_buffer = buffer;
257 output_data->crtc_fb_id = fb_id;
259 TDM_DBG("drmModeSetCrtc unset drm_fd(%d) crtc_id(%u)",
260 vc4_data->drm_fd, output_data->crtc_id);
261 if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
262 0, 0, 0, NULL, 0, NULL)) {
263 TDM_ERR("unset crtc failed: %m");
264 return TDM_ERROR_OPERATION_FAILED;
267 if (output_data->crtc_buffer) {
268 ret = drmModeRmFB(vc4_data->drm_fd, output_data->crtc_fb_id);
270 TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
271 tbm_surface_destroy(output_data->crtc_buffer);
273 output_data->crtc_buffer = NULL;
274 output_data->crtc_fb_id = 0;
277 return TDM_ERROR_NONE;
280 static tdm_vc4_display_buffer *
281 _tdm_vc4_display_find_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer)
283 tdm_vc4_display_buffer *display_buffer = NULL;
285 LIST_FOR_EACH_ENTRY(display_buffer, &vc4_data->buffer_list, link) {
286 if (display_buffer->buffer == buffer)
287 return display_buffer;
294 _tdm_vc4_display_to_tdm_mode(drmModeModeInfoPtr vc4_mode,
295 tdm_output_mode *tdm_mode)
297 tdm_mode->clock = vc4_mode->clock;
298 tdm_mode->hdisplay = vc4_mode->hdisplay;
299 tdm_mode->hsync_start = vc4_mode->hsync_start;
300 tdm_mode->hsync_end = vc4_mode->hsync_end;
301 tdm_mode->htotal = vc4_mode->htotal;
302 tdm_mode->hskew = vc4_mode->hskew;
303 tdm_mode->vdisplay = vc4_mode->vdisplay;
304 tdm_mode->vsync_start = vc4_mode->vsync_start;
305 tdm_mode->vsync_end = vc4_mode->vsync_end;
306 tdm_mode->vtotal = vc4_mode->vtotal;
307 tdm_mode->vscan = vc4_mode->vscan;
308 tdm_mode->vrefresh = vc4_mode->vrefresh;
309 tdm_mode->flags = vc4_mode->flags;
310 tdm_mode->type = vc4_mode->type;
311 snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", vc4_mode->name);
315 _tdm_vc4_display_get_cur_msc(int fd, int pipe, uint *msc)
319 vbl.request.type = DRM_VBLANK_RELATIVE;
321 vbl.request.type |= DRM_VBLANK_SECONDARY;
323 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
325 vbl.request.sequence = 0;
326 if (drmWaitVBlank(fd, &vbl)) {
327 TDM_ERR("get vblank counter failed: %m");
329 return TDM_ERROR_OPERATION_FAILED;
332 *msc = vbl.reply.sequence;
334 return TDM_ERROR_NONE;
338 _tdm_vc4_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
342 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
344 vbl.request.type |= DRM_VBLANK_SECONDARY;
346 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
348 vbl.request.sequence = *target_msc;
349 vbl.request.signal = (unsigned long)(uintptr_t)data;
351 if (drmWaitVBlank(fd, &vbl)) {
352 TDM_ERR("wait vblank failed: %m");
354 return TDM_ERROR_OPERATION_FAILED;
357 *target_msc = vbl.reply.sequence;
359 return TDM_ERROR_NONE;
363 _tdm_vc4_output_update_status(tdm_vc4_output_data *output_data,
364 tdm_output_conn_status status)
366 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
368 if (output_data->status == status)
369 return TDM_ERROR_NONE;
371 output_data->status = status;
373 if (output_data->status_func)
374 output_data->status_func(output_data, status,
375 output_data->status_user_data);
377 return TDM_ERROR_NONE;
381 _tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
383 tdm_vc4_data *vc4_data = layer_data->vc4_data;
384 tdm_vc4_output_data *output_data = layer_data->output_data;
385 uint32_t fx, fy, fw, fh;
388 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
389 return TDM_ERROR_NONE;
391 if (!output_data->crtc_enabled || output_data->mode_changed) {
392 if (_tdm_vc4_display_set_crtc(vc4_data, output_data, 1) != TDM_ERROR_NONE)
393 return TDM_ERROR_OPERATION_FAILED;
395 output_data->crtc_enabled = 1;
398 if (output_data->current_mode)
399 crtc_w = output_data->current_mode->hdisplay;
401 drmModeCrtcPtr crtc = drmModeGetCrtc(vc4_data->drm_fd, output_data->crtc_id);
403 TDM_ERR("getting crtc failed");
404 return TDM_ERROR_OPERATION_FAILED;
406 crtc_w = crtc->width;
408 TDM_ERR("getting crtc width failed");
409 drmModeFreeCrtc(crtc);
410 return TDM_ERROR_OPERATION_FAILED;
412 drmModeFreeCrtc(crtc);
415 layer_data->display_buffer_changed = 0;
416 layer_data->info_changed = 0;
418 if (!layer_data->display_buffer) {
419 if (drmModeSetPlane(vc4_data->drm_fd, layer_data->plane_id,
420 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
421 TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
423 return TDM_ERROR_NONE;
426 /* Source values are 16.16 fixed point */
427 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
428 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
429 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
430 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
432 if (drmModeSetPlane(vc4_data->drm_fd, layer_data->plane_id,
433 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
434 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
435 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
436 fx, fy, fw, fh) < 0) {
437 TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
438 return TDM_ERROR_OPERATION_FAILED;
441 TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
442 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
443 layer_data->display_buffer->fb_id,
444 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
445 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
446 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
447 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
449 return TDM_ERROR_NONE;
453 _tdm_vc4_display_cb_event(int fd, unsigned int sequence,
454 unsigned int tv_sec, unsigned int tv_usec,
457 tdm_vc4_event_data *event_data = user_data;
458 tdm_vc4_output_data *output_data;
461 TDM_ERR("no event data");
465 output_data = event_data->output_data;
467 switch (event_data->type) {
468 case TDM_DRM_EVENT_TYPE_PAGEFLIP:
469 if (output_data->commit_func)
470 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
471 event_data->user_data);
473 case TDM_DRM_EVENT_TYPE_WAIT:
474 if (output_data->vblank_func)
475 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
476 event_data->user_data);
478 case TDM_DRM_EVENT_TYPE_COMMIT:
479 if (output_data->commit_func)
480 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
481 event_data->user_data);
491 _tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data)
493 tdm_vc4_output_data *output_data = NULL;
496 if (LIST_IS_EMPTY(&vc4_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, &vc4_data->output_list, link) {
506 if (vc4_data->plane_res->count_planes == 0) {
507 TDM_ERR("no layer error");
508 return TDM_ERROR_OPERATION_FAILED;
511 for (i = 0; i < vc4_data->plane_res->count_planes; i++) {
512 tdm_vc4_layer_data *layer_data;
513 drmModePlanePtr plane;
515 plane = drmModeGetPlane(vc4_data->drm_fd, vc4_data->plane_res->planes[i]);
521 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
522 drmModeFreePlane(plane);
526 layer_data = calloc(1, sizeof(tdm_vc4_layer_data));
528 TDM_ERR("alloc failed");
529 drmModeFreePlane(plane);
533 layer_data->vc4_data = vc4_data;
534 layer_data->output_data = output_data;
535 layer_data->plane_id = vc4_data->plane_res->planes[i];
537 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
538 TDM_LAYER_CAPABILITY_GRAPHIC;
539 output_data->primary_layer = layer_data;
541 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
542 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
543 layer_data->capabilities);
545 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
547 drmModeFreePlane(plane);
549 /* can't take care of other planes for various hardware devices */
553 return TDM_ERROR_NONE;
556 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
559 _tdm_vc4_display_get_property(tdm_vc4_data *vc4_data,
560 unsigned int obj_id, unsigned int obj_type,
561 const char *name, unsigned int *value,
564 drmModeObjectPropertiesPtr props = NULL;
567 props = drmModeObjectGetProperties(vc4_data->drm_fd, obj_id, obj_type);
569 return TDM_ERROR_OPERATION_FAILED;
571 for (i = 0; i < props->count_props; i++) {
572 drmModePropertyPtr prop = drmModeGetProperty(vc4_data->drm_fd,
578 if (!strcmp(prop->name, name)) {
580 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
582 *value = (unsigned int)props->prop_values[i];
583 drmModeFreeProperty(prop);
584 drmModeFreeObjectProperties(props);
585 return TDM_ERROR_NONE;
588 drmModeFreeProperty(prop);
590 drmModeFreeObjectProperties(props);
591 TDM_DBG("coundn't find '%s' property", name);
592 return TDM_ERROR_OPERATION_FAILED;
596 _tdm_vc4_display_create_layer_list_type(tdm_vc4_data *vc4_data)
598 tdm_vc4_output_data *output_data = NULL;
599 drmModePlanePtr *planes = NULL;
600 unsigned int *types = NULL;
601 unsigned int type = 0;
602 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
603 int opos_next, cpos_next;
607 if (LIST_IS_EMPTY(&vc4_data->output_list)) {
608 TDM_ERR("no output");
609 return TDM_ERROR_OPERATION_FAILED;
612 /* The TDM drm backend only support one output. */
613 LIST_FOR_EACH_ENTRY(output_data, &vc4_data->output_list, link) {
617 ret = _tdm_vc4_display_get_property(vc4_data,
618 vc4_data->plane_res->planes[0],
619 DRM_MODE_OBJECT_PLANE, "type", &type,
621 if (ret != TDM_ERROR_NONE) {
622 TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
624 /* if a plane doesn't have "type" property, we call a fallback function
627 return _tdm_vc4_display_create_layer_list(vc4_data);
630 planes = calloc(vc4_data->plane_res->count_planes, sizeof(drmModePlanePtr));
632 TDM_ERR("alloc failed");
636 types = calloc(vc4_data->plane_res->count_planes, sizeof(unsigned int));
638 TDM_ERR("alloc failed");
643 for (i = 0; i < vc4_data->plane_res->count_planes; i++) {
644 drmModePlanePtr plane;
646 plane = drmModeGetPlane(vc4_data->drm_fd, vc4_data->plane_res->planes[i]);
648 TDM_ERR("no plane(%d)", vc4_data->plane_res->planes[i]);
652 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
653 drmModeFreePlane(plane);
657 ret = _tdm_vc4_display_get_property(vc4_data,
658 vc4_data->plane_res->planes[i],
659 DRM_MODE_OBJECT_PLANE, "type", &type,
661 if (ret != TDM_ERROR_NONE) {
662 drmModeFreePlane(plane);
663 TDM_ERR("plane(%d) doesn't have 'type' info",
664 vc4_data->plane_res->planes[i]);
668 planes[plane_cnt] = plane;
669 types[plane_cnt] = type;
673 primary_cnt = ovl_cnt = cursor_cnt = 0;
674 for (i = 0; i < plane_cnt; i++) {
675 if (types[i] == DRM_PLANE_TYPE_CURSOR)
677 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
679 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
682 TDM_ERR("invalid type(%d)", types[i]);
685 if (primary_cnt != 1) {
686 TDM_ERR("primary layer count(%d) should be one", primary_cnt);
690 /* do not use primary plane(0) because of yuv format displaying problem */
691 /* set 2nd overlay plane to primary, 1st plane is for video */
693 cpos_next = ovl_cnt - 1;
694 for (i = 1; i < plane_cnt; i++) {
695 tdm_vc4_layer_data *layer_data;
697 layer_data = calloc(1, sizeof(tdm_vc4_layer_data));
699 TDM_ERR("alloc failed");
703 layer_data->vc4_data = vc4_data;
704 layer_data->output_data = output_data;
705 layer_data->plane_id = planes[i]->plane_id;
707 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
708 layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
709 TDM_LAYER_CAPABILITY_GRAPHIC;
710 layer_data->zpos = cpos_next++;
711 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
713 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
714 TDM_LAYER_CAPABILITY_GRAPHIC |
715 TDM_LAYER_CAPABILITY_SCALE;
717 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
718 TDM_LAYER_CAPABILITY_GRAPHIC;
719 output_data->primary_layer = layer_data;
721 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
722 TDM_LAYER_CAPABILITY_GRAPHIC;
724 layer_data->zpos = opos_next++;
730 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
731 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
732 layer_data->zpos, layer_data->capabilities);
734 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
737 for (i = 0; i < plane_cnt; i++)
739 drmModeFreePlane(planes[i]);
744 return TDM_ERROR_NONE;
748 for (i = 0; i < vc4_data->plane_res->count_planes; i++)
750 drmModeFreePlane(planes[i]);
756 return TDM_ERROR_OPERATION_FAILED;
761 _tdm_vc4_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
763 tdm_vc4_data *vc4_data;
764 tdm_vc4_display_buffer *display_buffer;
768 TDM_ERR("no user_data");
772 TDM_ERR("no buffer");
776 vc4_data = (tdm_vc4_data *)user_data;
778 display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer);
779 if (!display_buffer) {
780 TDM_ERR("no display_buffer");
783 LIST_DEL(&display_buffer->link);
785 if (display_buffer->fb_id > 0) {
786 ret = drmModeRmFB(vc4_data->drm_fd, display_buffer->fb_id);
788 TDM_ERR("rm fb failed");
791 TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id);
793 TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id);
795 free(display_buffer);
799 tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data)
801 tdm_vc4_output_data *output_data = NULL;
804 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
805 if (vc4_data->has_universal_plane)
806 ret = _tdm_vc4_display_create_layer_list_type(vc4_data);
809 ret = _tdm_vc4_display_create_layer_list(vc4_data);
811 if (ret != TDM_ERROR_NONE)
814 LIST_FOR_EACH_ENTRY(output_data, &vc4_data->output_list, link) {
815 if (!output_data->primary_layer) {
816 TDM_ERR("output(%d) no primary layer", output_data->pipe);
817 return TDM_ERROR_OPERATION_FAILED;
821 return TDM_ERROR_NONE;
825 tdm_vc4_display_destroy_output_list(tdm_vc4_data *vc4_data)
827 tdm_vc4_output_data *o = NULL, *oo = NULL;
829 if (LIST_IS_EMPTY(&vc4_data->output_list))
832 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &vc4_data->output_list, link) {
834 if (o->target_hwc_window)
835 vc4_output_hwc_window_destroy(o, o->target_hwc_window);
837 if (o->crtc_enabled) {
838 _tdm_vc4_display_set_crtc(vc4_data, o, 0);
843 if (!LIST_IS_EMPTY(&o->layer_list)) {
844 tdm_vc4_layer_data *l = NULL, *ll = NULL;
845 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
851 free(o->output_modes);
857 tdm_vc4_display_update_output_status(tdm_vc4_data *vc4_data)
859 tdm_vc4_output_data *output_data = NULL;
861 if (LIST_IS_EMPTY(&vc4_data->output_list))
864 LIST_FOR_EACH_ENTRY(output_data, &vc4_data->output_list, link) {
865 drmModeConnectorPtr connector;
866 tdm_output_conn_status new_status;
868 connector = drmModeGetConnector(vc4_data->drm_fd,
869 output_data->connector_id);
871 TDM_ERR("no connector: %d", output_data->connector_id);
875 if (connector->connection == DRM_MODE_CONNECTED)
876 new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
878 new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
880 _tdm_vc4_output_update_status(output_data, new_status);
882 drmModeFreeConnector(connector);
887 tdm_vc4_display_create_output_list(tdm_vc4_data *vc4_data)
889 tdm_vc4_output_data *output_data;
893 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&vc4_data->output_list),
894 TDM_ERROR_OPERATION_FAILED);
896 for (i = 0; i < vc4_data->mode_res->count_connectors; i++) {
897 drmModeConnectorPtr connector;
898 drmModeEncoderPtr encoder;
899 int crtc_id = 0, c, j;
901 connector = drmModeGetConnector(vc4_data->drm_fd,
902 vc4_data->mode_res->connectors[i]);
904 TDM_ERR("no connector");
905 ret = TDM_ERROR_OPERATION_FAILED;
909 /* The TDM drm backend is not interested with disconnected connectors.
910 * And it only considers 1 connected connector because it is the TDM
911 * reference backend and can't take care of all hardware devices.
912 * To support various connectors, planes and crtcs, the new TDM backend
913 * should be implemented.
915 if (connector->connection != DRM_MODE_CONNECTED) {
916 drmModeFreeConnector(connector);
920 if (connector->count_encoders != 1) {
921 TDM_ERR("too many encoders: %d", connector->count_encoders);
922 drmModeFreeConnector(connector);
923 ret = TDM_ERROR_OPERATION_FAILED;
927 encoder = drmModeGetEncoder(vc4_data->drm_fd, connector->encoders[0]);
929 TDM_ERR("no encoder");
930 drmModeFreeConnector(connector);
931 ret = TDM_ERROR_OPERATION_FAILED;
935 for (c = 0; c < vc4_data->mode_res->count_crtcs; c++) {
936 if ((encoder->possible_crtcs & (1 << c)) == 0)
939 crtc_id = vc4_data->mode_res->crtcs[c];
944 TDM_ERR("no possible crtc");
945 drmModeFreeConnector(connector);
946 drmModeFreeEncoder(encoder);
947 ret = TDM_ERROR_OPERATION_FAILED;
951 output_data = calloc(1, sizeof(tdm_vc4_output_data));
953 TDM_ERR("alloc failed");
954 drmModeFreeConnector(connector);
955 drmModeFreeEncoder(encoder);
956 ret = TDM_ERROR_OUT_OF_MEMORY;
960 LIST_INITHEAD(&output_data->layer_list);
962 output_data->vc4_data = vc4_data;
963 output_data->connector_id = vc4_data->mode_res->connectors[i];
964 output_data->encoder_id = encoder->encoder_id;
965 output_data->crtc_id = crtc_id;
966 output_data->pipe = c;
967 output_data->connector_type = connector->connector_type;
968 output_data->connector_type_id = connector->connector_type_id;
970 if (connector->connection == DRM_MODE_CONNECTED)
971 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
973 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
975 for (j = 0; j < connector->count_props; j++) {
976 drmModePropertyPtr prop = drmModeGetProperty(vc4_data->drm_fd,
977 connector->props[j]);
980 if (!strcmp(prop->name, "DPMS")) {
981 output_data->dpms_prop_id = connector->props[j];
982 drmModeFreeProperty(prop);
985 drmModeFreeProperty(prop);
988 if (output_data->dpms_prop_id == 0)
989 TDM_WRN("not support DPMS");
991 output_data->count_modes = connector->count_modes;
992 output_data->vc4_modes = calloc(connector->count_modes,
993 sizeof(drmModeModeInfo));
994 if (!output_data->vc4_modes) {
995 TDM_ERR("alloc failed");
997 drmModeFreeConnector(connector);
998 drmModeFreeEncoder(encoder);
999 ret = TDM_ERROR_OUT_OF_MEMORY;
1002 output_data->output_modes = calloc(connector->count_modes,
1003 sizeof(tdm_output_mode));
1004 if (!output_data->output_modes) {
1005 TDM_ERR("alloc failed");
1006 free(output_data->vc4_modes);
1008 drmModeFreeConnector(connector);
1009 drmModeFreeEncoder(encoder);
1010 ret = TDM_ERROR_OUT_OF_MEMORY;
1013 for (j = 0; j < connector->count_modes; j++) {
1014 output_data->vc4_modes[j] = connector->modes[j];
1015 _tdm_vc4_display_to_tdm_mode(&output_data->vc4_modes[j],
1016 &output_data->output_modes[j]);
1019 if (vc4_data->hwc_mode) {
1020 output_data->hwc_enable = 1;
1021 output_data->target_hwc_window = NULL;
1022 LIST_INITHEAD(&output_data->hwc_window_list);
1025 LIST_ADDTAIL(&output_data->link, &vc4_data->output_list);
1027 TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
1028 output_data, output_data->connector_id, output_data->status,
1029 output_data->connector_type,
1030 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
1031 output_data->pipe, output_data->dpms_prop_id);
1033 drmModeFreeEncoder(encoder);
1034 drmModeFreeConnector(connector);
1036 /* The TDM drm backend is not interested with disconnected connectors.
1037 * And it only considers 1 connected connector because it is the TDM
1038 * reference backend and can't take care of all hardware devices.
1039 * To support various connectors, planes and crtcs, the new TDM backend
1040 * should be implemented.
1045 TDM_DBG("output count: %d", vc4_data->mode_res->count_connectors);
1047 return TDM_ERROR_NONE;
1049 tdm_vc4_display_destroy_output_list(vc4_data);
1054 vc4_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
1056 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1058 caps->max_layer_count = -1; /* not defined */
1060 return TDM_ERROR_NONE;
1064 vc4_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
1066 tdm_vc4_data *vc4_data = bdata;
1067 tdm_vc4_output_data *output_data = NULL;
1068 tdm_output **outputs;
1072 RETURN_VAL_IF_FAIL(vc4_data, NULL);
1073 RETURN_VAL_IF_FAIL(count, NULL);
1076 LIST_FOR_EACH_ENTRY(output_data, &vc4_data->output_list, link)
1080 ret = TDM_ERROR_NONE;
1084 /* will be freed in frontend */
1085 outputs = calloc(*count, sizeof(tdm_vc4_output_data *));
1087 TDM_ERR("failed: alloc memory");
1089 ret = TDM_ERROR_OUT_OF_MEMORY;
1094 LIST_FOR_EACH_ENTRY(output_data, &vc4_data->output_list, link)
1095 outputs[i++] = output_data;
1098 *error = TDM_ERROR_NONE;
1108 vc4_display_get_fd(tdm_backend_data *bdata, int *fd)
1110 tdm_vc4_data *vc4_data = bdata;
1112 RETURN_VAL_IF_FAIL(vc4_data, TDM_ERROR_INVALID_PARAMETER);
1113 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
1115 *fd = vc4_data->drm_fd;
1117 return TDM_ERROR_NONE;
1121 vc4_display_handle_events(tdm_backend_data *bdata)
1123 tdm_vc4_data *vc4_data = bdata;
1124 drmEventContext ctx;
1126 RETURN_VAL_IF_FAIL(vc4_data, TDM_ERROR_INVALID_PARAMETER);
1128 memset(&ctx, 0, sizeof(drmEventContext));
1130 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1131 ctx.page_flip_handler = _tdm_vc4_display_cb_event;
1132 ctx.vblank_handler = _tdm_vc4_display_cb_event;
1134 drmHandleEvent(vc4_data->drm_fd, &ctx);
1136 return TDM_ERROR_NONE;
1140 vc4_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1142 tdm_vc4_output_data *output_data = output;
1143 tdm_vc4_data *vc4_data;
1144 drmModeConnectorPtr connector = NULL;
1145 drmModeCrtcPtr crtc = NULL;
1146 drmModeObjectPropertiesPtr props = NULL;
1150 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1151 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1153 memset(caps, 0, sizeof(tdm_caps_output));
1155 vc4_data = output_data->vc4_data;
1157 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1158 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1159 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1161 caps->status = output_data->status;
1162 caps->type = output_data->connector_type;
1163 caps->type_id = output_data->connector_type_id;
1165 connector = drmModeGetConnector(vc4_data->drm_fd, output_data->connector_id);
1166 RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
1168 caps->mode_count = connector->count_modes;
1169 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1171 ret = TDM_ERROR_OUT_OF_MEMORY;
1172 TDM_ERR("alloc failed\n");
1175 for (i = 0; i < caps->mode_count; i++)
1176 caps->modes[i] = output_data->output_modes[i];
1178 caps->mmWidth = connector->mmWidth;
1179 caps->mmHeight = connector->mmHeight;
1180 caps->subpixel = connector->subpixel;
1182 caps->min_w = vc4_data->mode_res->min_width;
1183 caps->min_h = vc4_data->mode_res->min_height;
1184 caps->max_w = vc4_data->mode_res->max_width;
1185 caps->max_h = vc4_data->mode_res->max_height;
1186 caps->preferred_align = -1;
1188 crtc = drmModeGetCrtc(vc4_data->drm_fd, output_data->crtc_id);
1190 ret = TDM_ERROR_OPERATION_FAILED;
1191 TDM_ERR("get crtc failed: %m\n");
1195 props = drmModeObjectGetProperties(vc4_data->drm_fd, output_data->crtc_id,
1196 DRM_MODE_OBJECT_CRTC);
1198 ret = TDM_ERROR_OPERATION_FAILED;
1199 TDM_ERR("get crtc properties failed: %m\n");
1203 caps->prop_count = props->count_props;
1204 caps->props = calloc(1, sizeof(tdm_prop) * caps->prop_count);
1206 ret = TDM_ERROR_OUT_OF_MEMORY;
1207 TDM_ERR("alloc failed\n");
1211 for (i = 0; i < caps->prop_count; i++) {
1212 drmModePropertyPtr prop = drmModeGetProperty(vc4_data->drm_fd, props->props[i]);
1215 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1216 caps->props[i].id = props->props[i];
1217 drmModeFreeProperty(prop);
1220 if (output_data->hwc_enable)
1221 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
1223 drmModeFreeObjectProperties(props);
1224 drmModeFreeCrtc(crtc);
1225 drmModeFreeConnector(connector);
1227 return TDM_ERROR_NONE;
1229 drmModeFreeCrtc(crtc);
1230 drmModeFreeObjectProperties(props);
1231 drmModeFreeConnector(connector);
1234 memset(caps, 0, sizeof(tdm_caps_output));
1239 vc4_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1241 tdm_vc4_output_data *output_data = output;
1242 tdm_vc4_layer_data *layer_data = NULL;
1247 RETURN_VAL_IF_FAIL(output_data, NULL);
1248 RETURN_VAL_IF_FAIL(count, NULL);
1251 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1255 ret = TDM_ERROR_NONE;
1259 /* will be freed in frontend */
1260 layers = calloc(*count, sizeof(tdm_vc4_layer_data *));
1262 TDM_ERR("failed: alloc memory");
1264 ret = TDM_ERROR_OUT_OF_MEMORY;
1269 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1270 layers[i++] = layer_data;
1273 *error = TDM_ERROR_NONE;
1283 vc4_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1285 tdm_vc4_output_data *output_data = output;
1286 tdm_vc4_data *vc4_data;
1289 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1290 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1292 vc4_data = output_data->vc4_data;
1293 ret = drmModeObjectSetProperty(vc4_data->drm_fd,
1294 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1297 TDM_ERR("set property failed: %m");
1298 return TDM_ERROR_OPERATION_FAILED;
1301 return TDM_ERROR_NONE;
1305 vc4_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1307 tdm_vc4_output_data *output_data = output;
1308 tdm_vc4_data *vc4_data;
1309 drmModeObjectPropertiesPtr props;
1312 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1313 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1314 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1316 vc4_data = output_data->vc4_data;
1317 props = drmModeObjectGetProperties(vc4_data->drm_fd, output_data->crtc_id,
1318 DRM_MODE_OBJECT_CRTC);
1319 if (props == NULL) {
1320 TDM_ERR("get property failed: %m");
1321 return TDM_ERROR_OPERATION_FAILED;
1324 for (i = 0; i < props->count_props; i++)
1325 if (props->props[i] == id) {
1326 (*value).u32 = (uint)props->prop_values[i];
1330 drmModeFreeObjectProperties(props);
1332 return TDM_ERROR_NONE;
1336 vc4_output_wait_vblank(tdm_output *output, int interval, int sync,
1339 tdm_vc4_output_data *output_data = output;
1340 tdm_vc4_data *vc4_data;
1341 tdm_vc4_event_data *event_data;
1345 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1347 event_data = calloc(1, sizeof(tdm_vc4_event_data));
1349 TDM_ERR("alloc failed");
1350 return TDM_ERROR_OUT_OF_MEMORY;
1353 vc4_data = output_data->vc4_data;
1355 ret = _tdm_vc4_display_get_cur_msc(vc4_data->drm_fd, output_data->pipe,
1357 if (ret != TDM_ERROR_NONE)
1360 target_msc += interval;
1362 event_data->type = TDM_DRM_EVENT_TYPE_WAIT;
1363 event_data->output_data = output_data;
1364 event_data->user_data = user_data;
1366 ret = _tdm_vc4_display_wait_vblank(vc4_data->drm_fd, output_data->pipe,
1367 &target_msc, event_data);
1368 if (ret != TDM_ERROR_NONE)
1371 return TDM_ERROR_NONE;
1378 vc4_output_set_vblank_handler(tdm_output *output,
1379 tdm_output_vblank_handler func)
1381 tdm_vc4_output_data *output_data = output;
1383 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1384 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1386 output_data->vblank_func = func;
1388 return TDM_ERROR_NONE;
1391 tdm_vc4_layer_data *
1392 _vc4_output_get_layer(tdm_vc4_output_data *output_data, int index)
1394 tdm_vc4_layer_data *l = NULL;
1395 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
1396 if (l->zpos == index)
1403 _vc4_layer_attach_window(tdm_vc4_layer_data *layer_data,
1404 tdm_vc4_hwc_window_data *hwc_window_data)
1408 if (hwc_window_data == NULL || !hwc_window_data->surface) {
1409 ret = vc4_layer_unset_buffer(layer_data);
1410 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1412 ret = vc4_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
1413 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1414 RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
1415 ret = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
1416 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1423 _get_primary_layer_index(tdm_vc4_output_data *vc4_output)
1426 tdm_vc4_layer_data *layer = NULL;
1428 LIST_FOR_EACH_ENTRY(layer, &vc4_output->layer_list, link) {
1429 if (layer->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
1438 _tdm_vc4_display_prepare_commit(tdm_vc4_output_data *output_data) {
1440 tdm_vc4_layer_data * layer = NULL;
1441 tdm_vc4_hwc_window_data *hw = NULL;
1442 int num_hw_layer = 0;
1446 RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
1448 i = output_data->top_layer_idx;
1449 num_hw_layer = LIST_LENGTH(&output_data->layer_list);
1450 fb_idx = _get_primary_layer_index(output_data);
1452 //set target hwc window
1453 if (output_data->need_target_buffer) {
1454 layer = _vc4_output_get_layer(output_data, fb_idx);
1455 _vc4_layer_attach_window(layer, output_data->target_hwc_window);
1459 LIST_FOR_EACH_ENTRY_REV(hw, &output_data->hwc_window_list, link) {
1460 if (output_data->need_target_buffer && i == fb_idx) {
1463 if (hw->client_type != TDM_COMPOSITION_DEVICE)
1465 RETURN_VAL_IF_FAIL(i >= 0, TDM_ERROR_OPERATION_FAILED);
1466 layer = _vc4_output_get_layer(output_data, i--);
1467 _vc4_layer_attach_window(layer, hw);
1470 //disable unused layer
1472 layer = _vc4_output_get_layer(output_data, i--);
1473 _vc4_layer_attach_window(layer, NULL);
1476 i = output_data->top_layer_idx + 1;
1477 while (i < num_hw_layer) {
1478 layer = _vc4_output_get_layer(output_data, i++);
1479 _vc4_layer_attach_window(layer, NULL);
1482 return TDM_ERROR_NONE;
1486 vc4_output_commit(tdm_output *output, int sync, void *user_data)
1488 tdm_vc4_output_data *output_data = output;
1489 tdm_vc4_data *vc4_data;
1490 tdm_vc4_layer_data *layer_data = NULL;
1492 int do_waitvblank = 1;
1494 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1496 vc4_data = output_data->vc4_data;
1498 if (output_data->hwc_enable) {
1499 ret = _tdm_vc4_display_prepare_commit(output_data);
1500 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1503 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1504 ret = _tdm_vc4_display_commit_layer(layer_data);
1505 if (ret != TDM_ERROR_NONE)
1509 if (do_waitvblank == 1) {
1510 tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
1514 TDM_ERR("alloc failed");
1515 return TDM_ERROR_OUT_OF_MEMORY;
1518 ret = _tdm_vc4_display_get_cur_msc(vc4_data->drm_fd, output_data->pipe,
1520 if (ret != TDM_ERROR_NONE) {
1527 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1528 event_data->output_data = output_data;
1529 event_data->user_data = user_data;
1531 ret = _tdm_vc4_display_wait_vblank(vc4_data->drm_fd, output_data->pipe,
1532 &target_msc, event_data);
1533 if (ret != TDM_ERROR_NONE) {
1539 return TDM_ERROR_NONE;
1543 vc4_output_set_commit_handler(tdm_output *output,
1544 tdm_output_commit_handler func)
1546 tdm_vc4_output_data *output_data = output;
1548 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1549 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1551 output_data->commit_func = func;
1553 return TDM_ERROR_NONE;
1557 vc4_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1559 tdm_vc4_output_data *output_data = output;
1560 tdm_vc4_data *vc4_data;
1563 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1565 if (output_data->dpms_prop_id == 0) {
1566 TDM_WRN("not support DPMS");
1567 return TDM_ERROR_OPERATION_FAILED;
1570 vc4_data = output_data->vc4_data;
1571 ret = drmModeObjectSetProperty(vc4_data->drm_fd,
1572 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1573 output_data->dpms_prop_id, dpms_value);
1575 TDM_ERR("set dpms failed: %m");
1576 return TDM_ERROR_OPERATION_FAILED;
1579 return TDM_ERROR_NONE;
1583 vc4_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1585 tdm_vc4_output_data *output_data = output;
1586 tdm_vc4_data *vc4_data;
1587 drmModeObjectPropertiesPtr props;
1590 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1591 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1593 vc4_data = output_data->vc4_data;
1594 props = drmModeObjectGetProperties(vc4_data->drm_fd, output_data->connector_id,
1595 DRM_MODE_OBJECT_CONNECTOR);
1596 if (props == NULL) {
1597 TDM_ERR("get property failed: %m");
1598 return TDM_ERROR_OPERATION_FAILED;
1601 for (i = 0; i < props->count_props; i++)
1602 if (props->props[i] == output_data->dpms_prop_id) {
1603 *dpms_value = (uint)props->prop_values[i];
1607 drmModeFreeObjectProperties(props);
1609 return TDM_ERROR_NONE;
1613 vc4_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1615 tdm_vc4_output_data *output_data = output;
1617 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1618 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1620 if (output_data->hwc_enable) {
1622 tdm_hwc_window_info info = {0};
1623 tdm_error ret = TDM_ERROR_NONE;
1624 tdm_vc4_hwc_window_data *target_hwc_window;
1628 info.dst_pos.h = mode->vdisplay;;
1629 info.dst_pos.w = mode->hdisplay;
1631 info.src_config.pos.x = 0;
1632 info.src_config.pos.y = 0;
1633 info.src_config.pos.h = mode->vdisplay;
1634 info.src_config.pos.w = mode->hdisplay;
1636 info.src_config.size.h = mode->hdisplay;
1637 info.src_config.size.v = mode->vdisplay;
1638 info.src_config.format = TBM_FORMAT_ARGB8888;
1640 target_hwc_window = _vc4_output_hwc_window_create(output_data, &info, &ret);
1641 if (ret != TDM_ERROR_NONE) {
1642 TDM_ERR("create target hwc window failed (%d)", ret);
1643 return TDM_ERROR_OPERATION_FAILED;
1646 if (output_data->target_hwc_window)
1647 vc4_output_hwc_window_destroy(output, output_data->target_hwc_window);
1649 output_data->target_hwc_window = target_hwc_window;
1650 output_data->need_set_crtc = 1;
1653 output_data->current_mode = mode;
1654 output_data->mode_changed = 1;
1655 return TDM_ERROR_NONE;
1659 vc4_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1661 tdm_vc4_output_data *output_data = output;
1663 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1664 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1666 *mode = output_data->current_mode;
1668 return TDM_ERROR_NONE;
1672 vc4_output_set_status_handler(tdm_output *output,
1673 tdm_output_status_handler func,
1676 tdm_vc4_output_data *output_data = output;
1678 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1679 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1681 output_data->status_func = func;
1682 output_data->status_user_data = user_data;
1684 return TDM_ERROR_NONE;
1688 vc4_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1690 tdm_vc4_layer_data *layer_data = layer;
1691 tdm_vc4_data *vc4_data;
1692 drmModePlanePtr plane = NULL;
1693 drmModeObjectPropertiesPtr props = NULL;
1694 int i, format_count = 0;
1697 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1698 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1700 memset(caps, 0, sizeof(tdm_caps_layer));
1702 vc4_data = layer_data->vc4_data;
1703 plane = drmModeGetPlane(vc4_data->drm_fd, layer_data->plane_id);
1705 TDM_ERR("get plane failed: %m");
1706 ret = TDM_ERROR_OPERATION_FAILED;
1710 caps->capabilities = layer_data->capabilities;
1711 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1713 caps->format_count = plane->count_formats;
1714 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1715 if (!caps->formats) {
1716 ret = TDM_ERROR_OUT_OF_MEMORY;
1717 TDM_ERR("alloc failed\n");
1721 for (i = 0; i < caps->format_count; i++) {
1722 /* TODO: kernel reports wrong formats */
1723 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1724 plane->formats[i] != DRM_FORMAT_ARGB8888 &&
1725 plane->formats[i] != DRM_FORMAT_NV12 &&
1726 plane->formats[i] != DRM_FORMAT_YUV420)
1728 caps->formats[format_count] = tdm_vc4_format_to_tbm_format(plane->formats[i]);
1732 caps->format_count = format_count;
1734 props = drmModeObjectGetProperties(vc4_data->drm_fd, layer_data->plane_id,
1735 DRM_MODE_OBJECT_PLANE);
1737 ret = TDM_ERROR_OPERATION_FAILED;
1738 TDM_ERR("get plane properties failed: %m\n");
1742 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1744 ret = TDM_ERROR_OUT_OF_MEMORY;
1745 TDM_ERR("alloc failed\n");
1749 caps->prop_count = 0;
1750 for (i = 0; i < props->count_props; i++) {
1751 drmModePropertyPtr prop = drmModeGetProperty(vc4_data->drm_fd, props->props[i]);
1754 if (!strncmp(prop->name, "type", TDM_NAME_LEN)) {
1755 drmModeFreeProperty(prop);
1758 if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) {
1759 drmModeFreeProperty(prop);
1762 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1763 caps->props[i].id = props->props[i];
1765 drmModeFreeProperty(prop);
1768 drmModeFreeObjectProperties(props);
1769 drmModeFreePlane(plane);
1771 return TDM_ERROR_NONE;
1773 drmModeFreeObjectProperties(props);
1774 drmModeFreePlane(plane);
1775 free(caps->formats);
1777 memset(caps, 0, sizeof(tdm_caps_layer));
1782 vc4_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1784 tdm_vc4_layer_data *layer_data = layer;
1785 tdm_vc4_data *vc4_data;
1788 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1789 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1791 vc4_data = layer_data->vc4_data;
1792 ret = drmModeObjectSetProperty(vc4_data->drm_fd,
1793 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1796 TDM_ERR("set property failed: %m");
1797 return TDM_ERROR_OPERATION_FAILED;
1800 return TDM_ERROR_NONE;
1804 vc4_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1806 tdm_vc4_layer_data *layer_data = layer;
1807 tdm_vc4_data *vc4_data;
1808 drmModeObjectPropertiesPtr props;
1811 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1812 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1813 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1815 vc4_data = layer_data->vc4_data;
1816 props = drmModeObjectGetProperties(vc4_data->drm_fd, layer_data->plane_id,
1817 DRM_MODE_OBJECT_PLANE);
1818 if (props == NULL) {
1819 TDM_ERR("get property failed: %m");
1820 return TDM_ERROR_OPERATION_FAILED;
1823 for (i = 0; i < props->count_props; i++)
1824 if (props->props[i] == id) {
1825 (*value).u32 = (uint)props->prop_values[i];
1829 drmModeFreeObjectProperties(props);
1831 return TDM_ERROR_NONE;
1835 vc4_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1837 tdm_vc4_layer_data *layer_data = layer;
1839 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1840 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1842 layer_data->info = *info;
1843 layer_data->info_changed = 1;
1845 return TDM_ERROR_NONE;
1849 vc4_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1851 tdm_vc4_layer_data *layer_data = layer;
1853 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1854 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1856 *info = layer_data->info;
1858 return TDM_ERROR_NONE;
1862 vc4_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1864 tdm_vc4_layer_data *layer_data = layer;
1865 tdm_vc4_data *vc4_data;
1866 tdm_vc4_display_buffer *display_buffer;
1867 tdm_error err = TDM_ERROR_NONE;
1870 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1871 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
1873 vc4_data = layer_data->vc4_data;
1875 display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer);
1876 if (!display_buffer) {
1877 display_buffer = calloc(1, sizeof(tdm_vc4_display_buffer));
1878 if (!display_buffer) {
1879 TDM_ERR("alloc failed");
1880 return TDM_ERROR_OUT_OF_MEMORY;
1882 display_buffer->buffer = buffer;
1884 err = tdm_buffer_add_destroy_handler(buffer, _tdm_vc4_display_cb_destroy_buffer,
1886 if (err != TDM_ERROR_NONE) {
1887 TDM_ERR("add destroy handler fail");
1888 free(display_buffer);
1889 return TDM_ERROR_OPERATION_FAILED;
1892 LIST_ADDTAIL(&display_buffer->link, &vc4_data->buffer_list);
1895 if (display_buffer->fb_id == 0) {
1897 unsigned int height;
1898 unsigned int format;
1899 unsigned int handles[4] = {0,};
1900 unsigned int pitches[4] = {0,};
1901 unsigned int offsets[4] = {0,};
1905 width = tbm_surface_get_width(buffer);
1906 height = tbm_surface_get_height(buffer);
1907 format = tbm_surface_get_format(buffer);
1908 count = tbm_surface_internal_get_num_planes(format);
1910 bo = tbm_surface_internal_get_bo(buffer, 0);
1911 handles[0] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1912 for (i = 1; i < count; i++)
1913 handles[i] = handles[0];
1915 for (i = 0; i < count; i++)
1916 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
1918 ret = drmModeAddFB2(vc4_data->drm_fd, width, height, format,
1919 handles, pitches, offsets, &display_buffer->fb_id, 0);
1921 TDM_ERR("add fb failed: %m");
1922 return TDM_ERROR_OPERATION_FAILED;
1924 TDM_DBG("vc4_data->drm_fd : %d, display_buffer->fb_id:%u", vc4_data->drm_fd,
1925 display_buffer->fb_id);
1928 display_buffer->width = pitches[0] >> 2;
1930 display_buffer->width = pitches[0];
1933 layer_data->display_buffer = display_buffer;
1934 layer_data->display_buffer_changed = 1;
1936 return TDM_ERROR_NONE;
1940 vc4_layer_unset_buffer(tdm_layer *layer)
1942 tdm_vc4_layer_data *layer_data = layer;
1944 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1946 layer_data->display_buffer = NULL;
1947 layer_data->display_buffer_changed = 1;
1949 return TDM_ERROR_NONE;
1953 tdm_vc4_output_insert_hwc_window(tdm_vc4_output_data *output, tdm_vc4_hwc_window_data *hwc_window)
1955 tdm_vc4_hwc_window_data *item = NULL;
1956 LIST_FOR_EACH_ENTRY_REV(item, &output->hwc_window_list, link) {
1957 if (item == hwc_window)
1958 return TDM_ERROR_OPERATION_FAILED;
1960 if (item->zpos <= hwc_window->zpos)
1964 LIST_INSERT_AFTER(&item->link, &hwc_window->link);
1966 return TDM_ERROR_NONE;
1970 _vc4_output_get_changed_number(tdm_vc4_output_data *vc4_output)
1973 tdm_vc4_hwc_window_data *hw = NULL;
1975 LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
1976 if (hw->client_type != hw->validated_type)
1984 _vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info, tdm_error *error)
1986 tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
1987 tdm_vc4_output_data *vc4_output = output;
1990 *error = TDM_ERROR_NONE;
1993 TDM_ERR("invalid params");
1995 *error = TDM_ERROR_INVALID_PARAMETER;
1999 vc4_hwc_window = calloc(1, sizeof(tdm_vc4_hwc_window_data));
2000 if (!vc4_hwc_window) {
2001 TDM_ERR("alloc failed");
2003 *error = TDM_ERROR_OUT_OF_MEMORY;
2007 if ((vc4_hwc_window->vc4_data = vc4_output->vc4_data) == NULL) {
2008 TDM_ERR("invalid params");
2010 *error = TDM_ERROR_INVALID_PARAMETER;
2014 vc4_hwc_window->output_data = output;
2015 vc4_hwc_window->zpos = 0;
2018 memcpy(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info));
2020 return vc4_hwc_window;
2023 free(vc4_hwc_window);
2029 vc4_output_hwc_window_create(tdm_output *output, tdm_error *error)
2031 tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
2032 tdm_vc4_output_data *vc4_output = output;
2035 vc4_hwc_window = _vc4_output_hwc_window_create(vc4_output, NULL, error);
2036 if (vc4_hwc_window == NULL)
2039 err = tdm_vc4_output_insert_hwc_window(vc4_output, vc4_hwc_window);
2040 if (err != TDM_ERROR_NONE) {
2043 free(vc4_hwc_window);
2047 TDM_DBG("hwc_window(%p) create", vc4_hwc_window);
2049 *error = TDM_ERROR_NONE;
2051 return vc4_hwc_window;
2055 vc4_output_hwc_window_destroy(tdm_output *output, tdm_hwc_window *hwc_window)
2057 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2059 LIST_DEL(&vc4_hwc_window->link);
2061 free(vc4_hwc_window);
2063 return TDM_ERROR_NONE;
2067 _comp_to_str(tdm_hwc_window_composition composition_type)
2069 if (composition_type == TDM_COMPOSITION_CLIENT)
2071 else if (composition_type == TDM_COMPOSITION_DEVICE_CANDIDATE)
2072 return "DEVICE_CANDIDATE";
2073 else if (composition_type == TDM_COMPOSITION_DEVICE)
2075 else if (composition_type == TDM_COMPOSITION_CURSOR)
2082 vc4_output_hwc_validate(tdm_output *output, uint32_t *num_types)
2084 tdm_vc4_output_data *vc4_output = output;
2085 tdm_vc4_data *vc4_data = NULL;
2086 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2087 RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
2088 tdm_vc4_hwc_window_data *hw = NULL;
2089 int hw_layer_count = 0;
2090 int need_target_buffer = 0;
2091 int max_hw_layer = LIST_LENGTH(&vc4_output->layer_list);
2092 int fb_index = _get_primary_layer_index(vc4_output);
2094 int top_layer_idx = fb_index;
2096 vc4_data = vc4_output->vc4_data;
2097 RETURN_VAL_IF_FAIL(vc4_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2099 if (vc4_output->need_set_crtc) {
2100 need_target_buffer = 1;
2102 LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
2103 hw->validated_type = TDM_COMPOSITION_CLIENT;
2107 int num_hwc_windows = LIST_LENGTH(&vc4_output->hwc_window_list);
2109 LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
2110 hw->validated_type = TDM_COMPOSITION_CLIENT;
2113 /* mark the top window */
2114 if (num_hwc_windows > 1) {
2115 layer_idx = max_hw_layer;
2116 LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
2118 if (hw->client_type == TDM_COMPOSITION_DEVICE && layer_idx != fb_index) {
2120 if (IS_RGB(hw->info.src_config.format)) {
2121 hw->validated_type = TDM_COMPOSITION_DEVICE;
2131 if ((num_hwc_windows - hw_layer_count) > (fb_index + 1))
2132 need_target_buffer = 1;
2134 max_hw_layer = fb_index + 1;
2135 if (need_target_buffer)
2138 /* mark the bottom windows */
2140 LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
2142 /* break if the remaining windows are already marked */
2143 if (hw->validated_type == TDM_COMPOSITION_DEVICE)
2145 if (hw->client_type == TDM_COMPOSITION_DEVICE && layer_idx < max_hw_layer) {
2147 if (IS_RGB(hw->info.src_config.format)) {
2148 hw->validated_type = TDM_COMPOSITION_DEVICE;
2154 need_target_buffer = 1;
2159 LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
2160 if (need_target_buffer && fb_index == i++)
2161 TDM_DBG(" window(%p) target", vc4_output->target_hwc_window);
2163 TDM_DBG(" window(%p) type: %s -> %s", hw,
2164 _comp_to_str(hw->client_type), _comp_to_str(hw->validated_type));
2167 if (need_target_buffer)
2170 vc4_output->need_target_buffer = need_target_buffer;
2171 vc4_output->hw_layer_count = hw_layer_count;
2172 vc4_output->top_layer_idx = top_layer_idx;
2174 *num_types = _vc4_output_get_changed_number(vc4_output);
2176 if (*num_types == 0)
2177 vc4_output->need_validate = 0;
2179 return TDM_ERROR_NONE;
2183 vc4_output_hwc_get_changed_composition_types(tdm_output *output,
2184 uint32_t *num_elements,
2185 tdm_hwc_window **hwc_window,
2186 tdm_hwc_window_composition *composition_types)
2188 tdm_vc4_output_data *vc4_output = output;
2191 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2192 RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
2194 if ((hwc_window == NULL) || (composition_types == NULL)) {
2195 *num_elements = _vc4_output_get_changed_number(vc4_output);
2196 return TDM_ERROR_NONE;
2199 tdm_vc4_hwc_window_data *hw = NULL;
2200 LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
2202 if (num >= *num_elements)
2205 if (hw->client_type != hw->validated_type) {
2206 composition_types[num] = hw->validated_type;
2207 hwc_window[num] = hw;
2212 //set real num of changed composition types
2213 *num_elements = num;
2215 return TDM_ERROR_NONE;
2219 vc4_output_hwc_accept_changes(tdm_output *output)
2221 tdm_vc4_output_data *vc4_output = output;
2223 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2225 tdm_vc4_hwc_window_data *hw = NULL;
2226 LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link)
2227 hw->client_type = hw->validated_type;
2229 vc4_output->need_validate = 0;
2231 return TDM_ERROR_NONE;
2235 vc4_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error)
2237 tdm_vc4_output_data *vc4_output = output;
2238 tbm_surface_queue_h tqueue = NULL;
2241 *error = TDM_ERROR_INVALID_PARAMETER;
2243 RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
2245 if (vc4_output->target_hwc_window == NULL) {
2247 *error = TDM_ERROR_OPERATION_FAILED;
2251 tqueue = vc4_hwc_window_get_tbm_buffer_queue(vc4_output->target_hwc_window, error);
2252 RETURN_VAL_IF_FAIL(tqueue, NULL);
2255 *error = TDM_ERROR_NONE;
2261 vc4_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer,
2262 tdm_hwc_region damage, tdm_hwc_window **composited_wnds,
2265 tdm_vc4_output_data *vc4_output = output;
2268 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2269 RETURN_VAL_IF_FAIL(vc4_output->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
2271 err = vc4_hwc_window_set_buffer(vc4_output->target_hwc_window, buffer);
2272 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2274 err = vc4_hwc_window_set_buffer_damage(vc4_output->target_hwc_window, damage);
2275 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2277 return TDM_ERROR_NONE;
2282 vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
2284 tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
2285 tdm_vc4_output_data *vc4_output = NULL;
2286 tbm_surface_queue_h tqueue = NULL;
2290 *error = TDM_ERROR_INVALID_PARAMETER;
2292 RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
2293 vc4_hwc_window = hwc_window;
2294 vc4_output = vc4_hwc_window->output_data;
2295 RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
2297 int wight = vc4_hwc_window->info.src_config.size.h;
2298 int hight = vc4_hwc_window->info.src_config.size.v;
2300 format = vc4_hwc_window->info.src_config.format;
2302 tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
2304 *error = TDM_ERROR_OPERATION_FAILED;
2305 RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
2308 *error = TDM_ERROR_NONE;
2315 vc4_hwc_window_set_zpos(tdm_hwc_window *hwc_window, uint32_t zpos)
2317 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2318 tdm_vc4_output_data *vc4_output;
2320 RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
2321 RETURN_VAL_IF_FAIL(zpos < 256, TDM_ERROR_INVALID_PARAMETER);
2323 vc4_output = vc4_hwc_window->output_data;
2324 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2326 if (vc4_hwc_window->zpos == zpos)
2327 return TDM_ERROR_NONE;
2329 LIST_DEL(&vc4_hwc_window->link);
2331 vc4_hwc_window->zpos = zpos;
2333 tdm_vc4_output_insert_hwc_window(vc4_output, vc4_hwc_window);
2335 vc4_output->need_validate = 1;
2337 return TDM_ERROR_NONE;
2342 vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
2343 tdm_hwc_window_composition comp_type)
2345 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2346 tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
2348 RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
2349 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2351 if (vc4_hwc_window->client_type == comp_type)
2352 return TDM_ERROR_NONE;
2354 vc4_hwc_window->client_type = comp_type;
2355 vc4_output->need_validate = 1;
2357 return TDM_ERROR_NONE;
2362 vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage)
2364 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2365 tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
2367 RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
2368 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2372 return TDM_ERROR_NONE;
2376 vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
2378 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2379 tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
2381 RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
2382 RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
2384 if (!memcmp(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info)))
2385 return TDM_ERROR_NONE;
2387 vc4_hwc_window->info = *info;
2388 vc4_output->need_validate = 1;
2390 return TDM_ERROR_NONE;
2394 vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
2396 tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
2397 tdm_vc4_output_data *vc4_output;
2398 tdm_vc4_data *vc4_data;
2399 tdm_error err = TDM_ERROR_OPERATION_FAILED;
2401 RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, err);
2403 vc4_output = vc4_hwc_window->output_data;
2404 vc4_data = vc4_hwc_window->vc4_data;
2406 RETURN_VAL_IF_FAIL(vc4_output != NULL, err);
2407 RETURN_VAL_IF_FAIL(vc4_data != NULL, err);
2409 if (vc4_hwc_window->surface == surface)
2410 return TDM_ERROR_NONE;
2412 vc4_hwc_window->surface = surface;
2414 return TDM_ERROR_NONE;