bec0ea3ad8d1570d96114c9522ffa5fa5426cb7c
[platform/adaptation/nexell/libtdm-nexell.git] / src / libhal-backend-tdm-nexell / tdm_nexell_hwc.c
1 /**************************************************************************
2
3 libtdm_nexell
4
5 Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "tdm_backend_nexell.h"
36
37 #define MIN_WIDTH      32
38
39 tbm_format hwc_window_video_formats[] = {
40         TBM_FORMAT_NV12,
41         TBM_FORMAT_YUV420
42 };
43
44 const char *
45 _comp_to_str(hal_tdm_hwc_window_composition composition_type)
46 {
47         if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT)
48                 return "CLIENT";
49         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_DEVICE)
50                 return "DEVICE";
51         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR)
52                 return "CURSOR";
53         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_VIDEO)
54                 return "VIDEO";
55         else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
56                 return "SKIP";
57
58         return "unknown";
59 }
60
61 static int
62 _nexell_hwc_cursor_buffer_image_render(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data)
63 {
64         tbm_surface_info_s tsurface_info;
65         tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE;
66         void *src_ptr = NULL, *dst_ptr = NULL;
67         int src_stride, transform, img_w, img_h;
68         pixman_image_t *src_img = NULL, *dst_img = NULL;
69         pixman_transform_t t;
70         struct pixman_f_transform ft;
71         int c = 0, s = 0, tx = 0, ty = 0;
72         int i;
73
74         ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info);
75         if (ret != TBM_SURFACE_ERROR_NONE) {
76                 TDM_BACKEND_ERR("Failed to map tsurface\n");
77                 return 0;
78         }
79
80         src_ptr = hwc_window_data->cursor_img.ptr;
81         src_stride = hwc_window_data->cursor_img.stride;
82         img_w = hwc_window_data->cursor_img.width;
83         img_h = hwc_window_data->cursor_img.height;
84         transform = hwc_window_data->info.transform;
85
86         dst_ptr = tsurface_info.planes[0].ptr;
87
88         memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height);
89
90         if (transform) {
91                 src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride);
92                 if (!src_img) {
93                         TDM_BACKEND_ERR("Failed to create src pixman\n");
94                         return 0;
95                 }
96
97                 dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info.width, tsurface_info.height,
98                         (uint32_t*)dst_ptr, tsurface_info.planes[0].stride);
99                 if (!dst_img) {
100                         TDM_BACKEND_ERR("Failed to create dst pixman\n");
101                         pixman_image_unref(src_img);
102                         return 0;
103                 }
104
105                 pixman_f_transform_init_identity(&ft);
106
107                 if (transform >= HAL_TDM_TRANSFORM_FLIPPED) {
108                         pixman_f_transform_scale(&ft, NULL, -1, 1);
109                         pixman_f_transform_translate(&ft, NULL, tsurface_info.width, 0);
110                 }
111
112                 switch (transform) {
113                 case HAL_TDM_TRANSFORM_90:
114                 case HAL_TDM_TRANSFORM_FLIPPED_90:
115                         c = 0, s = 1, ty = -tsurface_info.height;
116                         break;
117                 case HAL_TDM_TRANSFORM_180:
118                 case HAL_TDM_TRANSFORM_FLIPPED_180:
119                         c = -1, s = 0, tx = -tsurface_info.width, ty = -tsurface_info.height;
120                         break;
121                 case HAL_TDM_TRANSFORM_270:
122                 case HAL_TDM_TRANSFORM_FLIPPED_270:
123                         c = 0, s = -1, tx = -tsurface_info.width;
124                         break;
125                 default:
126                         break;
127                 }
128
129                 pixman_f_transform_translate(&ft, NULL, tx, ty);
130                 pixman_f_transform_rotate(&ft, NULL, c, s);
131                 pixman_transform_from_pixman_f_transform(&t, &ft);
132                 pixman_image_set_transform(src_img, &t);
133                 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0,
134                                        tsurface_info.width, tsurface_info.height);
135                 pixman_image_unref(src_img);
136                 pixman_image_unref(dst_img);
137         }
138         else {
139                 for (i = 0 ; i < img_h ; i++) {
140                         memcpy(dst_ptr, src_ptr, src_stride);
141                         dst_ptr += tsurface_info.planes[0].stride;
142                         src_ptr += src_stride;
143                 }
144         }
145
146         tbm_surface_unmap(hwc_data->cursor_tsurface);
147
148         return 1;
149 }
150
151 static int
152 _nexell_hwc_cursor_window_surface_clear(tdm_nexell_hwc_window_data *hwc_window_data)
153 {
154         hwc_window_data->surface = NULL;
155         hwc_window_data->cursor_img_surface = 0;
156
157         hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width;
158         hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height;
159         hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width;
160         hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height;
161
162         return 1;
163 }
164
165 static void
166 _nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc *hwc_data)
167 {
168         if (hwc_data->cursor_tsurface) {
169                 tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface);
170                 hwc_data->cursor_tsurface = NULL;
171         }
172
173         if (hwc_data->cursor_tqueue) {
174                 tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->cursor_tqueue);
175                 hwc_data->cursor_tqueue = NULL;
176         }
177 }
178
179 static void
180 _nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data)
181 {
182         int x, y, width, height;
183
184         width = tbm_surface_get_width(hwc_data->cursor_tsurface);
185         height = tbm_surface_get_height(hwc_data->cursor_tsurface);
186
187         hwc_window_data->info.src_config.pos.w = width;
188         hwc_window_data->info.src_config.pos.h = height;
189         hwc_window_data->info.dst_pos.w = width;
190         hwc_window_data->info.dst_pos.h = height;
191
192         /* dst pos of cursor is possible set by negative value
193          * this is temporary code.
194          */
195         x = hwc_window_data->info.dst_pos.x;
196         y = hwc_window_data->info.dst_pos.y;
197
198         if (x < 0) hwc_window_data->info.dst_pos.x = 0;
199         if (y < 0) hwc_window_data->info.dst_pos.y = 0;
200 }
201
202 static int
203 _nexell_hwc_cursor_buffer_set(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data)
204 {
205         tbm_surface_h cursor_tsurface = NULL;
206         tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE;
207         int img_w, img_h;
208         int tqueue_w, tqueue_h;
209         hal_tdm_error error;
210
211         if (hwc_window_data->cursor_img_refresh || !hwc_window_data->surface) {
212                 switch (hwc_window_data->info.transform) {
213                 case HAL_TDM_TRANSFORM_90:
214                 case HAL_TDM_TRANSFORM_FLIPPED_90:
215                 case HAL_TDM_TRANSFORM_270:
216                 case HAL_TDM_TRANSFORM_FLIPPED_270:
217                         img_w = hwc_window_data->cursor_img.height;
218                         img_h = hwc_window_data->cursor_img.width;
219                         break;
220                 default:
221                         img_w = hwc_window_data->cursor_img.width;
222                         img_h = hwc_window_data->cursor_img.height;
223                         break;
224                 }
225
226                 if (!hwc_data->cursor_tqueue) {
227                         hwc_data->cursor_tqueue = tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hwc_window_data, &error);
228                         if (error != HAL_TDM_ERROR_NONE) {
229                                 TDM_BACKEND_ERR("Failed to create cursor buffer queue error:%d", error);
230                                 return 0;
231                         }
232                 } else {
233                         tqueue_w = tbm_surface_queue_get_width(hwc_data->cursor_tqueue);
234                         tqueue_h = tbm_surface_queue_get_height(hwc_data->cursor_tqueue);
235                         if ((img_w != tqueue_w) || (img_h != tqueue_h))
236                                 tbm_surface_queue_reset(hwc_data->cursor_tqueue, img_w, img_h, TBM_FORMAT_ARGB8888);
237                 }
238
239                 if (hwc_data->cursor_tsurface) {
240                         tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface);
241                         hwc_data->cursor_tsurface = NULL;
242                 }
243
244                 if (!tbm_surface_queue_can_dequeue(hwc_data->cursor_tqueue, 0)) {
245                         TDM_BACKEND_ERR("Can't dequeue cursor tqueue");
246                         return 0;
247                 }
248
249                 tsq_error = tbm_surface_queue_dequeue(hwc_data->cursor_tqueue, &cursor_tsurface);
250                 if (tsq_error != TBM_SURFACE_QUEUE_ERROR_NONE) {
251                         TDM_BACKEND_ERR("Failed to dequeue cursor tqueue error:%d", tsq_error);
252                         return 0;
253                 }
254
255                 hwc_data->cursor_tsurface = cursor_tsurface;
256
257                 _nexell_hwc_cursor_buffer_image_render(hwc_data, hwc_window_data);
258
259                 hwc_window_data->surface = cursor_tsurface;
260                 hwc_window_data->cursor_img_surface = 1;
261                 hwc_window_data->cursor_img_refresh = 0;
262         }
263
264         _nexell_hwc_cursor_adjust_pos(hwc_data, hwc_window_data);
265
266         return 1;
267 }
268
269 static void
270 _print_validate_result(tdm_nexell_hwc *hwc_data, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds)
271 {
272         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
273         int i;
274         int lzpos_queue;
275
276         for (i = 0; i < num_wnds; i++) {
277                 hwc_window_data = composited_wnds[i];
278                 lzpos_queue = hwc_window_data->lzpos_queue;
279                 switch (hwc_window_data->validated_type) {
280                 case HAL_TDM_HWC_WIN_COMPOSITION_CLIENT:
281                         TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data,
282                                         _comp_to_str(hwc_window_data->client_type),
283                                         _comp_to_str(hwc_window_data->validated_type),
284                                         hwc_data->target_hwc_window->lzpos,
285                                         lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue,
286                                         lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt,
287                                         hwc_window_data->name ? hwc_window_data->name : "NONE");
288                         break;
289                 case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
290                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
291                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
292                 case HAL_TDM_HWC_WIN_COMPOSITION_NONE:
293                         TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s}", hwc_window_data,
294                                         _comp_to_str(hwc_window_data->client_type),
295                                         _comp_to_str(hwc_window_data->validated_type),
296                                         hwc_window_data->lzpos,
297                                         lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue,
298                                         lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt,
299                                         hwc_window_data->name ? hwc_window_data->name : "NONE");
300                         break;
301                 default:
302                         break;
303                 }
304         }
305 }
306
307 static int
308 _nexell_hwc_window_has_reserved_buffer(tdm_nexell_hwc_window_data *hwc_window_data) {
309         tbm_bo bo = NULL;
310         int flags = 0;
311
312         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0);
313         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, 0);
314
315         bo = tbm_surface_internal_get_bo(hwc_window_data->surface, 0);
316         TDM_BACKEND_RETURN_VAL_IF_FAIL(bo != NULL, 0);
317
318         flags = tbm_bo_get_flags(bo);
319
320         return flags & TBM_BO_SCANOUT;
321 }
322
323 static int
324 _nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data, int bottom)
325 {
326         if (!hwc_window_data->surface)
327                 return 0;
328
329         if (hwc_window_data->info.transform != HAL_TDM_TRANSFORM_NORMAL)
330                 return 0;
331
332         if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w)
333                 return 0;
334
335         if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h)
336                 return 0;
337
338         if (!IS_RGB(hwc_window_data->info.src_config.format))
339                 return 0;
340
341         if ((hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay) ||
342                 (hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay))
343                 return 0;
344
345         if (bottom) {
346                 if ((hwc_window_data->info.dst_pos.w != hwc_window_data->hwc_data->output_data->current_mode->hdisplay) ||
347                         (hwc_window_data->info.dst_pos.h != hwc_window_data->hwc_data->output_data->current_mode->vdisplay))
348                 return 0;
349         }
350
351         return 1;
352 }
353
354 tbm_surface_queue_h
355 tdm_nexell_hwc_window_create_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error)
356 {
357         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
358         tbm_surface_queue_h tqueue = NULL;
359         int width, height;
360         tbm_format format;
361
362         if (error)
363                 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
364
365         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
366
367         hwc_window_data = hwc_window;
368
369         width = hwc_window_data->info.src_config.pos.w;
370         height = hwc_window_data->info.src_config.pos.h;
371         format = hwc_window_data->info.src_config.format;
372
373         tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT);
374         if (error)
375                 *error = HAL_TDM_ERROR_OPERATION_FAILED;
376         TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
377
378         if (error)
379                 *error = HAL_TDM_ERROR_NONE;
380
381         return tqueue;
382 }
383
384 tbm_surface_queue_h
385 tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error)
386 {
387         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
388         tbm_surface_queue_h tqueue = NULL;
389         int width, height;
390
391         if (error)
392                 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
393
394         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
395
396         hwc_window_data = hwc_window;
397
398         switch (hwc_window_data->info.transform) {
399         case HAL_TDM_TRANSFORM_90:
400         case HAL_TDM_TRANSFORM_FLIPPED_90:
401         case HAL_TDM_TRANSFORM_270:
402         case HAL_TDM_TRANSFORM_FLIPPED_270:
403                 width = hwc_window_data->cursor_img.height;
404                 height = hwc_window_data->cursor_img.width;
405                 break;
406         default:
407                 width = hwc_window_data->cursor_img.width;
408                 height = hwc_window_data->cursor_img.height;
409                 break;
410         }
411
412         tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
413         if (error)
414                 *error = HAL_TDM_ERROR_OPERATION_FAILED;
415         TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
416
417         tbm_surface_queue_set_modes(tqueue, TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE);
418
419         if (error)
420                 *error = HAL_TDM_ERROR_NONE;
421
422         return tqueue;
423 }
424
425 void
426 tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue)
427 {
428         tbm_surface_queue_destroy(tqueue);
429 }
430
431 static hal_tdm_error
432 _nexell_hwc_layer_attach_window(tdm_nexell_layer *layer_data, tdm_nexell_hwc_window_data *hwc_window_data)
433 {
434         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
435
436         TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_OPERATION_FAILED);
437
438         if (hwc_window_data == NULL || hwc_window_data->surface == NULL) {
439                 if (layer_data->display_buffer)
440                         ret = nexell_layer_unset_buffer(layer_data);
441                 TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
442         } else {
443                 ret = nexell_layer_set_info((tdm_nexell_layer *)layer_data, (tdm_nexell_layer_info *)&(hwc_window_data->info));
444                 TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
445                 TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
446                 ret = nexell_layer_set_buffer(layer_data, hwc_window_data->surface);
447                 TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
448         }
449
450         return ret;
451 }
452
453 static hal_tdm_error
454 _nexell_hwc_prepare_commit(tdm_nexell_hwc *hwc_data)
455 {
456         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
457         tdm_nexell_layer *layer_data = NULL;
458         int use_layers_zpos[NUM_LAYERS] = {0,};
459         int lzpos = 0;
460         int cursor_enabled = 0;
461
462         /* set target hwc window to the layer_data */
463         if (hwc_data->need_target_window) {
464                 layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
465                 _nexell_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
466                 use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
467         }
468
469         /* set the hwc_windows to the layers */
470         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
471                 if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE ||
472                         hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) {
473                         if (hwc_window_data->cursor_img_surface)
474                                 _nexell_hwc_cursor_window_surface_clear(hwc_window_data);
475
476                         continue;
477                 }
478
479                 if (hwc_window_data == hwc_data->target_hwc_window)
480                         continue;
481
482                 /* set the cursor buffer HERE if it needs */
483                 if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR) {
484                         _nexell_hwc_cursor_buffer_set(hwc_data, hwc_window_data);
485                         cursor_enabled = 1;
486                 }
487
488                 layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos);
489                 _nexell_hwc_layer_attach_window(layer_data, hwc_window_data);
490                 use_layers_zpos[hwc_window_data->lzpos] = 1;
491         }
492
493         /* unset the unused layers */
494         for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
495                 if (use_layers_zpos[lzpos])
496                         continue;
497
498                 layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, lzpos);
499                 if (!layer_data)
500                         continue;
501
502                 _nexell_hwc_layer_attach_window(layer_data, NULL);
503         }
504
505         if (!cursor_enabled)
506                 _nexell_hwc_cursor_buffer_unset(hwc_data);
507
508         /* for debug */
509         for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) {
510                 if (use_layers_zpos[lzpos])
511                         TDM_BACKEND_DBG(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET");
512         }
513
514         return HAL_TDM_ERROR_NONE;
515 }
516
517 /* assign the validated_type to the composited_wnds
518  * assign the layer_zpos to the composited_wnds
519  */
520 static void
521 _nexell_hwc_apply_policy(tdm_nexell_hwc *hwc_data , hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds)
522 {
523         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
524         tdm_nexell_hwc_window_data **composited_list = NULL;
525         int client_count = 0;
526         int device_count = 0;
527         int video_count = 0;
528         int cursor_count = 0;
529         int ui_lzpos_top = ZPOS_2;
530         int ui_lzpos_bottom = ZPOS_1;
531         int num_ui_layers = NUM_UI_LAYERS;
532         int set_clients_below = 0;
533         int i = 0;
534
535         composited_list = (tdm_nexell_hwc_window_data **)composited_wnds;
536
537         /* initialize the need_target_window */
538         hwc_data->need_target_window = 0;
539
540         /* initialize the validated_types and constraints */
541         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
542                 hwc_window_data->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE;
543                 hwc_window_data->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_NONE;
544                 hwc_window_data->lzpos = -1;
545                 hwc_window_data->lzpos_queue = -1;
546         }
547
548         /* use the target_window to commit when there is no window. */
549         if (num_wnds == 0) {
550                 hwc_data->need_target_window = 1;
551                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
552                 hwc_data->target_hwc_window->lzpos_queue = ui_lzpos_bottom;
553                 return;
554         }
555
556         /* 1. first check validate_type without target_window */
557         for (i = 0; i < num_wnds; i++) {
558                 switch (composited_list[i]->client_type) {
559                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
560                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_VIDEO;
561                         video_count++;
562                         continue;
563                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
564                         if (set_clients_below) break;
565                         if (num_ui_layers <= 0) break;
566
567                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CURSOR;
568                         cursor_count++;
569                         num_ui_layers--;
570                         continue;
571                 case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
572                         if (set_clients_below) break;
573                         if (num_ui_layers <= 0) break;
574
575                         if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i], (i == num_wnds - 1)))
576                                 break;
577
578                         if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i])) {
579                                 composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
580                                 break;
581                         }
582
583                         composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_DEVICE;
584                         composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
585                         device_count++;
586                         num_ui_layers--;
587                         continue;
588                 default:
589                         break;
590                 }
591
592                 composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT;
593                 client_count++;
594                 set_clients_below = 1;
595         }
596
597         /* 2. check need target window and set ui_lzpos top and bottom */
598         num_ui_layers = NUM_UI_LAYERS;
599         if (client_count > 0) {
600                 hwc_data->need_target_window = 1;
601                 hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
602                 ui_lzpos_bottom++;
603                 num_ui_layers--;
604         }
605
606         if (num_ui_layers > (device_count + cursor_count))
607                 ui_lzpos_top = ui_lzpos_bottom + device_count + cursor_count - 1;
608
609         /* 3. set lzpos and modify validate_type with target_window */
610         for (i = 0; i < num_wnds; i++) {
611                 switch (composited_list[i]->validated_type) {
612                 case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO:
613                         composited_list[i]->lzpos = ZPOS_VIDEO1;
614                         continue;
615                 case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR:
616                 case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE:
617                         if (num_ui_layers <= 0) break;
618
619                         composited_list[i]->lzpos = ui_lzpos_top;
620                         composited_list[i]->lzpos_queue = ui_lzpos_top;
621                         ui_lzpos_top--;
622                         num_ui_layers--;
623                         continue;
624                 default:
625                         break;
626                 }
627
628                 composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT;
629
630                 if (composited_list[i]->constraints == HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE) {
631                         if (i == num_wnds - 1) //set target window queue zpos
632                                 composited_list[i]->lzpos_queue = ui_lzpos_top;
633                         else if(num_ui_layers > 0)
634                                 composited_list[i]->lzpos_queue = ui_lzpos_top + 1;
635                         else
636                                 composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE;
637                 }
638         }
639 }
640
641 static int
642 _nexell_hwc_get_changed_number(tdm_nexell_hwc *hwc_data)
643 {
644         int num = 0;
645         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
646
647         LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
648                 if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
649                         continue;
650
651                 if (hwc_window_data->client_type != hwc_window_data->validated_type)
652                         num++;
653         }
654
655         return num;
656 }
657
658 hal_tdm_hwc_window *
659 _nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_hwc_window_info *info, hal_tdm_error *error)
660 {
661         tdm_nexell_hwc *hwc_data = hwc;
662         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
663
664         if (error)
665                 *error = HAL_TDM_ERROR_NONE;
666
667         if (!hwc_data) {
668                 TDM_BACKEND_ERR("invalid params");
669                 if (error)
670                         *error = HAL_TDM_ERROR_INVALID_PARAMETER;
671                 return NULL;
672         }
673
674         hwc_window_data = calloc(1, sizeof(tdm_nexell_hwc_window_data));
675         if (!hwc_window_data) {
676                 TDM_BACKEND_ERR("alloc failed");
677                 if (error)
678                         *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
679                 return NULL;
680         }
681
682         hwc_window_data->hwc_data = hwc_data;
683
684         if (info)
685                 memcpy(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info));
686
687         LIST_INITHEAD(&hwc_window_data->link);
688
689         return hwc_window_data;
690 }
691
692 hal_tdm_hwc_window *
693 nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error)
694 {
695         tdm_nexell_hwc *hwc_data = hwc;
696         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
697
698         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, NULL);
699
700         hwc_window_data = _nexell_hwc_create_window(hwc_data, NULL, error);
701         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
702
703         LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
704
705         TDM_BACKEND_DBG("hwc_window(%p) create", hwc_window_data);
706         if (error)
707                 *error = HAL_TDM_ERROR_NONE;
708
709         return hwc_window_data;
710 }
711
712 hal_tdm_error
713 nexell_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count)
714 {
715         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
716         TDM_BACKEND_RETURN_VAL_IF_FAIL(formats != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
717         TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
718
719         // TODO: fix these formats.
720         *formats = hwc_window_video_formats;
721         *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
722
723         return HAL_TDM_ERROR_NONE;
724 }
725
726 hal_tdm_error
727 nexell_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities)
728 {
729         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
730         TDM_BACKEND_RETURN_VAL_IF_FAIL(capabilities != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
731
732         *capabilities |= HAL_TDM_HWC_CAPABILITY_VIDEO_SCALE;
733
734         return HAL_TDM_ERROR_NONE;
735 }
736
737 hal_tdm_error
738 nexell_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count)
739 {
740         tdm_nexell_hwc *hwc_data = hwc;
741
742         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
743         TDM_BACKEND_RETURN_VAL_IF_FAIL(props != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
744         TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
745
746         *props = NULL;
747         *count = 0;
748
749         return HAL_TDM_ERROR_NONE;
750 }
751
752 tbm_surface_queue_h
753 nexell_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error)
754 {
755         tdm_nexell_hwc *hwc_data = hwc;
756         tbm_surface_queue_h tqueue = NULL;
757
758         if (error)
759                 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
760
761         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
762
763         if (hwc_data->target_hwc_window == NULL) {
764                 if (error)
765                         *error = HAL_TDM_ERROR_OPERATION_FAILED;
766                 return NULL;
767         }
768
769         tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_data->target_hwc_window, error);
770         TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue, NULL);
771
772         hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue;
773         hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1;
774
775         if (error)
776                 *error = HAL_TDM_ERROR_NONE;
777
778         return tqueue;
779 }
780
781 hal_tdm_error
782 nexell_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage)
783 {
784         tdm_nexell_hwc *hwc_data = hwc;
785         hal_tdm_error err;
786
787         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
788         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window  != NULL, HAL_TDM_ERROR_OPERATION_FAILED);
789
790         err = nexell_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
791         TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err);
792
793         err = nexell_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
794         TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err);
795
796         return HAL_TDM_ERROR_NONE;
797 }
798
799 hal_tdm_error
800 nexell_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
801 {
802         tdm_nexell_hwc *hwc_data = hwc;
803         tdm_nexell_output *output_data;
804
805         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
806         TDM_BACKEND_RETURN_VAL_IF_FAIL(num_types != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
807
808         output_data = hwc_data->output_data;
809         TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
810
811         TDM_BACKEND_DBG(" ==============Validate=================================");
812
813         /* adapt policy */
814         _nexell_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
815
816         *num_types = _nexell_hwc_get_changed_number(hwc_data);
817
818         _print_validate_result(hwc_data, composited_wnds, num_wnds);
819
820         return HAL_TDM_ERROR_NONE;
821 }
822
823 hal_tdm_error
824 nexell_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements,
825                                 hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types)
826 {
827         tdm_nexell_hwc *hwc_data = hwc;
828         tdm_nexell_hwc_window_data *hwc_window_data = NULL;
829         int num = 0;
830
831         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
832         TDM_BACKEND_RETURN_VAL_IF_FAIL(num_elements != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
833
834         if ((hwc_wnds == NULL) || (composition_types == NULL)) {
835                 *num_elements = _nexell_hwc_get_changed_number(hwc_data);
836                 return HAL_TDM_ERROR_NONE;
837         }
838
839         LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
840                 if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE)
841                         continue;
842
843                 if (num >= *num_elements)
844                         break;
845
846                 if (hwc_window_data->client_type != hwc_window_data->validated_type) {
847                         composition_types[num] = hwc_window_data->validated_type;
848                         hwc_wnds[num] = hwc_window_data;
849                         num++;
850                 }
851         }
852
853         /* set real num of changed composition types */
854         *num_elements = num;
855
856         return HAL_TDM_ERROR_NONE;
857 }
858
859 hal_tdm_error
860 nexell_hwc_accept_validation(hal_tdm_hwc *hwc)
861 {
862         tdm_nexell_hwc *hwc_data = hwc;
863         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
864
865         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
866         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
867
868         TDM_BACKEND_DBG(" ==============Accept Changes Done=================================");
869
870         ret = _nexell_hwc_prepare_commit(hwc_data);
871         TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
872
873         return HAL_TDM_ERROR_NONE;
874 }
875
876 hal_tdm_error
877 nexell_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data)
878 {
879         tdm_nexell_hwc *hwc_data = hwc;
880         tdm_nexell_output *output_data = NULL;
881         hal_tdm_error ret;
882
883         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
884
885         output_data = hwc_data->output_data;
886         TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
887
888         TDM_BACKEND_DBG(" ==============COMMIT=================================");
889
890         ret = nexell_output_commit(output_data, sync, user_data);
891         TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
892
893         return HAL_TDM_ERROR_NONE;
894 }
895
896 hal_tdm_error
897 nexell_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func)
898 {
899         tdm_nexell_hwc *hwc_data = hwc;
900
901         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
902         TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
903
904         hwc_data->commit_func = func;
905
906         return HAL_TDM_ERROR_NONE;
907 }
908
909 hal_tdm_error
910 nexell_hwc_target_window_set_info(tdm_nexell_hwc *hwc_data, int width, int height)
911 {
912         hal_tdm_hwc_window_info info = {0};
913         tdm_nexell_hwc_window_data *target_hwc_window;
914         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
915
916         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
917         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, HAL_TDM_ERROR_INVALID_PARAMETER);
918
919         target_hwc_window = hwc_data->target_hwc_window;
920
921         info.dst_pos.x = 0;
922         info.dst_pos.y = 0;
923         info.dst_pos.w = width;
924         info.dst_pos.h = height;
925
926         info.src_config.pos.x = 0;
927         info.src_config.pos.y = 0;
928         info.src_config.pos.w = width;
929         info.src_config.pos.h = height;
930
931         info.src_config.size.h = width;
932         info.src_config.size.v = height;
933         info.src_config.format = TBM_FORMAT_ARGB8888;
934
935         ret = nexell_hwc_window_set_info(target_hwc_window, &info);
936         if (ret != HAL_TDM_ERROR_NONE) {
937                 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
938                 return HAL_TDM_ERROR_OPERATION_FAILED;
939         }
940
941         return HAL_TDM_ERROR_NONE;
942 }
943
944 hal_tdm_error
945 tdm_nexell_hwc_initailize_target_window(tdm_nexell_hwc *hwc_data)
946 {
947         hal_tdm_hwc_window_info info = {0};
948         hal_tdm_error ret = HAL_TDM_ERROR_NONE;
949         tdm_nexell_hwc_window_data *target_hwc_window;
950
951         TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER);
952
953         info.dst_pos.x = 0;
954         info.dst_pos.y = 0;
955         info.dst_pos.w = 2;
956         info.dst_pos.h = 1;
957
958         info.src_config.pos.x = 0;
959         info.src_config.pos.y = 0;
960         info.src_config.pos.w = 2;
961         info.src_config.pos.h = 1;
962
963         info.src_config.size.h = 2;
964         info.src_config.size.v = 1;
965         info.src_config.format = TBM_FORMAT_ARGB8888;
966
967         target_hwc_window = _nexell_hwc_create_window(hwc_data, &info, &ret);
968         if (ret != HAL_TDM_ERROR_NONE) {
969                 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
970                 return HAL_TDM_ERROR_OPERATION_FAILED;
971         }
972
973         if (hwc_data->target_hwc_window)
974                 nexell_hwc_window_destroy(hwc_data->target_hwc_window);
975
976         hwc_data->target_hwc_window = target_hwc_window;
977         hwc_data->need_set_crtc = 1;
978
979         return HAL_TDM_ERROR_NONE;
980 }