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;
252 struct epoll_event ep;
254 ASSERT_NO_FATAL_FAILURE(TDMPP::SetUp());
256 epFd = epoll_create1(0);
257 ASSERT_TRUE(epFd != -1);
259 timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
260 ASSERT_TRUE(timerFd != -1);
262 memset(&ep, 0, sizeof ep);
263 ep.events |= EPOLLIN;
264 ep.data.fd = timerFd;
265 ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, timerFd, &ep) == 0);
267 ASSERT_TRUE(tdm_display_get_fd(dpy, &tdmFd) == TDM_ERROR_NONE);
269 memset(&ep, 0, sizeof ep);
270 ep.events |= EPOLLIN;
272 ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, tdmFd, &ep) == 0);
285 void UtHandlePPEvent(int num_attached_buffers)
287 struct itimerspec its;
289 struct epoll_event ep_event[2];
291 if (utPpDoneHandlerSuccessCounter == num_attached_buffers)
294 its.it_interval.tv_sec = 0;
295 its.it_interval.tv_nsec = 0;
296 its.it_value.tv_sec = timeLimitSec;
297 its.it_value.tv_nsec = timeLimitNsec;
299 ASSERT_TRUE(timerfd_settime(timerFd, 0, &its, NULL) == 0);
302 count = epoll_wait(epFd, ep_event, sizeof(ep_event), -1);
303 ASSERT_TRUE(count >= 0);
305 for (int i = 0; i < count; i++) {
306 if (ep_event[i].data.fd == timerFd) {
309 ASSERT_TRUE(tdm_display_handle_events(dpy) == TDM_ERROR_NONE);
310 if (utPpDoneHandlerSuccessCounter == num_attached_buffers)
317 int UtPrepareToPP(tdm_info_pp *info)
320 tbm_surface_h src_buf, dst_buf;
322 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
323 EXPECT_EQ(TDM_ERROR_NONE, error);
324 if (error != TDM_ERROR_NONE)
327 error = tdm_pp_set_info(pp, info);
328 EXPECT_EQ(TDM_ERROR_NONE, error);
329 if (error != TDM_ERROR_NONE)
332 src_buf = UtCreateBuffer(info->src_config.pos.w, info->src_config.pos.h,
333 info->src_config.format);
334 EXPECT_NE(NULL, src_buf);
338 dst_buf = UtCreateBuffer(info->dst_config.pos.w, info->dst_config.pos.h,
339 info->dst_config.format);
340 EXPECT_NE(NULL, dst_buf);
344 error = tdm_pp_attach(pp, src_buf, dst_buf);
345 EXPECT_EQ(TDM_ERROR_NONE, error);
346 if (error != TDM_ERROR_NONE)
352 int UtPrepareToPPWithScale()
354 tdm_info_pp info = {0};
356 UtGetPPInfoWithScale(&info);
358 return UtPrepareToPP(&info);
361 int UtPrepareToPPWithScaleAndTransform()
363 tdm_info_pp info = {0};
365 UtGetPPInfoWithScaleAndTransform(&info);
367 return UtPrepareToPP(&info);
370 int UtPrepareToPPWithWrongInfo()
372 tdm_info_pp info = {0};
376 UtGetPPInfoWithScale(&info);
378 ret = UtPrepareToPP(&info);
382 UtGetPPInfoWithWrongInfo(&info);
384 error = tdm_pp_set_info(pp, &info);
385 EXPECT_EQ(TDM_ERROR_NONE, error);
386 if (error != TDM_ERROR_NONE)
394 class TDMPPCommitThread : public TDMPPCommit {
398 TDMPPCommit::SetEnvs();
399 setenv("TDM_THREAD", "1", 1);
403 TDMPPCommit::UnsetEnvs();
404 unsetenv("TDM_THREAD");
408 void UtPpDoneHandler(tdm_pp *pp, tbm_surface_h src,
409 tbm_surface_h dst, void *user_data)
411 TDMPPCommit *pp_commit = (TDMPPCommit *)user_data;
412 bool src_valid = false, dst_valid = false;
417 for (auto it = pp_commit->buffers_list.begin(); it != pp_commit->buffers_list.end(); ++it) {
424 if (src_valid && dst_valid)
425 pp_commit->utPpDoneHandlerSuccessCounter++;
428 TEST_F(TDMPPWithoutCreation, DisplayGetPPAvailableFormatsSuccessful)
431 const tbm_format *formats = NULL;
433 ASSERT_TRUE(TDM_ERROR_NONE == tdm_display_get_pp_available_formats(dpy, &formats, &count));
434 ASSERT_FALSE(-42 == count);
435 ASSERT_FALSE(NULL == formats);
438 /* tdm_display_create_pp() */
440 TEST_F(TDMPPWithoutCreation, DisplayCreatePPNullAll)
445 pp = tdm_display_create_pp(NULL, NULL);
449 TEST_F(TDMPPWithoutCreation, DisplayCreatePPNullDpy)
455 pp = tdm_display_create_pp(NULL, &error);
457 ASSERT_NE(TDM_ERROR_NONE, error);
460 TEST_F(TDMPPWithoutCreation, DisplayCreatePPSuccessNullError)
465 pp = tdm_display_create_pp(dpy, NULL);
469 TEST_F(TDMPPWithoutCreation, DisplayCreatePPSuccess)
475 pp = tdm_display_create_pp(dpy, &error);
477 ASSERT_EQ(TDM_ERROR_NONE, error);
480 /* tdm_pp_set_info() */
482 TEST_F(TDMPP, PpSetInfoNullAll)
487 error = tdm_pp_set_info(NULL, NULL);
488 ASSERT_NE(TDM_ERROR_NONE, error);
491 TEST_F(TDMPP, PpSetInfoNullPP)
497 error = tdm_pp_set_info(NULL, &info);
498 ASSERT_NE(TDM_ERROR_NONE, error);
501 TEST_F(TDMPP, PpSetInfoNullInfo)
506 error = tdm_pp_set_info(pp, NULL);
507 ASSERT_NE(TDM_ERROR_NONE, error);
510 TEST_F(TDMPP, PpSetInfoSuccess)
516 UtGetPPInfoWithScale(&info);
518 error = tdm_pp_set_info(pp, &info);
519 ASSERT_EQ(TDM_ERROR_NONE, error);
522 /* tdm_pp_set_done_handler() */
524 TEST_F(TDMPP, PpSetDoneHandlerFailNullAll)
529 error = tdm_pp_set_done_handler(NULL, NULL, NULL);
530 ASSERT_NE(TDM_ERROR_NONE, error);
533 TEST_F(TDMPP, PpSetDoneHandlerFailNullPP)
538 error = tdm_pp_set_done_handler(NULL, UtPpDoneHandler, this);
539 ASSERT_NE(TDM_ERROR_NONE, error);
542 TEST_F(TDMPP, PpSetDoneHandlerSuccessNullFailNullFunc)
548 error = tdm_pp_set_done_handler(pp, NULL, &data);
549 ASSERT_NE(TDM_ERROR_NONE, error);
552 TEST_F(TDMPP, PpSetDoneHandlerSuccessNullData)
557 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
558 ASSERT_EQ(TDM_ERROR_NONE, error);
561 TEST_F(TDMPP, PpSetDoneHandlerSuccess)
566 error = tdm_pp_set_done_handler(pp, UtPpDoneHandler, this);
567 ASSERT_EQ(TDM_ERROR_NONE, error);
570 /* tdm_pp_attach() */
572 TEST_F(TDMPP, PpAttachFailNullAll)
577 error = tdm_pp_attach(NULL, NULL, NULL);
578 ASSERT_NE(TDM_ERROR_NONE, error);
581 TEST_F(TDMPP, PpAttachFailNullPp)
585 tbm_surface_h dst_buf, src_buf;
587 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
588 ASSERT_NE(NULL, src_buf);
590 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
591 ASSERT_NE(NULL, dst_buf);
593 error = tdm_pp_attach(NULL, src_buf, dst_buf);
594 ASSERT_NE(TDM_ERROR_NONE, error);
597 TEST_F(TDMPP, PpAttachFailNullSrc)
601 tbm_surface_h dst_buf;
603 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
604 ASSERT_NE(NULL, dst_buf);
606 error = tdm_pp_attach(pp, NULL, dst_buf);
607 ASSERT_NE(TDM_ERROR_NONE, error);
610 TEST_F(TDMPP, PpAttachFailNullDst)
614 tbm_surface_h src_buf;
616 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
617 ASSERT_NE(NULL, src_buf);
619 error = tdm_pp_attach(pp, src_buf, NULL);
620 ASSERT_NE(TDM_ERROR_NONE, error);
623 TEST_F(TDMPP, PpAttachSuccess)
627 tbm_surface_h dst_buf, src_buf;
629 src_buf = UtCreateBuffer(default_src_w, default_src_h, formats[0]);
630 ASSERT_NE(NULL, src_buf);
632 dst_buf = UtCreateBuffer(default_dst_w, default_dst_h, formats[0]);
633 ASSERT_NE(NULL, dst_buf);
635 error = tdm_pp_attach(pp, src_buf, dst_buf);
636 ASSERT_EQ(TDM_ERROR_NONE, error);
639 /* tdm_pp_commit() */
641 TEST_F(TDMPP, PpCommitFailNullPP)
646 error = tdm_pp_commit(NULL);
647 ASSERT_NE(TDM_ERROR_NONE, error);
650 TEST_F(TDMPPCommit, PpCommitFailWrongInfo)
655 ASSERT_NE(-1, UtPrepareToPPWithWrongInfo());
657 error = tdm_pp_commit(pp);
658 ASSERT_NE(TDM_ERROR_NONE, error);
661 TEST_F(TDMPPCommit, PpCommitSuccessScale)
666 ASSERT_NE(-1, UtPrepareToPPWithScale());
668 error = tdm_pp_commit(pp);
669 ASSERT_EQ(TDM_ERROR_NONE, error);
673 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
676 TEST_F(TDMPPCommit, PpCommitSuccessScaleAndTransform)
681 ASSERT_NE(-1, UtPrepareToPPWithScale());
683 error = tdm_pp_commit(pp);
684 ASSERT_EQ(TDM_ERROR_NONE, error);
688 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
691 TEST_F(TDMPPCommitThread, PpCommitSuccessScale)
696 ASSERT_NE(-1, UtPrepareToPPWithScale());
698 error = tdm_pp_commit(pp);
699 ASSERT_EQ(TDM_ERROR_NONE, error);
703 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
706 TEST_F(TDMPPCommitThread, PpCommitSuccessScaleAndTransform)
711 ASSERT_NE(-1, UtPrepareToPPWithScale());
713 error = tdm_pp_commit(pp);
714 ASSERT_EQ(TDM_ERROR_NONE, error);
718 ASSERT_EQ(1, utPpDoneHandlerSuccessCounter);
721 /* tdm_pp_destroy() */
723 void UtBufferReleaseHandler(tbm_surface_h buffer,
726 int *data = (int *)user_data;
733 TEST_F(TDMPPCommit, PPDestroySuccessAfterCommit)
737 int release_data = 0;
739 ASSERT_NE(-1, UtPrepareToPPWithScale());
741 for (auto it = buffers_list.begin(); it != buffers_list.end(); ++it) {
742 tdm_buffer_add_release_handler((tbm_surface_h)*it, UtBufferReleaseHandler, &release_data);
745 error = tdm_pp_commit(pp);
746 ASSERT_EQ(TDM_ERROR_NONE, error);
751 ASSERT_EQ(2, release_data);