42031cca0c9134a04686d8bd85d6f65c03515f85
[platform/core/uifw/libtdm.git] / backends / virtual / tdm_virtual_hwc.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <tdm_helper.h>
6 #include "tdm_virtual.h"
7
8 #define MIN_WIDTH      32
9
10 #define NUM_LAYERS     1
11 #define NUM_BUFFERS    3
12
13 #define NUM_UI_LAYERS  1
14
15 #define ZPOS_MAX       1
16 #define ZPOS_0         0
17 #define ZPOS_NONE      -999
18
19 tbm_format hwc_window_video_formats[] = {
20         TBM_FORMAT_ARGB8888,
21         TBM_FORMAT_XRGB8888,
22 };
23
24 const char *
25 _comp_to_str(tdm_hwc_window_composition composition_type)
26 {
27         if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
28                 return "CLIENT";
29         else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
30                 return "DEVICE";
31         else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
32                 return "CURSOR";
33         else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
34                 return "VIDEO";
35         else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE)
36                 return "SKIP";
37
38         return "unknown";
39 }
40
41 static void
42 _print_validate_result(tdm_virtual_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
43 {
44         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
45         int i;
46
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");
56                         break;
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");
66                         break;
67                 default:
68                         break;
69                 }
70         }
71 }
72
73 static tbm_surface_queue_h
74 _virtual_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
75 {
76         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
77         tbm_surface_queue_h tqueue = NULL;
78         int width, height;
79         tbm_format format;
80
81         if (error)
82                 *error = TDM_ERROR_INVALID_PARAMETER;
83
84         RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
85
86         hwc_window_data = hwc_window;
87
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;
91
92         tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT);
93         if (error)
94                 *error = TDM_ERROR_OPERATION_FAILED;
95         RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
96
97         if (error)
98                 *error = TDM_ERROR_NONE;
99
100         return tqueue;
101 }
102
103 static tdm_error
104 _virtual_hwc_layer_attach_window(tdm_virtual_layer_data *layer_data, tdm_virtual_hwc_window_data *hwc_window_data)
105 {
106         tdm_error ret = TDM_ERROR_NONE;
107
108         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
109
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);
114         } else {
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);
120         }
121
122         return ret;
123 }
124
125 static tdm_error
126 _virtual_hwc_prepare_commit(tdm_virtual_hwc_data *hwc_data)
127 {
128         tdm_virtual_layer_data *layer_data = NULL;
129         int use_layers_zpos[NUM_LAYERS] = {0,};
130         int lzpos = 0;
131
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;
137         }
138
139         /* unset the unused layers */
140         for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
141                 if (use_layers_zpos[lzpos])
142                         continue;
143
144                 layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, lzpos);
145                 if (!layer_data)
146                         continue;
147
148                 _virtual_hwc_layer_attach_window(layer_data, NULL);
149         }
150
151         /* for debug */
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");
155         }
156
157         return TDM_ERROR_NONE;
158 }
159
160 /* assign the validated_type to the composited_wnds
161  * assign the layer_zpos to the composited_wnds
162  */
163 static void
164 _virtual_hwc_apply_policy(tdm_virtual_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
165 {
166         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
167         tdm_virtual_hwc_window_data **composited_list = NULL;
168         int i = 0;
169
170         composited_list = (tdm_virtual_hwc_window_data **)composited_wnds;
171
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;
176         }
177
178         /* use the target_window to commit when there is no window. */
179         if (num_wnds == 0) {
180                 hwc_data->need_target_window = 1;
181                 hwc_data->target_hwc_window->lzpos = ZPOS_0;
182                 return;
183         }
184
185         /* use onyl 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;
189         }
190
191         hwc_data->need_target_window = 1;
192         hwc_data->target_hwc_window->lzpos = ZPOS_0;
193 }
194
195 static int
196 _virtual_hwc_get_changed_number(tdm_virtual_hwc_data *hwc_data)
197 {
198         int num = 0;
199         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
200
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)
203                         continue;
204
205                 if (hwc_window_data->client_type != hwc_window_data->validated_type)
206                         num++;
207         }
208
209         return num;
210 }
211
212 tdm_hwc_window *
213 _virtual_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
214 {
215         tdm_virtual_hwc_data *hwc_data = hwc;
216         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
217
218         if (error)
219                 *error = TDM_ERROR_NONE;
220
221         if (!hwc_data) {
222                 TDM_ERR("invalid params");
223                 if (error)
224                         *error = TDM_ERROR_INVALID_PARAMETER;
225                 return NULL;
226         }
227
228         hwc_window_data = calloc(1, sizeof(tdm_virtual_hwc_window_data));
229         if (!hwc_window_data) {
230                 TDM_ERR("alloc failed");
231                 if (error)
232                         *error = TDM_ERROR_OUT_OF_MEMORY;
233                 return NULL;
234         }
235
236         hwc_window_data->hwc_data = hwc_data;
237
238         if (info)
239                 memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
240
241         LIST_INITHEAD(&hwc_window_data->link);
242
243         return hwc_window_data;
244 }
245
246 tdm_hwc_window *
247 virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
248 {
249         tdm_virtual_hwc_data *hwc_data = hwc;
250         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
251
252         RETURN_VAL_IF_FAIL(hwc_data, NULL);
253
254         hwc_window_data = _virtual_hwc_create_window(hwc_data, NULL, error);
255         RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
256
257         LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
258
259         TDM_DBG("hwc_window(%p) create", hwc_window_data);
260         if (error)
261                 *error = TDM_ERROR_NONE;
262
263         return hwc_window_data;
264 }
265
266 tdm_error
267 virtual_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
268 {
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);
272
273         // TODO: fix these formats.
274         *formats = hwc_window_video_formats;
275         *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
276
277         return TDM_ERROR_NONE;
278 }
279
280 tdm_error
281 virtual_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
282 {
283         RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
284         RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
285
286         *capabilities = 0;
287
288         return TDM_ERROR_NONE;
289 }
290
291 tdm_error
292 virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
293 {
294         tdm_virtual_hwc_data *hwc_data = hwc;
295
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);
299
300         *props = NULL;
301         *count = 0;
302
303         return TDM_ERROR_NONE;
304 }
305
306 tbm_surface_queue_h
307 virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
308 {
309         tdm_virtual_hwc_data *hwc_data = hwc;
310         tbm_surface_queue_h tqueue = NULL;
311
312         if (error)
313                 *error = TDM_ERROR_INVALID_PARAMETER;
314
315         RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
316
317         if (hwc_data->target_hwc_window == NULL) {
318                 if (error)
319                         *error = TDM_ERROR_OPERATION_FAILED;
320                 return NULL;
321         }
322
323         tqueue = _virtual_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
324         RETURN_VAL_IF_FAIL(tqueue, NULL);
325
326         if (error)
327                 *error = TDM_ERROR_NONE;
328
329         return tqueue;
330 }
331
332 tdm_error
333 virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
334 {
335         tdm_virtual_hwc_data *hwc_data = hwc;
336         tdm_error err;
337
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);
340
341         TDM_INFO(" ==============Set Target Buffer Virtual=================================");
342
343         err = virtual_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
344         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
345
346         err = virtual_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
347         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
348
349         return TDM_ERROR_NONE;
350 }
351
352 tdm_error
353 virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
354 {
355         tdm_virtual_hwc_data *hwc_data = hwc;
356
357         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
358         RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
359
360         TDM_DBG(" ==============Validate Virtual=================================");
361
362         _virtual_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
363
364         *num_types = _virtual_hwc_get_changed_number(hwc_data);
365
366         _print_validate_result(hwc_data, composited_wnds, num_wnds);
367
368         return TDM_ERROR_NONE;
369 }
370
371 tdm_error
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)
374 {
375         tdm_virtual_hwc_data *hwc_data = hwc;
376         tdm_virtual_hwc_window_data *hwc_window_data = NULL;
377         int num = 0;
378
379         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
380         RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
381
382         if ((hwc_wnds == NULL) || (composition_types == NULL)) {
383                 *num_elements = _virtual_hwc_get_changed_number(hwc_data);
384                 return TDM_ERROR_NONE;
385         }
386
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)
389                         continue;
390
391                 if (num >= *num_elements)
392                         break;
393
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;
397                         num++;
398                 }
399         }
400
401         /* set real num of changed composition types */
402         *num_elements = num;
403
404         return TDM_ERROR_NONE;
405 }
406
407 tdm_error
408 virtual_hwc_accept_validation(tdm_hwc *hwc)
409 {
410         tdm_virtual_hwc_data *hwc_data = hwc;
411         tdm_error ret = TDM_ERROR_NONE;
412
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);
415
416         TDM_DBG(" ==============Accept Changes Done Virtual=================================");
417
418         ret = _virtual_hwc_prepare_commit(hwc_data);
419         RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
420
421         return TDM_ERROR_NONE;
422 }
423
424 tdm_error
425 virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
426 {
427         tdm_virtual_hwc_data *hwc_data = hwc;
428         tdm_virtual_output_data *output_data = NULL;
429         tdm_error ret;
430
431         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
432
433         output_data = hwc_data->output_data;
434         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
435
436         TDM_INFO(" ==============COMMIT Virtual=================================");
437
438         ret = virtual_output_commit(output_data, sync, user_data);
439         RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
440
441         return TDM_ERROR_NONE;
442 }
443
444 tdm_error
445 virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
446 {
447         tdm_virtual_hwc_data *hwc_data = hwc;
448
449         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
450         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
451
452         hwc_data->commit_func = func;
453
454         return TDM_ERROR_NONE;
455 }
456
457 tdm_error
458 virtual_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
459 {
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;
464
465         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
466
467         info.dst_pos.x = 0;
468         info.dst_pos.y = 0;
469         info.dst_pos.h = height;
470         info.dst_pos.w = width;
471
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;
476
477         info.src_config.size.h = width;
478         info.src_config.size.v = height;
479         info.src_config.format = TBM_FORMAT_ARGB8888;
480
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;
485         }
486
487         if (hwc_data->target_hwc_window)
488                 virtual_hwc_window_destroy(hwc_data->target_hwc_window);
489
490         hwc_data->target_hwc_window = target_hwc_window;
491         hwc_data->need_set_crtc = 1;
492
493         return TDM_ERROR_NONE;
494 }