tdm_hwc_window_composition client_type;
/* validated_type stores the type after running Validate */
tdm_hwc_window_composition validated_type;
+ /* prev_validated_type is used to achieve requirements tied with the client_candidate type */
+ tdm_hwc_window_composition prev_validated_type;
tdm_hwc_window_flag flags;
};
return TDM_ERROR_NONE;
}
+static int
+_are_windows_with_client_candidate_type(struct list_head *hwc_wnds)
+{
+ tdm_sprd_hwc_window_data *hw = NULL;
+
+ RETURN_VAL_IF_FAIL(hwc_wnds, 0);
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+
+ if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP)
+ continue;
+
+ if (hw->validated_type == TDM_COMPOSITION_CLIENT_CANDIDATE)
+ return 1;
+ }
+
+ return 0;
+}
+
static tdm_error
_tdm_sprd_display_prepare_commit(tdm_sprd_output_data *output_data) {
_sprd_layer_attach_window(layer, output_data->target_hwc_window);
}
- /* set hwc windows */
+ if (_are_windows_with_client_candidate_type(&output_data->hwc_window_list))
+ return TDM_ERROR_NONE;
+
+ /* set hwc windows */
LIST_FOR_EACH_ENTRY_REV(hw, &output_data->hwc_window_list, link) {
if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP)
continue;
sprd_hwc_window->output_data = output;
sprd_hwc_window->zpos = 0;
+ sprd_hwc_window->prev_validated_type = TDM_COMPOSITION_CLIENT;
if (info)
memcpy(&sprd_hwc_window->info, info, sizeof(tdm_hwc_window_info));
{
if (composition_type == TDM_COMPOSITION_CLIENT)
return "CLIENT";
+ else if (composition_type == TDM_COMPOSITION_CLIENT_CANDIDATE)
+ return "CLIENT_CANDIDATE";
else if (composition_type == TDM_COMPOSITION_DEVICE_CANDIDATE)
return "DEVICE_CANDIDATE";
else if (composition_type == TDM_COMPOSITION_DEVICE)
return number;
}
+static void
+_update_windows_previous_type(struct list_head *hwc_wnds)
+{
+ tdm_sprd_hwc_window_data *hw = NULL;
+
+ RETURN_VOID_IF_FAIL(hwc_wnds);
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+ if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP) {
+ hw->prev_validated_type = TDM_COMPOSITION_CLIENT;
+ continue;
+ }
+
+ hw->prev_validated_type = hw->validated_type;
+ }
+}
+
+static void
+_reset_windows_to_client(struct list_head *hwc_wnds)
+{
+ tdm_sprd_hwc_window_data *hw = NULL;
+
+ RETURN_VOID_IF_FAIL(hwc_wnds);
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+
+ if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP)
+ continue;
+
+ if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE_CANDIDATE)
+ hw->validated_type = TDM_COMPOSITION_CLIENT;
+
+ if (hw->prev_validated_type == TDM_COMPOSITION_CLIENT)
+ hw->validated_type = TDM_COMPOSITION_CLIENT;
+
+ else if (hw->prev_validated_type == TDM_COMPOSITION_CLIENT_CANDIDATE)
+ hw->validated_type = TDM_COMPOSITION_CLIENT_CANDIDATE;
+
+ else if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE)
+ hw->validated_type = TDM_COMPOSITION_CLIENT_CANDIDATE;
+
+ else if (hw->prev_validated_type == TDM_COMPOSITION_VIDEO)
+ hw->validated_type = TDM_COMPOSITION_CLIENT_CANDIDATE;
+ }
+}
+
+/*
+ * If we got at least one device/video -> client transition or we still have at
+ * least one window at the client_candidate state we reset all windows
+ * to the client/client_candidate state as it's a reference implementation
+ * of the driver
+ */
+static int
+_is_reset_to_client_needed(struct list_head *hwc_wnds)
+{
+ tdm_sprd_hwc_window_data *hw = NULL;
+
+ RETURN_VAL_IF_FAIL(hwc_wnds, 0);
+
+ LIST_FOR_EACH_ENTRY(hw, hwc_wnds, link) {
+
+ if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP)
+ continue;
+
+ /* client_type is kept, as a TDM_COMPOSITION_CLIENT_CANDIDATE, by the client(e20)
+ * till buffer (of this window) being composited to the fb_target */
+ if (hw->prev_validated_type == TDM_COMPOSITION_DEVICE &&
+ hw->validated_type == TDM_COMPOSITION_CLIENT)
+ return 1;
+
+ if (hw->prev_validated_type == TDM_COMPOSITION_VIDEO &&
+ hw->validated_type == TDM_COMPOSITION_CLIENT)
+ return 1;
+
+ if (hw->client_type == TDM_COMPOSITION_CLIENT_CANDIDATE)
+ return 1;
+ }
+
+ return 0;
+}
+
tdm_error
sprd_output_hwc_validate(tdm_output *output, uint32_t *num_types)
{
int need_target_buffer = 0;
int is_client_detected = 0;
int max_hw_layer = HW_LAYER_NUM;
- int i = 0;
+ int need_reset_wnds_to_client;
sprd_data = sprd_output->sprd_data;
RETURN_VAL_IF_FAIL(sprd_data != NULL, TDM_ERROR_INVALID_PARAMETER);
if (is_client_detected)
need_target_buffer = 1;
+ need_reset_wnds_to_client =
+ _is_reset_to_client_needed(&sprd_output->hwc_window_list);
+
+ if (need_reset_wnds_to_client) {
+ _reset_windows_to_client(&sprd_output->hwc_window_list);
+
+ /* restore previous value */
+ need_target_buffer = sprd_output->need_target_buffer;
+ }
+
+ _update_windows_previous_type(&sprd_output->hwc_window_list);
+
LIST_FOR_EACH_ENTRY(hw, &sprd_output->hwc_window_list, link) {
if (hw->flags & TDM_HWC_WINDOW_FLAG_SKIP)
continue;
- if (need_target_buffer && hw_layer_count == i++)
- TDM_DBG(" window(%p) target", sprd_output->target_hwc_window);
- else
- TDM_DBG(" window(%p) type: %s -> %s", hw,
- _comp_to_str(hw->client_type), _comp_to_str(hw->validated_type));
+ TDM_DBG(" window(%p) type: %s -> %s", hw,
+ _comp_to_str(hw->client_type), _comp_to_str(hw->validated_type));
}
sprd_output->need_target_buffer = need_target_buffer;