+ tbm_surface_h surface;
+ tdm_error err;
+ int i, count, first = 0;
+
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(dst_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(x >= 0, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(y >= 0, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(w >= 0, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(h >= 0, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ err = tdm_output_get_layer_count(output, &count);
+ if (err != TDM_ERROR_NONE) {
+ TDM_ERR("tdm_output_get_layer_count fail(%d)\n", err);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+ if (count <= 0) {
+ TDM_ERR("tdm_output_get_layer_count err(%d, %d)\n", err, count);
+ return TDM_ERROR_BAD_MODULE;
+ }
+
+ for (i = count - 1; i >= 0; i--) {
+ tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+
+ surface = tdm_layer_get_displaying_buffer(layer, &err);
+ if (err != TDM_ERROR_NONE)
+ continue;
+
+ err = _tdm_helper_buffer_convert(surface, dst_buffer, x, y, w, h, first++);
+ if (err != TDM_ERROR_NONE)
+ TDM_DBG("convert fail %d-layer buffer\n", i);
+ else
+ TDM_DBG("convert success %d-layer buffer\n", i);
+ }
+
+ func(dst_buffer, data);
+
+ return TDM_ERROR_NONE;
+}
+
+static char *
+_tdm_helper_get_backend_information(tdm_private_module *private_module, char *reply, int *len)
+{
+ tdm_backend_module *module_data;
+ tdm_func_output *func_output;
+ tdm_func_layer *func_layer;
+ tdm_private_output *private_output = NULL;
+ tdm_private_layer *private_layer = NULL;
+ tdm_private_pp *private_pp = NULL;
+ tdm_private_capture *private_capture = NULL;
+ tdm_error ret;
+ int i;
+
+ func_output = &private_module->func_output;
+ func_layer = &private_module->func_layer;
+
+ /* module information */
+ module_data = private_module->module_data;
+ TDM_SNPRINTF(reply, len, "['%s' backend information]\n", module_data->name);
+ TDM_SNPRINTF(reply, len, "vendor: %s\n", module_data->vendor);
+ TDM_SNPRINTF(reply, len, "version: %d.%d\n\n",
+ (int)TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version),
+ (int)TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version));
+
+ /* output information */
+ TDM_SNPRINTF(reply, len, "['%s' backend output information]\n", module_data->name);
+ TDM_SNPRINTF(reply, len, "--------------------------------------------------------------------------------------------\n");
+ TDM_SNPRINTF(reply, len, "idx maker model name type status dpms subpixel align_w min max phy(mm)\n");
+ TDM_SNPRINTF(reply, len, "--------------------------------------------------------------------------------------------\n");
+ LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
+ TDM_SNPRINTF(reply, len, "%d %s %s %s %s %s %s %u %d %dx%d %dx%d %ux%u\n",
+ private_output->index, private_output->caps.maker,
+ private_output->caps.model, private_output->caps.name,
+ tdm_conn_str(private_output->caps.type),
+ tdm_status_str(private_output->caps.status),
+ tdm_dpms_str(private_output->current_dpms_value),
+ private_output->caps.subpixel,
+ TDM_FRONT_VALUE(private_output->caps.preferred_align),
+ TDM_FRONT_VALUE(private_output->caps.min_w),
+ TDM_FRONT_VALUE(private_output->caps.min_h),
+ TDM_FRONT_VALUE(private_output->caps.max_w),
+ TDM_FRONT_VALUE(private_output->caps.max_h),
+ private_output->caps.mmWidth, private_output->caps.mmHeight);
+
+ TDM_SNPRINTF(reply, len, "\t%u modes:\n", private_output->caps.mode_count);
+
+ if (private_output->caps.mode_count > 0) {
+ TDM_SNPRINTF(reply, len, "\t\t name refresh (Hz) clk hdisp hss hse htot vdisp vss vse vtot vscan\n");
+ for (i = 0; i < private_output->caps.mode_count; i++) {
+ char *current = (private_output->current_mode == private_output->caps.modes + i) ? "*" : " ";
+ TDM_SNPRINTF(reply, len, "\t\t%s%s %u %u %u %u %u %u %u %u %u %u %u ",
+ current,
+ private_output->caps.modes[i].name,
+ private_output->caps.modes[i].vrefresh,
+ private_output->caps.modes[i].clock,
+ private_output->caps.modes[i].hdisplay,
+ private_output->caps.modes[i].hsync_start,
+ private_output->caps.modes[i].hsync_end,
+ private_output->caps.modes[i].htotal,
+ private_output->caps.modes[i].vdisplay,
+ private_output->caps.modes[i].vsync_start,
+ private_output->caps.modes[i].vsync_end,
+ private_output->caps.modes[i].vtotal,
+ private_output->caps.modes[i].vscan);
+ tdm_mode_flag_str(private_output->caps.modes[i].flags, &reply, len);
+ TDM_SNPRINTF(reply, len, " ");
+ tdm_mode_type_str(private_output->caps.modes[i].type, &reply, len);
+ TDM_SNPRINTF(reply, len, "\n");
+ }
+ }
+
+ TDM_SNPRINTF(reply, len, "\t%d properties:\n", private_output->caps.prop_count);
+ if (private_output->caps.prop_count > 0) {
+ TDM_SNPRINTF(reply, len, "\t\tname\ttype\tidx\tvalue\n");
+ for (i = 0; i < private_output->caps.prop_count; i++) {
+ tdm_value value;
+ TDM_DBG_RETURN_VAL_IF_FAIL(func_output->output_get_property, reply);
+ ret = func_output->output_get_property(private_output->output_backend,
+ private_output->caps.props[i].id,
+ &value);
+ TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply);
+ TDM_SNPRINTF(reply, len, "\t\t%s\t%s\t%u\t",
+ private_output->caps.props[i].name,
+ tdm_value_type_str(private_output->caps.props[i].type),
+ private_output->caps.props[i].id);
+ switch (private_output->caps.props[i].type) {
+ case TDM_VALUE_TYPE_PTR:
+ TDM_SNPRINTF(reply, len, "%p\n", value.ptr);
+ break;
+ case TDM_VALUE_TYPE_INT32:
+ TDM_SNPRINTF(reply, len, "%d\n", value.s32);
+ break;
+ case TDM_VALUE_TYPE_INT64:
+ TDM_SNPRINTF(reply, len, "%"PRId64"\n", value.s64);
+ break;
+ case TDM_VALUE_TYPE_UINT64:
+ TDM_SNPRINTF(reply, len, "%"PRIu64"\n", value.u64);
+ break;
+ case TDM_VALUE_TYPE_UINT32:
+ default:
+ TDM_SNPRINTF(reply, len, "%u\n", value.u32);
+ break;
+ }
+ }
+ }
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+
+ /* layer information */
+ TDM_SNPRINTF(reply, len, "['%s' backend layer information]\n", module_data->name);
+ TDM_SNPRINTF(reply, len, "-----------------------------------------------------------------------\n");
+ TDM_SNPRINTF(reply, len, "idx output zpos buf format size crop geometry transform\n");
+ TDM_SNPRINTF(reply, len, "-----------------------------------------------------------------------\n");
+ LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) {
+ LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
+ if (!private_layer->usable) {
+ tdm_info_layer info;
+ unsigned int format;
+ tdm_size size;
+ tbm_surface_info_s buf_info;
+
+ TDM_DBG_RETURN_VAL_IF_FAIL(func_layer->layer_get_info, reply);
+ memset(&info, 0, sizeof info);
+ ret = func_layer->layer_get_info(private_layer->layer_backend, &info);
+ TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply);
+
+ if (!private_layer->showing_buffer)
+ continue;
+
+ format = tbm_surface_get_format(private_layer->showing_buffer->buffer);
+ tbm_surface_get_info(private_layer->showing_buffer->buffer, &buf_info);
+
+ if (IS_RGB(format))
+ size.h = buf_info.planes[0].stride >> 2;
+ else
+ size.h = buf_info.planes[0].stride;
+ size.v = tbm_surface_get_height(private_layer->showing_buffer->buffer);
+
+ if (info.src_config.format)
+ format = (info.src_config.format) ? : format;
+
+ TDM_SNPRINTF(reply, len, "%d %d %d %p %c%c%c%c %ux%u %ux%u+%u+%u %ux%u+%u+%u %s\n",
+ private_layer->index,
+ private_output->index,
+ private_layer->caps.zpos,
+ private_layer->showing_buffer->buffer, FOURCC_STR(format), size.h, size.v,
+ info.src_config.pos.w, info.src_config.pos.h, info.src_config.pos.x, info.src_config.pos.y,
+ info.dst_pos.w, info.dst_pos.h, info.dst_pos.x, info.dst_pos.y,
+ tdm_transform_str(info.transform));
+ } else {
+ TDM_SNPRINTF(reply, len, "%d %d %d -\n",
+ private_layer->index,
+ private_output->index,
+ private_layer->caps.zpos);
+ }
+
+ TDM_SNPRINTF(reply, len, "\tcaps\t: ");
+ tdm_layer_caps_str(private_layer->caps.capabilities, &reply, len);
+ TDM_SNPRINTF(reply, len, "\n");
+
+ TDM_SNPRINTF(reply, len, "\tformats\t: ");
+ if (private_layer->caps.format_count > 0) {
+ const char *sep = "";
+ for (i = 0; i < private_layer->caps.format_count; i++) {
+ if (private_layer->caps.formats[i] == 0)
+ continue;
+ TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_layer->caps.formats[i]));
+ sep = ",";
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+ }
+
+ TDM_SNPRINTF(reply, len, "\t%u properties:\n", private_layer->caps.prop_count);
+ if (private_layer->caps.prop_count > 0) {
+ TDM_SNPRINTF(reply, len, "\t\tname\ttype\tidx\tvalue\n");
+ for (i = 0; i < private_layer->caps.prop_count; i++) {
+ tdm_value value;
+ TDM_DBG_RETURN_VAL_IF_FAIL(func_layer->layer_get_property, reply);
+ ret = func_layer->layer_get_property(private_layer->layer_backend,
+ private_layer->caps.props[i].id,
+ &value);
+ TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply);
+ TDM_SNPRINTF(reply, len, "\t\t%s\t%s\t%u\t",
+ private_layer->caps.props[i].name,
+ tdm_value_type_str(private_output->caps.props[i].type),
+ private_layer->caps.props[i].id);
+ switch (private_layer->caps.props[i].type) {
+ case TDM_VALUE_TYPE_PTR:
+ TDM_SNPRINTF(reply, len, "%p\n", value.ptr);
+ break;
+ case TDM_VALUE_TYPE_INT32:
+ TDM_SNPRINTF(reply, len, "%d\n", value.s32);
+ break;
+ case TDM_VALUE_TYPE_INT64:
+ TDM_SNPRINTF(reply, len, "%"PRId64"\n", value.s64);
+ break;
+ case TDM_VALUE_TYPE_UINT64:
+ TDM_SNPRINTF(reply, len, "%"PRIu64"\n", value.u64);
+ break;
+ case TDM_VALUE_TYPE_UINT32:
+ default:
+ TDM_SNPRINTF(reply, len, "%u\n", value.u32);
+ break;
+ }
+ }
+ }
+ }
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+
+ if (private_module->capabilities & TDM_DISPLAY_CAPABILITY_PP) {
+ const char *sep = "";
+ TDM_SNPRINTF(reply, len, "['%s' backend PP information]\n", module_data->name);
+ TDM_SNPRINTF(reply, len, "caps\t: ");
+ tdm_pp_caps_str(private_module->caps_pp.capabilities, &reply, len);
+ TDM_SNPRINTF(reply, len, "\n");
+ TDM_SNPRINTF(reply, len, "formats\t: ");
+ for (i = 0; i < private_module->caps_pp.format_count; i++) {
+ if (private_module->caps_pp.formats[i] == 0)
+ continue;
+ TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_module->caps_pp.formats[i]));
+ sep = ",";
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+ TDM_SNPRINTF(reply, len, "size\t: min(%dx%d) max(%dx%d) align_w(%d)\n",
+ TDM_FRONT_VALUE(private_module->caps_pp.min_w),
+ TDM_FRONT_VALUE(private_module->caps_pp.min_h),
+ TDM_FRONT_VALUE(private_module->caps_pp.max_w),
+ TDM_FRONT_VALUE(private_module->caps_pp.max_h),
+ TDM_FRONT_VALUE(private_module->caps_pp.preferred_align));
+ if (!LIST_IS_EMPTY(&private_module->pp_list)) {
+ TDM_SNPRINTF(reply, len, "-------------------------------------------------------------\n");
+ TDM_SNPRINTF(reply, len, "src(format size crop) | dst(format size crop) | transform\n");
+ TDM_SNPRINTF(reply, len, "-------------------------------------------------------------\n");
+ LIST_FOR_EACH_ENTRY(private_pp, &private_module->pp_list, link) {
+ TDM_SNPRINTF(reply, len, "%c%c%c%c %ux%u %ux%u+%u+%u | %c%c%c%c %ux%u %ux%u+%u+%u | %s\n",
+ FOURCC_STR(private_pp->info.src_config.format),
+ private_pp->info.src_config.size.h,
+ private_pp->info.src_config.size.v,
+ private_pp->info.src_config.pos.x, private_pp->info.src_config.pos.y,
+ private_pp->info.src_config.pos.w, private_pp->info.src_config.pos.h,
+ FOURCC_STR(private_pp->info.dst_config.format),
+ private_pp->info.dst_config.size.h,
+ private_pp->info.dst_config.size.v,
+ private_pp->info.dst_config.pos.x, private_pp->info.dst_config.pos.y,
+ private_pp->info.dst_config.pos.w, private_pp->info.dst_config.pos.h,
+ tdm_transform_str(private_pp->info.transform));
+ }
+ }
+ } else {
+ TDM_SNPRINTF(reply, len, "['%s' backend No PP capability]\n", module_data->name);
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+
+ if (private_module->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) {
+ const char *sep = "";
+ TDM_SNPRINTF(reply, len, "['%s' backend capture information]\n", module_data->name);
+ TDM_SNPRINTF(reply, len, "caps\t: ");
+ tdm_capture_caps_str(private_module->caps_capture.capabilities, &reply, len);
+ TDM_SNPRINTF(reply, len, "\n");
+ TDM_SNPRINTF(reply, len, "formats\t: ");
+ for (i = 0; i < private_module->caps_capture.format_count; i++) {
+ if (private_module->caps_capture.formats[i] == 0)
+ continue;
+ TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_module->caps_capture.formats[i]));
+ sep = ",";
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+ TDM_SNPRINTF(reply, len, "size\t: min(%dx%d) max(%dx%d) align_w(%d)\n",
+ TDM_FRONT_VALUE(private_module->caps_capture.min_w),
+ TDM_FRONT_VALUE(private_module->caps_capture.min_h),
+ TDM_FRONT_VALUE(private_module->caps_capture.max_w),
+ TDM_FRONT_VALUE(private_module->caps_capture.max_h),
+ TDM_FRONT_VALUE(private_module->caps_capture.preferred_align));
+ if (!LIST_IS_EMPTY(&private_module->capture_list)) {
+ TDM_SNPRINTF(reply, len, "-----------------------------------\n");
+ TDM_SNPRINTF(reply, len, "dst(format size crop) | transform\n");
+ TDM_SNPRINTF(reply, len, "-----------------------------------\n");
+ LIST_FOR_EACH_ENTRY(private_capture, &private_module->capture_list, link) {
+ TDM_SNPRINTF(reply, len, "%c%c%c%c %ux%u %ux%u+%u+%u | %s\n",
+ FOURCC_STR(private_capture->info.dst_config.format),
+ private_capture->info.dst_config.size.h,
+ private_capture->info.dst_config.size.v,
+ private_capture->info.dst_config.pos.x, private_capture->info.dst_config.pos.y,
+ private_capture->info.dst_config.pos.w, private_capture->info.dst_config.pos.h,
+ tdm_transform_str(private_capture->info.transform));
+ }
+ }
+ } else {
+ TDM_SNPRINTF(reply, len, "['%s' backend No Capture capability]\n", module_data->name);
+ }
+ TDM_SNPRINTF(reply, len, "\n");
+ return reply;
+}
+
+EXTERN void
+tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len)
+{
+ tdm_private_display *private_display;
+ tdm_private_module *private_module = NULL;
+
+ TDM_DBG_RETURN_IF_FAIL(dpy != NULL);
+
+ private_display = dpy;
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
+ reply = _tdm_helper_get_backend_information(private_module, reply, len);
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+}
+
+/* LCOV_EXCL_START */
+EXTERN int
+tdm_helper_commit_per_vblank_enabled(tdm_display *dpy)
+{
+ TDM_DEPRECATED("Use tdm_helper_output_commit_per_vblank_enabled");
+
+ return 0;