75aefe4b5c16e8169d6c9a435454690cfb107692
[platform/core/uifw/libtdm.git] / haltests / src / tc_tdm_output.cpp
1 /**************************************************************************
2  *
3  * Copyright 2016 Samsung Electronics co., Ltd. All Rights Reserved.
4  *
5  * Contact: Konstantin Drabeniuk <k.drabeniuk@samsung.com>
6  * Contact: Andrii Sokolenko <a.sokolenko@samsung.com>
7  * Contact: Roman Marchenko <r.marchenko@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 #include "tc_tdm.h"
32
33 /* LCOV_EXCL_START */
34
35 static void _tc_tdm_output_change_cb(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data);
36 static void _tc_tdm_output_change_cb2(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data);
37
38 TDMOutput::TDMOutput()
39 {
40         has_outputs = false;
41         output_count = TDM_UT_INVALID_VALUE;
42         outputs = NULL;
43
44         done1 = done2 = done3 = false;
45 }
46
47 void TDMOutput::SetUp(void)
48 {
49         TDMDisplay::SetUp();
50
51         ASSERT_EQ(tdm_display_get_output_count(dpy, &output_count), TDM_ERROR_NONE);
52         ASSERT_GE(output_count, 0);
53
54         if (output_count > 0) {
55                 outputs = (tdm_output**)calloc(output_count, sizeof(tdm_output*));
56                 ASSERT_NE(outputs, NULL);
57
58                 for (int o = 0; o < output_count; o++) {
59                         tdm_error ret;
60                         tdm_output *output = tdm_display_get_output(dpy, o, &ret);
61                         ASSERT_EQ(ret, TDM_ERROR_NONE);
62                         ASSERT_NE(output, NULL);
63                         outputs[o] = output;
64                 }
65                 has_outputs = true;
66         } else {
67                 has_outputs = false;
68         }
69 }
70
71 void TDMOutput::TearDown(void)
72 {
73         if (outputs) {
74                 for (int o = 0; o < output_count; o++) {
75                         ASSERT_EQ(tc_tdm_output_unset(dpy, outputs[o]), true);
76                         tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, &done1);
77                         tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, &done2);
78                         tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, &done3);
79                         tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, NULL);
80                 }
81                 free(outputs);
82         }
83
84         TDMDisplay::TearDown();
85 }
86
87 bool
88 tc_tdm_output_mode_setting(tdm_output *output)
89 {
90         const tdm_output_mode *modes = (const tdm_output_mode *)TDM_UT_INVALID_VALUE;
91         const tdm_output_mode *found = NULL;
92         const tdm_output_mode *best = NULL;
93         int count = TDM_UT_INVALID_VALUE;
94         unsigned int pipe = 0;
95
96         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_available_modes(output, &modes, &count) == TDM_ERROR_NONE);
97         TDM_UT_RETURN_FALSE_IF_FAIL(count > 0);
98         TDM_UT_RETURN_FALSE_IF_FAIL(modes != NULL && modes != (const tdm_output_mode *)TDM_UT_INVALID_VALUE);
99
100         for (int i = 0; i < count; i++) {
101                 if (!best)
102                         best = &modes[i];
103                 if (modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
104                         found = &modes[i];
105         }
106         if (!found && best)
107                 found = best;
108
109         TDM_UT_RETURN_FALSE_IF_FAIL(found != NULL);
110
111         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_set_mode(output, found) == TDM_ERROR_NONE);
112
113         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_pipe(output, &pipe) == TDM_ERROR_NONE);
114
115         TDM_INFO("setting output(%d) mode done: %dx%d %d", pipe, found->hdisplay, found->vdisplay, found->vrefresh);
116
117         return true;
118 }
119
120 bool
121 tc_tdm_output_is_async_dpms_enable(tdm_output *output)
122 {
123         tdm_output_capability capabilities = (tdm_output_capability)TDM_UT_INVALID_VALUE;
124         if (tdm_output_get_capabilities(output, &capabilities) != TDM_ERROR_NONE)
125                 return false;
126         return capabilities & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS;
127 }
128
129 bool
130 tc_tdm_output_is_hwc_enable(tdm_output *output)
131 {
132         tdm_output_capability capabilities = (tdm_output_capability)TDM_UT_INVALID_VALUE;
133         if (tdm_output_get_capabilities(output, &capabilities) != TDM_ERROR_NONE)
134                 return false;
135         return capabilities & TDM_OUTPUT_CAPABILITY_HWC;
136 }
137
138 bool
139 tc_tdm_output_is_aod_enable(tdm_output *output)
140 {
141         tdm_output_capability capabilities = (tdm_output_capability)TDM_UT_INVALID_VALUE;
142         if (tdm_output_get_capabilities(output, &capabilities) != TDM_ERROR_NONE)
143                 return false;
144         return capabilities & TDM_OUTPUT_CAPABILITY_EXTENDED_DPMS;
145 }
146
147 bool
148 tc_tdm_output_is_connected(tdm_output *output)
149 {
150         tdm_output_conn_status status;
151         if (tdm_output_get_conn_status(output, &status) != TDM_ERROR_NONE)
152                 return false;
153         return (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) ? true : false;
154 }
155
156 tdm_layer *
157 tc_tdm_output_get_primary_layer(tdm_output *output)
158 {
159         tdm_error ret;
160         tdm_layer *layer;
161         int primary_index = -1;
162
163         TDM_UT_RETURN_VAL_IF_FAIL(tdm_output_get_primary_index(output, &primary_index) == TDM_ERROR_NONE, NULL);
164         TDM_UT_RETURN_VAL_IF_FAIL(primary_index >= 0, NULL);
165
166         layer = tdm_output_get_layer(output, primary_index, &ret);
167         TDM_UT_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, NULL);
168         TDM_UT_RETURN_VAL_IF_FAIL(layer != NULL, NULL);
169
170         return layer;
171 }
172
173 static void
174 _tc_tdm_output_done_cb(tdm_output *output, unsigned int sequence,
175                                            unsigned int tv_sec, unsigned int tv_usec,
176                                            void *user_data)
177 {
178         bool *done = (bool*)user_data;
179         if (done)
180                 *done = true;
181 }
182
183 bool
184 tc_tdm_output_prepare_hwc_buffer(tdm_output *output, tbm_surface_h *buffers, int buffer_count, bool fill)
185 {
186         int w, h;
187         const tdm_output_mode *mode = NULL;
188
189         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_mode(output, &mode) == TDM_ERROR_NONE);
190         TDM_UT_RETURN_FALSE_IF_FAIL(mode != NULL);
191
192         w = mode->hdisplay;
193         h = mode->vdisplay;
194
195         TDM_UT_RETURN_FALSE_IF_FAIL(tc_tdm_buffer_create(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT, fill, buffer_count, buffers) == true);
196
197         return true;
198 }
199
200 bool
201 tc_tdm_output_prepare(tdm_display *dpy, tdm_output *output, bool fill)
202 {
203         tbm_surface_h buffer = NULL;
204         tdm_error ret;
205         int primary_index = -1;
206         tdm_layer *layer;
207         bool done = false;
208         tdm_output_conn_status status;
209         tdm_region fb_damage;
210         tdm_hwc *thwc = NULL;
211         uint32_t num = 0;
212
213         TDM_UT_RETURN_FALSE_IF_FAIL(tc_tdm_output_is_connected(output) == true);
214         TDM_UT_RETURN_FALSE_IF_FAIL(tc_tdm_output_mode_setting(output) == true);
215         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON) == TDM_ERROR_NONE);
216
217         if (tc_tdm_output_is_hwc_enable(output)) {
218                 TDM_UT_RETURN_FALSE_IF_FAIL(tc_tdm_output_prepare_hwc_buffer(output, &buffer, 1, fill) == true);
219                 thwc = tdm_output_get_hwc(output, &ret);
220                 TDM_UT_GOTO_IF_FAIL(thwc != NULL, failed);
221
222                 TDM_UT_GOTO_IF_FAIL(tdm_hwc_set_client_target_buffer(thwc, buffer, fb_damage) == TDM_ERROR_NONE, failed);
223                 TDM_UT_GOTO_IF_FAIL(tdm_hwc_validate(thwc, NULL, 0, &num) == TDM_ERROR_NONE, failed);
224                 TDM_UT_GOTO_IF_FAIL(tdm_hwc_accept_validation(thwc) == TDM_ERROR_NONE, failed);
225                 TDM_UT_GOTO_IF_FAIL(tdm_hwc_commit(thwc, 0, NULL, NULL) == TDM_ERROR_NONE, failed);
226         } else {
227                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_primary_index(output, &primary_index) == TDM_ERROR_NONE);
228                 TDM_UT_RETURN_FALSE_IF_FAIL(primary_index >= 0);
229
230                 layer = tdm_output_get_layer(output, primary_index, &ret);
231                 TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
232                 TDM_UT_RETURN_FALSE_IF_FAIL(layer != NULL);
233
234                 TDM_UT_RETURN_FALSE_IF_FAIL(tc_tdm_layer_prepare_buffer(layer, &buffer, 1, fill) == true);
235                 TDM_UT_RETURN_FALSE_IF_FAIL(buffer != NULL);
236
237                 TDM_UT_GOTO_IF_FAIL(tc_tdm_layer_set_buffer(layer, buffer) == true, failed);
238
239                 if (tdm_helper_output_commit_per_vblank_enabled(output))
240                         TDM_UT_GOTO_IF_FAIL(tdm_layer_commit(layer, NULL, NULL) == TDM_ERROR_NONE, failed);
241                 else
242                         TDM_UT_GOTO_IF_FAIL(tdm_output_commit(output, 0, NULL, NULL) == TDM_ERROR_NONE, failed);
243         }
244
245         TDM_UT_GOTO_IF_FAIL(tdm_output_get_conn_status(output, &status) == TDM_ERROR_NONE, failed);
246         TDM_UT_GOTO_IF_FAIL(status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED, failed);
247
248         while (!done) {
249                 TDM_UT_GOTO_IF_FAIL(tdm_output_wait_vblank(output, 1, 0, _tc_tdm_output_done_cb, &done) == TDM_ERROR_NONE, failed);
250                 TDM_UT_GOTO_IF_FAIL(tc_tdm_display_handle_events(dpy) == TDM_ERROR_NONE, failed);
251         }
252
253         tbm_surface_internal_unref(buffer);
254
255         return true;
256 failed:
257         tbm_surface_internal_unref(buffer);
258
259         return false;
260 }
261
262 bool
263 tc_tdm_output_prepare_all_output(tdm_display *dpy, tdm_output **outputs, int output_count, bool fill)
264 {
265         for (int o = 0; o < output_count; o++) {
266                 if (!tc_tdm_output_is_connected(outputs[o]))
267                         continue;
268                 if (!tc_tdm_output_prepare(dpy, outputs[o], fill))
269                         return false;
270         }
271         return true;
272 }
273
274 bool
275 tc_tdm_output_unset(tdm_display *dpy, tdm_output *output)
276 {
277         tdm_error ret;
278         int count = 0;
279         unsigned int pipe = 0;
280         tdm_hwc *thwc = NULL;
281         const tdm_output_mode *mode = NULL;
282         tdm_output_dpms dpms = TDM_OUTPUT_DPMS_OFF;
283         tdm_region fb_damage;
284         uint32_t num = 0;
285
286         if (tc_tdm_output_is_hwc_enable(output)) {
287                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_mode(output, &mode) == TDM_ERROR_NONE);
288                 if (mode == NULL)
289                         return true;
290                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_dpms(output, &dpms) == TDM_ERROR_NONE);
291                 if (dpms != TDM_OUTPUT_DPMS_ON)
292                         return true;
293
294                 thwc = tdm_output_get_hwc(output, &ret);
295                 TDM_UT_RETURN_FALSE_IF_FAIL(thwc != NULL);
296
297                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_hwc_set_client_target_buffer(thwc, NULL, fb_damage) == TDM_ERROR_NONE);
298                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_hwc_validate(thwc, NULL, 0, &num) == TDM_ERROR_NONE);
299                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_hwc_accept_validation(thwc) == TDM_ERROR_NONE);
300                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_hwc_commit(thwc, 0, NULL, NULL) == TDM_ERROR_NONE);
301         } else {
302                 TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_layer_count(output, &count) == TDM_ERROR_NONE);
303                 TDM_UT_RETURN_FALSE_IF_FAIL(count > 0);
304
305                 for (int l = 0; l < count; l++) {
306                         tdm_layer *layer = tdm_output_get_layer(output, l, &ret);
307                         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
308                         TDM_UT_RETURN_FALSE_IF_FAIL(layer != NULL);
309
310                         if (tc_tdm_layer_is_cursor_layer(layer))
311                                 continue;
312                         if (tc_tdm_layer_is_video_layer(layer))
313                                 continue;
314
315                         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_layer_unset_buffer(layer) == TDM_ERROR_NONE);
316                 }
317         }
318
319         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_pipe(output, &pipe) == TDM_ERROR_NONE);
320
321         TDM_INFO("unsetting output(%d) done", pipe);
322
323         return true;
324 }
325
326 /* msec */
327 double
328 tc_tdm_output_get_vblank_interval_time(tdm_output *output)
329 {
330         const tdm_output_mode *mode = (const tdm_output_mode *)TDM_UT_INVALID_VALUE;
331         tdm_error ret = tdm_output_get_mode(output, &mode);
332
333         assert(ret == TDM_ERROR_NONE);
334         assert(mode != NULL);
335         assert(mode->vrefresh > 0);
336
337         return (double)1.0 / (double)mode->vrefresh;
338 }
339
340 TEST_P(TDMOutput, OutputGetBackendModule)
341 {
342         TDM_UT_SKIP_FLAG(has_outputs);
343
344         for (int o = 0; o < output_count; o++) {
345                 tdm_error ret = (tdm_error)TDM_UT_INVALID_VALUE;
346                 ASSERT_NE(tdm_output_get_backend_module(outputs[o], &ret), NULL);
347                 ASSERT_EQ(ret, TDM_ERROR_NONE);
348         }
349 }
350
351 TEST_P(TDMOutput, OutputGetBackendModuleNullOBject)
352 {
353         TDM_UT_SKIP_FLAG(has_outputs);
354
355         tdm_error ret = (tdm_error)TDM_UT_INVALID_VALUE;
356         ASSERT_EQ(tdm_output_get_backend_module(NULL, &ret), NULL);
357         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
358 }
359
360 TEST_P(TDMOutput, OutputGetBackendModuleNullOther)
361 {
362         TDM_UT_SKIP_FLAG(has_outputs);
363
364         for (int o = 0; o < output_count; o++) {
365                 ASSERT_NE(tdm_output_get_backend_module(outputs[o], NULL), NULL);
366         }
367 }
368
369 TEST_P(TDMOutput, OutputGetCapabilities)
370 {
371         TDM_UT_SKIP_FLAG(has_outputs);
372
373         for (int o = 0; o < output_count; o++) {
374                 tdm_output_capability capabilities = (tdm_output_capability)TDM_UT_INVALID_VALUE;
375                 ASSERT_EQ(tdm_output_get_capabilities(outputs[o], &capabilities), TDM_ERROR_NONE);
376                 ASSERT_NE(capabilities, TDM_UT_INVALID_VALUE);
377         }
378 }
379
380 TEST_P(TDMOutput, OutputGetCapabilitiesNullObject)
381 {
382         TDM_UT_SKIP_FLAG(has_outputs);
383
384         tdm_output_capability capabilities = (tdm_output_capability)TDM_UT_INVALID_VALUE;
385         ASSERT_EQ(tdm_output_get_capabilities(NULL, &capabilities), TDM_ERROR_INVALID_PARAMETER);
386         ASSERT_EQ(capabilities, (tdm_output_capability)TDM_UT_INVALID_VALUE);
387 }
388
389 TEST_P(TDMOutput, OutputGetCapabilitiesNullOther)
390 {
391         TDM_UT_SKIP_FLAG(has_outputs);
392
393         ASSERT_EQ(tdm_output_get_capabilities(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
394 }
395
396 TEST_P(TDMOutput, OutputGetModelInfo)
397 {
398         TDM_UT_SKIP_FLAG(has_outputs);
399
400         for (int o = 0; o < output_count; o++) {
401                 const char *maker = NULL, *model = NULL, *name = NULL;
402                 ASSERT_EQ(tdm_output_get_model_info(outputs[o], &maker, &model, &name), TDM_ERROR_NONE);
403                 ASSERT_NE(maker, NULL);
404                 ASSERT_NE(model, NULL);
405                 ASSERT_NE(name, NULL);
406         }
407 }
408
409 TEST_P(TDMOutput, OutputGetModelInfoNullObject)
410 {
411         TDM_UT_SKIP_FLAG(has_outputs);
412
413         const char *maker = (const char*)TDM_UT_INVALID_VALUE;
414         const char *model = (const char*)TDM_UT_INVALID_VALUE;
415         const char *name = (const char*)TDM_UT_INVALID_VALUE;
416
417         ASSERT_EQ(tdm_output_get_model_info(NULL, &maker, &model, &name), TDM_ERROR_INVALID_PARAMETER);
418         ASSERT_EQ(maker, (const char*)TDM_UT_INVALID_VALUE);
419         ASSERT_EQ(model, (const char*)TDM_UT_INVALID_VALUE);
420         ASSERT_EQ(name, (const char*)TDM_UT_INVALID_VALUE);
421 }
422
423 TEST_P(TDMOutput, OutputGetModelInfoNullOther)
424 {
425         TDM_UT_SKIP_FLAG(has_outputs);
426
427         ASSERT_EQ(tdm_output_get_model_info(outputs[0], NULL, NULL, NULL), TDM_ERROR_NONE);
428 }
429
430 TEST_P(TDMOutput, OutputGetConnStatus)
431 {
432         TDM_UT_SKIP_FLAG(has_outputs);
433
434         for (int o = 0; o < output_count; o++) {
435                 tdm_output_conn_status status = (tdm_output_conn_status)TDM_UT_INVALID_VALUE;
436                 ASSERT_EQ(tdm_output_get_conn_status(outputs[o], &status), TDM_ERROR_NONE);
437                 ASSERT_NE(status, TDM_UT_INVALID_VALUE);
438         }
439 }
440
441 TEST_P(TDMOutput, OutputGetConnStatusNullObject)
442 {
443         TDM_UT_SKIP_FLAG(has_outputs);
444
445         tdm_output_conn_status status = (tdm_output_conn_status)TDM_UT_INVALID_VALUE;
446
447         ASSERT_EQ(tdm_output_get_conn_status(NULL, &status), TDM_ERROR_INVALID_PARAMETER);
448         ASSERT_EQ(status, (tdm_output_conn_status)TDM_UT_INVALID_VALUE);
449 }
450
451 TEST_P(TDMOutput, OutputGetConnStatusNullOther)
452 {
453         TDM_UT_SKIP_FLAG(has_outputs);
454
455         ASSERT_EQ(tdm_output_get_conn_status(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
456 }
457
458 TEST_P(TDMOutput, OutputGetOutputType)
459 {
460         TDM_UT_SKIP_FLAG(has_outputs);
461
462         for (int o = 0; o < output_count; o++) {
463                 tdm_output_type type = (tdm_output_type)TDM_UT_INVALID_VALUE;
464                 ASSERT_EQ(tdm_output_get_output_type(outputs[o], &type), TDM_ERROR_NONE);
465                 ASSERT_NE(type, TDM_UT_INVALID_VALUE);
466         }
467 }
468
469 TEST_P(TDMOutput, OutputGetOutputTypeNullObject)
470 {
471         TDM_UT_SKIP_FLAG(has_outputs);
472
473         tdm_output_type type = (tdm_output_type)TDM_UT_INVALID_VALUE;
474         ASSERT_EQ(tdm_output_get_output_type(NULL, &type), TDM_ERROR_INVALID_PARAMETER);
475         ASSERT_EQ(type, (tdm_output_type)TDM_UT_INVALID_VALUE);
476 }
477
478 TEST_P(TDMOutput, OutputGetOutputTypeNullOther)
479 {
480         TDM_UT_SKIP_FLAG(has_outputs);
481
482         ASSERT_EQ(tdm_output_get_output_type(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
483 }
484
485 TEST_P(TDMOutput, OutputGetLayerCount)
486 {
487         TDM_UT_SKIP_FLAG(has_outputs);
488
489         for (int o = 0; o < output_count; o++) {
490                 int count = TDM_UT_INVALID_VALUE;
491                 if (tc_tdm_output_is_hwc_enable(outputs[o])) {
492                         ASSERT_EQ(tdm_output_get_layer_count(outputs[o], &count), TDM_ERROR_BAD_REQUEST);
493                         ASSERT_EQ(count, 0);
494                 } else {
495                         ASSERT_EQ(tdm_output_get_layer_count(outputs[o], &count), TDM_ERROR_NONE);
496                         ASSERT_GT(count, 0);
497                 }
498         }
499 }
500
501 TEST_P(TDMOutput, OutputGetLayerCountNullObject)
502 {
503         TDM_UT_SKIP_FLAG(has_outputs);
504
505         int count = TDM_UT_INVALID_VALUE;
506         ASSERT_EQ(tdm_output_get_layer_count(NULL, &count), TDM_ERROR_INVALID_PARAMETER);
507         ASSERT_EQ(count, TDM_UT_INVALID_VALUE);
508 }
509
510 TEST_P(TDMOutput, OutputGetLayerCountNullOther)
511 {
512         TDM_UT_SKIP_FLAG(has_outputs);
513
514         ASSERT_EQ(tdm_output_get_layer_count(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
515 }
516
517 TEST_P(TDMOutput, OutputGetLayer)
518 {
519         TDM_UT_SKIP_FLAG(has_outputs);
520
521         for (int o = 0; o < output_count; o++) {
522                 tdm_error ret;
523                 tdm_layer *layer;
524                 int layer_count = TDM_UT_INVALID_VALUE;
525
526                 if (tc_tdm_output_is_hwc_enable(outputs[o])) {
527                         ASSERT_EQ(tdm_output_get_layer_count(outputs[o], &layer_count), TDM_ERROR_BAD_REQUEST);
528                         ASSERT_EQ(layer_count, 0);
529
530                         layer = tdm_output_get_layer(outputs[o], 0, &ret);
531                         ASSERT_EQ(ret, TDM_ERROR_BAD_REQUEST);
532                         ASSERT_EQ(layer, NULL);
533                 } else {
534                         ASSERT_EQ(tdm_output_get_layer_count(outputs[o], &layer_count), TDM_ERROR_NONE);
535                         ASSERT_GT(layer_count, 0);
536
537                         for (int l = 0; l < layer_count; l++) {
538                                 tdm_layer *layer = tdm_output_get_layer(outputs[o], l, &ret);
539                                 ASSERT_EQ(ret, TDM_ERROR_NONE);
540                                 ASSERT_NE(layer, NULL);
541                         }
542                 }
543         }
544 }
545
546 TEST_P(TDMOutput, OutputGetLayerNullObject)
547 {
548         TDM_UT_SKIP_FLAG(has_outputs);
549
550         tdm_error ret;
551         tdm_layer *layer = tdm_output_get_layer(NULL, 0, &ret);
552         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
553         ASSERT_EQ(layer, NULL);
554 }
555
556 TEST_P(TDMOutput, OutputGetLayerNullOther)
557 {
558         TDM_UT_SKIP_FLAG(has_outputs);
559
560         tdm_layer *layer;
561         if (tc_tdm_output_is_hwc_enable(outputs[0])) {
562                 layer = tdm_output_get_layer(outputs[0], 0, NULL);
563                 ASSERT_EQ(layer, NULL);
564         } else {
565                 layer = tdm_output_get_layer(outputs[0], 0, NULL);
566                 ASSERT_NE(layer, NULL);
567         }
568 }
569
570 TEST_P(TDMOutput, OutputGetAvailableProperties)
571 {
572         TDM_UT_SKIP_FLAG(has_outputs);
573
574         for (int o = 0; o < output_count; o++) {
575                 int count = TDM_UT_INVALID_VALUE;
576                 const tdm_prop *props = (const tdm_prop *)TDM_UT_INVALID_VALUE;
577                 ASSERT_EQ(tdm_output_get_available_properties(outputs[o], &props, &count), TDM_ERROR_NONE);
578                 ASSERT_GE(count, 0);
579                 if (count > 0)
580                         ASSERT_TRUE(props != NULL && props != (const tdm_prop *)TDM_UT_INVALID_VALUE);
581         }
582 }
583
584 TEST_P(TDMOutput, OutputGetAvailablePropertiesNullObject)
585 {
586         TDM_UT_SKIP_FLAG(has_outputs);
587
588         const tdm_prop *props = (const tdm_prop *)TDM_UT_INVALID_VALUE;
589         int count = TDM_UT_INVALID_VALUE;
590         ASSERT_EQ(tdm_output_get_available_properties(NULL, &props, &count), TDM_ERROR_INVALID_PARAMETER);
591         ASSERT_EQ(props, (const tdm_prop *)TDM_UT_INVALID_VALUE);
592         ASSERT_EQ(count, TDM_UT_INVALID_VALUE);
593 }
594
595 TEST_P(TDMOutput, OutputGetAvailablePropertiesNullOther)
596 {
597         TDM_UT_SKIP_FLAG(has_outputs);
598
599         ASSERT_EQ(tdm_output_get_available_properties(outputs[0], NULL, NULL), TDM_ERROR_INVALID_PARAMETER);
600 }
601
602 TEST_P(TDMOutput, OutputGetAvailableModes)
603 {
604         TDM_UT_SKIP_FLAG(has_outputs);
605
606         for (int o = 0; o < output_count; o++) {
607                 if (!tc_tdm_output_is_connected(outputs[o]))
608                         continue;
609
610                 int count = TDM_UT_INVALID_VALUE;
611                 const tdm_output_mode *modes_array = (const tdm_output_mode *) TDM_UT_INVALID_VALUE;
612                 ASSERT_EQ(tdm_output_get_available_modes(outputs[o], &modes_array, &count), TDM_ERROR_NONE);
613                 ASSERT_GT(count, 0);
614                 ASSERT_TRUE(modes_array != NULL && modes_array != (const tdm_output_mode *)TDM_UT_INVALID_VALUE);
615         }
616 }
617
618 TEST_P(TDMOutput, OutputGetAvailableModesNullObject)
619 {
620         TDM_UT_SKIP_FLAG(has_outputs);
621
622         int count = TDM_UT_INVALID_VALUE;
623         const tdm_output_mode *modes_array = (const tdm_output_mode *) TDM_UT_INVALID_VALUE;
624         ASSERT_EQ(tdm_output_get_available_modes(NULL, &modes_array, &count), TDM_ERROR_INVALID_PARAMETER);
625         ASSERT_EQ(count, TDM_UT_INVALID_VALUE);
626         ASSERT_EQ(modes_array, (const tdm_output_mode *) TDM_UT_INVALID_VALUE);
627 }
628
629 TEST_P(TDMOutput, OutputGetAvailableModesNullOther)
630 {
631         TDM_UT_SKIP_FLAG(has_outputs);
632
633         ASSERT_EQ(tdm_output_get_available_modes(outputs[0], NULL, NULL), TDM_ERROR_INVALID_PARAMETER);
634 }
635
636 TEST_P(TDMOutput, OutputGetAvailableSize)
637 {
638         TDM_UT_SKIP_FLAG(has_outputs);
639
640         for (int o = 0; o < output_count; o++) {
641                 if (!tc_tdm_output_is_connected(outputs[o]))
642                         continue;
643
644                 int min_w = TDM_UT_INVALID_VALUE, min_h = TDM_UT_INVALID_VALUE;
645                 int max_w = TDM_UT_INVALID_VALUE, max_h = TDM_UT_INVALID_VALUE;
646                 int preferred_align = TDM_UT_INVALID_VALUE;
647                 ASSERT_EQ(tdm_output_get_available_size(outputs[o], &min_w, &min_h, &max_w, &max_h, &preferred_align), TDM_ERROR_NONE);
648                 ASSERT_NE(min_w, TDM_UT_INVALID_VALUE);
649                 ASSERT_NE(min_h, TDM_UT_INVALID_VALUE);
650                 ASSERT_NE(max_w, TDM_UT_INVALID_VALUE);
651                 ASSERT_NE(max_h, TDM_UT_INVALID_VALUE);
652                 ASSERT_NE(preferred_align, TDM_UT_INVALID_VALUE);
653         }
654 }
655
656 TEST_P(TDMOutput, OutputGetAvailableSizeNullObject)
657 {
658         TDM_UT_SKIP_FLAG(has_outputs);
659
660         int min_w = TDM_UT_INVALID_VALUE, min_h = TDM_UT_INVALID_VALUE;
661         int max_w = TDM_UT_INVALID_VALUE, max_h = TDM_UT_INVALID_VALUE;
662         int preferred_align = TDM_UT_INVALID_VALUE;
663         ASSERT_EQ(tdm_output_get_available_size(NULL, &min_w, &min_h, &max_w, &max_h, &preferred_align), TDM_ERROR_INVALID_PARAMETER);
664         ASSERT_EQ(min_w, TDM_UT_INVALID_VALUE);
665         ASSERT_EQ(min_h, TDM_UT_INVALID_VALUE);
666         ASSERT_EQ(max_w, TDM_UT_INVALID_VALUE);
667         ASSERT_EQ(max_h, TDM_UT_INVALID_VALUE);
668         ASSERT_EQ(preferred_align, TDM_UT_INVALID_VALUE);
669 }
670
671 TEST_P(TDMOutput, OutputGetAvailableSizeNullOther)
672 {
673         TDM_UT_SKIP_FLAG(has_outputs);
674
675         ASSERT_EQ(tdm_output_get_available_size(outputs[0], NULL, NULL, NULL, NULL, NULL), TDM_ERROR_NONE);
676 }
677
678 TEST_P(TDMOutput, OutputGetCursorAvailableSize)
679 {
680         TDM_UT_SKIP_FLAG(has_outputs);
681
682         int major = TDM_UT_INVALID_VALUE;
683         int minor = TDM_UT_INVALID_VALUE;
684
685         ASSERT_EQ(tdm_display_get_backend_info(dpy, NULL, NULL, &major, &minor), TDM_ERROR_NONE);
686         if (major > 1 || (major >= 1 && minor >= 5)) {
687                 for (int o = 0; o < output_count; o++) {
688                         int min_w = TDM_UT_INVALID_VALUE, min_h = TDM_UT_INVALID_VALUE;
689                         int max_w = TDM_UT_INVALID_VALUE, max_h = TDM_UT_INVALID_VALUE;
690                         int preferred_align = TDM_UT_INVALID_VALUE;
691                         ASSERT_EQ(tdm_output_get_cursor_available_size(outputs[o], &min_w, &min_h, &max_w, &max_h, &preferred_align), TDM_ERROR_NONE);
692                         ASSERT_NE(min_w, TDM_UT_INVALID_VALUE);
693                         ASSERT_NE(min_h, TDM_UT_INVALID_VALUE);
694                         ASSERT_NE(max_w, TDM_UT_INVALID_VALUE);
695                         ASSERT_NE(max_h, TDM_UT_INVALID_VALUE);
696                         ASSERT_NE(preferred_align, TDM_UT_INVALID_VALUE);
697                 }
698         }
699 }
700
701 TEST_P(TDMOutput, OutputGetCursorAvailableSizeNullObject)
702 {
703         TDM_UT_SKIP_FLAG(has_outputs);
704
705         int major = TDM_UT_INVALID_VALUE;
706         int minor = TDM_UT_INVALID_VALUE;
707
708         ASSERT_EQ(tdm_display_get_backend_info(dpy, NULL, NULL, &major, &minor), TDM_ERROR_NONE);
709         if (major > 1 || (major >= 1 && minor >= 5)) {
710                 for (int o = 0; o < output_count; o++) {
711                         int min_w = TDM_UT_INVALID_VALUE, min_h = TDM_UT_INVALID_VALUE;
712                         int max_w = TDM_UT_INVALID_VALUE, max_h = TDM_UT_INVALID_VALUE;
713                         int preferred_align = TDM_UT_INVALID_VALUE;
714                         ASSERT_EQ(tdm_output_get_cursor_available_size(NULL, &min_w, &min_h, &max_w, &max_h, &preferred_align), TDM_ERROR_INVALID_PARAMETER);
715                         ASSERT_EQ(min_w, TDM_UT_INVALID_VALUE);
716                         ASSERT_EQ(min_h, TDM_UT_INVALID_VALUE);
717                         ASSERT_EQ(max_w, TDM_UT_INVALID_VALUE);
718                         ASSERT_EQ(max_h, TDM_UT_INVALID_VALUE);
719                         ASSERT_EQ(preferred_align, TDM_UT_INVALID_VALUE);
720                 }
721         }
722 }
723
724 TEST_P(TDMOutput, OutputGetCursorAvailableSizeNullOther)
725 {
726         TDM_UT_SKIP_FLAG(has_outputs);
727
728         int major = TDM_UT_INVALID_VALUE;
729         int minor = TDM_UT_INVALID_VALUE;
730
731         ASSERT_EQ(tdm_display_get_backend_info(dpy, NULL, NULL, &major, &minor), TDM_ERROR_NONE);
732         if (major > 1 || (major >= 1 && minor >= 5))
733                 ASSERT_EQ(tdm_output_get_cursor_available_size(outputs[0], NULL, NULL, NULL, NULL, NULL), TDM_ERROR_NONE);
734 }
735
736 TEST_P(TDMOutput, OutputGetCursorAvailableSizeNoMatchVersion)
737 {
738         TDM_UT_SKIP_FLAG(has_outputs);
739
740         int major = TDM_UT_INVALID_VALUE;
741         int minor = TDM_UT_INVALID_VALUE;
742
743         ASSERT_EQ(tdm_display_get_backend_info(dpy, NULL, NULL, &major, &minor), TDM_ERROR_NONE);
744         if (major <= 1 && minor < 5) {
745                 for (int o = 0; o < output_count; o++) {
746                         int min_w = TDM_UT_INVALID_VALUE, min_h = TDM_UT_INVALID_VALUE;
747                         int max_w = TDM_UT_INVALID_VALUE, max_h = TDM_UT_INVALID_VALUE;
748                         int preferred_align = TDM_UT_INVALID_VALUE;
749                         ASSERT_EQ(tdm_output_get_cursor_available_size(outputs[o], &min_w, &min_h, &max_w, &max_h, &preferred_align), TDM_ERROR_BAD_REQUEST);
750                         ASSERT_EQ(min_w, TDM_UT_INVALID_VALUE);
751                         ASSERT_EQ(min_h, TDM_UT_INVALID_VALUE);
752                         ASSERT_EQ(max_w, TDM_UT_INVALID_VALUE);
753                         ASSERT_EQ(max_h, TDM_UT_INVALID_VALUE);
754                         ASSERT_EQ(preferred_align, TDM_UT_INVALID_VALUE);
755                 }
756         }
757 }
758
759 TEST_P(TDMOutput, OutputGetPhysicalSize)
760 {
761         TDM_UT_SKIP_FLAG(has_outputs);
762
763         for (int o = 0; o < output_count; o++) {
764                 unsigned int mmWidth = (unsigned int)TDM_UT_INVALID_VALUE;
765                 unsigned int mmHeight = (unsigned int)TDM_UT_INVALID_VALUE;
766                 ASSERT_EQ(tdm_output_get_physical_size(outputs[o], &mmWidth, &mmHeight), TDM_ERROR_NONE);
767                 ASSERT_NE(mmWidth, (unsigned int)TDM_UT_INVALID_VALUE);
768                 ASSERT_NE(mmHeight, (unsigned int)TDM_UT_INVALID_VALUE);
769         }
770 }
771
772 TEST_P(TDMOutput, OutputGetPhysicalSizeNullObject)
773 {
774         TDM_UT_SKIP_FLAG(has_outputs);
775
776         unsigned int mmWidth = (unsigned int)TDM_UT_INVALID_VALUE;
777         unsigned int mmHeight = (unsigned int)TDM_UT_INVALID_VALUE;
778         ASSERT_EQ(tdm_output_get_physical_size(NULL, &mmWidth, &mmHeight), TDM_ERROR_INVALID_PARAMETER);
779         ASSERT_EQ(mmWidth, (unsigned int)TDM_UT_INVALID_VALUE);
780         ASSERT_EQ(mmHeight, (unsigned int)TDM_UT_INVALID_VALUE);
781 }
782
783 TEST_P(TDMOutput, OutputGetPhysicalSizeNullOther)
784 {
785         TDM_UT_SKIP_FLAG(has_outputs);
786
787         ASSERT_EQ(tdm_output_get_physical_size(outputs[0], NULL, NULL), TDM_ERROR_NONE);
788 }
789
790 TEST_P(TDMOutput, OutputGetSubpixel)
791 {
792         TDM_UT_SKIP_FLAG(has_outputs);
793
794         for (int o = 0; o < output_count; o++) {
795                 unsigned int subpixel = (unsigned int)TDM_UT_INVALID_VALUE;
796                 ASSERT_EQ(tdm_output_get_subpixel(outputs[o], &subpixel), TDM_ERROR_NONE);
797                 ASSERT_NE(subpixel, (unsigned int)TDM_UT_INVALID_VALUE);
798         }
799 }
800
801 TEST_P(TDMOutput, OutputGetSubpixelNullObject)
802 {
803         TDM_UT_SKIP_FLAG(has_outputs);
804
805         unsigned int subpixel = (unsigned int)TDM_UT_INVALID_VALUE;
806         ASSERT_EQ(tdm_output_get_subpixel(NULL, &subpixel), TDM_ERROR_INVALID_PARAMETER);
807         ASSERT_EQ(subpixel, (unsigned int)TDM_UT_INVALID_VALUE);
808 }
809
810 TEST_P(TDMOutput, OutputGetSubpixelNullOther)
811 {
812         TDM_UT_SKIP_FLAG(has_outputs);
813
814         ASSERT_EQ(tdm_output_get_subpixel(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
815 }
816
817 TEST_P(TDMOutput, OutputGetPipe)
818 {
819         TDM_UT_SKIP_FLAG(has_outputs);
820
821         for (int o = 0; o < output_count; o++) {
822                 unsigned int pipe = (unsigned int)TDM_UT_INVALID_VALUE;
823                 ASSERT_EQ(tdm_output_get_pipe(outputs[o], &pipe), TDM_ERROR_NONE);
824                 ASSERT_NE(pipe, (unsigned int)TDM_UT_INVALID_VALUE);
825         }
826 }
827
828 TEST_P(TDMOutput, OutputGetPipeNullObject)
829 {
830         TDM_UT_SKIP_FLAG(has_outputs);
831
832         unsigned int pipe = (unsigned int)TDM_UT_INVALID_VALUE;
833         ASSERT_EQ(tdm_output_get_pipe(NULL, &pipe), TDM_ERROR_INVALID_PARAMETER);
834         ASSERT_EQ(pipe, (unsigned int)TDM_UT_INVALID_VALUE);
835 }
836
837 TEST_P(TDMOutput, OutputGetPipeNullOther)
838 {
839         TDM_UT_SKIP_FLAG(has_outputs);
840
841         ASSERT_EQ(tdm_output_get_pipe(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
842 }
843
844 TEST_P(TDMOutput, OutputGetPrimaryIndex)
845 {
846         TDM_UT_SKIP_FLAG(has_outputs);
847
848         for (int o = 0; o < output_count; o++) {
849                 int primary_index = TDM_UT_INVALID_VALUE;
850
851                 if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
852                         ASSERT_EQ(tdm_output_get_primary_index(outputs[o], &primary_index), TDM_ERROR_NONE);
853                         ASSERT_NE(primary_index, TDM_UT_INVALID_VALUE);
854                 } else
855                         TDM_UT_SKIP_FLAG(0);
856         }
857 }
858
859 TEST_P(TDMOutput, OutputGetPrimaryIndexNullObject)
860 {
861         TDM_UT_SKIP_FLAG(has_outputs);
862
863         int primary_index = TDM_UT_INVALID_VALUE;
864         ASSERT_EQ(tdm_output_get_primary_index(NULL, &primary_index), TDM_ERROR_INVALID_PARAMETER);
865         ASSERT_EQ(primary_index, TDM_UT_INVALID_VALUE);
866 }
867
868 TEST_P(TDMOutput, OutputGetPrimaryIndexNullOther)
869 {
870         TDM_UT_SKIP_FLAG(has_outputs);
871
872         ASSERT_EQ(tdm_output_get_primary_index(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
873 }
874
875 TEST_P(TDMOutput, DISABLED_OutputSetProperty)
876 {
877 }
878
879 TEST_P(TDMOutput, OutputSetPropertyNullObject)
880 {
881         tdm_value value = {.s32 = 0};
882
883         ASSERT_EQ(tdm_output_set_property(NULL, 0, value), TDM_ERROR_INVALID_PARAMETER);
884 }
885
886 TEST_P(TDMOutput, OutputGetProperty)
887 {
888         TDM_UT_SKIP_FLAG(has_outputs);
889
890         for (int o = 0; o < output_count; o++) {
891                 int count = TDM_UT_INVALID_VALUE;
892                 const tdm_prop *props = (const tdm_prop *)TDM_UT_INVALID_VALUE;
893                 ASSERT_EQ(tdm_output_get_available_properties(outputs[o], &props, &count), TDM_ERROR_NONE);
894                 ASSERT_GE(count, 0);
895                 if (count > 0) {
896                         ASSERT_TRUE(props != NULL && props != (const tdm_prop *)TDM_UT_INVALID_VALUE);
897
898                         for (int i = 0; i < count; i++) {
899                                 tdm_value value = {.s32 = TDM_UT_INVALID_VALUE};
900                                 ASSERT_EQ(tdm_output_get_property(outputs[o], props[i].id, &value), TDM_ERROR_NONE);
901                                 ASSERT_NE(value.s32, TDM_UT_INVALID_VALUE);
902                         }
903                 }
904         }
905 }
906
907 TEST_P(TDMOutput, OutputGetPropertyNullObject)
908 {
909         TDM_UT_SKIP_FLAG(has_outputs);
910
911         tdm_value value = {.s32 = TDM_UT_INVALID_VALUE};
912         ASSERT_EQ(tdm_output_get_property(NULL, 0, &value), TDM_ERROR_INVALID_PARAMETER);
913         ASSERT_EQ(value.s32, TDM_UT_INVALID_VALUE);
914 }
915
916 TEST_P(TDMOutput, OutputGetPropertyNullOther)
917 {
918         TDM_UT_SKIP_FLAG(has_outputs);
919
920         ASSERT_EQ(tdm_output_get_property(outputs[0], 0, NULL), TDM_ERROR_INVALID_PARAMETER);
921 }
922
923 static void
924 _tc_tdm_output_change_cb(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
925 {
926         bool *done = (bool *)user_data;
927         if (done)
928                 *done = true;
929 }
930
931 TEST_P(TDMOutput, OutputAddChangeHandler)
932 {
933         TDM_UT_SKIP_FLAG(has_outputs);
934
935         for (int o = 0; o < output_count; o++) {
936                 if (!tc_tdm_output_is_connected(outputs[o]))
937                         continue;
938
939                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
940
941                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
942
943                 done1 = false;
944                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb, &done1), TDM_ERROR_NONE);
945                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
946                 ASSERT_EQ(done1, true);
947         }
948 }
949
950 TEST_P(TDMOutput, OutputAddChangeHandlerTwice)
951 {
952         TDM_UT_SKIP_FLAG(has_outputs);
953
954         ASSERT_EQ(tdm_output_add_change_handler(outputs[0], _tc_tdm_output_change_cb, NULL), TDM_ERROR_NONE);
955         ASSERT_EQ(tdm_output_add_change_handler(outputs[0], _tc_tdm_output_change_cb, NULL), TDM_ERROR_BAD_REQUEST);
956 }
957
958 TEST_P(TDMOutput, OutputAddChangeHandlerNullObject)
959 {
960         TDM_UT_SKIP_FLAG(has_outputs);
961
962         ASSERT_EQ(tdm_output_add_change_handler(NULL, _tc_tdm_output_change_cb, NULL), TDM_ERROR_INVALID_PARAMETER);
963 }
964
965 TEST_P(TDMOutput, OutputAddChangeHandlerNullOther)
966 {
967         TDM_UT_SKIP_FLAG(has_outputs);
968
969         ASSERT_EQ(tdm_output_add_change_handler(outputs[0], NULL, NULL), TDM_ERROR_INVALID_PARAMETER);
970 }
971
972 TEST_P(TDMOutput, OutputRemoveChangeHandler)
973 {
974         TDM_UT_SKIP_FLAG(has_outputs);
975
976         for (int o = 0; o < output_count; o++) {
977                 for (int t = 0; t < 10; t++) {
978                         ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb, NULL), TDM_ERROR_NONE);
979                         tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, NULL);
980                 }
981         }
982 }
983
984 TEST_P(TDMOutput, OutputRemoveChangeHandlerDifferentData)
985 {
986         TDM_UT_SKIP_FLAG(has_outputs);
987
988         for (int o = 0; o < output_count; o++) {
989                 if (!tc_tdm_output_is_connected(outputs[o]))
990                         continue;
991
992                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
993
994                 done1 = false;
995                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb, &done1), TDM_ERROR_NONE);
996                 tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, NULL);
997
998                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
999                 ASSERT_EQ(done1, true);
1000         }
1001 }
1002
1003 static void
1004 _tc_tdm_output_change_cb2(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
1005 {
1006         bool *done = (bool*)user_data;
1007         if (done)
1008                 *done = true;
1009         tdm_output_remove_change_handler(output, _tc_tdm_output_change_cb2, user_data);
1010 }
1011
1012 TEST_P(TDMOutput, OutputRemoveChangeHandlerInHandler)
1013 {
1014         TDM_UT_SKIP_FLAG(has_outputs);
1015
1016         for (int o = 0; o < output_count; o++) {
1017                 if (!tc_tdm_output_is_connected(outputs[o]))
1018                         continue;
1019
1020                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1021
1022                 done1 = false;
1023                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb2, &done1), TDM_ERROR_NONE);
1024                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1025                 ASSERT_EQ(done1, true);
1026
1027                 done2 = false;
1028                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb, &done2), TDM_ERROR_NONE);
1029                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1030                 ASSERT_EQ(done2, true);
1031
1032                 done3 = false;
1033                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb2, &done3), TDM_ERROR_NONE);
1034                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1035                 ASSERT_EQ(done3, true);
1036         }
1037 }
1038
1039 TEST_P(TDMOutput, OutputRemoveChangeHandlerNullObject)
1040 {
1041         TDM_UT_SKIP_FLAG(has_outputs);
1042
1043         tdm_output_remove_change_handler(NULL, _tc_tdm_output_change_cb, NULL);
1044 }
1045
1046 TEST_P(TDMOutput, OutputRemoveChangeHandlerNullOther)
1047 {
1048         TDM_UT_SKIP_FLAG(has_outputs);
1049
1050         tdm_output_remove_change_handler(outputs[0], NULL, NULL);
1051 }
1052
1053 TEST_P(TDMOutput, OutputSetMode)
1054 {
1055         TDM_UT_SKIP_FLAG(has_outputs);
1056
1057         for (int o = 0; o < output_count; o++) {
1058                 const tdm_output_mode *modes;
1059                 int count;
1060                 if (!tc_tdm_output_is_connected(outputs[o]))
1061                         continue;
1062
1063                 ASSERT_EQ(tdm_output_get_available_modes(outputs[o], &modes, &count), TDM_ERROR_NONE);
1064                 ASSERT_NE(modes, NULL);
1065                 ASSERT_GT(count, 0);
1066
1067                 for (int m = 0; m < count; m++)
1068                         ASSERT_EQ(tdm_output_set_mode(outputs[o], modes + m), TDM_ERROR_NONE);
1069         }
1070 }
1071
1072 TEST_P(TDMOutput, OutputSetModeNullObject)
1073 {
1074         TDM_UT_SKIP_FLAG(has_outputs);
1075
1076         const tdm_output_mode *mode = (const tdm_output_mode *)TDM_UT_INVALID_VALUE;
1077         ASSERT_EQ(tdm_output_set_mode(NULL, mode), TDM_ERROR_INVALID_PARAMETER);
1078 }
1079
1080 TEST_P(TDMOutput, OutputSetModeNullOther)
1081 {
1082         TDM_UT_SKIP_FLAG(has_outputs);
1083
1084         for (int o = 0; o < output_count; o++) {
1085                 if (!tc_tdm_output_is_connected(outputs[o]))
1086                         continue;
1087
1088                 ASSERT_EQ(tdm_output_set_mode(outputs[o], NULL), TDM_ERROR_INVALID_PARAMETER);
1089         }
1090 }
1091
1092 TEST_P(TDMOutput, OutputGetMode)
1093 {
1094         TDM_UT_SKIP_FLAG(has_outputs);
1095
1096         for (int o = 0; o < output_count; o++) {
1097                 const tdm_output_mode *modes;
1098                 int count;
1099
1100                 if (!tc_tdm_output_is_connected(outputs[o]))
1101                         continue;
1102
1103                 ASSERT_EQ(tdm_output_get_available_modes(outputs[o], &modes, &count), TDM_ERROR_NONE);
1104                 ASSERT_NE(modes, NULL);
1105                 ASSERT_GT(count, 0);
1106
1107                 for (int m = 0; m < count; m++) {
1108                         const tdm_output_mode *current_mode;
1109                         ASSERT_EQ(tdm_output_set_mode(outputs[o], modes + m), TDM_ERROR_NONE);
1110                         ASSERT_EQ(tdm_output_get_mode(outputs[o], &current_mode), TDM_ERROR_NONE);
1111                         ASSERT_EQ(current_mode, modes + m);
1112                 }
1113         }
1114 }
1115
1116 TEST_P(TDMOutput, OutputGetModeNullObject)
1117 {
1118         TDM_UT_SKIP_FLAG(has_outputs);
1119
1120         const tdm_output_mode *current_mode = (const tdm_output_mode *)TDM_UT_INVALID_VALUE;
1121         ASSERT_EQ(tdm_output_get_mode(NULL, &current_mode), TDM_ERROR_INVALID_PARAMETER);
1122         ASSERT_EQ(current_mode, (const tdm_output_mode *)TDM_UT_INVALID_VALUE);
1123 }
1124
1125 TEST_P(TDMOutput, OutputGetModeNullOther)
1126 {
1127         TDM_UT_SKIP_FLAG(has_outputs);
1128
1129         ASSERT_EQ(tdm_output_get_mode(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
1130 }
1131
1132 TEST_P(TDMOutput, OutputGetModeNoSet)
1133 {
1134         TDM_UT_SKIP_FLAG(has_outputs);
1135
1136         for (int o = 0; o < output_count; o++) {
1137                 const tdm_output_mode *mode;
1138                 ASSERT_EQ(tdm_output_get_mode(outputs[o], &mode), TDM_ERROR_NONE);
1139                 ASSERT_EQ(mode, NULL);
1140         }
1141 }
1142
1143 TEST_P(TDMOutput, OutputSetDpms)
1144 {
1145         TDM_UT_SKIP_FLAG(has_outputs);
1146
1147         for (int o = 0; o < output_count; o++) {
1148                 if (!tc_tdm_output_is_connected(outputs[o]))
1149                         continue;
1150
1151                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1152                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_STANDBY), TDM_ERROR_NONE);
1153                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_SUSPEND), TDM_ERROR_NONE);
1154                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1155                 if (tc_tdm_output_is_aod_enable(outputs[o])) {
1156                         ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_AOD), TDM_ERROR_NONE);
1157                 } else {
1158                         ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_AOD), TDM_ERROR_BAD_REQUEST);
1159                 }
1160         }
1161 }
1162
1163 TEST_P(TDMOutput, OutputSetDpmsNullObject)
1164 {
1165         TDM_UT_SKIP_FLAG(has_outputs);
1166
1167         ASSERT_EQ(tdm_output_set_dpms(NULL, TDM_OUTPUT_DPMS_OFF), TDM_ERROR_INVALID_PARAMETER);
1168 }
1169
1170 TEST_P(TDMOutput, OutputSetDpmsNullOther)
1171 {
1172         TDM_UT_SKIP_FLAG(has_outputs);
1173
1174         ASSERT_EQ(tdm_output_set_dpms(outputs[0], (tdm_output_dpms)-1), TDM_ERROR_BAD_REQUEST);
1175         ASSERT_EQ(tdm_output_set_dpms(outputs[0], (tdm_output_dpms)INT_MAX), TDM_ERROR_BAD_REQUEST);
1176 }
1177
1178 TEST_P(TDMOutput, OutputSetDpmsAsync)
1179 {
1180         TDM_UT_SKIP_FLAG(has_outputs);
1181
1182         for (int o = 0; o < output_count; o++) {
1183                 if (!tc_tdm_output_is_connected(outputs[o]))
1184                         continue;
1185                 if (!tc_tdm_output_is_async_dpms_enable(outputs[o]))
1186                         continue;
1187
1188                 done1 = false;
1189                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1190                 ASSERT_EQ(tdm_output_add_change_handler(outputs[o], _tc_tdm_output_change_cb, &done1), TDM_ERROR_NONE);
1191                 ASSERT_EQ(tdm_output_set_dpms_async(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1192                 while (!done1)
1193                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1194                 tdm_output_remove_change_handler(outputs[o], _tc_tdm_output_change_cb, &done1);
1195         }
1196 }
1197
1198 TEST_P(TDMOutput, OutputGetDpms)
1199 {
1200         TDM_UT_SKIP_FLAG(has_outputs);
1201
1202         for (int o = 0; o < output_count; o++) {
1203                 tdm_output_dpms dpms_value;
1204
1205                 if (!tc_tdm_output_is_connected(outputs[o]))
1206                         continue;
1207
1208                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1209                 ASSERT_EQ(tdm_output_get_dpms(outputs[o], &dpms_value), TDM_ERROR_NONE);
1210                 ASSERT_EQ(dpms_value, TDM_OUTPUT_DPMS_OFF);
1211
1212                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_STANDBY), TDM_ERROR_NONE);
1213                 ASSERT_EQ(tdm_output_get_dpms(outputs[o], &dpms_value), TDM_ERROR_NONE);
1214                 ASSERT_EQ(dpms_value, TDM_OUTPUT_DPMS_STANDBY);
1215
1216                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_SUSPEND), TDM_ERROR_NONE);
1217                 ASSERT_EQ(tdm_output_get_dpms(outputs[o], &dpms_value), TDM_ERROR_NONE);
1218                 ASSERT_EQ(dpms_value, TDM_OUTPUT_DPMS_SUSPEND);
1219
1220                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1221                 ASSERT_EQ(tdm_output_get_dpms(outputs[o], &dpms_value), TDM_ERROR_NONE);
1222                 ASSERT_EQ(dpms_value, TDM_OUTPUT_DPMS_ON);
1223
1224                 if (tc_tdm_output_is_aod_enable(outputs[o])) {
1225                         ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_AOD), TDM_ERROR_NONE);
1226                         ASSERT_EQ(tdm_output_get_dpms(outputs[o], &dpms_value), TDM_ERROR_NONE);
1227                         ASSERT_EQ(dpms_value, TDM_OUTPUT_DPMS_AOD);
1228                 } else {
1229                         ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_AOD), TDM_ERROR_BAD_REQUEST);
1230                 }
1231         }
1232 }
1233
1234 TEST_P(TDMOutput, OutputGetDpmsNullObject)
1235 {
1236         TDM_UT_SKIP_FLAG(has_outputs);
1237
1238         tdm_output_dpms dpms_value = (tdm_output_dpms)TDM_UT_INVALID_VALUE;
1239         ASSERT_EQ(tdm_output_get_dpms(NULL, &dpms_value), TDM_ERROR_INVALID_PARAMETER);
1240         ASSERT_EQ(dpms_value, (tdm_output_dpms)TDM_UT_INVALID_VALUE);
1241 }
1242
1243 TEST_P(TDMOutput, OutputGetDpmsNullOther)
1244 {
1245         TDM_UT_SKIP_FLAG(has_outputs);
1246
1247         ASSERT_EQ(tdm_output_get_dpms(outputs[0], NULL), TDM_ERROR_INVALID_PARAMETER);
1248 }
1249
1250 TEST_P(TDMOutput, OutputWaitVblank)
1251 {
1252         TDM_UT_SKIP_FLAG(has_outputs);
1253
1254         for (int o = 0; o < output_count; o++) {
1255                 if (!tc_tdm_output_is_connected(outputs[o]))
1256                         continue;
1257
1258                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1259
1260                 for (int t = 0; t < 10; t++) {
1261                         double start, end, interval;
1262
1263                         interval = tc_tdm_output_get_vblank_interval_time(outputs[o]);
1264
1265                         done1 = false;
1266                         start = tdm_helper_get_time();
1267                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], 1, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1268                         while (!done1)
1269                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1270                         end = tdm_helper_get_time();
1271
1272                         /* "+ interval" consider the delay of socket communication between kernel and platform */
1273                         ASSERT_LT((end - start), (interval + interval));
1274                 }
1275         }
1276 }
1277
1278 TEST_P(TDMOutput, OutputWaitVblankNullObject)
1279 {
1280         TDM_UT_SKIP_FLAG(has_outputs);
1281
1282         ASSERT_EQ(tdm_output_wait_vblank(NULL, 1, 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_INVALID_PARAMETER);
1283 }
1284
1285 TEST_P(TDMOutput, OutputWaitVblankNullOther)
1286 {
1287         TDM_UT_SKIP_FLAG(has_outputs);
1288
1289         for (int o = 0; o < output_count; o++) {
1290                 if (!tc_tdm_output_is_connected(outputs[o]))
1291                         continue;
1292
1293                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1294
1295                 ASSERT_EQ(tdm_output_wait_vblank(outputs[o], 1, 0, NULL, NULL), TDM_ERROR_NONE);
1296         }
1297 }
1298
1299 TEST_P(TDMOutput, OutputWaitVblankTimeout)
1300 {
1301         TDM_UT_SKIP_FLAG(has_outputs);
1302
1303         for (int o = 0; o < output_count; o++) {
1304                 if (!tc_tdm_output_is_connected(outputs[o]))
1305                         continue;
1306
1307                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1308
1309                 ASSERT_EQ(tdm_output_wait_vblank(outputs[o], 1, 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_NONE);
1310
1311                 usleep(1100000);
1312                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1313
1314                 ASSERT_GT(tdm_helper_output_vblank_timer_expired(outputs[o]), 0);
1315         }
1316 }
1317
1318 TEST_P(TDMOutput, OutputWaitVblankInterval0)
1319 {
1320         TDM_UT_SKIP_FLAG(has_outputs);
1321
1322         ASSERT_EQ(tdm_output_wait_vblank(outputs[0], 0, 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_INVALID_PARAMETER);
1323 }
1324
1325 TEST_P(TDMOutput, OutputWaitVblankInterval)
1326 {
1327         TDM_UT_SKIP_FLAG(has_outputs);
1328
1329         for (int o = 0; o < output_count; o++) {
1330                 if (!tc_tdm_output_is_connected(outputs[o]))
1331                         continue;
1332
1333                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1334
1335                 /* start from 1 */
1336                 for (int t = 1; t < 10; t++) {
1337                         double start, end, interval;
1338
1339                         interval = tc_tdm_output_get_vblank_interval_time(outputs[o]);
1340
1341                         done1 = false;
1342                         start = tdm_helper_get_time();
1343                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1344                         while (!done1)
1345                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1346                         end = tdm_helper_get_time();
1347
1348                         /* "+ interval" consider the delay of socket communication between kernel and platform */
1349                         ASSERT_GT((end - start), (interval * (t - 1)));
1350                         ASSERT_LT((end - start), (interval * t + interval));
1351                 }
1352         }
1353 }
1354
1355 TEST_P(TDMOutput, OutputWaitVblankFewTimesInOneVblank)
1356 {
1357         TDM_UT_SKIP_FLAG(has_outputs);
1358
1359         for (int o = 0; o < output_count; o++) {
1360                 if (!tc_tdm_output_is_connected(outputs[o]))
1361                         continue;
1362
1363                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1364
1365                 /* start from 1 */
1366                 for (int t = 1; t < 10; t++) {
1367                         double start, end, interval;
1368
1369                         interval = tc_tdm_output_get_vblank_interval_time(outputs[o]);
1370
1371                         done1 = done2 = done3 = false;
1372                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1373                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1374                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1375
1376                         start = tdm_helper_get_time();
1377                         while (!done1 || !done2 || !done3)
1378                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1379                         end = tdm_helper_get_time();
1380
1381                         /* "+ interval" consider the delay of socket communication between kernel and platform */
1382                         ASSERT_GT((end - start), (interval * (t - 1)));
1383                         ASSERT_LT((end - start), (interval * t + interval));
1384                 }
1385         }
1386 }
1387
1388 TEST_P(TDMOutput, OutputWaitVblankBeforeDpmsOff)
1389 {
1390         TDM_UT_SKIP_FLAG(has_outputs);
1391
1392         for (int o = 0; o < output_count; o++) {
1393                 if (!tc_tdm_output_is_connected(outputs[o]))
1394                         continue;
1395
1396                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], false), true);
1397
1398                 for (int t = 0; t < 10; t++) {
1399                         bool done = false;
1400
1401                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], 1, 0, _tc_tdm_output_done_cb, &done), TDM_ERROR_NONE);
1402                         if (t == 9)
1403                                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1404                         while (!done)
1405                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1406                 }
1407         }
1408 }
1409
1410 TEST_P(TDMOutput, OutputRemoveVblankHandler)
1411 {
1412         TDM_UT_SKIP_FLAG(has_outputs);
1413
1414         for (int o = 0; o < output_count; o++) {
1415                 if (!tc_tdm_output_is_connected(outputs[o]))
1416                         continue;
1417
1418                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1419
1420                 /* start from 1 */
1421                 for (int t = 1; t < 10; t++) {
1422                         done1 = done2 = done3 = false;
1423                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1424                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1425                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1426                         tdm_output_remove_vblank_handler(outputs[o], _tc_tdm_output_done_cb, &done2);
1427                         while (!done1 || done2 || !done3)
1428                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1429                 }
1430         }
1431 }
1432
1433 TEST_P(TDMOutput, OutputRemoveVblankHandlerDifferentData)
1434 {
1435         TDM_UT_SKIP_FLAG(has_outputs);
1436
1437         for (int o = 0; o < output_count; o++) {
1438                 if (!tc_tdm_output_is_connected(outputs[o]))
1439                         continue;
1440
1441                 tc_tdm_output_prepare(dpy, outputs[o], true);
1442
1443                 /* start from 1 */
1444                 for (int t = 1; t < 10; t++) {
1445                         done1 = done2 = done3 = false;
1446                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1447                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1448                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1449                         tdm_output_remove_vblank_handler(outputs[o], _tc_tdm_output_done_cb, NULL);
1450                         while (!done1 || !done2 || !done3)
1451                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1452                 }
1453         }
1454 }
1455
1456 static void
1457 _tc_tdm_output_done_cb2(tdm_output *output, unsigned int sequence,
1458                                                 unsigned int tv_sec, unsigned int tv_usec,
1459                                                 void *user_data)
1460 {
1461         bool *done = (bool*)user_data;
1462         if (done)
1463                 *done = true;
1464         tdm_output_remove_commit_handler(output, _tc_tdm_output_done_cb2, user_data);
1465 }
1466
1467 TEST_P(TDMOutput, OutputRemoveVblankHandlerInHandler)
1468 {
1469         TDM_UT_SKIP_FLAG(has_outputs);
1470
1471         for (int o = 0; o < output_count; o++) {
1472                 if (!tc_tdm_output_is_connected(outputs[o]))
1473                         continue;
1474
1475                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1476
1477                 /* start from 1 */
1478                 for (int t = 1; t < 10; t++) {
1479                         done1 = done2 = done3 = false;
1480                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1481                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1482                         ASSERT_EQ(tdm_output_wait_vblank(outputs[o], t, 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1483                         while (!done1 || !done2 || !done3)
1484                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1485                 }
1486         }
1487 }
1488
1489 TEST_P(TDMOutput, OutputCommit)
1490 {
1491         TDM_UT_SKIP_FLAG(has_outputs);
1492
1493         for (int o = 0; o < output_count; o++) {
1494                 /* if true, have to use tdm_layer_commit. so skip */
1495                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1496                         continue;
1497
1498                 if (!tc_tdm_output_is_connected(outputs[o]))
1499                         continue;
1500
1501                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1502
1503                 for (int t = 0; t < 10; t++) {
1504                         double start, end, interval;
1505
1506                         interval = tc_tdm_output_get_vblank_interval_time(outputs[o]);
1507
1508                         done1 = false;
1509                         start = tdm_helper_get_time();
1510                         if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1511                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1512                                 while (!done1)
1513                                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1514                                 end = tdm_helper_get_time();
1515
1516                                 /* "+ interval" consider the delay of socket communication between kernel and platform */
1517                                 ASSERT_LT((end - start), (interval + interval));
1518                         } else
1519                                 TDM_UT_SKIP_FLAG(0);
1520                 }
1521         }
1522 }
1523
1524 TEST_P(TDMOutput, OutputCommitNullObject)
1525 {
1526         TDM_UT_SKIP_FLAG(has_outputs);
1527
1528         ASSERT_EQ(tdm_output_commit(NULL, 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_INVALID_PARAMETER);
1529 }
1530
1531 TEST_P(TDMOutput, OutputCommitNullOther)
1532 {
1533         TDM_UT_SKIP_FLAG(has_outputs);
1534
1535         for (int o = 0; o < output_count; o++) {
1536                 /* if true, have to use tdm_layer_commit. so skip */
1537                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1538                         continue;
1539
1540                 if (!tc_tdm_output_is_connected(outputs[o]))
1541                         continue;
1542
1543                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_ON), TDM_ERROR_NONE);
1544                 if (!tc_tdm_output_is_hwc_enable(outputs[o]))
1545                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, NULL, NULL), TDM_ERROR_NONE);
1546                 else
1547                         TDM_UT_SKIP_FLAG(0);
1548         }
1549 }
1550
1551 TEST_P(TDMOutput, OutputCommitDpmsSuspend)
1552 {
1553         TDM_UT_SKIP_FLAG(has_outputs);
1554
1555         for (int o = 0; o < output_count; o++) {
1556                 /* if true, have to use tdm_layer_commit. so skip */
1557                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1558                         continue;
1559
1560                 if (!tc_tdm_output_is_connected(outputs[o]))
1561                         continue;
1562
1563                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1564
1565                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_SUSPEND), TDM_ERROR_NONE);
1566
1567                 if (!tc_tdm_output_is_hwc_enable(outputs[o]))
1568                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_DPMS_OFF);
1569                 else
1570                         TDM_UT_SKIP_FLAG(0);
1571         }
1572 }
1573
1574 TEST_P(TDMOutput, OutputCommitDpmsOff)
1575 {
1576         TDM_UT_SKIP_FLAG(has_outputs);
1577
1578         for (int o = 0; o < output_count; o++) {
1579                 /* if true, have to use tdm_layer_commit. so skip */
1580                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1581                         continue;
1582
1583                 if (!tc_tdm_output_is_connected(outputs[o]))
1584                         continue;
1585
1586                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1587
1588                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_OFF), TDM_ERROR_NONE);
1589
1590                 if (!tc_tdm_output_is_hwc_enable(outputs[o]))
1591                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, NULL), TDM_ERROR_DPMS_OFF);
1592                 else
1593                         TDM_UT_SKIP_FLAG(0);
1594         }
1595 }
1596
1597 TEST_P(TDMOutput, OutputCommitDpmsAOD)
1598 {
1599         TDM_UT_SKIP_FLAG(has_outputs);
1600
1601         for (int o = 0; o < output_count; o++) {
1602                 /* if true, have to use tdm_layer_commit. so skip */
1603                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1604                         continue;
1605
1606                 if (!tc_tdm_output_is_connected(outputs[o]))
1607                         continue;
1608
1609                 if (!tc_tdm_output_is_aod_enable(outputs[o]))
1610                         continue;
1611
1612                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1613
1614                 ASSERT_EQ(tdm_output_set_dpms(outputs[o], TDM_OUTPUT_DPMS_AOD), TDM_ERROR_NONE);
1615
1616                 for (int t = 0; t < 10; t++) {
1617                         done1 = false;
1618                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1619                         while (!done1)
1620                                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1621                 }
1622         }
1623 }
1624
1625 TEST_P(TDMOutput, OutputCommitAfterLayerCommit)
1626 {
1627         TDM_UT_SKIP_FLAG(has_outputs);
1628
1629         for (int o = 0; o < output_count; o++) {
1630                 int index = TDM_UT_INVALID_VALUE;
1631                 tdm_layer *layer;
1632                 tdm_error ret;
1633
1634                 if (!tc_tdm_output_is_connected(outputs[o]))
1635                         continue;
1636
1637                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1638
1639                 if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1640                         ASSERT_EQ(tdm_output_get_primary_index(outputs[o], &index), TDM_ERROR_NONE);
1641                         ASSERT_NE(index, TDM_UT_INVALID_VALUE);
1642                 } else
1643                         TDM_UT_SKIP_FLAG(0);
1644
1645                 layer = tdm_output_get_layer(outputs[o], index, &ret);
1646                 ASSERT_EQ(ret, TDM_ERROR_NONE);
1647                 ASSERT_NE(layer, NULL);
1648
1649                 ASSERT_EQ(tdm_layer_commit(layer, NULL, NULL), TDM_ERROR_NONE);
1650
1651                 if (!tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1652                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, NULL, NULL), TDM_ERROR_NONE);
1653                 else
1654                         ASSERT_EQ(tdm_output_commit(outputs[o], 0, NULL, NULL), TDM_ERROR_BAD_REQUEST);
1655         }
1656 }
1657
1658 TEST_P(TDMOutput, OutputCommitMismatchCommitType)
1659 {
1660         TDM_UT_SKIP_FLAG(has_outputs);
1661
1662         for (int o = 0; o < output_count; o++) {
1663                 if (!tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1664                         continue;
1665                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, NULL, NULL), TDM_ERROR_BAD_REQUEST);
1666         }
1667 }
1668
1669 TEST_P(TDMOutput, OutputCommitFewTimesInOneVblank)
1670 {
1671         TDM_UT_SKIP_FLAG(has_outputs);
1672
1673         for (int o = 0; o < output_count; o++) {
1674                 /* if true, have to use tdm_layer_commit. so skip */
1675                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1676                         continue;
1677
1678                 if (!tc_tdm_output_is_connected(outputs[o]))
1679                         continue;
1680
1681                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1682
1683                 for (int t = 0; t < 10; t++) {
1684                         if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1685                                 done1 = done2 = done3 = false;
1686                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1687                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1688                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1689                                 while (!done1 || !done2 || !done3)
1690                                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1691                         } else
1692                                 TDM_UT_SKIP_FLAG(0);
1693                 }
1694         }
1695 }
1696
1697 //TODO
1698 TEST_P(TDMOutput, DISABLED_OutputCommitBeforeDpmsOff)
1699 {
1700         /* output commit -> dpms off -> then? (commit handler is called? or not?) */
1701 }
1702
1703 TEST_P(TDMOutput, OutputRemoveCommitHandler)
1704 {
1705         TDM_UT_SKIP_FLAG(has_outputs);
1706
1707         for (int o = 0; o < output_count; o++) {
1708                 /* if true, have to use tdm_layer_commit. so skip */
1709                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1710                         continue;
1711
1712                 if (!tc_tdm_output_is_connected(outputs[o]))
1713                         continue;
1714
1715                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1716
1717                 for (int t = 0; t < 10; t++) {
1718                         if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1719                                 done1 = done2 = done3 = false;
1720                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1721                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1722                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1723                                 tdm_output_remove_commit_handler(outputs[o], _tc_tdm_output_done_cb, &done2);
1724                                 while (!done1 || done2 || !done3)
1725                                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1726                         } else
1727                                 TDM_UT_SKIP_FLAG(0);
1728                 }
1729         }
1730 }
1731
1732 TEST_P(TDMOutput, OutputRemoveCommitHandlerDifferentData)
1733 {
1734         TDM_UT_SKIP_FLAG(has_outputs);
1735
1736         for (int o = 0; o < output_count; o++) {
1737                 /* if true, have to use tdm_layer_commit. so skip */
1738                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1739                         continue;
1740
1741                 if (!tc_tdm_output_is_connected(outputs[o]))
1742                         continue;
1743
1744                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1745
1746                 for (int t = 0; t < 10; t++) {
1747                         if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1748                                 done1 = done2 = done3 = false;
1749                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done1), TDM_ERROR_NONE);
1750                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done2), TDM_ERROR_NONE);
1751                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb, &done3), TDM_ERROR_NONE);
1752                                 tdm_output_remove_commit_handler(outputs[o], _tc_tdm_output_done_cb, NULL);
1753                                 while (!done1 || !done2 || !done3)
1754                                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1755                         } else
1756                                 TDM_UT_SKIP_FLAG(0);
1757                 }
1758         }
1759 }
1760
1761 TEST_P(TDMOutput, OutputRemoveCommitHandlerInHandler)
1762 {
1763         TDM_UT_SKIP_FLAG(has_outputs);
1764
1765         for (int o = 0; o < output_count; o++) {
1766                 /* if true, have to use tdm_layer_commit. so skip */
1767                 if (tdm_helper_output_commit_per_vblank_enabled(outputs[o]))
1768                         continue;
1769
1770                 if (!tc_tdm_output_is_connected(outputs[o]))
1771                         continue;
1772
1773                 ASSERT_EQ(tc_tdm_output_prepare(dpy, outputs[o], true), true);
1774
1775                 for (int t = 0; t < 10; t++) {
1776                         if (!tc_tdm_output_is_hwc_enable(outputs[o])) {
1777                                 done1 = done2 = done3 = false;
1778                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb2, &done1), TDM_ERROR_NONE);
1779                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb2, &done2), TDM_ERROR_NONE);
1780                                 ASSERT_EQ(tdm_output_commit(outputs[o], 0, _tc_tdm_output_done_cb2, &done3), TDM_ERROR_NONE);
1781                                 while (!done1 || !done2 || !done3)
1782                                         ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1783                         } else
1784                                 TDM_UT_SKIP_FLAG(0);
1785                 }
1786         }
1787 }
1788
1789 #ifdef TDM_UT_TEST_WITH_PARAMS
1790 INSTANTIATE_TEST_CASE_P(TDMOutputParams,
1791                                                 TDMOutput,
1792                                                 Combine(Bool(), Bool(), Values(TDM_DEFAULT_MODULE)));
1793 #else
1794 INSTANTIATE_TEST_CASE_P(TDMOutputParams,
1795                                                 TDMOutput,
1796                                                 Values(TDM_DEFAULT_MODULE));
1797 #endif
1798
1799 /* LCOV_EXCL_END */