1 /**************************************************************************
3 * Copyright 2016 Samsung Electronics co., Ltd. All Rights Reserved.
5 * Contact: Konstantin Drabeniuk <k.drabeniuk@samsung.com>
6 * Contact: Andrii Sokolenko <a.sokolenko@samsung.com>
7 * Contact: Roman Marchenko <r.marchenko@samsung.com>
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:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
31 #include "gtest/gtest.h"
32 #include "ut_common.h"
35 #include "tbm_bufmgr.h"
36 #include "tbm_drm_helper.h"
39 #include <sys/epoll.h>
40 #include <sys/timerfd.h>
44 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
46 class TDMPPWithoutCreation : public testing::Test {
48 tdm_display *dpy = NULL;
50 tdm_display_capability display_capability = (tdm_display_capability)0;
52 std::list<tbm_surface_h> buffers_list;
54 virtual void SetEnvs()
56 setenv("TDM_DLOG", "1", 1);
57 setenv("XDG_RUNTIME_DIR", ".", 1);
58 setenv("TBM_DLOG", "1", 1);
59 setenv("TDM_DEBUG_MODULE", "all", 1);
60 setenv("TDM_DEBUG", "1", 1);
61 setenv("TBM_DISPLAY_SERVER", "1", 1);
64 virtual void UnsetEnvs()
67 unsetenv("XDG_RUNTIME_DIR");
69 unsetenv("TDM_DEBUG_MODULE");
70 unsetenv("TDM_DEBUG");
71 unsetenv("TBM_DISPLAY_SERVER");
76 tdm_error error = TDM_ERROR_NONE;
80 bufmgr = tbm_bufmgr_init(-1);
81 ASSERT_FALSE(bufmgr == NULL);
83 dpy = tdm_display_init(&error);
84 ASSERT_TRUE(error == TDM_ERROR_NONE);
85 ASSERT_FALSE(dpy == NULL);
87 error = tdm_display_get_capabilities(dpy, &display_capability);
88 #ifdef FAIL_ON_UNSUPPORTED
89 ASSERT_TRUE(display_capability & TDM_DISPLAY_CAPABILITY_PP);
91 ASSERT_TRUE(error == TDM_ERROR_NONE);
93 if (display_capability & TDM_DISPLAY_CAPABILITY_PP)
100 tdm_display_deinit(dpy);
102 tbm_bufmgr_deinit(bufmgr);
108 class TDMPP : public TDMPPWithoutCreation {
111 const tbm_format *formats = NULL;
112 int format_count = 0;
117 int preferred_align = 0;
118 int default_src_w = 128;
119 int default_src_h = 256;
120 int default_dst_w = 512;
121 int default_dst_h = 1024;
127 ASSERT_NO_FATAL_FAILURE(TDMPPWithoutCreation::SetUp());
132 pp = tdm_display_create_pp(dpy, &error);
134 ASSERT_EQ(TDM_ERROR_NONE, error);
137 tdm_display_get_pp_available_formats(dpy, &formats, &format_count);
138 ASSERT_EQ(TDM_ERROR_NONE, error);
139 ASSERT_NE(NULL, formats);
140 ASSERT_GE(format_count, 0);
143 tdm_display_get_pp_available_size(dpy, &min_w, &min_h,
144 &max_w, &max_h, &preferred_align);
145 ASSERT_EQ(TDM_ERROR_NONE, error);
146 if (preferred_align > 0) {
147 default_src_w = SIZE_ALIGN(default_src_w, preferred_align);
148 default_src_h = SIZE_ALIGN(default_src_h, preferred_align);
149 default_dst_w = SIZE_ALIGN(default_dst_w, preferred_align);
150 default_dst_h = SIZE_ALIGN(default_dst_h, preferred_align);
152 if (min_w > default_src_w)
153 default_src_w = min_w;
154 if (min_h > default_src_h)
155 default_src_h = min_h;
156 if (max_w > 0 && max_w < default_dst_w)
157 default_dst_w = max_w;
158 if (max_h > 0 && max_h < default_dst_h)
159 default_dst_h = max_h;
167 for (auto it = buffers_list.begin(); it != buffers_list.end(); ++it) {
168 tbm_surface_destroy(*it);
171 buffers_list.clear();
173 TDMPPWithoutCreation::TearDown();
176 void UtGetPPInfoWithScale(tdm_info_pp *info)
178 memset((void *)info, 0, sizeof(tdm_info_pp));
180 info->src_config.size.h = default_src_w;
181 info->src_config.size.v = default_src_h;
182 info->src_config.pos.x = 0;
183 info->src_config.pos.y = 0;
184 info->src_config.pos.w = default_src_w;
185 info->src_config.pos.h = default_src_h;
186 info->src_config.format = formats[0];
187 info->dst_config.size.h = default_dst_w;
188 info->dst_config.size.v = default_dst_h;
189 info->dst_config.pos.x = 0;
190 info->dst_config.pos.y = 0;
191 info->dst_config.pos.w = default_dst_w;
192 info->dst_config.pos.h = default_dst_h;
193 info->dst_config.format = formats[0];
196 void UtGetPPInfoWithScaleAndTransform(tdm_info_pp *info)
198 UtGetPPInfoWithScale(info);
200 info->transform = TDM_TRANSFORM_180;
203 void UtGetPPInfoWithWrongInfo(tdm_info_pp *info)
205 info->src_config.size.h = UINT_MAX;
206 info->src_config.size.v = UINT_MAX;
207 info->src_config.pos.x = 0;
208 info->src_config.pos.y = 0;
209 info->src_config.pos.w = UINT_MAX;
210 info->src_config.pos.h = UINT_MAX;
211 info->src_config.format = INT_MAX;
212 info->dst_config.size.h = UINT_MAX;
213 info->dst_config.size.v = UINT_MAX;
214 info->dst_config.pos.x = 0;
215 info->dst_config.pos.y = 0;
216 info->dst_config.pos.w = UINT_MAX;
217 info->dst_config.pos.h = UINT_MAX;
218 info->dst_config.format = INT_MAX;
222 UtCreateBuffer(int w, int h, tbm_format format)
224 tbm_surface_h buffer;
226 buffer = tbm_surface_create(w, h, format);
228 buffers_list.push_back(buffer);
234 void UtPpDoneHandler(tdm_pp *pp, tbm_surface_h src,
235 tbm_surface_h dst, void *user_data);
237 class TDMPPCommit : public TDMPP {
239 friend void UtPpDoneHandler(tdm_pp *pp, tbm_surface_h src,
240 tbm_surface_h dst, void *user_data);
245 static const int timeLimitSec = 0;
246 static const int timeLimitNsec = 100000000;
248 int utPpDoneHandlerSuccessCounter = 0;
254 struct epoll_event ep;
255 tdm_pp_capability pp_capability;
257 ASSERT_NO_FATAL_FAILURE(TDMPP::SetUp());
259 epFd = epoll_create1(0);
260 ASSERT_TRUE(epFd != -1);
262 timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
263 ASSERT_TRUE(timerFd != -1);
265 memset(&ep, 0, sizeof ep);
266 ep.events |= EPOLLIN;
267 ep.data.fd = timerFd;
268 ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, timerFd, &ep) == 0);
270 ASSERT_TRUE(tdm_display_get_fd(dpy, &tdmFd) == TDM_ERROR_NONE);
272 memset(&ep, 0, sizeof ep);
273 ep.events |= EPOLLIN;
275 ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, tdmFd, &ep) == 0);
290 void UtHandlePPEvent(int num_attached_buffers)
292 struct itimerspec its;
294 struct epoll_event ep_event[2];
296 if (utPpDoneHandlerSuccessCounter == num_attached_buffers)
299 its.it_interval.tv_sec = 0;
300 its.it_interval.tv_nsec = 0;
301 its.it_value.tv_sec = timeLimitSec;
302 its.it_value.tv_nsec = timeLimitNsec;
304 ASSERT_TRUE(timerfd_settime(timerFd, 0, &its, NULL) == 0);
307 count = epoll_wait(epFd, ep_event, sizeof(ep_event), -1);
308 ASSERT_TRUE(count >= 0);
310 for (int i = 0; i < count; i++) {
311 if (ep_event[i].data.fd == timerFd) {
314 ASSERT_TRUE(tdm_display_handle_events(dpy) == TDM_ERROR_NONE);
315 if (utPpDoneHandlerSuccessCounter == num_attached_buffers)
322 int UtPrepareToPP(tdm_info_pp *info)
325 tbm_surface_h src_buf, dst_buf;
327 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
328 EXPECT_EQ(TDM_ERROR_NONE, error);
329 if (error != TDM_ERROR_NONE)
332 error = tdm_pp_set_info(pp, info);
333 EXPECT_EQ(TDM_ERROR_NONE, error);
334 if (error != TDM_ERROR_NONE)
337 src_buf = UtCreateBuffer(info->src_config.pos.w, info->src_config.pos.h,
338 info->src_config.format);
339 EXPECT_NE(NULL, src_buf);
343 dst_buf = UtCreateBuffer(info->dst_config.pos.w, info->dst_config.pos.h,
344 info->dst_config.format);
345 EXPECT_NE(NULL, dst_buf);
349 error = tdm_pp_attach(pp, src_buf, dst_buf);
350 EXPECT_EQ(TDM_ERROR_NONE, error);
351 if (error != TDM_ERROR_NONE)
356 int UtPrepareToPPWithScale()
358 tdm_info_pp info = {0};
360 tbm_surface_h src_buf, dst_buf;
362 UtGetPPInfoWithScale(&info);
364 return UtPrepareToPP(&info);
367 int UtPrepareToPPWithScaleAndTransform()
369 tdm_info_pp info = {0};
371 tbm_surface_h src_buf, dst_buf;
373 UtGetPPInfoWithScaleAndTransform(&info);
375 return UtPrepareToPP(&info);
378 int UtPrepareToPPWithWrongInfo()
380 tdm_info_pp info = {0};
382 tbm_surface_h src_buf, dst_buf;
385 UtGetPPInfoWithScale(&info);
387 ret = UtPrepareToPP(&info);
391 UtGetPPInfoWithWrongInfo(&info);
393 error = tdm_pp_set_info(pp, &info);
394 EXPECT_EQ(TDM_ERROR_NONE, error);
395 if (error != TDM_ERROR_NONE)
403 class TDMPPCommitThread : public TDMPPCommit {
407 TDMPPCommit::SetEnvs();
408 setenv("TDM_THREAD", "1", 1);
412 TDMPPCommit::UnsetEnvs();
413 unsetenv("TDM_THREAD");
417 void UtPpDoneHandler(tdm_pp *pp, tbm_surface_h src,
418 tbm_surface_h dst, void *user_data)
420 TDMPPCommit *pp_commit = (TDMPPCommit *)user_data;
421 bool src_valid, dst_valid;
426 for (auto it = pp_commit->buffers_list.begin(); it != pp_commit->buffers_list.end(); ++it) {
433 if (src_valid && dst_valid)
434 pp_commit->utPpDoneHandlerSuccessCounter++;
437 TEST_F(TDMPPWithoutCreation, DisplayGetPPAvailableFormatsSuccessful)
440 const tbm_format *formats = NULL;
442 ASSERT_TRUE(TDM_ERROR_NONE == tdm_display_get_pp_available_formats(dpy, &formats, &count));
443 ASSERT_FALSE(-42 == count);
444 ASSERT_FALSE(NULL == formats);
447 /* tdm_display_create_pp() */
449 TEST_F(TDMPPWithoutCreation, DisplayCreatePPNullAll)
454 pp = tdm_display_create_pp(NULL, NULL);
458 TEST_F(TDMPPWithoutCreation, DisplayCreatePPNullDpy)
464 pp = tdm_display_create_pp(NULL, &error);
466 ASSERT_NE(TDM_ERROR_NONE, error);
469 TEST_F(TDMPPWithoutCreation, DisplayCreatePPSuccessNullError)
474 pp = tdm_display_create_pp(dpy, NULL);
478 TEST_F(TDMPPWithoutCreation, DisplayCreatePPSuccess)
484 pp = tdm_display_create_pp(dpy, &error);
486 ASSERT_EQ(TDM_ERROR_NONE, error);
489 /* tdm_pp_set_info() */
491 TEST_F(TDMPP, PpSetInfoNullAll)
496 error = tdm_pp_set_info(NULL, NULL);
497 ASSERT_NE(TDM_ERROR_NONE, error);
500 TEST_F(TDMPP, PpSetInfoNullPP)
506 error = tdm_pp_set_info(NULL, &info);
507 ASSERT_NE(TDM_ERROR_NONE, error);
510 TEST_F(TDMPP, PpSetInfoNullInfo)
515 error = tdm_pp_set_info(pp, NULL);
516 ASSERT_NE(TDM_ERROR_NONE, error);
519 TEST_F(TDMPP, PpSetInfoSuccess)
525 UtGetPPInfoWithScale(&info);
527 error = tdm_pp_set_info(pp, &info);
528 ASSERT_EQ(TDM_ERROR_NONE, error);
531 /* tdm_pp_set_done_handler() */
533 TEST_F(TDMPP, PpSetDoneHandlerFailNullAll)
538 error = tdm_pp_set_done_handler(NULL, NULL, NULL);
539 ASSERT_NE(TDM_ERROR_NONE, error);
542 TEST_F(TDMPP, PpSetDoneHandlerFailNullPP)
548 error = tdm_pp_set_done_handler(NULL, UtPpDoneHandler, this);
549 ASSERT_NE(TDM_ERROR_NONE, error);
552 TEST_F(TDMPP, PpSetDoneHandlerSuccessNullFailNullFunc)
558 error = tdm_pp_set_done_handler(pp, NULL, &data);
559 ASSERT_NE(TDM_ERROR_NONE, error);
562 TEST_F(TDMPP, PpSetDoneHandlerSuccessNullData)
567 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
568 ASSERT_EQ(TDM_ERROR_NONE, error);
571 TEST_F(TDMPP, PpSetDoneHandlerSuccess)
577 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
578 ASSERT_EQ(TDM_ERROR_NONE, error);
581 /* tdm_pp_attach() */
583 TEST_F(TDMPP, PpAttachFailNullAll)
588 error = tdm_pp_attach(NULL, NULL, NULL);
589 ASSERT_NE(TDM_ERROR_NONE, error);
592 TEST_F(TDMPP, PpAttachFailNullPp)
596 tbm_surface_h dst_buf, src_buf;
598 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
599 ASSERT_NE(NULL, src_buf);
601 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
602 ASSERT_NE(NULL, dst_buf);
604 error = tdm_pp_attach(NULL, src_buf, dst_buf);
605 ASSERT_NE(TDM_ERROR_NONE, error);
608 TEST_F(TDMPP, PpAttachFailNullSrc)
612 tbm_surface_h dst_buf;
614 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
615 ASSERT_NE(NULL, dst_buf);
617 error = tdm_pp_attach(pp, NULL, dst_buf);
618 ASSERT_NE(TDM_ERROR_NONE, error);
621 TEST_F(TDMPP, PpAttachFailNullDst)
625 tbm_surface_h src_buf;
627 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
628 ASSERT_NE(NULL, src_buf);
630 error = tdm_pp_attach(pp, src_buf, NULL);
631 ASSERT_NE(TDM_ERROR_NONE, error);
634 TEST_F(TDMPP, PpAttachSuccess)
638 tbm_surface_h dst_buf, src_buf;
640 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
641 ASSERT_NE(NULL, src_buf);
643 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
644 ASSERT_NE(NULL, dst_buf);
646 error = tdm_pp_attach(pp, src_buf, dst_buf);
647 ASSERT_EQ(TDM_ERROR_NONE, error);
650 /* tdm_pp_commit() */
652 TEST_F(TDMPP, PpCommitFailNullPP)
657 error = tdm_pp_commit(NULL);
658 ASSERT_NE(TDM_ERROR_NONE, error);
661 TEST_F(TDMPPCommit, PpCommitFailWrongInfo)
666 ASSERT_NE(-1, UtPrepareToPPWithWrongInfo());
668 error = tdm_pp_commit(pp);
669 ASSERT_NE(TDM_ERROR_NONE, error);
672 TEST_F(TDMPPCommit, PpCommitSuccessScale)
677 ASSERT_NE(-1, UtPrepareToPPWithScale());
679 error = tdm_pp_commit(pp);
680 ASSERT_EQ(TDM_ERROR_NONE, error);
684 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
687 TEST_F(TDMPPCommit, PpCommitSuccessScaleAndTransform)
692 ASSERT_NE(-1, UtPrepareToPPWithScale());
694 error = tdm_pp_commit(pp);
695 ASSERT_EQ(TDM_ERROR_NONE, error);
699 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
702 TEST_F(TDMPPCommitThread, PpCommitSuccessScale)
707 ASSERT_NE(-1, UtPrepareToPPWithScale());
709 error = tdm_pp_commit(pp);
710 ASSERT_EQ(TDM_ERROR_NONE, error);
714 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
717 TEST_F(TDMPPCommitThread, PpCommitSuccessScaleAndTransform)
722 ASSERT_NE(-1, UtPrepareToPPWithScale());
724 error = tdm_pp_commit(pp);
725 ASSERT_EQ(TDM_ERROR_NONE, error);
729 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
732 /* tdm_pp_destroy() */
734 void UtBufferReleaseHandler(tbm_surface_h buffer,
737 int *data = (int *)user_data;
744 TEST_F(TDMPPCommit, PPDestroySuccessAfterCommit)
748 int release_data = 0;
750 ASSERT_NE(-1, UtPrepareToPPWithScale());
752 for (auto it = buffers_list.begin(); it != buffers_list.end(); ++it) {
753 tdm_buffer_add_release_handler((tbm_surface_h)*it, UtBufferReleaseHandler, &release_data);
756 error = tdm_pp_commit(pp);
757 ASSERT_EQ(TDM_ERROR_NONE, error);
762 ASSERT_EQ(2, release_data);