continue;
if (hw->assigned_layer_zpos == layer_zpos &&
- hw->validated_type == TDM_COMPOSITION_DEVICE)
+ (hw->validated_type == TDM_COMPOSITION_DEVICE || hw->is_device_to_client_transition))
return hw;
}
return NULL;
}
+static void
+_update_layers_info(tdm_exynos_output_data *output_data)
+{
+ tdm_exynos_layer_data *layer = NULL;
+ tdm_exynos_hwc_window_data *hw;
+ int primary_layer_zpos = _get_primary_layer_zpos(output_data);
+ tdm_error ret;
+
+ LIST_FOR_EACH_ENTRY(layer, &output_data->layer_list, link) {
+ if (output_data->need_target_window && layer->zpos == primary_layer_zpos)
+ hw = output_data->target_hwc_window;
+ else
+ hw = _find_maped_hwc_window_to_layer(&output_data->hwc_window_list, layer->zpos);
+
+ if (hw) {
+ ret = exynos_layer_set_info((tdm_layer *)layer,
+ (tdm_info_layer *)&(hw->info));
+ if (ret != TDM_ERROR_NONE)
+ TDM_ERR("cannot set info to layer with %d zpos", layer->zpos);
+ }
+ }
+}
+
+static int
+_is_device_to_client_transition_finished(struct list_head *hwc_wnds)
+{
+ tdm_exynos_hwc_window_data *hw = NULL;
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (hw->is_device_to_client_transition)
+ goto work;
+ }
+
+ TDM_INFO("no device to client transition.");
+
+ /* if there wasn't the device to client transition there's no
+ * the device to client transition end :) */
+ return 0;
+
+work:
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (hw->is_device_to_client_transition && !hw->present_on_target_wnd)
+ return 0;
+ }
+
+ return 1;
+}
+
static tdm_error
_tdm_exynos_display_prepare_commit(tdm_exynos_output_data *output_data) {
tdm_exynos_layer_data *layer = NULL;
- tdm_exynos_hwc_window_data *hw;
+ tdm_exynos_hwc_window_data *hw = NULL;
int primary_layer_zpos = _get_primary_layer_zpos(output_data);
+ int device_to_client_transition_finished;
RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
_set_hwc_window_buffer_to_layer(layer, output_data->video_hwc_window);
}
+ device_to_client_transition_finished =
+ _is_device_to_client_transition_finished(&output_data->hwc_window_list);
+
+ if (device_to_client_transition_finished) {
+ LIST_FOR_EACH_ENTRY(hw, &output_data->hwc_window_list, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (hw->is_device_to_client_transition)
+ hw->surface = NULL; /* to unset layers */
+ }
+
+ TDM_INFO("the device to client transition has finished, need_target_wnd:%d",
+ output_data->need_target_window);
+
+ /* if at the moment tdm-backend found a device to client transition
+ * the target_wnd was turned off, we'll skip one frame for target_buffer
+ * without the next lines */
+ if (!output_data->need_target_window) {
+ output_data->need_target_window = 1;
+
+ layer = _exynos_output_get_layer(output_data, primary_layer_zpos);
+ _set_hwc_window_buffer_to_layer(layer, output_data->target_hwc_window);
+
+ /* preempt the hwc_wnd which was mapped to the primary layer */
+ hw = _find_maped_hwc_window_to_layer(&output_data->hwc_window_list, primary_layer_zpos);
+ hw->assigned_layer_zpos = -1;
+ hw->prev_assigned_layer_zpos = -1;
+
+ _update_layers_info(output_data);
+ }
+
+ /* tdm-backend resets all hwc_wnds to CLIENTs while there's any hwc_wnd
+ * within 'device to client transition' state, so after such transition
+ * has finished, we trigger a revalidate event to reevaluate the overlay policy */
+ tdm_backend_trigger_need_validate_event(output_data);
+ }
+
LIST_FOR_EACH_ENTRY(layer, &output_data->layer_list, link) {
if (output_data->need_target_window && layer->zpos == primary_layer_zpos)
continue;
_set_hwc_window_buffer_to_layer(layer, hw);
}
+ if (device_to_client_transition_finished) {
+ hw = NULL;
+
+ LIST_FOR_EACH_ENTRY(hw, &output_data->hwc_window_list, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ hw->is_device_to_client_transition = 0;
+ }
+ }
+
return TDM_ERROR_NONE;
}
}
static void
-_update_layers_info(tdm_exynos_output_data *output_data)
+_reset_buffers_for_unvis_hwc_windows(tdm_exynos_output_data *output_data)
{
- tdm_exynos_layer_data *layer = NULL;
- tdm_exynos_hwc_window_data *hw;
- int primary_layer_zpos = _get_primary_layer_zpos(output_data);
- tdm_error ret;
+ tdm_exynos_hwc_window_data *hw = NULL;
- LIST_FOR_EACH_ENTRY(layer, &output_data->layer_list, link) {
- if (output_data->need_target_window && layer->zpos == primary_layer_zpos)
- hw = output_data->target_hwc_window;
- else
- hw = _find_maped_hwc_window_to_layer(&output_data->hwc_window_list, layer->zpos);
+ if (!output_data->need_target_window)
+ output_data->target_hwc_window->surface = NULL;
- if (hw) {
- ret = exynos_layer_set_info((tdm_layer *)layer,
- (tdm_info_layer *)&(hw->info));
- if (ret != TDM_ERROR_NONE)
- TDM_ERR("cannot set info to layer with %d zpos", layer->zpos);
+ LIST_FOR_EACH_ENTRY(hw, &output_data->hwc_window_list, link)
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ hw->surface = NULL;
+}
+
+static void
+_restore_windows_assigned_layer_zpos(struct list_head *hwc_wnds)
+{
+ tdm_exynos_hwc_window_data *hw = NULL;
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE) {
+ hw->assigned_layer_zpos = -1;
+ continue;
}
+
+ hw->assigned_layer_zpos = hw->prev_assigned_layer_zpos;
}
}
static void
-_reset_buffers_for_unvis_hwc_windows(tdm_exynos_output_data *output_data)
+_reset_windows_to_client(struct list_head *hwc_wnds)
{
tdm_exynos_hwc_window_data *hw = NULL;
- if (!output_data->need_target_window)
- output_data->target_hwc_window->surface = NULL;
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
- LIST_FOR_EACH_ENTRY(hw, &output_data->hwc_window_list, link)
+ if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE &&
+ hw->validated_type == TDM_COMPOSITION_CLIENT)
+ hw->is_device_to_client_transition = 1;
+
+ hw->validated_type = TDM_COMPOSITION_CLIENT;
+ }
+
+ /* move to 'device to client transition' state hwc_wnds
+ * which were mapped to overlays, but which weren't reset to
+ * CLIENT by e20 or _map_hwc_windows_to_layers() func */
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
if (hw->client_type == TDM_COMPOSITION_NONE)
- hw->surface = NULL;
+ continue;
+
+ if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE &&
+ hw->validated_type == TDM_COMPOSITION_CLIENT)
+ hw->is_device_to_client_transition = 1;
+ }
+}
+
+/* if we got at least one device -> client transition or we have
+ * at least one window in 'device to client transitional state' we
+ * reset all windows to the client state, as it's a reference
+ * implementation of the driver */
+static int
+_is_reset_to_client_needed(struct list_head *hwc_wnds)
+{
+ tdm_exynos_hwc_window_data *hw = NULL;
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE &&
+ hw->validated_type == TDM_COMPOSITION_CLIENT)
+ return 1;
+
+ if (hw->is_device_to_client_transition)
+ return 1;
+ }
+
+ return 0;
}
tdm_error
RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
int need_map_hwc_windows_to_layers;
+ int need_reset_to_client;
+ int prev_need_target_window;
exynos_data = exynos_output->exynos_data;
RETURN_VAL_IF_FAIL(exynos_data != NULL, TDM_ERROR_INVALID_PARAMETER);
_reset_composition_types(&exynos_output->hwc_window_list);
} else {
+
+ prev_need_target_window = exynos_output->need_target_window;
+
/* if previous mapping can be used it is not needed to remap hwc_windows
* to layers */
need_map_hwc_windows_to_layers = _need_map_hwc_windows_to_layers(exynos_output);
if (need_map_hwc_windows_to_layers)
_map_hwc_windows_to_layers(exynos_output);
+ need_reset_to_client = _is_reset_to_client_needed(&exynos_output->hwc_window_list);
+ if (need_reset_to_client) {
+ TDM_INFO("reset all hwc_wnds to CLIENT.");
+
+ _reset_windows_to_client(&exynos_output->hwc_window_list);
+ _restore_windows_assigned_layer_zpos(&exynos_output->hwc_window_list);
+
+ exynos_output->need_target_window = prev_need_target_window;
+ }
+
_update_windows_previous_type(&exynos_output->hwc_window_list);
_update_windows_previous_assigned_layer_zpos(&exynos_output->hwc_window_list);
}
tdm_error
exynos_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer,
- tdm_hwc_region damage)
+ tdm_hwc_region damage, tdm_hwc_window **composited_wnds,
+ uint32_t num_wnds)
{
tdm_exynos_output_data *exynos_output = output;
+ tdm_exynos_hwc_window_data **exynos_hwc_window = NULL;
+ tdm_exynos_hwc_window_data *hw = NULL;
tdm_error err;
RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
err = exynos_hwc_window_set_buffer_damage(exynos_output->target_hwc_window, damage);
RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+ /* TODO: sergs: think about it
+ * a hack to allow the e-boot-animation to be shown */
+ if (!composited_wnds || !num_wnds)
+ return TDM_ERROR_NONE;
+
+ /* to keep a list up to date with one provided by e20 */
+ LIST_FOR_EACH_ENTRY(hw, &exynos_output->hwc_window_list, link)
+ hw->present_on_target_wnd = 0;
+
+ exynos_hwc_window = (tdm_exynos_hwc_window_data**)composited_wnds;
+
+ for (uint32_t i = 0; i < num_wnds; i++)
+ exynos_hwc_window[i]->present_on_target_wnd = 1;
+
+ LIST_FOR_EACH_ENTRY(hw, &exynos_output->hwc_window_list, link)
+ if (hw->present_on_target_wnd)
+ TDM_INFO("hwc_wnd:%p presents on the target window.", hw);
+
return TDM_ERROR_NONE;
}