manage the multiple layers to set the atomic properties. 53/199453/2
authorSooChan Lim <sc1.lim@samsung.com>
Mon, 11 Feb 2019 12:02:49 +0000 (21:02 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 11 Feb 2019 12:44:44 +0000 (21:44 +0900)
add the atomic properties to the layers which have the change
of the buffers and the change of the infos

Change-Id: I641593972dc1010e177b9cc3893d80a5199a088f

src/tdm_vc4.c
src/tdm_vc4_display.c
src/tdm_vc4_types.h

index 9814812..83efda0 100644 (file)
@@ -382,6 +382,13 @@ tdm_vc4_init(tdm_display *dpy, tdm_error *error)
                TDM_INFO("has universal planes");
                vc4_data->has_universal_plane = 1;
        }
+
+       if (drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) {
+               TDM_WRN("Set DRM_CLIENT_CAP_ATOMIC failed");
+       } else {
+               TDM_INFO("has atomic");
+               vc4_data->has_atomic = 1;
+       }
 #endif
 
        vc4_data->mode_res = drmModeGetResources(vc4_data->drm_fd);
index 0c6d669..5418bbf 100644 (file)
@@ -18,6 +18,73 @@ static int tdm_vc4_buffer_key;
                (__after)->next->prev = (__item); \
                (__after)->next = (__item);
 
+static tdm_error
+check_hw_restriction(unsigned int crtc_w, unsigned int crtc_h, unsigned int buf_w,
+                                               unsigned int src_x, unsigned int src_w,
+                                               unsigned int dst_x, unsigned int dst_y, unsigned int dst_w,
+                                               unsigned int *new_src_x, unsigned int *new_src_w,
+                                               unsigned int *new_dst_x, unsigned int *new_dst_w)
+{
+       int start, end, diff;
+       int virtual_screen;
+
+       *new_src_x = src_x;
+       *new_src_w = src_w;
+       *new_dst_x = dst_x;
+       *new_dst_w = dst_w;
+
+       if (buf_w < MIN_WIDTH || buf_w % 2) {
+               TDM_ERR("buf_w(%u) not 2's multiple or less than %u", buf_w, MIN_WIDTH);
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       if (dst_x > crtc_w || dst_y > crtc_h) {
+               TDM_ERR("dst_pos(%u,%u) is out of crtc(%ux%u)", dst_x, dst_y, crtc_w, crtc_h);
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       if (src_x > dst_x || ((dst_x - src_x) + buf_w) > crtc_w)
+               virtual_screen = 1;
+       else
+               virtual_screen = 0;
+
+       start = dst_x;
+       end = ((dst_x + dst_w) > crtc_w) ? crtc_w : (dst_x + dst_w);
+
+       /* check window minimun width */
+       if ((end - start) < MIN_WIDTH) {
+               TDM_ERR("visible_w(%d) less than %u", end - start, MIN_WIDTH);
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       if (!virtual_screen) {
+               /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
+               if ((end - start) % 2)
+                       end--;
+       } else {
+               /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
+               if (end % 2)
+                       end--;
+       }
+
+       *new_dst_x = start;
+       *new_dst_w = end - start;
+       *new_src_w = *new_dst_w;
+       diff = start - dst_x;
+       *new_src_x += diff;
+
+       RETURN_VAL_IF_FAIL(*new_src_w > 0, TDM_ERROR_BAD_REQUEST);
+       RETURN_VAL_IF_FAIL(*new_dst_w > 0, TDM_ERROR_BAD_REQUEST);
+
+       if (src_x != *new_src_x || src_w != *new_src_w || dst_x != *new_dst_x ||
+           dst_w != *new_dst_w)
+               TDM_DBG("=> buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)",
+                               buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start,
+                               end);
+
+       return TDM_ERROR_NONE;
+}
+
 static void
 _tdm_vc4_display_buffer_destroy(void *user_data)
 {
@@ -113,6 +180,7 @@ _tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data)
 
        for (i = 0; i < output_data->count_drm_modes; i++) {
                drmModeModeInfoPtr vc4_mode = &output_data->vc4_modes[i];
+
                if ((vc4_mode->hdisplay == output_data->current_mode->hdisplay) &&
                        (vc4_mode->vdisplay == output_data->current_mode->vdisplay) &&
                        (vc4_mode->vrefresh == output_data->current_mode->vrefresh) &&
@@ -337,170 +405,14 @@ _tdm_vc4_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
        return TDM_ERROR_NONE;
 }
 
+#if 0
 static tdm_error
-_tdm_vc4_display_get_properties(int drm_fd, uint32_t connector_id, uint32_t crtc_id,
-                                       uint32_t plane_id, struct display_properties_ids *ids)
-{
-       drmModeObjectPropertiesPtr properties = NULL;
-       drmModePropertyPtr property = NULL;
-       int i, j;
-       tdm_error ret = TDM_ERROR_NONE;
-       struct {
-               uint32_t object_type;
-               uint32_t object_id;
-               char *name;
-               uint32_t *value;
-       } glue[] = {
-               { DRM_MODE_OBJECT_CONNECTOR, connector_id, "CRTC_ID", &ids->connector_crtc_id },
-               { DRM_MODE_OBJECT_CRTC, crtc_id, "MODE_ID", &ids->crtc_mode_id },
-               { DRM_MODE_OBJECT_CRTC, crtc_id, "ACTIVE", &ids->crtc_active },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "FB_ID", &ids->plane_fb_id },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_ID", &ids->plane_crtc_id },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_X", &ids->plane_src_x },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_Y", &ids->plane_src_y },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_W", &ids->plane_src_w },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_H", &ids->plane_src_h },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_X", &ids->plane_crtc_x },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_Y", &ids->plane_crtc_y },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_W", &ids->plane_crtc_w },
-               { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_H", &ids->plane_crtc_h },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(glue); i++) {
-               properties = drmModeObjectGetProperties(drm_fd,
-                                                       glue[i].object_id,
-                                                       glue[i].object_type);
-
-               if (properties == NULL) {
-                       ret = TDM_ERROR_OPERATION_FAILED;
-                       goto finish;
-               }
-
-               for (j = 0; j < properties->count_props; j++) {
-                       property = drmModeGetProperty(drm_fd, properties->props[j]);
-                       if (property == NULL) {
-                               continue;
-                       }
-
-                       if (strcmp(property->name, glue[i].name) == 0) {
-                               *glue[i].value = property->prop_id;
-                               drmModeFreeProperty(property);
-                               break;
-                       }
-                       drmModeFreeProperty(property);
-               }
-
-               if (j == properties->count_props) {
-                       ret = TDM_ERROR_OPERATION_FAILED;
-                       goto finish;
-               }
-
-               drmModeFreeObjectProperties(properties);
-               properties = NULL;
-       }
-
-finish:
-       if (properties != NULL)
-               drmModeFreeObjectProperties(properties);
-
-       return ret;
-}
-
-static tdm_error
-_tdm_vc4_display_get_plane_id(int drm_fd, uint32_t crtc_id, uint32_t *id)
-{
-       drmModeResPtr ressources = NULL;
-       drmModePlaneResPtr plane_resources;
-       uint32_t crtc_index = 0;
-       uint32_t plane_id = 0;
-       uint32_t found_primary = 0;
-       int i, j;
-       tdm_error ret = TDM_ERROR_NONE;
-
-       if (id) *id = 0;
-
-       ressources = drmModeGetResources(drm_fd);
-       if (ressources == NULL) {
-               ret = TDM_ERROR_OPERATION_FAILED;
-               goto finish;
-       }
-
-       for (i = 0; i < ressources->count_crtcs; i++) {
-               if (ressources->crtcs[i] == crtc_id) {
-                       crtc_index = i;
-                       break;
-               }
-       }
-
-       if (i == ressources->count_crtcs) {
-               ret = TDM_ERROR_OPERATION_FAILED;
-               goto free_resource;
-       }
-
-       plane_resources = drmModeGetPlaneResources(drm_fd);
-       if (!plane_resources) {
-               ret = TDM_ERROR_OPERATION_FAILED;
-               goto free_resource;
-       }
-
-       for (i = 0; (i < plane_resources->count_planes) && !found_primary; i++) {
-               plane_id = plane_resources->planes[i];
-               drmModePlanePtr plane = drmModeGetPlane(drm_fd, plane_id);
-               if (!plane) {
-                       continue;
-               }
-
-               if (plane->possible_crtcs & (1 << crtc_index)) {
-                       drmModeObjectPropertiesPtr props =
-                               drmModeObjectGetProperties(drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
-                       if (!props) {
-                               ret = TDM_ERROR_OPERATION_FAILED;
-                               goto free_resource;
-                       }
-
-                       for (j = 0; j < props->count_props; j++) {
-                               drmModePropertyPtr p = drmModeGetProperty(drm_fd, props->props[j]);
-
-                               if (!p)
-                                       continue;
-
-                               if ((strcmp(p->name, "type") == 0) &&
-                                               (props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY)) {
-                                       found_primary = 1;
-                               }
-
-                               drmModeFreeProperty(p);
-                       }
-
-                       drmModeFreeObjectProperties(props);
-               }
-
-               drmModeFreePlane(plane);
-       }
-
-       if (found_primary) {
-               if (id)
-                       *id = plane_id;
-       } else {
-               ret = TDM_ERROR_OPERATION_FAILED;
-       }
-
-       drmModeFreePlaneResources(plane_resources);
-free_resource:
-       drmModeFreeResources(ressources);
-finish:
-       return ret;
-}
-
-static tdm_error
-_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data, void *event_data)
+_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
 {
        tdm_vc4_data *vc4_data = layer_data->vc4_data;
        tdm_vc4_output_data *output_data = layer_data->output_data;
        uint32_t fx, fy, fw, fh;
-       drmModeAtomicReqPtr request;
-       uint32_t flags =  0;
-       tdm_error ret = TDM_ERROR_NONE;
+       int crtc_w;
 
        if (!layer_data->display_buffer_changed && !layer_data->info_changed)
                return TDM_ERROR_NONE;
@@ -509,46 +421,63 @@ _tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data, void *event_data)
                if (_tdm_vc4_display_set_crtc(vc4_data, output_data, 1) != TDM_ERROR_NONE)
                        return TDM_ERROR_OPERATION_FAILED;
 
-               drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
-               drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+               output_data->crtc_enabled = 1;
+       }
+
+       if (output_data->current_mode)
+               crtc_w = output_data->current_mode->hdisplay;
+       else {
+               drmModeCrtcPtr crtc = drmModeGetCrtc(vc4_data->drm_fd, output_data->crtc_id);
+               if (!crtc) {
+                       TDM_ERR("getting crtc failed");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+               crtc_w = crtc->width;
+               if (crtc_w == 0) {
+                       TDM_ERR("getting crtc width failed");
+                       drmModeFreeCrtc(crtc);
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+               drmModeFreeCrtc(crtc);
+       }
 
-               ret = _tdm_vc4_display_get_plane_id(vc4_data->drm_fd, output_data->crtc_id, &output_data->output_plane);
-               if (ret != TDM_ERROR_NONE) return ret;
+       layer_data->display_buffer_changed = 0;
+       layer_data->info_changed = 0;
 
-               ret = _tdm_vc4_display_get_properties(vc4_data->drm_fd, output_data->connector_id,
-                                                       output_data->crtc_id, output_data->output_plane, &output_data->props);
-               if (ret != TDM_ERROR_NONE) return ret;
+       if (!layer_data->display_buffer) {
+               if (drmModeSetPlane(vc4_data->drm_fd, layer_data->plane_id,
+                                                       output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
+                       TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
 
-               output_data->crtc_enabled = 1;
+               return TDM_ERROR_NONE;
        }
 
-       flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
-       request = drmModeAtomicAlloc();
-
        /* Source values are 16.16 fixed point */
        fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
        fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
        fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
        fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
 
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_fb_id, layer_data->display_buffer->fb_id);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_id, output_data->crtc_id);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_x, fx);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_y, fy);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_w, fw);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_h, fh);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_x, layer_data->info.src_config.pos.x);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_y, layer_data->info.src_config.pos.y);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_w, layer_data->info.src_config.pos.w);
-       drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_h, layer_data->info.src_config.pos.h);
-
-       layer_data->display_buffer_changed = 0;
-       layer_data->info_changed = 0;
+       if (drmModeSetPlane(vc4_data->drm_fd, layer_data->plane_id,
+                                               output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
+                                               layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
+                                               layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
+                                               fx, fy, fw, fh) < 0) {
+               TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
 
-       drmModeAtomicCommit(vc4_data->drm_fd, request, flags, event_data);
+       TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
+                       layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
+                       layer_data->display_buffer->fb_id,
+                       layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
+                       layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
+                       layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
+                       layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
 
        return TDM_ERROR_NONE;
 }
+#endif
 
 static void
 _tdm_vc4_display_cb_event(int fd, unsigned int sequence,
@@ -604,6 +533,38 @@ _tdm_vc4_display_cb_event(int fd, unsigned int sequence,
 }
 
 static tdm_error
+_vc4_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
+{
+       drmModeObjectPropertiesPtr properties = NULL;
+       drmModePropertyPtr property = NULL;
+       int i;
+
+       properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
+       if (properties == NULL) {
+               TDM_ERR("drmModeObjectGetProperties failed");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       for (i = 0; i < properties->count_props; i++) {
+               property = drmModeGetProperty(drm_fd, properties->props[i]);
+               if (property == NULL) {
+                       continue;
+               }
+
+               if (strcmp(property->name, name) == 0) {
+                       *id = property->prop_id;
+                       drmModeFreeProperty(property);
+                       break;
+               }
+               drmModeFreeProperty(property);
+       }
+
+       drmModeFreeObjectProperties(properties);
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
 _tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data)
 {
        tdm_vc4_output_data *output_data = NULL;
@@ -856,6 +817,50 @@ _tdm_vc4_display_create_layer_list_type(tdm_vc4_data *vc4_data)
                                 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
                                 layer_data->zpos, layer_data->capabilities);
 
+               /* get the atomic prop ids*/
+               if (vc4_data->has_atomic) {
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+                       ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
+                       if (ret != TDM_ERROR_NONE)
+                               goto failed_atomic_prop_id;
+               }
+
                LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
        }
 
@@ -868,6 +873,7 @@ _tdm_vc4_display_create_layer_list_type(tdm_vc4_data *vc4_data)
 
        return TDM_ERROR_NONE;
 
+failed_atomic_prop_id:
 failed:
        if (planes) {
                for (i = 0; i < vc4_data->plane_res->count_planes; i++)
@@ -1190,9 +1196,28 @@ tdm_vc4_display_create_output_list(tdm_vc4_data *vc4_data)
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
 
+       /* get the atomic prop ids*/
+       if (vc4_data->has_atomic) {
+               ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, output_data->connector_id,
+                                       DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_atomic_prop_id;
+
+               ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, output_data->crtc_id,
+                                       DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_atomic_prop_id;
+
+               ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, output_data->crtc_id,
+                                       DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_atomic_prop_id;
+       }
+
        TDM_DBG("output count: %d", vc4_data->mode_res->count_connectors);
 
        return TDM_ERROR_NONE;
+failed_atomic_prop_id:
 failed_create:
        tdm_vc4_display_destroy_output_list(vc4_data);
        return ret;
@@ -1591,34 +1616,284 @@ vc4_output_set_vblank_handler(tdm_output *output,
        return TDM_ERROR_NONE;
 }
 
+static tdm_error
+_vc4_layer_add_atomic_properties(tdm_vc4_layer_data *layer_data, drmModeAtomicReqPtr request,
+                       uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
+                       uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h)
+{
+       tdm_error ret = TDM_ERROR_NONE;
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_x(%u)", src_x);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_y(%u)", src_y);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_w(%u)", src_w);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_h(%u)", src_h);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
+_vc4_layer_make_atomic_request(tdm_vc4_layer_data *layer_data, drmModeAtomicReqPtr request)
+{
+       tdm_vc4_data *vc4_data = layer_data->vc4_data;
+       tdm_vc4_output_data *output_data = layer_data->output_data;
+       unsigned int new_src_x, new_src_w;
+       unsigned int new_dst_x, new_dst_w;
+       uint32_t fx, fy, fw, fh;
+       int crtc_w, crtc_h;
+       tdm_info_layer layer_info = layer_data->info;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       if (!layer_data->display_buffer_changed && !layer_data->info_changed)
+               return TDM_ERROR_NONE;
+
+       if (output_data->current_mode) {
+               crtc_w = output_data->current_mode->hdisplay;
+               crtc_h = output_data->current_mode->vdisplay;
+       } else {
+               drmModeCrtcPtr crtc = drmModeGetCrtc(vc4_data->drm_fd, output_data->crtc_id);
+               if (!crtc) {
+                       TDM_ERR("getting crtc failed");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+               crtc_w = crtc->width;
+               crtc_h = crtc->height;
+               if (crtc_w == 0) {
+                       TDM_ERR("getting crtc width failed");
+                       drmModeFreeCrtc(crtc);
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+               drmModeFreeCrtc(crtc);
+       }
+
+       layer_data->display_buffer_changed = 0;
+       layer_data->info_changed = 0;
+
+       if (!layer_data->display_buffer) {
+               TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
+                               vc4_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
+
+               ret = _vc4_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("_vc4_layer_add_atomic_properties failed.");
+                       return ret;
+               }
+
+               return TDM_ERROR_NONE;
+       }
+
+       /* check hw restriction*/
+       if (check_hw_restriction(crtc_w, crtc_h, layer_data->display_buffer->width,
+                                                        layer_info.src_config.pos.x,
+                                                        layer_info.src_config.pos.w,
+                                                        layer_info.dst_pos.x,
+                                                        layer_info.dst_pos.y,
+                                                        layer_info.dst_pos.w,
+                                                        &new_src_x, &new_src_w, &new_dst_x, &new_dst_w) != TDM_ERROR_NONE) {
+               TDM_WRN("not going to set plane(%u)", layer_data->plane_id);
+               return TDM_ERROR_NONE;
+       }
+
+       if (layer_info.src_config.pos.x != new_src_x)
+               TDM_DBG("src_x changed: %u => %u", layer_info.src_config.pos.x, new_src_x);
+       if (layer_info.src_config.pos.w != new_src_w)
+               TDM_DBG("src_w changed: %u => %u", layer_info.src_config.pos.w, new_src_w);
+       if (layer_info.dst_pos.x != new_dst_x)
+               TDM_DBG("dst_x changed: %u => %u", layer_info.dst_pos.x, new_dst_x);
+       if (layer_info.dst_pos.w != new_dst_w)
+               TDM_DBG("dst_w changed: %u => %u", layer_info.dst_pos.w, new_dst_w);
+
+       /* Source values are 16.16 fixed point */
+       fx = ((unsigned int)new_src_x) << 16;
+       fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
+       fw = ((unsigned int)new_src_w) << 16;
+       fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
+
+       TDM_INFO("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)",
+                       vc4_data->drm_fd, layer_data->plane_id, layer_data->zpos,
+                       output_data->crtc_id, layer_data->display_buffer->fb_id,
+                       new_src_x, layer_info.src_config.pos.y,
+                       new_src_w, layer_info.src_config.pos.h,
+                       layer_info.dst_pos.x, layer_info.dst_pos.y,
+                       layer_info.dst_pos.w, layer_info.dst_pos.h);
+
+       ret = _vc4_layer_add_atomic_properties(layer_data, request,
+                                               layer_data->display_buffer->fb_id, output_data->crtc_id,
+                                               fx, fy, fw, fh,
+                                               layer_data->info.src_config.pos.x,
+                                               layer_data->info.src_config.pos.y,
+                                               layer_data->info.src_config.pos.w,
+                                               layer_data->info.src_config.pos.h);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("MakeAtomicRequest failed: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u) failed: %m",
+                               vc4_data->drm_fd, layer_data->plane_id, layer_data->zpos,
+                               output_data->crtc_id, layer_data->display_buffer->fb_id,
+                               new_src_x, layer_info.src_config.pos.y,
+                               new_src_w, layer_info.src_config.pos.h,
+                               layer_info.dst_pos.x, layer_info.dst_pos.y,
+                               layer_info.dst_pos.w, layer_info.dst_pos.h);
+               return ret;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
 tdm_error
 vc4_output_commit(tdm_output *output, int sync, void *user_data)
 {
        tdm_vc4_output_data *output_data = output;
        tdm_vc4_layer_data *layer_data = NULL;
+       tdm_vc4_event_data *event_data;
+       drmModeAtomicReqPtr request;
+       uint32_t flags =  0;
        tdm_error ret;
 
        RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
 
-       tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
-       RETURN_VAL_IF_FAIL(event_data, TDM_ERROR_OUT_OF_MEMORY);
+       if (!output_data->crtc_enabled || output_data->mode_changed) {
+               ret = _tdm_vc4_display_set_crtc(output_data->vc4_data, output_data, 1);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("fail to set crtc.");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
 
-       event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
-       event_data->output_data = output_data;
-       event_data->user_data = user_data;
+               output_data->crtc_enabled = 1;
+#if 0//TODO: do set crtc with atomic pageflip
+               flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
+               drmModeModeInfoPtr mode;
+               uint32_t blob_id;
+
+               mode = _tdm_vc4_display_get_mode(output_data);
+               if (!mode) {
+                       TDM_ERR("fail to find the drm mode.");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               if (drmModeCreatePropertyBlob(output_data->vc4_data->drm_fd, mode, sizeof(*mode), &blob_id) != 0) {
+                       TDM_ERR("fail to create the Mode PropertyBlob.");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_fb_id,
+                               layer_data->display_buffer->fb_id);
+
+               output_data->crtc_enabled = 1;
+#endif
+       }
+
+       request = drmModeAtomicAlloc();
+       if (!request) {
+               TDM_ERR("drmModeAtomicAlloc failed.");
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
 
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
-               ret = _tdm_vc4_display_commit_layer(layer_data, event_data);
+               ret = _vc4_layer_make_atomic_request(layer_data, request);
                if (ret != TDM_ERROR_NONE) {
-                       free(event_data);
+                       TDM_ERR("_vc4_layer_make_atomic_request failed.");
+                       drmModeAtomicFree(request);
                        return ret;
                }
        }
 
+       event_data = calloc(1, sizeof(tdm_vc4_event_data));
+       if (!event_data) {
+               TDM_ERR("fail to alloc event_data.");
+               drmModeAtomicFree(request);
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
+       event_data->output_data = output_data;
+       event_data->user_data = user_data;
+
+       if (drmModeAtomicCommit(output_data->vc4_data->drm_fd, request, flags, event_data) < 0) {
+               TDM_ERR("drmModeAtomicCommit failed.");
+               drmModeAtomicFree(request);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       drmModeAtomicFree(request);
+
 #if 0
        tdm_vc4_data *vc4_data;
-       int do_waitvblank = 0;
        vc4_data = output_data->vc4_data;
+       int do_waitvblank = 0;
+
+       event_data = calloc(1, sizeof(tdm_vc4_event_data));
+       if (!event_data) {
+               TDM_ERR("fail to alloc event_data.");
+               drmModeAtomicFree(request);
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
+       event_data->output_data = output_data;
+       event_data->user_data = user_data;
+
+       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+               ret = _tdm_vc4_display_commit_layer(layer_data);
+               if (ret != TDM_ERROR_NONE) {
+                       free(event_data);
+                       return ret;
+               }
+       }
 
        if (do_waitvblank == 1) {
                event_data = calloc(1, sizeof(tdm_vc4_event_data));
index 2585dd1..d3d71c2 100644 (file)
@@ -93,6 +93,7 @@ struct _tdm_vc4_data {
 
 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4  && LIBDRM_MICRO_VERSION >= 47
        int has_universal_plane;
+       int has_atomic;
 #endif
 
 #if HAVE_UDEV
@@ -179,6 +180,13 @@ struct _tdm_vc4_output_data {
        /* hwc */
        int hwc_enable;
        tdm_vc4_hwc_data *hwc_data;
+
+       /* atomic prop ids*/
+       struct {
+               uint32_t crtc_id;
+               uint32_t crtc_mode_id;
+               uint32_t crtc_active;
+       } atomic_props_ids;
 };
 
 struct _tdm_vc4_layer_data {
@@ -197,6 +205,21 @@ struct _tdm_vc4_layer_data {
 
        tdm_vc4_display_buffer *display_buffer;
        int display_buffer_changed;
+
+       /* atomic prop ids*/
+       struct {
+               uint32_t fb_id;
+               uint32_t crtc_id;
+               uint32_t src_x;
+               uint32_t src_y;
+               uint32_t src_w;
+               uint32_t src_h;
+               uint32_t crtc_x;
+               uint32_t crtc_y;
+               uint32_t crtc_w;
+               uint32_t crtc_h;
+               uint32_t zpos;
+       } atomic_props_ids;
 };
 
 struct _tdm_vc4_hwc_data {