utest: Add 33 tests cases for tdm_helper
[platform/core/uifw/libtdm.git] / utests / src / ut_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 "gtest/gtest.h"
32 #include "ut_common.h"
33 #include <climits>
34 extern "C" {
35 #include "tdm.h"
36 #include "tbm_bufmgr.h"
37 #include "tbm_drm_helper.h"
38 }
39
40 class TDMOutput : public ::testing::Test {
41 protected:
42         tdm_display *dpy = NULL;
43         int output_count = 0, master_fd = -42, tbm_fd = -42;
44         bool has_output = false;
45         tbm_bufmgr tbm_bufmgr = NULL;
46         static unsigned int handle_call;
47         static void tdm_output_change_handler_test_func(tdm_output *output,
48                                                                                                         tdm_output_change_type type,
49                                                                                                         tdm_value value,
50                                                                                                         void *u_data)
51         {
52                 if ( ((int) u_data) < -100) {
53                         TDMOutput::handle_call++;
54                 }
55         }
56         void SetUp(void)
57         {
58                 setenv("TDM_DLOG", "1", 1);
59                 setenv("XDG_RUNTIME_DIR", ".", 1);
60                 setenv("TBM_DLOG", "1", 1);
61                 setenv("TBM_DISPLAY_SERVER", "1", 1);
62                 setenv("TDM_COMMIT_PER_VBLANK", "0", 1);
63
64                 tdm_error error = TDM_ERROR_NONE;
65                 dpy = tdm_display_init(&error);
66                 ASSERT_TRUE(error == TDM_ERROR_NONE);
67                 ASSERT_FALSE(dpy == NULL);
68                 tbm_bufmgr = tbm_bufmgr_init(-1);
69                 ASSERT_FALSE(tbm_bufmgr == NULL);
70                 master_fd = tbm_drm_helper_get_master_fd();
71                 tbm_fd = tbm_drm_helper_get_fd();
72                 error = tdm_display_get_output_count(dpy, &output_count);
73 #ifdef FAIL_ON_UNSUPPORTED
74                 ASSERT_GT(output_count, 0);
75 #endif
76                 if (output_count > 0)
77                         has_output = true;
78                 handle_call = 0;
79         }
80         void TearDown(void)
81         {
82                 tdm_display_deinit(dpy);
83                 dpy = NULL;
84                 tbm_bufmgr_deinit(tbm_bufmgr);
85                 tbm_bufmgr = NULL;
86                 if (master_fd > -1) {
87                         int temp_master_fd = tbm_drm_helper_get_master_fd();
88                         EXPECT_EQ(temp_master_fd, -1) << "Fatal Error. Can't deinit tdm/tbm" << std::endl;
89                         if (temp_master_fd > -1)
90                                 exit(1);
91                         close(master_fd);
92                 }
93                 if (tbm_fd > -1) {
94                         int temp_tbm_fd = tbm_drm_helper_get_fd();
95                         EXPECT_EQ(temp_tbm_fd, -1) << "Fatal Error. Can't deinit tdm/tbm" << std::endl;
96                         if (temp_tbm_fd > -1)
97                                 exit(1);
98                         close(tbm_fd);
99                 }
100                 unsetenv("TDM_DLOG");
101                 unsetenv("XDG_RUNTIME_DIR");
102                 unsetenv("TBM_DLOG");
103                 unsetenv("TBM_DISPLAY_SERVER");
104                 unsetenv("TDM_COMMIT_PER_VBLANK");
105         }
106 };
107
108 class TDMOutputCommit : public TDMOutput {
109 protected:
110         int conn_output_count = 0;
111         tdm_output ** connected_output_array = NULL;
112         const tdm_output_mode** preferred_mode = NULL;
113         bool has_output = false;
114         void SetUp(void)
115         {
116                 ASSERT_NO_FATAL_FAILURE(TDMOutput::SetUp());
117                 if (TDMOutput::output_count > 0) {
118                         connected_output_array = (tdm_output **) calloc(TDMOutput::output_count, sizeof(tdm_output *));
119                         ASSERT_FALSE(NULL == connected_output_array);
120                         preferred_mode = (const tdm_output_mode **) calloc(TDMOutput::output_count, sizeof(tdm_output_mode*));
121                         ASSERT_FALSE(NULL == preferred_mode);
122                 }
123                 conn_output_count = 0;
124                 for (int i = 0; i < TDMOutput::output_count; i++) {
125                         tdm_error error = TDM_ERROR_NONE;
126                         int output_modes_cnt = 0;
127                         const tdm_output_mode* output_modes = NULL;
128                         tdm_output * output = tdm_display_get_output(TDMOutput::dpy, i, &error);
129                         if (TDM_ERROR_NONE != error || NULL == output)
130                                 continue;
131                         tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
132                         if (TDM_ERROR_NONE != tdm_output_get_conn_status(output, &status))
133                                 continue;
134                         if (TDM_OUTPUT_CONN_STATUS_DISCONNECTED == status)
135                                 continue;
136                         if (TDM_ERROR_NONE != tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON))
137                                 continue;
138                         if(TDM_ERROR_NONE != tdm_output_get_available_modes(output,
139                                                                                                                                 &output_modes,
140                                                                                                                                 &output_modes_cnt))
141                                 continue;
142                         for(int k = 0; k < output_modes_cnt; k++) {
143                                 if(output_modes[k].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) {
144                                         preferred_mode[conn_output_count] = &output_modes[k];
145                                         break;
146                                 }
147                         }
148                         if (NULL == preferred_mode[conn_output_count])
149                                 continue;
150                         connected_output_array[conn_output_count++] = output;
151                 }
152 #ifdef FAIL_ON_UNSUPPORTED
153                 ASSERT_GT(conn_output_count, 0);
154 #endif
155
156                 if (conn_output_count > 0)
157                         has_output = true;
158         }
159         void TearDown(void)
160         {
161                 for (int i = 0; i < conn_output_count; i++) {
162                         EXPECT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(connected_output_array[i],
163                                                                                                                           TDM_OUTPUT_DPMS_OFF));
164                 }
165                 if (connected_output_array)
166                         free(connected_output_array);
167                 if (preferred_mode)
168                         free(preferred_mode);
169                 ASSERT_NO_FATAL_FAILURE(TDMOutput::TearDown());
170         }
171 };
172
173
174 unsigned int TDMOutput::handle_call = 0;
175
176 TEST_F(TDMOutput, DisplayGetOutputSuccessful)
177 {
178         SKIP_FLAG(has_output);
179         for (int i = 0; i < output_count; i++) {
180                 tdm_error error = TDM_ERROR_NONE;
181                 ASSERT_FALSE(NULL == tdm_display_get_output(dpy, i, &error));
182                 ASSERT_TRUE(TDM_ERROR_NONE == error);
183         }
184 }
185
186 TEST_F(TDMOutput, DisplayGetOutputSuccessfulWrongIndex)
187 {
188         SKIP_FLAG(has_output);
189         tdm_error error = TDM_ERROR_NONE;
190         ASSERT_TRUE(NULL == tdm_display_get_output(dpy, -1, &error));
191         ASSERT_TRUE(TDM_ERROR_NONE == error);
192 }
193
194 TEST_F(TDMOutput, DisplayGetOutputSuccessfulBigIndex)
195 {
196         SKIP_FLAG(has_output);
197         tdm_error error = TDM_ERROR_NONE;
198         ASSERT_TRUE(NULL == tdm_display_get_output(dpy, INT_MAX, &error));
199         ASSERT_TRUE(TDM_ERROR_NONE == error);
200 }
201
202 TEST_F(TDMOutput, DisplayGetOutputSuccessfulSmallIndex)
203 {
204         SKIP_FLAG(has_output);
205         tdm_error error = TDM_ERROR_NONE;
206         ASSERT_TRUE(NULL == tdm_display_get_output(dpy, INT_MIN, &error));
207         ASSERT_TRUE(TDM_ERROR_NONE == error);
208 }
209
210 TEST_F(TDMOutput, DisplayGetOutputSuccessfulErrorNull)
211 {
212         SKIP_FLAG(has_output);
213         ASSERT_FALSE(NULL == tdm_display_get_output(dpy, 0, NULL));
214 }
215
216 TEST_F(TDMOutput, DisplayOutputGetCapabilitiesSuccessful)
217 {
218         SKIP_FLAG(has_output);
219         for (int i = 0; i < output_count; i++) {
220                 tdm_error error = TDM_ERROR_NONE;
221                 tdm_output_capability capabilities = (tdm_output_capability) -42;
222                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
223                 ASSERT_FALSE(NULL == output);
224                 ASSERT_TRUE(TDM_ERROR_NONE == error);
225                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_capabilities(output, &capabilities));
226                 ASSERT_FALSE(-42 == capabilities);
227         }
228 }
229
230 TEST_F(TDMOutput, DisplayOutputGetCapabilitiesFailAllNull)
231 {
232         SKIP_FLAG(has_output);
233         ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_get_capabilities(NULL, NULL));
234 }
235
236 TEST_F(TDMOutput, DisplayOutputGetCapabilitiesFailOnlyOutput)
237 {
238         SKIP_FLAG(has_output);
239         for (int i = 0; i < output_count; i++) {
240                 tdm_error error = TDM_ERROR_NONE;
241                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
242                 ASSERT_FALSE(NULL == output);
243                 ASSERT_TRUE(TDM_ERROR_NONE == error);
244                 ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_get_capabilities(output, NULL));
245         }
246 }
247
248 TEST_F(TDMOutput, OutputGetModelInfoSuccessful)
249 {
250         SKIP_FLAG(has_output);
251         for (int i = 0; i < output_count; i++) {
252                 tdm_error error = TDM_ERROR_NONE;
253                 const char * maker = NULL, * model = NULL, * name = NULL;
254                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
255                 ASSERT_FALSE(NULL == output);
256                 ASSERT_TRUE(TDM_ERROR_NONE == error);
257                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_model_info(output, &maker, &model, &name));
258                 ASSERT_FALSE(NULL == maker);
259                 ASSERT_FALSE(NULL == model);
260                 ASSERT_FALSE(NULL == name);
261         }
262 }
263
264 TEST_F(TDMOutput, OutputGetModelInfoFailAllNull)
265 {
266         SKIP_FLAG(has_output);
267         ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_get_model_info(NULL, NULL, NULL, NULL));
268 }
269
270 TEST_F(TDMOutput, OutputGetModelInfoSuccessfulOnlyOutput)
271 {
272         SKIP_FLAG(has_output);
273         for (int i = 0; i < output_count; i++) {
274                 tdm_error error = TDM_ERROR_NONE;
275                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
276                 ASSERT_FALSE(NULL == output);
277                 ASSERT_TRUE(TDM_ERROR_NONE == error);
278                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_model_info(output, NULL, NULL, NULL));
279         }
280 }
281
282 TEST_F(TDMOutput, OutputGetConnStatusSuccessful)
283 {
284         SKIP_FLAG(has_output);
285         for (int i = 0; i < output_count; i++) {
286                 tdm_error error = TDM_ERROR_NONE;
287                 tdm_output_conn_status status = (tdm_output_conn_status) -42;
288                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
289                 ASSERT_FALSE(NULL == output);
290                 ASSERT_TRUE(TDM_ERROR_NONE == error);
291                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
292                 ASSERT_FALSE(-42 == status);
293         }
294 }
295
296 TEST_F(TDMOutput, OutputGetConnStatusFailAllNull)
297 {
298         SKIP_FLAG(has_output);
299         ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_get_conn_status(NULL, NULL));
300 }
301
302 TEST_F(TDMOutput, OutputGetConnStatusFailOnlyOutput)
303 {
304         SKIP_FLAG(has_output);
305         for (int i = 0; i < output_count; i++) {
306                 tdm_error error = TDM_ERROR_NONE;
307                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
308                 ASSERT_FALSE(NULL == output);
309                 ASSERT_TRUE(TDM_ERROR_NONE == error);
310                 ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, NULL));
311         }
312 }
313
314 TEST_F(TDMOutput, OutputSetDPMSSuccessful)
315 {
316         SKIP_FLAG(has_output);
317         bool checked = false;
318         for (int i = 0; i < output_count; i++) {
319                 tdm_error error = TDM_ERROR_NONE;
320                 tdm_output_conn_status status;
321                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
322                 ASSERT_FALSE(NULL == output);
323                 ASSERT_TRUE(TDM_ERROR_NONE == error);
324                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
325                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
326                         continue;
327                 checked = true;
328                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
329                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_STANDBY));
330                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_SUSPEND));
331                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
332         }
333         if (false == checked) {
334                 FAIL() << "All outputs are disconnected. Testcase skipped" << std::endl;
335         }
336 }
337
338 TEST_F(TDMOutput, OutputAddChangeHandlerSuccessful)
339 {
340         SKIP_FLAG(has_output);
341         bool checked = false;
342         for (int i = 0; i < output_count; i++) {
343                 tdm_error error = TDM_ERROR_NONE;
344                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
345                 ASSERT_FALSE(NULL == output);
346                 ASSERT_TRUE(TDM_ERROR_NONE == error);
347                 tdm_output_conn_status status;
348                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
349                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
350                         continue;
351                 checked = true;
352                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output,
353                                                                                                                                         tdm_output_change_handler_test_func,
354                                                                                                                                         (void *) -101));
355                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
356                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
357                 ASSERT_GT(handle_call, 0);
358         }
359         if (false == checked) {
360                 FAIL() << "All outputs are disconnected. Testcase skipped" << std::endl;
361         }
362 }
363
364 TEST_F(TDMOutput, OutputAddChangeHandlerSuccessfulFewFuncs)
365 {
366         SKIP_FLAG(has_output);
367         bool checked = false;
368         for (int i = 0; i < output_count; i++) {
369                 tdm_error error = TDM_ERROR_NONE;
370                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
371                 ASSERT_FALSE(NULL == output);
372                 ASSERT_TRUE(TDM_ERROR_NONE == error);
373                 tdm_output_conn_status status;
374                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
375                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
376                         continue;
377                 checked = true;
378                 for (int k = 0; k < 20; k++) {
379                         ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output,
380                                                                                                                                                 tdm_output_change_handler_test_func,
381                                                                                                                                                 (void *) (-101-k)));
382                 }
383                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
384                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
385                 ASSERT_GT(handle_call, 20);
386         }
387         if (false == checked) {
388                 FAIL() << "All outputs are disconnected. Testcase skipped" << std::endl;
389         }
390 }
391
392
393 TEST_F(TDMOutput, OutputAddChangeHandlerFailAllNull)
394 {
395         SKIP_FLAG(has_output);
396         ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_add_change_handler(NULL, NULL, NULL));
397 }
398
399 TEST_F(TDMOutput, OutputAddChangeHandlerFailOnlyOutput)
400 {
401         SKIP_FLAG(has_output);
402         for (int i = 0; i < output_count; i++) {
403                 tdm_error error = TDM_ERROR_NONE;
404                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
405                 ASSERT_FALSE(NULL == output);
406                 ASSERT_TRUE(TDM_ERROR_NONE == error);
407                 ASSERT_FALSE(TDM_ERROR_NONE == tdm_output_add_change_handler(output, NULL, NULL));
408         }
409 }
410
411 TEST_F(TDMOutput, OutputAddChangeHandlerFailWrongOutput)
412 {
413         SKIP_FLAG(has_output);
414         ASSERT_EXIT({tdm_output *output = (tdm_output *) 0xBEAF;
415                                  tdm_output_add_change_handler(output,
416                                                                                            tdm_output_change_handler_test_func,
417                                                                                            (void *) -101);
418                                  exit(0);}, ::testing::ExitedWithCode(0), "");
419 }
420
421 TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessful)
422 {
423         SKIP_FLAG(has_output);
424         bool checked = false;
425         for (int i = 0; i < output_count; i++) {
426                 tdm_error error = TDM_ERROR_NONE;
427                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
428                 ASSERT_FALSE(NULL == output);
429                 ASSERT_TRUE(TDM_ERROR_NONE == error);
430                 tdm_output_conn_status status;
431                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
432                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
433                         continue;
434                 checked = true;
435                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output,
436                                                                                                                                         tdm_output_change_handler_test_func,
437                                                                                                                                         (void *) -101));
438                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
439                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
440                 ASSERT_GT(handle_call, 0);
441                 handle_call = 0;
442                 tdm_output_remove_change_handler(output, tdm_output_change_handler_test_func, (void *) -101);
443                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
444                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
445                 ASSERT_EQ(handle_call, 0);
446         }
447         if (false == checked) {
448                 FAIL() << "All outputs are disconnected. Testcase skipped" << std::endl;
449         }
450 }
451
452 TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessfulFewFuncs)
453 {
454         SKIP_FLAG(has_output);
455         bool checked = false;
456         for (int i = 0; i < output_count; i++) {
457                 tdm_error error = TDM_ERROR_NONE;
458                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
459                 ASSERT_FALSE(NULL == output);
460                 ASSERT_TRUE(TDM_ERROR_NONE == error);
461                 tdm_output_conn_status status;
462                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_conn_status(output, &status));
463                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
464                         continue;
465                 checked = true;
466                 for (int k = 0; k < 20; k++) {
467                         ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output,
468                                                                                                                                                 tdm_output_change_handler_test_func,
469                                                                                                                                                 (void *) (-101-k)));
470                 }
471                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
472                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
473                 ASSERT_GT(handle_call, 20);
474                 handle_call = 0;
475                 for (int k = 0; k < 20; k++) {
476                         tdm_output_remove_change_handler(output, tdm_output_change_handler_test_func, (void *) (-101-k));
477                 }
478                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON));
479                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF));
480                 ASSERT_EQ(handle_call, 0);
481         }
482         if (false == checked) {
483                 FAIL() << "All outputs are disconnected. Testcase skipped" << std::endl;
484         }
485 }
486
487 TEST_F(TDMOutput, OutputRemoveChangeHandlerFailAllNull)
488 {
489         SKIP_FLAG(has_output);
490         ASSERT_EXIT({tdm_output_remove_change_handler(NULL, NULL, NULL);
491                                  exit(0);}, ::testing::ExitedWithCode(0), "");
492 }
493
494 TEST_F(TDMOutput, OutputRemoveChangeHandlerFailOnlyOutput)
495 {
496         SKIP_FLAG(has_output);
497         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
498                                          tdm_error error = TDM_ERROR_NONE;
499                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
500                                          if (NULL == output) exit(1);
501                                          if (TDM_ERROR_NONE != error) exit(1);
502                                          tdm_output_remove_change_handler(output, NULL, NULL);
503                                  } exit(0);}, ::testing::ExitedWithCode(0), "");
504 }
505
506 TEST_F(TDMOutput, OutputRemoveChangeHandlerFailWrongOutput)
507 {
508         SKIP_FLAG(has_output);
509         ASSERT_EXIT({tdm_output *output = (tdm_output *) 0xBEAF;
510                                  tdm_output_remove_change_handler(output,
511                                                                                            tdm_output_change_handler_test_func,
512                                                                                            (void *) -101);
513                                  exit(0);}, ::testing::ExitedWithCode(0), "");
514 }
515
516 TEST_F(TDMOutput, OutputGetOutputTypeSuccessful)
517 {
518         SKIP_FLAG(has_output);
519         for (int i = 0; i < output_count; i++) {
520                 tdm_error error = TDM_ERROR_NONE;
521                 tdm_output_type type = (tdm_output_type) -42;
522                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
523                 ASSERT_FALSE(NULL == output);
524                 ASSERT_TRUE(TDM_ERROR_NONE == error);
525                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_output_type(output, &type));
526                 ASSERT_NE(type, -42);
527         }
528 }
529
530 TEST_F(TDMOutput, OutputGetOutputTypeFailNullAll)
531 {
532         SKIP_FLAG(has_output);
533         ASSERT_EXIT({if (tdm_output_get_output_type(NULL, NULL) == TDM_ERROR_NONE) exit(1);
534                                  exit(0);}, ::testing::ExitedWithCode(0), "");
535 }
536
537 TEST_F(TDMOutput, OutputGetOutputTypeFailOnlyOutput)
538 {
539         SKIP_FLAG(has_output);
540         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
541                                          tdm_error error = TDM_ERROR_NONE;
542                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
543                                          if (NULL == output) exit(1);
544                                          if (TDM_ERROR_NONE != error) exit(1);
545                                          if (tdm_output_get_output_type(output, NULL) == TDM_ERROR_NONE) exit(1);
546                                 }
547                                 exit(0);}, ::testing::ExitedWithCode(0), "");
548 }
549
550 TEST_F(TDMOutput, OutputGetLayerCountSuccessful)
551 {
552         SKIP_FLAG(has_output);
553         for (int i = 0; i < output_count; i++) {
554                 tdm_error error = TDM_ERROR_NONE;
555                 int count = -42;
556                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
557                 ASSERT_FALSE(NULL == output);
558                 ASSERT_TRUE(TDM_ERROR_NONE == error);
559                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_layer_count(output, &count));
560                 ASSERT_NE(count, -42);
561         }
562 }
563
564 TEST_F(TDMOutput, OutputGetLayerCountFailNullAll)
565 {
566         SKIP_FLAG(has_output);
567         ASSERT_EXIT({if (tdm_output_get_layer_count(NULL, NULL) == TDM_ERROR_NONE) exit(1);
568                                  exit(0);}, ::testing::ExitedWithCode(0), "");
569 }
570
571 TEST_F(TDMOutput, OutputGetLayerCountFailOnlyOutput)
572 {
573         SKIP_FLAG(has_output);
574         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
575                                          tdm_error error = TDM_ERROR_NONE;
576                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
577                                          if (NULL == output) exit(1);
578                                          if (TDM_ERROR_NONE != error) exit(1);
579                                          if (TDM_ERROR_NONE == tdm_output_get_layer_count(output, NULL)) exit(1);
580                                 }
581                                 exit(0);}, ::testing::ExitedWithCode(0), "");
582 }
583
584 TEST_F(TDMOutput, OutputGetAvailablePropertiesSuccessful)
585 {
586         SKIP_FLAG(has_output);
587         for (int i = 0; i < output_count; i++) {
588                 tdm_error error = TDM_ERROR_NONE;
589                 int count = -42;
590                 const tdm_prop *tdm_prop_array = (const tdm_prop *) 0xBEAF;
591                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
592                 ASSERT_FALSE(NULL == output);
593                 ASSERT_TRUE(TDM_ERROR_NONE == error);
594                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_available_properties(output,
595                                                                                                                                                   &tdm_prop_array,
596                                                                                                                                                   &count));
597                 ASSERT_NE(count, -42);
598                 ASSERT_NE(tdm_prop_array, 0xBEAF);
599         }
600 }
601
602 TEST_F(TDMOutput, OutputGetAvailablePropertiesFailNullAll)
603 {
604         SKIP_FLAG(has_output);
605         ASSERT_EXIT({if (tdm_output_get_available_properties(NULL, NULL, NULL) == TDM_ERROR_NONE) exit(1);
606                                  exit(0);}, ::testing::ExitedWithCode(0), "");
607 }
608
609 TEST_F(TDMOutput, OutputGetAvailablePropertiesFailOnlyOutput)
610 {
611         SKIP_FLAG(has_output);
612         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
613                                          tdm_error error = TDM_ERROR_NONE;
614                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
615                                          if (NULL == output) exit(1);
616                                          if (TDM_ERROR_NONE != error) exit(1);
617                                          if (TDM_ERROR_NONE == tdm_output_get_available_properties(output, NULL, NULL)) exit(1);
618                                 }
619                                 exit(0);}, ::testing::ExitedWithCode(0), "");
620 }
621
622 TEST_F(TDMOutput, OutputGetAvailablePropertiesFailNullCount)
623 {
624         SKIP_FLAG(has_output);
625         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
626                                          tdm_error error = TDM_ERROR_NONE;
627                                          const tdm_prop *tdm_prop_array = NULL;
628                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
629                                          if (NULL == output) exit(1);
630                                          if (TDM_ERROR_NONE != error) exit(1);
631                                          if (TDM_ERROR_NONE == tdm_output_get_available_properties(output,
632                                                                                                                                                            &tdm_prop_array,
633                                                                                                                                                            NULL)) exit(1);
634                                 }
635                                 exit(0);}, ::testing::ExitedWithCode(0), "");
636 }
637
638 TEST_F(TDMOutput, OutputGetAvailablePropertiesFailNullProperty)
639 {
640         SKIP_FLAG(has_output);
641         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
642                                          tdm_error error = TDM_ERROR_NONE;
643                                          int count = -42;
644                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
645                                          if (NULL == output) exit(1);
646                                          if (TDM_ERROR_NONE != error) exit(1);
647                                          if (TDM_ERROR_NONE == tdm_output_get_available_properties(output,
648                                                                                                                                                            NULL,
649                                                                                                                                                            &count)) exit(1);
650                                 }
651                                 exit(0);}, ::testing::ExitedWithCode(0), "");
652 }
653
654 TEST_F(TDMOutput, OutputGetAvailableModesSuccessful)
655 {
656         SKIP_FLAG(has_output);
657         for (int i = 0; i < output_count; i++) {
658                 tdm_error error = TDM_ERROR_NONE;
659                 int count = -42;
660                 const tdm_output_mode *modes_array = (const tdm_output_mode *) 0xBEAF;
661                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
662                 ASSERT_FALSE(NULL == output);
663                 ASSERT_TRUE(TDM_ERROR_NONE == error);
664                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_available_modes(output,
665                                                                                                                                          &modes_array,
666                                                                                                                                          &count));
667                 ASSERT_NE(count, -42);
668                 ASSERT_NE(modes_array, 0xBEAF);
669         }
670 }
671
672 TEST_F(TDMOutput, OutputGetAvailableModesFailNullAll)
673 {
674         SKIP_FLAG(has_output);
675         ASSERT_EXIT({if (tdm_output_get_available_modes(NULL, NULL, NULL) == TDM_ERROR_NONE) exit(1);
676                                  exit(0);}, ::testing::ExitedWithCode(0), "");
677 }
678
679 TEST_F(TDMOutput, OutputGetAvailableModesFailOnlyOutput)
680 {
681         SKIP_FLAG(has_output);
682         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
683                                          tdm_error error = TDM_ERROR_NONE;
684                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
685                                          if (NULL == output) exit(1);
686                                          if (TDM_ERROR_NONE != error) exit(1);
687                                          if (TDM_ERROR_NONE == tdm_output_get_available_modes(output, NULL, NULL)) exit(1);
688                                 }
689                                 exit(0);}, ::testing::ExitedWithCode(0), "");
690 }
691
692 TEST_F(TDMOutput, OutputGetAvailableModesFailNullCount)
693 {
694         SKIP_FLAG(has_output);
695         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
696                                          tdm_error error = TDM_ERROR_NONE;
697                                          const tdm_output_mode *modes_array = NULL;
698                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
699                                          if (NULL == output) exit(1);
700                                          if (TDM_ERROR_NONE != error) exit(1);
701                                          if (TDM_ERROR_NONE == tdm_output_get_available_modes(output,
702                                                                                                                                                   &modes_array,
703                                                                                                                                                   NULL)) exit(1);
704                                 }
705                                 exit(0);}, ::testing::ExitedWithCode(0), "");
706 }
707
708 TEST_F(TDMOutput, OutputGetAvailableModesFailNullModes)
709 {
710         SKIP_FLAG(has_output);
711         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
712                                          tdm_error error = TDM_ERROR_NONE;
713                                          int count = -42;
714                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
715                                          if (NULL == output) exit(1);
716                                          if (TDM_ERROR_NONE != error) exit(1);
717                                          if (TDM_ERROR_NONE == tdm_output_get_available_modes(output,
718                                                                                                                                                   NULL,
719                                                                                                                                                   &count)) exit(1);
720                                 }
721                                 exit(0);}, ::testing::ExitedWithCode(0), "");
722 }
723
724 TEST_F(TDMOutput, OutputGetAvailableSizeSuccessful)
725 {
726         SKIP_FLAG(has_output);
727         for (int i = 0; i < output_count; i++) {
728                 tdm_error error = TDM_ERROR_NONE;
729                 int min_w = -42, min_h = -42, max_w = -42, max_h = -42, preferred_align = -42;
730                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
731                 ASSERT_FALSE(NULL == output);
732                 ASSERT_TRUE(TDM_ERROR_NONE == error);
733                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_available_size(output, &min_w, &min_h,
734                                                                                                                                         &max_w, &max_h, &preferred_align));
735                 ASSERT_NE(min_w, -42);
736                 ASSERT_NE(min_h, -42);
737                 ASSERT_NE(max_w, -42);
738                 ASSERT_NE(max_h, -42);
739                 ASSERT_NE(preferred_align, -42);
740         }
741 }
742
743 TEST_F(TDMOutput, OutputGetAvailableSizeFailNullAll)
744 {
745         SKIP_FLAG(has_output);
746         ASSERT_EXIT({if (tdm_output_get_available_size(NULL, NULL, NULL,
747                                                                                                    NULL, NULL, NULL) == TDM_ERROR_NONE) exit(1);
748                                  exit(0);}, ::testing::ExitedWithCode(0), "");
749 }
750
751 TEST_F(TDMOutput, OutputGetAvailableSizeSuccessfulOnlyOutput)
752 {
753         SKIP_FLAG(has_output);
754         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
755                                          tdm_error error = TDM_ERROR_NONE;
756                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
757                                          if (NULL == output) exit(1);
758                                          if (TDM_ERROR_NONE != error) exit(1);
759                                          if (tdm_output_get_available_size(output, NULL, NULL,
760                                                                                                                 NULL, NULL, NULL) != TDM_ERROR_NONE) exit(1);
761                                 }
762                                 exit(0);}, ::testing::ExitedWithCode(0), "");
763 }
764
765 TEST_F(TDMOutput, OutputGetCursorAvailableSizeSuccessful)
766 {
767         SKIP_FLAG(has_output);
768         for (int i = 0; i < output_count; i++) {
769                 tdm_error error = TDM_ERROR_NONE;
770                 int min_w = -42, min_h = -42, max_w = -42, max_h = -42, preferred_align = -42;
771                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
772                 ASSERT_FALSE(NULL == output);
773                 ASSERT_TRUE(TDM_ERROR_NONE == error);
774                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_cursor_available_size(output, &min_w, &min_h,
775                                                                                                                                                    &max_w, &max_h, &preferred_align));
776                 ASSERT_NE(min_w, -42);
777                 ASSERT_NE(min_h, -42);
778                 ASSERT_NE(max_w, -42);
779                 ASSERT_NE(max_h, -42);
780                 ASSERT_NE(preferred_align, -42);
781         }
782 }
783
784 TEST_F(TDMOutput, OutputGetCursorAvailableSizeFailNullAll)
785 {
786         SKIP_FLAG(has_output);
787         ASSERT_EXIT({if (tdm_output_get_cursor_available_size(NULL, NULL, NULL,
788                                                                                                                   NULL, NULL, NULL) == TDM_ERROR_NONE) exit(1);
789                                  exit(0);}, ::testing::ExitedWithCode(0), "");
790 }
791
792 TEST_F(TDMOutput, OutputGetCursorAvailableSizeSuccessfulOnlyOutput)
793 {
794         SKIP_FLAG(has_output);
795         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
796                                          tdm_error error = TDM_ERROR_NONE;
797                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
798                                          if (NULL == output) exit(1);
799                                          if (TDM_ERROR_NONE != error) exit(1);
800                                          if (tdm_output_get_cursor_available_size(output, NULL, NULL,
801                                                                                                                           NULL, NULL, NULL) != TDM_ERROR_NONE) exit(1);
802                                 }
803                                 exit(0);}, ::testing::ExitedWithCode(0), "");
804 }
805
806 TEST_F(TDMOutput, OutputGetPhysicalSizeSuccessful)
807 {
808         SKIP_FLAG(has_output);
809         for (int i = 0; i < output_count; i++) {
810                 tdm_error error = TDM_ERROR_NONE;
811                 unsigned int mmWidth = UINT_MAX, mmHeight = UINT_MAX;
812                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
813                 ASSERT_FALSE(NULL == output);
814                 ASSERT_TRUE(TDM_ERROR_NONE == error);
815                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_physical_size(output, &mmWidth, &mmHeight));
816                 ASSERT_NE(mmWidth, UINT_MAX);
817                 ASSERT_NE(mmHeight, UINT_MAX);
818         }
819 }
820
821 TEST_F(TDMOutput, OutputGetPhysicalSizeFailNullAll)
822 {
823         SKIP_FLAG(has_output);
824         ASSERT_EXIT({if (tdm_output_get_physical_size(NULL, NULL, NULL) == TDM_ERROR_NONE) exit(1);
825                                  exit(0);}, ::testing::ExitedWithCode(0), "");
826 }
827
828 TEST_F(TDMOutput, OutputGetPhysicalSuccessfulOnlyOutput)
829 {
830         SKIP_FLAG(has_output);
831         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
832                                          tdm_error error = TDM_ERROR_NONE;
833                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
834                                          if (NULL == output) exit(1);
835                                          if (TDM_ERROR_NONE != error) exit(1);
836                                          if (tdm_output_get_physical_size(output, NULL, NULL) != TDM_ERROR_NONE) exit(1);
837                                 }
838                                 exit(0);}, ::testing::ExitedWithCode(0), "");
839 }
840
841 TEST_F(TDMOutput, OutputGetSubpixelSuccessful)
842 {
843         SKIP_FLAG(has_output);
844         for (int i = 0; i < output_count; i++) {
845                 tdm_error error = TDM_ERROR_NONE;
846                 unsigned int subpixel = UINT_MAX;
847                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
848                 ASSERT_FALSE(NULL == output);
849                 ASSERT_TRUE(TDM_ERROR_NONE == error);
850                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_subpixel(output, &subpixel));
851                 ASSERT_NE(subpixel, UINT_MAX);
852         }
853 }
854
855 TEST_F(TDMOutput, OutputGetSubpixelFailNullAll)
856 {
857         SKIP_FLAG(has_output);
858         ASSERT_EXIT({if (tdm_output_get_subpixel(NULL, NULL) == TDM_ERROR_NONE) exit(1);
859                                  exit(0);}, ::testing::ExitedWithCode(0), "");
860 }
861
862 TEST_F(TDMOutput, OutputGetSubpixelFailOnlyOutput)
863 {
864         SKIP_FLAG(has_output);
865         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
866                                          tdm_error error = TDM_ERROR_NONE;
867                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
868                                          if (NULL == output) exit(1);
869                                          if (TDM_ERROR_NONE != error) exit(1);
870                                          if (tdm_output_get_subpixel(output, NULL) == TDM_ERROR_NONE) exit(1);
871                                 }
872                                 exit(0);}, ::testing::ExitedWithCode(0), "");
873 }
874
875 TEST_F(TDMOutput, OutputGetPipeSuccessful)
876 {
877         SKIP_FLAG(has_output);
878         for (int i = 0; i < output_count; i++) {
879                 tdm_error error = TDM_ERROR_NONE;
880                 unsigned int pipe = UINT_MAX;
881                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
882                 ASSERT_FALSE(NULL == output);
883                 ASSERT_TRUE(TDM_ERROR_NONE == error);
884                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_pipe(output, &pipe));
885                 ASSERT_NE(pipe, UINT_MAX);
886         }
887 }
888
889 TEST_F(TDMOutput, OutputGetPipeFailNullAll)
890 {
891         SKIP_FLAG(has_output);
892         ASSERT_EXIT({if (tdm_output_get_pipe(NULL, NULL) == TDM_ERROR_NONE) exit(1);
893                                  exit(0);}, ::testing::ExitedWithCode(0), "");
894 }
895
896 TEST_F(TDMOutput, OutputGetPipeFailOnlyOutput)
897 {
898         SKIP_FLAG(has_output);
899         ASSERT_EXIT({for (int i = 0; i < output_count; i++) {
900                                          tdm_error error = TDM_ERROR_NONE;
901                                          tdm_output * output = tdm_display_get_output(dpy, i, &error);
902                                          if (NULL == output) exit(1);
903                                          if (TDM_ERROR_NONE != error) exit(1);
904                                          if (tdm_output_get_pipe(output, NULL) == TDM_ERROR_NONE) exit(1);
905                                 }
906                                 exit(0);}, ::testing::ExitedWithCode(0), "");
907 }
908
909 TEST_F(TDMOutput, OutputSetPropertySuccessful)
910 {
911         SKIP_FLAG(has_output);
912         for (int i = 0; i < output_count; i++) {
913                 tdm_error error = TDM_ERROR_NONE;
914                 tdm_value value = {.u32 = 0};
915                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
916                 ASSERT_FALSE(NULL == output);
917                 ASSERT_TRUE(TDM_ERROR_NONE == error);
918                 error = tdm_output_set_property(output, UINT_MAX, value);
919                 ASSERT_TRUE(error == TDM_ERROR_NOT_IMPLEMENTED || error == TDM_ERROR_OPERATION_FAILED);
920         }
921 }
922
923 TEST_F(TDMOutput, OutputSetPropertyFailNullAll)
924 {
925         SKIP_FLAG(has_output);
926         ASSERT_EXIT({tdm_error error = TDM_ERROR_NONE;
927                                  tdm_value value = {.u32 = 0};
928                                  error = tdm_output_set_property(NULL, 0, value);
929                                  if (error == TDM_ERROR_NONE || error == TDM_ERROR_NOT_IMPLEMENTED ||
930                                         error == TDM_ERROR_OPERATION_FAILED) exit(1);
931                                  exit(0);}, ::testing::ExitedWithCode(0), "");
932 }
933
934 TEST_F(TDMOutput, OutputGetPropertySuccessful)
935 {
936         SKIP_FLAG(has_output);
937         for (int i = 0; i < output_count; i++) {
938                 tdm_error error = TDM_ERROR_NONE;
939                 tdm_value value = {.u32 = 0};
940                 tdm_output * output = tdm_display_get_output(dpy, i, &error);
941                 ASSERT_FALSE(NULL == output);
942                 ASSERT_TRUE(TDM_ERROR_NONE == error);
943                 error = tdm_output_get_property(output, UINT_MAX, &value);
944                 ASSERT_TRUE(error == TDM_ERROR_NOT_IMPLEMENTED || error == TDM_ERROR_OPERATION_FAILED);
945         }
946 }
947
948 TEST_F(TDMOutput, OutputGetPropertyFailNullAll)
949 {
950         SKIP_FLAG(has_output);
951         ASSERT_EXIT({tdm_error error = TDM_ERROR_NONE;
952                                  error = tdm_output_get_property(NULL, 0, NULL);
953                                  if (error == TDM_ERROR_NONE || error == TDM_ERROR_NOT_IMPLEMENTED ||
954                                          error == TDM_ERROR_OPERATION_FAILED) exit(1);
955                                  exit(0);}, ::testing::ExitedWithCode(0), "");
956 }
957
958 TEST_F(TDMOutputCommit, OutputCommit)
959 {
960         SKIP_FLAG(has_output);
961         for (int i = 0; i < conn_output_count; i++) {
962                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_mode(connected_output_array[i], preferred_mode[i]));
963                 ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, NULL, NULL));
964                 /* TODO: use a commit handler instead of an usleep to wait when
965                 * commit will be applied */
966                 usleep(20000);
967         }
968 }
969
970 TEST_F(TDMOutputCommit, DISABLED_OutputWaitVBlank)
971 {
972         SKIP_FLAG(has_output);
973 }