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