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