5 #include <tdm_helper.h>
6 #include "tdm_virtual.h"
13 #define NUM_UI_LAYERS 1
17 #define ZPOS_NONE -999
19 tbm_format hwc_window_video_formats[] = {
25 _comp_to_str(tdm_hwc_window_composition composition_type)
27 if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
29 else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
31 else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
33 else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
35 else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE)
42 _print_validate_result(tdm_virtual_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
44 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
47 for (i = 0; i < num_wnds; i++) {
48 hwc_window_data = composited_wnds[i];
49 switch (hwc_window_data->validated_type) {
50 case TDM_HWC_WIN_COMPOSITION_CLIENT:
51 TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s} on TARGET WINDOW", hwc_window_data,
52 _comp_to_str(hwc_window_data->client_type),
53 _comp_to_str(hwc_window_data->validated_type),
54 hwc_data->target_hwc_window->lzpos,
55 hwc_window_data->name ? hwc_window_data->name : "NONE");
57 case TDM_HWC_WIN_COMPOSITION_DEVICE:
58 case TDM_HWC_WIN_COMPOSITION_VIDEO:
59 case TDM_HWC_WIN_COMPOSITION_CURSOR:
60 case TDM_HWC_WIN_COMPOSITION_NONE:
61 TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s}", hwc_window_data,
62 _comp_to_str(hwc_window_data->client_type),
63 _comp_to_str(hwc_window_data->validated_type),
64 hwc_window_data->lzpos,
65 hwc_window_data->name ? hwc_window_data->name : "NONE");
73 static tbm_surface_queue_h
74 _virtual_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
76 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
77 tbm_surface_queue_h tqueue = NULL;
82 *error = TDM_ERROR_INVALID_PARAMETER;
84 RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
86 hwc_window_data = hwc_window;
88 width = hwc_window_data->info.src_config.size.h;
89 height = hwc_window_data->info.src_config.size.v;
90 format = hwc_window_data->info.src_config.format;
92 tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT);
94 *error = TDM_ERROR_OPERATION_FAILED;
95 RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
98 *error = TDM_ERROR_NONE;
104 _virtual_hwc_layer_attach_window(tdm_virtual_layer_data *layer_data, tdm_virtual_hwc_window_data *hwc_window_data)
106 tdm_error ret = TDM_ERROR_NONE;
108 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
110 if (hwc_window_data == NULL || hwc_window_data->surface == NULL) {
111 if (layer_data->display_buffer)
112 ret = virtual_layer_unset_buffer(layer_data);
113 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
115 ret = virtual_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
116 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
117 RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
118 ret = virtual_layer_set_buffer(layer_data, hwc_window_data->surface);
119 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
126 _virtual_hwc_prepare_commit(tdm_virtual_hwc_data *hwc_data)
128 tdm_virtual_layer_data *layer_data = NULL;
129 int use_layers_zpos[NUM_LAYERS] = {0,};
132 /* set target hwc window to the layer */
133 if (hwc_data->need_target_window) {
134 layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
135 _virtual_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
136 use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
139 /* unset the unused layers */
140 for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
141 if (use_layers_zpos[lzpos])
144 layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, lzpos);
148 _virtual_hwc_layer_attach_window(layer_data, NULL);
152 for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) {
153 if (use_layers_zpos[lzpos])
154 TDM_INFO(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET");
157 return TDM_ERROR_NONE;
160 /* assign the validated_type to the composited_wnds
161 * assign the layer_zpos to the composited_wnds
164 _virtual_hwc_apply_policy(tdm_virtual_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
166 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
167 tdm_virtual_hwc_window_data **composited_list = NULL;
170 composited_list = (tdm_virtual_hwc_window_data **)composited_wnds;
172 /* initialize the validated_types */
173 LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
174 if (hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_NONE)
175 hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE;
178 /* use the target_window to commit when there is no window. */
180 hwc_data->need_target_window = 1;
181 hwc_data->target_hwc_window->lzpos = ZPOS_0;
185 /* use only target_window */
186 for (i = 0; i < num_wnds; i++) {
187 composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
188 composited_list[i]->lzpos = ZPOS_NONE;
191 hwc_data->need_target_window = 1;
192 hwc_data->target_hwc_window->lzpos = ZPOS_0;
196 _virtual_hwc_get_changed_number(tdm_virtual_hwc_data *hwc_data)
199 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
201 LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
202 if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
205 if (hwc_window_data->client_type != hwc_window_data->validated_type)
213 _virtual_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
215 tdm_virtual_hwc_data *hwc_data = hwc;
216 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
219 *error = TDM_ERROR_NONE;
222 TDM_ERR("invalid params");
224 *error = TDM_ERROR_INVALID_PARAMETER;
228 hwc_window_data = calloc(1, sizeof(tdm_virtual_hwc_window_data));
229 if (!hwc_window_data) {
230 TDM_ERR("alloc failed");
232 *error = TDM_ERROR_OUT_OF_MEMORY;
236 hwc_window_data->hwc_data = hwc_data;
239 memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
241 LIST_INITHEAD(&hwc_window_data->link);
243 return hwc_window_data;
247 virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
249 tdm_virtual_hwc_data *hwc_data = hwc;
250 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
252 RETURN_VAL_IF_FAIL(hwc_data, NULL);
254 hwc_window_data = _virtual_hwc_create_window(hwc_data, NULL, error);
255 RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
257 LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
259 TDM_DBG("hwc_window(%p) create", hwc_window_data);
261 *error = TDM_ERROR_NONE;
263 return hwc_window_data;
267 virtual_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
269 RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
270 RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
271 RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
273 // TODO: fix these formats.
274 *formats = hwc_window_video_formats;
275 *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
277 return TDM_ERROR_NONE;
281 virtual_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
283 RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
284 RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
288 return TDM_ERROR_NONE;
292 virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
294 tdm_virtual_hwc_data *hwc_data = hwc;
296 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
297 RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
298 RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
303 return TDM_ERROR_NONE;
307 virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
309 tdm_virtual_hwc_data *hwc_data = hwc;
310 tbm_surface_queue_h tqueue = NULL;
313 *error = TDM_ERROR_INVALID_PARAMETER;
315 RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
317 if (hwc_data->target_hwc_window == NULL) {
319 *error = TDM_ERROR_OPERATION_FAILED;
323 tqueue = _virtual_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
324 RETURN_VAL_IF_FAIL(tqueue, NULL);
327 *error = TDM_ERROR_NONE;
333 virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
335 tdm_virtual_hwc_data *hwc_data = hwc;
338 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
339 RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
341 TDM_INFO(" ==============Set Target Buffer Virtual=================================");
343 err = virtual_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
344 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
346 err = virtual_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
347 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
349 return TDM_ERROR_NONE;
353 virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
355 tdm_virtual_hwc_data *hwc_data = hwc;
357 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
358 RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
360 TDM_DBG(" ==============Validate Virtual=================================");
362 _virtual_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
364 *num_types = _virtual_hwc_get_changed_number(hwc_data);
366 _print_validate_result(hwc_data, composited_wnds, num_wnds);
368 return TDM_ERROR_NONE;
372 virtual_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
373 tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types)
375 tdm_virtual_hwc_data *hwc_data = hwc;
376 tdm_virtual_hwc_window_data *hwc_window_data = NULL;
379 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
380 RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
382 if ((hwc_wnds == NULL) || (composition_types == NULL)) {
383 *num_elements = _virtual_hwc_get_changed_number(hwc_data);
384 return TDM_ERROR_NONE;
387 LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
388 if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
391 if (num >= *num_elements)
394 if (hwc_window_data->client_type != hwc_window_data->validated_type) {
395 composition_types[num] = hwc_window_data->validated_type;
396 hwc_wnds[num] = hwc_window_data;
401 /* set real num of changed composition types */
404 return TDM_ERROR_NONE;
408 virtual_hwc_accept_validation(tdm_hwc *hwc)
410 tdm_virtual_hwc_data *hwc_data = hwc;
411 tdm_error ret = TDM_ERROR_NONE;
413 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
414 RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
416 TDM_DBG(" ==============Accept Changes Done Virtual=================================");
418 ret = _virtual_hwc_prepare_commit(hwc_data);
419 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
421 return TDM_ERROR_NONE;
425 virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
427 tdm_virtual_hwc_data *hwc_data = hwc;
428 tdm_virtual_output_data *output_data = NULL;
431 RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
433 output_data = hwc_data->output_data;
434 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
436 TDM_INFO(" ==============COMMIT Virtual=================================");
438 ret = virtual_output_commit(output_data, sync, user_data);
439 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
441 return TDM_ERROR_NONE;
445 virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
447 tdm_virtual_hwc_data *hwc_data = hwc;
449 RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
450 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
452 hwc_data->commit_func = func;
454 return TDM_ERROR_NONE;
458 virtual_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
460 tdm_hwc_window_info info = {0};
461 tdm_error ret = TDM_ERROR_NONE;
462 tdm_virtual_hwc_window_data *target_hwc_window;
463 tdm_virtual_hwc_data *hwc_data = hwc;
465 RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
469 info.dst_pos.h = height;
470 info.dst_pos.w = width;
472 info.src_config.pos.x = 0;
473 info.src_config.pos.y = 0;
474 info.src_config.pos.h = height;
475 info.src_config.pos.w = width;
477 info.src_config.size.h = width;
478 info.src_config.size.v = height;
479 info.src_config.format = TBM_FORMAT_ARGB8888;
481 target_hwc_window = _virtual_hwc_create_window(hwc_data, &info, &ret);
482 if (ret != TDM_ERROR_NONE) {
483 TDM_ERR("create target hwc window failed (%d)", ret);
484 return TDM_ERROR_OPERATION_FAILED;
487 if (hwc_data->target_hwc_window)
488 virtual_hwc_window_destroy(hwc_data->target_hwc_window);
490 hwc_data->target_hwc_window = target_hwc_window;
491 hwc_data->need_set_crtc = 1;
493 return TDM_ERROR_NONE;