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