void *user_data;
};
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+struct display_properties_ids {
+ uint32_t connector_crtc_id;
+ uint32_t crtc_mode_id;
+ uint32_t crtc_active;
+ uint32_t plane_fb_id;
+ uint32_t plane_crtc_id;
+ uint32_t plane_src_x;
+ uint32_t plane_src_y;
+ uint32_t plane_src_w;
+ uint32_t plane_src_h;
+ uint32_t plane_crtc_x;
+ uint32_t plane_crtc_y;
+ uint32_t plane_crtc_w;
+ uint32_t plane_crtc_h;
+ uint32_t plane_zpos;
+};
+
struct _tdm_vc4_output_data {
struct list_head link;
int crtc_enabled;
unsigned int crtc_fb_id;
+ uint32_t output_plane;
+ struct display_properties_ids props;
+
/* hwc */
int hwc_enable;
tdm_vc4_hwc_data *hwc_data;
return TDM_ERROR_NONE;
}
+static int _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 int _tdm_vc4_display_get_plane_id(int drm_fd, uint32_t crtc_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;
+
+ ressources = drmModeGetResources(drm_fd);
+ if (ressources == NULL) {
+ 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) {
+ goto free_resource;
+ }
+
+ plane_resources = drmModeGetPlaneResources(drm_fd);
+ if (!plane_resources) {
+ 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);
+
+ for (j = 0; j < props->count_props; j++) {
+ drmModePropertyPtr p = drmModeGetProperty(drm_fd, props->props[j]);
+
+ if ((strcmp(p->name, "type") == 0) &&
+ (props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY)) {
+ found_primary = 1;
+ }
+
+ drmModeFreeProperty(p);
+ }
+
+ drmModeFreeObjectProperties(props);
+ }
+
+ drmModeFreePlane(plane);
+ }
+
+ drmModeFreePlaneResources(plane_resources);
+free_resource:
+ drmModeFreeResources(ressources);
+finish:
+ return plane_id;
+}
+
static tdm_error
-_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
+_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data, void *event_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;
- int crtc_w;
+ drmModeAtomicReqPtr request;
+ uint32_t flags = 0;
if (!layer_data->display_buffer_changed && !layer_data->info_changed)
return TDM_ERROR_NONE;
if (_tdm_vc4_display_set_crtc(vc4_data, output_data, 1) != TDM_ERROR_NONE)
return TDM_ERROR_OPERATION_FAILED;
- 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);
- }
+ drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
+ drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
+ output_data->output_plane = _tdm_vc4_display_get_plane_id(vc4_data->drm_fd, output_data->crtc_id);
- 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);
+ _tdm_vc4_display_get_properties(vc4_data->drm_fd, output_data->connector_id,
+ output_data->crtc_id, output_data->output_plane, &output_data->props);
- return TDM_ERROR_NONE;
+ output_data->crtc_enabled = 1;
}
+ 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;
- 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;
- }
+ 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;
- 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);
+ drmModeAtomicCommit(vc4_data->drm_fd, request, flags, event_data);
return TDM_ERROR_NONE;
}
tdm_vc4_data *vc4_data;
tdm_vc4_layer_data *layer_data = NULL;
tdm_error ret;
- int do_waitvblank = 1;
+ int do_waitvblank = 0;
RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
vc4_data = output_data->vc4_data;
+ tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
+ event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
+ event_data->output_data = output_data;
+ event_data->user_data = user_data;
+
#if 0
if (output_data->hwc_enable) {
ret = _tdm_vc4_display_prepare_commit(output_data);
#endif
LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
- ret = _tdm_vc4_display_commit_layer(layer_data);
- if (ret != TDM_ERROR_NONE)
+ ret = _tdm_vc4_display_commit_layer(layer_data, event_data);
+ if (ret != TDM_ERROR_NONE) {
+ free(event_data);
return ret;
+ }
}
if (do_waitvblank == 1) {
- tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
+ event_data = calloc(1, sizeof(tdm_vc4_event_data));
uint target_msc;
if (!event_data) {