vc4_func_hwc.hwc_get_available_properties = vc4_hwc_get_available_properties;
vc4_func_hwc.hwc_get_client_target_buffer_queue = vc4_hwc_get_client_target_buffer_queue;
vc4_func_hwc.hwc_set_client_target_buffer = vc4_hwc_set_client_target_buffer;
+ vc4_func_hwc.hwc_set_client_target_acquire_fence = vc4_hwc_set_client_target_acquire_fence;
vc4_func_hwc.hwc_validate = vc4_hwc_validate;
vc4_func_hwc.hwc_get_changed_composition_types = vc4_hwc_get_changed_composition_types;
vc4_func_hwc.hwc_accept_validation = vc4_hwc_accept_validation;
vc4_func_hwc.hwc_commit = vc4_hwc_commit;
vc4_func_hwc.hwc_set_commit_handler = vc4_hwc_set_commit_handler;
+ vc4_func_hwc.hwc_get_commit_fence = vc4_hwc_get_commit_fence;
+ vc4_func_hwc.hwc_get_release_fences = vc4_hwc_get_release_fences;
memset(&vc4_func_hwc_window, 0, sizeof(vc4_func_hwc_window));
vc4_func_hwc_window.hwc_window_destroy = vc4_hwc_window_destroy;
vc4_func_hwc_window.hwc_window_get_constraints = vc4_hwc_window_get_constraints;
vc4_func_hwc_window.hwc_window_set_name = vc4_hwc_window_set_name;
vc4_func_hwc_window.hwc_window_set_cursor_image = vc4_hwc_window_set_cursor_image;
+ vc4_func_hwc_window.hwc_window_set_acquire_fence = vc4_hwc_window_set_acquire_fence;
}
memset(&vc4_func_layer, 0, sizeof(vc4_func_layer));
tdm_error vc4_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count);
tbm_surface_queue_h vc4_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error);
tdm_error vc4_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage);
+tdm_error vc4_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence);
tdm_error vc4_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types);
tdm_error vc4_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types);
tdm_error vc4_hwc_accept_validation(tdm_hwc *hwc);
tdm_error vc4_hwc_commit(tdm_hwc *hwc, int sync, void *user_data);
tdm_error vc4_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func);
+tdm_error vc4_hwc_get_commit_fence(tdm_hwc *hwc, int *fence);
+tdm_error vc4_hwc_get_release_fences(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_window, int *fences);
void vc4_hwc_window_destroy(tdm_hwc_window *hwc_window);
tdm_error vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type);
tdm_error vc4_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints);
tdm_error vc4_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name);
tdm_error vc4_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr);
+tdm_error vc4_hwc_window_set_acquire_fence(tdm_hwc_window *hwc_window, int acquire_fence);
tdm_error vc4_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
tdm_error vc4_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value);
tdm_error vc4_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
tdm_error vc4_layer_unset_buffer(tdm_layer *layer);
tdm_error vc4_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags);
+tdm_error vc4_layer_set_acquire_fence(tdm_layer *layer, int acquire_fence);
uint32_t tdm_vc4_format_to_drm_format(tbm_format format);
tbm_format tdm_vc4_format_to_tbm_format(uint32_t format);
layer_data->vc4_data = vc4_data;
layer_data->output_data = output_data;
layer_data->plane_id = vc4_data->plane_res->planes[i];
+ layer_data->acquire_fence = -1;
layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
TDM_LAYER_CAPABILITY_GRAPHIC;
layer_data->vc4_data = vc4_data;
layer_data->output_data = output_data;
layer_data->plane_id = vc4_data->plane_res->planes[i];
+ layer_data->acquire_fence = -1;
if (type == DRM_PLANE_TYPE_CURSOR) {
layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
free(layer_data);
goto failed_atomic_prop_id;
}
+
+ ret = _vc4_output_get_atomic_prop_id(vc4_data->drm_fd, layer_data->plane_id,
+ DRM_MODE_OBJECT_PLANE, "IN_FENCE_FD", &layer_data->atomic_props_ids.in_fence_fd);
+ if (ret != TDM_ERROR_NONE) {
+ free(layer_data);
+ goto failed_atomic_prop_id;
+ }
}
drmModeFreePlane(plane);
output_data->pipe = c;
output_data->connector_type = connector->connector_type;
output_data->connector_type_id = connector->connector_type_id;
+ output_data->commit_fence = -1;
if (connector->connection == DRM_MODE_CONNECTED)
output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
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, "OUT_FENCE_PTR", &output_data->atomic_props_ids.out_fence_ptr);
+ if (ret != TDM_ERROR_NONE)
+ goto failed_atomic_prop_id;
}
}
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)
+ uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h, int acquire_fence)
{
tdm_error ret = TDM_ERROR_NONE;
return TDM_ERROR_OPERATION_FAILED;
}
+ ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.in_fence_fd, acquire_fence);
+ if (ret < 0) {
+ TDM_ERR("fail to add the atomic prop. acquire_fence(%d)", acquire_fence);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
return TDM_ERROR_NONE;
}
TDM_INFO("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);
+ ret = _vc4_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1);
if (ret != TDM_ERROR_NONE) {
TDM_ERR("_vc4_layer_add_atomic_properties failed.");
return ret;
layer_data->display_buffer->fb_id, output_data->crtc_id,
fx, fy, fw, fh,
new_dst_x, layer_info.dst_pos.y,
- new_dst_w, layer_info.dst_pos.h);
+ new_dst_w, layer_info.dst_pos.h, layer_data->acquire_fence);
if (ret != TDM_ERROR_NONE) {
TDM_ERR("MakeAtomicRequest failed");
return ret;
drmModeAtomicReqPtr request;
uint32_t flags = 0;
tdm_error ret;
+ int out_fence_fd = -1;
RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
+ ret = drmModeAtomicAddProperty(request, output_data->crtc_id, output_data->atomic_props_ids.out_fence_ptr, (uint32_t)&out_fence_fd);
+ if (ret < 0) {
+ TDM_ERR("fail to out fence ptr error:%d", errno);
+ return ret;
+ }
+
LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
ret = _vc4_layer_make_atomic_request(layer_data, request);
if (ret != TDM_ERROR_NONE) {
return TDM_ERROR_OPERATION_FAILED;
}
+ if (output_data->commit_fence >= 0)
+ close(output_data->commit_fence);
+
+ output_data->commit_fence = out_fence_fd;
+
drmModeAtomicFree(request);
return TDM_ERROR_NONE;
return TDM_ERROR_NONE;
}
+
+tdm_error
+vc4_layer_set_acquire_fence(tdm_layer *layer, int acquire_fence)
+{
+ tdm_vc4_layer_data *layer_data = layer;
+
+ RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
+
+ TDM_DBG("layer[%p]zpos[%d] acquire_fence:%d", layer, layer_data->zpos, acquire_fence);
+
+ if (layer_data->acquire_fence != acquire_fence)
+ layer_data->acquire_fence = acquire_fence;
+
+ return TDM_ERROR_NONE;
+}
if (layer_data->display_buffer)
ret = vc4_layer_unset_buffer(layer_data);
RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+ if (layer_data->acquire_fence >= 0)
+ ret = vc4_layer_set_acquire_fence(layer_data, -1);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
} else {
ret = vc4_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
ret = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ ret = vc4_layer_set_acquire_fence(layer_data, hwc_window_data->acquire_fence);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
}
return ret;
hwc_window_data = _vc4_hwc_create_window(hwc_data, NULL, error);
RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
+ hwc_window_data->acquire_fence = -1;
+
LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
TDM_DBG("hwc_window(%p) create", hwc_window_data);
*capabilities |= TDM_HWC_CAPABILITY_VIDEO_SCALE;
+ /* temporary enable/disable */
+ char *env;
+
+ env = getenv("TDM_HWC_FENCE");
+ if (env) {
+ if (atoi(env))
+ *capabilities |= TDM_HWC_CAPABILITY_FENCE;
+ }
+ /* temporary enable/disable */
+
return TDM_ERROR_NONE;
}
}
tdm_error
+vc4_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence)
+{
+ tdm_vc4_hwc_data *hwc_data = hwc;
+ tdm_error err;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
+
+ err = vc4_hwc_window_set_acquire_fence(hwc_data->target_hwc_window, acquire_fence);
+ RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
vc4_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
{
tdm_vc4_hwc_data *hwc_data = hwc;
}
tdm_error
+vc4_hwc_get_commit_fence(tdm_hwc *hwc, int *commit_fence)
+{
+ tdm_vc4_hwc_data *hwc_data = hwc;
+ tdm_vc4_output_data *output_data;
+
+ RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(commit_fence, TDM_ERROR_INVALID_PARAMETER);
+
+ output_data = hwc_data->output_data;
+ RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+ *commit_fence = dup(output_data->commit_fence);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_get_release_fences(tdm_hwc *hwc, uint32_t *num_elements,
+ tdm_hwc_window **hwc_wnds, int *fences)
+{
+ tdm_vc4_hwc_data *hwc_data = hwc;
+ tdm_vc4_output_data *output_data;
+ tdm_vc4_hwc_window_data *hwc_window_data = NULL;
+ int num = 0;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ output_data = hwc_data->output_data;
+ RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+ LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+ if ((hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_DEVICE) &&
+ (hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_VIDEO))
+ continue;
+
+ if (hwc_wnds && fences) {
+ fences[num] = dup(output_data->commit_fence);
+ hwc_wnds[num] = hwc_window_data;
+ }
+
+ num++;
+ }
+
+ *num_elements = num;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
vc4_hwc_target_window_set_info(tdm_vc4_hwc_data *hwc_data, int width, int height)
{
tdm_hwc_window_info info = {0};
return TDM_ERROR_NONE;
}
+
+tdm_error
+vc4_hwc_window_set_acquire_fence(tdm_hwc_window *hwc_window, int acquire_fence)
+{
+ tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+
+ RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (hwc_window_data->acquire_fence >= 0) {
+ close(hwc_window_data->acquire_fence);
+ hwc_window_data->acquire_fence = -1;
+ }
+
+ if (acquire_fence >= 0)
+ hwc_window_data->acquire_fence = dup(acquire_fence);
+
+ return TDM_ERROR_NONE;
+}
uint32_t crtc_id;
uint32_t crtc_mode_id;
uint32_t crtc_active;
+ uint32_t out_fence_ptr;
} atomic_props_ids;
/* mirroring output_data, only one support */
tdm_vc4_output_data *mirror_dst_output_data;
tdm_transform mirror_dst_transform;
tdm_vc4_output_data *mirror_src_output_data;
+
+ int commit_fence;
};
struct _tdm_vc4_layer_data {
uint32_t crtc_w;
uint32_t crtc_h;
uint32_t zpos;
+ uint32_t in_fence_fd;
} atomic_props_ids;
+
+ int acquire_fence;
};
struct _tdm_vc4_hwc_data {
tdm_hwc_commit_handler commit_func;
};
+
struct _tdm_vc4_hwc_window_data {
struct list_head link;
} cursor_img;
int cursor_img_surface;
int cursor_img_refresh;
+
+ int acquire_fence;
};
#endif /* _TDM_VC4_TYPES_H_ */