tdm_server: Remove duplicate code
[platform/core/uifw/libtdm.git] / src / tdm_hwc.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2018 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
7  * Contact: SooChan Lim <sc1.lim@samsung.com>,
8  *          Boram Park <boram1288.park@samsung.com>,
9  *          Changyeon Lee <cyeon.lee@samsung.com>,
10  *          Sangjin Lee <lsj119@samsung.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the
14  * "Software"), to deal in the Software without restriction, including
15  * without limitation the rights to use, copy, modify, merge, publish,
16  * distribute, sub license, and/or sell copies of the Software, and to
17  * permit persons to whom the Software is furnished to do so, subject to
18  * the following conditions:
19  *
20  * The above copyright notice and this permission notice (including the
21  * next paragraph) shall be included in all copies or substantial portions
22  * of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
27  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
28  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31  *
32 **************************************************************************/
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include "tdm_private.h"
39
40 #define HWC_FUNC_ENTRY() \
41         tdm_private_display *private_display; \
42         tdm_private_output *private_output; \
43         tdm_private_hwc *private_hwc; \
44         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
45         TDM_RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); \
46         private_hwc = (tdm_private_hwc*)hwc; \
47         private_output = private_hwc->private_output; \
48         TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); \
49         private_display = private_output->private_display
50
51 #define HWC_FUNC_ENTRY_ERROR() \
52         tdm_private_display *private_display; \
53         tdm_private_output *private_output; \
54         tdm_private_hwc *private_hwc; \
55         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
56         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(hwc != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
57         private_hwc = (tdm_private_hwc*)hwc; \
58         private_output = private_hwc->private_output; \
59         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_output != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); \
60         private_display = private_output->private_display
61
62 #define HWC_FUNC_ENTRY_VOID_RETURN() \
63         tdm_private_display *private_display; \
64         tdm_private_output *private_output; \
65         tdm_private_hwc *private_hwc; \
66         tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\
67         TDM_RETURN_IF_FAIL(hwc != NULL); \
68         private_hwc = (tdm_private_hwc*)hwc; \
69         private_output = private_hwc->private_output; \
70         TDM_RETURN_IF_FAIL(private_output != NULL); \
71         private_display = private_output->private_display
72
73 static int hwc_use_vblank;
74 static unsigned int hwc_vblank_fps;
75
76 static tdm_private_hwc_window *
77 _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *hwc_window_backend)
78 {
79         tdm_private_hwc_window *private_hwc_window = NULL;
80
81         LIST_FOR_EACH_ENTRY(private_hwc_window, &private_hwc->hwc_window_list, link) {
82                 if (private_hwc_window->hwc_window_backend == hwc_window_backend)
83                         return private_hwc_window;
84         }
85
86         return NULL;
87 }
88
89 static tdm_error
90 _tdm_hwc_check_hwc_commit_handler_validation(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
91 {
92         tdm_private_hwc_commit_handler *commit_handler = NULL;
93
94         if (LIST_IS_EMPTY(&private_hwc->hwc_commit_handler_list))
95                 return TDM_ERROR_INVALID_PARAMETER;
96
97         LIST_FOR_EACH_ENTRY(commit_handler, &private_hwc->hwc_commit_handler_list, link) {
98                 if (commit_handler == hwc_commit_handler)
99                         return TDM_ERROR_NONE;
100         }
101
102         return TDM_ERROR_INVALID_PARAMETER;
103 }
104
105 static void
106 _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object,
107                                 tdm_thread_cb_base *cb_base, void *user_data)
108 {
109         tdm_thread_cb_hwc_commit *hwc_commit = (tdm_thread_cb_hwc_commit *)cb_base;
110         tdm_private_hwc_commit_handler *hwc_commit_handler = hwc_commit->base.data;
111         tdm_private_hwc *private_hwc = object;
112
113         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
114
115         if (!hwc_commit_handler)
116                 return;
117
118         assert(hwc_commit_handler->owner_tid == syscall(SYS_gettid));
119
120         tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
121                                         _tdm_hwc_thread_cb_commit, NULL);
122
123         TDM_RETURN_IF_FAIL(_tdm_hwc_check_hwc_commit_handler_validation(private_hwc, hwc_commit_handler) == TDM_ERROR_NONE)
124
125         LIST_DEL(&hwc_commit_handler->link);
126
127         if (tdm_debug_module & TDM_DEBUG_COMMIT) {
128                 TDM_INFO("----------------------------------------- hwc(%d) committed", private_hwc->index);
129                 TDM_INFO("handler(%p)", hwc_commit_handler);
130         }
131
132         /* LCOV_EXCL_START */
133         if (private_display->print_fps) {
134                 double curr = tdm_helper_get_time();
135                 if (private_hwc->fps_stamp == 0) {
136                         private_hwc->fps_stamp = curr;
137                 } else if ((curr - private_hwc->fps_stamp) > 1.0) {
138                         TDM_INFO("hwc(%p,%d) fps: %d",
139                                          private_hwc, private_hwc->index, private_hwc->fps_count);
140                         private_hwc->fps_count = 0;
141                         private_hwc->fps_stamp = curr;
142                 } else
143                         private_hwc->fps_count++;
144         } else if (private_hwc->fps_stamp != 0) {
145                 private_hwc->fps_stamp = 0;
146                 private_hwc->fps_count = 0;
147         }
148         /* LCOV_EXCL_STOP */
149
150         if (hwc_commit_handler->func) {
151                 _pthread_mutex_unlock(&private_display->lock);
152                 hwc_commit_handler->func(private_hwc,
153                                                                         hwc_commit->sequence,
154                                                                         hwc_commit->tv_sec,
155                                                                         hwc_commit->tv_usec,
156                                                                         hwc_commit_handler->user_data);
157                 _pthread_mutex_lock(&private_display->lock);
158         }
159
160         free(hwc_commit_handler);
161
162         if (tdm_debug_module & TDM_DEBUG_COMMIT)
163                 TDM_INFO("-----------------------------------------...");
164 }
165
166 static void
167 _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence,
168                                           unsigned int tv_sec, unsigned int tv_usec, void *user_data)
169 {
170         tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
171         tdm_private_hwc *private_hwc;
172         tdm_thread_cb_hwc_commit hwc_commit;
173         tdm_error ret;
174
175         if (hwc_commit_handler && hwc_commit_handler->use_vblank)
176                 return;
177
178         if (hwc_commit_handler)
179                 private_hwc = hwc_commit_handler->private_hwc;
180         else
181                 private_hwc = tdm_display_find_private_hwc(tdm_display_get(), hwc_backend);
182
183         memset(&hwc_commit, 0, sizeof hwc_commit);
184         hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
185         hwc_commit.base.length = sizeof hwc_commit;
186         hwc_commit.base.object_stamp = private_hwc->stamp;
187         hwc_commit.base.data = hwc_commit_handler;
188         hwc_commit.base.sync = 0;
189         hwc_commit.sequence = sequence;
190         hwc_commit.tv_sec = tv_sec;
191         hwc_commit.tv_usec = tv_usec;
192
193         ret = tdm_thread_cb_call(private_hwc, &hwc_commit.base, 1);
194         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
195 }
196
197 static void
198 _tdm_hwc_cb_commit_hal_tdm(hal_tdm_hwc *hwc_backend, unsigned int sequence,
199                                           unsigned int tv_sec, unsigned int tv_usec, void *user_data)
200 {
201         tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
202         tdm_private_hwc *private_hwc;
203         tdm_thread_cb_hwc_commit hwc_commit;
204         tdm_error ret;
205
206         if (hwc_commit_handler && hwc_commit_handler->use_vblank)
207                 return;
208
209         if (hwc_commit_handler)
210                 private_hwc = hwc_commit_handler->private_hwc;
211         else
212                 private_hwc = tdm_display_find_private_hwc(tdm_display_get(), (tdm_hwc *)hwc_backend);
213
214         memset(&hwc_commit, 0, sizeof hwc_commit);
215         hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
216         hwc_commit.base.length = sizeof hwc_commit;
217         hwc_commit.base.object_stamp = private_hwc->stamp;
218         hwc_commit.base.data = hwc_commit_handler;
219         hwc_commit.base.sync = 0;
220         hwc_commit.sequence = sequence;
221         hwc_commit.tv_sec = tv_sec;
222         hwc_commit.tv_usec = tv_usec;
223
224         ret = tdm_thread_cb_call(private_hwc, &hwc_commit.base, 1);
225         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
226 }
227
228 /* LCOV_EXCL_START */
229 static void
230 _tdm_hwc_got_wait_vblank(unsigned int sequence,
231                                                  unsigned int tv_sec, unsigned int tv_usec, void *user_data)
232 {
233         tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
234         tdm_private_hwc *private_hwc;
235         tdm_thread_cb_hwc_commit hwc_commit;
236
237         private_hwc = hwc_commit_handler->private_hwc;
238         private_hwc->private_output->layer_waiting_vblank = 0;
239
240         memset(&hwc_commit, 0, sizeof hwc_commit);
241         hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
242         hwc_commit.base.length = sizeof hwc_commit;
243         hwc_commit.base.object_stamp = private_hwc->stamp;
244         hwc_commit.base.data = hwc_commit_handler;
245         hwc_commit.base.sync = 0;
246         hwc_commit.sequence = sequence;
247         hwc_commit.tv_sec = tv_sec;
248         hwc_commit.tv_usec = tv_usec;
249
250         _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data);
251 }
252
253 static void
254 _tdm_hwc_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
255                                                 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
256 {
257         tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
258         tdm_private_output *private_output = NULL;
259         tdm_private_display *private_display;
260
261         if (!hwc_commit_handler->use_vblank)
262                 return;
263
264         TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL);
265         TDM_RETURN_IF_FAIL(hwc_commit_handler->private_hwc != NULL);
266
267         private_output = hwc_commit_handler->private_hwc->private_output;
268         TDM_RETURN_IF_FAIL(private_output != NULL);
269
270         private_display = private_output->private_display;
271
272         _pthread_mutex_lock(&private_display->lock);
273
274         _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data);
275
276         _pthread_mutex_unlock(&private_display->lock);
277 }
278
279 static tdm_error
280 _tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
281 {
282         tdm_private_display *private_display;
283         tdm_private_output *private_output;
284         tdm_error ret = TDM_ERROR_NONE;
285
286         private_output = private_hwc->private_output;
287         TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
288         private_display = private_output->private_display;
289
290         if (!private_output->vblank) {
291                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
292                 _pthread_mutex_unlock(&private_display->lock);
293                 private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
294                 _pthread_mutex_lock(&private_display->lock);
295                 TDM_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED);
296         }
297
298         if (!private_output->layer_waiting_vblank) {
299                 ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps);
300                 if (ret != TDM_ERROR_NONE)
301                         goto done;
302
303                 private_output->layer_waiting_vblank = 1;
304
305                 /* tdm_vblank APIs is for server. it should be called in unlock status*/
306                 _pthread_mutex_unlock(&private_display->lock);
307                 ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_hwc_cb_wait_vblank, hwc_commit_handler);
308                 _pthread_mutex_lock(&private_display->lock);
309                 if (ret != TDM_ERROR_NONE) {
310                         if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
311                                 private_output->layer_waiting_vblank = 0;
312                         }
313                 }
314         }
315
316 done:
317         return ret;
318 }
319 /* LCOV_EXCL_STOP */
320
321 INTERN tdm_error
322 tdm_hwc_init(tdm_private_display *private_display)
323 {
324         tdm_thread_cb_set_find_func(TDM_THREAD_CB_HWC_COMMIT, tdm_display_find_hwc_stamp);
325
326         return TDM_ERROR_NONE;
327 }
328
329 INTERN void
330 tdm_hwc_set_vblank(unsigned int fps)
331 {
332         hwc_use_vblank = 1;
333         hwc_vblank_fps = fps;
334 }
335
336 INTERN void
337 tdm_hwc_unset_vblank(void)
338 {
339         hwc_use_vblank = 0;
340         hwc_vblank_fps = 0;
341 }
342
343 EXTERN tdm_hwc_window *
344 tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
345 {
346         tdm_hwc_window *hwc_window = NULL;
347
348         HWC_FUNC_ENTRY_ERROR();
349
350         _pthread_mutex_lock(&private_display->lock);
351
352         hwc_window = (tdm_hwc_window *)tdm_hwc_window_create_internal(private_hwc, error);
353
354         _pthread_mutex_unlock(&private_display->lock);
355
356         return hwc_window;
357 }
358
359 EXTERN tdm_error
360 tdm_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
361 {
362         tdm_private_module *private_module;
363         tdm_func_hwc *func_hwc;
364
365         HWC_FUNC_ENTRY();
366
367         TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
368         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
369
370         _pthread_mutex_lock(&private_display->lock);
371
372         private_module = private_output->private_module;
373         func_hwc = &private_module->func_hwc;
374
375         if (private_module->use_hal_tdm) {
376                 ret = (tdm_error)hal_tdm_hwc_get_video_supported_formats((hal_tdm_hwc *)private_hwc->hwc_backend, formats, count);
377         } else {
378                 if (!func_hwc->hwc_get_video_supported_formats) {
379                         /* LCOV_EXCL_START */
380                         _pthread_mutex_unlock(&private_display->lock);
381                         TDM_WRN("not implemented!!");
382                         return TDM_ERROR_NOT_IMPLEMENTED;
383                         /* LCOV_EXCL_STOP */
384                 }
385
386                 ret = func_hwc->hwc_get_video_supported_formats(private_hwc->hwc_backend, formats, count);
387         }
388         _pthread_mutex_unlock(&private_display->lock);
389
390         return ret;
391 }
392
393 EXTERN tdm_error
394 tdm_hwc_get_video_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
395 {
396         tdm_private_module *private_module;
397         tdm_func_hwc *func_hwc = NULL;
398
399         HWC_FUNC_ENTRY();
400
401         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
402         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
403
404         _pthread_mutex_lock(&private_display->lock);
405
406         private_module = private_output->private_module;
407         func_hwc = &private_module->func_hwc;
408
409         if (private_module->use_hal_tdm) {
410                 ret = (tdm_error)hal_tdm_hwc_get_video_available_properties((hal_tdm_hwc *)private_hwc->hwc_backend,
411                                                                                                                                 (const hal_tdm_prop **)props, count);
412         } else {
413                 if (!func_hwc->hwc_get_video_available_properties) {
414                         /* LCOV_EXCL_START */
415                         _pthread_mutex_unlock(&private_display->lock);
416                         TDM_WRN("not implemented!!");
417                         return TDM_ERROR_NOT_IMPLEMENTED;
418                         /* LCOV_EXCL_STOP */
419                 }
420
421                 ret = func_hwc->hwc_get_video_available_properties(private_hwc->hwc_backend, props, count);
422         }
423         _pthread_mutex_unlock(&private_display->lock);
424
425         return ret;
426 }
427
428 EXTERN tdm_error
429 tdm_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
430 {
431         tdm_private_module *private_module;
432         tdm_func_hwc *func_hwc;
433
434         HWC_FUNC_ENTRY();
435
436         _pthread_mutex_lock(&private_display->lock);
437
438         private_module = private_output->private_module;
439         func_hwc = &private_module->func_hwc;
440
441         if (private_module->use_hal_tdm) {
442                 ret = (tdm_error)hal_tdm_hwc_get_capabilities((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_capability *)capabilities);
443         } else {
444                 if (!func_hwc->hwc_get_capabilities) {
445                         _pthread_mutex_unlock(&private_display->lock);
446                         TDM_WRN("not implemented!!");
447                         return TDM_ERROR_NOT_IMPLEMENTED;
448                 }
449
450                 ret = func_hwc->hwc_get_capabilities(private_hwc->hwc_backend, capabilities);
451         }
452         _pthread_mutex_unlock(&private_display->lock);
453
454         return ret;
455 }
456
457 EXTERN tdm_error
458 tdm_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
459 {
460         tdm_private_module *private_module;
461         tdm_func_hwc *func_hwc = NULL;
462
463         HWC_FUNC_ENTRY();
464
465         TDM_RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
466         TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
467
468         _pthread_mutex_lock(&private_display->lock);
469
470         private_module = private_output->private_module;
471         func_hwc = &private_module->func_hwc;
472
473         if (private_module->use_hal_tdm) {
474                 ret = (tdm_error)hal_tdm_hwc_get_available_properties((hal_tdm_hwc *)private_hwc->hwc_backend, (const hal_tdm_prop **)props, count);
475         } else {
476                 if (!func_hwc->hwc_get_available_properties) {
477                         /* LCOV_EXCL_START */
478                         _pthread_mutex_unlock(&private_display->lock);
479                         TDM_WRN("not implemented!!");
480                         return TDM_ERROR_NOT_IMPLEMENTED;
481                         /* LCOV_EXCL_STOP */
482                 }
483
484                 ret = func_hwc->hwc_get_available_properties(private_hwc->hwc_backend, props, count);
485         }
486         _pthread_mutex_unlock(&private_display->lock);
487
488         return ret;
489 }
490
491 EXTERN tbm_surface_queue_h
492 tdm_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
493 {
494         tdm_private_module *private_module;
495         tdm_func_hwc *func_hwc = NULL;
496         tbm_surface_queue_h queue = NULL;
497
498         HWC_FUNC_ENTRY_ERROR();
499
500         _pthread_mutex_lock(&private_display->lock);
501
502         private_module = private_hwc->private_module;
503         func_hwc = &private_module->func_hwc;
504
505         if (private_module->use_hal_tdm) {
506                 queue = hal_tdm_hwc_get_client_target_buffer_queue((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_error *)error);
507         } else {
508                 if (!func_hwc->hwc_get_client_target_buffer_queue) {
509                         /* LCOV_EXCL_START */
510                         _pthread_mutex_unlock(&private_display->lock);
511                         TDM_WRN("not implemented!!");
512                         return NULL;
513                         /* LCOV_EXCL_STOP */
514                 }
515
516                 queue = func_hwc->hwc_get_client_target_buffer_queue(private_hwc->hwc_backend, error);
517         }
518         _pthread_mutex_unlock(&private_display->lock);
519
520         return queue;
521 }
522
523 EXTERN tdm_error
524 tdm_hwc_set_client_target_buffer_info(tdm_hwc *hwc, tdm_hwc_window_info *info)
525 {
526         tdm_private_module *private_module;
527         tdm_func_hwc *func_hwc = NULL;
528
529         HWC_FUNC_ENTRY();
530
531         _pthread_mutex_lock(&private_display->lock);
532
533         private_module = private_hwc->private_module;
534         func_hwc = &private_module->func_hwc;
535
536         if (private_module->use_hal_tdm) {
537                 ret = (tdm_error)hal_tdm_hwc_set_client_target_buffer_info((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_window_info *)info);
538         } else {
539                 if (!func_hwc->hwc_set_client_target_buffer_info) {
540                         /* LCOV_EXCL_START */
541                         _pthread_mutex_unlock(&private_display->lock);
542                         return TDM_ERROR_NOT_IMPLEMENTED;
543                         /* LCOV_EXCL_STOP */
544                 }
545
546                 ret = func_hwc->hwc_set_client_target_buffer_info(private_hwc->hwc_backend, info);
547         }
548
549         _pthread_mutex_unlock(&private_display->lock);
550
551         return ret;
552 }
553
554 EXTERN tdm_error
555 tdm_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h target_buffer, tdm_region damage)
556 {
557         tdm_private_module *private_module;
558         tdm_func_hwc *func_hwc = NULL;
559
560         HWC_FUNC_ENTRY();
561
562         _pthread_mutex_lock(&private_display->lock);
563
564         if (tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) {
565                 /* LCOV_EXCL_START */
566                 char str[TDM_PATH_LEN];
567                 static int i;
568                 snprintf(str, TDM_PATH_LEN, "target_window_%03d", i++);
569                 tdm_helper_dump_buffer_str(target_buffer, tdm_debug_dump_dir, str);
570                 /* LCOV_EXCL_STOP */
571         }
572
573         private_module = private_hwc->private_module;
574         func_hwc = &private_module->func_hwc;
575
576         if (private_module->use_hal_tdm) {
577                 hal_tdm_region hdamage;
578                 memcpy(&hdamage, &damage, sizeof(hal_tdm_region));
579                 ret = (tdm_error)hal_tdm_hwc_set_client_target_buffer((hal_tdm_hwc *)private_hwc->hwc_backend, target_buffer, hdamage);
580         } else {
581                 if (!func_hwc->hwc_set_client_target_buffer) {
582                         /* LCOV_EXCL_START */
583                         _pthread_mutex_unlock(&private_display->lock);
584                         TDM_WRN("not implemented!!");
585                         return TDM_ERROR_NOT_IMPLEMENTED;
586                         /* LCOV_EXCL_STOP */
587                 }
588
589                 ret = func_hwc->hwc_set_client_target_buffer(private_hwc->hwc_backend, target_buffer, damage);
590         }
591         if (private_hwc->display_target_buffer) {
592                 if (private_hwc->display_target_buffer != target_buffer) {
593                         tbm_surface_internal_unref(private_hwc->display_target_buffer);
594                         private_hwc->display_target_buffer = target_buffer;
595                         if (target_buffer)
596                                 tbm_surface_internal_ref(private_hwc->display_target_buffer);
597                 }
598         } else {
599                 if (target_buffer) {
600                         private_hwc->display_target_buffer = target_buffer;
601                         tbm_surface_internal_ref(private_hwc->display_target_buffer);
602                 }
603         }
604
605         _pthread_mutex_unlock(&private_display->lock);
606
607         return ret;
608 }
609
610 EXTERN tdm_error
611 tdm_hwc_set_client_target_acquire_fence(tdm_hwc *hwc, int acquire_fence)
612 {
613         tdm_private_module *private_module;
614         tdm_func_hwc *func_hwc = NULL;
615
616         HWC_FUNC_ENTRY();
617
618         _pthread_mutex_lock(&private_display->lock);
619
620         private_module = private_hwc->private_module;
621         func_hwc = &private_module->func_hwc;
622
623         if (private_module->use_hal_tdm) {
624                 ret = (tdm_error)hal_tdm_hwc_set_client_target_acquire_fence((hal_tdm_hwc *)private_hwc->hwc_backend, acquire_fence);
625         } else {
626                 if (!func_hwc->hwc_set_client_target_acquire_fence) {
627                         /* LCOV_EXCL_START */
628                         _pthread_mutex_unlock(&private_display->lock);
629                         TDM_WRN("not implemented!!");
630                         return TDM_ERROR_NOT_IMPLEMENTED;
631                         /* LCOV_EXCL_STOP */
632                 }
633
634                 ret = func_hwc->hwc_set_client_target_acquire_fence(private_hwc->hwc_backend, acquire_fence);
635         }
636         _pthread_mutex_unlock(&private_display->lock);
637
638         return ret;
639 }
640
641 EXTERN tdm_error
642 tdm_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
643 {
644         tdm_private_module *private_module;
645         tdm_func_hwc *func_hwc = NULL;
646         tdm_private_hwc_window **composited_wnds_frontend = NULL;
647         tdm_hwc_window **composited_wnds_backend = NULL;
648         int i;
649
650         HWC_FUNC_ENTRY();
651
652         TDM_RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
653
654         _pthread_mutex_lock(&private_display->lock);
655
656         private_module = private_hwc->private_module;
657         func_hwc = &private_module->func_hwc;
658
659         if (private_module->use_hal_tdm) {
660                 if (num_wnds == 0) {
661                         ret = (tdm_error)hal_tdm_hwc_validate((hal_tdm_hwc *)private_hwc->hwc_backend, NULL, 0, num_types);
662
663                         _pthread_mutex_unlock(&private_display->lock);
664                         return ret;
665                 }
666         } else {
667                 if (!func_hwc->hwc_validate) {
668                         /* LCOV_EXCL_START */
669                         _pthread_mutex_unlock(&private_display->lock);
670                         TDM_WRN("not implemented!!");
671                         return TDM_ERROR_NOT_IMPLEMENTED;
672                         /* LCOV_EXCL_STOP */
673                 }
674
675                 if (num_wnds == 0) {
676                         ret = func_hwc->hwc_validate(private_hwc->hwc_backend, NULL, 0, num_types);
677
678                         _pthread_mutex_unlock(&private_display->lock);
679                         return ret;
680                 }
681         }
682         composited_wnds_backend = calloc(num_wnds, sizeof(tdm_hwc_window *));
683         if (!composited_wnds_backend) {
684                 /* LCOV_EXCL_START */
685                 _pthread_mutex_unlock(&private_display->lock);
686                 return TDM_ERROR_OUT_OF_MEMORY;
687                 /* LCOV_EXCL_STOP */
688         }
689
690         composited_wnds_frontend = (tdm_private_hwc_window **)composited_wnds;
691
692         for (i = 0; i < num_wnds; i++)
693                 composited_wnds_backend[i] = composited_wnds_frontend[i]->hwc_window_backend;
694
695         if (private_module->use_hal_tdm)
696                 ret = (tdm_error)hal_tdm_hwc_validate((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_window **)composited_wnds_backend,
697                                                                         num_wnds, num_types);
698         else
699                 ret = func_hwc->hwc_validate(private_hwc->hwc_backend, composited_wnds_backend,
700                                                                         num_wnds, num_types);
701
702         free(composited_wnds_backend);
703
704         _pthread_mutex_unlock(&private_display->lock);
705
706         return ret;
707 }
708
709 EXTERN tdm_error
710 tdm_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
711                                                                 tdm_hwc_window **hwc_window,
712                                                                 tdm_hwc_window_composition *composition_types)
713 {
714         tdm_private_module *private_module;
715         tdm_func_hwc *func_hwc = NULL;
716         tdm_private_hwc_window * private_hwc_window = NULL;
717         int i = 0;
718
719         HWC_FUNC_ENTRY();
720
721         TDM_RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
722
723         _pthread_mutex_lock(&private_display->lock);
724
725         private_module = private_hwc->private_module;
726         func_hwc = &private_module->func_hwc;
727
728         if (private_module->use_hal_tdm) {
729                 ret = (tdm_error)hal_tdm_hwc_get_changed_composition_types((hal_tdm_hwc *)private_hwc->hwc_backend, num_elements,
730                                                                         (hal_tdm_hwc_window **)hwc_window,
731                                                                         (hal_tdm_hwc_window_composition *)composition_types);
732         } else {
733                 if (!func_hwc->hwc_get_changed_composition_types) {
734                         /* LCOV_EXCL_START */
735                         _pthread_mutex_unlock(&private_display->lock);
736                         TDM_WRN("not implemented!!");
737                         return TDM_ERROR_NOT_IMPLEMENTED;
738                         /* LCOV_EXCL_STOP */
739                 }
740
741                 ret = func_hwc->hwc_get_changed_composition_types(private_hwc->hwc_backend,
742                                                                 num_elements, hwc_window, composition_types);
743         }
744         if (ret != TDM_ERROR_NONE) {
745                 /* LCOV_EXCL_START */
746                 _pthread_mutex_unlock(&private_display->lock);
747                 return ret;
748                 /* LCOV_EXCL_STOP */
749         }
750
751         if (hwc_window == NULL || composition_types == NULL) {
752                 _pthread_mutex_unlock(&private_display->lock);
753                 return TDM_ERROR_NONE;
754         }
755
756         for (i = 0; i < *num_elements; i++) {
757                 private_hwc_window = _tdm_hwc_find_private_hwc_window(private_hwc, hwc_window[i]);
758                 if (private_hwc_window == NULL) {
759                         /* LCOV_EXCL_START */
760                         TDM_ERR("failed! This should never happen!");
761                         tdm_hwc_window_destroy_internal(private_hwc_window);
762                         *num_elements = 0;
763                         _pthread_mutex_unlock(&private_display->lock);
764                         return TDM_ERROR_OPERATION_FAILED;
765                         /* LCOV_EXCL_STOP */
766                 }
767
768                 hwc_window[i] = (tdm_hwc_window*)private_hwc_window;
769         }
770
771         _pthread_mutex_unlock(&private_display->lock);
772
773         return ret;
774 }
775
776 EXTERN tdm_error
777 tdm_hwc_accept_validation(tdm_hwc *hwc)
778 {
779         tdm_private_module *private_module;
780         tdm_func_hwc *func_hwc = NULL;
781
782         HWC_FUNC_ENTRY();
783
784         _pthread_mutex_lock(&private_display->lock);
785
786         private_module = private_hwc->private_module;
787         func_hwc = &private_module->func_hwc;
788
789         if (private_module->use_hal_tdm) {
790                 ret = (tdm_error)hal_tdm_hwc_accept_validation((hal_tdm_hwc *)private_hwc->hwc_backend);
791         } else {
792                 if (!func_hwc->hwc_validate) {
793                         /* LCOV_EXCL_START */
794                         _pthread_mutex_unlock(&private_display->lock);
795                         TDM_WRN("not implemented!!");
796                         return TDM_ERROR_NOT_IMPLEMENTED;
797                         /* LCOV_EXCL_STOP */
798                 }
799
800                 ret = func_hwc->hwc_accept_validation(private_hwc->hwc_backend);
801         }
802         _pthread_mutex_unlock(&private_display->lock);
803
804         return ret;
805 }
806
807 EXTERN tdm_error
808 tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_data)
809 {
810         tdm_private_module *private_module;
811         tdm_func_hwc *func_hwc = NULL;
812         tdm_private_hwc_commit_handler *hwc_commit_handler = NULL;
813         tdm_private_voutput *private_voutput = NULL;
814         tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
815
816         HWC_FUNC_ENTRY();
817
818         _pthread_mutex_lock(&private_display->lock);
819
820         private_module = private_hwc->private_module;
821         func_hwc = &private_module->func_hwc;
822
823         if (!private_module->use_hal_tdm) {
824                 if (!func_hwc->hwc_commit) {
825                         /* LCOV_EXCL_START */
826                         TDM_WRN("not implemented!!");
827                         _pthread_mutex_unlock(&private_display->lock);
828                         return TDM_ERROR_NOT_IMPLEMENTED;
829                         /* LCOV_EXCL_STOP */
830                 }
831         }
832
833 //TODO: I am not sure yet whether we have to check the dpms at hwc_commit.
834 #if 0
835         /* check if the dpms is off */
836         if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) {
837                 TDM_ERR("hwc(%d) dpms: %s", private_hwc->index,
838                                 tdm_dpms_str(private_output->current_dpms_value));
839                 _pthread_mutex_unlock(&private_display->lock);
840                 return TDM_ERROR_DPMS_OFF;
841         }
842 #endif
843
844         if (tdm_debug_module & TDM_DEBUG_COMMIT)
845                 TDM_INFO("hwc(%d) commit", private_hwc->index);
846
847         if (private_module == private_display->virtual_module) {
848                 if (!private_output->private_voutput) {
849                         TDM_ERR("virtual module but don't have voutput");
850                         _pthread_mutex_unlock(&private_display->lock);
851                         return TDM_ERROR_BAD_MODULE;
852                 }
853         }
854
855         if (!private_hwc->regist_commit_cb) {
856                 private_hwc->regist_commit_cb = 1;
857                 if (private_module->use_hal_tdm)
858                         ret = (tdm_error)hal_tdm_hwc_set_commit_handler((hal_tdm_hwc *)private_hwc->hwc_backend, _tdm_hwc_cb_commit_hal_tdm);
859                 else
860                         ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit);
861                 /* LCOV_EXCL_START */
862                 if (ret != TDM_ERROR_NONE) {
863                         private_hwc->regist_commit_cb = 0;
864                         TDM_ERR("hwc(%d) fail to set hwc_set_commit_handler", private_hwc->index);
865                         _pthread_mutex_unlock(&private_display->lock);
866                         return ret;
867                 /* LCOV_EXCL_STOP */
868                 }
869         }
870
871         hwc_commit_handler = calloc(1, sizeof(tdm_private_hwc_commit_handler));
872         if (!hwc_commit_handler) {
873                 /* LCOV_EXCL_START */
874                 TDM_ERR("failed: alloc memory");
875                 _pthread_mutex_unlock(&private_display->lock);
876                 return TDM_ERROR_OUT_OF_MEMORY;
877                 /* LCOV_EXCL_STOP */
878         }
879
880         ret = tdm_thread_cb_add(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
881                                         _tdm_hwc_thread_cb_commit, NULL);
882         if (ret != TDM_ERROR_NONE) {
883                 TDM_ERR("tdm_thread_cb_add failed");
884                 free(hwc_commit_handler);
885                 _pthread_mutex_unlock(&private_display->lock);
886                 return ret;
887         }
888
889         LIST_ADDTAIL(&hwc_commit_handler->link, &private_hwc->hwc_commit_handler_list);
890         hwc_commit_handler->private_hwc = private_hwc;
891         hwc_commit_handler->func = func;
892         hwc_commit_handler->user_data = user_data;
893         hwc_commit_handler->owner_tid = syscall(SYS_gettid);
894         if (hwc_use_vblank)
895                 hwc_commit_handler->use_vblank = 1;
896
897         if (private_module == private_display->virtual_module) {
898                 private_voutput = private_output->private_voutput;
899
900                 if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
901                         voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
902                         voutput_commit_handler->user_data = private_hwc->display_target_buffer;
903                 }
904         }
905
906         if (private_module->use_hal_tdm)
907                 ret = (tdm_error)hal_tdm_hwc_commit((hal_tdm_hwc *)private_hwc->hwc_backend, sync, hwc_commit_handler);
908         else
909                 ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler);
910         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
911
912         if (hwc_use_vblank) {
913                 /* LCOV_EXCL_START */
914                 ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler);
915                 if (ret == TDM_ERROR_NONE) {
916                         if (tdm_debug_module & TDM_DEBUG_COMMIT)
917                                 TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)",
918                                         private_hwc->index, hwc_commit_handler, func, user_data);
919                 } else
920                         goto commit_failed;
921                 /* LCOV_EXCL_STOP */
922         } else {
923                 if (tdm_debug_module & TDM_DEBUG_COMMIT)
924                         TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)",
925                                         private_hwc->index, hwc_commit_handler, func, user_data);
926         }
927
928         _pthread_mutex_unlock(&private_display->lock);
929
930         return ret;
931
932 commit_failed:
933         /* LCOV_EXCL_START */
934         if (hwc_commit_handler) {
935                 tdm_thread_cb_remove(private_hwc, TDM_THREAD_CB_HWC_COMMIT, hwc_commit_handler,
936                                                 _tdm_hwc_thread_cb_commit, NULL);
937                 LIST_DEL(&hwc_commit_handler->link);
938                 free(hwc_commit_handler);
939         }
940
941         _pthread_mutex_unlock(&private_display->lock);
942
943         return ret;
944         /* LCOV_EXCL_STOP */
945 }
946
947 EXTERN tdm_error
948 tdm_hwc_get_commit_fence(tdm_hwc *hwc, int *commit_fence)
949 {
950         tdm_private_module *private_module;
951         tdm_func_hwc *func_hwc = NULL;
952
953         HWC_FUNC_ENTRY();
954
955         _pthread_mutex_lock(&private_display->lock);
956
957         private_module = private_hwc->private_module;
958         func_hwc = &private_module->func_hwc;
959
960         if (private_module->use_hal_tdm) {
961                 ret = (tdm_error)hal_tdm_hwc_get_commit_fence((hal_tdm_hwc *)private_hwc->hwc_backend, commit_fence);
962         } else {
963                 if (!func_hwc->hwc_get_commit_fence) {
964                         /* LCOV_EXCL_START */
965                         _pthread_mutex_unlock(&private_display->lock);
966                         TDM_WRN("not implemented!!");
967                         return TDM_ERROR_NOT_IMPLEMENTED;
968                         /* LCOV_EXCL_STOP */
969                 }
970
971                 ret = func_hwc->hwc_get_commit_fence(private_hwc->hwc_backend, commit_fence);
972         }
973         _pthread_mutex_unlock(&private_display->lock);
974
975         return ret;
976 }
977
978 EXTERN tdm_error
979 tdm_hwc_get_release_fences(tdm_hwc *hwc, uint32_t *num_elements,
980                                                 tdm_hwc_window **hwc_windows, int *fences)
981 {
982         tdm_private_module *private_module;
983         tdm_func_hwc *func_hwc = NULL;
984         tdm_private_hwc_window *private_hwc_window = NULL;
985         int i;
986
987         HWC_FUNC_ENTRY();
988
989         _pthread_mutex_lock(&private_display->lock);
990
991         private_module = private_hwc->private_module;
992         func_hwc = &private_module->func_hwc;
993
994         if (private_module->use_hal_tdm) {
995                 ret = (tdm_error)hal_tdm_hwc_get_release_fences((hal_tdm_hwc *)private_hwc->hwc_backend, num_elements,
996                                                                                         (hal_tdm_hwc_window **)hwc_windows, fences);
997         } else {
998                 if (!func_hwc->hwc_get_release_fences) {
999                         /* LCOV_EXCL_START */
1000                         _pthread_mutex_unlock(&private_display->lock);
1001                         TDM_WRN("not implemented!!");
1002                         return TDM_ERROR_NOT_IMPLEMENTED;
1003                         /* LCOV_EXCL_STOP */
1004                 }
1005
1006                 ret = func_hwc->hwc_get_release_fences(private_hwc->hwc_backend, num_elements,
1007                                                                                         hwc_windows, fences);
1008         }
1009         if (hwc_windows == NULL || fences == NULL) {
1010                 _pthread_mutex_unlock(&private_display->lock);
1011                 return TDM_ERROR_NONE;
1012         }
1013
1014         for (i = 0; i < *num_elements; i++) {
1015                 private_hwc_window = _tdm_hwc_find_private_hwc_window(private_hwc, hwc_windows[i]);
1016                 if (private_hwc_window == NULL) {
1017                         /* LCOV_EXCL_START */
1018                         TDM_ERR("failed! This should never happen!");
1019                         tdm_hwc_window_destroy_internal(private_hwc_window);
1020                         *num_elements = 0;
1021                         _pthread_mutex_unlock(&private_display->lock);
1022                         return TDM_ERROR_OPERATION_FAILED;
1023                         /* LCOV_EXCL_STOP */
1024                 }
1025
1026                 hwc_windows[i] = (tdm_hwc_window*)private_hwc_window;
1027         }
1028
1029         _pthread_mutex_unlock(&private_display->lock);
1030
1031         return ret;
1032 }
1033
1034 tdm_error
1035 tdm_hwc_set_property(tdm_hwc *hwc, uint32_t id, tdm_value value)
1036 {
1037         tdm_private_module *private_module;
1038         tdm_func_hwc *func_hwc = NULL;
1039
1040         HWC_FUNC_ENTRY();
1041
1042         _pthread_mutex_lock(&private_display->lock);
1043
1044         private_module = private_hwc->private_module;
1045         func_hwc = &private_module->func_hwc;
1046
1047         if (private_module->use_hal_tdm) {
1048                 hal_tdm_value hvalue;
1049                 memcpy(&hvalue.ptr, &value.ptr, sizeof(hal_tdm_value));
1050                 ret = (tdm_error)hal_tdm_hwc_set_property((hal_tdm_hwc *)private_hwc->hwc_backend, id, hvalue);
1051         } else {
1052                 if (!func_hwc->hwc_set_property) {
1053                         /* LCOV_EXCL_START */
1054                         _pthread_mutex_unlock(&private_display->lock);
1055                         TDM_WRN("not implemented!!");
1056                         return TDM_ERROR_NOT_IMPLEMENTED;
1057                         /* LCOV_EXCL_STOP */
1058                 }
1059
1060                 ret = func_hwc->hwc_set_property(private_hwc->hwc_backend, id, value);
1061         }
1062         _pthread_mutex_unlock(&private_display->lock);
1063
1064         return ret;
1065 }
1066
1067 tdm_error
1068 tdm_hwc_get_property(tdm_hwc *hwc, uint32_t id, tdm_value *value)
1069 {
1070         tdm_private_module *private_module;
1071         tdm_func_hwc *func_hwc = NULL;
1072
1073         HWC_FUNC_ENTRY();
1074
1075         _pthread_mutex_lock(&private_display->lock);
1076
1077         private_module = private_hwc->private_module;
1078         func_hwc = &private_module->func_hwc;
1079
1080         if (private_module->use_hal_tdm) {
1081                 hal_tdm_value hvalue;
1082                 ret = (tdm_error)hal_tdm_hwc_get_property((hal_tdm_hwc *)private_hwc->hwc_backend, id, &hvalue);
1083                 if (ret == TDM_ERROR_NONE)
1084                         memcpy(&value->ptr, &hvalue.ptr, sizeof(tdm_value));
1085         } else {
1086                 if (!func_hwc->hwc_get_property) {
1087                         /* LCOV_EXCL_START */
1088                         _pthread_mutex_unlock(&private_display->lock);
1089                         TDM_WRN("not implemented!!");
1090                         return TDM_ERROR_NOT_IMPLEMENTED;
1091                         /* LCOV_EXCL_STOP */
1092                 }
1093
1094                 ret = func_hwc->hwc_get_property(private_hwc->hwc_backend, id, value);
1095         }
1096         _pthread_mutex_unlock(&private_display->lock);
1097
1098         return ret;
1099 }
1100
1101 tdm_error
1102 tdm_hwc_get_commit_interval(tdm_hwc *hwc, tdm_hwc_commit_interval *refresh)
1103 {
1104         tdm_private_module *private_module;
1105         tdm_func_hwc *func_hwc = NULL;
1106
1107         HWC_FUNC_ENTRY();
1108
1109         _pthread_mutex_lock(&private_display->lock);
1110
1111         private_module = private_hwc->private_module;
1112         func_hwc = &private_module->func_hwc;
1113
1114         if (private_module->use_hal_tdm) {
1115                 ret = (tdm_error)hal_tdm_hwc_get_commit_interval((hal_tdm_hwc *)private_hwc->hwc_backend, (hal_tdm_hwc_commit_interval *)refresh);
1116         } else {
1117                 /* LCOV_EXCL_START */
1118                 if (!func_hwc->hwc_get_commit_interval) {
1119                         _pthread_mutex_unlock(&private_display->lock);
1120                         return TDM_ERROR_NOT_IMPLEMENTED;
1121                 }
1122
1123                 ret = func_hwc->hwc_get_commit_interval(private_hwc->hwc_backend, refresh);
1124                 /* LCOV_EXCL_STOP */
1125         }
1126         _pthread_mutex_unlock(&private_display->lock);
1127
1128         return ret;
1129 }