exynos_func_output.output_hwc_accept_changes = exynos_output_hwc_accept_changes;
exynos_func_output.output_hwc_get_target_buffer_queue = exynos_output_hwc_get_target_buffer_queue;
exynos_func_output.output_hwc_set_client_target_buffer = exynos_output_hwc_set_client_target_buffer;
+ exynos_func_output.output_hwc_get_video_supported_formats = exynos_output_hwc_get_video_supported_formats;
+ exynos_func_output.output_hwc_create_video_window = exynos_output_hwc_create_video_window;
memset(&exynos_func_hwc_window, 0, sizeof(exynos_func_hwc_window));
exynos_func_hwc_window.hwc_window_get_tbm_buffer_queue = exynos_hwc_window_get_tbm_buffer_queue;
exynos_func_hwc_window.hwc_window_set_flags = exynos_hwc_window_set_flags;
exynos_func_hwc_window.hwc_window_unset_flags = exynos_hwc_window_unset_flags;
exynos_func_hwc_window.hwc_window_video_get_capability = exynos_hwc_window_video_get_capability;
- exynos_func_hwc_window.hwc_window_video_get_supported_format = exynos_hwc_window_video_get_supported_format;
+ exynos_func_hwc_window.hwc_window_video_get_available_properties = exynos_hwc_window_video_get_available_properties;
+ exynos_func_hwc_window.hwc_window_video_get_property = exynos_hwc_window_video_get_property;
+ exynos_func_hwc_window.hwc_window_video_set_property = exynos_hwc_window_video_set_property;
}
memset(&exynos_func_layer, 0, sizeof(exynos_func_layer));
tbm_surface_queue_h exynos_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error);
tdm_error exynos_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer,
tdm_hwc_region damage);
+tdm_error exynos_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count);
+tdm_hwc_window *exynos_output_hwc_create_video_window(tdm_output *output, tdm_error *error);
tdm_error exynos_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
tdm_error exynos_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value);
tdm_error exynos_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value);
tdm_error exynos_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags);
tdm_error exynos_hwc_window_video_get_capability(tdm_hwc_window *hwc_window,
tdm_hwc_window_video_capability *video_capability);
-tdm_error exynos_hwc_window_video_get_supported_format(tdm_hwc_window *hwc_window,
- const tbm_format **formats,
- int *count);
+tdm_error exynos_hwc_window_video_get_available_properties(tdm_hwc_window *hwc_window, const tdm_prop **props, int *count);
+tdm_error exynos_hwc_window_video_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value);
+tdm_error exynos_hwc_window_video_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value);
void exynos_pp_destroy(tdm_pp *pp);
tdm_error exynos_pp_set_info(tdm_pp *pp, tdm_info_pp *info);
tdm_error exynos_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst);
tdm_exynos_layer_data *l = NULL, *ll = NULL;
LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
LIST_DEL(&l->link);
+ if (l->formats)
+ free(l->formats);
+ if (l->props)
+ free(l->props);
free(l);
}
}
*out_format_count = 0;
return ret;
}
+
+tdm_error
+exynos_layer_get_available_properties(tdm_layer *layer, const tdm_prop **out_props,
+ int *out_prop_count)
+{
+ tdm_exynos_layer_data *layer_data = layer;
+ tdm_exynos_data *exynos_data;
+ drmModePlanePtr plane = NULL;
+ drmModeObjectPropertiesPtr props = NULL;
+ int i;
+ tdm_error ret;
+ tdm_prop *tdm_props = NULL;
+ int prop_count;
+
+ RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(out_props, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(out_prop_count, TDM_ERROR_INVALID_PARAMETER);
+
+ if (layer_data->props) {
+ *out_props = layer_data->props;
+ *out_prop_count = layer_data->prop_count;
+
+ return TDM_ERROR_NONE;
+ }
+
+ exynos_data = layer_data->exynos_data;
+ plane = drmModeGetPlane(exynos_data->drm_fd, layer_data->plane_id);
+ if (!plane) {
+ TDM_ERR("get plane failed: %m");
+ ret = TDM_ERROR_OPERATION_FAILED;
+ goto failed_get;
+ }
+
+ props = drmModeObjectGetProperties(exynos_data->drm_fd, layer_data->plane_id,
+ DRM_MODE_OBJECT_PLANE);
+ if (!props) {
+ ret = TDM_ERROR_OPERATION_FAILED;
+ TDM_ERR("get plane properties failed: %m\n");
+ goto failed_get;
+ }
+
+ tdm_props = calloc(1, sizeof(tdm_prop) * props->count_props);
+ if (!tdm_props) {
+ ret = TDM_ERROR_OUT_OF_MEMORY;
+ TDM_ERR("alloc failed\n");
+ goto failed_get;
+ }
+
+ prop_count = 0;
+ for (i = 0; i < props->count_props; i++) {
+ drmModePropertyPtr prop = drmModeGetProperty(exynos_data->drm_fd,
+ props->props[i]);
+ if (!prop)
+ continue;
+ if (!strncmp(prop->name, "type", TDM_NAME_LEN)) {
+ drmModeFreeProperty(prop);
+ continue;
+ }
+ if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) {
+ drmModeFreeProperty(prop);
+ continue;
+ }
+ snprintf(tdm_props[i].name, TDM_NAME_LEN, "%s", prop->name);
+ tdm_props[i].id = props->props[i];
+ prop_count++;
+ drmModeFreeProperty(prop);
+ }
+
+ drmModeFreeObjectProperties(props);
+ drmModeFreePlane(plane);
+
+ layer_data->props = tdm_props;
+ layer_data->prop_count = prop_count;
+
+ *out_props = layer_data->props;
+ *out_prop_count = layer_data->prop_count;
+
+ return TDM_ERROR_NONE;
+failed_get:
+ drmModeFreeObjectProperties(props);
+ drmModeFreePlane(plane);
+ *out_props = NULL;
+ *out_prop_count = 0;
+
+ return ret;
+}
tdm_error
tdm_exynos_layer_get_supported_format(tdm_layer *layer, const tbm_format **out_formats,
int *out_format_count);
+tdm_error
+exynos_layer_get_available_properties(tdm_layer *layer, const tdm_prop **out_props,
+ int *out_prop_count);
#endif /* _TDM_EXYNOS_LAYER_H_ */
continue;
if (hw->assigned_layer_zpos == layer_zpos &&
- (hw->validated_type == TDM_COMPOSITION_VIDEO ||
- hw->validated_type == TDM_COMPOSITION_DEVICE ||
+ (hw->validated_type == TDM_COMPOSITION_DEVICE ||
hw->validated_type == TDM_COMPOSITION_CLIENT_CANDIDATE))
return hw;
}
_set_hwc_window_buffer_to_layer(layer, output_data->target_hwc_window);
}
+ if (output_data->video_hwc_window) {
+ layer = _exynos_output_get_layer(output_data, output_data->video_hwc_window->assigned_layer_zpos);
+ _set_hwc_window_buffer_to_layer(layer, output_data->video_hwc_window);
+ }
+
if (_are_windows_with_client_candidate_type(&output_data->hwc_window_list))
return TDM_ERROR_NONE;
LIST_FOR_EACH_ENTRY(layer, &output_data->layer_list, link) {
if (output_data->need_target_window && layer->zpos == primary_layer_zpos)
continue;
+ if (output_data->video_hwc_window && layer->zpos == output_data->video_hwc_window->assigned_layer_zpos)
+ continue;
hw = _find_maped_hwc_window_to_layer(&output_data->hwc_window_list, layer->zpos);
_set_hwc_window_buffer_to_layer(layer, hw);
exynos_output_hwc_window_destroy(tdm_output *output, tdm_hwc_window *hwc_window)
{
tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
+ tdm_exynos_output_data *output_data;
+
+ RETURN_VAL_IF_FAIL(exynos_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ output_data = exynos_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (output_data->video_hwc_window == exynos_hwc_window)
+ output_data->video_hwc_window = NULL;
LIST_DEL(&exynos_hwc_window->link);
return "DEVICE";
else if (composition_type == TDM_COMPOSITION_CURSOR)
return "CURSOR";
- else if (composition_type == TDM_COMPOSITION_VIDEO)
- return "VIDEO";
else if (composition_type == TDM_COMPOSITION_NONE)
return "SKIP";
return number;
}
-static int
-_buttom_window_is_video(struct list_head *hwc_window_list)
-{
- tdm_exynos_hwc_window_data *window = NULL;
-
- LIST_FOR_EACH_ENTRY(window, hwc_window_list, link) {
- if (window->client_type == TDM_COMPOSITION_NONE)
- continue;
- if (window->client_type == TDM_COMPOSITION_VIDEO)
- return 1;
- break;
- }
-
- return 0;
-}
-
static int
_top_window_should_be_placed_on_fb_layer(struct list_head *hwc_window_list)
{
int num_hwc_windows = _get_number_of_visible_windows(hwc_window_list);
- if (_buttom_window_is_video(hwc_window_list))
- num_hwc_windows--;
-
return num_hwc_windows <= 1;
}
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
+/* if we got at least one device -> 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 */
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;
}
}
}
+ if (exynos_output->video_hwc_window)
+ num_bottom_layer_with_primary--;
+
if (num_unmarked_layers > num_bottom_layer_with_primary)
need_target_window = 1;
layer_zpos = -1;
if (num_skip_layers > 0)
layer_zpos += num_skip_layers;
+ if (exynos_output->video_hwc_window)
+ layer_zpos++;
LIST_FOR_EACH_ENTRY(hw, &exynos_output->hwc_window_list, link) {
if (hw->client_type == TDM_COMPOSITION_NONE)
continue;
/* break if the remaining windows are already marked */
if (hw->validated_type == TDM_COMPOSITION_DEVICE)
break;
- if (hw->client_type == TDM_COMPOSITION_VIDEO && layer_zpos == 0) {
- hw->validated_type = TDM_COMPOSITION_VIDEO;
- hw->assigned_layer_zpos = layer_zpos;
- continue;
- }
- if ((hw->client_type == TDM_COMPOSITION_DEVICE || hw->client_type == TDM_COMPOSITION_VIDEO)
+ if ((hw->client_type == TDM_COMPOSITION_DEVICE)
&& layer_zpos < max_hw_layer_zpos) {
/* check format */
if (IS_RGB(hw->info.src_config.format)) {
_need_map_hwc_windows_to_layers(tdm_exynos_output_data *exynos_output)
{
tdm_exynos_hwc_window_data *hw = NULL;
+ tdm_exynos_output_data *output_data;
int primary_layer_zpos = _get_primary_layer_zpos(exynos_output);
int hw_window_is_maped_on_primary_layer = 0;
int need_target_window = 0;
return 1;
if (hw->client_type == TDM_COMPOSITION_CLIENT)
need_target_window = 1;
+
+ output_data = hw->output_data;
+ if (output_data && output_data->video_hwc_window)
+ if (output_data->video_hwc_window->assigned_layer_zpos == hw->assigned_layer_zpos)
+ return 1;
}
if (need_target_window != exynos_output->need_target_window)
continue;
if (hw->validated_type == TDM_COMPOSITION_DEVICE ||
- hw->validated_type == TDM_COMPOSITION_VIDEO ||
hw->validated_type == TDM_COMPOSITION_CLIENT_CANDIDATE)
TDM_DBG(" window(%p) type: %s -> %s : is mapped to layer with %d zpos", hw,
_comp_to_str(hw->client_type), _comp_to_str(hw->validated_type),
return TDM_ERROR_NONE;
}
+tdm_hwc_window *
+exynos_output_hwc_create_video_window(tdm_output *output, tdm_error *error)
+{
+ tdm_exynos_hwc_window_data *exynos_hwc_window = NULL;
+ tdm_exynos_output_data *exynos_output = output;
+
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+
+ RETURN_VAL_IF_FAIL(exynos_output != NULL, NULL);
+
+ if (error)
+ *error = TDM_ERROR_OPERATION_FAILED;
+
+ if (exynos_output->video_hwc_window)
+ return NULL;
+
+ exynos_hwc_window = _exynos_output_hwc_window_create(exynos_output, NULL, error);
+ if (exynos_hwc_window == NULL)
+ return NULL;
+
+ exynos_hwc_window->assigned_layer_zpos = 0;
+ exynos_output->video_hwc_window = exynos_hwc_window;
+
+ TDM_DBG("hwc_window(%p) video create", exynos_hwc_window);
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return exynos_hwc_window;
+}
+
+tdm_error
+exynos_output_hwc_get_video_supported_formats(tdm_output *output,
+ const tbm_format **formats,
+ int *count)
+{
+ tdm_exynos_output_data *output_data = output;
+ tdm_exynos_layer_data * layer = NULL;
+
+ RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ /* now the video window supported only on the layer with index 0 */
+ layer = _exynos_output_get_layer(output_data, 0);
+
+ return tdm_exynos_layer_get_supported_format(layer, formats, count);
+}
int hwc_enable;
tdm_exynos_hwc_window_data *target_hwc_window;
+ tdm_exynos_hwc_window_data *video_hwc_window;
int need_validate;
int need_target_window;
tbm_format *formats;
int format_count;
+
+ tdm_prop *props;
+ int prop_count;
};
struct _tdm_exynos_hwc_window_data {
exynos_hwc_window = hwc_window;
exynos_output = exynos_hwc_window->output_data;
RETURN_VAL_IF_FAIL(exynos_output != NULL, NULL);
+ RETURN_VAL_IF_FAIL(exynos_output->video_hwc_window != exynos_hwc_window, NULL);
int wight = exynos_hwc_window->info.src_config.size.h;
int hight = exynos_hwc_window->info.src_config.size.v;
exynos_output = exynos_hwc_window->output_data;
RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(exynos_output->video_hwc_window != exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
if (exynos_hwc_window->zpos == zpos)
return TDM_ERROR_NONE;
RETURN_VAL_IF_FAIL(exynos_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(exynos_output->video_hwc_window != exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
if (exynos_hwc_window->client_type == comp_type)
return TDM_ERROR_NONE;
exynos_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
{
tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
- tdm_exynos_output_data *exynos_output = exynos_hwc_window->output_data;
+ tdm_exynos_output_data *exynos_output;
RETURN_VAL_IF_FAIL(exynos_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ exynos_output = exynos_hwc_window->output_data;
RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
if (!memcmp(&exynos_hwc_window->info, info, sizeof(tdm_hwc_window_info)))
return TDM_ERROR_NONE;
+ if (exynos_output->video_hwc_window == exynos_hwc_window) {
+ tdm_exynos_layer_data *layer;
+ layer = _exynos_output_get_layer(exynos_output, exynos_hwc_window->assigned_layer_zpos);
+
+ return exynos_layer_set_info(layer, (tdm_info_layer *)info);
+ }
+
exynos_hwc_window->info = *info;
exynos_output->need_validate = 1;
tdm_hwc_window_video_capability *video_capability)
{
tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
+ tdm_exynos_output_data *exynos_output;
RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ exynos_output = exynos_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(exynos_output != NULL, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(exynos_hwc_window->validated_type == TDM_COMPOSITION_VIDEO, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(exynos_output->video_hwc_window == exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
*video_capability = 0;
return TDM_ERROR_NONE;
}
+
tdm_error
-exynos_hwc_window_video_get_supported_format(tdm_hwc_window *hwc_window,
- const tbm_format **formats,
- int *count)
+exynos_hwc_window_video_get_available_properties(tdm_hwc_window *hwc_window,
+ const tdm_prop **props, int *count)
{
tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
- tdm_exynos_layer_data * layer = NULL;
+ tdm_exynos_output_data *output_data;
+ tdm_exynos_layer_data *layer_data;
RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(exynos_hwc_window->validated_type == TDM_COMPOSITION_VIDEO, TDM_ERROR_INVALID_PARAMETER);
- /* now the video window supported only on the layer with index 0 */
- layer = _exynos_output_get_layer(exynos_hwc_window->output_data, 0);
+ output_data = exynos_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(output_data->video_hwc_window == exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
+
+ layer_data = _exynos_output_get_layer(output_data, exynos_hwc_window->assigned_layer_zpos);
- return tdm_exynos_layer_get_supported_format(layer, formats, count);
+ return exynos_layer_get_available_properties(layer_data, props, count);
}
+
+tdm_error
+exynos_hwc_window_video_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
+{
+ tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
+ tdm_exynos_output_data *output_data;
+ tdm_exynos_layer_data *layer_data;
+
+ RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ output_data = exynos_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(output_data->video_hwc_window == exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
+
+ layer_data = _exynos_output_get_layer(output_data, exynos_hwc_window->assigned_layer_zpos);
+
+ return exynos_layer_get_property(layer_data, id, value);
+}
+
+tdm_error
+exynos_hwc_window_video_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
+{
+ tdm_exynos_hwc_window_data *exynos_hwc_window = hwc_window;
+ tdm_exynos_output_data *output_data;
+ tdm_exynos_layer_data *layer_data;
+
+ RETURN_VAL_IF_FAIL(hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ output_data = exynos_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(output_data->video_hwc_window == exynos_hwc_window, TDM_ERROR_INVALID_PARAMETER);
+
+ layer_data = _exynos_output_get_layer(output_data, exynos_hwc_window->assigned_layer_zpos);
+
+ return exynos_layer_set_property(layer_data, id, value);
+}
\ No newline at end of file