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