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