00a3c5bc2f4efcc0dcc1b4ed329adbeb3dbf961a
[platform/adaptation/libtdm-drm.git] / src / libhal-backend-tdm-drm / tdm_drm_hwc.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "tdm_backend_drm.h"
6
7 #define MIN_WIDTH      32
8
9 #define NUM_LAYERS     4
10 #define NUM_BUFFERS    3
11
12 #define NUM_UI_LAYERS  1
13
14 #define ZPOS_MAX       1
15 #define ZPOS_CURSOR    2
16 #define ZPOS_1         1
17 #define ZPOS_0         0
18 #define ZPOS_VIDEO1    0
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(hal_tdm_hwc_window_composition composition_type)
28 {
29         if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT)
30                 return "CLIENT";
31         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_DEVICE)
32                 return "DEVICE";
33         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR)
34                 return "CURSOR";
35         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_VIDEO)
36                 return "VIDEO";
37         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
38                 return "SKIP";
39
40         return "unknown";
41 }
42
43 static int
44 _drm_hwc_cursor_buffer_unset(tdm_drm_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 _drm_hwc_cursor_adjust_pos(tdm_drm_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 _drm_hwc_cursor_buffer_set(tdm_drm_hwc *hwc_data, tdm_drm_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         _drm_hwc_cursor_adjust_pos(hwc_window_data);
87
88         if (!hwc_window_data->cursor_img_refresh && hwc_window_data->surface)
89                 return 1;
90
91         img_w = hwc_window_data->cursor_img.width;
92         img_h = hwc_window_data->cursor_img.height;
93         new_format = hwc_window_data->info.src_config.format;
94
95         /* cursor restriction to set the cursor layer */
96         new_w = (CURSOR_MIN_W > img_w) ? CURSOR_MIN_W : img_w;
97         new_h = (CURSOR_MIN_H > img_h) ? CURSOR_MIN_H : img_h;
98
99         if (hwc_data->cursor_tsurface) {
100                 tbm_surface_internal_unref(hwc_data->cursor_tsurface);
101                 hwc_data->cursor_tsurface = NULL;
102         }
103
104         cursor_tsurface = tbm_surface_internal_create_with_flags(new_w, new_h, new_format, flags);
105         RETURN_VAL_IF_FAIL(cursor_tsurface, 0);
106
107         hwc_data->cursor_tsurface = cursor_tsurface;
108         ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info);
109         if (ret != TBM_SURFACE_ERROR_NONE) {
110                 TDM_BACKEND_ERR("Failed to map tsurface\n");
111                 tbm_surface_internal_unref(hwc_data->cursor_tsurface);
112                 hwc_data->cursor_tsurface = NULL;
113                 return 0;
114         }
115
116         src_ptr = hwc_window_data->cursor_img.ptr;
117         dst_ptr = tsurface_info.planes[0].ptr;
118         src_stride = hwc_window_data->cursor_img.stride;
119
120         memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height);
121
122         for (i = 0 ; i < img_h ; i++) {
123                 memcpy(dst_ptr, src_ptr, src_stride);
124                 dst_ptr += tsurface_info.planes[0].stride;
125                 src_ptr += src_stride;
126         }
127
128         tbm_surface_unmap(hwc_data->cursor_tsurface);
129
130         hwc_window_data->surface = hwc_data->cursor_tsurface;
131         hwc_window_data->cursor_img_surface = 1;
132
133         /* fix the dst_pos info of the cursor window */
134         hwc_window_data->info.src_config.pos.w = new_w;
135         hwc_window_data->info.src_config.pos.h = new_h;
136         hwc_window_data->info.dst_pos.w = new_w;
137         hwc_window_data->info.dst_pos.h = new_h;
138
139         hwc_window_data->cursor_img_refresh = 0;
140
141         return 1;
142 }
143
144 static void
145 _print_validate_result(tdm_drm_hwc *hwc_data, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds)
146 {
147         tdm_drm_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 HAL_TDM_HWC_WIN_COMPOSITION_CLIENT:
154                         TDM_BACKEND_INFO(" 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 HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
161                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
162                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
163                 case HAL_TDM_HWC_WIN_COMPOSITION_NONE:
164                         TDM_BACKEND_INFO(" 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 _drm_hwc_window_can_set_on_hw_layer(tdm_drm_hwc_window_data *hwc_window_data)
178 {
179         if (!hwc_window_data->surface)
180                 return 0;
181
182         if (hwc_window_data->info.transform != HAL_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 _drm_hwc_window_get_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error)
206 {
207         tdm_drm_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 = HAL_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 = HAL_TDM_ERROR_OPERATION_FAILED;
226         RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
227
228         if (error)
229                 *error = HAL_TDM_ERROR_NONE;
230
231         return tqueue;
232 }
233
234 static hal_tdm_error
235 _drm_hwc_layer_attach_window(tdm_drm_layer *layer_data, tdm_drm_hwc_window_data *hwc_window_data)
236 {
237         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
238
239         RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_OPERATION_FAILED);
240
241         if (hwc_window_data == NULL || hwc_window_data->surface == NULL) {
242                 if (layer_data->display_buffer)
243                         ret = drm_layer_unset_buffer(layer_data);
244                 RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
245         } else {
246                 ret = drm_layer_set_info((tdm_drm_layer *)layer_data, (tdm_drm_layer_info *)&(hwc_window_data->info));
247                 RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
248                 RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
249                 ret = drm_layer_set_buffer(layer_data, hwc_window_data->surface);
250                 RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
251         }
252
253         return ret;
254 }
255
256 static hal_tdm_error
257 _drm_hwc_prepare_commit(tdm_drm_hwc *hwc_data)
258 {
259         tdm_drm_hwc_window_data *hwc_window_data = NULL;
260         tdm_drm_layer *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 = drm_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
267                 _drm_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 == HAL_TDM_HWC_WIN_COMPOSITION_NONE ||
274                         hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) {
275
276                         if (hwc_window_data->cursor_img_surface)
277                                 _drm_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 == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR)
287                         _drm_hwc_cursor_buffer_set(hwc_data, hwc_window_data);
288
289                 layer_data = drm_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos);
290                 _drm_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 = drm_output_data_get_layer_data(hwc_data->output_data, lzpos);
300                 if (!layer_data)
301                         continue;
302
303                 _drm_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_BACKEND_INFO(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET");
310         }
311
312         return HAL_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 _drm_hwc_apply_policy(tdm_drm_hwc *hwc_data , hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds)
320 {
321         tdm_drm_hwc_window_data *hwc_window_data = NULL;
322         tdm_drm_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 ui_lzpos_top = ZPOS_0;
328         int ui_lzpos_bottom = ZPOS_0;
329         int num_ui_layers = NUM_UI_LAYERS;
330         int set_clients_below = 0;
331         int i = 0;
332
333         composited_list = (tdm_drm_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 != HAL_TDM_HWC_WIN_COMPOSITION_NONE)
341                         hwc_window_data->validated_type = HAL_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                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
348                 return;
349         }
350
351         /* 1. first check validate_type without target_window */
352         for (i = 0; i < num_wnds; i++) {
353                 switch (composited_list[i]->client_type) {
354                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
355                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_VIDEO;
356                         video_count++;
357                         continue;
358                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
359                         if (set_clients_below) break;
360                         if (cursor_count > 0) break;
361
362                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CURSOR;
363                         cursor_count++;
364                         continue;
365                 case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
366                         if (set_clients_below) break;
367                         if (num_ui_layers <= 0) break;
368                         if (!_drm_hwc_window_can_set_on_hw_layer(composited_list[i])) break;
369
370                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_DEVICE;
371                         device_count++;
372                         num_ui_layers--;
373                         continue;
374                 default:
375                         break;
376                 }
377
378                 composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT;
379                 client_count++;
380                 set_clients_below = 1;
381         }
382
383         /* 2. check need target window and set ui_lzpos top and bottom */
384         num_ui_layers = NUM_UI_LAYERS;
385
386         if (video_count > 0) {
387                 ui_lzpos_bottom++;
388                 num_ui_layers--;
389         }
390
391         if (client_count > 0) {
392                 ui_lzpos_bottom++;
393                 num_ui_layers--;
394                 hwc_data->need_target_window = 1;
395                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom - 1;
396         }
397
398         if (num_ui_layers > device_count)
399                 ui_lzpos_top = ui_lzpos_bottom + device_count - 1;
400
401         /* 3. set lzpos and modify validate_type with target_window */
402         for (i = 0; i < num_wnds; i++) {
403                 switch (composited_list[i]->validated_type) {
404                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
405                         composited_list[i]->lzpos = ZPOS_VIDEO1;
406                         continue;
407                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
408                         composited_list[i]->lzpos = ZPOS_CURSOR;
409                         continue;
410                 case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
411                         if (num_ui_layers <= 0) break;
412                         composited_list[i]->lzpos = ui_lzpos_top;
413                         ui_lzpos_top--;
414                         num_ui_layers--;
415                         continue;
416                 default:
417                         break;
418                 }
419
420                 composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT;
421                 composited_list[i]->lzpos = ZPOS_NONE;
422         }
423 }
424
425 static int
426 _drm_hwc_get_changed_number(tdm_drm_hwc *hwc_data)
427 {
428         int num = 0;
429         tdm_drm_hwc_window_data *hwc_window_data = NULL;
430
431         LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
432                 if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
433                         continue;
434
435                 if (hwc_window_data->client_type != hwc_window_data->validated_type)
436                         num++;
437         }
438
439         return num;
440 }
441
442 hal_tdm_hwc_window *
443 _drm_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_hwc_window_info *info, hal_tdm_error *error)
444 {
445         tdm_drm_hwc *hwc_data = hwc;
446         tdm_drm_hwc_window_data *hwc_window_data = NULL;
447
448         if (error)
449                 *error = HAL_TDM_ERROR_NONE;
450
451         if (!hwc_data) {
452                 TDM_BACKEND_ERR("invalid params");
453                 if (error)
454                         *error = HAL_TDM_ERROR_INVALID_PARAMETER;
455                 return NULL;
456         }
457
458         hwc_window_data = calloc(1, sizeof(tdm_drm_hwc_window_data));
459         if (!hwc_window_data) {
460                 TDM_BACKEND_ERR("alloc failed");
461                 if (error)
462                         *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
463                 return NULL;
464         }
465
466         hwc_window_data->hwc_data = hwc_data;
467
468         if (info)
469                 memcpy(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info));
470
471         LIST_INITHEAD(&hwc_window_data->link);
472
473         return hwc_window_data;
474 }
475
476 hal_tdm_hwc_window *
477 drm_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error)
478 {
479         tdm_drm_hwc *hwc_data = hwc;
480         tdm_drm_hwc_window_data *hwc_window_data = NULL;
481
482         RETURN_VAL_IF_FAIL(hwc_data, NULL);
483
484         hwc_window_data = _drm_hwc_create_window(hwc_data, NULL, error);
485         RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
486
487         LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
488
489         TDM_BACKEND_INFO("hwc_window(%p) create", hwc_window_data);
490         if (error)
491                 *error = HAL_TDM_ERROR_NONE;
492
493         return hwc_window_data;
494 }
495
496 hal_tdm_error
497 drm_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count)
498 {
499         RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
500         RETURN_VAL_IF_FAIL(formats != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
501         RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
502
503         // TODO: fix these formats.
504         *formats = hwc_window_video_formats;
505         *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
506
507         return HAL_TDM_ERROR_NONE;
508 }
509
510 hal_tdm_error
511 drm_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities)
512 {
513         RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
514         RETURN_VAL_IF_FAIL(capabilities != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
515
516         *capabilities |= HAL_TDM_HWC_CAPABILITY_VIDEO_SCALE;
517
518         return HAL_TDM_ERROR_NONE;
519 }
520
521 hal_tdm_error
522 drm_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count)
523 {
524         tdm_drm_hwc *hwc_data = hwc;
525
526         RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
527         RETURN_VAL_IF_FAIL(props != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
528         RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
529
530         *props = NULL;
531         *count = 0;
532
533         return HAL_TDM_ERROR_NONE;
534 }
535
536 tbm_surface_queue_h
537 drm_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error)
538 {
539         tdm_drm_hwc *hwc_data = hwc;
540         tbm_surface_queue_h tqueue = NULL;
541
542         if (error)
543                 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
544
545         RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
546
547         if (hwc_data->target_hwc_window == NULL) {
548                 if (error)
549                         *error = HAL_TDM_ERROR_OPERATION_FAILED;
550                 return NULL;
551         }
552
553         tqueue = _drm_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
554         RETURN_VAL_IF_FAIL(tqueue, NULL);
555
556         if (error)
557                 *error = HAL_TDM_ERROR_NONE;
558
559         return tqueue;
560 }
561
562 hal_tdm_error
563 drm_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage)
564 {
565         tdm_drm_hwc *hwc_data = hwc;
566         hal_tdm_error err;
567
568         RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
569         RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window  != NULL, HAL_TDM_ERROR_OPERATION_FAILED);
570
571         err = drm_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
572         RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err);
573
574         err = drm_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
575         RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err);
576
577         return HAL_TDM_ERROR_NONE;
578 }
579
580 hal_tdm_error
581 drm_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
582 {
583         tdm_drm_hwc *hwc_data = hwc;
584         tdm_drm_output *output_data;
585
586         RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
587         RETURN_VAL_IF_FAIL(num_types != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
588
589         output_data = hwc_data->output_data;
590         RETURN_VAL_IF_FAIL(output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
591
592         TDM_BACKEND_INFO(" ==============Validate=================================");
593
594         _drm_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
595
596         *num_types = _drm_hwc_get_changed_number(hwc_data);
597
598         _print_validate_result(hwc_data, composited_wnds, num_wnds);
599
600         return HAL_TDM_ERROR_NONE;
601 }
602
603 hal_tdm_error
604 drm_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements,
605                                 hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types)
606 {
607         tdm_drm_hwc *hwc_data = hwc;
608         tdm_drm_hwc_window_data *hwc_window_data = NULL;
609         int num = 0;
610
611         RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
612         RETURN_VAL_IF_FAIL(num_elements != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
613
614         if ((hwc_wnds == NULL) || (composition_types == NULL)) {
615                 *num_elements = _drm_hwc_get_changed_number(hwc_data);
616                 return HAL_TDM_ERROR_NONE;
617         }
618
619         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
620                 if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
621                         continue;
622
623                 if (num >= *num_elements)
624                         break;
625
626                 if (hwc_window_data->client_type != hwc_window_data->validated_type) {
627                         composition_types[num] = hwc_window_data->validated_type;
628                         hwc_wnds[num] = hwc_window_data;
629                         num++;
630                 }
631         }
632
633         /* set real num of changed composition types */
634         *num_elements = num;
635
636         return HAL_TDM_ERROR_NONE;
637 }
638
639 hal_tdm_error
640 drm_hwc_accept_validation(hal_tdm_hwc *hwc)
641 {
642         tdm_drm_hwc *hwc_data = hwc;
643         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
644
645         RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
646         RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
647
648         TDM_BACKEND_INFO(" ==============Accept Changes Done=================================");
649
650         if (hwc_data->output_data->current_dpms != HAL_TDM_OUTPUT_DPMS_ON) {
651                 TDM_BACKEND_ERR("dpms is not on. do not set buffer");
652                 return HAL_TDM_ERROR_BAD_REQUEST;
653         }
654
655         ret = _drm_hwc_prepare_commit(hwc_data);
656         RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
657
658         return HAL_TDM_ERROR_NONE;
659 }
660
661 hal_tdm_error
662 drm_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data)
663 {
664         tdm_drm_hwc *hwc_data = hwc;
665         tdm_drm_output *output_data = NULL;
666         hal_tdm_error ret;
667
668         RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
669
670         output_data = hwc_data->output_data;
671         RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
672
673         TDM_BACKEND_INFO(" ==============COMMIT=================================");
674
675         if (hwc_data->output_data->current_dpms != HAL_TDM_OUTPUT_DPMS_ON) {
676                 TDM_BACKEND_ERR("dpms is not on. do not commit");
677                 return HAL_TDM_ERROR_BAD_REQUEST;
678         }
679
680         ret = drm_output_commit(output_data, sync, user_data);
681         RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
682
683         return HAL_TDM_ERROR_NONE;
684 }
685
686 hal_tdm_error
687 drm_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func)
688 {
689         tdm_drm_hwc *hwc_data = hwc;
690
691         RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
692         RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
693
694         hwc_data->commit_func = func;
695
696         return HAL_TDM_ERROR_NONE;
697 }
698
699 hal_tdm_error
700 drm_hwc_target_window_set_info(tdm_drm_hwc *hwc_data, int width, int height)
701 {
702         hal_tdm_hwc_window_info info = {0};
703         tdm_drm_hwc_window_data *target_hwc_window;
704         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
705
706         RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
707         RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, HAL_TDM_ERROR_INVALID_PARAMETER);
708
709         target_hwc_window = hwc_data->target_hwc_window;
710
711         info.dst_pos.x = 0;
712         info.dst_pos.y = 0;
713         info.dst_pos.w = width;
714         info.dst_pos.h = height;
715
716         info.src_config.pos.x = 0;
717         info.src_config.pos.y = 0;
718         info.src_config.pos.w = width;
719         info.src_config.pos.h = height;
720
721         info.src_config.size.h = width;
722         info.src_config.size.v = height;
723         info.src_config.format = TBM_FORMAT_ARGB8888;
724
725         ret = drm_hwc_window_set_info(target_hwc_window, &info);
726         if (ret != HAL_TDM_ERROR_NONE) {
727                 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
728                 return HAL_TDM_ERROR_OPERATION_FAILED;
729         }
730
731         return HAL_TDM_ERROR_NONE;
732 }
733
734 hal_tdm_error
735 drm_hwc_initailize_target_window(tdm_drm_hwc *hwc_data)
736 {
737         hal_tdm_hwc_window_info info = {0};
738         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
739         tdm_drm_hwc_window_data *target_hwc_window;
740
741         RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
742
743         info.dst_pos.x = 0;
744         info.dst_pos.y = 0;
745         info.dst_pos.w = 2;
746         info.dst_pos.h = 1;
747
748         info.src_config.pos.x = 0;
749         info.src_config.pos.y = 0;
750         info.src_config.pos.w = 2;
751         info.src_config.pos.h = 1;
752
753         info.src_config.size.h = 2;
754         info.src_config.size.v = 1;
755         info.src_config.format = TBM_FORMAT_ARGB8888;
756
757         target_hwc_window = _drm_hwc_create_window(hwc_data, &info, &ret);
758         if (ret != HAL_TDM_ERROR_NONE) {
759                 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
760                 return HAL_TDM_ERROR_OPERATION_FAILED;
761         }
762
763         if (hwc_data->target_hwc_window)
764                 drm_hwc_window_destroy(hwc_data->target_hwc_window);
765
766         hwc_data->target_hwc_window = target_hwc_window;
767         hwc_data->need_set_crtc = 1;
768
769         return HAL_TDM_ERROR_NONE;
770 }