make the target_window info get the proper w/h.
[platform/adaptation/broadcom/libtdm-vc4.git] / src / tdm_vc4_hwc.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <tdm_helper.h>
6 #include "tdm_vc4.h"
7
8 #define MIN_WIDTH      32
9
10 #define NUM_LAYERS     4
11 #define NUM_BUFFERS    3
12
13 #define NUM_UI_LAYERS  3
14
15 #define ZPOS_MAX       4
16 #define ZPOS_CURSOR    3
17 #define ZPOS_2         2
18 #define ZPOS_1         1
19 #define ZPOS_0         0
20 #define ZPOS_VIDEO1    0
21 #define ZPOS_NONE      -999
22
23 tbm_format hwc_window_video_formats[] = {
24         TBM_FORMAT_NV12,
25         TBM_FORMAT_YUV420
26 };
27
28 const char *
29 _comp_to_str(tdm_hwc_window_composition composition_type)
30 {
31         if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
32                 return "CLIENT";
33         else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
34                 return "DEVICE";
35         else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
36                 return "CURSOR";
37         else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
38                 return "VIDEO";
39         else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE)
40                 return "SKIP";
41
42         return "unknown";
43 }
44
45 static int
46 _vc4_hwc_cursor_buffer_unset(tdm_vc4_hwc_window_data *hwc_window_data)
47 {
48         hwc_window_data->surface = NULL;
49         hwc_window_data->cursor_img_surface = 0;
50
51         hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width;
52         hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height;
53         hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width;
54         hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height;
55
56         return 1;
57 }
58
59 static void
60 _vc4_hwc_cursor_adjust_pos(tdm_vc4_hwc_window_data *hwc_window_data)
61 {
62         int x, y;
63
64         /* dst pos of cursor is possible set by negative value
65          * this is temporary code.
66          */
67
68         x = hwc_window_data->info.dst_pos.x;
69         y = hwc_window_data->info.dst_pos.y;
70
71         if (x < 0) hwc_window_data->info.dst_pos.x = 0;
72         if (y < 0) hwc_window_data->info.dst_pos.y = 0;
73 }
74
75 static int
76 _vc4_hwc_cursor_buffer_set(tdm_vc4_hwc_data *hwc_data, tdm_vc4_hwc_window_data *hwc_window_data)
77 {
78         tbm_surface_h cursor_tsurface = NULL;
79         tbm_surface_info_s tsurface_info;
80         tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE;
81         int img_w, img_h, new_w, new_h;
82         tbm_format new_format;
83         unsigned int flags = TBM_BO_SCANOUT;
84         void *src_ptr = NULL, *dst_ptr = NULL;
85         int src_stride;
86         int i;
87
88         _vc4_hwc_cursor_adjust_pos(hwc_window_data);
89
90         if (!hwc_window_data->cursor_img_refresh && hwc_window_data->surface)
91                 return 1;
92
93         img_w = hwc_window_data->cursor_img.width;
94         img_h = hwc_window_data->cursor_img.height;
95         new_format = hwc_window_data->info.src_config.format;
96
97         /* cursor restriction to set the cursor layer */
98         new_w = (CURSOR_MIN_W > img_w) ? CURSOR_MIN_W : img_w;
99         new_h = (CURSOR_MIN_H > img_h) ? CURSOR_MIN_H : img_h;
100
101         if (hwc_data->cursor_tsurface) {
102                 tbm_surface_internal_unref(hwc_data->cursor_tsurface);
103                 hwc_data->cursor_tsurface = NULL;
104         }
105
106         cursor_tsurface = tbm_surface_internal_create_with_flags(new_w, new_h, new_format, flags);
107         RETURN_VAL_IF_FAIL(cursor_tsurface, 0);
108
109         hwc_data->cursor_tsurface = cursor_tsurface;
110         ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info);
111         if (ret != TBM_SURFACE_ERROR_NONE) {
112                 TDM_ERR("Failed to map tsurface\n");
113                 tbm_surface_internal_unref(hwc_data->cursor_tsurface);
114                 hwc_data->cursor_tsurface = NULL;
115                 return 0;
116         }
117
118         src_ptr = hwc_window_data->cursor_img.ptr;
119         dst_ptr = tsurface_info.planes[0].ptr;
120         src_stride = hwc_window_data->cursor_img.stride;
121
122         memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height);
123
124         for (i = 0 ; i < img_h ; i++) {
125                 memcpy(dst_ptr, src_ptr, src_stride);
126                 dst_ptr += tsurface_info.planes[0].stride;
127                 src_ptr += src_stride;
128         }
129
130         tbm_surface_unmap(hwc_data->cursor_tsurface);
131
132         hwc_window_data->surface = hwc_data->cursor_tsurface;
133         hwc_window_data->cursor_img_surface = 1;
134
135         /* fix the dst_pos info of the cursor window */
136         hwc_window_data->info.src_config.pos.w = new_w;
137         hwc_window_data->info.src_config.pos.h = new_h;
138         hwc_window_data->info.dst_pos.w = new_w;
139         hwc_window_data->info.dst_pos.h = new_h;
140
141         hwc_window_data->cursor_img_refresh = 0;
142
143         return 1;
144 }
145
146 static void
147 _print_validate_result(tdm_vc4_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
148 {
149         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
150         int i;
151
152         for (i = 0; i < num_wnds; i++) {
153                 hwc_window_data = composited_wnds[i];
154                 switch (hwc_window_data->validated_type) {
155                 case TDM_HWC_WIN_COMPOSITION_CLIENT:
156                         TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s} on TARGET WINDOW", hwc_window_data,
157                                         _comp_to_str(hwc_window_data->client_type),
158                                         _comp_to_str(hwc_window_data->validated_type),
159                                         hwc_data->target_hwc_window->lzpos,
160                                         hwc_window_data->name ? hwc_window_data->name : "NONE");
161                         break;
162                 case TDM_HWC_WIN_COMPOSITION_DEVICE:
163                 case TDM_HWC_WIN_COMPOSITION_VIDEO:
164                 case TDM_HWC_WIN_COMPOSITION_CURSOR:
165                 case TDM_HWC_WIN_COMPOSITION_NONE:
166                         TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s}", hwc_window_data,
167                                         _comp_to_str(hwc_window_data->client_type),
168                                         _comp_to_str(hwc_window_data->validated_type),
169                                         hwc_window_data->lzpos,
170                                         hwc_window_data->name ? hwc_window_data->name : "NONE");
171                         break;
172                 default:
173                         break;
174                 }
175         }
176 }
177
178 static int
179 _vc4_hwc_window_can_set_on_hw_layer(tdm_vc4_hwc_window_data *hwc_window_data)
180 {
181         if (!hwc_window_data->surface)
182                 return 0;
183
184         if (hwc_window_data->info.transform != TDM_TRANSFORM_NORMAL)
185                 return 0;
186
187         if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w)
188                 return 0;
189
190         if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h)
191                 return 0;
192
193         if (!IS_RGB(hwc_window_data->info.src_config.format))
194                 return 0;
195
196         if (hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay ||
197                 hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)
198                 return 0;
199
200         if (hwc_window_data->info.src_config.pos.w < MIN_WIDTH || hwc_window_data->info.src_config.pos.w % 2)
201                 return 0;
202
203         return 1;
204 }
205
206 static tbm_surface_queue_h
207 _vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
208 {
209         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
210         tbm_surface_queue_h tqueue = NULL;
211         int width, height;
212         tbm_format format;
213
214         if (error)
215                 *error = TDM_ERROR_INVALID_PARAMETER;
216
217         RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
218
219         hwc_window_data = hwc_window;
220
221         width = hwc_window_data->info.src_config.size.h;
222         height = hwc_window_data->info.src_config.size.v;
223         format = hwc_window_data->info.src_config.format;
224
225         tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT);
226         if (error)
227                 *error = TDM_ERROR_OPERATION_FAILED;
228         RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
229
230         if (error)
231                 *error = TDM_ERROR_NONE;
232
233         return tqueue;
234 }
235
236 static tdm_error
237 _vc4_hwc_layer_attach_window(tdm_vc4_layer_data *layer_data, tdm_vc4_hwc_window_data *hwc_window_data)
238 {
239         tdm_error ret = TDM_ERROR_NONE;
240
241         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
242
243         if (hwc_window_data == NULL || hwc_window_data->surface == NULL) {
244                 if (layer_data->display_buffer)
245                         ret = vc4_layer_unset_buffer(layer_data);
246                 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
247         } else {
248                 ret = vc4_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
249                 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
250                 RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
251                 ret = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
252                 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
253         }
254
255         return ret;
256 }
257
258 static tdm_error
259 _vc4_hwc_prepare_commit(tdm_vc4_hwc_data *hwc_data)
260 {
261         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
262         tdm_vc4_layer_data *layer_data = NULL;
263         int use_layers_zpos[NUM_LAYERS] = {0,};
264         int lzpos = 0;
265
266         /* set target hwc window to the layer */
267         if (hwc_data->need_target_window) {
268                 layer_data = vc4_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
269                 _vc4_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
270                 use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
271         }
272
273         /* set the hwc_windows to the layers */
274         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
275                 if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_NONE ||
276                         hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CLIENT) {
277
278                         if (hwc_window_data->cursor_img_surface)
279                                 _vc4_hwc_cursor_buffer_unset(hwc_window_data);
280
281                         continue;
282                 }
283
284                 if (hwc_window_data == hwc_data->target_hwc_window)
285                         continue;
286
287                 /* set the cursor buffer HERE if it needs */
288                 if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
289                         _vc4_hwc_cursor_buffer_set(hwc_data, hwc_window_data);
290
291                 layer_data = vc4_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos);
292                 _vc4_hwc_layer_attach_window(layer_data, hwc_window_data);
293                 use_layers_zpos[hwc_window_data->lzpos] = 1;
294         }
295
296         /* unset the unused layers */
297         for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
298                 if (use_layers_zpos[lzpos])
299                         continue;
300
301                 layer_data = vc4_output_data_get_layer_data(hwc_data->output_data, lzpos);
302                 if (!layer_data)
303                         continue;
304
305                 _vc4_hwc_layer_attach_window(layer_data, NULL);
306         }
307
308         /* for debug */
309         for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) {
310                 if (use_layers_zpos[lzpos])
311                         TDM_DBG(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET");
312         }
313
314         return TDM_ERROR_NONE;
315 }
316
317 /* assign the validated_type to the composited_wnds
318  * assign the layer_zpos to the composited_wnds
319  */
320 static void
321 _vc4_hwc_apply_policy(tdm_vc4_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
322 {
323         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
324         tdm_vc4_hwc_window_data **composited_list = NULL;
325         int client_count = 0;
326         int device_count = 0;
327         int video_count = 0;
328         int cursor_count = 0;
329         int ui_lzpos_top = ZPOS_2;
330         int ui_lzpos_bottom = ZPOS_0;
331         int num_ui_layers = NUM_UI_LAYERS;
332         int set_clients_below = 0;
333         int i = 0;
334
335         composited_list = (tdm_vc4_hwc_window_data **)composited_wnds;
336
337         /* initialize the need_target_window */
338         hwc_data->need_target_window = 0;
339
340         /* initialize the validated_types */
341         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
342                 if (hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_NONE)
343                         hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE;
344         }
345
346         /* use the target_window to commit when there is no window. */
347         if (num_wnds == 0) {
348                 hwc_data->need_target_window = 1;
349                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
350                 return;
351         }
352
353         /* 1. first check validate_type without target_window */
354         for (i = 0; i < num_wnds; i++) {
355                 switch (composited_list[i]->client_type) {
356                 case TDM_HWC_WIN_COMPOSITION_VIDEO:
357                         composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_VIDEO;
358                         video_count++;
359                         continue;
360                 case TDM_HWC_WIN_COMPOSITION_CURSOR:
361                         if (set_clients_below) break;
362                         if (cursor_count > 0) break;
363
364                         composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CURSOR;
365                         cursor_count++;
366                         continue;
367                 case TDM_HWC_WIN_COMPOSITION_DEVICE:
368                         if (set_clients_below) break;
369                         if (num_ui_layers <= 0) break;
370                         if (!_vc4_hwc_window_can_set_on_hw_layer(composited_list[i])) break;
371
372                         composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_DEVICE;
373                         device_count++;
374                         num_ui_layers--;
375                         continue;
376                 default:
377                         break;
378                 }
379
380                 composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
381                 client_count++;
382                 set_clients_below = 1;
383         }
384
385         /* 2. check need target window and set ui_lzpos top and bottom */
386         num_ui_layers = NUM_UI_LAYERS;
387
388         if (video_count > 0) {
389                 ui_lzpos_bottom++;
390                 num_ui_layers--;
391         }
392
393         if (client_count > 0) {
394                 ui_lzpos_bottom++;
395                 num_ui_layers--;
396                 hwc_data->need_target_window = 1;
397                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom - 1;
398         }
399
400         if (num_ui_layers > device_count)
401                 ui_lzpos_top = ui_lzpos_bottom + device_count - 1;
402
403         /* 3. set lzpos and modify validate_type with target_window */
404         for (i = 0; i < num_wnds; i++) {
405                 switch (composited_list[i]->validated_type) {
406                 case TDM_HWC_WIN_COMPOSITION_VIDEO:
407                         composited_list[i]->lzpos = ZPOS_VIDEO1;
408                         continue;
409                 case TDM_HWC_WIN_COMPOSITION_CURSOR:
410                         composited_list[i]->lzpos = ZPOS_CURSOR;
411                         continue;
412                 case TDM_HWC_WIN_COMPOSITION_DEVICE:
413                         if (num_ui_layers <= 0) break;
414                         composited_list[i]->lzpos = ui_lzpos_top;
415                         ui_lzpos_top--;
416                         num_ui_layers--;
417                         continue;
418                 default:
419                         break;
420                 }
421
422                 composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
423                 composited_list[i]->lzpos = ZPOS_NONE;
424         }
425 }
426
427 static int
428 _vc4_hwc_get_changed_number(tdm_vc4_hwc_data *hwc_data)
429 {
430         int num = 0;
431         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
432
433         LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
434                 if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
435                         continue;
436
437                 if (hwc_window_data->client_type != hwc_window_data->validated_type)
438                         num++;
439         }
440
441         return num;
442 }
443
444 tdm_hwc_window *
445 _vc4_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
446 {
447         tdm_vc4_hwc_data *hwc_data = hwc;
448         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
449
450         if (error)
451                 *error = TDM_ERROR_NONE;
452
453         if (!hwc_data) {
454                 TDM_ERR("invalid params");
455                 if (error)
456                         *error = TDM_ERROR_INVALID_PARAMETER;
457                 return NULL;
458         }
459
460         hwc_window_data = calloc(1, sizeof(tdm_vc4_hwc_window_data));
461         if (!hwc_window_data) {
462                 TDM_ERR("alloc failed");
463                 if (error)
464                         *error = TDM_ERROR_OUT_OF_MEMORY;
465                 return NULL;
466         }
467
468         hwc_window_data->hwc_data = hwc_data;
469
470         if (info)
471                 memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
472
473         LIST_INITHEAD(&hwc_window_data->link);
474
475         return hwc_window_data;
476 }
477
478 tdm_hwc_window *
479 vc4_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
480 {
481         tdm_vc4_hwc_data *hwc_data = hwc;
482         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
483
484         RETURN_VAL_IF_FAIL(hwc_data, NULL);
485
486         hwc_window_data = _vc4_hwc_create_window(hwc_data, NULL, error);
487         RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
488
489         LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
490
491         TDM_DBG("hwc_window(%p) create", hwc_window_data);
492         if (error)
493                 *error = TDM_ERROR_NONE;
494
495         return hwc_window_data;
496 }
497
498 tdm_error
499 vc4_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
500 {
501         RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
502         RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
503         RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
504
505         // TODO: fix these formats.
506         *formats = hwc_window_video_formats;
507         *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
508
509         return TDM_ERROR_NONE;
510 }
511
512 tdm_error
513 vc4_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
514 {
515         RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
516         RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
517
518         *capabilities |= TDM_HWC_CAPABILITY_VIDEO_SCALE;
519
520         return TDM_ERROR_NONE;
521 }
522
523 tdm_error
524 vc4_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
525 {
526         tdm_vc4_hwc_data *hwc_data = hwc;
527
528         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
529         RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
530         RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
531
532         *props = NULL;
533         *count = 0;
534
535         return TDM_ERROR_NONE;
536 }
537
538 tbm_surface_queue_h
539 vc4_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
540 {
541         tdm_vc4_hwc_data *hwc_data = hwc;
542         tbm_surface_queue_h tqueue = NULL;
543
544         if (error)
545                 *error = TDM_ERROR_INVALID_PARAMETER;
546
547         RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
548
549         if (hwc_data->target_hwc_window == NULL) {
550                 if (error)
551                         *error = TDM_ERROR_OPERATION_FAILED;
552                 return NULL;
553         }
554
555         tqueue = _vc4_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
556         RETURN_VAL_IF_FAIL(tqueue, NULL);
557
558         if (error)
559                 *error = TDM_ERROR_NONE;
560
561         return tqueue;
562 }
563
564 tdm_error
565 vc4_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
566 {
567         tdm_vc4_hwc_data *hwc_data = hwc;
568         tdm_error err;
569
570         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
571         RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window  != NULL, TDM_ERROR_OPERATION_FAILED);
572
573         err = vc4_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
574         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
575
576         err = vc4_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
577         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
578
579         return TDM_ERROR_NONE;
580 }
581
582 tdm_error
583 vc4_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
584 {
585         tdm_vc4_hwc_data *hwc_data = hwc;
586
587         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
588         RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
589
590         TDM_INFO(" ==============Validate=================================");
591
592         _vc4_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
593
594         *num_types = _vc4_hwc_get_changed_number(hwc_data);
595
596         _print_validate_result(hwc_data, composited_wnds, num_wnds);
597
598         return TDM_ERROR_NONE;
599 }
600
601 tdm_error
602 vc4_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
603                                 tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types)
604 {
605         tdm_vc4_hwc_data *hwc_data = hwc;
606         tdm_vc4_hwc_window_data *hwc_window_data = NULL;
607         int num = 0;
608
609         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
610         RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
611
612         if ((hwc_wnds == NULL) || (composition_types == NULL)) {
613                 *num_elements = _vc4_hwc_get_changed_number(hwc_data);
614                 return TDM_ERROR_NONE;
615         }
616
617         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
618                 if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
619                         continue;
620
621                 if (num >= *num_elements)
622                         break;
623
624                 if (hwc_window_data->client_type != hwc_window_data->validated_type) {
625                         composition_types[num] = hwc_window_data->validated_type;
626                         hwc_wnds[num] = hwc_window_data;
627                         num++;
628                 }
629         }
630
631         /* set real num of changed composition types */
632         *num_elements = num;
633
634         return TDM_ERROR_NONE;
635 }
636
637 tdm_error
638 vc4_hwc_accept_validation(tdm_hwc *hwc)
639 {
640         tdm_vc4_hwc_data *hwc_data = hwc;
641         tdm_error ret = TDM_ERROR_NONE;
642
643         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
644         RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
645
646         TDM_DBG(" ==============Accept Changes Done=================================");
647
648         ret = _vc4_hwc_prepare_commit(hwc_data);
649         RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
650
651         return TDM_ERROR_NONE;
652 }
653
654 tdm_error
655 vc4_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
656 {
657         tdm_vc4_hwc_data *hwc_data = hwc;
658         tdm_vc4_output_data *output_data = NULL;
659         tdm_error ret;
660
661         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
662
663         output_data = hwc_data->output_data;
664         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
665
666         TDM_INFO(" ==============COMMIT=================================");
667
668         ret = vc4_output_commit(output_data, sync, user_data);
669         RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
670
671         return TDM_ERROR_NONE;
672 }
673
674 tdm_error
675 vc4_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
676 {
677         tdm_vc4_hwc_data *hwc_data = hwc;
678
679         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
680         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
681
682         hwc_data->commit_func = func;
683
684         return TDM_ERROR_NONE;
685 }
686
687 tdm_error
688 vc4_hwc_target_window_set_info(tdm_vc4_hwc_data *hwc_data, int width, int height)
689 {
690         tdm_hwc_window_info info = {0};
691         tdm_vc4_hwc_window_data *target_hwc_window;
692         tdm_error ret = TDM_ERROR_NONE;
693
694         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
695         RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, TDM_ERROR_INVALID_PARAMETER);
696
697         target_hwc_window = hwc_data->target_hwc_window;
698
699         info.dst_pos.x = 0;
700         info.dst_pos.y = 0;
701         info.dst_pos.w = width;
702         info.dst_pos.h = height;
703
704         info.src_config.pos.x = 0;
705         info.src_config.pos.y = 0;
706         info.src_config.pos.w = width;
707         info.src_config.pos.h = height;
708
709         info.src_config.size.h = width;
710         info.src_config.size.v = height;
711         info.src_config.format = TBM_FORMAT_ARGB8888;
712
713         ret = vc4_hwc_window_set_info(target_hwc_window, &info);
714         if (ret != TDM_ERROR_NONE) {
715                 TDM_ERR("set info target hwc window failed (%d)", ret);
716                 return TDM_ERROR_OPERATION_FAILED;
717         }
718
719         return TDM_ERROR_NONE;
720 }
721
722 tdm_error
723 vc4_hwc_initailize_target_window(tdm_vc4_hwc_data *hwc_data)
724 {
725         tdm_hwc_window_info info = {0};
726         tdm_error ret = TDM_ERROR_NONE;
727         tdm_vc4_hwc_window_data *target_hwc_window;
728
729         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
730
731         info.dst_pos.x = 0;
732         info.dst_pos.y = 0;
733         info.dst_pos.w = 1;
734         info.dst_pos.h = 2;
735
736         info.src_config.pos.x = 0;
737         info.src_config.pos.y = 0;
738         info.src_config.pos.w = 1;
739         info.src_config.pos.h = 2;
740
741         info.src_config.size.h = 2;
742         info.src_config.size.v = 1;
743         info.src_config.format = TBM_FORMAT_ARGB8888;
744
745         target_hwc_window = _vc4_hwc_create_window(hwc_data, &info, &ret);
746         if (ret != TDM_ERROR_NONE) {
747                 TDM_ERR("create target hwc window failed (%d)", ret);
748                 return TDM_ERROR_OPERATION_FAILED;
749         }
750
751         if (hwc_data->target_hwc_window)
752                 vc4_hwc_window_destroy(hwc_data->target_hwc_window);
753
754         hwc_data->target_hwc_window = target_hwc_window;
755         hwc_data->need_set_crtc = 1;
756
757         return TDM_ERROR_NONE;
758 }