From: Changyeon Lee Date: Wed, 22 Jun 2022 07:53:12 +0000 (+0900) Subject: remove legacy libtdm backend X-Git-Tag: submit/tizen/20220627.072238^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Faccepted%2Ftizen_unified;p=platform%2Fadaptation%2Fnexell%2Flibtdm-nexell.git remove legacy libtdm backend Change-Id: I057b8730e0be11f7089a3e907bea96f7f8133801 --- diff --git a/configure.ac b/configure.ac index feea542..1c4d932 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.60]) -AC_INIT([libtdm-nexell], +AC_INIT([hal-backend-tdm-nexell], [1.0.0], [https://www.tizen.org], - [libtdm-nexell]) + [hal-backend-tdm-nexell]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([Makefile.am]) @@ -25,30 +25,16 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) PKG_CHECK_MODULES(UDEV, libudev, [udev=yes], [udev=no]) -# for libtdm-nexell -PKG_CHECK_MODULES(TDM_NEXELL, libtdm libtbm libdrm pixman-1) - # for libhal-backend-tdm-nexell -PKG_CHECK_MODULES(LIBHAL_BACKEND_TDM_NEXELL, hal-api-common hal-api-tdm hal-api-tbm libdrm dlog pixman-1) +PKG_CHECK_MODULES(LIBHAL_BACKEND_TDM_NEXELL, hal-api-common hal-api-tdm hal-api-tbm libtbm libdrm dlog pixman-1) if test x"$udev" = xyes; then - # for libtdm-nexell AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) - TDM_NEXELL_CFLAGS="$TDM_NEXELL_CFLAGS $UDEV_CFLAGS" - TDM_NEXELL_LIBS="$TDM_NEXELL_LIBS $UDEV_LIBS" - # for libhal-backend-tdm-nexell LIBHAL_BACKEND_TDM_NEXELL_CFLAGS="$LIBHAL_BACKEND_TDM_NEXELL_CFLAGS $UDEV_CFLAGS" LIBHAL_BACKEND_TDM_NEXELL_LIBS="$LIBHAL_BACKEND_TDM_NEXELL_LIBS $UDEV_LIBS" - AC_SUBST(LIBHAL_BACKEND_TDM_NEXELL_CFLAGS) - AC_SUBST(LIBHAL_BACKEND_TDM_NEXELL_LIBS) fi -# for libtdm-nexell -AC_SUBST(TDM_NEXELL_CFLAGS) -AC_SUBST(TDM_NEXELL_LIBS) - -# for libhal-backend-tdm-nexell AC_SUBST(LIBHAL_BACKEND_TDM_NEXELL_CFLAGS) AC_SUBST(LIBHAL_BACKEND_TDM_NEXELL_LIBS) @@ -59,13 +45,6 @@ AC_DEFINE_UNQUOTED(LIBDRM_MINOR_VERSION, [`pkg-config --modversion libdrm | cut AC_DEFINE_UNQUOTED(LIBDRM_MICRO_VERSION, [`pkg-config --modversion libdrm | cut -d '.' -f 3`], dnl [libdrm major version]) -# set the dir for the tbm module -DEFAULT_TDM_MODULE_PATH="${libdir}/tdm" -AC_ARG_WITH(tdm-module-path, AS_HELP_STRING([--with-tdm-module-path=PATH], [tdm module dir]), - [ TDM_MODULE_PATH="$withval" ], - [ TDM_MODULE_PATH="${DEFAULT_TDM_MODULE_PATH}" ]) -AC_SUBST(TDM_MODULE_PATH) - # set the library dir for the tdm hal backend DEFAULT_HAL_LIBDIR="/hal/lib" AC_ARG_WITH(hal-libdir, AS_HELP_STRING([--with-hal-libdir=PATH], [hal backend library path]), @@ -77,21 +56,12 @@ AC_SUBST(HAL_LIBDIR) # For enumerating devices in test case AC_OUTPUT([ Makefile - src/libhal-backend-tdm-nexell/Makefile - src/libtdm-nexell/Makefile src/Makefile]) echo "" echo "$PACKAGE_STRING will be compiled with:" echo "" -echo "TDM_NEXELL_CFLAGS : $LIBHAL_BACKEND_TDM_NEXELL_CFLAGS" -echo "TDM_NEXELL_LIBS : $LIBHAL_BACKEND_TDM_NEXELL_LIBS" -echo "TDM_MODULE_DIR : $HAL_LIBDIR" -echo "" -echo "" -echo "$PACKAGE_STRING will be compiled with:" -echo "" -echo "TDM_NEXELL_CFLAGS : $TDM_NEXELL_CFLAGS" -echo "TDM_NEXELL_LIBS : $TDM_NEXELL_LIBS" -echo "TDM_MODULE_DIR : $TDM_MODULE_PATH" +echo "LIBHAL_BACKEND_TDM_NEXELL_CFLAGS : $LIBHAL_BACKEND_TDM_NEXELL_CFLAGS" +echo "LIBHAL_BACKEND_TDM_NEXELL_LIBS : $LIBHAL_BACKEND_TDM_NEXELL_LIBS" +echo "HAL_LIBDIR : $HAL_LIBDIR" echo "" diff --git a/packaging/hal-backend-tdm-nexell.manifest b/packaging/hal-backend-tdm-nexell.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/hal-backend-tdm-nexell.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/hal-backend-tdm-nexell.spec b/packaging/hal-backend-tdm-nexell.spec new file mode 100644 index 0000000..8174eb8 --- /dev/null +++ b/packaging/hal-backend-tdm-nexell.spec @@ -0,0 +1,62 @@ +Name: hal-backend-tdm-nexell +Version: 3.0.6 +Release: 0 +Summary: hal-backend-tdm module for nexell +Group: System/Libraries +License: MIT +ExclusiveArch: %{arm} aarch64 +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest + +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(libudev) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(hal-api-common) +BuildRequires: pkgconfig(hal-api-tdm) +BuildRequires: pkgconfig(hal-api-tbm) +BuildRequires: pkgconfig(pixman-1) +%ifarch %{arm} +BuildRequires: artik530-raptor-linux-kernel-headers +BuildConflicts: linux-glibc-devel +%else +BuildRequires: artik710-raptor-linux-kernel-headers +BuildConflicts: linux-glibc-devel +%endif + +%description +description: hal tdm backend module for nexell + +%global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share} + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +%reconfigure --prefix=%{_prefix} --libdir=%{_libdir} --disable-static \ + --with-hal-libdir=%{_hal_libdir} \ + CFLAGS="${CFLAGS} -Wall -Werror" \ + LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" +make %{?_smp_mflags} + +%install +rm -rf %{buildroot} +%make_install + +# make lincense directory and move COPY to it. +mkdir -p %{buildroot}%{_hal_licensedir}/libhal-backend-tdm-nexell +cp -af COPYING %{buildroot}%{_hal_licensedir}/libhal-backend-tdm-nexell + +%post +if [ -f %{_hal_libdir}/libhal-backend-tdm.so ]; then + rm -rf %{_hal_libdir}/libhal-backend-tdm.so +fi +ln -s libhal-backend-tdm-nexell.so %{_hal_libdir}/libhal-backend-tdm.so + +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%{_hal_licensedir}/libhal-backend-tdm-nexell/COPYING +%{_hal_libdir}/libhal-backend-*.so* diff --git a/packaging/libhal-backend-tdm-nexell.manifest b/packaging/libhal-backend-tdm-nexell.manifest deleted file mode 100644 index 75b0fa5..0000000 --- a/packaging/libhal-backend-tdm-nexell.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packaging/libtdm-nexell.manifest b/packaging/libtdm-nexell.manifest deleted file mode 100644 index 75b0fa5..0000000 --- a/packaging/libtdm-nexell.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packaging/libtdm-nexell.spec b/packaging/libtdm-nexell.spec deleted file mode 100644 index e0d04a9..0000000 --- a/packaging/libtdm-nexell.spec +++ /dev/null @@ -1,88 +0,0 @@ -Name: libtdm-nexell -Version: 3.0.6 -Release: 0 -Summary: Tizen Display Manager Nexell Back-End Library -Group: Development/Libraries -License: MIT -ExclusiveArch: %{arm} aarch64 -Source0: %{name}-%{version}.tar.gz -Source1001: %{name}.manifest -Source1002: libhal-backend-tdm-nexell.manifest - -BuildRequires: pkgconfig(libdrm) -BuildRequires: pkgconfig(libudev) -BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(libtdm) -BuildRequires: pkgconfig(libtbm) -BuildRequires: pkgconfig(hal-api-common) -BuildRequires: pkgconfig(hal-api-tdm) -BuildRequires: pkgconfig(hal-api-tbm) -BuildRequires: pkgconfig(pixman-1) -%ifarch %{arm} -BuildRequires: artik530-raptor-linux-kernel-headers -BuildConflicts: linux-glibc-devel -%else -BuildRequires: artik710-raptor-linux-kernel-headers -BuildConflicts: linux-glibc-devel -%endif - -%description -Back-End library of Tizen Display Manager Nexell : libtdm-mgr Nexell library - -%package -n hal-backend-tdm-nexell -Summary: hal-backend-tdm module for nexell -Group: System/Libraries -Requires: hal-api-tdm -Requires: hal-api-common - -%description -n hal-backend-tdm-nexell -descriptionion: hal tdm backend module for nexell - -%global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share} - -%prep -%setup -q -cp %{SOURCE1001} . -cp %{SOURCE1002} . - -%build -%reconfigure --prefix=%{_prefix} --libdir=%{_libdir} --disable-static \ - --with-hal-libdir=%{_hal_libdir} \ - CFLAGS="${CFLAGS} -Wall -Werror" \ - LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" -make %{?_smp_mflags} - -%install -rm -rf %{buildroot} -%make_install - -# make lincense directory and move COPY to it. -mkdir -p %{buildroot}%{_hal_licensedir}/libhal-backend-tdm-nexell -cp -af COPYING %{buildroot}%{_hal_licensedir}/libhal-backend-tdm-nexell - -%post -if [ -f %{_libdir}/tdm/libtdm-default.so ]; then - rm -rf %{_libdir}/tdm/libtdm-default.so -fi -ln -s libtdm-nexell.so %{_libdir}/tdm/libtdm-default.so - -%postun -p /sbin/ldconfig - -%post -n hal-backend-tdm-nexell -if [ -f %{_hal_libdir}/libhal-backend-tdm.so ]; then - rm -rf %{_hal_libdir}/libhal-backend-tdm.so -fi -ln -s libhal-backend-tdm-nexell.so %{_hal_libdir}/libhal-backend-tdm.so - -%postun -n hal-backend-tdm-nexell -p /sbin/ldconfig - -%files -%defattr(-,root,root,-) -%manifest %{name}.manifest -%license COPYING -%{_libdir}/tdm/libtdm-nexell.so - -%files -n hal-backend-tdm-nexell -%manifest libhal-backend-tdm-nexell.manifest -%{_hal_licensedir}/libhal-backend-tdm-nexell/COPYING -%{_hal_libdir}/libhal-backend-*.so* diff --git a/src/Makefile.am b/src/Makefile.am index 1dfe35d..fdaf1b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1,17 @@ -SUBDIRS = libtdm-nexell libhal-backend-tdm-nexell +AM_CFLAGS = \ + $(LIBHAL_BACKEND_TDM_NEXELL_CFLAGS) \ + -I$(top_srcdir)/src + +libhal_backend_tdm_nexell_la_LTLIBRARIES = libhal-backend-tdm-nexell.la +libhal_backend_tdm_nexell_ladir = @HAL_LIBDIR@ +libhal_backend_tdm_nexell_la_LDFLAGS = -module -avoid-version +libhal_backend_tdm_nexell_la_LIBADD = $(LIBHAL_BACKEND_TDM_NEXELL_LIBS) -ldl + +libhal_backend_tdm_nexell_la_SOURCES = \ + tdm_backend_log.c \ + tdm_backend_nexell.c \ + tdm_nexell_display.c \ + tdm_nexell_format.c \ + tdm_nexell_hwc_window.c \ + tdm_nexell_hwc.c \ + tdm_nexell_pp.c diff --git a/src/libhal-backend-tdm-nexell/Makefile.am b/src/libhal-backend-tdm-nexell/Makefile.am deleted file mode 100644 index a5ebd14..0000000 --- a/src/libhal-backend-tdm-nexell/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -AM_CFLAGS = \ - $(LIBHAL_BACKEND_TDM_NEXELL_CFLAGS) \ - -I$(top_srcdir)/src/libhal-backend-tdm-nexell - -libhal_backend_tdm_nexell_la_LTLIBRARIES = libhal-backend-tdm-nexell.la -libhal_backend_tdm_nexell_ladir = @HAL_LIBDIR@ -libhal_backend_tdm_nexell_la_LDFLAGS = -module -avoid-version -libhal_backend_tdm_nexell_la_LIBADD = $(LIBHAL_BACKEND_TDM_NEXELL_LIBS) -ldl - -libhal_backend_tdm_nexell_la_SOURCES = \ - tdm_backend_log.c \ - tdm_backend_nexell.c \ - tdm_nexell_display.c \ - tdm_nexell_format.c \ - tdm_nexell_hwc_window.c \ - tdm_nexell_hwc.c \ - tdm_nexell_pp.c diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_list.h b/src/libhal-backend-tdm-nexell/tdm_backend_list.h deleted file mode 100644 index 3873817..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_list.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - */ - -/** - * \file - * List macros heavily inspired by the Linux kernel - * list handling. No list looping yet. - * - * Is not threadsafe, so common operations need to - * be protected using an external mutex. - */ -#ifndef _U_DOUBLE_LIST_H_ -#define _U_DOUBLE_LIST_H_ - -#include - -struct list_head { - struct list_head *prev; - struct list_head *next; -}; - -static inline void list_inithead(struct list_head *item) -{ - item->prev = item; - item->next = item; -} - -static inline void list_add(struct list_head *item, struct list_head *list) -{ - item->prev = list; - item->next = list->next; - list->next->prev = item; - list->next = item; -} - -static inline void list_addtail(struct list_head *item, struct list_head *list) -{ - item->next = list; - item->prev = list->prev; - list->prev->next = item; - list->prev = item; -} - -static inline void list_replace(struct list_head *from, struct list_head *to) -{ - to->prev = from->prev; - to->next = from->next; - from->next->prev = to; - from->prev->next = to; -} - -static inline void list_del(struct list_head *item) -{ - item->prev->next = item->next; - item->next->prev = item->prev; -} - -static inline void list_delinit(struct list_head *item) -{ - item->prev->next = item->next; - item->next->prev = item->prev; - item->next = item; - item->prev = item; -} - -static inline int list_length(struct list_head *item) -{ - struct list_head *next; - int length = 0; - - next = item->next; - while (next != item) { - length++; - next = next->next; - } - - return length; -} - -#define LIST_INITHEAD(__item) list_inithead(__item) -#define LIST_ADD(__item, __list) list_add(__item, __list) -#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) -#define LIST_REPLACE(__from, __to) list_replace(__from, __to) -#define LIST_DEL(__item) list_del(__item) -#define LIST_DELINIT(__item) list_delinit(__item) -#define LIST_LENGTH(__item) list_length(__item) - -#define LIST_ENTRY(__type, __item, __field) \ - ((__type *)(((char *)(__item)) - offsetof(__type, __field))) - -#define LIST_FIRST_ENTRY(__ptr, __type, __field) \ - LIST_ENTRY(__type, (__ptr)->next, __field) - -#define LIST_LAST_ENTRY(__ptr, __type, __field) \ - LIST_ENTRY(__type, (__ptr)->prev, __field) - -#define LIST_IS_EMPTY(__list) \ - ((__list)->next == (__list)) - -#ifndef container_of -#define container_of(ptr, sample, member) \ - (void *)((char *)(ptr) \ - - ((char *)&(sample)->member - (char *)(sample))) -#endif - -#define LIST_FOR_EACH_ENTRY(pos, head, member) \ - for (pos = container_of((head)->next, pos, member); \ - &pos->member != (head); \ - pos = container_of(pos->member.next, pos, member)) - -#define LIST_FOR_EACH_ENTRY_REV(pos, head, member) \ - for (pos = container_of((head)->prev, pos, member); \ - &pos->member != (head); \ - pos = container_of(pos->member.prev, pos, member)) - -#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ - for (pos = container_of((head)->next, pos, member), \ - storage = container_of(pos->member.next, pos, member); \ - &pos->member != (head); \ - pos = storage, storage = container_of(storage->member.next, storage, member)) - -#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ - for (pos = container_of((head)->prev, pos, member), \ - storage = container_of(pos->member.prev, pos, member); \ - &pos->member != (head); \ - pos = storage, storage = container_of(storage->member.prev, storage, member)) - -#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ - for (pos = container_of((start), pos, member); \ - &pos->member != (head); \ - pos = container_of(pos->member.next, pos, member)) - -#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ - for (pos = container_of((start), pos, member); \ - &pos->member != (head); \ - pos = container_of(pos->member.prev, pos, member)) - -#define LIST_FIND_ITEM(item, head, type, member, found) \ - do { \ - type *pos = NULL; \ - found = NULL; \ - LIST_FOR_EACH_ENTRY(pos, head, member) \ - if (pos == item) { found = item; break; } \ - } while (0) - -#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_log.c b/src/libhal-backend-tdm-nexell/tdm_backend_log.c deleted file mode 100644 index 31d1b83..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_log.c +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#include "tdm_backend_log.h" - -#undef LOG_TAG -#define LOG_TAG "HAL_TDM_BACKEND" - -unsigned int tbm_log_debug_level = TDM_BACKEND_LOG_LEVEL_INFO; - -static void -_tdm_backend_log_dlog_print(int level, const char *fmt, va_list arg) -{ - log_priority dlog_prio; - - switch (level) { - case TDM_BACKEND_LOG_LEVEL_ERR: - dlog_prio = DLOG_ERROR; - break; - case TDM_BACKEND_LOG_LEVEL_WRN: - dlog_prio = DLOG_WARN; - break; - case TDM_BACKEND_LOG_LEVEL_INFO: - dlog_prio = DLOG_INFO; - break; - case TDM_BACKEND_LOG_LEVEL_DBG: - dlog_prio = DLOG_DEBUG; - break; - default: - return; - } - __dlog_vprint(LOG_ID_SYSTEM, dlog_prio, LOG_TAG, fmt, arg); -} - -void -tdm_backend_log_print(int level, const char *fmt, ...) -{ - va_list arg; - - if (level > tbm_log_debug_level) - return; - - va_start(arg, fmt); - _tdm_backend_log_dlog_print(level, fmt, arg); - va_end(arg); -} diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_log.h b/src/libhal-backend-tdm-nexell/tdm_backend_log.h deleted file mode 100644 index ec76eff..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_log.h +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef __TDM_BACKEND_LOG_H__ -#define __TDM_BACKEND_LOG_H__ - -#include -#include -#include -#include - -enum { - TDM_BACKEND_LOG_LEVEL_NONE, - TDM_BACKEND_LOG_LEVEL_ERR, - TDM_BACKEND_LOG_LEVEL_WRN, - TDM_BACKEND_LOG_LEVEL_INFO, - TDM_BACKEND_LOG_LEVEL_DBG, -}; - - -/* log level */ -void tdm_backend_log_print(int level, const char *fmt, ...); - -#define TDM_BACKEND_DBG(fmt, args...) \ - do { \ - struct timespec ts; \ - clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_DBG, "[%5d.%06d][%d][%s %d]"fmt, \ - (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ - } while (0) - -#define TDM_BACKEND_INFO(fmt, args...) \ - do { \ - struct timespec ts; \ - clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt, \ - (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ - } while (0) - -#define TDM_BACKEND_WRN(fmt, args...) \ - do { \ - struct timespec ts; \ - clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_WRN, "[%5d.%06d][%d][%s %d]"fmt, \ - (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ - } while (0) - -#define TDM_BACKEND_ERR(fmt, args...) \ - do { \ - struct timespec ts; \ - clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_ERR, "[%5d.%06d][%d][%s %d]"fmt, \ - (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ - } while (0) - -#define TDM_BACKEND_RETURN_IF_FAIL(cond) {\ - if (!(cond)) {\ - TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ - return;\ - } \ -} -#define TDM_BACKEND_RETURN_VAL_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ - return val;\ - } \ -} -#define TDM_BACKEND_GOTO_VAL_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ - goto val;\ - } \ -} - -#endif /* __TDM_BACKEND_LOG_H__ */ \ No newline at end of file diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_nexell.c b/src/libhal-backend-tdm-nexell/tdm_backend_nexell.c deleted file mode 100644 index a041159..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_nexell.c +++ /dev/null @@ -1,585 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -#if HAVE_UDEV -#include -#endif - -#define ENABLE_PP -#define HAL_TDM_NEXELL_ENABLE_HWC 1 - -#define HAL_TDM_NEXELL_NAME "nexell" - -#ifdef HAVE_UDEV -static struct udev_device * -_tdm_find_primary_gpu(void) -{ - struct udev *udev; - struct udev_enumerate *e; - struct udev_list_entry *entry; - const char *path, *id; - struct udev_device *device, *drm_device, *pci; - - udev = udev_new(); - if (!udev) { - TDM_BACKEND_ERR("fail to initialize udev context\n"); - return NULL; - } - - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "drm"); - udev_enumerate_add_match_sysname(e, "card[0-9]*"); - - udev_enumerate_scan_devices(e); - drm_device = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - if (!device) - continue; - - pci = udev_device_get_parent_with_subsystem_devtype(device, "pci", NULL); - if (pci) { - id = udev_device_get_sysattr_value(pci, "boot_vga"); - if (id && !strcmp(id, "1")) { - if (drm_device) - udev_device_unref(drm_device); - drm_device = device; - break; - } - } - - if (!drm_device) - drm_device = device; - else - udev_device_unref(device); - } - - udev_enumerate_unref(e); - - return drm_device; -} - -static hal_tdm_error -_tdm_nexell_udev_fd_handler(int fd, hal_tdm_event_loop_mask mask, void *user_data) -{ - tdm_nexell_display *display_data = (tdm_nexell_display*)user_data; - struct udev_device *dev; - const char *hotplug; - struct stat s; - dev_t udev_devnum; - int ret; - - dev = udev_monitor_receive_device(display_data->uevent_monitor); - if (!dev) { - TDM_BACKEND_ERR("couldn't receive device"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - udev_devnum = udev_device_get_devnum(dev); - - ret = fstat(display_data->drm_fd, &s); - if (ret == -1) { - TDM_BACKEND_ERR("fstat failed"); - udev_device_unref(dev); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - hotplug = udev_device_get_property_value(dev, "HOTPLUG"); - - if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && - hotplug && atoi(hotplug) == 1) - { - TDM_BACKEND_INFO("HotPlug"); - tdm_nexell_display_update_output_status(display_data); - } - - udev_device_unref(dev); - - return HAL_TDM_ERROR_NONE; -} - -static struct udev_monitor * -_tdm_nexell_create_udev_monitor() -{ - struct udev *u = NULL; - struct udev_monitor *mon = NULL; - - u = udev_new(); - if (!u) { - TDM_BACKEND_ERR("couldn't create udev"); - goto failed; - } - - mon = udev_monitor_new_from_netlink(u, "udev"); - if (!mon) { - TDM_BACKEND_ERR("couldn't create udev monitor"); - goto failed; - } - - if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 || - udev_monitor_enable_receiving(mon) < 0) { - TDM_BACKEND_ERR("add match subsystem failed"); - goto failed; - } - - TDM_BACKEND_INFO("hotplug monitor created"); - - return mon; - -failed: - if (mon) - udev_monitor_unref(mon); - if (u) - udev_unref(u); - - return NULL; -} - -static void -_tdm_nexell_destroy_udev_monitor(struct udev_monitor *mon) -{ - struct udev *u; - - if (!mon) - return; - - u = udev_monitor_get_udev(mon); - udev_monitor_unref(mon); - udev_unref(u); - - TDM_BACKEND_INFO("hotplug monitor destroyed"); -} -#endif - -static int -_tdm_nexell_open_drm(void) -{ - int fd = -1; - - fd = drmOpen(HAL_TDM_NEXELL_NAME, NULL); - if (fd < 0) - TDM_BACKEND_WRN("Cannot open '%s' drm", HAL_TDM_NEXELL_NAME); - -#ifdef HAVE_UDEV - if (fd < 0) { - struct udev_device *drm_device = NULL; - const char *filename; - TDM_BACKEND_WRN("Cannot open drm device.. search by udev"); - - drm_device = _tdm_find_primary_gpu(); - if (drm_device == NULL) { - TDM_BACKEND_ERR("fail to find drm device\n"); - goto close_l; - } - - filename = udev_device_get_devnode(drm_device); - - fd = open(filename, O_RDWR | O_CLOEXEC); - if (fd < 0) - TDM_BACKEND_ERR("Cannot open drm device(%s)\n", filename); - - TDM_BACKEND_DBG("open drm device (name:%s, fd:%d)", filename, fd); - - udev_device_unref(drm_device); - } -close_l: -#endif - - return fd; -} - -static void -_tdm_nexell_display_deinitialize(tdm_nexell_display *display_data) -{ - tdm_nexell_display_destroy_output_list(display_data); - tdm_nexell_display_destroy_buffer_list(display_data); - - if (display_data->plane_res) - drmModeFreePlaneResources(display_data->plane_res); - if (display_data->mode_res) - drmModeFreeResources(display_data->mode_res); -} - -static hal_tdm_error -_tdm_nexell_display_initialize(tdm_nexell_display *display_data) -{ - hal_tdm_error ret; - - display_data->scaler_fd = open("/dev/scaler", O_RDWR); - if (display_data->scaler_fd < 0) - TDM_BACKEND_ERR("scaler open fail. cannot use pp."); - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - if (drmSetClientCap(display_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { - TDM_BACKEND_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed"); - } else { - TDM_BACKEND_INFO("has universal planes"); - display_data->has_universal_plane = 1; - } - - if (drmSetClientCap(display_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) { - TDM_BACKEND_WRN("Set DRM_CLIENT_CAP_ATOMIC failed"); - } else { - TDM_BACKEND_INFO("has atomic"); - display_data->has_atomic = 1; - } -#endif - - display_data->mode_res = drmModeGetResources(display_data->drm_fd); - if (!display_data->mode_res) { - TDM_BACKEND_ERR("no drm resource: %m"); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - display_data->plane_res = drmModeGetPlaneResources(display_data->drm_fd); - if (!display_data->plane_res) { - TDM_BACKEND_ERR("no drm plane resource: %m"); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - if (display_data->plane_res->count_planes <= 0) { - TDM_BACKEND_ERR("no drm plane resource"); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - ret = tdm_nexell_display_create_output_list(display_data); - if (ret != HAL_TDM_ERROR_NONE) - goto failed; - - ret = tdm_nexell_display_create_layer_list(display_data); - if (ret != HAL_TDM_ERROR_NONE) - goto failed; - - return ret; - -failed: - _tdm_nexell_display_deinitialize(display_data); - - return ret; -} - -static hal_tdm_error -_tdm_nexell_master_drm_fd_handler(hal_tdm_fd master_drm_fd, void *user_data) -{ - tdm_nexell_display *display_data = (tdm_nexell_display *) user_data; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data->drm_fd = master_drm_fd; - TDM_BACKEND_INFO("Get the master drm_fd(%d)!\n", display_data->drm_fd); - - // initialize display with a master drm_fd - ret = _tdm_nexell_display_initialize(display_data); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("fail to _tdm_nexell_display_initialize!\n"); - - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -int -hal_backend_tdm_nexell_exit(void *data) -{ - hal_tdm_backend_data *backend_data = (hal_tdm_backend_data *)data; - tdm_nexell_display *display_data; - - TDM_BACKEND_INFO("deinit"); - - TDM_BACKEND_RETURN_VAL_IF_FAIL(backend_data != NULL, -1); - - display_data = (tdm_nexell_display *)backend_data->display; - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, -1); - - if (backend_data->pp_funcs) { - free(backend_data->pp_funcs); - backend_data->pp_funcs = NULL; - } - if (backend_data->hwc_window_funcs) { - free(backend_data->hwc_window_funcs); - backend_data->hwc_window_funcs = NULL; - } - if (backend_data->hwc_funcs) { - free(backend_data->hwc_funcs); - backend_data->hwc_funcs = NULL; - } - if (backend_data->output_funcs) { - free(backend_data->output_funcs); - backend_data->output_funcs = NULL; - } - if (backend_data->display_funcs) { - free(backend_data->display_funcs); - backend_data->display_funcs = NULL; - } - - _tdm_nexell_display_deinitialize(display_data); - -#ifdef HAVE_UDEV - if (display_data->uevent_monitor) - _tdm_nexell_destroy_udev_monitor(display_data->uevent_monitor); -#endif - - if (display_data->drm_fd >= 0) - close(display_data->drm_fd); - - free(display_data); - free(backend_data); - - return HAL_TDM_ERROR_NONE; -} - -static int -hal_backend_tdm_nexell_init(void **data) -{ - hal_tdm_backend_data *backend_data = NULL; - hal_tdm_display_funcs *display_funcs = NULL; - hal_tdm_output_funcs *output_funcs = NULL; - hal_tdm_hwc_funcs *hwc_funcs = NULL; - hal_tdm_hwc_window_funcs *hwc_window_funcs = NULL; -#ifdef ENABLE_PP - hal_tdm_pp_funcs *pp_funcs = NULL; -#endif - tdm_nexell_display *display_data = NULL; - hal_tdm_error ret; - int drm_fd; -#ifdef HAVE_UDEV - static struct udev_monitor *mon; - hal_tdm_event_source *udev_event_source; -#endif - - /* allocate a hal_tdm_backend_data */ - backend_data = calloc(1, sizeof(struct _hal_tdm_backend_data)); - if (!backend_data) { - TDM_BACKEND_ERR("fail to alloc backend_data!\n"); - *data = NULL; - return -1; - } - *data = backend_data; - - /* allocate a hal_tdm_display */ - display_data = calloc(1, sizeof(struct _tdm_nexell_display)); - if (!display_data) { - TDM_BACKEND_ERR("fail to alloc display_data!\n"); - goto failed; - } - backend_data->display = (hal_tdm_display *)display_data; - - LIST_INITHEAD(&display_data->output_list); - LIST_INITHEAD(&display_data->buffer_list); - - // check if drm_fd is master fd. - drm_fd = _tdm_nexell_open_drm(); - if (drm_fd < 0) { - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - // set true when backend has a drm_device. - backend_data->has_drm_device = 1; - - if (drmIsMaster(drm_fd)) { - // drm_fd is a master drm_fd. - backend_data->drm_info.drm_fd = drm_fd; - backend_data->drm_info.is_master = 1; - - display_data->drm_fd = drm_fd; - TDM_BACKEND_INFO("Get the master drm_fd(%d)!\n", display_data->drm_fd); - - // initialize display with a master drm_fd - ret = _tdm_nexell_display_initialize(display_data); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("fail to _tdm_nexell_display_initialize!\n"); - goto failed; - } - } else { - // drm_fd is not a master drm_fd. - // request a master drm_fd - close(drm_fd); - backend_data->drm_info.drm_fd = -1; - backend_data->drm_info.is_master = 0; - backend_data->drm_info.master_drm_fd_func = _tdm_nexell_master_drm_fd_handler; - backend_data->drm_info.user_data = display_data; - - TDM_BACKEND_INFO("A backend requests an master drm_fd.\n"); - } - -#ifdef HAVE_UDEV - mon = _tdm_nexell_create_udev_monitor(); - if (!mon) { - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed; - } - display_data->uevent_monitor = mon; - - /* alloc and register udev_event_source */ - udev_event_source = calloc(1, sizeof(struct _hal_tdm_event_source)); - if (!udev_event_source) { - TDM_BACKEND_ERR("fail to alloc udev_event_source!\n"); - goto failed; - } - udev_event_source->event_fd = udev_monitor_get_fd(mon); - udev_event_source->func = _tdm_nexell_udev_fd_handler; - udev_event_source->user_data = display_data; - - backend_data->event_sources[0] = udev_event_source; - backend_data->num_event_sources++; -#endif - - /* alloc and register display_funcs */ - display_funcs = calloc(1, sizeof(struct _hal_tdm_display_funcs)); - if (!display_funcs) { - TDM_BACKEND_ERR("fail to alloc display_funcs!\n"); - goto failed; - } - backend_data->display_funcs = display_funcs; - - display_funcs->display_get_capability = nexell_display_get_capability; - display_funcs->display_get_pp_capability = nexell_display_get_pp_capability; - display_funcs->display_get_outputs = nexell_display_get_outputs; - display_funcs->display_get_fd = nexell_display_get_fd; - display_funcs->display_handle_events = nexell_display_handle_events; - display_funcs->display_create_pp = nexell_display_create_pp; - - /* alloc and register output_funcs */ - output_funcs = calloc(1, sizeof(struct _hal_tdm_output_funcs)); - if (!output_funcs) { - TDM_BACKEND_ERR("fail to alloc output_funcs!\n"); - goto failed; - } - backend_data->output_funcs = output_funcs; - - output_funcs->output_get_capability = nexell_output_get_capability; - output_funcs->output_set_property = nexell_output_set_property; - output_funcs->output_get_property = nexell_output_get_property; - output_funcs->output_wait_vblank = nexell_output_wait_vblank; - output_funcs->output_set_vblank_handler = nexell_output_set_vblank_handler; - output_funcs->output_set_dpms = nexell_output_set_dpms; - output_funcs->output_get_dpms = nexell_output_get_dpms; - output_funcs->output_set_mode = nexell_output_set_mode; - output_funcs->output_get_mode = nexell_output_get_mode; - output_funcs->output_set_mirror = NULL; - output_funcs->output_unset_mirror = NULL; -#ifdef HAVE_UDEV - output_funcs->output_set_status_handler = nexell_output_set_status_handler; -#endif - output_funcs->output_get_hwc = nexell_output_get_hwc; - - /* alloc and register hwc_funcs */ - hwc_funcs = calloc(1, sizeof(struct _hal_tdm_hwc_funcs)); - if (!hwc_funcs) { - TDM_BACKEND_ERR("fail to alloc hwc_funcs!\n"); - goto failed; - } - backend_data->hwc_funcs = hwc_funcs; - - hwc_funcs->hwc_create_window = nexell_hwc_create_window; - hwc_funcs->hwc_get_video_supported_formats = nexell_hwc_get_video_supported_formats; - hwc_funcs->hwc_get_video_available_properties = NULL; - hwc_funcs->hwc_get_capabilities = nexell_hwc_get_capabilities; - hwc_funcs->hwc_get_available_properties = nexell_hwc_get_available_properties; - hwc_funcs->hwc_get_client_target_buffer_queue = nexell_hwc_get_client_target_buffer_queue; - hwc_funcs->hwc_set_client_target_buffer = nexell_hwc_set_client_target_buffer; - hwc_funcs->hwc_set_client_target_acquire_fence = NULL; - hwc_funcs->hwc_validate = nexell_hwc_validate; - hwc_funcs->hwc_get_changed_composition_types = nexell_hwc_get_changed_composition_types; - hwc_funcs->hwc_accept_validation = nexell_hwc_accept_validation; - hwc_funcs->hwc_commit = nexell_hwc_commit; - hwc_funcs->hwc_set_commit_handler = nexell_hwc_set_commit_handler; - hwc_funcs->hwc_get_commit_fence = NULL; - hwc_funcs->hwc_get_release_fences = NULL; - - /* alloc and register hwc_window_funcs */ - hwc_window_funcs = calloc(1, sizeof(struct _hal_tdm_hwc_window_funcs)); - if (!hwc_window_funcs) { - TDM_BACKEND_ERR("fail to alloc hwc_window_funcs!\n"); - goto failed; - } - backend_data->hwc_window_funcs = hwc_window_funcs; - - hwc_window_funcs->hwc_window_destroy = nexell_hwc_window_destroy; - hwc_window_funcs->hwc_window_acquire_buffer_queue = nexell_hwc_window_acquire_buffer_queue; - hwc_window_funcs->hwc_window_release_buffer_queue = nexell_hwc_window_release_buffer_queue; - hwc_window_funcs->hwc_window_set_composition_type = nexell_hwc_window_set_composition_type; - hwc_window_funcs->hwc_window_set_buffer_damage = nexell_hwc_window_set_buffer_damage; - hwc_window_funcs->hwc_window_set_info = nexell_hwc_window_set_info; - hwc_window_funcs->hwc_window_set_buffer = nexell_hwc_window_set_buffer; - hwc_window_funcs->hwc_window_set_property = nexell_hwc_window_set_property; - hwc_window_funcs->hwc_window_get_property = nexell_hwc_window_get_property; - hwc_window_funcs->hwc_window_get_constraints = nexell_hwc_window_get_constraints; - hwc_window_funcs->hwc_window_set_name = nexell_hwc_window_set_name; - hwc_window_funcs->hwc_window_set_cursor_image = nexell_hwc_window_set_cursor_image; - -#ifdef ENABLE_PP - /* alloc and register pp_funcs */ - pp_funcs = calloc(1, sizeof(struct _hal_tdm_pp_funcs)); - if (!pp_funcs) { - TDM_BACKEND_ERR("fail to alloc pp_funcs!\n"); - goto failed; - } - backend_data->pp_funcs = pp_funcs; - - pp_funcs->pp_destroy = nexell_pp_destroy; - pp_funcs->pp_set_info = nexell_pp_set_info; - pp_funcs->pp_attach = nexell_pp_attach; - pp_funcs->pp_commit = nexell_pp_commit; - pp_funcs->pp_set_done_handler = nexell_pp_set_done_handler; -#endif - - TDM_BACKEND_INFO("init success!"); - - return HAL_TDM_ERROR_NONE; - -failed: - TDM_BACKEND_ERR("init failed!"); - - hal_backend_tdm_nexell_exit((void *)backend_data); - - return -1; -} - -hal_backend hal_backend_tdm_data = { - "nexell", - "Samsung", - HAL_ABI_VERSION_TIZEN_6_5, - hal_backend_tdm_nexell_init, - hal_backend_tdm_nexell_exit -}; diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_nexell.h b/src/libhal-backend-tdm-nexell/tdm_backend_nexell.h deleted file mode 100644 index c382548..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_nexell.h +++ /dev/null @@ -1,133 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _HAL_TDM_NEXELL_H_ -#define _HAL_TDM_NEXELL_H_ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell_types.h" - -/* display funcs */ -hal_tdm_error nexell_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps); -hal_tdm_error nexell_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps); -hal_tdm_output **nexell_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error); -hal_tdm_error nexell_display_get_fd(hal_tdm_display *display, int *fd); -hal_tdm_error nexell_display_handle_events(hal_tdm_display *display); -hal_tdm_pp* nexell_display_create_pp(hal_tdm_display *display, hal_tdm_error *error); - -/* output funcs */ -hal_tdm_error nexell_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps); -hal_tdm_error nexell_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value); -hal_tdm_error nexell_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value); -hal_tdm_error nexell_output_wait_vblank(hal_tdm_output *output, int interval, int sync, void *user_data); -hal_tdm_error nexell_output_set_vblank_handler(hal_tdm_output *output, hal_tdm_output_vblank_handler func); -hal_tdm_error nexell_output_commit(hal_tdm_output *output, int sync, void *user_data); -hal_tdm_error nexell_output_set_commit_handler(hal_tdm_output *output, hal_tdm_output_commit_handler func); -hal_tdm_error nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value); -hal_tdm_error nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value); -hal_tdm_error nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode); -hal_tdm_error nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode); -hal_tdm_error nexell_output_set_status_handler(hal_tdm_output *output, hal_tdm_output_status_handler func, void *user_data); -hal_tdm_hwc *nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error); - -/* hwc funcs */ -hal_tdm_hwc_window *nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error); -hal_tdm_error nexell_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count); -hal_tdm_error nexell_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities); -hal_tdm_error nexell_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count); -tbm_surface_queue_h nexell_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error); -hal_tdm_error nexell_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage); -hal_tdm_error nexell_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types); -hal_tdm_error nexell_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements, hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types); -hal_tdm_error nexell_hwc_accept_validation(hal_tdm_hwc *hwc); -hal_tdm_error nexell_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data); -hal_tdm_error nexell_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func); - -/* hwc_window funcs */ -void nexell_hwc_window_destroy(hal_tdm_hwc_window *hwc_window); -hal_tdm_error nexell_hwc_window_set_composition_type(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_composition composition_type); -hal_tdm_error nexell_hwc_window_set_buffer_damage(hal_tdm_hwc_window *hwc_window, hal_tdm_region damage); -hal_tdm_error nexell_hwc_window_set_info(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_info *info); -hal_tdm_error nexell_hwc_window_set_buffer(hal_tdm_hwc_window *hwc_window, tbm_surface_h surface); -hal_tdm_error nexell_hwc_window_set_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value value); -hal_tdm_error nexell_hwc_window_get_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value *value); -hal_tdm_error nexell_hwc_window_get_constraints(hal_tdm_hwc_window *hwc_window, int *constraints); -tbm_surface_queue_h nexell_hwc_window_acquire_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); -void nexell_hwc_window_release_buffer_queue(hal_tdm_hwc_window *hwc_window, tbm_surface_queue_h queue); -hal_tdm_error nexell_hwc_window_set_name(hal_tdm_hwc_window *hwc_window, const char *name); -hal_tdm_error nexell_hwc_window_set_cursor_image(hal_tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr); - -/* pp funcs */ -void nexell_pp_destroy(hal_tdm_pp *pp); -hal_tdm_error nexell_pp_set_info(hal_tdm_pp *pp, hal_tdm_info_pp *info); -hal_tdm_error nexell_pp_attach(hal_tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); -hal_tdm_error nexell_pp_commit(hal_tdm_pp *pp); -hal_tdm_error nexell_pp_set_done_handler(hal_tdm_pp *pp, hal_tdm_pp_done_handler func, void *user_data); - -/* nexell display */ -hal_tdm_error tdm_nexell_display_create_output_list(tdm_nexell_display *display_data); -void tdm_nexell_display_destroy_output_list(tdm_nexell_display *display_data); -void tdm_nexell_display_update_output_status(tdm_nexell_display *display_data); -hal_tdm_error tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data); -void tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data); - -/* nexell output */ -tdm_nexell_layer *nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zops); - -/* nexell hwc */ -hal_tdm_error tdm_nexell_hwc_initailize_target_window(tdm_nexell_hwc *hwc_data); -hal_tdm_error nexell_hwc_target_window_set_info(tdm_nexell_hwc *hwc_data, int width, int height); -tbm_surface_queue_h tdm_nexell_hwc_window_create_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); -tbm_surface_queue_h tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); -void tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue); - -/* nexell layer_data */ -hal_tdm_error nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps); -hal_tdm_error nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value); -hal_tdm_error nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value); -hal_tdm_error nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info); -hal_tdm_error nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info); -hal_tdm_error nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer); -hal_tdm_error nexell_layer_unset_buffer(tdm_nexell_layer *layer_data); - -/* nexell pp */ -hal_tdm_error tdm_nexell_pp_get_capability(tdm_nexell_display *display_data, hal_tdm_caps_pp *caps); -hal_tdm_pp* tdm_nexell_pp_create(tdm_nexell_display *display_data, hal_tdm_error *error); -void tdm_nexell_pp_handler(unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec, unsigned int tv_usec, void *data); -void tdm_nexell_pp_cb(int fd, unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec, unsigned int tv_usec, void *user_data); - -/* nexell format */ -uint32_t tdm_nexell_format_to_drm_format(tbm_format format); -tbm_format tdm_nexell_format_to_tbm_format(uint32_t format); - -#endif /* _HAL_TDM_NEXELL_H_ */ diff --git a/src/libhal-backend-tdm-nexell/tdm_backend_nexell_types.h b/src/libhal-backend-tdm-nexell/tdm_backend_nexell_types.h deleted file mode 100644 index 3d52813..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_backend_nexell_types.h +++ /dev/null @@ -1,343 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _HAL_TDM_NEXELL_TYPES_H_ -#define _HAL_TDM_NEXELL_TYPES_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "tdm_backend_list.h" -#include "tdm_backend_log.h" - -#define C(b, m) (((b) >> (m)) & 0xFF) -#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s)) -#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0)) -#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24) - -#define IS_RGB(format) (format == TBM_FORMAT_XRGB8888 || format == TBM_FORMAT_ARGB8888 || \ - format == TBM_FORMAT_XBGR8888 || format == TBM_FORMAT_ABGR8888) - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define SWAP(a, b) ({int t; t = a; a = b; b = t; }) -#define ROUNDUP(x) (ceil(floor((float)(height) / 4))) - -#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4) -#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) -#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) -#define ALIGN_TO_2KB(x) ((((x) + (1 << 11) - 1) >> 11) << 11) -#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) -#define ALIGN_TO_64KB(x) ((((x) + (1 << 16) - 1) >> 16) << 16) - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -#define NUM_BUFFERS 3 - -#define NUM_LAYERS 3 -#define NUM_UI_LAYERS 2 -#define ZPOS_MAX 2 -#define ZPOS_CURSOR 2 // cursor -#define ZPOS_2 2 // ui -#define ZPOS_1 1 // ui, primary layer_data -#define ZPOS_0 0 // video -#define ZPOS_VIDEO1 0 // video -#define ZPOS_NONE -999 - -typedef struct _tdm_nexell_display tdm_nexell_display; -typedef struct _tdm_nexell_output_data tdm_nexell_output; -typedef struct _tdm_nexell_layer_data tdm_nexell_layer; -typedef struct _tdm_nexell_hwc_data tdm_nexell_hwc; -typedef struct _tdm_nexell_hwc_window_data tdm_nexell_hwc_window_data; -typedef struct _tdm_nexell_event_data tdm_nexell_event_data; -typedef struct _tdm_nexell_display_buffer tdm_nexell_display_buffer; - -typedef enum { - TDM_NEXELL_LAYER_CAPABILITY_CURSOR = (1 << 0), /**< cursor */ - TDM_NEXELL_LAYER_CAPABILITY_PRIMARY = (1 << 1), /**< primary */ - TDM_NEXELL_LAYER_CAPABILITY_OVERLAY = (1 << 2), /**< overlay */ - TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC = (1 << 4), /**< graphic */ - TDM_NEXELL_LAYER_CAPABILITY_VIDEO = (1 << 5), /**< video */ - TDM_NEXELL_LAYER_CAPABILITY_SCALE = (1 << 8), /**< if a layer_data has scale capability */ - TDM_NEXELL_LAYER_CAPABILITY_TRANSFORM = (1 << 9), /**< if a layer_data has transform capability */ - TDM_NEXELL_LAYER_CAPABILITY_SCANOUT = (1 << 10), /**< if a layer_data allows a scanout buffer only */ - TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY = (1 << 11), /**< if a layer_data allows a reserved buffer only */ - TDM_NEXELL_LAYER_CAPABILITY_NO_CROP = (1 << 12), /**< if a layer_data has no cropping capability */ -} tdm_nexell_layer_capability; - -typedef enum { - HAL_TDM_NEXELL_EVENT_TYPE_WAIT, - HAL_TDM_NEXELL_EVENT_TYPE_COMMIT, - HAL_TDM_NEXELL_EVENT_TYPE_PAGEFLIP, -} tdm_nexell_event_type; - -struct _tdm_nexell_display -{ - int drm_fd; - int scaler_fd; - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - int has_universal_plane; - int has_atomic; -#endif - -#if HAVE_UDEV - struct udev_monitor *uevent_monitor; -#endif - - drmModeResPtr mode_res; - drmModePlaneResPtr plane_res; - - struct list_head output_list; - struct list_head buffer_list; -}; - -struct _tdm_nexell_display_buffer { - struct list_head link; - - unsigned int fb_id; - tbm_surface_h buffer; - int width; - unsigned int height; - unsigned int format; - unsigned int handles[4]; - unsigned int fds[4]; - unsigned int pitches[4]; - unsigned int offsets[4]; - unsigned int size; - unsigned int count; -}; - -struct _tdm_nexell_event_data { - tdm_nexell_event_type type; - tdm_nexell_output *output_data; - void *user_data; -}; - -struct display_properties_ids { - uint32_t connector_crtc_id; - uint32_t crtc_mode_id; - uint32_t crtc_active; - uint32_t plane_fb_id; - uint32_t plane_crtc_id; - uint32_t plane_src_x; - uint32_t plane_src_y; - uint32_t plane_src_w; - uint32_t plane_src_h; - uint32_t plane_crtc_x; - uint32_t plane_crtc_y; - uint32_t plane_crtc_w; - uint32_t plane_crtc_h; - uint32_t plane_zpos; -}; - -struct _tdm_nexell_output_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_nexell_display *display_data; - uint32_t connector_id; - uint32_t encoder_id; - uint32_t crtc_id; - uint32_t pipe; - uint32_t dpms_prop_id; - int count_modes; - drmModeModeInfoPtr drm_modes; - hal_tdm_output_mode *output_modes; - hal_tdm_output_type connector_type; - unsigned int connector_type_id; - struct list_head layer_list; - tdm_nexell_layer *primary_layer; - - /* not fixed data below */ - hal_tdm_output_vblank_handler vblank_func; - hal_tdm_output_commit_handler commit_func; - - hal_tdm_output_conn_status status; - hal_tdm_output_status_handler status_func; - void *status_user_data; - - int mode_changed; - const hal_tdm_output_mode *current_mode; - - struct display_properties_ids props; - - int crtc_enabled; - - /* atomic prop ids*/ - struct { - uint32_t crtc_id; - uint32_t crtc_mode_id; - uint32_t crtc_active; - } atomic_props_ids; - - /* hwc */ - tdm_nexell_hwc *hwc_data; -}; - -typedef struct _tdm_nexell_layer_info { - hal_tdm_info_config src_config; - hal_tdm_pos dst_pos; - hal_tdm_transform transform; -} tdm_nexell_layer_info; - -typedef struct _tdm_nexell_caps_layer { - tdm_nexell_layer_capability capabilities; /**< The capabilities of layer_data */ - - /** - * The z-order - * GRAPHIC layers are non-changeable. The zpos of GRAPHIC layers starts - * from 0. If there are 4 GRAPHIC layers, The zpos SHOULD be 0, 1, 2, 3.\n - * But the zpos of VIDEO layer_data is changeable by layer_set_video_pos() function - * of #tdm_func_layer. And The zpos of VIDEO layers is less than GRAPHIC - * layers or more than GRAPHIC layers. - * ie, ..., -2, -1, 4, 5, ... (if 0 <= GRAPHIC layer_data's zpos < 4). - * The zpos of VIDEO layers is @b relative. It doesn't need to start - * from -1 or 4. Let's suppose that there are two VIDEO layers. - * One has -2 zpos. Another has -4 zpos. Then -2 Video layer_data is higher - * than -4 VIDEO layer_data. - */ - int zpos; - - unsigned int format_count; /**< The count of available formats */ - tbm_format *formats; /**< The @b newly-allocated array of formats. will be freed in frontend. */ - - unsigned int prop_count; /**< The count of available properties */ - hal_tdm_prop *props; /**< The @b newly-allocated array of properties. will be freed in frontend. */ -} tdm_nexell_caps_layer; - -struct _tdm_nexell_layer_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_nexell_display *display_data; - tdm_nexell_output *output_data; - uint32_t plane_id; - tdm_nexell_layer_capability capabilities; - int zpos; - - /* not fixed data below */ - tdm_nexell_layer_info info; - int info_changed; - - tdm_nexell_display_buffer *display_buffer; - int display_buffer_changed; - - /* atomic prop ids*/ - struct { - uint32_t fb_id; - uint32_t crtc_id; - uint32_t src_x; - uint32_t src_y; - uint32_t src_w; - uint32_t src_h; - uint32_t crtc_x; - uint32_t crtc_y; - uint32_t crtc_w; - uint32_t crtc_h; - uint32_t zpos; - } atomic_props_ids; -}; - -struct _tdm_nexell_hwc_data { - tdm_nexell_hwc_window_data *target_hwc_window; - - int need_validate; - int need_target_window; - int need_set_crtc; - - int target_window_zpos; - - tdm_nexell_output *output_data; - struct list_head hwc_window_list; - - tbm_surface_queue_h cursor_tqueue; - tbm_surface_h cursor_tsurface; - - /* UI buffer_queue list for the reserved scanout memory */ - struct { - tbm_surface_queue_h tqueue; - int ref_cnt; - } ui_buffer_queue[NUM_LAYERS]; - - hal_tdm_hwc_commit_handler commit_func; -}; - -struct _tdm_nexell_hwc_window_data { - struct list_head link; - - tdm_nexell_hwc *hwc_data; - - hal_tdm_hwc_window_info info; - tbm_surface_h surface; - hal_tdm_hwc_window_composition client_type; - hal_tdm_hwc_window_composition validated_type; - int lzpos; - int lzpos_queue; - - char name[HAL_TDM_NAME_LEN]; - struct { - int width; - int height; - int stride; - void *ptr; - } cursor_img; - int cursor_img_surface; - int cursor_img_refresh; - - int constraints; -}; - -#endif /* _HAL_TDM_NEXELL_TYPES_H_ */ diff --git a/src/libhal-backend-tdm-nexell/tdm_nexell_display.c b/src/libhal-backend-tdm-nexell/tdm_nexell_display.c deleted file mode 100644 index 63a827a..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_nexell_display.c +++ /dev/null @@ -1,2206 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -#define MIN_WIDTH 32 - -static drmModeModeInfoPtr -_tdm_nexell_display_get_mode(tdm_nexell_output *output_data) -{ - int i; - - if (!output_data->current_mode) { - TDM_BACKEND_ERR("no output_data->current_mode"); - return NULL; - } - - for (i = 0; i < output_data->count_modes; i++) { - drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i]; - if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) && - (drm_mode->vdisplay == output_data->current_mode->vdisplay) && - (drm_mode->vrefresh == output_data->current_mode->vrefresh) && - (drm_mode->flags == output_data->current_mode->flags) && - (drm_mode->type == output_data->current_mode->type) && - !(strncmp(drm_mode->name, output_data->current_mode->name, HAL_TDM_NAME_LEN))) - return drm_mode; - } - - return NULL; -} - -static void -_tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode, - hal_tdm_output_mode *tdm_mode) -{ - tdm_mode->clock = drm_mode->clock; - tdm_mode->hdisplay = drm_mode->hdisplay; - tdm_mode->hsync_start = drm_mode->hsync_start; - tdm_mode->hsync_end = drm_mode->hsync_end; - tdm_mode->htotal = drm_mode->htotal; - tdm_mode->hskew = drm_mode->hskew; - tdm_mode->vdisplay = drm_mode->vdisplay; - tdm_mode->vsync_start = drm_mode->vsync_start; - tdm_mode->vsync_end = drm_mode->vsync_end; - tdm_mode->vtotal = drm_mode->vtotal; - tdm_mode->vscan = drm_mode->vscan; - tdm_mode->vrefresh = drm_mode->vrefresh; - tdm_mode->flags = drm_mode->flags; - tdm_mode->type = drm_mode->type; - snprintf(tdm_mode->name, HAL_TDM_NAME_LEN, "%s", drm_mode->name); -} - -static hal_tdm_error -_tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc) -{ - drmVBlank vbl; - - vbl.request.type = DRM_VBLANK_RELATIVE; - if (pipe == 1) - vbl.request.type |= DRM_VBLANK_SECONDARY; - else if (pipe > 1) - vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; - - vbl.request.sequence = 0; - if (drmWaitVBlank(fd, &vbl)) { - TDM_BACKEND_ERR("get vblank counter failed: %m"); - *msc = 0; - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - *msc = vbl.reply.sequence; - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data) -{ - drmVBlank vbl; - - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - if (pipe == 1) - vbl.request.type |= DRM_VBLANK_SECONDARY; - else if (pipe > 1) - vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; - - vbl.request.sequence = *target_msc; - vbl.request.signal = (unsigned long)(uintptr_t)data; - - if (drmWaitVBlank(fd, &vbl)) { - TDM_BACKEND_ERR("wait vblank failed: %m"); - *target_msc = 0; - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - *target_msc = vbl.reply.sequence; - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_tdm_nexell_output_update_status(tdm_nexell_output *output_data, - hal_tdm_output_conn_status status) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (output_data->status == status) - return HAL_TDM_ERROR_NONE; - - output_data->status = status; - - if (output_data->status_func) - output_data->status_func(output_data, status, - output_data->status_user_data); - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_tdm_nexell_display_commit_primary_layer(tdm_nexell_layer *layer_data, - void *user_data, int *do_waitvblank) -{ - tdm_nexell_display *display_data = layer_data->display_data; - tdm_nexell_output *output_data = layer_data->output_data; - - if (output_data->mode_changed && layer_data->display_buffer_changed) { - drmModeModeInfoPtr mode; - - if (!layer_data->display_buffer) { - TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting"); - return HAL_TDM_ERROR_BAD_REQUEST; - } - - output_data->mode_changed = 0; - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - mode = _tdm_nexell_display_get_mode(output_data); - if (!mode) { - TDM_BACKEND_ERR("couldn't find proper mode"); - return HAL_TDM_ERROR_BAD_REQUEST; - } - - if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, 0, 0, - &output_data->connector_id, 1, mode)) { - TDM_BACKEND_ERR("set crtc failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED); - - *do_waitvblank = 1; - return HAL_TDM_ERROR_NONE; - } else if (layer_data->display_buffer_changed) { - layer_data->display_buffer_changed = 0; - - if (layer_data->display_buffer) { - tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); - - if (!event_data) { - TDM_BACKEND_ERR("alloc failed"); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - - event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - if (drmModePageFlip(display_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) { - TDM_BACKEND_ERR("pageflip failed: %m"); - free(event_data); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - *do_waitvblank = 0; - } - }else { - /* to call a user commit handler whenever committed */ - *do_waitvblank = 1; - } - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_tdm_nexell_display_commit_layer(tdm_nexell_layer *layer_data) -{ - tdm_nexell_display *display_data = layer_data->display_data; - tdm_nexell_output *output_data = layer_data->output_data; - uint32_t fx, fy, fw, fh; - int crtc_w; - - if (!layer_data->display_buffer_changed && !layer_data->info_changed) - return HAL_TDM_ERROR_NONE; - - if (output_data->current_mode) - crtc_w = output_data->current_mode->hdisplay; - else { - drmModeCrtcPtr crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id); - if (!crtc) { - TDM_BACKEND_ERR("getting crtc failed"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - crtc_w = crtc->width; - if (crtc_w == 0) { - TDM_BACKEND_ERR("getting crtc width failed"); - drmModeFreeCrtc(crtc); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - drmModeFreeCrtc(crtc); - } - - // reset the changed flags - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - if (layer_data->display_buffer) { // set plane - /* Source values are 16.16 fixed point */ - fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16; - fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16; - fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16; - fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16; - - TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", - layer_data->plane_id, output_data->crtc_id, layer_data->zpos, - layer_data->display_buffer->fb_id, - layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y, - layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h, - layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, - layer_data->info.dst_pos.w, layer_data->info.dst_pos.h); - - if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id, - output_data->crtc_id, layer_data->display_buffer->fb_id, 0, - layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, - layer_data->info.dst_pos.w, layer_data->info.dst_pos.h, - fx, fy, fw, fh) < 0) { - TDM_BACKEND_ERR("set plane(%d) failed: %m", layer_data->plane_id); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - } else { // unset plane - TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n", - layer_data->plane_id, output_data->crtc_id, layer_data->zpos); - - if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id, - output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - TDM_BACKEND_ERR("unset plane(%d) filed: %m", layer_data->plane_id); - } - - return HAL_TDM_ERROR_NONE; -} - -static void -_tdm_nexell_display_cb_event(int fd, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, - void *user_data) -{ - tdm_nexell_event_data *event_data = user_data; - tdm_nexell_output *output_data; - tdm_nexell_hwc *hwc_data; - - if (!event_data) { - TDM_BACKEND_ERR("no event data"); - return; - } - - output_data = event_data->output_data; - - switch (event_data->type) { - case HAL_TDM_NEXELL_EVENT_TYPE_PAGEFLIP: - if (output_data->commit_func) - output_data->commit_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - case HAL_TDM_NEXELL_EVENT_TYPE_WAIT: - if (output_data->vblank_func) - output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - case HAL_TDM_NEXELL_EVENT_TYPE_COMMIT: - hwc_data = output_data->hwc_data; - if (!hwc_data) { - TDM_BACKEND_ERR("no hwc_data"); - break; - } - - if (hwc_data->commit_func) - hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - default: - break; - } - - free(event_data); -} - -static hal_tdm_error -_tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data) -{ - tdm_nexell_output *output_data = NULL; - int i; - - if (LIST_IS_EMPTY(&display_data->output_list)) { - TDM_BACKEND_ERR("no output"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend only support one output. */ - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { - break; - } - - if (display_data->plane_res->count_planes == 0) { - TDM_BACKEND_ERR("no layer_data error"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < display_data->plane_res->count_planes; i++) { - tdm_nexell_layer *layer_data; - drmModePlanePtr plane; - - plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]); - if (!plane) { - TDM_BACKEND_ERR("no plane"); - continue; - } - - if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { - drmModeFreePlane(plane); - continue; - } - - layer_data = calloc(1, sizeof(tdm_nexell_layer)); - if (!layer_data) { - TDM_BACKEND_ERR("alloc failed"); - drmModeFreePlane(plane); - continue; - } - - layer_data->display_data = display_data; - layer_data->output_data = output_data; - layer_data->plane_id = display_data->plane_res->planes[i]; - - layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY | - TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC; - output_data->primary_layer = layer_data; - - TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)", - layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, - layer_data->capabilities); - - LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); - - drmModeFreePlane(plane); - - /* can't take care of other planes for various hardware devices */ - break; - } - - return HAL_TDM_ERROR_NONE; -} - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - -static hal_tdm_error -_tdm_nexell_display_get_property(tdm_nexell_display *display_data, - unsigned int obj_id, unsigned int obj_type, - const char *name, unsigned int *value, - int *is_immutable) -{ - drmModeObjectPropertiesPtr props = NULL; - int i; - - props = drmModeObjectGetProperties(display_data->drm_fd, obj_id, obj_type); - if (!props) - return HAL_TDM_ERROR_OPERATION_FAILED; - - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, - props->props[i]); - - if (!prop) - continue; - - if (!strcmp(prop->name, name)) { - if (is_immutable) - *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; - if (value) - *value = (unsigned int)props->prop_values[i]; - drmModeFreeProperty(prop); - drmModeFreeObjectProperties(props); - return HAL_TDM_ERROR_NONE; - } - - drmModeFreeProperty(prop); - } - drmModeFreeObjectProperties(props); - TDM_BACKEND_DBG("coundn't find '%s' property", name); - return HAL_TDM_ERROR_OPERATION_FAILED; -} - -static hal_tdm_error -_nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id) -{ - drmModeObjectPropertiesPtr properties = NULL; - drmModePropertyPtr property = NULL; - int i; - - properties = drmModeObjectGetProperties(drm_fd, object_id, object_type); - if (properties == NULL) { - TDM_BACKEND_ERR("drmModeObjectGetProperties failed"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < properties->count_props; i++) { - property = drmModeGetProperty(drm_fd, properties->props[i]); - if (property == NULL) { - continue; - } - - if (strcmp(property->name, name) == 0) { - *id = property->prop_id; - drmModeFreeProperty(property); - break; - } - drmModeFreeProperty(property); - } - - drmModeFreeObjectProperties(properties); - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_tdm_nexell_display_create_layer_list_type(tdm_nexell_display *display_data) -{ - tdm_nexell_output *output_data = NULL; - drmModePlanePtr *planes = NULL; - unsigned int *types = NULL; - unsigned int type = 0; - int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt; - int opos_next, cpos_next; - hal_tdm_error ret; - int i; - - if (LIST_IS_EMPTY(&display_data->output_list)) { - TDM_BACKEND_ERR("no output"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend only support one output. */ - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { - break; - } - - ret = _tdm_nexell_display_get_property(display_data, - display_data->plane_res->planes[0], - DRM_MODE_OBJECT_PLANE, "type", &type, - NULL); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("plane doesn't have 'type' property. Call a fallback function"); - - /* if a plane doesn't have "type" property, we call a fallback function - * as default - */ - return _tdm_nexell_display_create_layer_list(display_data); - } - - planes = calloc(display_data->plane_res->count_planes, sizeof(drmModePlanePtr)); - if (!planes) { - TDM_BACKEND_ERR("alloc failed"); - goto failed; - } - - types = calloc(display_data->plane_res->count_planes, sizeof(unsigned int)); - if (!types) { - TDM_BACKEND_ERR("alloc failed"); - goto failed; - } - - plane_cnt = 0; - for (i = 0; i < display_data->plane_res->count_planes; i++) { - drmModePlanePtr plane; - - plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]); - if (!plane) { - TDM_BACKEND_ERR("no plane(%d)", display_data->plane_res->planes[i]); - goto failed; - } - - if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { - drmModeFreePlane(plane); - continue; - } - - ret = _tdm_nexell_display_get_property(display_data, - display_data->plane_res->planes[i], - DRM_MODE_OBJECT_PLANE, "type", &type, - NULL); - if (ret != HAL_TDM_ERROR_NONE) { - drmModeFreePlane(plane); - TDM_BACKEND_ERR("plane(%d) doesn't have 'type' info", - display_data->plane_res->planes[i]); - goto failed; - } - - planes[plane_cnt] = plane; - types[plane_cnt] = type; - plane_cnt++; - } - - primary_cnt = ovl_cnt = cursor_cnt = 0; - for (i = 0; i < plane_cnt; i++) { - if (types[i] == DRM_PLANE_TYPE_CURSOR) - cursor_cnt++; - else if (types[i] == DRM_PLANE_TYPE_OVERLAY) - ovl_cnt++; - else if (types[i] == DRM_PLANE_TYPE_PRIMARY) - primary_cnt++; - else - TDM_BACKEND_ERR("invalid type(%d)", types[i]); - } - - if (primary_cnt != 1) { - TDM_BACKEND_ERR("primary layer_data count(%d) should be one", primary_cnt); - goto failed; - } - - opos_next = 0; - cpos_next = ovl_cnt; - if (plane_cnt < 1) { - TDM_BACKEND_ERR("plane count(%d) should be over 1", plane_cnt); - goto failed; - } - - for (i = plane_cnt - 1; i >= 0; i--) { - tdm_nexell_layer *layer_data; - - layer_data = calloc(1, sizeof(tdm_nexell_layer)); - if (!layer_data) { - TDM_BACKEND_ERR("alloc failed"); - goto failed; - } - - layer_data->display_data = display_data; - layer_data->output_data = output_data; - layer_data->plane_id = planes[i]->plane_id; - - if (types[i] == DRM_PLANE_TYPE_CURSOR) { - layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_CURSOR | - TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | - TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; - layer_data->zpos = cpos_next++; - TDM_BACKEND_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos); - } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) { - if (opos_next == 0) { - layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY | - TDM_NEXELL_LAYER_CAPABILITY_SCALE | - TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; - } else { - layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY | - TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | - TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY | - TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; - } - if (opos_next == 1) { - layer_data->zpos = 2; - opos_next = 2; - } else { - layer_data->zpos = opos_next++; - } - - TDM_BACKEND_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos); - } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) { - layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY | - TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | - TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY | - TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; - layer_data->zpos = 1; - output_data->primary_layer = layer_data; - - TDM_BACKEND_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos); - } else { - free(layer_data); - continue; - } - - TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)", - layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, - layer_data->zpos, layer_data->capabilities); - - LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); - - /* get the atomic prop ids*/ - if (display_data->has_atomic) { - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h); - if (ret != HAL_TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - } - } - - for (i = 0; i < plane_cnt; i++) - if (planes[i]) - drmModeFreePlane(planes[i]); - - free(planes); - free(types); - - return HAL_TDM_ERROR_NONE; - -failed: - if (planes) { - for (i = 0; i < display_data->plane_res->count_planes; i++) - if (planes[i]) - drmModeFreePlane(planes[i]); - free(planes); - } - - free(types); - - return HAL_TDM_ERROR_OPERATION_FAILED; -} -#endif - -hal_tdm_error -tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data) -{ - tdm_nexell_output *output_data = NULL; - hal_tdm_error ret; - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - if (display_data->has_universal_plane) - ret = _tdm_nexell_display_create_layer_list_type(display_data); - else -#endif - ret = _tdm_nexell_display_create_layer_list(display_data); - - if (ret != HAL_TDM_ERROR_NONE) - return ret; - - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { - if (!output_data->primary_layer) { - TDM_BACKEND_ERR("output(%d) no primary layer_data", output_data->pipe); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - } - - return HAL_TDM_ERROR_NONE; -} - -void -tdm_nexell_display_destroy_output_list(tdm_nexell_display *display_data) -{ - tdm_nexell_output *o = NULL, *oo = NULL; - tdm_nexell_hwc *hwc_data = NULL; - - if (LIST_IS_EMPTY(&display_data->output_list)) - return; - - LIST_FOR_EACH_ENTRY_SAFE(o, oo, &display_data->output_list, link) { - hwc_data = o->hwc_data; - if (hwc_data && hwc_data->target_hwc_window) - nexell_hwc_window_destroy(hwc_data->target_hwc_window); - - LIST_DEL(&o->link); - if (!LIST_IS_EMPTY(&o->layer_list)) { - tdm_nexell_layer *l = NULL, *ll = NULL; - LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { - LIST_DEL(&l->link); - if (l->display_buffer) - tbm_surface_internal_unref(l->display_buffer->buffer); - free(l); - } - } - free(o->drm_modes); - free(o->output_modes); - free(o); - } -} - -void -tdm_nexell_display_update_output_status(tdm_nexell_display *display_data) -{ - tdm_nexell_output *output_data = NULL; - - if (LIST_IS_EMPTY(&display_data->output_list)) - return; - - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { - drmModeConnectorPtr connector; - hal_tdm_output_conn_status new_status; - - connector = drmModeGetConnector(display_data->drm_fd, - output_data->connector_id); - if (!connector) { - TDM_BACKEND_ERR("no connector: %d", output_data->connector_id); - continue; - } - - if (connector->connection == DRM_MODE_CONNECTED) - new_status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED; - else - new_status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - - _tdm_nexell_output_update_status(output_data, new_status); - - drmModeFreeConnector(connector); - } -} - -hal_tdm_error -tdm_nexell_display_create_output_list(tdm_nexell_display *display_data) -{ - tdm_nexell_output *output_data; - int i; - hal_tdm_error ret; - int allocated = 0; - drmModeConnectorPtr connector; - drmModeEncoderPtr encoder; - int conn_idx = -1; - int hdmia_idx = -1, hdmib_idx = -1; - int crtc_id = 0, c, j; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&display_data->output_list), - HAL_TDM_ERROR_OPERATION_FAILED); - - /* check if there is a connected output */ - for (i = 0; i < display_data->mode_res->count_connectors; i++) { - connector = drmModeGetConnector(display_data->drm_fd, - display_data->mode_res->connectors[i]); - if (!connector) { - TDM_BACKEND_ERR("no connector"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend considers only 1 connector because it is the TDM - * reference backend and can't take care of all hardware devices. - * To support various connectors, planes and crtcs, the new TDM backend - * should be implemented. - */ - if (connector->connection == DRM_MODE_CONNECTED) { - conn_idx = i; - drmModeFreeConnector(connector); - break; - } - - if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) - hdmia_idx = i; - if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) - hdmib_idx = i; - - drmModeFreeConnector(connector); - } - - /* use the hdmi connector if there is no connected connector. */ - /* if there is no hdmi connector, use first connector. */ - if (conn_idx == -1) { - if (hdmia_idx != -1) - conn_idx = hdmia_idx; - else if (hdmib_idx != -1) - conn_idx = hdmib_idx; - else - conn_idx = 0; - } - - /* The TDM drm backend considers only 1 connector because it is the TDM - * reference backend and can't take care of all hardware devices. - * To support various connectors, planes and crtcs, the new TDM backend - * should be implemented. - */ - connector = drmModeGetConnector(display_data->drm_fd, - display_data->mode_res->connectors[conn_idx]); - if (!connector) { - TDM_BACKEND_ERR("no connector"); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - if (connector->count_encoders != 1) { - TDM_BACKEND_ERR("too many encoders: %d", connector->count_encoders); - drmModeFreeConnector(connector); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - encoder = drmModeGetEncoder(display_data->drm_fd, connector->encoders[0]); - if (!encoder) { - TDM_BACKEND_ERR("no encoder"); - drmModeFreeConnector(connector); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - for (c = 0; c < display_data->mode_res->count_crtcs; c++) { - if ((encoder->possible_crtcs & (1 << c)) == 0) - continue; - - crtc_id = display_data->mode_res->crtcs[c]; - allocated |= (1 << c); - break; - } - - if (crtc_id == 0) { - TDM_BACKEND_ERR("no possible crtc"); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - output_data = calloc(1, sizeof(tdm_nexell_output)); - if (!output_data) { - TDM_BACKEND_ERR("alloc failed"); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - - LIST_INITHEAD(&output_data->layer_list); - - output_data->display_data = display_data; - output_data->connector_id = display_data->mode_res->connectors[conn_idx]; - output_data->encoder_id = encoder->encoder_id; - output_data->crtc_id = crtc_id; - output_data->pipe = c; - output_data->connector_type = connector->connector_type; - output_data->connector_type_id = connector->connector_type_id; - - if (connector->connection == DRM_MODE_CONNECTED) - output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED; - else - output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - - for (j = 0; j < connector->count_props; j++) { - drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, - connector->props[j]); - if (!prop) - continue; - if (!strcmp(prop->name, "DPMS")) { - output_data->dpms_prop_id = connector->props[j]; - drmModeFreeProperty(prop); - break; - } - drmModeFreeProperty(prop); - } - - if (output_data->dpms_prop_id == 0) - TDM_BACKEND_WRN("not support DPMS"); - - output_data->count_modes = connector->count_modes; - output_data->drm_modes = calloc(connector->count_modes, - sizeof(drmModeModeInfo)); - if (!output_data->drm_modes) { - TDM_BACKEND_ERR("alloc failed"); - free(output_data); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - output_data->output_modes = calloc(connector->count_modes, - sizeof(hal_tdm_output_mode)); - if (!output_data->output_modes) { - TDM_BACKEND_ERR("alloc failed"); - free(output_data->drm_modes); - free(output_data); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - for (j = 0; j < connector->count_modes; j++) { - output_data->drm_modes[j] = connector->modes[j]; - _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j], - &output_data->output_modes[j]); - } - - LIST_ADDTAIL(&output_data->link, &display_data->output_list); - - TDM_BACKEND_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)", - output_data, output_data->connector_id, output_data->status, - output_data->connector_type, - output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id, - output_data->pipe, output_data->dpms_prop_id); - - drmModeFreeEncoder(encoder); - drmModeFreeConnector(connector); - - /* get the atomic prop ids*/ - if (display_data->has_atomic) { - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->connector_id, - DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id); - if (ret != HAL_TDM_ERROR_NONE) - goto failed_create; - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id); - if (ret != HAL_TDM_ERROR_NONE) - goto failed_create; - - ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active); - if (ret != HAL_TDM_ERROR_NONE) - goto failed_create; - } - - TDM_BACKEND_DBG("output count: %d", display_data->mode_res->count_connectors); - - return HAL_TDM_ERROR_NONE; -failed_create: - tdm_nexell_display_destroy_output_list(display_data); - return ret; -} - -hal_tdm_error -nexell_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); - - caps->max_layer_count = -1; /* not defined */ - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps) -{ - return tdm_nexell_pp_get_capability(display, caps); -} - -hal_tdm_output ** -nexell_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error) -{ - tdm_nexell_display *display_data = display; - tdm_nexell_output *output_data = NULL; - hal_tdm_output **outputs; - hal_tdm_error ret; - int i; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL); - TDM_BACKEND_RETURN_VAL_IF_FAIL(count, NULL); - - *count = 0; - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) - (*count)++; - - if (*count == 0) { - ret = HAL_TDM_ERROR_NONE; - goto failed_get; - } - - /* will be freed in frontend */ - outputs = calloc(*count, sizeof(tdm_nexell_output *)); - if (!outputs) { - TDM_BACKEND_ERR("failed: alloc memory"); - *count = 0; - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - goto failed_get; - } - - i = 0; - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) - outputs[i++] = output_data; - - if (error) - *error = HAL_TDM_ERROR_NONE; - - return outputs; -failed_get: - if (error) - *error = ret; - return NULL; -} - -hal_tdm_error -nexell_display_get_fd(hal_tdm_display *display, int *fd) -{ - tdm_nexell_display *display_data = display; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(fd, HAL_TDM_ERROR_INVALID_PARAMETER); - - *fd = display_data->drm_fd; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_display_handle_events(hal_tdm_display *display) -{ - tdm_nexell_display *display_data = display; - drmEventContext ctx; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - memset(&ctx, 0, sizeof(drmEventContext)); - - ctx.version = DRM_EVENT_CONTEXT_VERSION; - ctx.page_flip_handler = _tdm_nexell_display_cb_event; - ctx.vblank_handler = _tdm_nexell_display_cb_event; - - drmHandleEvent(display_data->drm_fd, &ctx); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_pp * -nexell_display_create_pp(hal_tdm_display *display, hal_tdm_error *error) -{ - tdm_nexell_display *display_data = display; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL); - - return tdm_nexell_pp_create(display_data, error); -} - -hal_tdm_error -nexell_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - drmModeConnectorPtr connector = NULL; - drmModeCrtcPtr crtc = NULL; - drmModeObjectPropertiesPtr props = NULL; - int i; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); - - memset(caps, 0, sizeof(hal_tdm_caps_output)); - - display_data = output_data->display_data; - - snprintf(caps->maker, HAL_TDM_NAME_LEN, "unknown"); - snprintf(caps->model, HAL_TDM_NAME_LEN, "unknown"); - snprintf(caps->name, HAL_TDM_NAME_LEN, "unknown"); - - caps->status = output_data->status; - caps->type = output_data->connector_type; - caps->type_id = output_data->connector_type_id; - - connector = drmModeGetConnector(display_data->drm_fd, output_data->connector_id); - TDM_BACKEND_RETURN_VAL_IF_FAIL(connector, HAL_TDM_ERROR_OPERATION_FAILED); - - caps->mode_count = connector->count_modes; - caps->modes = calloc(1, sizeof(hal_tdm_output_mode) * caps->mode_count); - if (!caps->modes) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed\n"); - goto failed_get; - } - - if (caps->mode_count != output_data->count_modes) { - drmModeModeInfoPtr new_drm_modes; - hal_tdm_output_mode *new_output_modes; - - new_drm_modes = calloc(connector->count_modes, - sizeof(drmModeModeInfo)); - if (!new_drm_modes) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed drm_modes\n"); - goto failed_get; - } - new_output_modes = calloc(connector->count_modes, - sizeof(hal_tdm_output_mode)); - if (!new_output_modes) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed output_modes\n"); - free(new_drm_modes); - goto failed_get; - } - free(output_data->drm_modes); - free(output_data->output_modes); - - output_data->drm_modes = new_drm_modes; - output_data->output_modes = new_output_modes; - output_data->count_modes = caps->mode_count; - } - - for (i = 0; i < caps->mode_count; i++) { - output_data->drm_modes[i] = connector->modes[i]; - _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i], - &output_data->output_modes[i]); - caps->modes[i] = output_data->output_modes[i]; - } - - caps->mmWidth = connector->mmWidth; - caps->mmHeight = connector->mmHeight; - caps->subpixel = connector->subpixel; - - caps->min_w = display_data->mode_res->min_width; - caps->min_h = display_data->mode_res->min_height; - caps->max_w = display_data->mode_res->max_width; - caps->max_h = display_data->mode_res->max_height; - caps->preferred_align = -1; - - crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id); - if (!crtc) { - ret = HAL_TDM_ERROR_OPERATION_FAILED; - TDM_BACKEND_ERR("get crtc failed: %m\n"); - goto failed_get; - } - - props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (!props) { - ret = HAL_TDM_ERROR_OPERATION_FAILED; - TDM_BACKEND_ERR("get crtc properties failed: %m\n"); - goto failed_get; - } - - caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props); - if (!caps->props) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed\n"); - goto failed_get; - } - - caps->prop_count = 0; - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]); - if (!prop) - continue; - snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name); - caps->props[caps->prop_count].id = props->props[i]; - caps->prop_count++; - drmModeFreeProperty(prop); - } - - caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_HWC; - - drmModeFreeObjectProperties(props); - drmModeFreeCrtc(crtc); - drmModeFreeConnector(connector); - - return HAL_TDM_ERROR_NONE; -failed_get: - drmModeFreeCrtc(crtc); - drmModeFreeObjectProperties(props); - drmModeFreeConnector(connector); - free(caps->modes); - free(caps->props); - memset(caps, 0, sizeof(hal_tdm_caps_output)); - return ret; -} - -hal_tdm_error -nexell_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - int ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = output_data->display_data; - ret = drmModeObjectSetProperty(display_data->drm_fd, - output_data->crtc_id, DRM_MODE_OBJECT_CRTC, - id, value.u32); - if (ret < 0) { - TDM_BACKEND_ERR("set property failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - drmModeObjectPropertiesPtr props; - int i; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = output_data->display_data; - props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (props == NULL) { - TDM_BACKEND_ERR("get property failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == id) { - (*value).u32 = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_wait_vblank(hal_tdm_output *output, int interval, int sync, - void *user_data) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - tdm_nexell_event_data *event_data; - uint target_msc; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - event_data = calloc(1, sizeof(tdm_nexell_event_data)); - if (!event_data) { - TDM_BACKEND_ERR("alloc failed"); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - - display_data = output_data->display_data; - - ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != HAL_TDM_ERROR_NONE) - goto failed_vblank; - - target_msc += interval; - - event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_WAIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe, - &target_msc, event_data); - if (ret != HAL_TDM_ERROR_NONE) - goto failed_vblank; - - return HAL_TDM_ERROR_NONE; -failed_vblank: - free(event_data); - return ret; -} - -hal_tdm_error -nexell_output_set_vblank_handler(hal_tdm_output *output, - hal_tdm_output_vblank_handler func) -{ - tdm_nexell_output *output_data = output; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); - - output_data->vblank_func = func; - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_nexell_layer_add_atomic_properties(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request, - uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, - uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h) -{ - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. fb_id(%u)", fb_id); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. src_x(%u)", src_x); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. src_y(%u)", src_y); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. src_w(%u)", src_w); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. src_h(%u)", src_h); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h); - if (ret < 0) { - TDM_BACKEND_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_nexell_layer_make_atomic_request(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request) -{ - tdm_nexell_display *display_data = layer_data->display_data; - tdm_nexell_output *output_data = layer_data->output_data; - uint32_t fx, fy, fw, fh; - tdm_nexell_layer_info layer_info = layer_data->info; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - if (!layer_data->display_buffer_changed && !layer_data->info_changed) - return HAL_TDM_ERROR_NONE; - - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - if (!layer_data->display_buffer) { - TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off", - display_data->drm_fd, layer_data->plane_id, output_data->crtc_id); - - ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("_nexell_layer_add_atomic_properties failed."); - return ret; - } - - return HAL_TDM_ERROR_NONE; - } - - /* Source values are 16.16 fixed point */ - fx = ((unsigned int)layer_info.src_config.pos.x) << 16; - fy = ((unsigned int)layer_info.src_config.pos.y) << 16; - fw = ((unsigned int)layer_info.src_config.pos.w) << 16; - fh = ((unsigned int)layer_info.src_config.pos.h) << 16; - - TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)", - display_data->drm_fd, layer_data->plane_id, layer_data->zpos, - output_data->crtc_id, layer_data->display_buffer->fb_id, - layer_info.src_config.pos.x, layer_info.src_config.pos.y, - layer_info.src_config.pos.w, layer_info.src_config.pos.h, - layer_info.dst_pos.x, layer_info.dst_pos.y, - layer_info.dst_pos.w, layer_info.dst_pos.h); - - ret = _nexell_layer_add_atomic_properties(layer_data, request, - layer_data->display_buffer->fb_id, output_data->crtc_id, - fx, fy, fw, fh, - layer_info.dst_pos.x, layer_info.dst_pos.y, - layer_info.dst_pos.w, layer_info.dst_pos.h); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("MakeAtomicRequest failed"); - return ret; - } - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_nexell_output_atomic_commit(hal_tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_layer *layer_data = NULL; - tdm_nexell_event_data *event_data; - drmModeAtomicReqPtr request; - uint32_t flags = 0; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (!output_data->crtc_enabled || output_data->mode_changed) { - drmModeModeInfoPtr mode; - - layer_data = output_data->primary_layer; - if (!layer_data->display_buffer) { - TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting"); - return HAL_TDM_ERROR_BAD_REQUEST; - } - - mode = _tdm_nexell_display_get_mode(output_data); - if (!mode) { - TDM_BACKEND_ERR("couldn't find proper mode"); - return HAL_TDM_ERROR_BAD_REQUEST; - } - - if (drmModeSetCrtc(output_data->display_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, 0, 0, - &output_data->connector_id, 1, mode)) { - TDM_BACKEND_ERR("set crtc failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED); - - output_data->crtc_enabled = 1; - output_data->mode_changed = 0; - } - - request = drmModeAtomicAlloc(); - if (!request) { - TDM_BACKEND_ERR("drmModeAtomicAlloc failed."); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - - flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - ret = _nexell_layer_make_atomic_request(layer_data, request); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("_nexell_layer_make_atomic_request failed."); - drmModeAtomicFree(request); - return ret; - } - } - - event_data = calloc(1, sizeof(tdm_nexell_event_data)); - if (!event_data) { - TDM_BACKEND_ERR("fail to alloc event_data."); - drmModeAtomicFree(request); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - - event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - TDM_BACKEND_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u", - output_data->pipe, output_data->crtc_id, output_data->connector_id); - - if (drmModeAtomicCommit(output_data->display_data->drm_fd, request, flags, event_data) < 0) { - TDM_BACKEND_ERR("drmModeAtomicCommit failed."); - free(event_data); - drmModeAtomicFree(request); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - drmModeAtomicFree(request); - - return HAL_TDM_ERROR_NONE; -} - -static hal_tdm_error -_nexell_output_layers_commit(hal_tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - tdm_nexell_layer *layer_data = NULL; - hal_tdm_error ret; - int do_waitvblank = 1; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = output_data->display_data; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (layer_data == output_data->primary_layer) { - ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data, - &do_waitvblank); - if (ret != HAL_TDM_ERROR_NONE) - return ret; - } else { - ret = _tdm_nexell_display_commit_layer(layer_data); - if (ret != HAL_TDM_ERROR_NONE) - return ret; - } - } - - if (do_waitvblank == 1) { - tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); - uint target_msc; - - if (!event_data) { - TDM_BACKEND_ERR("alloc failed"); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - - ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != HAL_TDM_ERROR_NONE) { - free(event_data); - return ret; - } - - target_msc++; - - event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe, - &target_msc, event_data); - if (ret != HAL_TDM_ERROR_NONE) { - free(event_data); - return ret; - } - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_commit(hal_tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = output_data->display_data; - - /* check the atomic pageflip */ - if (display_data->has_atomic) { - ret = _nexell_output_atomic_commit(output, sync, user_data); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("_nexell_output_atomic_commit failed."); - return ret; - } - } else { - ret = _nexell_output_layers_commit(output, sync, user_data); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("_nexell_output_layers_commit failed."); - return ret; - } - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_set_commit_handler(hal_tdm_output *output, - hal_tdm_output_commit_handler func) -{ - tdm_nexell_output *output_data = output; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); - - output_data->commit_func = func; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - int ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (output_data->dpms_prop_id == 0) { - TDM_BACKEND_WRN("not support DPMS"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - display_data = output_data->display_data; - ret = drmModeObjectSetProperty(display_data->drm_fd, - output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR, - output_data->dpms_prop_id, dpms_value); - if (ret < 0) { - TDM_BACKEND_ERR("set dpms failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value) -{ - tdm_nexell_output *output_data = output; - tdm_nexell_display *display_data; - drmModeObjectPropertiesPtr props; - int i; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = output_data->display_data; - props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id, - DRM_MODE_OBJECT_CONNECTOR); - if (props == NULL) { - TDM_BACKEND_ERR("get property failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == output_data->dpms_prop_id) { - *dpms_value = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode) -{ - tdm_nexell_output *output_data = output; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER); - - /* create or replace the target_window when the output mode is set */ - ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret); - return ret; - } - - output_data->current_mode = mode; - output_data->mode_changed = 1; - - TDM_BACKEND_INFO("Set the output mode: %s, %d, %d, %d, %d, %d", - mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode) -{ - tdm_nexell_output *output_data = output; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER); - - *mode = output_data->current_mode; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_hwc * -nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error) -{ - tdm_nexell_hwc *hwc_data = NULL; - tdm_nexell_output *output_data = output; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - int i; - - if (!output_data) { - TDM_BACKEND_ERR("invalid params"); - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - return NULL; - } - - if (output_data->hwc_data) { - TDM_BACKEND_INFO("hwc_data already exists"); - if (error) - *error = HAL_TDM_ERROR_NONE; - return output_data->hwc_data; - } - - hwc_data = calloc(1, sizeof(tdm_nexell_hwc)); - if (!hwc_data) { - TDM_BACKEND_ERR("alloc failed"); - if (error) - *error = HAL_TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - for (i = 0; i < NUM_LAYERS; i++) { - hwc_data->ui_buffer_queue[i].tqueue = NULL; - hwc_data->ui_buffer_queue[i].ref_cnt = 0; - } - - hwc_data->output_data = output_data; - - LIST_INITHEAD(&hwc_data->hwc_window_list); - - output_data->hwc_data = hwc_data; - - ret = tdm_nexell_hwc_initailize_target_window(output_data->hwc_data); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("create target hwc window failed (%d)", ret); - free(hwc_data); - if (error) - *error = ret; - return NULL; - } - - if (error) - *error = HAL_TDM_ERROR_NONE; - - return hwc_data; -} - -hal_tdm_error -nexell_output_set_status_handler(hal_tdm_output *output, - hal_tdm_output_status_handler func, - void *user_data) -{ - tdm_nexell_output *output_data = output; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); - - output_data->status_func = func; - output_data->status_user_data = user_data; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps) -{ - tdm_nexell_display *display_data; - drmModePlanePtr plane = NULL; - drmModeObjectPropertiesPtr props = NULL; - int i, format_count = 0; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); - - memset(caps, 0, sizeof(tdm_nexell_caps_layer)); - - display_data = layer_data->display_data; - plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id); - if (!plane) { - TDM_BACKEND_ERR("get plane failed: %m"); - ret = HAL_TDM_ERROR_OPERATION_FAILED; - goto failed_get; - } - - caps->capabilities = layer_data->capabilities; - caps->zpos = layer_data->zpos; /* if VIDEO layer_data, zpos is -1 */ - - caps->format_count = plane->count_formats; - caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count); - if (!caps->formats) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed\n"); - goto failed_get; - } - - for (i = 0; i < caps->format_count; i++) { - /* TODO: kernel reports wrong formats */ - if (plane->formats[i] != DRM_FORMAT_XRGB8888 && - plane->formats[i] != DRM_FORMAT_ARGB8888 && - plane->formats[i] != DRM_FORMAT_YUV420) { - TDM_BACKEND_WRN("plane(%d) zpos(%d) %c%c%c%c skipped", - layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i])); - continue; - } - caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]); - format_count++; - } - - caps->format_count = format_count; - - props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE); - if (!props) { - ret = HAL_TDM_ERROR_OPERATION_FAILED; - TDM_BACKEND_ERR("get plane properties failed: %m\n"); - goto failed_get; - } - - caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props); - if (!caps->props) { - ret = HAL_TDM_ERROR_OUT_OF_MEMORY; - TDM_BACKEND_ERR("alloc failed\n"); - goto failed_get; - } - - caps->prop_count = 0; - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]); - if (!prop) - continue; - if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) { - drmModeFreeProperty(prop); - continue; - } - if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) { - drmModeFreeProperty(prop); - continue; - } - snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name); - caps->props[caps->prop_count].id = props->props[i]; - caps->prop_count++; - drmModeFreeProperty(prop); - } - - drmModeFreeObjectProperties(props); - drmModeFreePlane(plane); - - return HAL_TDM_ERROR_NONE; -failed_get: - drmModeFreeObjectProperties(props); - drmModeFreePlane(plane); - free(caps->formats); - free(caps->props); - memset(caps, 0, sizeof(tdm_nexell_caps_layer)); - return ret; -} - -hal_tdm_error -nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value) -{ - tdm_nexell_display *display_data; - int ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = layer_data->display_data; - ret = drmModeObjectSetProperty(display_data->drm_fd, - layer_data->plane_id, DRM_MODE_OBJECT_PLANE, - id, value.u32); - if (ret < 0) { - TDM_BACKEND_ERR("set property failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value) -{ - tdm_nexell_display *display_data; - drmModeObjectPropertiesPtr props; - int i; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = layer_data->display_data; - props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE); - if (props == NULL) { - TDM_BACKEND_ERR("get property failed: %m"); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == id) { - (*value).u32 = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); - - layer_data->info = *info; - layer_data->info_changed = 1; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); - - *info = layer_data->info; - - return HAL_TDM_ERROR_NONE; -} - -static tdm_nexell_display_buffer * -_tdm_nexell_display_find_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer) -{ - tdm_nexell_display_buffer *display_buffer = NULL; - - LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) { - if (display_buffer->buffer == buffer) - return display_buffer; - } - - return NULL; -} - -static void -_tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data) -{ - tdm_nexell_display *display_data; - tdm_nexell_display_buffer *display_buffer; - tdm_nexell_layer *layer_data = NULL; - tdm_nexell_output *output_data = NULL; - char buf[256] = {0,}; - char *ret_tmp; - - if (!user_data) { - TDM_BACKEND_ERR("no user_data"); - return; - } - if (!buffer) { - TDM_BACKEND_ERR("no buffer"); - return; - } - - display_data = (tdm_nexell_display *) user_data; - - display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer); - if (!display_buffer) { - TDM_BACKEND_ERR("no display_buffer"); - return; - } - - LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (display_buffer == layer_data->display_buffer) - layer_data->display_buffer = NULL; - } - } - - if (display_buffer->fb_id > 0) { - if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) { - ret_tmp = strerror_r(errno, buf, sizeof(buf)); - TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp); - } - } - - TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer); - - LIST_DEL(&display_buffer->link); - free(display_buffer); -} - -static tdm_nexell_display_buffer * -_tdm_nexell_display_create_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer, hal_tdm_error *err) -{ - tdm_nexell_display_buffer *display_buffer = NULL; - int count, i, ret; - - display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer)); - if (!display_buffer) { - TDM_BACKEND_ERR("alloc failed"); - if (err) - *err = HAL_TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - display_buffer->buffer = buffer; - - ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); - if (ret == 0) { - TDM_BACKEND_ERR("add destroy handler fail"); - free(display_buffer); - if (err) - *err = HAL_TDM_ERROR_OPERATION_FAILED; - return NULL; - } - - display_buffer->width = tbm_surface_get_width(buffer); - display_buffer->height = tbm_surface_get_height(buffer); - display_buffer->format = tbm_surface_get_format(buffer); - display_buffer->count = tbm_surface_internal_get_num_bos(buffer); - count = tbm_surface_internal_get_num_planes(display_buffer->format); - TDM_BACKEND_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d", - buffer, display_buffer->width, display_buffer->height, - FOURCC_STR(display_buffer->format), display_buffer->count, count); - - for (i = 0; i < count; i++) { - int bo_idx = 0; - tbm_bo bo = NULL; - - bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i); - bo = tbm_surface_internal_get_bo(buffer, bo_idx); - display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; - - tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size, - &display_buffer->offsets[i], - &display_buffer->pitches[i]); - TDM_BACKEND_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)", - i, display_buffer->size, display_buffer->offsets[i], - display_buffer->pitches[i], bo_idx, display_buffer->handles[i]); - } - - ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height, - display_buffer->format, display_buffer->handles, display_buffer->pitches, - display_buffer->offsets, &display_buffer->fb_id, 0); - if (ret < 0) { - TDM_BACKEND_ERR("add fb failed: %m"); - free(display_buffer); - if (err) - *err = HAL_TDM_ERROR_OPERATION_FAILED; - tbm_surface_internal_remove_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); - return NULL; - } - - TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd, - display_buffer->fb_id); - - if (IS_RGB(display_buffer->format)) - display_buffer->width = display_buffer->pitches[0] >> 2; - else - display_buffer->width = display_buffer->pitches[0]; - - LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list); - - if (err) - *err = HAL_TDM_ERROR_NONE; - - return display_buffer; -} - -void -tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data) -{ - tdm_nexell_display_buffer *b = NULL, *bb = NULL; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) { - tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); - _tdm_nexell_display_cb_destroy_buffer(b->buffer, display_data); - } -} - -hal_tdm_error -nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer) -{ - tdm_nexell_display *display_data; - tdm_nexell_display_buffer *display_buffer; - hal_tdm_error err = HAL_TDM_ERROR_NONE; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = layer_data->display_data; - display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer); - if (!display_buffer) { - display_buffer = _tdm_nexell_display_create_buffer(display_data, buffer, &err); - TDM_BACKEND_RETURN_VAL_IF_FAIL(display_buffer != NULL, err); - } - - if (layer_data->display_buffer != display_buffer) { - if (layer_data->display_buffer) - tbm_surface_internal_unref(layer_data->display_buffer->buffer); - - layer_data->display_buffer = display_buffer; - tbm_surface_internal_ref(layer_data->display_buffer->buffer); - layer_data->display_buffer_changed = 1; - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_layer_unset_buffer(tdm_nexell_layer *layer_data) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (!(layer_data->capabilities & TDM_NEXELL_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) { - tbm_surface_internal_unref(layer_data->display_buffer->buffer); - layer_data->display_buffer = NULL; - } - - layer_data->display_buffer_changed = 1; - - return HAL_TDM_ERROR_NONE; -} - -tdm_nexell_layer * -nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zpos) -{ - tdm_nexell_layer *l = NULL; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, NULL); - - LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) { - if (l->zpos == layer_zpos) - return l; - } - - return NULL; -} diff --git a/src/libhal-backend-tdm-nexell/tdm_nexell_format.c b/src/libhal-backend-tdm-nexell/tdm_nexell_format.c deleted file mode 100644 index ffe5ef2..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_nexell_format.c +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -typedef struct { - tbm_format tbm_format; - uint32_t drm_format; -} tbm_drm_format_data; - -static const tbm_drm_format_data formats[] = { - {TBM_FORMAT_C8, DRM_FORMAT_C8}, - {TBM_FORMAT_RGB332, DRM_FORMAT_RGB332}, - {TBM_FORMAT_BGR233, DRM_FORMAT_BGR233}, - {TBM_FORMAT_XRGB4444, DRM_FORMAT_XRGB4444}, - {TBM_FORMAT_XBGR4444, DRM_FORMAT_XBGR4444}, - {TBM_FORMAT_RGBX4444, DRM_FORMAT_RGBX4444}, - {TBM_FORMAT_BGRX4444, DRM_FORMAT_BGRX4444}, - {TBM_FORMAT_ARGB4444, DRM_FORMAT_ARGB4444}, - {TBM_FORMAT_ABGR4444, DRM_FORMAT_ABGR4444}, - {TBM_FORMAT_RGBA4444, DRM_FORMAT_RGBA4444}, - {TBM_FORMAT_BGRA4444, DRM_FORMAT_BGRA4444}, - {TBM_FORMAT_XRGB1555, DRM_FORMAT_XRGB1555}, - {TBM_FORMAT_XBGR1555, DRM_FORMAT_XBGR1555}, - {TBM_FORMAT_RGBX5551, DRM_FORMAT_RGBX5551}, - {TBM_FORMAT_BGRX5551, DRM_FORMAT_BGRX5551}, - {TBM_FORMAT_ARGB1555, DRM_FORMAT_ARGB1555}, - {TBM_FORMAT_ABGR1555, DRM_FORMAT_ABGR1555}, - {TBM_FORMAT_RGBA5551, DRM_FORMAT_RGBA5551}, - {TBM_FORMAT_BGRA5551, DRM_FORMAT_BGRA5551}, - {TBM_FORMAT_RGB565, DRM_FORMAT_RGB565}, - {TBM_FORMAT_BGR565, DRM_FORMAT_BGR565}, - {TBM_FORMAT_RGB888, DRM_FORMAT_RGB888}, - {TBM_FORMAT_BGR888, DRM_FORMAT_BGR888}, - {TBM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888}, - {TBM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888}, - {TBM_FORMAT_RGBX8888, DRM_FORMAT_RGBX8888}, - {TBM_FORMAT_BGRX8888, DRM_FORMAT_BGRX8888}, - {TBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888}, - {TBM_FORMAT_ABGR8888, DRM_FORMAT_ABGR8888}, - {TBM_FORMAT_RGBA8888, DRM_FORMAT_RGBA8888}, - {TBM_FORMAT_BGRA8888, DRM_FORMAT_BGRA8888}, - {TBM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010}, - {TBM_FORMAT_XBGR2101010, DRM_FORMAT_XBGR2101010}, - {TBM_FORMAT_RGBX1010102, DRM_FORMAT_RGBX1010102}, - {TBM_FORMAT_BGRX1010102, DRM_FORMAT_BGRX1010102}, - {TBM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB2101010}, - {TBM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR2101010}, - {TBM_FORMAT_RGBA1010102, DRM_FORMAT_RGBA1010102}, - {TBM_FORMAT_BGRA1010102, DRM_FORMAT_BGRA1010102}, - {TBM_FORMAT_YUYV, DRM_FORMAT_YUYV}, - {TBM_FORMAT_YVYU, DRM_FORMAT_YVYU}, - {TBM_FORMAT_UYVY, DRM_FORMAT_UYVY}, - {TBM_FORMAT_VYUY, DRM_FORMAT_VYUY}, - {TBM_FORMAT_AYUV, DRM_FORMAT_AYUV}, - {TBM_FORMAT_NV12, DRM_FORMAT_NV12}, - {TBM_FORMAT_NV21, DRM_FORMAT_NV21}, - {TBM_FORMAT_NV16, DRM_FORMAT_NV16}, - {TBM_FORMAT_NV61, DRM_FORMAT_NV61}, - {TBM_FORMAT_YUV410, DRM_FORMAT_YUV410}, - {TBM_FORMAT_YVU410, DRM_FORMAT_YVU410}, - {TBM_FORMAT_YUV411, DRM_FORMAT_YUV411}, - {TBM_FORMAT_YVU411, DRM_FORMAT_YVU411}, - {TBM_FORMAT_YUV420, DRM_FORMAT_YUV420}, - {TBM_FORMAT_YVU420, DRM_FORMAT_YVU420}, - {TBM_FORMAT_YUV422, DRM_FORMAT_YUV422}, - {TBM_FORMAT_YVU422, DRM_FORMAT_YVU422}, - {TBM_FORMAT_YUV444, DRM_FORMAT_YUV444}, - {TBM_FORMAT_YVU444, DRM_FORMAT_YVU444}, -}; - -#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) - -uint32_t -tdm_nexell_format_to_drm_format(tbm_format format) -{ - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (formats[i].tbm_format == format) - return formats[i].drm_format; - - TDM_BACKEND_ERR("tbm format '%c%c%c%c' not found", FOURCC_STR(format)); - - return 0; -} - -tbm_format -tdm_nexell_format_to_tbm_format(uint32_t format) -{ - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (formats[i].drm_format == format) - return formats[i].tbm_format; - - TDM_BACKEND_ERR("drm format '%c%c%c%c' not found", FOURCC_STR(format)); - - return 0; -} diff --git a/src/libhal-backend-tdm-nexell/tdm_nexell_hwc.c b/src/libhal-backend-tdm-nexell/tdm_nexell_hwc.c deleted file mode 100644 index bec0ea3..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_nexell_hwc.c +++ /dev/null @@ -1,980 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -#define MIN_WIDTH 32 - -tbm_format hwc_window_video_formats[] = { - TBM_FORMAT_NV12, - TBM_FORMAT_YUV420 -}; - -const char * -_comp_to_str(hal_tdm_hwc_window_composition composition_type) -{ - if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) - return "CLIENT"; - else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_DEVICE) - return "DEVICE"; - else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR) - return "CURSOR"; - else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_VIDEO) - return "VIDEO"; - else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) - return "SKIP"; - - return "unknown"; -} - -static int -_nexell_hwc_cursor_buffer_image_render(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - tbm_surface_info_s tsurface_info; - tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE; - void *src_ptr = NULL, *dst_ptr = NULL; - int src_stride, transform, img_w, img_h; - pixman_image_t *src_img = NULL, *dst_img = NULL; - pixman_transform_t t; - struct pixman_f_transform ft; - int c = 0, s = 0, tx = 0, ty = 0; - int i; - - ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info); - if (ret != TBM_SURFACE_ERROR_NONE) { - TDM_BACKEND_ERR("Failed to map tsurface\n"); - return 0; - } - - src_ptr = hwc_window_data->cursor_img.ptr; - src_stride = hwc_window_data->cursor_img.stride; - img_w = hwc_window_data->cursor_img.width; - img_h = hwc_window_data->cursor_img.height; - transform = hwc_window_data->info.transform; - - dst_ptr = tsurface_info.planes[0].ptr; - - memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height); - - if (transform) { - src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride); - if (!src_img) { - TDM_BACKEND_ERR("Failed to create src pixman\n"); - return 0; - } - - dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info.width, tsurface_info.height, - (uint32_t*)dst_ptr, tsurface_info.planes[0].stride); - if (!dst_img) { - TDM_BACKEND_ERR("Failed to create dst pixman\n"); - pixman_image_unref(src_img); - return 0; - } - - pixman_f_transform_init_identity(&ft); - - if (transform >= HAL_TDM_TRANSFORM_FLIPPED) { - pixman_f_transform_scale(&ft, NULL, -1, 1); - pixman_f_transform_translate(&ft, NULL, tsurface_info.width, 0); - } - - switch (transform) { - case HAL_TDM_TRANSFORM_90: - case HAL_TDM_TRANSFORM_FLIPPED_90: - c = 0, s = 1, ty = -tsurface_info.height; - break; - case HAL_TDM_TRANSFORM_180: - case HAL_TDM_TRANSFORM_FLIPPED_180: - c = -1, s = 0, tx = -tsurface_info.width, ty = -tsurface_info.height; - break; - case HAL_TDM_TRANSFORM_270: - case HAL_TDM_TRANSFORM_FLIPPED_270: - c = 0, s = -1, tx = -tsurface_info.width; - break; - default: - break; - } - - pixman_f_transform_translate(&ft, NULL, tx, ty); - pixman_f_transform_rotate(&ft, NULL, c, s); - pixman_transform_from_pixman_f_transform(&t, &ft); - pixman_image_set_transform(src_img, &t); - pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, - tsurface_info.width, tsurface_info.height); - pixman_image_unref(src_img); - pixman_image_unref(dst_img); - } - else { - for (i = 0 ; i < img_h ; i++) { - memcpy(dst_ptr, src_ptr, src_stride); - dst_ptr += tsurface_info.planes[0].stride; - src_ptr += src_stride; - } - } - - tbm_surface_unmap(hwc_data->cursor_tsurface); - - return 1; -} - -static int -_nexell_hwc_cursor_window_surface_clear(tdm_nexell_hwc_window_data *hwc_window_data) -{ - hwc_window_data->surface = NULL; - hwc_window_data->cursor_img_surface = 0; - - hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width; - hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height; - hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width; - hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height; - - return 1; -} - -static void -_nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc *hwc_data) -{ - if (hwc_data->cursor_tsurface) { - tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - } - - if (hwc_data->cursor_tqueue) { - tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->cursor_tqueue); - hwc_data->cursor_tqueue = NULL; - } -} - -static void -_nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - int x, y, width, height; - - width = tbm_surface_get_width(hwc_data->cursor_tsurface); - height = tbm_surface_get_height(hwc_data->cursor_tsurface); - - hwc_window_data->info.src_config.pos.w = width; - hwc_window_data->info.src_config.pos.h = height; - hwc_window_data->info.dst_pos.w = width; - hwc_window_data->info.dst_pos.h = height; - - /* dst pos of cursor is possible set by negative value - * this is temporary code. - */ - x = hwc_window_data->info.dst_pos.x; - y = hwc_window_data->info.dst_pos.y; - - if (x < 0) hwc_window_data->info.dst_pos.x = 0; - if (y < 0) hwc_window_data->info.dst_pos.y = 0; -} - -static int -_nexell_hwc_cursor_buffer_set(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - tbm_surface_h cursor_tsurface = NULL; - tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE; - int img_w, img_h; - int tqueue_w, tqueue_h; - hal_tdm_error error; - - if (hwc_window_data->cursor_img_refresh || !hwc_window_data->surface) { - switch (hwc_window_data->info.transform) { - case HAL_TDM_TRANSFORM_90: - case HAL_TDM_TRANSFORM_FLIPPED_90: - case HAL_TDM_TRANSFORM_270: - case HAL_TDM_TRANSFORM_FLIPPED_270: - img_w = hwc_window_data->cursor_img.height; - img_h = hwc_window_data->cursor_img.width; - break; - default: - img_w = hwc_window_data->cursor_img.width; - img_h = hwc_window_data->cursor_img.height; - break; - } - - if (!hwc_data->cursor_tqueue) { - hwc_data->cursor_tqueue = tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hwc_window_data, &error); - if (error != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("Failed to create cursor buffer queue error:%d", error); - return 0; - } - } else { - tqueue_w = tbm_surface_queue_get_width(hwc_data->cursor_tqueue); - tqueue_h = tbm_surface_queue_get_height(hwc_data->cursor_tqueue); - if ((img_w != tqueue_w) || (img_h != tqueue_h)) - tbm_surface_queue_reset(hwc_data->cursor_tqueue, img_w, img_h, TBM_FORMAT_ARGB8888); - } - - if (hwc_data->cursor_tsurface) { - tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - } - - if (!tbm_surface_queue_can_dequeue(hwc_data->cursor_tqueue, 0)) { - TDM_BACKEND_ERR("Can't dequeue cursor tqueue"); - return 0; - } - - tsq_error = tbm_surface_queue_dequeue(hwc_data->cursor_tqueue, &cursor_tsurface); - if (tsq_error != TBM_SURFACE_QUEUE_ERROR_NONE) { - TDM_BACKEND_ERR("Failed to dequeue cursor tqueue error:%d", tsq_error); - return 0; - } - - hwc_data->cursor_tsurface = cursor_tsurface; - - _nexell_hwc_cursor_buffer_image_render(hwc_data, hwc_window_data); - - hwc_window_data->surface = cursor_tsurface; - hwc_window_data->cursor_img_surface = 1; - hwc_window_data->cursor_img_refresh = 0; - } - - _nexell_hwc_cursor_adjust_pos(hwc_data, hwc_window_data); - - return 1; -} - -static void -_print_validate_result(tdm_nexell_hwc *hwc_data, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int i; - int lzpos_queue; - - for (i = 0; i < num_wnds; i++) { - hwc_window_data = composited_wnds[i]; - lzpos_queue = hwc_window_data->lzpos_queue; - switch (hwc_window_data->validated_type) { - case HAL_TDM_HWC_WIN_COMPOSITION_CLIENT: - TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data, - _comp_to_str(hwc_window_data->client_type), - _comp_to_str(hwc_window_data->validated_type), - hwc_data->target_hwc_window->lzpos, - lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, - lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, - hwc_window_data->name ? hwc_window_data->name : "NONE"); - break; - case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: - case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: - case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: - case HAL_TDM_HWC_WIN_COMPOSITION_NONE: - TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s}", hwc_window_data, - _comp_to_str(hwc_window_data->client_type), - _comp_to_str(hwc_window_data->validated_type), - hwc_window_data->lzpos, - lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, - lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, - hwc_window_data->name ? hwc_window_data->name : "NONE"); - break; - default: - break; - } - } -} - -static int -_nexell_hwc_window_has_reserved_buffer(tdm_nexell_hwc_window_data *hwc_window_data) { - tbm_bo bo = NULL; - int flags = 0; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, 0); - - bo = tbm_surface_internal_get_bo(hwc_window_data->surface, 0); - TDM_BACKEND_RETURN_VAL_IF_FAIL(bo != NULL, 0); - - flags = tbm_bo_get_flags(bo); - - return flags & TBM_BO_SCANOUT; -} - -static int -_nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data, int bottom) -{ - if (!hwc_window_data->surface) - return 0; - - if (hwc_window_data->info.transform != HAL_TDM_TRANSFORM_NORMAL) - return 0; - - if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w) - return 0; - - if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h) - return 0; - - if (!IS_RGB(hwc_window_data->info.src_config.format)) - return 0; - - if ((hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || - (hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) - return 0; - - if (bottom) { - if ((hwc_window_data->info.dst_pos.w != hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || - (hwc_window_data->info.dst_pos.h != hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) - return 0; - } - - return 1; -} - -tbm_surface_queue_h -tdm_nexell_hwc_window_create_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - tbm_format format; - - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); - - hwc_window_data = hwc_window; - - width = hwc_window_data->info.src_config.pos.w; - height = hwc_window_data->info.src_config.pos.h; - format = hwc_window_data->info.src_config.format; - - tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); - if (error) - *error = HAL_TDM_ERROR_OPERATION_FAILED; - TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); - - if (error) - *error = HAL_TDM_ERROR_NONE; - - return tqueue; -} - -tbm_surface_queue_h -tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); - - hwc_window_data = hwc_window; - - switch (hwc_window_data->info.transform) { - case HAL_TDM_TRANSFORM_90: - case HAL_TDM_TRANSFORM_FLIPPED_90: - case HAL_TDM_TRANSFORM_270: - case HAL_TDM_TRANSFORM_FLIPPED_270: - width = hwc_window_data->cursor_img.height; - height = hwc_window_data->cursor_img.width; - break; - default: - width = hwc_window_data->cursor_img.width; - height = hwc_window_data->cursor_img.height; - break; - } - - tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT); - if (error) - *error = HAL_TDM_ERROR_OPERATION_FAILED; - TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); - - tbm_surface_queue_set_modes(tqueue, TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE); - - if (error) - *error = HAL_TDM_ERROR_NONE; - - return tqueue; -} - -void -tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue) -{ - tbm_surface_queue_destroy(tqueue); -} - -static hal_tdm_error -_nexell_hwc_layer_attach_window(tdm_nexell_layer *layer_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_OPERATION_FAILED); - - if (hwc_window_data == NULL || hwc_window_data->surface == NULL) { - if (layer_data->display_buffer) - ret = nexell_layer_unset_buffer(layer_data); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - } else { - ret = nexell_layer_set_info((tdm_nexell_layer *)layer_data, (tdm_nexell_layer_info *)&(hwc_window_data->info)); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - ret = nexell_layer_set_buffer(layer_data, hwc_window_data->surface); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - } - - return ret; -} - -static hal_tdm_error -_nexell_hwc_prepare_commit(tdm_nexell_hwc *hwc_data) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tdm_nexell_layer *layer_data = NULL; - int use_layers_zpos[NUM_LAYERS] = {0,}; - int lzpos = 0; - int cursor_enabled = 0; - - /* set target hwc window to the layer_data */ - if (hwc_data->need_target_window) { - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos); - _nexell_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window); - use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1; - } - - /* set the hwc_windows to the layers */ - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE || - hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) { - if (hwc_window_data->cursor_img_surface) - _nexell_hwc_cursor_window_surface_clear(hwc_window_data); - - continue; - } - - if (hwc_window_data == hwc_data->target_hwc_window) - continue; - - /* set the cursor buffer HERE if it needs */ - if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR) { - _nexell_hwc_cursor_buffer_set(hwc_data, hwc_window_data); - cursor_enabled = 1; - } - - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos); - _nexell_hwc_layer_attach_window(layer_data, hwc_window_data); - use_layers_zpos[hwc_window_data->lzpos] = 1; - } - - /* unset the unused layers */ - for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) { - if (use_layers_zpos[lzpos]) - continue; - - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, lzpos); - if (!layer_data) - continue; - - _nexell_hwc_layer_attach_window(layer_data, NULL); - } - - if (!cursor_enabled) - _nexell_hwc_cursor_buffer_unset(hwc_data); - - /* for debug */ - for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) { - if (use_layers_zpos[lzpos]) - TDM_BACKEND_DBG(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET"); - } - - return HAL_TDM_ERROR_NONE; -} - -/* assign the validated_type to the composited_wnds - * assign the layer_zpos to the composited_wnds - */ -static void -_nexell_hwc_apply_policy(tdm_nexell_hwc *hwc_data , hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tdm_nexell_hwc_window_data **composited_list = NULL; - int client_count = 0; - int device_count = 0; - int video_count = 0; - int cursor_count = 0; - int ui_lzpos_top = ZPOS_2; - int ui_lzpos_bottom = ZPOS_1; - int num_ui_layers = NUM_UI_LAYERS; - int set_clients_below = 0; - int i = 0; - - composited_list = (tdm_nexell_hwc_window_data **)composited_wnds; - - /* initialize the need_target_window */ - hwc_data->need_target_window = 0; - - /* initialize the validated_types and constraints */ - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - hwc_window_data->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE; - hwc_window_data->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_NONE; - hwc_window_data->lzpos = -1; - hwc_window_data->lzpos_queue = -1; - } - - /* use the target_window to commit when there is no window. */ - if (num_wnds == 0) { - hwc_data->need_target_window = 1; - hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; - hwc_data->target_hwc_window->lzpos_queue = ui_lzpos_bottom; - return; - } - - /* 1. first check validate_type without target_window */ - for (i = 0; i < num_wnds; i++) { - switch (composited_list[i]->client_type) { - case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: - composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_VIDEO; - video_count++; - continue; - case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: - if (set_clients_below) break; - if (num_ui_layers <= 0) break; - - composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CURSOR; - cursor_count++; - num_ui_layers--; - continue; - case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: - if (set_clients_below) break; - if (num_ui_layers <= 0) break; - - if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i], (i == num_wnds - 1))) - break; - - if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i])) { - composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; - break; - } - - composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_DEVICE; - composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; - device_count++; - num_ui_layers--; - continue; - default: - break; - } - - composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT; - client_count++; - set_clients_below = 1; - } - - /* 2. check need target window and set ui_lzpos top and bottom */ - num_ui_layers = NUM_UI_LAYERS; - if (client_count > 0) { - hwc_data->need_target_window = 1; - hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; - ui_lzpos_bottom++; - num_ui_layers--; - } - - if (num_ui_layers > (device_count + cursor_count)) - ui_lzpos_top = ui_lzpos_bottom + device_count + cursor_count - 1; - - /* 3. set lzpos and modify validate_type with target_window */ - for (i = 0; i < num_wnds; i++) { - switch (composited_list[i]->validated_type) { - case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: - composited_list[i]->lzpos = ZPOS_VIDEO1; - continue; - case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: - case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: - if (num_ui_layers <= 0) break; - - composited_list[i]->lzpos = ui_lzpos_top; - composited_list[i]->lzpos_queue = ui_lzpos_top; - ui_lzpos_top--; - num_ui_layers--; - continue; - default: - break; - } - - composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT; - - if (composited_list[i]->constraints == HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE) { - if (i == num_wnds - 1) //set target window queue zpos - composited_list[i]->lzpos_queue = ui_lzpos_top; - else if(num_ui_layers > 0) - composited_list[i]->lzpos_queue = ui_lzpos_top + 1; - else - composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE; - } - } -} - -static int -_nexell_hwc_get_changed_number(tdm_nexell_hwc *hwc_data) -{ - int num = 0; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) - continue; - - if (hwc_window_data->client_type != hwc_window_data->validated_type) - num++; - } - - return num; -} - -hal_tdm_hwc_window * -_nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_hwc_window_info *info, hal_tdm_error *error) -{ - tdm_nexell_hwc *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - if (error) - *error = HAL_TDM_ERROR_NONE; - - if (!hwc_data) { - TDM_BACKEND_ERR("invalid params"); - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - return NULL; - } - - hwc_window_data = calloc(1, sizeof(tdm_nexell_hwc_window_data)); - if (!hwc_window_data) { - TDM_BACKEND_ERR("alloc failed"); - if (error) - *error = HAL_TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - hwc_window_data->hwc_data = hwc_data; - - if (info) - memcpy(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info)); - - LIST_INITHEAD(&hwc_window_data->link); - - return hwc_window_data; -} - -hal_tdm_hwc_window * -nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error) -{ - tdm_nexell_hwc *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, NULL); - - hwc_window_data = _nexell_hwc_create_window(hwc_data, NULL, error); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data, NULL); - - LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list); - - TDM_BACKEND_DBG("hwc_window(%p) create", hwc_window_data); - if (error) - *error = HAL_TDM_ERROR_NONE; - - return hwc_window_data; -} - -hal_tdm_error -nexell_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(formats != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - // TODO: fix these formats. - *formats = hwc_window_video_formats; - *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities) -{ - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(capabilities != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - *capabilities |= HAL_TDM_HWC_CAPABILITY_VIDEO_SCALE; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count) -{ - tdm_nexell_hwc *hwc_data = hwc; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(props != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - *props = NULL; - *count = 0; - - return HAL_TDM_ERROR_NONE; -} - -tbm_surface_queue_h -nexell_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error) -{ - tdm_nexell_hwc *hwc_data = hwc; - tbm_surface_queue_h tqueue = NULL; - - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); - - if (hwc_data->target_hwc_window == NULL) { - if (error) - *error = HAL_TDM_ERROR_OPERATION_FAILED; - return NULL; - } - - tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_data->target_hwc_window, error); - TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue, NULL); - - hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue; - hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1; - - if (error) - *error = HAL_TDM_ERROR_NONE; - - return tqueue; -} - -hal_tdm_error -nexell_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage) -{ - tdm_nexell_hwc *hwc_data = hwc; - hal_tdm_error err; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, HAL_TDM_ERROR_OPERATION_FAILED); - - err = nexell_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer); - TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err); - - err = nexell_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage); - TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) -{ - tdm_nexell_hwc *hwc_data = hwc; - tdm_nexell_output *output_data; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(num_types != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - output_data = hwc_data->output_data; - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - TDM_BACKEND_DBG(" ==============Validate================================="); - - /* adapt policy */ - _nexell_hwc_apply_policy(hwc_data, composited_wnds, num_wnds); - - *num_types = _nexell_hwc_get_changed_number(hwc_data); - - _print_validate_result(hwc_data, composited_wnds, num_wnds); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements, - hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types) -{ - tdm_nexell_hwc *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int num = 0; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(num_elements != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - if ((hwc_wnds == NULL) || (composition_types == NULL)) { - *num_elements = _nexell_hwc_get_changed_number(hwc_data); - return HAL_TDM_ERROR_NONE; - } - - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) - continue; - - if (num >= *num_elements) - break; - - if (hwc_window_data->client_type != hwc_window_data->validated_type) { - composition_types[num] = hwc_window_data->validated_type; - hwc_wnds[num] = hwc_window_data; - num++; - } - } - - /* set real num of changed composition types */ - *num_elements = num; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_accept_validation(hal_tdm_hwc *hwc) -{ - tdm_nexell_hwc *hwc_data = hwc; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - TDM_BACKEND_DBG(" ==============Accept Changes Done================================="); - - ret = _nexell_hwc_prepare_commit(hwc_data); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data) -{ - tdm_nexell_hwc *hwc_data = hwc; - tdm_nexell_output *output_data = NULL; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - output_data = hwc_data->output_data; - TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - TDM_BACKEND_DBG(" ==============COMMIT================================="); - - ret = nexell_output_commit(output_data, sync, user_data); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func) -{ - tdm_nexell_hwc *hwc_data = hwc; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); - - hwc_data->commit_func = func; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_target_window_set_info(tdm_nexell_hwc *hwc_data, int width, int height) -{ - hal_tdm_hwc_window_info info = {0}; - tdm_nexell_hwc_window_data *target_hwc_window; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, HAL_TDM_ERROR_INVALID_PARAMETER); - - target_hwc_window = hwc_data->target_hwc_window; - - info.dst_pos.x = 0; - info.dst_pos.y = 0; - info.dst_pos.w = width; - info.dst_pos.h = height; - - info.src_config.pos.x = 0; - info.src_config.pos.y = 0; - info.src_config.pos.w = width; - info.src_config.pos.h = height; - - info.src_config.size.h = width; - info.src_config.size.v = height; - info.src_config.format = TBM_FORMAT_ARGB8888; - - ret = nexell_hwc_window_set_info(target_hwc_window, &info); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -tdm_nexell_hwc_initailize_target_window(tdm_nexell_hwc *hwc_data) -{ - hal_tdm_hwc_window_info info = {0}; - hal_tdm_error ret = HAL_TDM_ERROR_NONE; - tdm_nexell_hwc_window_data *target_hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - info.dst_pos.x = 0; - info.dst_pos.y = 0; - info.dst_pos.w = 2; - info.dst_pos.h = 1; - - info.src_config.pos.x = 0; - info.src_config.pos.y = 0; - info.src_config.pos.w = 2; - info.src_config.pos.h = 1; - - info.src_config.size.h = 2; - info.src_config.size.v = 1; - info.src_config.format = TBM_FORMAT_ARGB8888; - - target_hwc_window = _nexell_hwc_create_window(hwc_data, &info, &ret); - if (ret != HAL_TDM_ERROR_NONE) { - TDM_BACKEND_ERR("create target hwc window failed (%d)", ret); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - if (hwc_data->target_hwc_window) - nexell_hwc_window_destroy(hwc_data->target_hwc_window); - - hwc_data->target_hwc_window = target_hwc_window; - hwc_data->need_set_crtc = 1; - - return HAL_TDM_ERROR_NONE; -} diff --git a/src/libhal-backend-tdm-nexell/tdm_nexell_hwc_window.c b/src/libhal-backend-tdm-nexell/tdm_nexell_hwc_window.c deleted file mode 100644 index 8e9c34c..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_nexell_hwc_window.c +++ /dev/null @@ -1,270 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -tbm_surface_queue_h -nexell_hwc_window_acquire_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) -{ - tdm_nexell_hwc *hwc_data = NULL; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - - if (error) - *error = HAL_TDM_ERROR_INVALID_PARAMETER; - - hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, NULL); - - hwc_data = hwc_window_data->hwc_data; - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); - - if (error) - *error = HAL_TDM_ERROR_NONE; - - if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue >= NUM_LAYERS)) { - TDM_BACKEND_ERR("invliad hwc_window:%p lzpos_queue:%d", hwc_window_data, hwc_window_data->lzpos); - if (error) - *error = HAL_TDM_ERROR_OPERATION_FAILED; - - return NULL; - } - - if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue) { - tqueue = hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue; - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; - } else { - tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window, error); - if (!tqueue) { - TDM_BACKEND_ERR("fail to create buffer queue"); - return NULL; - } - - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue = tqueue; - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; - } - - // target buffer queue can't be reset - if (hwc_window_data->lzpos_queue != ZPOS_1) { - width = tbm_surface_queue_get_width(tqueue); - height = tbm_surface_queue_get_height(tqueue); - - if ((hwc_window_data->info.src_config.pos.w != width) || - (hwc_window_data->info.src_config.pos.h != height)) - { - tbm_surface_queue_reset(tqueue, - hwc_window_data->info.src_config.pos.w, - hwc_window_data->info.src_config.pos.h, - hwc_window_data->info.src_config.format); - } - } - - return tqueue; -} - -void -nexell_hwc_window_release_buffer_queue(hal_tdm_hwc_window *hwc_window, tbm_surface_queue_h queue) -{ - tdm_nexell_hwc *hwc_data = NULL; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int i; - - hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; - TDM_BACKEND_RETURN_IF_FAIL(hwc_window_data != NULL); - - hwc_data = hwc_window_data->hwc_data; - TDM_BACKEND_RETURN_IF_FAIL(hwc_data != NULL); - - for (i = 0; i < NUM_LAYERS; i++) { - if (hwc_data->ui_buffer_queue[i].tqueue == queue) { - if (hwc_data->ui_buffer_queue[i].ref_cnt > 0) - hwc_data->ui_buffer_queue[i].ref_cnt--; - - if ((i != ZPOS_1) && (hwc_data->ui_buffer_queue[i].ref_cnt == 0)) { - tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->ui_buffer_queue[i].tqueue); - hwc_data->ui_buffer_queue[i].tqueue = NULL; - } - - break; - } - } -} - -void -nexell_hwc_window_destroy(hal_tdm_hwc_window *hwc_window) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_IF_FAIL(hwc_window_data != NULL); - - LIST_DEL(&hwc_window_data->link); - - free(hwc_window_data); -} - -hal_tdm_error -nexell_hwc_window_set_composition_type(hal_tdm_hwc_window *hwc_window, - hal_tdm_hwc_window_composition comp_type) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - tdm_nexell_hwc *hwc_data = hwc_window_data->hwc_data; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - /* change the client_type when it is different from one which has before */ - if (hwc_window_data->client_type == comp_type) - return HAL_TDM_ERROR_NONE; - - hwc_window_data->client_type = comp_type; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_buffer_damage(hal_tdm_hwc_window *hwc_window, hal_tdm_region damage) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - //TODO:: - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_info(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_info *info) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - tdm_nexell_hwc *hwc_data; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - hwc_data = hwc_window_data->hwc_data; - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(info != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (!memcmp(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info))) - return HAL_TDM_ERROR_NONE; - - hwc_window_data->info = *info; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_buffer(hal_tdm_hwc_window *hwc_window, tbm_surface_h surface) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - hal_tdm_error err = HAL_TDM_ERROR_OPERATION_FAILED; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err); - - if (hwc_window_data->surface == surface) - return HAL_TDM_ERROR_NONE; - - hwc_window_data->surface = surface; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value value) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - //TODO: - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_get_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value *value) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - //TODO: - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_get_constraints(hal_tdm_hwc_window *hwc_window, int *constraints) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(constraints != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - *constraints = hwc_window_data->constraints; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_name(hal_tdm_hwc_window *hwc_window, const char *name) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - if (!name) - return HAL_TDM_ERROR_NONE; - - snprintf(hwc_window_data->name, HAL_TDM_NAME_LEN, "%s", name); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_hwc_window_set_cursor_image(hal_tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); - - hwc_window_data->cursor_img.width = width; - hwc_window_data->cursor_img.height = height; - hwc_window_data->cursor_img.stride = stride; - hwc_window_data->cursor_img.ptr = ptr; - - hwc_window_data->cursor_img_refresh = 1; - - return HAL_TDM_ERROR_NONE; -} diff --git a/src/libhal-backend-tdm-nexell/tdm_nexell_pp.c b/src/libhal-backend-tdm-nexell/tdm_nexell_pp.c deleted file mode 100644 index 53f3a8f..0000000 --- a/src/libhal-backend-tdm-nexell/tdm_nexell_pp.c +++ /dev/null @@ -1,375 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_backend_nexell.h" - -#include -#include - -typedef struct _tdm_nexell_pp_buffer { - tbm_surface_h src; - tbm_surface_h dst; - - struct list_head link; -} tdm_nexell_pp_buffer; - -typedef struct _tdm_nexell_pp_data { - tdm_nexell_display *display_data; - - hal_tdm_info_pp info; - - struct list_head pending_buffer_list; - - hal_tdm_pp_done_handler done_func; - void *done_user_data; - - struct list_head link; -} tdm_nexell_pp_data; - -#define MAX_PLANE_NUM 3 - -struct rect { - int x; - int y; - int width; - int height; -}; - -typedef struct _tdm_nexell_scaler_context { - int src_plane_num; - int src_fds[MAX_PLANE_NUM]; - int src_stride[MAX_PLANE_NUM]; - unsigned int src_width; - unsigned int src_height; - unsigned int src_code; - - int dst_plane_num; - int dst_fds[MAX_PLANE_NUM]; - int dst_stride[MAX_PLANE_NUM]; - unsigned int dst_width; - unsigned int dst_height; - unsigned int dst_code; - - struct rect crop; -} tdm_nexell_scaler_context; - -static tbm_format pp_formats[] = { - TBM_FORMAT_YUV420 -}; - -#define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0])) -#define IOC_NX_MAGIC 0x6e78 /* nx */ -enum { - IOCTL_SCALER_SET_AND_RUN = _IO(IOC_NX_MAGIC, 1), -}; - -#ifndef ALIGN -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#endif - -static int pp_list_init; -static struct list_head pp_list; - -static int -_tdm_drm_ioctl(int fd, unsigned long request, void *arg) -{ - int ret; - - do { - ret = ioctl(fd, request, arg); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - - return ret; -} - -static int -_tdm_gem_to_dmafd(int drm_fd, int gem_fd) -{ - int ret; - struct drm_prime_handle arg = {0, }; - - arg.handle = gem_fd; - ret = _tdm_drm_ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg); - if (0 != ret) { - return -1; - } - return arg.fd; -} - -static hal_tdm_error -_tdm_nexell_pp_convert(tdm_nexell_pp_buffer *buffer, hal_tdm_info_pp *info, int drm_fd, int scaler_fd) -{ - tdm_nexell_scaler_context ctx; - unsigned int src_y_stride; - unsigned int src_c_stride; - unsigned int dst_y_stride; - unsigned int dst_c_stride; - tbm_bo bo_src = NULL; - tbm_bo bo_dst = NULL; - __u32 handle_src; - __u32 handle_dst; - - bo_src = tbm_surface_internal_get_bo(buffer->src, 0); - TDM_BACKEND_RETURN_VAL_IF_FAIL(bo_src != NULL, HAL_TDM_ERROR_OPERATION_FAILED); - handle_src = (__u32)tbm_bo_get_handle(bo_src, TBM_DEVICE_DEFAULT).u32; - ctx.src_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_src); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ctx.src_fds[0] >= 0, HAL_TDM_ERROR_OPERATION_FAILED); - - ctx.src_fds[1] = ctx.src_fds[0]; - ctx.src_fds[2] = ctx.src_fds[0]; - - bo_dst = tbm_surface_internal_get_bo(buffer->dst, 0); - if (bo_dst == NULL) { - close(ctx.src_fds[0]); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - handle_dst = (__u32)tbm_bo_get_handle(bo_dst, TBM_DEVICE_DEFAULT).u32; - ctx.dst_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_dst); - if (ctx.dst_fds[0] < 0) { - close(ctx.src_fds[0]); - return HAL_TDM_ERROR_OPERATION_FAILED; - } - - ctx.dst_fds[1] = ctx.dst_fds[0]; - ctx.dst_fds[2] = ctx.dst_fds[0]; - - src_y_stride = ALIGN(info->src_config.size.h, 32); - src_c_stride = ALIGN(src_y_stride >> 1, 16); - dst_y_stride = ALIGN(info->dst_config.size.h, 8); - dst_c_stride = ALIGN(dst_y_stride >> 1, 4); - - ctx.src_plane_num = 1; - ctx.src_width = info->src_config.size.h; - ctx.src_height = info->src_config.size.v; - ctx.src_code = MEDIA_BUS_FMT_YUYV8_2X8; - ctx.src_stride[0] = src_y_stride; - ctx.src_stride[1] = src_c_stride; - ctx.src_stride[2] = src_c_stride; - - ctx.dst_plane_num = 1; - ctx.dst_width = info->dst_config.size.h; - ctx.dst_height = info->dst_config.size.v; - ctx.dst_code = MEDIA_BUS_FMT_YUYV8_2X8; - ctx.dst_stride[0] = dst_y_stride; - ctx.dst_stride[1] = dst_c_stride; - ctx.dst_stride[2] = dst_c_stride; - - ctx.crop.x = info->src_config.pos.x; - ctx.crop.y = info->src_config.pos.y; - ctx.crop.width = info->src_config.pos.w; - ctx.crop.height = info->src_config.pos.h; - - TDM_BACKEND_DBG("pp %p(%d, %d). src(%dx%d, (%d,%d,%d) (%d,%d,%d)) dst(%dx%d, (%d,%d,%d) (%d,%d,%d)) crop(%dx%d, %dx%d)", info, drm_fd, scaler_fd, - ctx.src_width, ctx.src_height, ctx.src_stride[0], ctx.src_stride[1], ctx.src_stride[2], ctx.src_fds[0], ctx.src_fds[1], ctx.src_fds[2], - ctx.dst_width, ctx.dst_height, ctx.dst_stride[0], ctx.dst_stride[1], ctx.dst_stride[2], ctx.dst_fds[0], ctx.dst_fds[1], ctx.dst_fds[2], - ctx.crop.x, ctx.crop.y, ctx.crop.width, ctx.crop.height); - - if (ioctl(scaler_fd, IOCTL_SCALER_SET_AND_RUN, &ctx) < 0) { - TDM_BACKEND_ERR("IOCTL_SCALER_SET_AND_RUN failed"); - } - - close(ctx.src_fds[0]); - close(ctx.dst_fds[0]); - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -tdm_nexell_pp_get_capability(tdm_nexell_display *display_data, hal_tdm_caps_pp *caps) -{ - int i; - - if (!caps) { - TDM_BACKEND_ERR("invalid params"); - return HAL_TDM_ERROR_INVALID_PARAMETER; - } - - if (display_data->scaler_fd < 0 ) { - TDM_BACKEND_ERR("no scaler_fd. not support pp."); - return HAL_TDM_ERROR_BAD_MODULE; - } - - caps->capabilities = HAL_TDM_PP_CAPABILITY_SYNC | HAL_TDM_PP_CAPABILITY_SCANOUT | HAL_TDM_PP_CAPABILITY_NO_TRANSFORM_ROTATION; - - caps->format_count = NUM_PP_FORMAT; - - /* will be freed in frontend */ - caps->formats = calloc(1, sizeof pp_formats); - if (!caps->formats) { - TDM_BACKEND_ERR("alloc failed"); - return HAL_TDM_ERROR_OUT_OF_MEMORY; - } - for (i = 0; i < caps->format_count; i++) - caps->formats[i] = pp_formats[i]; - - caps->min_w = 16; - caps->min_h = 8; - caps->max_w = -1; /* not defined */ - caps->max_h = -1; - caps->preferred_align = 32; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_pp * -tdm_nexell_pp_create(tdm_nexell_display *display_data, hal_tdm_error *error) -{ - tdm_nexell_pp_data *pp_data = NULL; - - if (display_data->scaler_fd < 0 ) { - TDM_BACKEND_ERR("no scaler_fd."); - if (error) - *error = HAL_TDM_ERROR_BAD_MODULE; - return NULL; - } - - pp_data = calloc(1, sizeof(tdm_nexell_pp_data)); - if (!pp_data) { - TDM_BACKEND_ERR("alloc failed"); - if (error) - *error = HAL_TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - pp_data->display_data = display_data; - - LIST_INITHEAD(&pp_data->pending_buffer_list); - - if (!pp_list_init) { - pp_list_init = 1; - LIST_INITHEAD(&pp_list); - } - LIST_ADDTAIL(&pp_data->link, &pp_list); - - return pp_data; -} - -void -nexell_pp_destroy(hal_tdm_pp *pp) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *b = NULL, *bb = NULL; - - if (!pp_data) - return; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { - LIST_DEL(&b->link); - free(b); - } - - LIST_DEL(&pp_data->link); - - free(pp_data); -} - -hal_tdm_error -nexell_pp_set_info(hal_tdm_pp *pp, hal_tdm_info_pp *info) -{ - tdm_nexell_pp_data *pp_data = pp; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); - - pp_data->info = *info; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_pp_attach(hal_tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *buffer; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(src, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(dst, HAL_TDM_ERROR_INVALID_PARAMETER); - - buffer = calloc(1, sizeof(tdm_nexell_pp_buffer)); - if (!buffer) { - TDM_BACKEND_ERR("alloc failed"); - return HAL_TDM_ERROR_NONE; - } - - LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list); - - buffer->src = src; - buffer->dst = dst; - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_pp_commit(hal_tdm_pp *pp) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *b = NULL, *bb = NULL; - tdm_nexell_display *display_data; - hal_tdm_error ret; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); - - display_data = pp_data->display_data; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { - LIST_DEL(&b->link); - - ret = _tdm_nexell_pp_convert(b, &pp_data->info, display_data->drm_fd, display_data->scaler_fd); - TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); - - if (pp_data->done_func) - pp_data->done_func(pp_data, - b->src, - b->dst, - pp_data->done_user_data); - free(b); - } - - return HAL_TDM_ERROR_NONE; -} - -hal_tdm_error -nexell_pp_set_done_handler(hal_tdm_pp *pp, hal_tdm_pp_done_handler func, void *user_data) -{ - tdm_nexell_pp_data *pp_data = pp; - - TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); - TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); - - pp_data->done_func = func; - pp_data->done_user_data = user_data; - - return HAL_TDM_ERROR_NONE; -} diff --git a/src/libtdm-nexell/Makefile.am b/src/libtdm-nexell/Makefile.am deleted file mode 100644 index f026ba8..0000000 --- a/src/libtdm-nexell/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AM_CFLAGS = \ - $(TDM_NEXELL_CFLAGS) \ - -I$(top_srcdir)/src - -libtdm_nexell_la_LTLIBRARIES = libtdm-nexell.la -libtdm_nexell_ladir = $(TDM_MODULE_PATH) -libtdm_nexell_la_LDFLAGS = -module -avoid-version -libtdm_nexell_la_LIBADD = $(TDM_NEXELL_LIBS) -ldl - -libtdm_nexell_la_SOURCES = \ - tdm_nexell_display.c \ - tdm_nexell_format.c \ - tdm_nexell_hwc_window.c \ - tdm_nexell_hwc.c \ - tdm_nexell_pp.c \ - tdm_nexell.c diff --git a/src/libtdm-nexell/tdm_nexell.c b/src/libtdm-nexell/tdm_nexell.c deleted file mode 100644 index 637cabf..0000000 --- a/src/libtdm-nexell/tdm_nexell.c +++ /dev/null @@ -1,517 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#if HAVE_UDEV -#include -#endif - -#include "tdm_nexell.h" -#include -#include - -#define ENABLE_PP -#define TDM_NEXELL_ENABLE_HWC 1 - -#define TDM_NEXELL_NAME "nexell" - -static tdm_nexell_data *nexell_data; - -#ifdef HAVE_UDEV -static struct udev_device * -_tdm_find_primary_gpu(void) -{ - struct udev *udev; - struct udev_enumerate *e; - struct udev_list_entry *entry; - const char *path, *id; - struct udev_device *device, *drm_device, *pci; - - udev = udev_new(); - if (!udev) { - TDM_ERR("fail to initialize udev context\n"); - return NULL; - } - - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "drm"); - udev_enumerate_add_match_sysname(e, "card[0-9]*"); - - udev_enumerate_scan_devices(e); - drm_device = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - if (!device) - continue; - - pci = udev_device_get_parent_with_subsystem_devtype(device, - "pci", NULL); - if (pci) { - id = udev_device_get_sysattr_value(pci, "boot_vga"); - if (id && !strcmp(id, "1")) { - if (drm_device) - udev_device_unref(drm_device); - drm_device = device; - break; - } - } - - if (!drm_device) - drm_device = device; - else - udev_device_unref(device); - } - - udev_enumerate_unref(e); - return drm_device; -} - -static tdm_error -_tdm_nexell_udev_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data) -{ - tdm_nexell_data *display_data = (tdm_nexell_data*)user_data; - struct udev_device *dev; - const char *hotplug; - struct stat s; - dev_t udev_devnum; - int ret; - - dev = udev_monitor_receive_device(display_data->uevent_monitor); - if (!dev) { - TDM_ERR("couldn't receive device"); - return TDM_ERROR_OPERATION_FAILED; - } - - udev_devnum = udev_device_get_devnum(dev); - - ret = fstat(display_data->drm_fd, &s); - if (ret == -1) { - TDM_ERR("fstat failed"); - udev_device_unref(dev); - return TDM_ERROR_OPERATION_FAILED; - } - - hotplug = udev_device_get_property_value(dev, "HOTPLUG"); - - if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && - hotplug && atoi(hotplug) == 1) - { - TDM_INFO("HotPlug"); - tdm_nexell_display_update_output_status(display_data); - } - - udev_device_unref(dev); - - return TDM_ERROR_NONE; -} - -static void -_tdm_nexell_udev_init(tdm_nexell_data *display_data) -{ - struct udev *u = NULL; - struct udev_monitor *mon = NULL; - - u = udev_new(); - if (!u) { - TDM_ERR("couldn't create udev"); - goto failed; - } - - mon = udev_monitor_new_from_netlink(u, "udev"); - if (!mon) { - TDM_ERR("couldn't create udev monitor"); - goto failed; - } - - if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 || - udev_monitor_enable_receiving(mon) < 0) { - TDM_ERR("add match subsystem failed"); - goto failed; - } - - display_data->uevent_source = - tdm_event_loop_add_fd_handler(display_data->dpy, udev_monitor_get_fd(mon), - TDM_EVENT_LOOP_READABLE, - _tdm_nexell_udev_fd_handler, - display_data, NULL); - if (!display_data->uevent_source) { - TDM_ERR("couldn't create udev event source"); - goto failed; - } - - display_data->uevent_monitor = mon; - - TDM_INFO("hotplug monitor created"); - - return; -failed: - if (mon) - udev_monitor_unref(mon); - if (u) - udev_unref(u); -} - -static void -_tdm_nexell_udev_deinit(tdm_nexell_data *display_data) -{ - if (display_data->uevent_source) { - tdm_event_loop_source_remove(display_data->uevent_source); - display_data->uevent_source = NULL; - } - - if (display_data->uevent_monitor) { - struct udev *u = udev_monitor_get_udev(display_data->uevent_monitor); - udev_monitor_unref(display_data->uevent_monitor); - udev_unref(u); - display_data->uevent_monitor = NULL; - TDM_INFO("hotplug monitor destroyed"); - } -} -#endif - -static int -_tdm_nexell_open_drm(void) -{ - int fd = -1; - - fd = drmOpen(TDM_NEXELL_NAME, NULL); - if (fd < 0) { - TDM_WRN("Cannot open '%s' drm", TDM_NEXELL_NAME); - } - -#ifdef HAVE_UDEV - if (fd < 0) { - struct udev_device *drm_device = NULL; - const char *filename; - TDM_WRN("Cannot open drm device.. search by udev"); - - drm_device = _tdm_find_primary_gpu(); - if (drm_device == NULL) { - TDM_ERR("fail to find drm device\n"); - goto close_l; - } - - filename = udev_device_get_devnode(drm_device); - - fd = open(filename, O_RDWR | O_CLOEXEC); - if (fd < 0) - TDM_ERR("Cannot open drm device(%s)\n", filename); - - TDM_DBG("open drm device (name:%s, fd:%d)", filename, fd); - - udev_device_unref(drm_device); - } -close_l: -#endif - return fd; -} - -void -tdm_nexell_deinit(tdm_backend_data *bdata) -{ - if (nexell_data != bdata) - return; - - TDM_INFO("deinit"); - -#ifdef HAVE_UDEV - _tdm_nexell_udev_deinit(nexell_data); -#endif - - tdm_nexell_display_destroy_output_list(nexell_data); - tdm_nexell_data_destroy_buffer_list(nexell_data); - - if (nexell_data->plane_res) - drmModeFreePlaneResources(nexell_data->plane_res); - if (nexell_data->mode_res) - drmModeFreeResources(nexell_data->mode_res); - if (nexell_data->drm_fd >= 0) - close(nexell_data->drm_fd); - if (nexell_data->scaler_fd >= 0) - close(nexell_data->scaler_fd); - - free(nexell_data); - nexell_data = NULL; -} - -tdm_backend_data * -tdm_nexell_init(tdm_display *dpy, tdm_error *error) -{ - tdm_func_display nexell_func_display; - tdm_func_output nexell_func_output; - tdm_func_layer nexell_func_layer; - tdm_func_hwc nexell_func_hwc; - tdm_func_hwc_window nexell_func_hwc_window; -#ifdef ENABLE_PP - tdm_func_pp nexell_func_pp; -#endif - tdm_error ret; - char *str; - - if (!dpy) { - TDM_ERR("display is null"); - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - return NULL; - } - - if (nexell_data) { - TDM_ERR("failed: init twice"); - if (error) - *error = TDM_ERROR_BAD_REQUEST; - return NULL; - } - - nexell_data = calloc(1, sizeof(tdm_nexell_data)); - if (!nexell_data) { - TDM_ERR("alloc failed"); - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - str = getenv("TDM_HWC"); - if (str) { - char *end; - nexell_data->hwc_mode = strtol(str, &end, 10);; - } - - /* enable the tdm_hwc */ - nexell_data->hwc_mode = TDM_NEXELL_ENABLE_HWC; - - LIST_INITHEAD(&nexell_data->output_list); - LIST_INITHEAD(&nexell_data->buffer_list); - - memset(&nexell_func_display, 0, sizeof(nexell_func_display)); - nexell_func_display.display_get_capability = nexell_display_get_capability; - nexell_func_display.display_get_pp_capability = nexell_display_get_pp_capability; - nexell_func_display.display_get_outputs = nexell_display_get_outputs; - nexell_func_display.display_get_fd = nexell_display_get_fd; - nexell_func_display.display_handle_events = nexell_display_handle_events; - nexell_func_display.display_create_pp = nexell_display_create_pp; - - memset(&nexell_func_output, 0, sizeof(nexell_func_output)); - nexell_func_output.output_get_capability = nexell_output_get_capability; - nexell_func_output.output_get_layers = nexell_output_get_layers; - nexell_func_output.output_set_property = nexell_output_set_property; - nexell_func_output.output_get_property = nexell_output_get_property; - nexell_func_output.output_wait_vblank = nexell_output_wait_vblank; - nexell_func_output.output_set_vblank_handler = nexell_output_set_vblank_handler; - nexell_func_output.output_commit = nexell_output_commit; - nexell_func_output.output_set_commit_handler = nexell_output_set_commit_handler; - nexell_func_output.output_set_dpms = nexell_output_set_dpms; - nexell_func_output.output_get_dpms = nexell_output_get_dpms; - nexell_func_output.output_set_mode = nexell_output_set_mode; - nexell_func_output.output_get_mode = nexell_output_get_mode; - nexell_func_output.output_set_mirror = NULL; - nexell_func_output.output_unset_mirror = NULL; -#ifdef HAVE_UDEV - nexell_func_output.output_set_status_handler = nexell_output_set_status_handler; -#endif - - if (nexell_data->hwc_mode) { - nexell_func_output.output_get_hwc = nexell_output_get_hwc; - - memset(&nexell_func_hwc, 0, sizeof(nexell_func_hwc)); - nexell_func_hwc.hwc_create_window = nexell_hwc_create_window; - nexell_func_hwc.hwc_get_video_supported_formats = nexell_hwc_get_video_supported_formats; - nexell_func_hwc.hwc_get_video_available_properties = NULL; - nexell_func_hwc.hwc_get_capabilities = nexell_hwc_get_capabilities; - nexell_func_hwc.hwc_get_available_properties = nexell_hwc_get_available_properties; - nexell_func_hwc.hwc_get_client_target_buffer_queue = nexell_hwc_get_client_target_buffer_queue; - nexell_func_hwc.hwc_set_client_target_buffer = nexell_hwc_set_client_target_buffer; - nexell_func_hwc.hwc_set_client_target_acquire_fence = NULL; - nexell_func_hwc.hwc_validate = nexell_hwc_validate; - nexell_func_hwc.hwc_get_changed_composition_types = nexell_hwc_get_changed_composition_types; - nexell_func_hwc.hwc_accept_validation = nexell_hwc_accept_validation; - nexell_func_hwc.hwc_commit = nexell_hwc_commit; - nexell_func_hwc.hwc_set_commit_handler = nexell_hwc_set_commit_handler; - nexell_func_hwc.hwc_get_commit_fence = NULL; - nexell_func_hwc.hwc_get_release_fences = NULL; - - memset(&nexell_func_hwc_window, 0, sizeof(nexell_func_hwc_window)); - nexell_func_hwc_window.hwc_window_destroy = nexell_hwc_window_destroy; - nexell_func_hwc_window.hwc_window_acquire_buffer_queue = nexell_hwc_window_acquire_buffer_queue; - nexell_func_hwc_window.hwc_window_release_buffer_queue = nexell_hwc_window_release_buffer_queue; - nexell_func_hwc_window.hwc_window_set_composition_type = nexell_hwc_window_set_composition_type; - nexell_func_hwc_window.hwc_window_set_buffer_damage = nexell_hwc_window_set_buffer_damage; - nexell_func_hwc_window.hwc_window_set_info = nexell_hwc_window_set_info; - nexell_func_hwc_window.hwc_window_set_buffer = nexell_hwc_window_set_buffer; - nexell_func_hwc_window.hwc_window_set_property = nexell_hwc_window_set_property; - nexell_func_hwc_window.hwc_window_get_property = nexell_hwc_window_get_property; - nexell_func_hwc_window.hwc_window_get_constraints = nexell_hwc_window_get_constraints; - nexell_func_hwc_window.hwc_window_set_name = nexell_hwc_window_set_name; - nexell_func_hwc_window.hwc_window_set_cursor_image = nexell_hwc_window_set_cursor_image; - } - - memset(&nexell_func_layer, 0, sizeof(nexell_func_layer)); - nexell_func_layer.layer_get_capability = nexell_layer_get_capability; - nexell_func_layer.layer_set_property = nexell_layer_set_property; - nexell_func_layer.layer_get_property = nexell_layer_get_property; - nexell_func_layer.layer_set_info = nexell_layer_set_info; - nexell_func_layer.layer_get_info = nexell_layer_get_info; - nexell_func_layer.layer_set_buffer = nexell_layer_set_buffer; - nexell_func_layer.layer_unset_buffer = nexell_layer_unset_buffer; - -#ifdef ENABLE_PP - memset(&nexell_func_pp, 0, sizeof(nexell_func_pp)); - nexell_func_pp.pp_destroy = nexell_pp_destroy; - nexell_func_pp.pp_set_info = nexell_pp_set_info; - nexell_func_pp.pp_attach = nexell_pp_attach; - nexell_func_pp.pp_commit = nexell_pp_commit; - nexell_func_pp.pp_set_done_handler = nexell_pp_set_done_handler; -#endif - - ret = tdm_backend_register_func_display(dpy, &nexell_func_display); - if (ret != TDM_ERROR_NONE) - goto failed; - - ret = tdm_backend_register_func_output(dpy, &nexell_func_output); - if (ret != TDM_ERROR_NONE) - goto failed; - - if (nexell_data->hwc_mode) { - ret = tdm_backend_register_func_hwc(dpy, &nexell_func_hwc); - if (ret != TDM_ERROR_NONE) - goto failed; - - ret = tdm_backend_register_func_hwc_window(dpy, &nexell_func_hwc_window); - if (ret != TDM_ERROR_NONE) - goto failed; - } - - ret = tdm_backend_register_func_layer(dpy, &nexell_func_layer); - if (ret != TDM_ERROR_NONE) - goto failed; - -#ifdef ENABLE_PP - ret = tdm_backend_register_func_pp(dpy, &nexell_func_pp); - if (ret != TDM_ERROR_NONE) - goto failed; -#endif - - nexell_data->dpy = dpy; - - /* The drm master fd can be opened by a tbm backend module in - * tbm_bufmgr_init() time. In this case, we just get it from tbm. - */ - nexell_data->drm_fd = tbm_drm_helper_get_master_fd(); - if (nexell_data->drm_fd < 0) { - nexell_data->drm_fd = _tdm_nexell_open_drm(); - - if (nexell_data->drm_fd < 0) { - ret = TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - tbm_drm_helper_set_tbm_master_fd(nexell_data->drm_fd); - } - - TDM_INFO("master fd(%d)", nexell_data->drm_fd); - - nexell_data->scaler_fd = open("/dev/scaler", O_RDWR); - if (nexell_data->scaler_fd < 0) - TDM_ERR("scaler open fail. cannot use pp."); - -#ifdef HAVE_UDEV - _tdm_nexell_udev_init(nexell_data); -#endif - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { - TDM_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed"); - } else { - TDM_INFO("has universal planes"); - nexell_data->has_universal_plane = 1; - } - - if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) { - TDM_WRN("Set DRM_CLIENT_CAP_ATOMIC failed"); - } else { - TDM_INFO("has atomic"); - nexell_data->has_atomic = 1; - } -#endif - - nexell_data->mode_res = drmModeGetResources(nexell_data->drm_fd); - if (!nexell_data->mode_res) { - TDM_ERR("no drm resource: %m"); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - nexell_data->plane_res = drmModeGetPlaneResources(nexell_data->drm_fd); - if (!nexell_data->plane_res) { - TDM_ERR("no drm plane resource: %m"); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - if (nexell_data->plane_res->count_planes <= 0) { - TDM_ERR("no drm plane resource"); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed; - } - - ret = tdm_nexell_display_create_output_list(nexell_data); - if (ret != TDM_ERROR_NONE) - goto failed; - - ret = tdm_nexell_display_create_layer_list(nexell_data); - if (ret != TDM_ERROR_NONE) - goto failed; - - if (error) - *error = TDM_ERROR_NONE; - - TDM_INFO("init success!"); - - return (tdm_backend_data *)nexell_data; -failed: - if (error) - *error = ret; - - tdm_nexell_deinit(nexell_data); - - TDM_ERR("init failed!"); - return NULL; -} - -tdm_backend_module tdm_backend_module_data = { - "drm", - "Samsung", - TDM_BACKEND_SET_ABI_VERSION(2, 0), - tdm_nexell_init, - tdm_nexell_deinit -}; diff --git a/src/libtdm-nexell/tdm_nexell.h b/src/libtdm-nexell/tdm_nexell.h deleted file mode 100644 index 286abad..0000000 --- a/src/libtdm-nexell/tdm_nexell.h +++ /dev/null @@ -1,141 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _TDM_NEXELL_H_ -#define _TDM_NEXELL_H_ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "tdm_nexell_types.h" -#include "tdm_nexell_hwc.h" -#include "tdm_nexell_hwc_window.h" - -#if HAVE_UDEV -#include -#endif - -/* drm backend functions (display) */ -tdm_error nexell_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps); -tdm_error nexell_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps); -tdm_output** nexell_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error); -tdm_error nexell_display_get_fd(tdm_backend_data *bdata, int *fd); -tdm_error nexell_display_handle_events(tdm_backend_data *bdata); -tdm_pp* nexell_display_create_pp(tdm_backend_data *bdata, tdm_error *error); -tdm_error nexell_output_get_capability(tdm_output *output, tdm_caps_output *caps); -tdm_layer** nexell_output_get_layers(tdm_output *output, int *count, tdm_error *error); -tdm_error nexell_output_set_property(tdm_output *output, unsigned int id, tdm_value value); -tdm_error nexell_output_get_property(tdm_output *output, unsigned int id, tdm_value *value); -tdm_error nexell_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data); -tdm_error nexell_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func); -tdm_error nexell_output_commit(tdm_output *output, int sync, void *user_data); -tdm_error nexell_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func); -tdm_error nexell_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value); -tdm_error nexell_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value); -tdm_error nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode); -tdm_error nexell_output_get_mode(tdm_output *output, const tdm_output_mode **mode); -tdm_error nexell_output_set_status_handler(tdm_output *output, tdm_output_status_handler func, void *user_data); -tdm_hwc *nexell_output_get_hwc(tdm_output *output, tdm_error *error); - -tdm_hwc_window *nexell_hwc_create_window(tdm_hwc *hwc, tdm_error *error); -tdm_error nexell_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count); -tdm_error nexell_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities); -tdm_error nexell_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count); -tbm_surface_queue_h nexell_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error); -tdm_error nexell_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage); -tdm_error nexell_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types); -tdm_error nexell_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types); -tdm_error nexell_hwc_accept_validation(tdm_hwc *hwc); -tdm_error nexell_hwc_commit(tdm_hwc *hwc, int sync, void *user_data); -tdm_error nexell_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func); - -void nexell_hwc_window_destroy(tdm_hwc_window *hwc_window); -tdm_error nexell_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type); -tdm_error nexell_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage); -tdm_error nexell_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info); -tdm_error nexell_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface); -tdm_error nexell_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value); -tdm_error nexell_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value); -tdm_error nexell_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints); -tbm_surface_queue_h nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error); -void nexell_hwc_window_release_buffer_queue(tdm_hwc_window *hwc_window, tbm_surface_queue_h queue); -tdm_error nexell_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name); -tdm_error nexell_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr); - -tdm_error nexell_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps); -tdm_error nexell_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value); -tdm_error nexell_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); -tdm_error nexell_layer_set_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error nexell_layer_get_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); -tdm_error nexell_layer_unset_buffer(tdm_layer *layer); -void nexell_pp_destroy(tdm_pp *pp); -tdm_error nexell_pp_set_info(tdm_pp *pp, tdm_info_pp *info); -tdm_error nexell_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); -tdm_error nexell_pp_commit(tdm_pp *pp); -tdm_error nexell_pp_set_done_handler(tdm_pp *pp, tdm_pp_done_handler func, void *user_data); - - - -uint32_t tdm_nexell_format_to_drm_format(tbm_format format); -tbm_format tdm_nexell_format_to_tbm_format(uint32_t format); - -void tdm_nexell_display_update_output_status(tdm_nexell_data *nexell_data); -tdm_error tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data); -void tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data); -tdm_error tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data); - -tdm_nexell_layer_data * nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zops); - -void tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data); -tbm_surface_queue_h tdm_nexell_hwc_window_create_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error); -tbm_surface_queue_h tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error); -void tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue); -#endif /* _TDM_NEXELL_H_ */ diff --git a/src/libtdm-nexell/tdm_nexell_display.c b/src/libtdm-nexell/tdm_nexell_display.c deleted file mode 100644 index e859281..0000000 --- a/src/libtdm-nexell/tdm_nexell_display.c +++ /dev/null @@ -1,2283 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "tdm_nexell.h" -#include "tdm_nexell_pp.h" - -#define MIN_WIDTH 32 - -static drmModeModeInfoPtr -_tdm_nexell_display_get_mode(tdm_nexell_output_data *output_data) -{ - int i; - - if (!output_data->current_mode) { - TDM_ERR("no output_data->current_mode"); - return NULL; - } - - for (i = 0; i < output_data->count_modes; i++) { - drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i]; - if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) && - (drm_mode->vdisplay == output_data->current_mode->vdisplay) && - (drm_mode->vrefresh == output_data->current_mode->vrefresh) && - (drm_mode->flags == output_data->current_mode->flags) && - (drm_mode->type == output_data->current_mode->type) && - !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN))) - return drm_mode; - } - - return NULL; -} - -static void -_tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode, - tdm_output_mode *tdm_mode) -{ - tdm_mode->clock = drm_mode->clock; - tdm_mode->hdisplay = drm_mode->hdisplay; - tdm_mode->hsync_start = drm_mode->hsync_start; - tdm_mode->hsync_end = drm_mode->hsync_end; - tdm_mode->htotal = drm_mode->htotal; - tdm_mode->hskew = drm_mode->hskew; - tdm_mode->vdisplay = drm_mode->vdisplay; - tdm_mode->vsync_start = drm_mode->vsync_start; - tdm_mode->vsync_end = drm_mode->vsync_end; - tdm_mode->vtotal = drm_mode->vtotal; - tdm_mode->vscan = drm_mode->vscan; - tdm_mode->vrefresh = drm_mode->vrefresh; - tdm_mode->flags = drm_mode->flags; - tdm_mode->type = drm_mode->type; - snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name); -} - -static tdm_error -_tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc) -{ - drmVBlank vbl; - - vbl.request.type = DRM_VBLANK_RELATIVE; - if (pipe == 1) - vbl.request.type |= DRM_VBLANK_SECONDARY; - else if (pipe > 1) - vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; - - vbl.request.sequence = 0; - if (drmWaitVBlank(fd, &vbl)) { - TDM_ERR("get vblank counter failed: %m"); - *msc = 0; - return TDM_ERROR_OPERATION_FAILED; - } - - *msc = vbl.reply.sequence; - - return TDM_ERROR_NONE; -} - -static tdm_error -_tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data) -{ - drmVBlank vbl; - - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - if (pipe == 1) - vbl.request.type |= DRM_VBLANK_SECONDARY; - else if (pipe > 1) - vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; - - vbl.request.sequence = *target_msc; - vbl.request.signal = (unsigned long)(uintptr_t)data; - - if (drmWaitVBlank(fd, &vbl)) { - TDM_ERR("wait vblank failed: %m"); - *target_msc = 0; - return TDM_ERROR_OPERATION_FAILED; - } - - *target_msc = vbl.reply.sequence; - - return TDM_ERROR_NONE; -} - -static tdm_error -_tdm_nexell_output_update_status(tdm_nexell_output_data *output_data, - tdm_output_conn_status status) -{ - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - if (output_data->status == status) - return TDM_ERROR_NONE; - - output_data->status = status; - - if (output_data->status_func) - output_data->status_func(output_data, status, - output_data->status_user_data); - - return TDM_ERROR_NONE; -} - -static tdm_error -_tdm_nexell_display_commit_primary_layer(tdm_nexell_layer_data *layer_data, - void *user_data, int *do_waitvblank) -{ - tdm_nexell_data *nexell_data = layer_data->nexell_data; - tdm_nexell_output_data *output_data = layer_data->output_data; - - if (output_data->mode_changed && layer_data->display_buffer_changed) { - drmModeModeInfoPtr mode; - - if (!layer_data->display_buffer) { - TDM_ERR("primary layer should have a buffer for modestting"); - return TDM_ERROR_BAD_REQUEST; - } - - output_data->mode_changed = 0; - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - mode = _tdm_nexell_display_get_mode(output_data); - if (!mode) { - TDM_ERR("couldn't find proper mode"); - return TDM_ERROR_BAD_REQUEST; - } - - if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, 0, 0, - &output_data->connector_id, 1, mode)) { - TDM_ERR("set crtc failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED); - - *do_waitvblank = 1; - return TDM_ERROR_NONE; - } else if (layer_data->display_buffer_changed) { - layer_data->display_buffer_changed = 0; - - if (layer_data->display_buffer) { - tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); - - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - if (drmModePageFlip(nexell_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) { - TDM_ERR("pageflip failed: %m"); - free(event_data); - return TDM_ERROR_OPERATION_FAILED; - } - *do_waitvblank = 0; - } - }else { - /* to call a user commit handler whenever committed */ - *do_waitvblank = 1; - } - - return TDM_ERROR_NONE; -} - -static tdm_error -_tdm_nexell_display_commit_layer(tdm_nexell_layer_data *layer_data) -{ - tdm_nexell_data *nexell_data = layer_data->nexell_data; - tdm_nexell_output_data *output_data = layer_data->output_data; - uint32_t fx, fy, fw, fh; - int crtc_w; - - if (!layer_data->display_buffer_changed && !layer_data->info_changed) - return TDM_ERROR_NONE; - - if (output_data->current_mode) - crtc_w = output_data->current_mode->hdisplay; - else { - drmModeCrtcPtr crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id); - if (!crtc) { - TDM_ERR("getting crtc failed"); - return TDM_ERROR_OPERATION_FAILED; - } - crtc_w = crtc->width; - if (crtc_w == 0) { - TDM_ERR("getting crtc width failed"); - drmModeFreeCrtc(crtc); - return TDM_ERROR_OPERATION_FAILED; - } - drmModeFreeCrtc(crtc); - } - - // reset the changed flags - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - if (layer_data->display_buffer) { // set plane - /* Source values are 16.16 fixed point */ - fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16; - fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16; - fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16; - fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16; - - TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", - layer_data->plane_id, output_data->crtc_id, layer_data->zpos, - layer_data->display_buffer->fb_id, - layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y, - layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h, - layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, - layer_data->info.dst_pos.w, layer_data->info.dst_pos.h); - - if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id, - output_data->crtc_id, layer_data->display_buffer->fb_id, 0, - layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, - layer_data->info.dst_pos.w, layer_data->info.dst_pos.h, - fx, fy, fw, fh) < 0) { - TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id); - return TDM_ERROR_OPERATION_FAILED; - } - } else { // unset plane - TDM_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n", - layer_data->plane_id, output_data->crtc_id, layer_data->zpos); - - if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id, - output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id); - } - - return TDM_ERROR_NONE; -} - -static void -_tdm_nexell_display_cb_event(int fd, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, - void *user_data) -{ - tdm_nexell_event_data *event_data = user_data; - tdm_nexell_output_data *output_data; - tdm_nexell_hwc_data *hwc_data; - - if (!event_data) { - TDM_ERR("no event data"); - return; - } - - output_data = event_data->output_data; - - switch (event_data->type) { - case TDM_NEXELL_EVENT_TYPE_PAGEFLIP: - if (output_data->commit_func) - output_data->commit_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - case TDM_NEXELL_EVENT_TYPE_WAIT: - if (output_data->vblank_func) - output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - case TDM_NEXELL_EVENT_TYPE_COMMIT: - if (output_data->hwc_enable) { - hwc_data = output_data->hwc_data; - if (!hwc_data) { - TDM_ERR("no hwc_data"); - break; - } - - if (hwc_data->commit_func) - hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec, - event_data->user_data); - } else { - if (output_data->commit_func) - output_data->commit_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - } - break; - default: - break; - } - - free(event_data); -} - -static tdm_error -_tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *output_data = NULL; - int i; - - if (LIST_IS_EMPTY(&nexell_data->output_list)) { - TDM_ERR("no output"); - return TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend only support one output. */ - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) { - break; - } - - if (nexell_data->plane_res->count_planes == 0) { - TDM_ERR("no layer error"); - return TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < nexell_data->plane_res->count_planes; i++) { - tdm_nexell_layer_data *layer_data; - drmModePlanePtr plane; - - plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]); - if (!plane) { - TDM_ERR("no plane"); - continue; - } - - if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { - drmModeFreePlane(plane); - continue; - } - - layer_data = calloc(1, sizeof(tdm_nexell_layer_data)); - if (!layer_data) { - TDM_ERR("alloc failed"); - drmModeFreePlane(plane); - continue; - } - - layer_data->nexell_data = nexell_data; - layer_data->output_data = output_data; - layer_data->plane_id = nexell_data->plane_res->planes[i]; - - layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | - TDM_LAYER_CAPABILITY_GRAPHIC; - output_data->primary_layer = layer_data; - - TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)", - layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, - layer_data->capabilities); - - LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); - - drmModeFreePlane(plane); - - /* can't take care of other planes for various hardware devices */ - break; - } - - return TDM_ERROR_NONE; -} - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - -static tdm_error -_tdm_nexell_display_get_property(tdm_nexell_data *nexell_data, - unsigned int obj_id, unsigned int obj_type, - const char *name, unsigned int *value, - int *is_immutable) -{ - drmModeObjectPropertiesPtr props = NULL; - int i; - - props = drmModeObjectGetProperties(nexell_data->drm_fd, obj_id, obj_type); - if (!props) - return TDM_ERROR_OPERATION_FAILED; - - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, - props->props[i]); - - if (!prop) - continue; - - if (!strcmp(prop->name, name)) { - if (is_immutable) - *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; - if (value) - *value = (unsigned int)props->prop_values[i]; - drmModeFreeProperty(prop); - drmModeFreeObjectProperties(props); - return TDM_ERROR_NONE; - } - - drmModeFreeProperty(prop); - } - drmModeFreeObjectProperties(props); - TDM_DBG("coundn't find '%s' property", name); - return TDM_ERROR_OPERATION_FAILED; -} - -static tdm_error -_nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id) -{ - drmModeObjectPropertiesPtr properties = NULL; - drmModePropertyPtr property = NULL; - int i; - - properties = drmModeObjectGetProperties(drm_fd, object_id, object_type); - if (properties == NULL) { - TDM_ERR("drmModeObjectGetProperties failed"); - return TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < properties->count_props; i++) { - property = drmModeGetProperty(drm_fd, properties->props[i]); - if (property == NULL) { - continue; - } - - if (strcmp(property->name, name) == 0) { - *id = property->prop_id; - drmModeFreeProperty(property); - break; - } - drmModeFreeProperty(property); - } - - drmModeFreeObjectProperties(properties); - - return TDM_ERROR_NONE; -} - -static tdm_error -_tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *output_data = NULL; - drmModePlanePtr *planes = NULL; - unsigned int *types = NULL; - unsigned int type = 0; - int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt; - int opos_next, cpos_next; - tdm_error ret; - int i; - - if (LIST_IS_EMPTY(&nexell_data->output_list)) { - TDM_ERR("no output"); - return TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend only support one output. */ - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) { - break; - } - - ret = _tdm_nexell_display_get_property(nexell_data, - nexell_data->plane_res->planes[0], - DRM_MODE_OBJECT_PLANE, "type", &type, - NULL); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("plane doesn't have 'type' property. Call a fallback function"); - - /* if a plane doesn't have "type" property, we call a fallback function - * as default - */ - return _tdm_nexell_display_create_layer_list(nexell_data); - } - - planes = calloc(nexell_data->plane_res->count_planes, sizeof(drmModePlanePtr)); - if (!planes) { - TDM_ERR("alloc failed"); - goto failed; - } - - types = calloc(nexell_data->plane_res->count_planes, sizeof(unsigned int)); - if (!types) { - TDM_ERR("alloc failed"); - goto failed; - } - - plane_cnt = 0; - for (i = 0; i < nexell_data->plane_res->count_planes; i++) { - drmModePlanePtr plane; - - plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]); - if (!plane) { - TDM_ERR("no plane(%d)", nexell_data->plane_res->planes[i]); - goto failed; - } - - if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { - drmModeFreePlane(plane); - continue; - } - - ret = _tdm_nexell_display_get_property(nexell_data, - nexell_data->plane_res->planes[i], - DRM_MODE_OBJECT_PLANE, "type", &type, - NULL); - if (ret != TDM_ERROR_NONE) { - drmModeFreePlane(plane); - TDM_ERR("plane(%d) doesn't have 'type' info", - nexell_data->plane_res->planes[i]); - goto failed; - } - - planes[plane_cnt] = plane; - types[plane_cnt] = type; - plane_cnt++; - } - - primary_cnt = ovl_cnt = cursor_cnt = 0; - for (i = 0; i < plane_cnt; i++) { - if (types[i] == DRM_PLANE_TYPE_CURSOR) - cursor_cnt++; - else if (types[i] == DRM_PLANE_TYPE_OVERLAY) - ovl_cnt++; - else if (types[i] == DRM_PLANE_TYPE_PRIMARY) - primary_cnt++; - else - TDM_ERR("invalid type(%d)", types[i]); - } - - if (primary_cnt != 1) { - TDM_ERR("primary layer count(%d) should be one", primary_cnt); - goto failed; - } - - opos_next = 0; - cpos_next = ovl_cnt; - if (plane_cnt < 1) { - TDM_ERR("plane count(%d) should be over 1", plane_cnt); - goto failed; - } - - for (i = plane_cnt - 1; i >= 0; i--) { - tdm_nexell_layer_data *layer_data; - - layer_data = calloc(1, sizeof(tdm_nexell_layer_data)); - if (!layer_data) { - TDM_ERR("alloc failed"); - goto failed; - } - - layer_data->nexell_data = nexell_data; - layer_data->output_data = output_data; - layer_data->plane_id = planes[i]->plane_id; - - if (types[i] == DRM_PLANE_TYPE_CURSOR) { - layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR | - TDM_LAYER_CAPABILITY_GRAPHIC | - TDM_LAYER_CAPABILITY_SCANOUT; - layer_data->zpos = cpos_next++; - TDM_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos); - } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) { - if (opos_next == 0) { - layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY | - TDM_LAYER_CAPABILITY_SCALE | - TDM_LAYER_CAPABILITY_SCANOUT; - } else { - layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY | - TDM_LAYER_CAPABILITY_GRAPHIC | - TDM_LAYER_CAPABILITY_RESEVED_MEMORY | - TDM_LAYER_CAPABILITY_SCANOUT; - } - if (opos_next == 1) { - layer_data->zpos = 2; - opos_next = 2; - } else { - layer_data->zpos = opos_next++; - } - - TDM_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos); - } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) { - layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | - TDM_LAYER_CAPABILITY_GRAPHIC | - TDM_LAYER_CAPABILITY_RESEVED_MEMORY | - TDM_LAYER_CAPABILITY_SCANOUT; - layer_data->zpos = 1; - output_data->primary_layer = layer_data; - - TDM_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos); - } else { - free(layer_data); - continue; - } - - TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)", - layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, - layer_data->zpos, layer_data->capabilities); - - LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); - - /* get the atomic prop ids*/ - if (nexell_data->has_atomic) { - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h); - if (ret != TDM_ERROR_NONE) { - free(layer_data); - goto failed; - } - } - } - - for (i = 0; i < plane_cnt; i++) - if (planes[i]) - drmModeFreePlane(planes[i]); - - free(planes); - free(types); - - return TDM_ERROR_NONE; - -failed: - if (planes) { - for (i = 0; i < nexell_data->plane_res->count_planes; i++) - if (planes[i]) - drmModeFreePlane(planes[i]); - free(planes); - } - - free(types); - - return TDM_ERROR_OPERATION_FAILED; -} -#endif - -tdm_error -tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *output_data = NULL; - tdm_error ret; - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - if (nexell_data->has_universal_plane) - ret = _tdm_nexell_display_create_layer_list_type(nexell_data); - else -#endif - ret = _tdm_nexell_display_create_layer_list(nexell_data); - - if (ret != TDM_ERROR_NONE) - return ret; - - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) { - if (!output_data->primary_layer) { - TDM_ERR("output(%d) no primary layer", output_data->pipe); - return TDM_ERROR_OPERATION_FAILED; - } - } - - return TDM_ERROR_NONE; -} - -void -tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *o = NULL, *oo = NULL; - tdm_nexell_hwc_data *hwc_data = NULL; - - if (LIST_IS_EMPTY(&nexell_data->output_list)) - return; - - LIST_FOR_EACH_ENTRY_SAFE(o, oo, &nexell_data->output_list, link) { - hwc_data = o->hwc_data; - if (hwc_data && hwc_data->target_hwc_window) - nexell_hwc_window_destroy(hwc_data->target_hwc_window); - - LIST_DEL(&o->link); - if (!LIST_IS_EMPTY(&o->layer_list)) { - tdm_nexell_layer_data *l = NULL, *ll = NULL; - LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { - LIST_DEL(&l->link); - if (l->display_buffer) - tbm_surface_internal_unref(l->display_buffer->buffer); - free(l); - } - } - free(o->drm_modes); - free(o->output_modes); - free(o); - } -} - -void -tdm_nexell_display_update_output_status(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *output_data = NULL; - - if (LIST_IS_EMPTY(&nexell_data->output_list)) - return; - - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) { - drmModeConnectorPtr connector; - tdm_output_conn_status new_status; - - connector = drmModeGetConnector(nexell_data->drm_fd, - output_data->connector_id); - if (!connector) { - TDM_ERR("no connector: %d", output_data->connector_id); - continue; - } - - if (connector->connection == DRM_MODE_CONNECTED) - new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED; - else - new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - - _tdm_nexell_output_update_status(output_data, new_status); - - drmModeFreeConnector(connector); - } -} - -tdm_error -tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data) -{ - tdm_nexell_output_data *output_data; - int i; - tdm_error ret; - int allocated = 0; - drmModeConnectorPtr connector; - drmModeEncoderPtr encoder; - int conn_idx = -1; - int hdmia_idx = -1, hdmib_idx = -1; - int crtc_id = 0, c, j; - - RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&nexell_data->output_list), - TDM_ERROR_OPERATION_FAILED); - - /* check if there is a connected output */ - for (i = 0; i < nexell_data->mode_res->count_connectors; i++) { - connector = drmModeGetConnector(nexell_data->drm_fd, - nexell_data->mode_res->connectors[i]); - if (!connector) { - TDM_ERR("no connector"); - return TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM drm backend considers only 1 connector because it is the TDM - * reference backend and can't take care of all hardware devices. - * To support various connectors, planes and crtcs, the new TDM backend - * should be implemented. - */ - if (connector->connection == DRM_MODE_CONNECTED) { - conn_idx = i; - drmModeFreeConnector(connector); - break; - } - - if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) - hdmia_idx = i; - if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) - hdmib_idx = i; - - drmModeFreeConnector(connector); - } - - /* use the hdmi connector if there is no connected connector. */ - /* if there is no hdmi connector, use first connector. */ - if (conn_idx == -1) { - if (hdmia_idx != -1) - conn_idx = hdmia_idx; - else if (hdmib_idx != -1) - conn_idx = hdmib_idx; - else - conn_idx = 0; - } - - /* The TDM drm backend considers only 1 connector because it is the TDM - * reference backend and can't take care of all hardware devices. - * To support various connectors, planes and crtcs, the new TDM backend - * should be implemented. - */ - connector = drmModeGetConnector(nexell_data->drm_fd, - nexell_data->mode_res->connectors[conn_idx]); - if (!connector) { - TDM_ERR("no connector"); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - if (connector->count_encoders != 1) { - TDM_ERR("too many encoders: %d", connector->count_encoders); - drmModeFreeConnector(connector); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - encoder = drmModeGetEncoder(nexell_data->drm_fd, connector->encoders[0]); - if (!encoder) { - TDM_ERR("no encoder"); - drmModeFreeConnector(connector); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - for (c = 0; c < nexell_data->mode_res->count_crtcs; c++) { - if ((encoder->possible_crtcs & (1 << c)) == 0) - continue; - - crtc_id = nexell_data->mode_res->crtcs[c]; - allocated |= (1 << c); - break; - } - - if (crtc_id == 0) { - TDM_ERR("no possible crtc"); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed_create; - } - - output_data = calloc(1, sizeof(tdm_nexell_output_data)); - if (!output_data) { - TDM_ERR("alloc failed"); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - - LIST_INITHEAD(&output_data->layer_list); - - output_data->nexell_data = nexell_data; - output_data->connector_id = nexell_data->mode_res->connectors[conn_idx]; - output_data->encoder_id = encoder->encoder_id; - output_data->crtc_id = crtc_id; - output_data->pipe = c; - output_data->connector_type = connector->connector_type; - output_data->connector_type_id = connector->connector_type_id; - - if (connector->connection == DRM_MODE_CONNECTED) - output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; - else - output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - - for (j = 0; j < connector->count_props; j++) { - drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, - connector->props[j]); - if (!prop) - continue; - if (!strcmp(prop->name, "DPMS")) { - output_data->dpms_prop_id = connector->props[j]; - drmModeFreeProperty(prop); - break; - } - drmModeFreeProperty(prop); - } - - if (output_data->dpms_prop_id == 0) - TDM_WRN("not support DPMS"); - - output_data->count_modes = connector->count_modes; - output_data->drm_modes = calloc(connector->count_modes, - sizeof(drmModeModeInfo)); - if (!output_data->drm_modes) { - TDM_ERR("alloc failed"); - free(output_data); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - output_data->output_modes = calloc(connector->count_modes, - sizeof(tdm_output_mode)); - if (!output_data->output_modes) { - TDM_ERR("alloc failed"); - free(output_data->drm_modes); - free(output_data); - drmModeFreeConnector(connector); - drmModeFreeEncoder(encoder); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - for (j = 0; j < connector->count_modes; j++) { - output_data->drm_modes[j] = connector->modes[j]; - _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j], - &output_data->output_modes[j]); - } - - if (nexell_data->hwc_mode) - output_data->hwc_enable = 1; - - LIST_ADDTAIL(&output_data->link, &nexell_data->output_list); - - TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)", - output_data, output_data->connector_id, output_data->status, - output_data->connector_type, - output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id, - output_data->pipe, output_data->dpms_prop_id); - - drmModeFreeEncoder(encoder); - drmModeFreeConnector(connector); - - /* get the atomic prop ids*/ - if (nexell_data->has_atomic) { - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->connector_id, - DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id); - if (ret != TDM_ERROR_NONE) - goto failed_create; - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id); - if (ret != TDM_ERROR_NONE) - goto failed_create; - - ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active); - if (ret != TDM_ERROR_NONE) - goto failed_create; - } - - TDM_DBG("output count: %d", nexell_data->mode_res->count_connectors); - - return TDM_ERROR_NONE; -failed_create: - tdm_nexell_display_destroy_output_list(nexell_data); - return ret; -} - -tdm_error -nexell_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps) -{ - RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER); - - caps->max_layer_count = -1; /* not defined */ - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps) -{ - return tdm_nexell_pp_get_capability(bdata, caps); -} - -tdm_output ** -nexell_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error) -{ - tdm_nexell_data *nexell_data = bdata; - tdm_nexell_output_data *output_data = NULL; - tdm_output **outputs; - tdm_error ret; - int i; - - RETURN_VAL_IF_FAIL(nexell_data, NULL); - RETURN_VAL_IF_FAIL(count, NULL); - - *count = 0; - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) - (*count)++; - - if (*count == 0) { - ret = TDM_ERROR_NONE; - goto failed_get; - } - - /* will be freed in frontend */ - outputs = calloc(*count, sizeof(tdm_nexell_output_data *)); - if (!outputs) { - TDM_ERR("failed: alloc memory"); - *count = 0; - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_get; - } - - i = 0; - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) - outputs[i++] = output_data; - - if (error) - *error = TDM_ERROR_NONE; - - return outputs; -failed_get: - if (error) - *error = ret; - return NULL; -} - -tdm_error -nexell_display_get_fd(tdm_backend_data *bdata, int *fd) -{ - tdm_nexell_data *nexell_data = bdata; - - RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER); - - *fd = nexell_data->drm_fd; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_display_handle_events(tdm_backend_data *bdata) -{ - tdm_nexell_data *nexell_data = bdata; - drmEventContext ctx; - - RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER); - - memset(&ctx, 0, sizeof(drmEventContext)); - - ctx.version = DRM_EVENT_CONTEXT_VERSION; - ctx.page_flip_handler = _tdm_nexell_display_cb_event; - ctx.vblank_handler = _tdm_nexell_display_cb_event; - - drmHandleEvent(nexell_data->drm_fd, &ctx); - - return TDM_ERROR_NONE; -} - -tdm_pp * -nexell_display_create_pp(tdm_backend_data *bdata, tdm_error *error) -{ - tdm_nexell_data *nexell_data = bdata; - - RETURN_VAL_IF_FAIL(nexell_data, NULL); - - return tdm_nexell_pp_create(nexell_data, error); -} - -tdm_error -nexell_output_get_capability(tdm_output *output, tdm_caps_output *caps) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - drmModeConnectorPtr connector = NULL; - drmModeCrtcPtr crtc = NULL; - drmModeObjectPropertiesPtr props = NULL; - int i; - tdm_error ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER); - - memset(caps, 0, sizeof(tdm_caps_output)); - - nexell_data = output_data->nexell_data; - - snprintf(caps->maker, TDM_NAME_LEN, "unknown"); - snprintf(caps->model, TDM_NAME_LEN, "unknown"); - snprintf(caps->name, TDM_NAME_LEN, "unknown"); - - caps->status = output_data->status; - caps->type = output_data->connector_type; - caps->type_id = output_data->connector_type_id; - - connector = drmModeGetConnector(nexell_data->drm_fd, output_data->connector_id); - RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED); - - caps->mode_count = connector->count_modes; - caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count); - if (!caps->modes) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; - } - - if (caps->mode_count != output_data->count_modes) { - drmModeModeInfoPtr new_drm_modes; - tdm_output_mode *new_output_modes; - - new_drm_modes = calloc(connector->count_modes, - sizeof(drmModeModeInfo)); - if (!new_drm_modes) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed drm_modes\n"); - goto failed_get; - } - new_output_modes = calloc(connector->count_modes, - sizeof(tdm_output_mode)); - if (!new_output_modes) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed output_modes\n"); - free(new_drm_modes); - goto failed_get; - } - free(output_data->drm_modes); - free(output_data->output_modes); - - output_data->drm_modes = new_drm_modes; - output_data->output_modes = new_output_modes; - output_data->count_modes = caps->mode_count; - } - - for (i = 0; i < caps->mode_count; i++) { - output_data->drm_modes[i] = connector->modes[i]; - _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i], - &output_data->output_modes[i]); - caps->modes[i] = output_data->output_modes[i]; - } - - caps->mmWidth = connector->mmWidth; - caps->mmHeight = connector->mmHeight; - caps->subpixel = connector->subpixel; - - caps->min_w = nexell_data->mode_res->min_width; - caps->min_h = nexell_data->mode_res->min_height; - caps->max_w = nexell_data->mode_res->max_width; - caps->max_h = nexell_data->mode_res->max_height; - caps->preferred_align = -1; - - crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id); - if (!crtc) { - ret = TDM_ERROR_OPERATION_FAILED; - TDM_ERR("get crtc failed: %m\n"); - goto failed_get; - } - - props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (!props) { - ret = TDM_ERROR_OPERATION_FAILED; - TDM_ERR("get crtc properties failed: %m\n"); - goto failed_get; - } - - caps->props = calloc(1, sizeof(tdm_prop) * props->count_props); - if (!caps->props) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; - } - - caps->prop_count = 0; - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]); - if (!prop) - continue; - snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name); - caps->props[caps->prop_count].id = props->props[i]; - caps->prop_count++; - drmModeFreeProperty(prop); - } - - if (output_data->hwc_enable) { - caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC; - } - - drmModeFreeObjectProperties(props); - drmModeFreeCrtc(crtc); - drmModeFreeConnector(connector); - - return TDM_ERROR_NONE; -failed_get: - drmModeFreeCrtc(crtc); - drmModeFreeObjectProperties(props); - drmModeFreeConnector(connector); - free(caps->modes); - free(caps->props); - memset(caps, 0, sizeof(tdm_caps_output)); - return ret; -} - -tdm_layer ** -nexell_output_get_layers(tdm_output *output, int *count, tdm_error *error) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_layer_data *layer_data = NULL; - tdm_layer **layers; - tdm_error ret; - int i; - - RETURN_VAL_IF_FAIL(output_data, NULL); - RETURN_VAL_IF_FAIL(count, NULL); - - *count = 0; - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) - (*count)++; - - if (output_data->hwc_enable) { - *count = 0; - ret = TDM_ERROR_NONE; - goto failed_get; - } - - if (*count == 0) { - ret = TDM_ERROR_NONE; - goto failed_get; - } - - /* will be freed in frontend */ - layers = calloc(*count, sizeof(tdm_nexell_layer_data *)); - if (!layers) { - TDM_ERR("failed: alloc memory"); - *count = 0; - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_get; - } - - i = 0; - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) - layers[i++] = layer_data; - - if (error) - *error = TDM_ERROR_NONE; - - return layers; -failed_get: - if (error) - *error = ret; - return NULL; -} - -tdm_error -nexell_output_set_property(tdm_output *output, unsigned int id, tdm_value value) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - int ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = output_data->nexell_data; - ret = drmModeObjectSetProperty(nexell_data->drm_fd, - output_data->crtc_id, DRM_MODE_OBJECT_CRTC, - id, value.u32); - if (ret < 0) { - TDM_ERR("set property failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - drmModeObjectPropertiesPtr props; - int i; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = output_data->nexell_data; - props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (props == NULL) { - TDM_ERR("get property failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == id) { - (*value).u32 = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_wait_vblank(tdm_output *output, int interval, int sync, - void *user_data) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - tdm_nexell_event_data *event_data; - uint target_msc; - tdm_error ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - event_data = calloc(1, sizeof(tdm_nexell_event_data)); - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - nexell_data = output_data->nexell_data; - - ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != TDM_ERROR_NONE) - goto failed_vblank; - - target_msc += interval; - - event_data->type = TDM_NEXELL_EVENT_TYPE_WAIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe, - &target_msc, event_data); - if (ret != TDM_ERROR_NONE) - goto failed_vblank; - - return TDM_ERROR_NONE; -failed_vblank: - free(event_data); - return ret; -} - -tdm_error -nexell_output_set_vblank_handler(tdm_output *output, - tdm_output_vblank_handler func) -{ - tdm_nexell_output_data *output_data = output; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); - - output_data->vblank_func = func; - - return TDM_ERROR_NONE; -} - -static tdm_error -_nexell_layer_add_atomic_properties(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request, - uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, - uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h) -{ - tdm_error ret = TDM_ERROR_NONE; - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. fb_id(%u)", fb_id); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. src_x(%u)", src_x); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. src_y(%u)", src_y); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. src_w(%u)", src_w); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. src_h(%u)", src_h); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w); - return TDM_ERROR_OPERATION_FAILED; - } - - ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h); - if (ret < 0) { - TDM_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -static tdm_error -_nexell_layer_make_atomic_request(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request) -{ - tdm_nexell_data *nexell_data = layer_data->nexell_data; - tdm_nexell_output_data *output_data = layer_data->output_data; - uint32_t fx, fy, fw, fh; - tdm_info_layer layer_info = layer_data->info; - tdm_error ret = TDM_ERROR_NONE; - - if (!layer_data->display_buffer_changed && !layer_data->info_changed) - return TDM_ERROR_NONE; - - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - if (!layer_data->display_buffer) { - TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off", - nexell_data->drm_fd, layer_data->plane_id, output_data->crtc_id); - - ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("_nexell_layer_add_atomic_properties failed."); - return ret; - } - - return TDM_ERROR_NONE; - } - - /* Source values are 16.16 fixed point */ - fx = ((unsigned int)layer_info.src_config.pos.x) << 16; - fy = ((unsigned int)layer_info.src_config.pos.y) << 16; - fw = ((unsigned int)layer_info.src_config.pos.w) << 16; - fh = ((unsigned int)layer_info.src_config.pos.h) << 16; - - TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)", - nexell_data->drm_fd, layer_data->plane_id, layer_data->zpos, - output_data->crtc_id, layer_data->display_buffer->fb_id, - layer_info.src_config.pos.x, layer_info.src_config.pos.y, - layer_info.src_config.pos.w, layer_info.src_config.pos.h, - layer_info.dst_pos.x, layer_info.dst_pos.y, - layer_info.dst_pos.w, layer_info.dst_pos.h); - - ret = _nexell_layer_add_atomic_properties(layer_data, request, - layer_data->display_buffer->fb_id, output_data->crtc_id, - fx, fy, fw, fh, - layer_info.dst_pos.x, layer_info.dst_pos.y, - layer_info.dst_pos.w, layer_info.dst_pos.h); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("MakeAtomicRequest failed"); - return ret; - } - - return TDM_ERROR_NONE; -} - -static tdm_error -_nexell_output_atomic_commit(tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_layer_data *layer_data = NULL; - tdm_nexell_event_data *event_data; - drmModeAtomicReqPtr request; - uint32_t flags = 0; - tdm_error ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - if (!output_data->crtc_enabled || output_data->mode_changed) { - drmModeModeInfoPtr mode; - - layer_data = output_data->primary_layer; - if (!layer_data->display_buffer) { - TDM_ERR("primary layer should have a buffer for modestting"); - return TDM_ERROR_BAD_REQUEST; - } - - mode = _tdm_nexell_display_get_mode(output_data); - if (!mode) { - TDM_ERR("couldn't find proper mode"); - return TDM_ERROR_BAD_REQUEST; - } - - if (drmModeSetCrtc(output_data->nexell_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, 0, 0, - &output_data->connector_id, 1, mode)) { - TDM_ERR("set crtc failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED); - - output_data->crtc_enabled = 1; - output_data->mode_changed = 0; - } - - request = drmModeAtomicAlloc(); - if (!request) { - TDM_ERR("drmModeAtomicAlloc failed."); - return TDM_ERROR_OUT_OF_MEMORY; - } - - flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - ret = _nexell_layer_make_atomic_request(layer_data, request); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("_nexell_layer_make_atomic_request failed."); - drmModeAtomicFree(request); - return ret; - } - } - - event_data = calloc(1, sizeof(tdm_nexell_event_data)); - if (!event_data) { - TDM_ERR("fail to alloc event_data."); - drmModeAtomicFree(request); - return TDM_ERROR_OUT_OF_MEMORY; - } - - event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - TDM_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u", - output_data->pipe, output_data->crtc_id, output_data->connector_id); - - if (drmModeAtomicCommit(output_data->nexell_data->drm_fd, request, flags, event_data) < 0) { - TDM_ERR("drmModeAtomicCommit failed."); - free(event_data); - drmModeAtomicFree(request); - return TDM_ERROR_OPERATION_FAILED; - } - - drmModeAtomicFree(request); - - return TDM_ERROR_NONE; -} - -static tdm_error -_nexell_output_layers_commit(tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - tdm_nexell_layer_data *layer_data = NULL; - tdm_error ret; - int do_waitvblank = 1; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = output_data->nexell_data; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (layer_data == output_data->primary_layer) { - ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data, - &do_waitvblank); - if (ret != TDM_ERROR_NONE) - return ret; - } else { - ret = _tdm_nexell_display_commit_layer(layer_data); - if (ret != TDM_ERROR_NONE) - return ret; - } - } - - if (do_waitvblank == 1) { - tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); - uint target_msc; - - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != TDM_ERROR_NONE) { - free(event_data); - return ret; - } - - target_msc++; - - event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe, - &target_msc, event_data); - if (ret != TDM_ERROR_NONE) { - free(event_data); - return ret; - } - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_commit(tdm_output *output, int sync, void *user_data) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - tdm_error ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = output_data->nexell_data; - - /* check the atomic pageflip */ - if (nexell_data->has_atomic) { - ret = _nexell_output_atomic_commit(output, sync, user_data); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("_nexell_output_atomic_commit failed."); - return ret; - } - } else { - ret = _nexell_output_layers_commit(output, sync, user_data); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("_nexell_output_layers_commit failed."); - return ret; - } - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_set_commit_handler(tdm_output *output, - tdm_output_commit_handler func) -{ - tdm_nexell_output_data *output_data = output; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); - - output_data->commit_func = func; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - int ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - if (output_data->dpms_prop_id == 0) { - TDM_WRN("not support DPMS"); - return TDM_ERROR_OPERATION_FAILED; - } - - nexell_data = output_data->nexell_data; - ret = drmModeObjectSetProperty(nexell_data->drm_fd, - output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR, - output_data->dpms_prop_id, dpms_value); - if (ret < 0) { - TDM_ERR("set dpms failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value) -{ - tdm_nexell_output_data *output_data = output; - tdm_nexell_data *nexell_data; - drmModeObjectPropertiesPtr props; - int i; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = output_data->nexell_data; - props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->connector_id, - DRM_MODE_OBJECT_CONNECTOR); - if (props == NULL) { - TDM_ERR("get property failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == output_data->dpms_prop_id) { - *dpms_value = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode) -{ - tdm_nexell_output_data *output_data = output; - tdm_error ret = TDM_ERROR_NONE; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER); - - /* create or replace the target_window when the output mode is set */ - if (output_data->hwc_enable) { - ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("set info target hwc window failed (%d)", ret); - return ret; - } - } - - output_data->current_mode = mode; - output_data->mode_changed = 1; - - TDM_INFO("Set the output mode: %s, %d, %d, %d, %d, %d", - mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_output_get_mode(tdm_output *output, const tdm_output_mode **mode) -{ - tdm_nexell_output_data *output_data = output; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER); - - *mode = output_data->current_mode; - - return TDM_ERROR_NONE; -} - -tdm_hwc * -nexell_output_get_hwc(tdm_output *output, tdm_error *error) -{ - tdm_nexell_hwc_data *hwc_data = NULL; - tdm_nexell_output_data *output_data = output; - tdm_error ret = TDM_ERROR_NONE; - int i; - - if (!output_data) { - TDM_ERR("invalid params"); - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - return NULL; - } - - if (output_data->hwc_data) { - TDM_INFO("hwc_data already exists"); - if (error) - *error = TDM_ERROR_NONE; - return output_data->hwc_data; - } - - hwc_data = calloc(1, sizeof(tdm_nexell_hwc_data)); - if (!hwc_data) { - TDM_ERR("alloc failed"); - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - for (i = 0; i < NUM_LAYERS; i++) { - hwc_data->ui_buffer_queue[i].tqueue = NULL; - hwc_data->ui_buffer_queue[i].ref_cnt = 0; - } - - hwc_data->output_data = output_data; - - LIST_INITHEAD(&hwc_data->hwc_window_list); - - output_data->hwc_data = hwc_data; - - ret = nexell_hwc_initailize_target_window(output_data->hwc_data); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("create target hwc window failed (%d)", ret); - free(hwc_data); - if (error) - *error = ret; - return NULL; - } - - if (error) - *error = TDM_ERROR_NONE; - - return hwc_data; -} - -tdm_error -nexell_output_set_status_handler(tdm_output *output, - tdm_output_status_handler func, - void *user_data) -{ - tdm_nexell_output_data *output_data = output; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); - - output_data->status_func = func; - output_data->status_user_data = user_data; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps) -{ - tdm_nexell_layer_data *layer_data = layer; - tdm_nexell_data *nexell_data; - drmModePlanePtr plane = NULL; - drmModeObjectPropertiesPtr props = NULL; - int i, format_count = 0; - tdm_error ret; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER); - - memset(caps, 0, sizeof(tdm_caps_layer)); - - nexell_data = layer_data->nexell_data; - plane = drmModeGetPlane(nexell_data->drm_fd, layer_data->plane_id); - if (!plane) { - TDM_ERR("get plane failed: %m"); - ret = TDM_ERROR_OPERATION_FAILED; - goto failed_get; - } - - caps->capabilities = layer_data->capabilities; - caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */ - - caps->format_count = plane->count_formats; - caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count); - if (!caps->formats) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; - } - - for (i = 0; i < caps->format_count; i++) { - /* TODO: kernel reports wrong formats */ - if (plane->formats[i] != DRM_FORMAT_XRGB8888 && - plane->formats[i] != DRM_FORMAT_ARGB8888 && - plane->formats[i] != DRM_FORMAT_YUV420) { - TDM_WRN("plane(%d) zpos(%d) %c%c%c%c skipped", - layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i])); - continue; - } - caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]); - format_count++; - } - - caps->format_count = format_count; - - props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE); - if (!props) { - ret = TDM_ERROR_OPERATION_FAILED; - TDM_ERR("get plane properties failed: %m\n"); - goto failed_get; - } - - caps->props = calloc(1, sizeof(tdm_prop) * props->count_props); - if (!caps->props) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; - } - - caps->prop_count = 0; - for (i = 0; i < props->count_props; i++) { - drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]); - if (!prop) - continue; - if (!strncmp(prop->name, "type", TDM_NAME_LEN)) { - drmModeFreeProperty(prop); - continue; - } - if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) { - drmModeFreeProperty(prop); - continue; - } - snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name); - caps->props[caps->prop_count].id = props->props[i]; - caps->prop_count++; - drmModeFreeProperty(prop); - } - - drmModeFreeObjectProperties(props); - drmModeFreePlane(plane); - - return TDM_ERROR_NONE; -failed_get: - drmModeFreeObjectProperties(props); - drmModeFreePlane(plane); - free(caps->formats); - free(caps->props); - memset(caps, 0, sizeof(tdm_caps_layer)); - return ret; -} - -tdm_error -nexell_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value) -{ - tdm_nexell_layer_data *layer_data = layer; - tdm_nexell_data *nexell_data; - int ret; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = layer_data->nexell_data; - ret = drmModeObjectSetProperty(nexell_data->drm_fd, - layer_data->plane_id, DRM_MODE_OBJECT_PLANE, - id, value.u32); - if (ret < 0) { - TDM_ERR("set property failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value) -{ - tdm_nexell_layer_data *layer_data = layer; - tdm_nexell_data *nexell_data; - drmModeObjectPropertiesPtr props; - int i; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = layer_data->nexell_data; - props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id, - DRM_MODE_OBJECT_PLANE); - if (props == NULL) { - TDM_ERR("get property failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < props->count_props; i++) - if (props->props[i] == id) { - (*value).u32 = (uint)props->prop_values[i]; - break; - } - - drmModeFreeObjectProperties(props); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_layer_set_info(tdm_layer *layer, tdm_info_layer *info) -{ - tdm_nexell_layer_data *layer_data = layer; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER); - - layer_data->info = *info; - layer_data->info_changed = 1; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_layer_get_info(tdm_layer *layer, tdm_info_layer *info) -{ - tdm_nexell_layer_data *layer_data = layer; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER); - - *info = layer_data->info; - - return TDM_ERROR_NONE; -} - -static tdm_nexell_display_buffer * -_tdm_nexell_display_find_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer) -{ - tdm_nexell_display_buffer *display_buffer = NULL; - - LIST_FOR_EACH_ENTRY(display_buffer, &nexell_data->buffer_list, link) { - if (display_buffer->buffer == buffer) - return display_buffer; - } - - return NULL; -} - -static void -_tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data) -{ - tdm_nexell_data *nexell_data; - tdm_nexell_display_buffer *display_buffer; - tdm_nexell_layer_data *layer_data = NULL; - tdm_nexell_output_data *output_data = NULL; - char buf[256] = {0,}; - char *ret_tmp; - - if (!user_data) { - TDM_ERR("no user_data"); - return; - } - if (!buffer) { - TDM_ERR("no buffer"); - return; - } - - nexell_data = (tdm_nexell_data *) user_data; - - display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer); - if (!display_buffer) { - TDM_ERR("no display_buffer"); - return; - } - - LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) { - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (display_buffer == layer_data->display_buffer) - layer_data->display_buffer = NULL; - } - } - - if (display_buffer->fb_id > 0) { - if (drmModeRmFB(nexell_data->drm_fd, display_buffer->fb_id) < 0) { - ret_tmp = strerror_r(errno, buf, sizeof(buf)); - TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp); - } - } - - TDM_DBG("destroy buffer:%p", display_buffer->buffer); - - LIST_DEL(&display_buffer->link); - free(display_buffer); -} - -static tdm_nexell_display_buffer * -_tdm_nexell_display_create_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer, tdm_error *err) -{ - tdm_nexell_display_buffer *display_buffer = NULL; - tdm_error res = TDM_ERROR_NONE; - int count, i, ret; - - display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer)); - if (!display_buffer) { - TDM_ERR("alloc failed"); - if (err) - *err = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - display_buffer->buffer = buffer; - - res = tdm_buffer_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data); - if (res != TDM_ERROR_NONE) { - TDM_ERR("add destroy handler fail"); - free(display_buffer); - if (err) - *err = res; - return NULL; - } - - display_buffer->width = tbm_surface_get_width(buffer); - display_buffer->height = tbm_surface_get_height(buffer); - display_buffer->format = tbm_surface_get_format(buffer); - display_buffer->count = tbm_surface_internal_get_num_bos(buffer); - count = tbm_surface_internal_get_num_planes(display_buffer->format); - TDM_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d", - buffer, display_buffer->width, display_buffer->height, - FOURCC_STR(display_buffer->format), display_buffer->count, count); - - for (i = 0; i < count; i++) { - int bo_idx = 0; - tbm_bo bo = NULL; - - bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i); - bo = tbm_surface_internal_get_bo(buffer, bo_idx); - display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; - - tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size, - &display_buffer->offsets[i], - &display_buffer->pitches[i]); - TDM_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)", - i, display_buffer->size, display_buffer->offsets[i], - display_buffer->pitches[i], bo_idx, display_buffer->handles[i]); - } - - ret = drmModeAddFB2(nexell_data->drm_fd, display_buffer->width, display_buffer->height, - display_buffer->format, display_buffer->handles, display_buffer->pitches, - display_buffer->offsets, &display_buffer->fb_id, 0); - if (ret < 0) { - TDM_ERR("add fb failed: %m"); - free(display_buffer); - if (err) - *err = TDM_ERROR_OPERATION_FAILED; - return NULL; - } - - TDM_DBG("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_data->drm_fd, - display_buffer->fb_id); - - if (IS_RGB(display_buffer->format)) - display_buffer->width = display_buffer->pitches[0] >> 2; - else - display_buffer->width = display_buffer->pitches[0]; - - LIST_ADDTAIL(&display_buffer->link, &nexell_data->buffer_list); - - if (err) - *err = TDM_ERROR_NONE; - - return display_buffer; -} - -void -tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data) -{ - tdm_nexell_display_buffer *b = NULL, *bb = NULL; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &nexell_data->buffer_list, link) { - tdm_buffer_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data); - _tdm_nexell_display_cb_destroy_buffer(b->buffer, nexell_data); - } -} - -tdm_error -nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) -{ - tdm_nexell_layer_data *layer_data = layer; - tdm_nexell_data *nexell_data; - tdm_nexell_display_buffer *display_buffer; - tdm_error err = TDM_ERROR_NONE; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = layer_data->nexell_data; - display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer); - if (!display_buffer) { - display_buffer = _tdm_nexell_display_create_buffer(nexell_data, buffer, &err); - RETURN_VAL_IF_FAIL(display_buffer != NULL, err); - } - - if (layer_data->display_buffer != display_buffer) { - if (layer_data->display_buffer) - tbm_surface_internal_unref(layer_data->display_buffer->buffer); - - layer_data->display_buffer = display_buffer; - tbm_surface_internal_ref(layer_data->display_buffer->buffer); - layer_data->display_buffer_changed = 1; - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_layer_unset_buffer(tdm_layer *layer) -{ - tdm_nexell_layer_data *layer_data = layer; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); - - if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) { - tbm_surface_internal_unref(layer_data->display_buffer->buffer); - layer_data->display_buffer = NULL; - } - - layer_data->display_buffer_changed = 1; - - return TDM_ERROR_NONE; -} - -tdm_nexell_layer_data * -nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zpos) -{ - tdm_nexell_layer_data *l = NULL; - - RETURN_VAL_IF_FAIL(output_data, NULL); - - LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) { - if (l->zpos == layer_zpos) - return l; - } - - return NULL; -} diff --git a/src/libtdm-nexell/tdm_nexell_format.c b/src/libtdm-nexell/tdm_nexell_format.c deleted file mode 100644 index 9cc3470..0000000 --- a/src/libtdm-nexell/tdm_nexell_format.c +++ /dev/null @@ -1,134 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "tdm_nexell.h" - -typedef struct { - tbm_format tbm_format; - uint32_t drm_format; -} tbm_drm_format_data; - -static const tbm_drm_format_data formats[] = { - {TBM_FORMAT_C8, DRM_FORMAT_C8}, - {TBM_FORMAT_RGB332, DRM_FORMAT_RGB332}, - {TBM_FORMAT_BGR233, DRM_FORMAT_BGR233}, - {TBM_FORMAT_XRGB4444, DRM_FORMAT_XRGB4444}, - {TBM_FORMAT_XBGR4444, DRM_FORMAT_XBGR4444}, - {TBM_FORMAT_RGBX4444, DRM_FORMAT_RGBX4444}, - {TBM_FORMAT_BGRX4444, DRM_FORMAT_BGRX4444}, - {TBM_FORMAT_ARGB4444, DRM_FORMAT_ARGB4444}, - {TBM_FORMAT_ABGR4444, DRM_FORMAT_ABGR4444}, - {TBM_FORMAT_RGBA4444, DRM_FORMAT_RGBA4444}, - {TBM_FORMAT_BGRA4444, DRM_FORMAT_BGRA4444}, - {TBM_FORMAT_XRGB1555, DRM_FORMAT_XRGB1555}, - {TBM_FORMAT_XBGR1555, DRM_FORMAT_XBGR1555}, - {TBM_FORMAT_RGBX5551, DRM_FORMAT_RGBX5551}, - {TBM_FORMAT_BGRX5551, DRM_FORMAT_BGRX5551}, - {TBM_FORMAT_ARGB1555, DRM_FORMAT_ARGB1555}, - {TBM_FORMAT_ABGR1555, DRM_FORMAT_ABGR1555}, - {TBM_FORMAT_RGBA5551, DRM_FORMAT_RGBA5551}, - {TBM_FORMAT_BGRA5551, DRM_FORMAT_BGRA5551}, - {TBM_FORMAT_RGB565, DRM_FORMAT_RGB565}, - {TBM_FORMAT_BGR565, DRM_FORMAT_BGR565}, - {TBM_FORMAT_RGB888, DRM_FORMAT_RGB888}, - {TBM_FORMAT_BGR888, DRM_FORMAT_BGR888}, - {TBM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888}, - {TBM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888}, - {TBM_FORMAT_RGBX8888, DRM_FORMAT_RGBX8888}, - {TBM_FORMAT_BGRX8888, DRM_FORMAT_BGRX8888}, - {TBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888}, - {TBM_FORMAT_ABGR8888, DRM_FORMAT_ABGR8888}, - {TBM_FORMAT_RGBA8888, DRM_FORMAT_RGBA8888}, - {TBM_FORMAT_BGRA8888, DRM_FORMAT_BGRA8888}, - {TBM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010}, - {TBM_FORMAT_XBGR2101010, DRM_FORMAT_XBGR2101010}, - {TBM_FORMAT_RGBX1010102, DRM_FORMAT_RGBX1010102}, - {TBM_FORMAT_BGRX1010102, DRM_FORMAT_BGRX1010102}, - {TBM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB2101010}, - {TBM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR2101010}, - {TBM_FORMAT_RGBA1010102, DRM_FORMAT_RGBA1010102}, - {TBM_FORMAT_BGRA1010102, DRM_FORMAT_BGRA1010102}, - {TBM_FORMAT_YUYV, DRM_FORMAT_YUYV}, - {TBM_FORMAT_YVYU, DRM_FORMAT_YVYU}, - {TBM_FORMAT_UYVY, DRM_FORMAT_UYVY}, - {TBM_FORMAT_VYUY, DRM_FORMAT_VYUY}, - {TBM_FORMAT_AYUV, DRM_FORMAT_AYUV}, - {TBM_FORMAT_NV12, DRM_FORMAT_NV12}, - {TBM_FORMAT_NV21, DRM_FORMAT_NV21}, - {TBM_FORMAT_NV16, DRM_FORMAT_NV16}, - {TBM_FORMAT_NV61, DRM_FORMAT_NV61}, - {TBM_FORMAT_YUV410, DRM_FORMAT_YUV410}, - {TBM_FORMAT_YVU410, DRM_FORMAT_YVU410}, - {TBM_FORMAT_YUV411, DRM_FORMAT_YUV411}, - {TBM_FORMAT_YVU411, DRM_FORMAT_YVU411}, - {TBM_FORMAT_YUV420, DRM_FORMAT_YUV420}, - {TBM_FORMAT_YVU420, DRM_FORMAT_YVU420}, - {TBM_FORMAT_YUV422, DRM_FORMAT_YUV422}, - {TBM_FORMAT_YVU422, DRM_FORMAT_YVU422}, - {TBM_FORMAT_YUV444, DRM_FORMAT_YUV444}, - {TBM_FORMAT_YVU444, DRM_FORMAT_YVU444}, -}; - -#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) - -uint32_t -tdm_nexell_format_to_drm_format(tbm_format format) -{ - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (formats[i].tbm_format == format) - return formats[i].drm_format; - - TDM_ERR("tbm format '%c%c%c%c' not found", FOURCC_STR(format)); - - return 0; -} - -tbm_format -tdm_nexell_format_to_tbm_format(uint32_t format) -{ - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (formats[i].drm_format == format) - return formats[i].tbm_format; - - TDM_ERR("drm format '%c%c%c%c' not found", FOURCC_STR(format)); - - return 0; -} diff --git a/src/libtdm-nexell/tdm_nexell_hwc.c b/src/libtdm-nexell/tdm_nexell_hwc.c deleted file mode 100644 index fb8a667..0000000 --- a/src/libtdm-nexell/tdm_nexell_hwc.c +++ /dev/null @@ -1,982 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include "tdm_nexell.h" - -#define MIN_WIDTH 32 - -tbm_format hwc_window_video_formats[] = { - TBM_FORMAT_NV12, - TBM_FORMAT_YUV420 -}; - -const char * -_comp_to_str(tdm_hwc_window_composition composition_type) -{ - if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT) - return "CLIENT"; - else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE) - return "DEVICE"; - else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR) - return "CURSOR"; - else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO) - return "VIDEO"; - else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE) - return "SKIP"; - - return "unknown"; -} - -static int -_nexell_hwc_cursor_buffer_image_render(tdm_nexell_hwc_data *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - tbm_surface_info_s tsurface_info; - tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE; - void *src_ptr = NULL, *dst_ptr = NULL; - int src_stride, transform, img_w, img_h; - pixman_image_t *src_img = NULL, *dst_img = NULL; - pixman_transform_t t; - struct pixman_f_transform ft; - int c = 0, s = 0, tx = 0, ty = 0; - int i; - - ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info); - if (ret != TBM_SURFACE_ERROR_NONE) { - TDM_ERR("Failed to map tsurface\n"); - return 0; - } - - src_ptr = hwc_window_data->cursor_img.ptr; - src_stride = hwc_window_data->cursor_img.stride; - img_w = hwc_window_data->cursor_img.width; - img_h = hwc_window_data->cursor_img.height; - transform = hwc_window_data->info.transform; - - dst_ptr = tsurface_info.planes[0].ptr; - - memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height); - - if (transform) { - src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride); - if (!src_img) { - TDM_ERR("Failed to create src pixman\n"); - return 0; - } - - dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info.width, tsurface_info.height, - (uint32_t*)dst_ptr, tsurface_info.planes[0].stride); - if (!dst_img) { - TDM_ERR("Failed to create dst pixman\n"); - pixman_image_unref(src_img); - return 0; - } - - pixman_f_transform_init_identity(&ft); - - if (transform >= TDM_TRANSFORM_FLIPPED) { - pixman_f_transform_scale(&ft, NULL, -1, 1); - pixman_f_transform_translate(&ft, NULL, tsurface_info.width, 0); - } - - switch (transform) { - case TDM_TRANSFORM_90: - case TDM_TRANSFORM_FLIPPED_90: - c = 0, s = 1, ty = -tsurface_info.height; - break; - case TDM_TRANSFORM_180: - case TDM_TRANSFORM_FLIPPED_180: - c = -1, s = 0, tx = -tsurface_info.width, ty = -tsurface_info.height; - break; - case TDM_TRANSFORM_270: - case TDM_TRANSFORM_FLIPPED_270: - c = 0, s = -1, tx = -tsurface_info.width; - break; - default: - break; - } - - pixman_f_transform_translate(&ft, NULL, tx, ty); - pixman_f_transform_rotate(&ft, NULL, c, s); - pixman_transform_from_pixman_f_transform(&t, &ft); - pixman_image_set_transform(src_img, &t); - pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, - tsurface_info.width, tsurface_info.height); - pixman_image_unref(src_img); - pixman_image_unref(dst_img); - } - else { - for (i = 0 ; i < img_h ; i++) { - memcpy(dst_ptr, src_ptr, src_stride); - dst_ptr += tsurface_info.planes[0].stride; - src_ptr += src_stride; - } - } - - tbm_surface_unmap(hwc_data->cursor_tsurface); - - return 1; -} - -static int -_nexell_hwc_cursor_window_surface_clear(tdm_nexell_hwc_window_data *hwc_window_data) -{ - hwc_window_data->surface = NULL; - hwc_window_data->cursor_img_surface = 0; - - hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width; - hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height; - hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width; - hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height; - - return 1; -} - -static void -_nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc_data *hwc_data) -{ - if (hwc_data->cursor_tsurface) { - tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - } - - if (hwc_data->cursor_tqueue) { - tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->cursor_tqueue); - hwc_data->cursor_tqueue = NULL; - } -} - -static void -_nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc_data *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - int x, y, width, height; - - width = tbm_surface_get_width(hwc_data->cursor_tsurface); - height = tbm_surface_get_height(hwc_data->cursor_tsurface); - - hwc_window_data->info.src_config.pos.w = width; - hwc_window_data->info.src_config.pos.h = height; - hwc_window_data->info.dst_pos.w = width; - hwc_window_data->info.dst_pos.h = height; - - /* dst pos of cursor is possible set by negative value - * this is temporary code. - */ - x = hwc_window_data->info.dst_pos.x; - y = hwc_window_data->info.dst_pos.y; - - if (x < 0) hwc_window_data->info.dst_pos.x = 0; - if (y < 0) hwc_window_data->info.dst_pos.y = 0; -} - -static int -_nexell_hwc_cursor_buffer_set(tdm_nexell_hwc_data *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - tbm_surface_h cursor_tsurface = NULL; - tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE; - int img_w, img_h; - int tqueue_w, tqueue_h; - tdm_error error; - - if (hwc_window_data->cursor_img_refresh || !hwc_window_data->surface) { - switch (hwc_window_data->info.transform) { - case TDM_TRANSFORM_90: - case TDM_TRANSFORM_FLIPPED_90: - case TDM_TRANSFORM_270: - case TDM_TRANSFORM_FLIPPED_270: - img_w = hwc_window_data->cursor_img.height; - img_h = hwc_window_data->cursor_img.width; - break; - default: - img_w = hwc_window_data->cursor_img.width; - img_h = hwc_window_data->cursor_img.height; - break; - } - - if (!hwc_data->cursor_tqueue) { - hwc_data->cursor_tqueue = tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hwc_window_data, &error); - if (error != TDM_ERROR_NONE) { - TDM_ERR("Failed to create cursor buffer queue error:%d", error); - return 0; - } - } else { - tqueue_w = tbm_surface_queue_get_width(hwc_data->cursor_tqueue); - tqueue_h = tbm_surface_queue_get_height(hwc_data->cursor_tqueue); - if ((img_w != tqueue_w) || (img_h != tqueue_h)) - tbm_surface_queue_reset(hwc_data->cursor_tqueue, img_w, img_h, TBM_FORMAT_ARGB8888); - } - - if (hwc_data->cursor_tsurface) { - tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - } - - if (!tbm_surface_queue_can_dequeue(hwc_data->cursor_tqueue, 0)) { - TDM_ERR("Can't dequeue cursor tqueue"); - return 0; - } - - tsq_error = tbm_surface_queue_dequeue(hwc_data->cursor_tqueue, &cursor_tsurface); - if (tsq_error != TBM_SURFACE_QUEUE_ERROR_NONE) { - TDM_ERR("Failed to dequeue cursor tqueue error:%d", tsq_error); - return 0; - } - - hwc_data->cursor_tsurface = cursor_tsurface; - - _nexell_hwc_cursor_buffer_image_render(hwc_data, hwc_window_data); - - hwc_window_data->surface = cursor_tsurface; - hwc_window_data->cursor_img_surface = 1; - hwc_window_data->cursor_img_refresh = 0; - } - - _nexell_hwc_cursor_adjust_pos(hwc_data, hwc_window_data); - - return 1; -} - -static void -_print_validate_result(tdm_nexell_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int i; - int lzpos_queue; - - for (i = 0; i < num_wnds; i++) { - hwc_window_data = composited_wnds[i]; - lzpos_queue = hwc_window_data->lzpos_queue; - switch (hwc_window_data->validated_type) { - case TDM_HWC_WIN_COMPOSITION_CLIENT: - TDM_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data, - _comp_to_str(hwc_window_data->client_type), - _comp_to_str(hwc_window_data->validated_type), - hwc_data->target_hwc_window->lzpos, - lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, - lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, - hwc_window_data->name ? hwc_window_data->name : "NONE"); - break; - case TDM_HWC_WIN_COMPOSITION_DEVICE: - case TDM_HWC_WIN_COMPOSITION_VIDEO: - case TDM_HWC_WIN_COMPOSITION_CURSOR: - case TDM_HWC_WIN_COMPOSITION_NONE: - TDM_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s}", hwc_window_data, - _comp_to_str(hwc_window_data->client_type), - _comp_to_str(hwc_window_data->validated_type), - hwc_window_data->lzpos, - lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, - lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, - hwc_window_data->name ? hwc_window_data->name : "NONE"); - break; - default: - break; - } - } -} - -static int -_nexell_hwc_window_has_reserved_buffer(tdm_nexell_hwc_window_data *hwc_window_data) { - tbm_bo bo = NULL; - int flags = 0; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0); - RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, 0); - - bo = tbm_surface_internal_get_bo(hwc_window_data->surface, 0); - RETURN_VAL_IF_FAIL(bo != NULL, 0); - - flags = tbm_bo_get_flags(bo); - - return flags & TBM_BO_SCANOUT; -} - -static int -_nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data, int bottom) -{ - if (!hwc_window_data->surface) - return 0; - - if (hwc_window_data->info.transform != TDM_TRANSFORM_NORMAL) - return 0; - - if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w) - return 0; - - if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h) - return 0; - - if (!IS_RGB(hwc_window_data->info.src_config.format)) - return 0; - - if ((hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || - (hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) - return 0; - - if (bottom) { - if ((hwc_window_data->info.dst_pos.w != hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || - (hwc_window_data->info.dst_pos.h != hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) - return 0; - } - - return 1; -} - -tbm_surface_queue_h -tdm_nexell_hwc_window_create_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - tbm_format format; - - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); - - hwc_window_data = hwc_window; - - width = hwc_window_data->info.src_config.pos.w; - height = hwc_window_data->info.src_config.pos.h; - format = hwc_window_data->info.src_config.format; - - tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); - if (error) - *error = TDM_ERROR_OPERATION_FAILED; - RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); - - if (error) - *error = TDM_ERROR_NONE; - - return tqueue; -} - -tbm_surface_queue_h -tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); - - hwc_window_data = hwc_window; - - switch (hwc_window_data->info.transform) { - case TDM_TRANSFORM_90: - case TDM_TRANSFORM_FLIPPED_90: - case TDM_TRANSFORM_270: - case TDM_TRANSFORM_FLIPPED_270: - width = hwc_window_data->cursor_img.height; - height = hwc_window_data->cursor_img.width; - break; - default: - width = hwc_window_data->cursor_img.width; - height = hwc_window_data->cursor_img.height; - break; - } - - tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT); - if (error) - *error = TDM_ERROR_OPERATION_FAILED; - RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); - - tbm_surface_queue_set_modes(tqueue, TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE); - - if (error) - *error = TDM_ERROR_NONE; - - return tqueue; -} - -void -tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue) -{ - tbm_surface_queue_destroy(tqueue); -} - -static tdm_error -_nexell_hwc_layer_attach_window(tdm_nexell_layer_data *layer_data, tdm_nexell_hwc_window_data *hwc_window_data) -{ - tdm_error ret = TDM_ERROR_NONE; - - RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED); - - if (hwc_window_data == NULL || hwc_window_data->surface == NULL) { - if (layer_data->display_buffer) - ret = nexell_layer_unset_buffer(layer_data); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - } else { - ret = nexell_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info)); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER); - ret = nexell_layer_set_buffer(layer_data, hwc_window_data->surface); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - } - - return ret; -} - -static tdm_error -_nexell_hwc_prepare_commit(tdm_nexell_hwc_data *hwc_data) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tdm_nexell_layer_data *layer_data = NULL; - int use_layers_zpos[NUM_LAYERS] = {0,}; - int lzpos = 0; - int cursor_enabled = 0; - - /* set target hwc window to the layer */ - if (hwc_data->need_target_window) { - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos); - _nexell_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window); - use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1; - } - - /* set the hwc_windows to the layers */ - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_NONE || - hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CLIENT) { - if (hwc_window_data->cursor_img_surface) - _nexell_hwc_cursor_window_surface_clear(hwc_window_data); - - continue; - } - - if (hwc_window_data == hwc_data->target_hwc_window) - continue; - - /* set the cursor buffer HERE if it needs */ - if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CURSOR) { - _nexell_hwc_cursor_buffer_set(hwc_data, hwc_window_data); - cursor_enabled = 1; - } - - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos); - _nexell_hwc_layer_attach_window(layer_data, hwc_window_data); - use_layers_zpos[hwc_window_data->lzpos] = 1; - } - - /* unset the unused layers */ - for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) { - if (use_layers_zpos[lzpos]) - continue; - - layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, lzpos); - if (!layer_data) - continue; - - _nexell_hwc_layer_attach_window(layer_data, NULL); - } - - if (!cursor_enabled) - _nexell_hwc_cursor_buffer_unset(hwc_data); - - /* for debug */ - for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) { - if (use_layers_zpos[lzpos]) - TDM_DBG(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET"); - } - - return TDM_ERROR_NONE; -} - -/* assign the validated_type to the composited_wnds - * assign the layer_zpos to the composited_wnds - */ -static void -_nexell_hwc_apply_policy(tdm_nexell_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds) -{ - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tdm_nexell_hwc_window_data **composited_list = NULL; - int client_count = 0; - int device_count = 0; - int video_count = 0; - int cursor_count = 0; - int ui_lzpos_top = ZPOS_2; - int ui_lzpos_bottom = ZPOS_1; - int num_ui_layers = NUM_UI_LAYERS; - int set_clients_below = 0; - int i = 0; - - composited_list = (tdm_nexell_hwc_window_data **)composited_wnds; - - /* initialize the need_target_window */ - hwc_data->need_target_window = 0; - - /* initialize the validated_types and constraints */ - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - hwc_window_data->constraints = TDM_HWC_WIN_CONSTRAINT_NONE; - hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE; - hwc_window_data->lzpos = -1; - hwc_window_data->lzpos_queue = -1; - } - - /* use the target_window to commit when there is no window. */ - if (num_wnds == 0) { - hwc_data->need_target_window = 1; - hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; - hwc_data->target_hwc_window->lzpos_queue = ui_lzpos_bottom; - return; - } - - /* 1. first check validate_type without target_window */ - for (i = 0; i < num_wnds; i++) { - switch (composited_list[i]->client_type) { - case TDM_HWC_WIN_COMPOSITION_VIDEO: - composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_VIDEO; - video_count++; - continue; - case TDM_HWC_WIN_COMPOSITION_CURSOR: - if (set_clients_below) break; - if (num_ui_layers <= 0) break; - - composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CURSOR; - cursor_count++; - num_ui_layers--; - continue; - case TDM_HWC_WIN_COMPOSITION_DEVICE: - if (set_clients_below) break; - if (num_ui_layers <= 0) break; - - if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i], (i == num_wnds - 1))) - break; - - if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i])) { - composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; - break; - } - - composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_DEVICE; - composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; - device_count++; - num_ui_layers--; - continue; - default: - break; - } - - composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT; - client_count++; - set_clients_below = 1; - } - - /* 2. check need target window and set ui_lzpos top and bottom */ - num_ui_layers = NUM_UI_LAYERS; - if (client_count > 0) { - hwc_data->need_target_window = 1; - hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; - ui_lzpos_bottom++; - num_ui_layers--; - } - - if (num_ui_layers > (device_count + cursor_count)) - ui_lzpos_top = ui_lzpos_bottom + device_count + cursor_count - 1; - - /* 3. set lzpos and modify validate_type with target_window */ - for (i = 0; i < num_wnds; i++) { - switch (composited_list[i]->validated_type) { - case TDM_HWC_WIN_COMPOSITION_VIDEO: - composited_list[i]->lzpos = ZPOS_VIDEO1; - continue; - case TDM_HWC_WIN_COMPOSITION_CURSOR: - case TDM_HWC_WIN_COMPOSITION_DEVICE: - if (num_ui_layers <= 0) break; - - composited_list[i]->lzpos = ui_lzpos_top; - composited_list[i]->lzpos_queue = ui_lzpos_top; - ui_lzpos_top--; - num_ui_layers--; - continue; - default: - break; - } - - composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT; - - if (composited_list[i]->constraints == TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE) { - if (i == num_wnds - 1) //set target window queue zpos - composited_list[i]->lzpos_queue = ui_lzpos_top; - else if(num_ui_layers > 0) - composited_list[i]->lzpos_queue = ui_lzpos_top + 1; - else - composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_NONE; - } - } -} - -static int -_nexell_hwc_get_changed_number(tdm_nexell_hwc_data *hwc_data) -{ - int num = 0; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE) - continue; - - if (hwc_window_data->client_type != hwc_window_data->validated_type) - num++; - } - - return num; -} - -tdm_hwc_window * -_nexell_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - if (error) - *error = TDM_ERROR_NONE; - - if (!hwc_data) { - TDM_ERR("invalid params"); - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - return NULL; - } - - hwc_window_data = calloc(1, sizeof(tdm_nexell_hwc_window_data)); - if (!hwc_window_data) { - TDM_ERR("alloc failed"); - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - hwc_window_data->hwc_data = hwc_data; - - if (info) - memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)); - - LIST_INITHEAD(&hwc_window_data->link); - - return hwc_window_data; -} - -tdm_hwc_window * -nexell_hwc_create_window(tdm_hwc *hwc, tdm_error *error) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - - RETURN_VAL_IF_FAIL(hwc_data, NULL); - - hwc_window_data = _nexell_hwc_create_window(hwc_data, NULL, error); - RETURN_VAL_IF_FAIL(hwc_window_data, NULL); - - LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list); - - TDM_DBG("hwc_window(%p) create", hwc_window_data); - if (error) - *error = TDM_ERROR_NONE; - - return hwc_window_data; -} - -tdm_error -nexell_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count) -{ - RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); - - // TODO: fix these formats. - *formats = hwc_window_video_formats; - *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities) -{ - RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER); - - *capabilities |= TDM_HWC_CAPABILITY_VIDEO_SCALE; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); - - *props = NULL; - *count = 0; - - return TDM_ERROR_NONE; -} - -tbm_surface_queue_h -nexell_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tbm_surface_queue_h tqueue = NULL; - - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); - - if (hwc_data->target_hwc_window == NULL) { - if (error) - *error = TDM_ERROR_OPERATION_FAILED; - return NULL; - } - - tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_data->target_hwc_window, error); - RETURN_VAL_IF_FAIL(tqueue, NULL); - - hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue; - hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1; - - if (error) - *error = TDM_ERROR_NONE; - - return tqueue; -} - -tdm_error -nexell_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_error err; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED); - - err = nexell_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer); - RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err); - - err = nexell_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage); - RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_nexell_output_data *output_data; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER); - - output_data = hwc_data->output_data; - RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - TDM_DBG(" ==============Validate================================="); - - /* adapt policy */ - _nexell_hwc_apply_policy(hwc_data, composited_wnds, num_wnds); - - *num_types = _nexell_hwc_get_changed_number(hwc_data); - - _print_validate_result(hwc_data, composited_wnds, num_wnds); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, - tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int num = 0; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER); - - if ((hwc_wnds == NULL) || (composition_types == NULL)) { - *num_elements = _nexell_hwc_get_changed_number(hwc_data); - return TDM_ERROR_NONE; - } - - LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { - if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE) - continue; - - if (num >= *num_elements) - break; - - if (hwc_window_data->client_type != hwc_window_data->validated_type) { - composition_types[num] = hwc_window_data->validated_type; - hwc_wnds[num] = hwc_window_data; - num++; - } - } - - /* set real num of changed composition types */ - *num_elements = num; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_accept_validation(tdm_hwc *hwc) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_error ret = TDM_ERROR_NONE; - - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - TDM_DBG(" ==============Accept Changes Done================================="); - - ret = _nexell_hwc_prepare_commit(hwc_data); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_commit(tdm_hwc *hwc, int sync, void *user_data) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - tdm_nexell_output_data *output_data = NULL; - tdm_error ret; - - RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); - - output_data = hwc_data->output_data; - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - TDM_DBG(" ==============COMMIT================================="); - - ret = nexell_output_commit(output_data, sync, user_data); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func) -{ - tdm_nexell_hwc_data *hwc_data = hwc; - - RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); - - hwc_data->commit_func = func; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_target_window_set_info(tdm_nexell_hwc_data *hwc_data, int width, int height) -{ - tdm_hwc_window_info info = {0}; - tdm_nexell_hwc_window_data *target_hwc_window; - tdm_error ret = TDM_ERROR_NONE; - - RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, TDM_ERROR_INVALID_PARAMETER); - - target_hwc_window = hwc_data->target_hwc_window; - - info.dst_pos.x = 0; - info.dst_pos.y = 0; - info.dst_pos.w = width; - info.dst_pos.h = height; - - info.src_config.pos.x = 0; - info.src_config.pos.y = 0; - info.src_config.pos.w = width; - info.src_config.pos.h = height; - - info.src_config.size.h = width; - info.src_config.size.v = height; - info.src_config.format = TBM_FORMAT_ARGB8888; - - ret = nexell_hwc_window_set_info(target_hwc_window, &info); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("set info target hwc window failed (%d)", ret); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_initailize_target_window(tdm_nexell_hwc_data *hwc_data) -{ - tdm_hwc_window_info info = {0}; - tdm_error ret = TDM_ERROR_NONE; - tdm_nexell_hwc_window_data *target_hwc_window; - - RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); - - info.dst_pos.x = 0; - info.dst_pos.y = 0; - info.dst_pos.w = 2; - info.dst_pos.h = 1; - - info.src_config.pos.x = 0; - info.src_config.pos.y = 0; - info.src_config.pos.w = 2; - info.src_config.pos.h = 1; - - info.src_config.size.h = 2; - info.src_config.size.v = 1; - info.src_config.format = TBM_FORMAT_ARGB8888; - - target_hwc_window = _nexell_hwc_create_window(hwc_data, &info, &ret); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("create target hwc window failed (%d)", ret); - return TDM_ERROR_OPERATION_FAILED; - } - - if (hwc_data->target_hwc_window) - nexell_hwc_window_destroy(hwc_data->target_hwc_window); - - hwc_data->target_hwc_window = target_hwc_window; - hwc_data->need_set_crtc = 1; - - return TDM_ERROR_NONE; -} diff --git a/src/libtdm-nexell/tdm_nexell_hwc.h b/src/libtdm-nexell/tdm_nexell_hwc.h deleted file mode 100644 index 84f424a..0000000 --- a/src/libtdm-nexell/tdm_nexell_hwc.h +++ /dev/null @@ -1,39 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _TDM_NEXELL_HWC_H_ -#define _TDM_NEXELL_HWC_H_ - -#include "tdm_nexell.h" - -tdm_error nexell_hwc_initailize_target_window(tdm_nexell_hwc_data *hwc_data); -tdm_error nexell_hwc_target_window_set_info(tdm_nexell_hwc_data *hwc_data, int width, int height); - -#endif /* _TDM_NEXELL_HWC_H_ */ diff --git a/src/libtdm-nexell/tdm_nexell_hwc_window.c b/src/libtdm-nexell/tdm_nexell_hwc_window.c deleted file mode 100644 index ffab416..0000000 --- a/src/libtdm-nexell/tdm_nexell_hwc_window.c +++ /dev/null @@ -1,270 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tdm_nexell.h" - -tbm_surface_queue_h -nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) -{ - tdm_nexell_hwc_data *hwc_data = NULL; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, NULL); - - hwc_data = hwc_window_data->hwc_data; - RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); - - if (error) - *error = TDM_ERROR_NONE; - - if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue >= NUM_LAYERS)) { - TDM_ERR("invliad hwc_window:%p lzpos_queue:%d", hwc_window_data, hwc_window_data->lzpos); - if (error) - *error = TDM_ERROR_OPERATION_FAILED; - - return NULL; - } - - if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue) { - tqueue = hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue; - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; - } else { - tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window, error); - if (!tqueue) { - TDM_ERR("fail to create buffer queue"); - return NULL; - } - - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue = tqueue; - hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; - } - - // target buffer queue can't be reset - if (hwc_window_data->lzpos_queue != ZPOS_1) { - width = tbm_surface_queue_get_width(tqueue); - height = tbm_surface_queue_get_height(tqueue); - - if ((hwc_window_data->info.src_config.pos.w != width) || - (hwc_window_data->info.src_config.pos.h != height)) - { - tbm_surface_queue_reset(tqueue, - hwc_window_data->info.src_config.pos.w, - hwc_window_data->info.src_config.pos.h, - hwc_window_data->info.src_config.format); - } - } - - return tqueue; -} - -void -nexell_hwc_window_release_buffer_queue(tdm_hwc_window *hwc_window, tbm_surface_queue_h queue) -{ - tdm_nexell_hwc_data *hwc_data = NULL; - tdm_nexell_hwc_window_data *hwc_window_data = NULL; - int i; - - hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; - RETURN_IF_FAIL(hwc_window_data != NULL); - - hwc_data = hwc_window_data->hwc_data; - RETURN_IF_FAIL(hwc_data != NULL); - - for (i = 0; i < NUM_LAYERS; i++) { - if (hwc_data->ui_buffer_queue[i].tqueue == queue) { - if (hwc_data->ui_buffer_queue[i].ref_cnt > 0) - hwc_data->ui_buffer_queue[i].ref_cnt--; - - if ((i != ZPOS_1) && (hwc_data->ui_buffer_queue[i].ref_cnt == 0)) { - tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->ui_buffer_queue[i].tqueue); - hwc_data->ui_buffer_queue[i].tqueue = NULL; - } - - break; - } - } -} - -void -nexell_hwc_window_destroy(tdm_hwc_window *hwc_window) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_IF_FAIL(hwc_window_data != NULL); - - LIST_DEL(&hwc_window_data->link); - - free(hwc_window_data); -} - -tdm_error -nexell_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, - tdm_hwc_window_composition comp_type) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - tdm_nexell_hwc_data *hwc_data = hwc_window_data->hwc_data; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - /* change the client_type when it is different from one which has before */ - if (hwc_window_data->client_type == comp_type) - return TDM_ERROR_NONE; - - hwc_window_data->client_type = comp_type; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - //TODO:: - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - tdm_nexell_hwc_data *hwc_data; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - hwc_data = hwc_window_data->hwc_data; - RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER); - - if (!memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info))) - return TDM_ERROR_NONE; - - hwc_window_data->info = *info; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - tdm_error err = TDM_ERROR_OPERATION_FAILED; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err); - - if (hwc_window_data->surface == surface) - return TDM_ERROR_NONE; - - hwc_window_data->surface = surface; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - //TODO: - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - //TODO: - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(constraints != NULL, TDM_ERROR_INVALID_PARAMETER); - - *constraints = hwc_window_data->constraints; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - if (!name) - return TDM_ERROR_NONE; - - snprintf(hwc_window_data->name, TDM_NAME_LEN, "%s", name); - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr) -{ - tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; - - RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - - hwc_window_data->cursor_img.width = width; - hwc_window_data->cursor_img.height = height; - hwc_window_data->cursor_img.stride = stride; - hwc_window_data->cursor_img.ptr = ptr; - - hwc_window_data->cursor_img_refresh = 1; - - return TDM_ERROR_NONE; -} diff --git a/src/libtdm-nexell/tdm_nexell_hwc_window.h b/src/libtdm-nexell/tdm_nexell_hwc_window.h deleted file mode 100644 index 393e3f6..0000000 --- a/src/libtdm-nexell/tdm_nexell_hwc_window.h +++ /dev/null @@ -1,36 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _TDM_NEXELL_HWC_WINDOW_H_ -#define _TDM_NEXELL_HWC_WINDOW_H_ - -#include "tdm_nexell.h" - -#endif /* _TDM_NEXELL_HWC_WINDOW_H_ */ diff --git a/src/libtdm-nexell/tdm_nexell_pp.c b/src/libtdm-nexell/tdm_nexell_pp.c deleted file mode 100644 index 64e30bc..0000000 --- a/src/libtdm-nexell/tdm_nexell_pp.c +++ /dev/null @@ -1,375 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "tdm_nexell.h" - -typedef struct _tdm_nexell_pp_buffer { - tbm_surface_h src; - tbm_surface_h dst; - - struct list_head link; -} tdm_nexell_pp_buffer; - -typedef struct _tdm_nexell_pp_data { - tdm_nexell_data *nexell_data; - - tdm_info_pp info; - - struct list_head pending_buffer_list; - - tdm_pp_done_handler done_func; - void *done_user_data; - - struct list_head link; -} tdm_nexell_pp_data; - -#define MAX_PLANE_NUM 3 - -struct rect { - int x; - int y; - int width; - int height; -}; - -typedef struct _tdm_nexell_scaler_context { - int src_plane_num; - int src_fds[MAX_PLANE_NUM]; - int src_stride[MAX_PLANE_NUM]; - unsigned int src_width; - unsigned int src_height; - unsigned int src_code; - - int dst_plane_num; - int dst_fds[MAX_PLANE_NUM]; - int dst_stride[MAX_PLANE_NUM]; - unsigned int dst_width; - unsigned int dst_height; - unsigned int dst_code; - - struct rect crop; -} tdm_nexell_scaler_context; - -static tbm_format pp_formats[] = { - TBM_FORMAT_YUV420 -}; - -#define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0])) -#define IOC_NX_MAGIC 0x6e78 /* nx */ -enum { - IOCTL_SCALER_SET_AND_RUN = _IO(IOC_NX_MAGIC, 1), -}; - -#ifndef ALIGN -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#endif - -static int pp_list_init; -static struct list_head pp_list; - -static int -_tdm_drm_ioctl(int fd, unsigned long request, void *arg) -{ - int ret; - - do { - ret = ioctl(fd, request, arg); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - - return ret; -} - -static int -_tdm_gem_to_dmafd(int drm_fd, int gem_fd) -{ - int ret; - struct drm_prime_handle arg = {0, }; - - arg.handle = gem_fd; - ret = _tdm_drm_ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg); - if (0 != ret) { - return -1; - } - return arg.fd; -} - -static tdm_error -_tdm_nexell_pp_convert(tdm_nexell_pp_buffer *buffer, tdm_info_pp *info, int drm_fd, int scaler_fd) -{ - tdm_nexell_scaler_context ctx; - unsigned int src_y_stride; - unsigned int src_c_stride; - unsigned int dst_y_stride; - unsigned int dst_c_stride; - tbm_bo bo_src = NULL; - tbm_bo bo_dst = NULL; - __u32 handle_src; - __u32 handle_dst; - - bo_src = tbm_surface_internal_get_bo(buffer->src, 0); - RETURN_VAL_IF_FAIL(bo_src != NULL, TDM_ERROR_OPERATION_FAILED); - handle_src = (__u32)tbm_bo_get_handle(bo_src, TBM_DEVICE_DEFAULT).u32; - ctx.src_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_src); - RETURN_VAL_IF_FAIL(ctx.src_fds[0] >= 0, TDM_ERROR_OPERATION_FAILED); - - ctx.src_fds[1] = ctx.src_fds[0]; - ctx.src_fds[2] = ctx.src_fds[0]; - - bo_dst = tbm_surface_internal_get_bo(buffer->dst, 0); - if (bo_dst == NULL) { - close(ctx.src_fds[0]); - return TDM_ERROR_OPERATION_FAILED; - } - handle_dst = (__u32)tbm_bo_get_handle(bo_dst, TBM_DEVICE_DEFAULT).u32; - ctx.dst_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_dst); - if (ctx.dst_fds[0] < 0) { - close(ctx.src_fds[0]); - return TDM_ERROR_OPERATION_FAILED; - } - - ctx.dst_fds[1] = ctx.dst_fds[0]; - ctx.dst_fds[2] = ctx.dst_fds[0]; - - src_y_stride = ALIGN(info->src_config.size.h, 32); - src_c_stride = ALIGN(src_y_stride >> 1, 16); - dst_y_stride = ALIGN(info->dst_config.size.h, 8); - dst_c_stride = ALIGN(dst_y_stride >> 1, 4); - - ctx.src_plane_num = 1; - ctx.src_width = info->src_config.size.h; - ctx.src_height = info->src_config.size.v; - ctx.src_code = MEDIA_BUS_FMT_YUYV8_2X8; - ctx.src_stride[0] = src_y_stride; - ctx.src_stride[1] = src_c_stride; - ctx.src_stride[2] = src_c_stride; - - ctx.dst_plane_num = 1; - ctx.dst_width = info->dst_config.size.h; - ctx.dst_height = info->dst_config.size.v; - ctx.dst_code = MEDIA_BUS_FMT_YUYV8_2X8; - ctx.dst_stride[0] = dst_y_stride; - ctx.dst_stride[1] = dst_c_stride; - ctx.dst_stride[2] = dst_c_stride; - - ctx.crop.x = info->src_config.pos.x; - ctx.crop.y = info->src_config.pos.y; - ctx.crop.width = info->src_config.pos.w; - ctx.crop.height = info->src_config.pos.h; - - TDM_DBG("pp %p(%d, %d). src(%dx%d, (%d,%d,%d) (%d,%d,%d)) dst(%dx%d, (%d,%d,%d) (%d,%d,%d)) crop(%dx%d, %dx%d)", info, drm_fd, scaler_fd, - ctx.src_width, ctx.src_height, ctx.src_stride[0], ctx.src_stride[1], ctx.src_stride[2], ctx.src_fds[0], ctx.src_fds[1], ctx.src_fds[2], - ctx.dst_width, ctx.dst_height, ctx.dst_stride[0], ctx.dst_stride[1], ctx.dst_stride[2], ctx.dst_fds[0], ctx.dst_fds[1], ctx.dst_fds[2], - ctx.crop.x, ctx.crop.y, ctx.crop.width, ctx.crop.height); - - if (ioctl(scaler_fd, IOCTL_SCALER_SET_AND_RUN, &ctx) < 0) { - TDM_ERR("IOCTL_SCALER_SET_AND_RUN failed"); - } - - close(ctx.src_fds[0]); - close(ctx.dst_fds[0]); - - return TDM_ERROR_NONE; -} - -tdm_error -tdm_nexell_pp_get_capability(tdm_nexell_data *nexell_data, tdm_caps_pp *caps) -{ - int i; - - if (!caps) { - TDM_ERR("invalid params"); - return TDM_ERROR_INVALID_PARAMETER; - } - - if (nexell_data->scaler_fd < 0 ) { - TDM_ERR("no scaler_fd. not support pp."); - return TDM_ERROR_BAD_MODULE; - } - - caps->capabilities = TDM_PP_CAPABILITY_SYNC | TDM_PP_CAPABILITY_SCANOUT | TDM_PP_CAPABILITY_NO_TRANSFORM_ROTATION; - - caps->format_count = NUM_PP_FORMAT; - - /* will be freed in frontend */ - caps->formats = calloc(1, sizeof pp_formats); - if (!caps->formats) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - for (i = 0; i < caps->format_count; i++) - caps->formats[i] = pp_formats[i]; - - caps->min_w = 16; - caps->min_h = 8; - caps->max_w = -1; /* not defined */ - caps->max_h = -1; - caps->preferred_align = 32; - - return TDM_ERROR_NONE; -} - -tdm_pp * -tdm_nexell_pp_create(tdm_nexell_data *nexell_data, tdm_error *error) -{ - tdm_nexell_pp_data *pp_data = NULL; - - if (nexell_data->scaler_fd < 0 ) { - TDM_ERR("no scaler_fd."); - if (error) - *error = TDM_ERROR_BAD_MODULE; - return NULL; - } - - pp_data = calloc(1, sizeof(tdm_nexell_pp_data)); - if (!pp_data) { - TDM_ERR("alloc failed"); - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - - pp_data->nexell_data = nexell_data; - - LIST_INITHEAD(&pp_data->pending_buffer_list); - - if (!pp_list_init) { - pp_list_init = 1; - LIST_INITHEAD(&pp_list); - } - LIST_ADDTAIL(&pp_data->link, &pp_list); - - return pp_data; -} - -void -nexell_pp_destroy(tdm_pp *pp) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *b = NULL, *bb = NULL; - - if (!pp_data) - return; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { - LIST_DEL(&b->link); - free(b); - } - - LIST_DEL(&pp_data->link); - - free(pp_data); -} - -tdm_error -nexell_pp_set_info(tdm_pp *pp, tdm_info_pp *info) -{ - tdm_nexell_pp_data *pp_data = pp; - - RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER); - - pp_data->info = *info; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *buffer; - - RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(src, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(dst, TDM_ERROR_INVALID_PARAMETER); - - buffer = calloc(1, sizeof(tdm_nexell_pp_buffer)); - if (!buffer) { - TDM_ERR("alloc failed"); - return TDM_ERROR_NONE; - } - - LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list); - - buffer->src = src; - buffer->dst = dst; - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_pp_commit(tdm_pp *pp) -{ - tdm_nexell_pp_data *pp_data = pp; - tdm_nexell_pp_buffer *b = NULL, *bb = NULL; - tdm_nexell_data *nexell_data; - tdm_error ret; - - RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER); - - nexell_data = pp_data->nexell_data; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { - LIST_DEL(&b->link); - - ret = _tdm_nexell_pp_convert(b, &pp_data->info, nexell_data->drm_fd, nexell_data->scaler_fd); - RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); - - if (pp_data->done_func) - pp_data->done_func(pp_data, - b->src, - b->dst, - pp_data->done_user_data); - free(b); - } - - return TDM_ERROR_NONE; -} - -tdm_error -nexell_pp_set_done_handler(tdm_pp *pp, tdm_pp_done_handler func, void *user_data) -{ - tdm_nexell_pp_data *pp_data = pp; - - RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); - - pp_data->done_func = func; - pp_data->done_user_data = user_data; - - return TDM_ERROR_NONE; -} diff --git a/src/libtdm-nexell/tdm_nexell_pp.h b/src/libtdm-nexell/tdm_nexell_pp.h deleted file mode 100644 index 085d059..0000000 --- a/src/libtdm-nexell/tdm_nexell_pp.h +++ /dev/null @@ -1,43 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _TDM_NEXELL_PP_H_ -#define _TDM_NEXELL_PP_H_ - -#include "tdm_nexell.h" - -tdm_error tdm_nexell_pp_get_capability(tdm_nexell_data *nexell_data, tdm_caps_pp *caps); -tdm_pp* tdm_nexell_pp_create(tdm_nexell_data *nexell_data, tdm_error *error); -void tdm_nexell_pp_handler(unsigned int prop_id, unsigned int *buf_idx, - unsigned int tv_sec, unsigned int tv_usec, void *data); -void tdm_nexell_pp_cb(int fd, unsigned int prop_id, unsigned int *buf_idx, - unsigned int tv_sec, unsigned int tv_usec, - void *user_data); -#endif /* _TDM_NEXELL_PP_H_ */ diff --git a/src/libtdm-nexell/tdm_nexell_types.h b/src/libtdm-nexell/tdm_nexell_types.h deleted file mode 100644 index 25efc95..0000000 --- a/src/libtdm-nexell/tdm_nexell_types.h +++ /dev/null @@ -1,323 +0,0 @@ -/************************************************************************** - -libtdm_nexell - -Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -#ifndef _TDM_NEXELL_TYPES_H_ -#define _TDM_NEXELL_TYPES_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if HAVE_UDEV -#include -#endif - -#define C(b, m) (((b) >> (m)) & 0xFF) -#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s)) -#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0)) -#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24) - -#define IS_RGB(format) (format == TBM_FORMAT_XRGB8888 || format == TBM_FORMAT_ARGB8888 || \ - format == TBM_FORMAT_XBGR8888 || format == TBM_FORMAT_ABGR8888) - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define SWAP(a, b) ({int t; t = a; a = b; b = t; }) -#define ROUNDUP(x) (ceil(floor((float)(height) / 4))) - -#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4) -#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) -#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) -#define ALIGN_TO_2KB(x) ((((x) + (1 << 11) - 1) >> 11) << 11) -#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) -#define ALIGN_TO_64KB(x) ((((x) + (1 << 16) - 1) >> 16) << 16) - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -#define NUM_BUFFERS 3 - -#define NUM_LAYERS 3 -#define NUM_UI_LAYERS 2 -#define ZPOS_MAX 2 -#define ZPOS_CURSOR 2 // cursor -#define ZPOS_2 2 // ui -#define ZPOS_1 1 // ui, primary layer -#define ZPOS_0 0 // video -#define ZPOS_VIDEO1 0 // video -#define ZPOS_NONE -999 - -#define RETURN_VAL_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_ERR("'%s' failed", #cond);\ - return val;\ - } \ -} - -#define RETURN_IF_FAIL(cond) {\ - if (!(cond)) {\ - TDM_ERR("'%s' failed", #cond);\ - return;\ - } \ -} - -#define GOTO_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_ERR("'%s' failed", #cond);\ - goto val;\ - } \ -} - -typedef struct _tdm_nexell_data tdm_nexell_data; -typedef struct _tdm_nexell_output_data tdm_nexell_output_data; -typedef struct _tdm_nexell_layer_data tdm_nexell_layer_data; -typedef struct _tdm_nexell_hwc_data tdm_nexell_hwc_data; -typedef struct _tdm_nexell_hwc_window_data tdm_nexell_hwc_window_data; -typedef struct _tdm_nexell_event_data tdm_nexell_event_data; -typedef struct _tdm_nexell_display_buffer tdm_nexell_display_buffer; - -typedef enum { - TDM_NEXELL_EVENT_TYPE_WAIT, - TDM_NEXELL_EVENT_TYPE_COMMIT, - TDM_NEXELL_EVENT_TYPE_PAGEFLIP, -} tdm_nexell_event_type; - -struct _tdm_nexell_data -{ - tdm_display *dpy; - - int drm_fd; - int scaler_fd; - -#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 - int has_universal_plane; - int has_atomic; -#endif - -#if HAVE_UDEV - struct udev_monitor *uevent_monitor; - tdm_event_loop_source *uevent_source; -#endif - - drmModeResPtr mode_res; - drmModePlaneResPtr plane_res; - - int hwc_mode; - - struct list_head output_list; - struct list_head buffer_list; -}; - -struct _tdm_nexell_display_buffer { - struct list_head link; - - unsigned int fb_id; - tbm_surface_h buffer; - int width; - unsigned int height; - unsigned int format; - unsigned int handles[4]; - unsigned int fds[4]; - unsigned int pitches[4]; - unsigned int offsets[4]; - unsigned int size; - unsigned int count; -}; - -struct _tdm_nexell_event_data { - tdm_nexell_event_type type; - tdm_nexell_output_data *output_data; - void *user_data; -}; - -struct display_properties_ids { - uint32_t connector_crtc_id; - uint32_t crtc_mode_id; - uint32_t crtc_active; - uint32_t plane_fb_id; - uint32_t plane_crtc_id; - uint32_t plane_src_x; - uint32_t plane_src_y; - uint32_t plane_src_w; - uint32_t plane_src_h; - uint32_t plane_crtc_x; - uint32_t plane_crtc_y; - uint32_t plane_crtc_w; - uint32_t plane_crtc_h; - uint32_t plane_zpos; -}; - -struct _tdm_nexell_output_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_nexell_data *nexell_data; - uint32_t connector_id; - uint32_t encoder_id; - uint32_t crtc_id; - uint32_t pipe; - uint32_t dpms_prop_id; - int count_modes; - drmModeModeInfoPtr drm_modes; - tdm_output_mode *output_modes; - tdm_output_type connector_type; - unsigned int connector_type_id; - struct list_head layer_list; - tdm_nexell_layer_data *primary_layer; - - /* not fixed data below */ - tdm_output_vblank_handler vblank_func; - tdm_output_commit_handler commit_func; - - tdm_output_conn_status status; - tdm_output_status_handler status_func; - void *status_user_data; - - int mode_changed; - const tdm_output_mode *current_mode; - - struct display_properties_ids props; - - int crtc_enabled; - - /* atomic prop ids*/ - struct { - uint32_t crtc_id; - uint32_t crtc_mode_id; - uint32_t crtc_active; - } atomic_props_ids; - - /* hwc */ - int hwc_enable; - tdm_nexell_hwc_data *hwc_data; -}; - -struct _tdm_nexell_layer_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_nexell_data *nexell_data; - tdm_nexell_output_data *output_data; - uint32_t plane_id; - tdm_layer_capability capabilities; - int zpos; - - /* not fixed data below */ - tdm_info_layer info; - int info_changed; - - tdm_nexell_display_buffer *display_buffer; - int display_buffer_changed; - - /* atomic prop ids*/ - struct { - uint32_t fb_id; - uint32_t crtc_id; - uint32_t src_x; - uint32_t src_y; - uint32_t src_w; - uint32_t src_h; - uint32_t crtc_x; - uint32_t crtc_y; - uint32_t crtc_w; - uint32_t crtc_h; - uint32_t zpos; - } atomic_props_ids; -}; - -struct _tdm_nexell_hwc_data { - tdm_nexell_hwc_window_data *target_hwc_window; - - int need_validate; - int need_target_window; - int need_set_crtc; - - int target_window_zpos; - - tdm_nexell_output_data *output_data; - struct list_head hwc_window_list; - - tbm_surface_queue_h cursor_tqueue; - tbm_surface_h cursor_tsurface; - - /* UI buffer_queue list for the reserved scanout memory */ - struct { - tbm_surface_queue_h tqueue; - int ref_cnt; - } ui_buffer_queue[NUM_LAYERS]; - - tdm_hwc_commit_handler commit_func; -}; - -struct _tdm_nexell_hwc_window_data { - struct list_head link; - - tdm_nexell_hwc_data *hwc_data; - - tdm_hwc_window_info info; - tbm_surface_h surface; - tdm_hwc_window_composition client_type; - tdm_hwc_window_composition validated_type; - int lzpos; - int lzpos_queue; - - char name[TDM_NAME_LEN]; - struct { - int width; - int height; - int stride; - void *ptr; - } cursor_img; - int cursor_img_surface; - int cursor_img_refresh; - - int constraints; -}; - -#endif /* _TDM_NEXELL_TYPES_H_ */ diff --git a/src/tdm_backend_list.h b/src/tdm_backend_list.h new file mode 100644 index 0000000..3873817 --- /dev/null +++ b/src/tdm_backend_list.h @@ -0,0 +1,170 @@ +/* + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_ + +#include + +struct list_head { + struct list_head *prev; + struct list_head *next; +}; + +static inline void list_inithead(struct list_head *item) +{ + item->prev = item; + item->next = item; +} + +static inline void list_add(struct list_head *item, struct list_head *list) +{ + item->prev = list; + item->next = list->next; + list->next->prev = item; + list->next = item; +} + +static inline void list_addtail(struct list_head *item, struct list_head *list) +{ + item->next = list; + item->prev = list->prev; + list->prev->next = item; + list->prev = item; +} + +static inline void list_replace(struct list_head *from, struct list_head *to) +{ + to->prev = from->prev; + to->next = from->next; + from->next->prev = to; + from->prev->next = to; +} + +static inline void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +static inline void list_delinit(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; + item->next = item; + item->prev = item; +} + +static inline int list_length(struct list_head *item) +{ + struct list_head *next; + int length = 0; + + next = item->next; + while (next != item) { + length++; + next = next->next; + } + + return length; +} + +#define LIST_INITHEAD(__item) list_inithead(__item) +#define LIST_ADD(__item, __list) list_add(__item, __list) +#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) +#define LIST_REPLACE(__from, __to) list_replace(__from, __to) +#define LIST_DEL(__item) list_del(__item) +#define LIST_DELINIT(__item) list_delinit(__item) +#define LIST_LENGTH(__item) list_length(__item) + +#define LIST_ENTRY(__type, __item, __field) \ + ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + +#define LIST_FIRST_ENTRY(__ptr, __type, __field) \ + LIST_ENTRY(__type, (__ptr)->next, __field) + +#define LIST_LAST_ENTRY(__ptr, __type, __field) \ + LIST_ENTRY(__type, (__ptr)->prev, __field) + +#define LIST_IS_EMPTY(__list) \ + ((__list)->next == (__list)) + +#ifndef container_of +#define container_of(ptr, sample, member) \ + (void *)((char *)(ptr) \ + - ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define LIST_FOR_EACH_ENTRY(pos, head, member) \ + for (pos = container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_REV(pos, head, member) \ + for (pos = container_of((head)->prev, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.prev, pos, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ + for (pos = container_of((head)->next, pos, member), \ + storage = container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.next, storage, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ + for (pos = container_of((head)->prev, pos, member), \ + storage = container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.prev, storage, member)) + +#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.prev, pos, member)) + +#define LIST_FIND_ITEM(item, head, type, member, found) \ + do { \ + type *pos = NULL; \ + found = NULL; \ + LIST_FOR_EACH_ENTRY(pos, head, member) \ + if (pos == item) { found = item; break; } \ + } while (0) + +#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/src/tdm_backend_log.c b/src/tdm_backend_log.c new file mode 100644 index 0000000..31d1b83 --- /dev/null +++ b/src/tdm_backend_log.c @@ -0,0 +1,73 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "tdm_backend_log.h" + +#undef LOG_TAG +#define LOG_TAG "HAL_TDM_BACKEND" + +unsigned int tbm_log_debug_level = TDM_BACKEND_LOG_LEVEL_INFO; + +static void +_tdm_backend_log_dlog_print(int level, const char *fmt, va_list arg) +{ + log_priority dlog_prio; + + switch (level) { + case TDM_BACKEND_LOG_LEVEL_ERR: + dlog_prio = DLOG_ERROR; + break; + case TDM_BACKEND_LOG_LEVEL_WRN: + dlog_prio = DLOG_WARN; + break; + case TDM_BACKEND_LOG_LEVEL_INFO: + dlog_prio = DLOG_INFO; + break; + case TDM_BACKEND_LOG_LEVEL_DBG: + dlog_prio = DLOG_DEBUG; + break; + default: + return; + } + __dlog_vprint(LOG_ID_SYSTEM, dlog_prio, LOG_TAG, fmt, arg); +} + +void +tdm_backend_log_print(int level, const char *fmt, ...) +{ + va_list arg; + + if (level > tbm_log_debug_level) + return; + + va_start(arg, fmt); + _tdm_backend_log_dlog_print(level, fmt, arg); + va_end(arg); +} diff --git a/src/tdm_backend_log.h b/src/tdm_backend_log.h new file mode 100644 index 0000000..ec76eff --- /dev/null +++ b/src/tdm_backend_log.h @@ -0,0 +1,106 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __TDM_BACKEND_LOG_H__ +#define __TDM_BACKEND_LOG_H__ + +#include +#include +#include +#include + +enum { + TDM_BACKEND_LOG_LEVEL_NONE, + TDM_BACKEND_LOG_LEVEL_ERR, + TDM_BACKEND_LOG_LEVEL_WRN, + TDM_BACKEND_LOG_LEVEL_INFO, + TDM_BACKEND_LOG_LEVEL_DBG, +}; + + +/* log level */ +void tdm_backend_log_print(int level, const char *fmt, ...); + +#define TDM_BACKEND_DBG(fmt, args...) \ + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_DBG, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) + +#define TDM_BACKEND_INFO(fmt, args...) \ + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) + +#define TDM_BACKEND_WRN(fmt, args...) \ + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_WRN, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) + +#define TDM_BACKEND_ERR(fmt, args...) \ + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_backend_log_print(TDM_BACKEND_LOG_LEVEL_ERR, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) + +#define TDM_BACKEND_RETURN_IF_FAIL(cond) {\ + if (!(cond)) {\ + TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ + return;\ + } \ +} +#define TDM_BACKEND_RETURN_VAL_IF_FAIL(cond, val) {\ + if (!(cond)) {\ + TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ + return val;\ + } \ +} +#define TDM_BACKEND_GOTO_VAL_IF_FAIL(cond, val) {\ + if (!(cond)) {\ + TDM_BACKEND_ERR("'%s' failed.\n", #cond);\ + goto val;\ + } \ +} + +#endif /* __TDM_BACKEND_LOG_H__ */ \ No newline at end of file diff --git a/src/tdm_backend_nexell.c b/src/tdm_backend_nexell.c new file mode 100644 index 0000000..a041159 --- /dev/null +++ b/src/tdm_backend_nexell.c @@ -0,0 +1,585 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +#if HAVE_UDEV +#include +#endif + +#define ENABLE_PP +#define HAL_TDM_NEXELL_ENABLE_HWC 1 + +#define HAL_TDM_NEXELL_NAME "nexell" + +#ifdef HAVE_UDEV +static struct udev_device * +_tdm_find_primary_gpu(void) +{ + struct udev *udev; + struct udev_enumerate *e; + struct udev_list_entry *entry; + const char *path, *id; + struct udev_device *device, *drm_device, *pci; + + udev = udev_new(); + if (!udev) { + TDM_BACKEND_ERR("fail to initialize udev context\n"); + return NULL; + } + + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "drm"); + udev_enumerate_add_match_sysname(e, "card[0-9]*"); + + udev_enumerate_scan_devices(e); + drm_device = NULL; + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + path = udev_list_entry_get_name(entry); + device = udev_device_new_from_syspath(udev, path); + if (!device) + continue; + + pci = udev_device_get_parent_with_subsystem_devtype(device, "pci", NULL); + if (pci) { + id = udev_device_get_sysattr_value(pci, "boot_vga"); + if (id && !strcmp(id, "1")) { + if (drm_device) + udev_device_unref(drm_device); + drm_device = device; + break; + } + } + + if (!drm_device) + drm_device = device; + else + udev_device_unref(device); + } + + udev_enumerate_unref(e); + + return drm_device; +} + +static hal_tdm_error +_tdm_nexell_udev_fd_handler(int fd, hal_tdm_event_loop_mask mask, void *user_data) +{ + tdm_nexell_display *display_data = (tdm_nexell_display*)user_data; + struct udev_device *dev; + const char *hotplug; + struct stat s; + dev_t udev_devnum; + int ret; + + dev = udev_monitor_receive_device(display_data->uevent_monitor); + if (!dev) { + TDM_BACKEND_ERR("couldn't receive device"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + udev_devnum = udev_device_get_devnum(dev); + + ret = fstat(display_data->drm_fd, &s); + if (ret == -1) { + TDM_BACKEND_ERR("fstat failed"); + udev_device_unref(dev); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + hotplug = udev_device_get_property_value(dev, "HOTPLUG"); + + if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && + hotplug && atoi(hotplug) == 1) + { + TDM_BACKEND_INFO("HotPlug"); + tdm_nexell_display_update_output_status(display_data); + } + + udev_device_unref(dev); + + return HAL_TDM_ERROR_NONE; +} + +static struct udev_monitor * +_tdm_nexell_create_udev_monitor() +{ + struct udev *u = NULL; + struct udev_monitor *mon = NULL; + + u = udev_new(); + if (!u) { + TDM_BACKEND_ERR("couldn't create udev"); + goto failed; + } + + mon = udev_monitor_new_from_netlink(u, "udev"); + if (!mon) { + TDM_BACKEND_ERR("couldn't create udev monitor"); + goto failed; + } + + if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 || + udev_monitor_enable_receiving(mon) < 0) { + TDM_BACKEND_ERR("add match subsystem failed"); + goto failed; + } + + TDM_BACKEND_INFO("hotplug monitor created"); + + return mon; + +failed: + if (mon) + udev_monitor_unref(mon); + if (u) + udev_unref(u); + + return NULL; +} + +static void +_tdm_nexell_destroy_udev_monitor(struct udev_monitor *mon) +{ + struct udev *u; + + if (!mon) + return; + + u = udev_monitor_get_udev(mon); + udev_monitor_unref(mon); + udev_unref(u); + + TDM_BACKEND_INFO("hotplug monitor destroyed"); +} +#endif + +static int +_tdm_nexell_open_drm(void) +{ + int fd = -1; + + fd = drmOpen(HAL_TDM_NEXELL_NAME, NULL); + if (fd < 0) + TDM_BACKEND_WRN("Cannot open '%s' drm", HAL_TDM_NEXELL_NAME); + +#ifdef HAVE_UDEV + if (fd < 0) { + struct udev_device *drm_device = NULL; + const char *filename; + TDM_BACKEND_WRN("Cannot open drm device.. search by udev"); + + drm_device = _tdm_find_primary_gpu(); + if (drm_device == NULL) { + TDM_BACKEND_ERR("fail to find drm device\n"); + goto close_l; + } + + filename = udev_device_get_devnode(drm_device); + + fd = open(filename, O_RDWR | O_CLOEXEC); + if (fd < 0) + TDM_BACKEND_ERR("Cannot open drm device(%s)\n", filename); + + TDM_BACKEND_DBG("open drm device (name:%s, fd:%d)", filename, fd); + + udev_device_unref(drm_device); + } +close_l: +#endif + + return fd; +} + +static void +_tdm_nexell_display_deinitialize(tdm_nexell_display *display_data) +{ + tdm_nexell_display_destroy_output_list(display_data); + tdm_nexell_display_destroy_buffer_list(display_data); + + if (display_data->plane_res) + drmModeFreePlaneResources(display_data->plane_res); + if (display_data->mode_res) + drmModeFreeResources(display_data->mode_res); +} + +static hal_tdm_error +_tdm_nexell_display_initialize(tdm_nexell_display *display_data) +{ + hal_tdm_error ret; + + display_data->scaler_fd = open("/dev/scaler", O_RDWR); + if (display_data->scaler_fd < 0) + TDM_BACKEND_ERR("scaler open fail. cannot use pp."); + +#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 + if (drmSetClientCap(display_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { + TDM_BACKEND_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed"); + } else { + TDM_BACKEND_INFO("has universal planes"); + display_data->has_universal_plane = 1; + } + + if (drmSetClientCap(display_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) { + TDM_BACKEND_WRN("Set DRM_CLIENT_CAP_ATOMIC failed"); + } else { + TDM_BACKEND_INFO("has atomic"); + display_data->has_atomic = 1; + } +#endif + + display_data->mode_res = drmModeGetResources(display_data->drm_fd); + if (!display_data->mode_res) { + TDM_BACKEND_ERR("no drm resource: %m"); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed; + } + + display_data->plane_res = drmModeGetPlaneResources(display_data->drm_fd); + if (!display_data->plane_res) { + TDM_BACKEND_ERR("no drm plane resource: %m"); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed; + } + + if (display_data->plane_res->count_planes <= 0) { + TDM_BACKEND_ERR("no drm plane resource"); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed; + } + + ret = tdm_nexell_display_create_output_list(display_data); + if (ret != HAL_TDM_ERROR_NONE) + goto failed; + + ret = tdm_nexell_display_create_layer_list(display_data); + if (ret != HAL_TDM_ERROR_NONE) + goto failed; + + return ret; + +failed: + _tdm_nexell_display_deinitialize(display_data); + + return ret; +} + +static hal_tdm_error +_tdm_nexell_master_drm_fd_handler(hal_tdm_fd master_drm_fd, void *user_data) +{ + tdm_nexell_display *display_data = (tdm_nexell_display *) user_data; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data->drm_fd = master_drm_fd; + TDM_BACKEND_INFO("Get the master drm_fd(%d)!\n", display_data->drm_fd); + + // initialize display with a master drm_fd + ret = _tdm_nexell_display_initialize(display_data); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("fail to _tdm_nexell_display_initialize!\n"); + + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +int +hal_backend_tdm_nexell_exit(void *data) +{ + hal_tdm_backend_data *backend_data = (hal_tdm_backend_data *)data; + tdm_nexell_display *display_data; + + TDM_BACKEND_INFO("deinit"); + + TDM_BACKEND_RETURN_VAL_IF_FAIL(backend_data != NULL, -1); + + display_data = (tdm_nexell_display *)backend_data->display; + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, -1); + + if (backend_data->pp_funcs) { + free(backend_data->pp_funcs); + backend_data->pp_funcs = NULL; + } + if (backend_data->hwc_window_funcs) { + free(backend_data->hwc_window_funcs); + backend_data->hwc_window_funcs = NULL; + } + if (backend_data->hwc_funcs) { + free(backend_data->hwc_funcs); + backend_data->hwc_funcs = NULL; + } + if (backend_data->output_funcs) { + free(backend_data->output_funcs); + backend_data->output_funcs = NULL; + } + if (backend_data->display_funcs) { + free(backend_data->display_funcs); + backend_data->display_funcs = NULL; + } + + _tdm_nexell_display_deinitialize(display_data); + +#ifdef HAVE_UDEV + if (display_data->uevent_monitor) + _tdm_nexell_destroy_udev_monitor(display_data->uevent_monitor); +#endif + + if (display_data->drm_fd >= 0) + close(display_data->drm_fd); + + free(display_data); + free(backend_data); + + return HAL_TDM_ERROR_NONE; +} + +static int +hal_backend_tdm_nexell_init(void **data) +{ + hal_tdm_backend_data *backend_data = NULL; + hal_tdm_display_funcs *display_funcs = NULL; + hal_tdm_output_funcs *output_funcs = NULL; + hal_tdm_hwc_funcs *hwc_funcs = NULL; + hal_tdm_hwc_window_funcs *hwc_window_funcs = NULL; +#ifdef ENABLE_PP + hal_tdm_pp_funcs *pp_funcs = NULL; +#endif + tdm_nexell_display *display_data = NULL; + hal_tdm_error ret; + int drm_fd; +#ifdef HAVE_UDEV + static struct udev_monitor *mon; + hal_tdm_event_source *udev_event_source; +#endif + + /* allocate a hal_tdm_backend_data */ + backend_data = calloc(1, sizeof(struct _hal_tdm_backend_data)); + if (!backend_data) { + TDM_BACKEND_ERR("fail to alloc backend_data!\n"); + *data = NULL; + return -1; + } + *data = backend_data; + + /* allocate a hal_tdm_display */ + display_data = calloc(1, sizeof(struct _tdm_nexell_display)); + if (!display_data) { + TDM_BACKEND_ERR("fail to alloc display_data!\n"); + goto failed; + } + backend_data->display = (hal_tdm_display *)display_data; + + LIST_INITHEAD(&display_data->output_list); + LIST_INITHEAD(&display_data->buffer_list); + + // check if drm_fd is master fd. + drm_fd = _tdm_nexell_open_drm(); + if (drm_fd < 0) { + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed; + } + + // set true when backend has a drm_device. + backend_data->has_drm_device = 1; + + if (drmIsMaster(drm_fd)) { + // drm_fd is a master drm_fd. + backend_data->drm_info.drm_fd = drm_fd; + backend_data->drm_info.is_master = 1; + + display_data->drm_fd = drm_fd; + TDM_BACKEND_INFO("Get the master drm_fd(%d)!\n", display_data->drm_fd); + + // initialize display with a master drm_fd + ret = _tdm_nexell_display_initialize(display_data); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("fail to _tdm_nexell_display_initialize!\n"); + goto failed; + } + } else { + // drm_fd is not a master drm_fd. + // request a master drm_fd + close(drm_fd); + backend_data->drm_info.drm_fd = -1; + backend_data->drm_info.is_master = 0; + backend_data->drm_info.master_drm_fd_func = _tdm_nexell_master_drm_fd_handler; + backend_data->drm_info.user_data = display_data; + + TDM_BACKEND_INFO("A backend requests an master drm_fd.\n"); + } + +#ifdef HAVE_UDEV + mon = _tdm_nexell_create_udev_monitor(); + if (!mon) { + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed; + } + display_data->uevent_monitor = mon; + + /* alloc and register udev_event_source */ + udev_event_source = calloc(1, sizeof(struct _hal_tdm_event_source)); + if (!udev_event_source) { + TDM_BACKEND_ERR("fail to alloc udev_event_source!\n"); + goto failed; + } + udev_event_source->event_fd = udev_monitor_get_fd(mon); + udev_event_source->func = _tdm_nexell_udev_fd_handler; + udev_event_source->user_data = display_data; + + backend_data->event_sources[0] = udev_event_source; + backend_data->num_event_sources++; +#endif + + /* alloc and register display_funcs */ + display_funcs = calloc(1, sizeof(struct _hal_tdm_display_funcs)); + if (!display_funcs) { + TDM_BACKEND_ERR("fail to alloc display_funcs!\n"); + goto failed; + } + backend_data->display_funcs = display_funcs; + + display_funcs->display_get_capability = nexell_display_get_capability; + display_funcs->display_get_pp_capability = nexell_display_get_pp_capability; + display_funcs->display_get_outputs = nexell_display_get_outputs; + display_funcs->display_get_fd = nexell_display_get_fd; + display_funcs->display_handle_events = nexell_display_handle_events; + display_funcs->display_create_pp = nexell_display_create_pp; + + /* alloc and register output_funcs */ + output_funcs = calloc(1, sizeof(struct _hal_tdm_output_funcs)); + if (!output_funcs) { + TDM_BACKEND_ERR("fail to alloc output_funcs!\n"); + goto failed; + } + backend_data->output_funcs = output_funcs; + + output_funcs->output_get_capability = nexell_output_get_capability; + output_funcs->output_set_property = nexell_output_set_property; + output_funcs->output_get_property = nexell_output_get_property; + output_funcs->output_wait_vblank = nexell_output_wait_vblank; + output_funcs->output_set_vblank_handler = nexell_output_set_vblank_handler; + output_funcs->output_set_dpms = nexell_output_set_dpms; + output_funcs->output_get_dpms = nexell_output_get_dpms; + output_funcs->output_set_mode = nexell_output_set_mode; + output_funcs->output_get_mode = nexell_output_get_mode; + output_funcs->output_set_mirror = NULL; + output_funcs->output_unset_mirror = NULL; +#ifdef HAVE_UDEV + output_funcs->output_set_status_handler = nexell_output_set_status_handler; +#endif + output_funcs->output_get_hwc = nexell_output_get_hwc; + + /* alloc and register hwc_funcs */ + hwc_funcs = calloc(1, sizeof(struct _hal_tdm_hwc_funcs)); + if (!hwc_funcs) { + TDM_BACKEND_ERR("fail to alloc hwc_funcs!\n"); + goto failed; + } + backend_data->hwc_funcs = hwc_funcs; + + hwc_funcs->hwc_create_window = nexell_hwc_create_window; + hwc_funcs->hwc_get_video_supported_formats = nexell_hwc_get_video_supported_formats; + hwc_funcs->hwc_get_video_available_properties = NULL; + hwc_funcs->hwc_get_capabilities = nexell_hwc_get_capabilities; + hwc_funcs->hwc_get_available_properties = nexell_hwc_get_available_properties; + hwc_funcs->hwc_get_client_target_buffer_queue = nexell_hwc_get_client_target_buffer_queue; + hwc_funcs->hwc_set_client_target_buffer = nexell_hwc_set_client_target_buffer; + hwc_funcs->hwc_set_client_target_acquire_fence = NULL; + hwc_funcs->hwc_validate = nexell_hwc_validate; + hwc_funcs->hwc_get_changed_composition_types = nexell_hwc_get_changed_composition_types; + hwc_funcs->hwc_accept_validation = nexell_hwc_accept_validation; + hwc_funcs->hwc_commit = nexell_hwc_commit; + hwc_funcs->hwc_set_commit_handler = nexell_hwc_set_commit_handler; + hwc_funcs->hwc_get_commit_fence = NULL; + hwc_funcs->hwc_get_release_fences = NULL; + + /* alloc and register hwc_window_funcs */ + hwc_window_funcs = calloc(1, sizeof(struct _hal_tdm_hwc_window_funcs)); + if (!hwc_window_funcs) { + TDM_BACKEND_ERR("fail to alloc hwc_window_funcs!\n"); + goto failed; + } + backend_data->hwc_window_funcs = hwc_window_funcs; + + hwc_window_funcs->hwc_window_destroy = nexell_hwc_window_destroy; + hwc_window_funcs->hwc_window_acquire_buffer_queue = nexell_hwc_window_acquire_buffer_queue; + hwc_window_funcs->hwc_window_release_buffer_queue = nexell_hwc_window_release_buffer_queue; + hwc_window_funcs->hwc_window_set_composition_type = nexell_hwc_window_set_composition_type; + hwc_window_funcs->hwc_window_set_buffer_damage = nexell_hwc_window_set_buffer_damage; + hwc_window_funcs->hwc_window_set_info = nexell_hwc_window_set_info; + hwc_window_funcs->hwc_window_set_buffer = nexell_hwc_window_set_buffer; + hwc_window_funcs->hwc_window_set_property = nexell_hwc_window_set_property; + hwc_window_funcs->hwc_window_get_property = nexell_hwc_window_get_property; + hwc_window_funcs->hwc_window_get_constraints = nexell_hwc_window_get_constraints; + hwc_window_funcs->hwc_window_set_name = nexell_hwc_window_set_name; + hwc_window_funcs->hwc_window_set_cursor_image = nexell_hwc_window_set_cursor_image; + +#ifdef ENABLE_PP + /* alloc and register pp_funcs */ + pp_funcs = calloc(1, sizeof(struct _hal_tdm_pp_funcs)); + if (!pp_funcs) { + TDM_BACKEND_ERR("fail to alloc pp_funcs!\n"); + goto failed; + } + backend_data->pp_funcs = pp_funcs; + + pp_funcs->pp_destroy = nexell_pp_destroy; + pp_funcs->pp_set_info = nexell_pp_set_info; + pp_funcs->pp_attach = nexell_pp_attach; + pp_funcs->pp_commit = nexell_pp_commit; + pp_funcs->pp_set_done_handler = nexell_pp_set_done_handler; +#endif + + TDM_BACKEND_INFO("init success!"); + + return HAL_TDM_ERROR_NONE; + +failed: + TDM_BACKEND_ERR("init failed!"); + + hal_backend_tdm_nexell_exit((void *)backend_data); + + return -1; +} + +hal_backend hal_backend_tdm_data = { + "nexell", + "Samsung", + HAL_ABI_VERSION_TIZEN_6_5, + hal_backend_tdm_nexell_init, + hal_backend_tdm_nexell_exit +}; diff --git a/src/tdm_backend_nexell.h b/src/tdm_backend_nexell.h new file mode 100644 index 0000000..c382548 --- /dev/null +++ b/src/tdm_backend_nexell.h @@ -0,0 +1,133 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _HAL_TDM_NEXELL_H_ +#define _HAL_TDM_NEXELL_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell_types.h" + +/* display funcs */ +hal_tdm_error nexell_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps); +hal_tdm_error nexell_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps); +hal_tdm_output **nexell_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error); +hal_tdm_error nexell_display_get_fd(hal_tdm_display *display, int *fd); +hal_tdm_error nexell_display_handle_events(hal_tdm_display *display); +hal_tdm_pp* nexell_display_create_pp(hal_tdm_display *display, hal_tdm_error *error); + +/* output funcs */ +hal_tdm_error nexell_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps); +hal_tdm_error nexell_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value); +hal_tdm_error nexell_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value); +hal_tdm_error nexell_output_wait_vblank(hal_tdm_output *output, int interval, int sync, void *user_data); +hal_tdm_error nexell_output_set_vblank_handler(hal_tdm_output *output, hal_tdm_output_vblank_handler func); +hal_tdm_error nexell_output_commit(hal_tdm_output *output, int sync, void *user_data); +hal_tdm_error nexell_output_set_commit_handler(hal_tdm_output *output, hal_tdm_output_commit_handler func); +hal_tdm_error nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value); +hal_tdm_error nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value); +hal_tdm_error nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode); +hal_tdm_error nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode); +hal_tdm_error nexell_output_set_status_handler(hal_tdm_output *output, hal_tdm_output_status_handler func, void *user_data); +hal_tdm_hwc *nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error); + +/* hwc funcs */ +hal_tdm_hwc_window *nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error); +hal_tdm_error nexell_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count); +hal_tdm_error nexell_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities); +hal_tdm_error nexell_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count); +tbm_surface_queue_h nexell_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error); +hal_tdm_error nexell_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage); +hal_tdm_error nexell_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types); +hal_tdm_error nexell_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements, hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types); +hal_tdm_error nexell_hwc_accept_validation(hal_tdm_hwc *hwc); +hal_tdm_error nexell_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data); +hal_tdm_error nexell_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func); + +/* hwc_window funcs */ +void nexell_hwc_window_destroy(hal_tdm_hwc_window *hwc_window); +hal_tdm_error nexell_hwc_window_set_composition_type(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_composition composition_type); +hal_tdm_error nexell_hwc_window_set_buffer_damage(hal_tdm_hwc_window *hwc_window, hal_tdm_region damage); +hal_tdm_error nexell_hwc_window_set_info(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_info *info); +hal_tdm_error nexell_hwc_window_set_buffer(hal_tdm_hwc_window *hwc_window, tbm_surface_h surface); +hal_tdm_error nexell_hwc_window_set_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value value); +hal_tdm_error nexell_hwc_window_get_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value *value); +hal_tdm_error nexell_hwc_window_get_constraints(hal_tdm_hwc_window *hwc_window, int *constraints); +tbm_surface_queue_h nexell_hwc_window_acquire_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); +void nexell_hwc_window_release_buffer_queue(hal_tdm_hwc_window *hwc_window, tbm_surface_queue_h queue); +hal_tdm_error nexell_hwc_window_set_name(hal_tdm_hwc_window *hwc_window, const char *name); +hal_tdm_error nexell_hwc_window_set_cursor_image(hal_tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr); + +/* pp funcs */ +void nexell_pp_destroy(hal_tdm_pp *pp); +hal_tdm_error nexell_pp_set_info(hal_tdm_pp *pp, hal_tdm_info_pp *info); +hal_tdm_error nexell_pp_attach(hal_tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); +hal_tdm_error nexell_pp_commit(hal_tdm_pp *pp); +hal_tdm_error nexell_pp_set_done_handler(hal_tdm_pp *pp, hal_tdm_pp_done_handler func, void *user_data); + +/* nexell display */ +hal_tdm_error tdm_nexell_display_create_output_list(tdm_nexell_display *display_data); +void tdm_nexell_display_destroy_output_list(tdm_nexell_display *display_data); +void tdm_nexell_display_update_output_status(tdm_nexell_display *display_data); +hal_tdm_error tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data); +void tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data); + +/* nexell output */ +tdm_nexell_layer *nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zops); + +/* nexell hwc */ +hal_tdm_error tdm_nexell_hwc_initailize_target_window(tdm_nexell_hwc *hwc_data); +hal_tdm_error nexell_hwc_target_window_set_info(tdm_nexell_hwc *hwc_data, int width, int height); +tbm_surface_queue_h tdm_nexell_hwc_window_create_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); +tbm_surface_queue_h tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error); +void tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue); + +/* nexell layer_data */ +hal_tdm_error nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps); +hal_tdm_error nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value); +hal_tdm_error nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value); +hal_tdm_error nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info); +hal_tdm_error nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info); +hal_tdm_error nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer); +hal_tdm_error nexell_layer_unset_buffer(tdm_nexell_layer *layer_data); + +/* nexell pp */ +hal_tdm_error tdm_nexell_pp_get_capability(tdm_nexell_display *display_data, hal_tdm_caps_pp *caps); +hal_tdm_pp* tdm_nexell_pp_create(tdm_nexell_display *display_data, hal_tdm_error *error); +void tdm_nexell_pp_handler(unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec, unsigned int tv_usec, void *data); +void tdm_nexell_pp_cb(int fd, unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec, unsigned int tv_usec, void *user_data); + +/* nexell format */ +uint32_t tdm_nexell_format_to_drm_format(tbm_format format); +tbm_format tdm_nexell_format_to_tbm_format(uint32_t format); + +#endif /* _HAL_TDM_NEXELL_H_ */ diff --git a/src/tdm_backend_nexell_types.h b/src/tdm_backend_nexell_types.h new file mode 100644 index 0000000..3d52813 --- /dev/null +++ b/src/tdm_backend_nexell_types.h @@ -0,0 +1,343 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _HAL_TDM_NEXELL_TYPES_H_ +#define _HAL_TDM_NEXELL_TYPES_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "tdm_backend_list.h" +#include "tdm_backend_log.h" + +#define C(b, m) (((b) >> (m)) & 0xFF) +#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s)) +#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0)) +#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24) + +#define IS_RGB(format) (format == TBM_FORMAT_XRGB8888 || format == TBM_FORMAT_ARGB8888 || \ + format == TBM_FORMAT_XBGR8888 || format == TBM_FORMAT_ABGR8888) + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define SWAP(a, b) ({int t; t = a; a = b; b = t; }) +#define ROUNDUP(x) (ceil(floor((float)(height) / 4))) + +#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4) +#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) +#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) +#define ALIGN_TO_2KB(x) ((((x) + (1 << 11) - 1) >> 11) << 11) +#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) +#define ALIGN_TO_64KB(x) ((((x) + (1 << 16) - 1) >> 16) << 16) + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define NUM_BUFFERS 3 + +#define NUM_LAYERS 3 +#define NUM_UI_LAYERS 2 +#define ZPOS_MAX 2 +#define ZPOS_CURSOR 2 // cursor +#define ZPOS_2 2 // ui +#define ZPOS_1 1 // ui, primary layer_data +#define ZPOS_0 0 // video +#define ZPOS_VIDEO1 0 // video +#define ZPOS_NONE -999 + +typedef struct _tdm_nexell_display tdm_nexell_display; +typedef struct _tdm_nexell_output_data tdm_nexell_output; +typedef struct _tdm_nexell_layer_data tdm_nexell_layer; +typedef struct _tdm_nexell_hwc_data tdm_nexell_hwc; +typedef struct _tdm_nexell_hwc_window_data tdm_nexell_hwc_window_data; +typedef struct _tdm_nexell_event_data tdm_nexell_event_data; +typedef struct _tdm_nexell_display_buffer tdm_nexell_display_buffer; + +typedef enum { + TDM_NEXELL_LAYER_CAPABILITY_CURSOR = (1 << 0), /**< cursor */ + TDM_NEXELL_LAYER_CAPABILITY_PRIMARY = (1 << 1), /**< primary */ + TDM_NEXELL_LAYER_CAPABILITY_OVERLAY = (1 << 2), /**< overlay */ + TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC = (1 << 4), /**< graphic */ + TDM_NEXELL_LAYER_CAPABILITY_VIDEO = (1 << 5), /**< video */ + TDM_NEXELL_LAYER_CAPABILITY_SCALE = (1 << 8), /**< if a layer_data has scale capability */ + TDM_NEXELL_LAYER_CAPABILITY_TRANSFORM = (1 << 9), /**< if a layer_data has transform capability */ + TDM_NEXELL_LAYER_CAPABILITY_SCANOUT = (1 << 10), /**< if a layer_data allows a scanout buffer only */ + TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY = (1 << 11), /**< if a layer_data allows a reserved buffer only */ + TDM_NEXELL_LAYER_CAPABILITY_NO_CROP = (1 << 12), /**< if a layer_data has no cropping capability */ +} tdm_nexell_layer_capability; + +typedef enum { + HAL_TDM_NEXELL_EVENT_TYPE_WAIT, + HAL_TDM_NEXELL_EVENT_TYPE_COMMIT, + HAL_TDM_NEXELL_EVENT_TYPE_PAGEFLIP, +} tdm_nexell_event_type; + +struct _tdm_nexell_display +{ + int drm_fd; + int scaler_fd; + +#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 + int has_universal_plane; + int has_atomic; +#endif + +#if HAVE_UDEV + struct udev_monitor *uevent_monitor; +#endif + + drmModeResPtr mode_res; + drmModePlaneResPtr plane_res; + + struct list_head output_list; + struct list_head buffer_list; +}; + +struct _tdm_nexell_display_buffer { + struct list_head link; + + unsigned int fb_id; + tbm_surface_h buffer; + int width; + unsigned int height; + unsigned int format; + unsigned int handles[4]; + unsigned int fds[4]; + unsigned int pitches[4]; + unsigned int offsets[4]; + unsigned int size; + unsigned int count; +}; + +struct _tdm_nexell_event_data { + tdm_nexell_event_type type; + tdm_nexell_output *output_data; + void *user_data; +}; + +struct display_properties_ids { + uint32_t connector_crtc_id; + uint32_t crtc_mode_id; + uint32_t crtc_active; + uint32_t plane_fb_id; + uint32_t plane_crtc_id; + uint32_t plane_src_x; + uint32_t plane_src_y; + uint32_t plane_src_w; + uint32_t plane_src_h; + uint32_t plane_crtc_x; + uint32_t plane_crtc_y; + uint32_t plane_crtc_w; + uint32_t plane_crtc_h; + uint32_t plane_zpos; +}; + +struct _tdm_nexell_output_data { + struct list_head link; + + /* data which are fixed at initializing */ + tdm_nexell_display *display_data; + uint32_t connector_id; + uint32_t encoder_id; + uint32_t crtc_id; + uint32_t pipe; + uint32_t dpms_prop_id; + int count_modes; + drmModeModeInfoPtr drm_modes; + hal_tdm_output_mode *output_modes; + hal_tdm_output_type connector_type; + unsigned int connector_type_id; + struct list_head layer_list; + tdm_nexell_layer *primary_layer; + + /* not fixed data below */ + hal_tdm_output_vblank_handler vblank_func; + hal_tdm_output_commit_handler commit_func; + + hal_tdm_output_conn_status status; + hal_tdm_output_status_handler status_func; + void *status_user_data; + + int mode_changed; + const hal_tdm_output_mode *current_mode; + + struct display_properties_ids props; + + int crtc_enabled; + + /* atomic prop ids*/ + struct { + uint32_t crtc_id; + uint32_t crtc_mode_id; + uint32_t crtc_active; + } atomic_props_ids; + + /* hwc */ + tdm_nexell_hwc *hwc_data; +}; + +typedef struct _tdm_nexell_layer_info { + hal_tdm_info_config src_config; + hal_tdm_pos dst_pos; + hal_tdm_transform transform; +} tdm_nexell_layer_info; + +typedef struct _tdm_nexell_caps_layer { + tdm_nexell_layer_capability capabilities; /**< The capabilities of layer_data */ + + /** + * The z-order + * GRAPHIC layers are non-changeable. The zpos of GRAPHIC layers starts + * from 0. If there are 4 GRAPHIC layers, The zpos SHOULD be 0, 1, 2, 3.\n + * But the zpos of VIDEO layer_data is changeable by layer_set_video_pos() function + * of #tdm_func_layer. And The zpos of VIDEO layers is less than GRAPHIC + * layers or more than GRAPHIC layers. + * ie, ..., -2, -1, 4, 5, ... (if 0 <= GRAPHIC layer_data's zpos < 4). + * The zpos of VIDEO layers is @b relative. It doesn't need to start + * from -1 or 4. Let's suppose that there are two VIDEO layers. + * One has -2 zpos. Another has -4 zpos. Then -2 Video layer_data is higher + * than -4 VIDEO layer_data. + */ + int zpos; + + unsigned int format_count; /**< The count of available formats */ + tbm_format *formats; /**< The @b newly-allocated array of formats. will be freed in frontend. */ + + unsigned int prop_count; /**< The count of available properties */ + hal_tdm_prop *props; /**< The @b newly-allocated array of properties. will be freed in frontend. */ +} tdm_nexell_caps_layer; + +struct _tdm_nexell_layer_data { + struct list_head link; + + /* data which are fixed at initializing */ + tdm_nexell_display *display_data; + tdm_nexell_output *output_data; + uint32_t plane_id; + tdm_nexell_layer_capability capabilities; + int zpos; + + /* not fixed data below */ + tdm_nexell_layer_info info; + int info_changed; + + tdm_nexell_display_buffer *display_buffer; + int display_buffer_changed; + + /* atomic prop ids*/ + struct { + uint32_t fb_id; + uint32_t crtc_id; + uint32_t src_x; + uint32_t src_y; + uint32_t src_w; + uint32_t src_h; + uint32_t crtc_x; + uint32_t crtc_y; + uint32_t crtc_w; + uint32_t crtc_h; + uint32_t zpos; + } atomic_props_ids; +}; + +struct _tdm_nexell_hwc_data { + tdm_nexell_hwc_window_data *target_hwc_window; + + int need_validate; + int need_target_window; + int need_set_crtc; + + int target_window_zpos; + + tdm_nexell_output *output_data; + struct list_head hwc_window_list; + + tbm_surface_queue_h cursor_tqueue; + tbm_surface_h cursor_tsurface; + + /* UI buffer_queue list for the reserved scanout memory */ + struct { + tbm_surface_queue_h tqueue; + int ref_cnt; + } ui_buffer_queue[NUM_LAYERS]; + + hal_tdm_hwc_commit_handler commit_func; +}; + +struct _tdm_nexell_hwc_window_data { + struct list_head link; + + tdm_nexell_hwc *hwc_data; + + hal_tdm_hwc_window_info info; + tbm_surface_h surface; + hal_tdm_hwc_window_composition client_type; + hal_tdm_hwc_window_composition validated_type; + int lzpos; + int lzpos_queue; + + char name[HAL_TDM_NAME_LEN]; + struct { + int width; + int height; + int stride; + void *ptr; + } cursor_img; + int cursor_img_surface; + int cursor_img_refresh; + + int constraints; +}; + +#endif /* _HAL_TDM_NEXELL_TYPES_H_ */ diff --git a/src/tdm_nexell_display.c b/src/tdm_nexell_display.c new file mode 100644 index 0000000..63a827a --- /dev/null +++ b/src/tdm_nexell_display.c @@ -0,0 +1,2206 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +#define MIN_WIDTH 32 + +static drmModeModeInfoPtr +_tdm_nexell_display_get_mode(tdm_nexell_output *output_data) +{ + int i; + + if (!output_data->current_mode) { + TDM_BACKEND_ERR("no output_data->current_mode"); + return NULL; + } + + for (i = 0; i < output_data->count_modes; i++) { + drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i]; + if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) && + (drm_mode->vdisplay == output_data->current_mode->vdisplay) && + (drm_mode->vrefresh == output_data->current_mode->vrefresh) && + (drm_mode->flags == output_data->current_mode->flags) && + (drm_mode->type == output_data->current_mode->type) && + !(strncmp(drm_mode->name, output_data->current_mode->name, HAL_TDM_NAME_LEN))) + return drm_mode; + } + + return NULL; +} + +static void +_tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode, + hal_tdm_output_mode *tdm_mode) +{ + tdm_mode->clock = drm_mode->clock; + tdm_mode->hdisplay = drm_mode->hdisplay; + tdm_mode->hsync_start = drm_mode->hsync_start; + tdm_mode->hsync_end = drm_mode->hsync_end; + tdm_mode->htotal = drm_mode->htotal; + tdm_mode->hskew = drm_mode->hskew; + tdm_mode->vdisplay = drm_mode->vdisplay; + tdm_mode->vsync_start = drm_mode->vsync_start; + tdm_mode->vsync_end = drm_mode->vsync_end; + tdm_mode->vtotal = drm_mode->vtotal; + tdm_mode->vscan = drm_mode->vscan; + tdm_mode->vrefresh = drm_mode->vrefresh; + tdm_mode->flags = drm_mode->flags; + tdm_mode->type = drm_mode->type; + snprintf(tdm_mode->name, HAL_TDM_NAME_LEN, "%s", drm_mode->name); +} + +static hal_tdm_error +_tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc) +{ + drmVBlank vbl; + + vbl.request.type = DRM_VBLANK_RELATIVE; + if (pipe == 1) + vbl.request.type |= DRM_VBLANK_SECONDARY; + else if (pipe > 1) + vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; + + vbl.request.sequence = 0; + if (drmWaitVBlank(fd, &vbl)) { + TDM_BACKEND_ERR("get vblank counter failed: %m"); + *msc = 0; + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + *msc = vbl.reply.sequence; + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data) +{ + drmVBlank vbl; + + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + if (pipe == 1) + vbl.request.type |= DRM_VBLANK_SECONDARY; + else if (pipe > 1) + vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; + + vbl.request.sequence = *target_msc; + vbl.request.signal = (unsigned long)(uintptr_t)data; + + if (drmWaitVBlank(fd, &vbl)) { + TDM_BACKEND_ERR("wait vblank failed: %m"); + *target_msc = 0; + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + *target_msc = vbl.reply.sequence; + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_tdm_nexell_output_update_status(tdm_nexell_output *output_data, + hal_tdm_output_conn_status status) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (output_data->status == status) + return HAL_TDM_ERROR_NONE; + + output_data->status = status; + + if (output_data->status_func) + output_data->status_func(output_data, status, + output_data->status_user_data); + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_tdm_nexell_display_commit_primary_layer(tdm_nexell_layer *layer_data, + void *user_data, int *do_waitvblank) +{ + tdm_nexell_display *display_data = layer_data->display_data; + tdm_nexell_output *output_data = layer_data->output_data; + + if (output_data->mode_changed && layer_data->display_buffer_changed) { + drmModeModeInfoPtr mode; + + if (!layer_data->display_buffer) { + TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting"); + return HAL_TDM_ERROR_BAD_REQUEST; + } + + output_data->mode_changed = 0; + layer_data->display_buffer_changed = 0; + layer_data->info_changed = 0; + + mode = _tdm_nexell_display_get_mode(output_data); + if (!mode) { + TDM_BACKEND_ERR("couldn't find proper mode"); + return HAL_TDM_ERROR_BAD_REQUEST; + } + + if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id, + layer_data->display_buffer->fb_id, 0, 0, + &output_data->connector_id, 1, mode)) { + TDM_BACKEND_ERR("set crtc failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED); + + *do_waitvblank = 1; + return HAL_TDM_ERROR_NONE; + } else if (layer_data->display_buffer_changed) { + layer_data->display_buffer_changed = 0; + + if (layer_data->display_buffer) { + tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); + + if (!event_data) { + TDM_BACKEND_ERR("alloc failed"); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + + event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; + event_data->output_data = output_data; + event_data->user_data = user_data; + if (drmModePageFlip(display_data->drm_fd, output_data->crtc_id, + layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) { + TDM_BACKEND_ERR("pageflip failed: %m"); + free(event_data); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + *do_waitvblank = 0; + } + }else { + /* to call a user commit handler whenever committed */ + *do_waitvblank = 1; + } + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_tdm_nexell_display_commit_layer(tdm_nexell_layer *layer_data) +{ + tdm_nexell_display *display_data = layer_data->display_data; + tdm_nexell_output *output_data = layer_data->output_data; + uint32_t fx, fy, fw, fh; + int crtc_w; + + if (!layer_data->display_buffer_changed && !layer_data->info_changed) + return HAL_TDM_ERROR_NONE; + + if (output_data->current_mode) + crtc_w = output_data->current_mode->hdisplay; + else { + drmModeCrtcPtr crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id); + if (!crtc) { + TDM_BACKEND_ERR("getting crtc failed"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + crtc_w = crtc->width; + if (crtc_w == 0) { + TDM_BACKEND_ERR("getting crtc width failed"); + drmModeFreeCrtc(crtc); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + drmModeFreeCrtc(crtc); + } + + // reset the changed flags + layer_data->display_buffer_changed = 0; + layer_data->info_changed = 0; + + if (layer_data->display_buffer) { // set plane + /* Source values are 16.16 fixed point */ + fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16; + fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16; + fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16; + fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16; + + TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", + layer_data->plane_id, output_data->crtc_id, layer_data->zpos, + layer_data->display_buffer->fb_id, + layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y, + layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h, + layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, + layer_data->info.dst_pos.w, layer_data->info.dst_pos.h); + + if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id, + output_data->crtc_id, layer_data->display_buffer->fb_id, 0, + layer_data->info.dst_pos.x, layer_data->info.dst_pos.y, + layer_data->info.dst_pos.w, layer_data->info.dst_pos.h, + fx, fy, fw, fh) < 0) { + TDM_BACKEND_ERR("set plane(%d) failed: %m", layer_data->plane_id); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + } else { // unset plane + TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n", + layer_data->plane_id, output_data->crtc_id, layer_data->zpos); + + if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id, + output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + TDM_BACKEND_ERR("unset plane(%d) filed: %m", layer_data->plane_id); + } + + return HAL_TDM_ERROR_NONE; +} + +static void +_tdm_nexell_display_cb_event(int fd, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + tdm_nexell_event_data *event_data = user_data; + tdm_nexell_output *output_data; + tdm_nexell_hwc *hwc_data; + + if (!event_data) { + TDM_BACKEND_ERR("no event data"); + return; + } + + output_data = event_data->output_data; + + switch (event_data->type) { + case HAL_TDM_NEXELL_EVENT_TYPE_PAGEFLIP: + if (output_data->commit_func) + output_data->commit_func(output_data, sequence, tv_sec, tv_usec, + event_data->user_data); + break; + case HAL_TDM_NEXELL_EVENT_TYPE_WAIT: + if (output_data->vblank_func) + output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, + event_data->user_data); + break; + case HAL_TDM_NEXELL_EVENT_TYPE_COMMIT: + hwc_data = output_data->hwc_data; + if (!hwc_data) { + TDM_BACKEND_ERR("no hwc_data"); + break; + } + + if (hwc_data->commit_func) + hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec, + event_data->user_data); + break; + default: + break; + } + + free(event_data); +} + +static hal_tdm_error +_tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data) +{ + tdm_nexell_output *output_data = NULL; + int i; + + if (LIST_IS_EMPTY(&display_data->output_list)) { + TDM_BACKEND_ERR("no output"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + /* The TDM drm backend only support one output. */ + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { + break; + } + + if (display_data->plane_res->count_planes == 0) { + TDM_BACKEND_ERR("no layer_data error"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < display_data->plane_res->count_planes; i++) { + tdm_nexell_layer *layer_data; + drmModePlanePtr plane; + + plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]); + if (!plane) { + TDM_BACKEND_ERR("no plane"); + continue; + } + + if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { + drmModeFreePlane(plane); + continue; + } + + layer_data = calloc(1, sizeof(tdm_nexell_layer)); + if (!layer_data) { + TDM_BACKEND_ERR("alloc failed"); + drmModeFreePlane(plane); + continue; + } + + layer_data->display_data = display_data; + layer_data->output_data = output_data; + layer_data->plane_id = display_data->plane_res->planes[i]; + + layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY | + TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC; + output_data->primary_layer = layer_data; + + TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)", + layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, + layer_data->capabilities); + + LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); + + drmModeFreePlane(plane); + + /* can't take care of other planes for various hardware devices */ + break; + } + + return HAL_TDM_ERROR_NONE; +} + +#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 + +static hal_tdm_error +_tdm_nexell_display_get_property(tdm_nexell_display *display_data, + unsigned int obj_id, unsigned int obj_type, + const char *name, unsigned int *value, + int *is_immutable) +{ + drmModeObjectPropertiesPtr props = NULL; + int i; + + props = drmModeObjectGetProperties(display_data->drm_fd, obj_id, obj_type); + if (!props) + return HAL_TDM_ERROR_OPERATION_FAILED; + + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, + props->props[i]); + + if (!prop) + continue; + + if (!strcmp(prop->name, name)) { + if (is_immutable) + *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE; + if (value) + *value = (unsigned int)props->prop_values[i]; + drmModeFreeProperty(prop); + drmModeFreeObjectProperties(props); + return HAL_TDM_ERROR_NONE; + } + + drmModeFreeProperty(prop); + } + drmModeFreeObjectProperties(props); + TDM_BACKEND_DBG("coundn't find '%s' property", name); + return HAL_TDM_ERROR_OPERATION_FAILED; +} + +static hal_tdm_error +_nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id) +{ + drmModeObjectPropertiesPtr properties = NULL; + drmModePropertyPtr property = NULL; + int i; + + properties = drmModeObjectGetProperties(drm_fd, object_id, object_type); + if (properties == NULL) { + TDM_BACKEND_ERR("drmModeObjectGetProperties failed"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < properties->count_props; i++) { + property = drmModeGetProperty(drm_fd, properties->props[i]); + if (property == NULL) { + continue; + } + + if (strcmp(property->name, name) == 0) { + *id = property->prop_id; + drmModeFreeProperty(property); + break; + } + drmModeFreeProperty(property); + } + + drmModeFreeObjectProperties(properties); + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_tdm_nexell_display_create_layer_list_type(tdm_nexell_display *display_data) +{ + tdm_nexell_output *output_data = NULL; + drmModePlanePtr *planes = NULL; + unsigned int *types = NULL; + unsigned int type = 0; + int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt; + int opos_next, cpos_next; + hal_tdm_error ret; + int i; + + if (LIST_IS_EMPTY(&display_data->output_list)) { + TDM_BACKEND_ERR("no output"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + /* The TDM drm backend only support one output. */ + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { + break; + } + + ret = _tdm_nexell_display_get_property(display_data, + display_data->plane_res->planes[0], + DRM_MODE_OBJECT_PLANE, "type", &type, + NULL); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("plane doesn't have 'type' property. Call a fallback function"); + + /* if a plane doesn't have "type" property, we call a fallback function + * as default + */ + return _tdm_nexell_display_create_layer_list(display_data); + } + + planes = calloc(display_data->plane_res->count_planes, sizeof(drmModePlanePtr)); + if (!planes) { + TDM_BACKEND_ERR("alloc failed"); + goto failed; + } + + types = calloc(display_data->plane_res->count_planes, sizeof(unsigned int)); + if (!types) { + TDM_BACKEND_ERR("alloc failed"); + goto failed; + } + + plane_cnt = 0; + for (i = 0; i < display_data->plane_res->count_planes; i++) { + drmModePlanePtr plane; + + plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]); + if (!plane) { + TDM_BACKEND_ERR("no plane(%d)", display_data->plane_res->planes[i]); + goto failed; + } + + if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) { + drmModeFreePlane(plane); + continue; + } + + ret = _tdm_nexell_display_get_property(display_data, + display_data->plane_res->planes[i], + DRM_MODE_OBJECT_PLANE, "type", &type, + NULL); + if (ret != HAL_TDM_ERROR_NONE) { + drmModeFreePlane(plane); + TDM_BACKEND_ERR("plane(%d) doesn't have 'type' info", + display_data->plane_res->planes[i]); + goto failed; + } + + planes[plane_cnt] = plane; + types[plane_cnt] = type; + plane_cnt++; + } + + primary_cnt = ovl_cnt = cursor_cnt = 0; + for (i = 0; i < plane_cnt; i++) { + if (types[i] == DRM_PLANE_TYPE_CURSOR) + cursor_cnt++; + else if (types[i] == DRM_PLANE_TYPE_OVERLAY) + ovl_cnt++; + else if (types[i] == DRM_PLANE_TYPE_PRIMARY) + primary_cnt++; + else + TDM_BACKEND_ERR("invalid type(%d)", types[i]); + } + + if (primary_cnt != 1) { + TDM_BACKEND_ERR("primary layer_data count(%d) should be one", primary_cnt); + goto failed; + } + + opos_next = 0; + cpos_next = ovl_cnt; + if (plane_cnt < 1) { + TDM_BACKEND_ERR("plane count(%d) should be over 1", plane_cnt); + goto failed; + } + + for (i = plane_cnt - 1; i >= 0; i--) { + tdm_nexell_layer *layer_data; + + layer_data = calloc(1, sizeof(tdm_nexell_layer)); + if (!layer_data) { + TDM_BACKEND_ERR("alloc failed"); + goto failed; + } + + layer_data->display_data = display_data; + layer_data->output_data = output_data; + layer_data->plane_id = planes[i]->plane_id; + + if (types[i] == DRM_PLANE_TYPE_CURSOR) { + layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_CURSOR | + TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | + TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; + layer_data->zpos = cpos_next++; + TDM_BACKEND_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos); + } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) { + if (opos_next == 0) { + layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY | + TDM_NEXELL_LAYER_CAPABILITY_SCALE | + TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; + } else { + layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY | + TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | + TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY | + TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; + } + if (opos_next == 1) { + layer_data->zpos = 2; + opos_next = 2; + } else { + layer_data->zpos = opos_next++; + } + + TDM_BACKEND_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos); + } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) { + layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY | + TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC | + TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY | + TDM_NEXELL_LAYER_CAPABILITY_SCANOUT; + layer_data->zpos = 1; + output_data->primary_layer = layer_data; + + TDM_BACKEND_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos); + } else { + free(layer_data); + continue; + } + + TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)", + layer_data, layer_data->plane_id, layer_data->output_data->crtc_id, + layer_data->zpos, layer_data->capabilities); + + LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); + + /* get the atomic prop ids*/ + if (display_data->has_atomic) { + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h); + if (ret != HAL_TDM_ERROR_NONE) { + free(layer_data); + goto failed; + } + } + } + + for (i = 0; i < plane_cnt; i++) + if (planes[i]) + drmModeFreePlane(planes[i]); + + free(planes); + free(types); + + return HAL_TDM_ERROR_NONE; + +failed: + if (planes) { + for (i = 0; i < display_data->plane_res->count_planes; i++) + if (planes[i]) + drmModeFreePlane(planes[i]); + free(planes); + } + + free(types); + + return HAL_TDM_ERROR_OPERATION_FAILED; +} +#endif + +hal_tdm_error +tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data) +{ + tdm_nexell_output *output_data = NULL; + hal_tdm_error ret; + +#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 + if (display_data->has_universal_plane) + ret = _tdm_nexell_display_create_layer_list_type(display_data); + else +#endif + ret = _tdm_nexell_display_create_layer_list(display_data); + + if (ret != HAL_TDM_ERROR_NONE) + return ret; + + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { + if (!output_data->primary_layer) { + TDM_BACKEND_ERR("output(%d) no primary layer_data", output_data->pipe); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + } + + return HAL_TDM_ERROR_NONE; +} + +void +tdm_nexell_display_destroy_output_list(tdm_nexell_display *display_data) +{ + tdm_nexell_output *o = NULL, *oo = NULL; + tdm_nexell_hwc *hwc_data = NULL; + + if (LIST_IS_EMPTY(&display_data->output_list)) + return; + + LIST_FOR_EACH_ENTRY_SAFE(o, oo, &display_data->output_list, link) { + hwc_data = o->hwc_data; + if (hwc_data && hwc_data->target_hwc_window) + nexell_hwc_window_destroy(hwc_data->target_hwc_window); + + LIST_DEL(&o->link); + if (!LIST_IS_EMPTY(&o->layer_list)) { + tdm_nexell_layer *l = NULL, *ll = NULL; + LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { + LIST_DEL(&l->link); + if (l->display_buffer) + tbm_surface_internal_unref(l->display_buffer->buffer); + free(l); + } + } + free(o->drm_modes); + free(o->output_modes); + free(o); + } +} + +void +tdm_nexell_display_update_output_status(tdm_nexell_display *display_data) +{ + tdm_nexell_output *output_data = NULL; + + if (LIST_IS_EMPTY(&display_data->output_list)) + return; + + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { + drmModeConnectorPtr connector; + hal_tdm_output_conn_status new_status; + + connector = drmModeGetConnector(display_data->drm_fd, + output_data->connector_id); + if (!connector) { + TDM_BACKEND_ERR("no connector: %d", output_data->connector_id); + continue; + } + + if (connector->connection == DRM_MODE_CONNECTED) + new_status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED; + else + new_status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + _tdm_nexell_output_update_status(output_data, new_status); + + drmModeFreeConnector(connector); + } +} + +hal_tdm_error +tdm_nexell_display_create_output_list(tdm_nexell_display *display_data) +{ + tdm_nexell_output *output_data; + int i; + hal_tdm_error ret; + int allocated = 0; + drmModeConnectorPtr connector; + drmModeEncoderPtr encoder; + int conn_idx = -1; + int hdmia_idx = -1, hdmib_idx = -1; + int crtc_id = 0, c, j; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&display_data->output_list), + HAL_TDM_ERROR_OPERATION_FAILED); + + /* check if there is a connected output */ + for (i = 0; i < display_data->mode_res->count_connectors; i++) { + connector = drmModeGetConnector(display_data->drm_fd, + display_data->mode_res->connectors[i]); + if (!connector) { + TDM_BACKEND_ERR("no connector"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + /* The TDM drm backend considers only 1 connector because it is the TDM + * reference backend and can't take care of all hardware devices. + * To support various connectors, planes and crtcs, the new TDM backend + * should be implemented. + */ + if (connector->connection == DRM_MODE_CONNECTED) { + conn_idx = i; + drmModeFreeConnector(connector); + break; + } + + if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) + hdmia_idx = i; + if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) + hdmib_idx = i; + + drmModeFreeConnector(connector); + } + + /* use the hdmi connector if there is no connected connector. */ + /* if there is no hdmi connector, use first connector. */ + if (conn_idx == -1) { + if (hdmia_idx != -1) + conn_idx = hdmia_idx; + else if (hdmib_idx != -1) + conn_idx = hdmib_idx; + else + conn_idx = 0; + } + + /* The TDM drm backend considers only 1 connector because it is the TDM + * reference backend and can't take care of all hardware devices. + * To support various connectors, planes and crtcs, the new TDM backend + * should be implemented. + */ + connector = drmModeGetConnector(display_data->drm_fd, + display_data->mode_res->connectors[conn_idx]); + if (!connector) { + TDM_BACKEND_ERR("no connector"); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed_create; + } + + if (connector->count_encoders != 1) { + TDM_BACKEND_ERR("too many encoders: %d", connector->count_encoders); + drmModeFreeConnector(connector); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed_create; + } + + encoder = drmModeGetEncoder(display_data->drm_fd, connector->encoders[0]); + if (!encoder) { + TDM_BACKEND_ERR("no encoder"); + drmModeFreeConnector(connector); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed_create; + } + + for (c = 0; c < display_data->mode_res->count_crtcs; c++) { + if ((encoder->possible_crtcs & (1 << c)) == 0) + continue; + + crtc_id = display_data->mode_res->crtcs[c]; + allocated |= (1 << c); + break; + } + + if (crtc_id == 0) { + TDM_BACKEND_ERR("no possible crtc"); + drmModeFreeConnector(connector); + drmModeFreeEncoder(encoder); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed_create; + } + + output_data = calloc(1, sizeof(tdm_nexell_output)); + if (!output_data) { + TDM_BACKEND_ERR("alloc failed"); + drmModeFreeConnector(connector); + drmModeFreeEncoder(encoder); + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + goto failed_create; + } + + LIST_INITHEAD(&output_data->layer_list); + + output_data->display_data = display_data; + output_data->connector_id = display_data->mode_res->connectors[conn_idx]; + output_data->encoder_id = encoder->encoder_id; + output_data->crtc_id = crtc_id; + output_data->pipe = c; + output_data->connector_type = connector->connector_type; + output_data->connector_type_id = connector->connector_type_id; + + if (connector->connection == DRM_MODE_CONNECTED) + output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED; + else + output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + for (j = 0; j < connector->count_props; j++) { + drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, + connector->props[j]); + if (!prop) + continue; + if (!strcmp(prop->name, "DPMS")) { + output_data->dpms_prop_id = connector->props[j]; + drmModeFreeProperty(prop); + break; + } + drmModeFreeProperty(prop); + } + + if (output_data->dpms_prop_id == 0) + TDM_BACKEND_WRN("not support DPMS"); + + output_data->count_modes = connector->count_modes; + output_data->drm_modes = calloc(connector->count_modes, + sizeof(drmModeModeInfo)); + if (!output_data->drm_modes) { + TDM_BACKEND_ERR("alloc failed"); + free(output_data); + drmModeFreeConnector(connector); + drmModeFreeEncoder(encoder); + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + goto failed_create; + } + output_data->output_modes = calloc(connector->count_modes, + sizeof(hal_tdm_output_mode)); + if (!output_data->output_modes) { + TDM_BACKEND_ERR("alloc failed"); + free(output_data->drm_modes); + free(output_data); + drmModeFreeConnector(connector); + drmModeFreeEncoder(encoder); + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + goto failed_create; + } + for (j = 0; j < connector->count_modes; j++) { + output_data->drm_modes[j] = connector->modes[j]; + _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j], + &output_data->output_modes[j]); + } + + LIST_ADDTAIL(&output_data->link, &display_data->output_list); + + TDM_BACKEND_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)", + output_data, output_data->connector_id, output_data->status, + output_data->connector_type, + output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id, + output_data->pipe, output_data->dpms_prop_id); + + drmModeFreeEncoder(encoder); + drmModeFreeConnector(connector); + + /* get the atomic prop ids*/ + if (display_data->has_atomic) { + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id); + if (ret != HAL_TDM_ERROR_NONE) + goto failed_create; + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id, + DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id); + if (ret != HAL_TDM_ERROR_NONE) + goto failed_create; + + ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id, + DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active); + if (ret != HAL_TDM_ERROR_NONE) + goto failed_create; + } + + TDM_BACKEND_DBG("output count: %d", display_data->mode_res->count_connectors); + + return HAL_TDM_ERROR_NONE; +failed_create: + tdm_nexell_display_destroy_output_list(display_data); + return ret; +} + +hal_tdm_error +nexell_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); + + caps->max_layer_count = -1; /* not defined */ + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps) +{ + return tdm_nexell_pp_get_capability(display, caps); +} + +hal_tdm_output ** +nexell_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error) +{ + tdm_nexell_display *display_data = display; + tdm_nexell_output *output_data = NULL; + hal_tdm_output **outputs; + hal_tdm_error ret; + int i; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL); + TDM_BACKEND_RETURN_VAL_IF_FAIL(count, NULL); + + *count = 0; + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) + (*count)++; + + if (*count == 0) { + ret = HAL_TDM_ERROR_NONE; + goto failed_get; + } + + /* will be freed in frontend */ + outputs = calloc(*count, sizeof(tdm_nexell_output *)); + if (!outputs) { + TDM_BACKEND_ERR("failed: alloc memory"); + *count = 0; + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + goto failed_get; + } + + i = 0; + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) + outputs[i++] = output_data; + + if (error) + *error = HAL_TDM_ERROR_NONE; + + return outputs; +failed_get: + if (error) + *error = ret; + return NULL; +} + +hal_tdm_error +nexell_display_get_fd(hal_tdm_display *display, int *fd) +{ + tdm_nexell_display *display_data = display; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(fd, HAL_TDM_ERROR_INVALID_PARAMETER); + + *fd = display_data->drm_fd; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_display_handle_events(hal_tdm_display *display) +{ + tdm_nexell_display *display_data = display; + drmEventContext ctx; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + memset(&ctx, 0, sizeof(drmEventContext)); + + ctx.version = DRM_EVENT_CONTEXT_VERSION; + ctx.page_flip_handler = _tdm_nexell_display_cb_event; + ctx.vblank_handler = _tdm_nexell_display_cb_event; + + drmHandleEvent(display_data->drm_fd, &ctx); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_pp * +nexell_display_create_pp(hal_tdm_display *display, hal_tdm_error *error) +{ + tdm_nexell_display *display_data = display; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL); + + return tdm_nexell_pp_create(display_data, error); +} + +hal_tdm_error +nexell_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + drmModeConnectorPtr connector = NULL; + drmModeCrtcPtr crtc = NULL; + drmModeObjectPropertiesPtr props = NULL; + int i; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); + + memset(caps, 0, sizeof(hal_tdm_caps_output)); + + display_data = output_data->display_data; + + snprintf(caps->maker, HAL_TDM_NAME_LEN, "unknown"); + snprintf(caps->model, HAL_TDM_NAME_LEN, "unknown"); + snprintf(caps->name, HAL_TDM_NAME_LEN, "unknown"); + + caps->status = output_data->status; + caps->type = output_data->connector_type; + caps->type_id = output_data->connector_type_id; + + connector = drmModeGetConnector(display_data->drm_fd, output_data->connector_id); + TDM_BACKEND_RETURN_VAL_IF_FAIL(connector, HAL_TDM_ERROR_OPERATION_FAILED); + + caps->mode_count = connector->count_modes; + caps->modes = calloc(1, sizeof(hal_tdm_output_mode) * caps->mode_count); + if (!caps->modes) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed\n"); + goto failed_get; + } + + if (caps->mode_count != output_data->count_modes) { + drmModeModeInfoPtr new_drm_modes; + hal_tdm_output_mode *new_output_modes; + + new_drm_modes = calloc(connector->count_modes, + sizeof(drmModeModeInfo)); + if (!new_drm_modes) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed drm_modes\n"); + goto failed_get; + } + new_output_modes = calloc(connector->count_modes, + sizeof(hal_tdm_output_mode)); + if (!new_output_modes) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed output_modes\n"); + free(new_drm_modes); + goto failed_get; + } + free(output_data->drm_modes); + free(output_data->output_modes); + + output_data->drm_modes = new_drm_modes; + output_data->output_modes = new_output_modes; + output_data->count_modes = caps->mode_count; + } + + for (i = 0; i < caps->mode_count; i++) { + output_data->drm_modes[i] = connector->modes[i]; + _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i], + &output_data->output_modes[i]); + caps->modes[i] = output_data->output_modes[i]; + } + + caps->mmWidth = connector->mmWidth; + caps->mmHeight = connector->mmHeight; + caps->subpixel = connector->subpixel; + + caps->min_w = display_data->mode_res->min_width; + caps->min_h = display_data->mode_res->min_height; + caps->max_w = display_data->mode_res->max_width; + caps->max_h = display_data->mode_res->max_height; + caps->preferred_align = -1; + + crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id); + if (!crtc) { + ret = HAL_TDM_ERROR_OPERATION_FAILED; + TDM_BACKEND_ERR("get crtc failed: %m\n"); + goto failed_get; + } + + props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!props) { + ret = HAL_TDM_ERROR_OPERATION_FAILED; + TDM_BACKEND_ERR("get crtc properties failed: %m\n"); + goto failed_get; + } + + caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props); + if (!caps->props) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed\n"); + goto failed_get; + } + + caps->prop_count = 0; + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]); + if (!prop) + continue; + snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name); + caps->props[caps->prop_count].id = props->props[i]; + caps->prop_count++; + drmModeFreeProperty(prop); + } + + caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_HWC; + + drmModeFreeObjectProperties(props); + drmModeFreeCrtc(crtc); + drmModeFreeConnector(connector); + + return HAL_TDM_ERROR_NONE; +failed_get: + drmModeFreeCrtc(crtc); + drmModeFreeObjectProperties(props); + drmModeFreeConnector(connector); + free(caps->modes); + free(caps->props); + memset(caps, 0, sizeof(hal_tdm_caps_output)); + return ret; +} + +hal_tdm_error +nexell_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + int ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = output_data->display_data; + ret = drmModeObjectSetProperty(display_data->drm_fd, + output_data->crtc_id, DRM_MODE_OBJECT_CRTC, + id, value.u32); + if (ret < 0) { + TDM_BACKEND_ERR("set property failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + drmModeObjectPropertiesPtr props; + int i; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = output_data->display_data; + props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (props == NULL) { + TDM_BACKEND_ERR("get property failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < props->count_props; i++) + if (props->props[i] == id) { + (*value).u32 = (uint)props->prop_values[i]; + break; + } + + drmModeFreeObjectProperties(props); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_wait_vblank(hal_tdm_output *output, int interval, int sync, + void *user_data) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + tdm_nexell_event_data *event_data; + uint target_msc; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + event_data = calloc(1, sizeof(tdm_nexell_event_data)); + if (!event_data) { + TDM_BACKEND_ERR("alloc failed"); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + + display_data = output_data->display_data; + + ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe, + &target_msc); + if (ret != HAL_TDM_ERROR_NONE) + goto failed_vblank; + + target_msc += interval; + + event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_WAIT; + event_data->output_data = output_data; + event_data->user_data = user_data; + + ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe, + &target_msc, event_data); + if (ret != HAL_TDM_ERROR_NONE) + goto failed_vblank; + + return HAL_TDM_ERROR_NONE; +failed_vblank: + free(event_data); + return ret; +} + +hal_tdm_error +nexell_output_set_vblank_handler(hal_tdm_output *output, + hal_tdm_output_vblank_handler func) +{ + tdm_nexell_output *output_data = output; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); + + output_data->vblank_func = func; + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_nexell_layer_add_atomic_properties(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request, + uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, + uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h) +{ + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. fb_id(%u)", fb_id); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. src_x(%u)", src_x); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. src_y(%u)", src_y); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. src_w(%u)", src_w); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. src_h(%u)", src_h); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h); + if (ret < 0) { + TDM_BACKEND_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_nexell_layer_make_atomic_request(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request) +{ + tdm_nexell_display *display_data = layer_data->display_data; + tdm_nexell_output *output_data = layer_data->output_data; + uint32_t fx, fy, fw, fh; + tdm_nexell_layer_info layer_info = layer_data->info; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + if (!layer_data->display_buffer_changed && !layer_data->info_changed) + return HAL_TDM_ERROR_NONE; + + layer_data->display_buffer_changed = 0; + layer_data->info_changed = 0; + + if (!layer_data->display_buffer) { + TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off", + display_data->drm_fd, layer_data->plane_id, output_data->crtc_id); + + ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("_nexell_layer_add_atomic_properties failed."); + return ret; + } + + return HAL_TDM_ERROR_NONE; + } + + /* Source values are 16.16 fixed point */ + fx = ((unsigned int)layer_info.src_config.pos.x) << 16; + fy = ((unsigned int)layer_info.src_config.pos.y) << 16; + fw = ((unsigned int)layer_info.src_config.pos.w) << 16; + fh = ((unsigned int)layer_info.src_config.pos.h) << 16; + + TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)", + display_data->drm_fd, layer_data->plane_id, layer_data->zpos, + output_data->crtc_id, layer_data->display_buffer->fb_id, + layer_info.src_config.pos.x, layer_info.src_config.pos.y, + layer_info.src_config.pos.w, layer_info.src_config.pos.h, + layer_info.dst_pos.x, layer_info.dst_pos.y, + layer_info.dst_pos.w, layer_info.dst_pos.h); + + ret = _nexell_layer_add_atomic_properties(layer_data, request, + layer_data->display_buffer->fb_id, output_data->crtc_id, + fx, fy, fw, fh, + layer_info.dst_pos.x, layer_info.dst_pos.y, + layer_info.dst_pos.w, layer_info.dst_pos.h); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("MakeAtomicRequest failed"); + return ret; + } + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_nexell_output_atomic_commit(hal_tdm_output *output, int sync, void *user_data) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_layer *layer_data = NULL; + tdm_nexell_event_data *event_data; + drmModeAtomicReqPtr request; + uint32_t flags = 0; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (!output_data->crtc_enabled || output_data->mode_changed) { + drmModeModeInfoPtr mode; + + layer_data = output_data->primary_layer; + if (!layer_data->display_buffer) { + TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting"); + return HAL_TDM_ERROR_BAD_REQUEST; + } + + mode = _tdm_nexell_display_get_mode(output_data); + if (!mode) { + TDM_BACKEND_ERR("couldn't find proper mode"); + return HAL_TDM_ERROR_BAD_REQUEST; + } + + if (drmModeSetCrtc(output_data->display_data->drm_fd, output_data->crtc_id, + layer_data->display_buffer->fb_id, 0, 0, + &output_data->connector_id, 1, mode)) { + TDM_BACKEND_ERR("set crtc failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED); + + output_data->crtc_enabled = 1; + output_data->mode_changed = 0; + } + + request = drmModeAtomicAlloc(); + if (!request) { + TDM_BACKEND_ERR("drmModeAtomicAlloc failed."); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + + flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; + + LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { + ret = _nexell_layer_make_atomic_request(layer_data, request); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("_nexell_layer_make_atomic_request failed."); + drmModeAtomicFree(request); + return ret; + } + } + + event_data = calloc(1, sizeof(tdm_nexell_event_data)); + if (!event_data) { + TDM_BACKEND_ERR("fail to alloc event_data."); + drmModeAtomicFree(request); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + + event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; + event_data->output_data = output_data; + event_data->user_data = user_data; + + TDM_BACKEND_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u", + output_data->pipe, output_data->crtc_id, output_data->connector_id); + + if (drmModeAtomicCommit(output_data->display_data->drm_fd, request, flags, event_data) < 0) { + TDM_BACKEND_ERR("drmModeAtomicCommit failed."); + free(event_data); + drmModeAtomicFree(request); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + drmModeAtomicFree(request); + + return HAL_TDM_ERROR_NONE; +} + +static hal_tdm_error +_nexell_output_layers_commit(hal_tdm_output *output, int sync, void *user_data) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + tdm_nexell_layer *layer_data = NULL; + hal_tdm_error ret; + int do_waitvblank = 1; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = output_data->display_data; + + LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { + if (layer_data == output_data->primary_layer) { + ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data, + &do_waitvblank); + if (ret != HAL_TDM_ERROR_NONE) + return ret; + } else { + ret = _tdm_nexell_display_commit_layer(layer_data); + if (ret != HAL_TDM_ERROR_NONE) + return ret; + } + } + + if (do_waitvblank == 1) { + tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data)); + uint target_msc; + + if (!event_data) { + TDM_BACKEND_ERR("alloc failed"); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + + ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe, + &target_msc); + if (ret != HAL_TDM_ERROR_NONE) { + free(event_data); + return ret; + } + + target_msc++; + + event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT; + event_data->output_data = output_data; + event_data->user_data = user_data; + + ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe, + &target_msc, event_data); + if (ret != HAL_TDM_ERROR_NONE) { + free(event_data); + return ret; + } + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_commit(hal_tdm_output *output, int sync, void *user_data) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = output_data->display_data; + + /* check the atomic pageflip */ + if (display_data->has_atomic) { + ret = _nexell_output_atomic_commit(output, sync, user_data); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("_nexell_output_atomic_commit failed."); + return ret; + } + } else { + ret = _nexell_output_layers_commit(output, sync, user_data); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("_nexell_output_layers_commit failed."); + return ret; + } + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_set_commit_handler(hal_tdm_output *output, + hal_tdm_output_commit_handler func) +{ + tdm_nexell_output *output_data = output; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); + + output_data->commit_func = func; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + int ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (output_data->dpms_prop_id == 0) { + TDM_BACKEND_WRN("not support DPMS"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + display_data = output_data->display_data; + ret = drmModeObjectSetProperty(display_data->drm_fd, + output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR, + output_data->dpms_prop_id, dpms_value); + if (ret < 0) { + TDM_BACKEND_ERR("set dpms failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value) +{ + tdm_nexell_output *output_data = output; + tdm_nexell_display *display_data; + drmModeObjectPropertiesPtr props; + int i; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = output_data->display_data; + props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + if (props == NULL) { + TDM_BACKEND_ERR("get property failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < props->count_props; i++) + if (props->props[i] == output_data->dpms_prop_id) { + *dpms_value = (uint)props->prop_values[i]; + break; + } + + drmModeFreeObjectProperties(props); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode) +{ + tdm_nexell_output *output_data = output; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER); + + /* create or replace the target_window when the output mode is set */ + ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret); + return ret; + } + + output_data->current_mode = mode; + output_data->mode_changed = 1; + + TDM_BACKEND_INFO("Set the output mode: %s, %d, %d, %d, %d, %d", + mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode) +{ + tdm_nexell_output *output_data = output; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER); + + *mode = output_data->current_mode; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_hwc * +nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error) +{ + tdm_nexell_hwc *hwc_data = NULL; + tdm_nexell_output *output_data = output; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + int i; + + if (!output_data) { + TDM_BACKEND_ERR("invalid params"); + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + return NULL; + } + + if (output_data->hwc_data) { + TDM_BACKEND_INFO("hwc_data already exists"); + if (error) + *error = HAL_TDM_ERROR_NONE; + return output_data->hwc_data; + } + + hwc_data = calloc(1, sizeof(tdm_nexell_hwc)); + if (!hwc_data) { + TDM_BACKEND_ERR("alloc failed"); + if (error) + *error = HAL_TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + for (i = 0; i < NUM_LAYERS; i++) { + hwc_data->ui_buffer_queue[i].tqueue = NULL; + hwc_data->ui_buffer_queue[i].ref_cnt = 0; + } + + hwc_data->output_data = output_data; + + LIST_INITHEAD(&hwc_data->hwc_window_list); + + output_data->hwc_data = hwc_data; + + ret = tdm_nexell_hwc_initailize_target_window(output_data->hwc_data); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("create target hwc window failed (%d)", ret); + free(hwc_data); + if (error) + *error = ret; + return NULL; + } + + if (error) + *error = HAL_TDM_ERROR_NONE; + + return hwc_data; +} + +hal_tdm_error +nexell_output_set_status_handler(hal_tdm_output *output, + hal_tdm_output_status_handler func, + void *user_data) +{ + tdm_nexell_output *output_data = output; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); + + output_data->status_func = func; + output_data->status_user_data = user_data; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps) +{ + tdm_nexell_display *display_data; + drmModePlanePtr plane = NULL; + drmModeObjectPropertiesPtr props = NULL; + int i, format_count = 0; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER); + + memset(caps, 0, sizeof(tdm_nexell_caps_layer)); + + display_data = layer_data->display_data; + plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id); + if (!plane) { + TDM_BACKEND_ERR("get plane failed: %m"); + ret = HAL_TDM_ERROR_OPERATION_FAILED; + goto failed_get; + } + + caps->capabilities = layer_data->capabilities; + caps->zpos = layer_data->zpos; /* if VIDEO layer_data, zpos is -1 */ + + caps->format_count = plane->count_formats; + caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count); + if (!caps->formats) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed\n"); + goto failed_get; + } + + for (i = 0; i < caps->format_count; i++) { + /* TODO: kernel reports wrong formats */ + if (plane->formats[i] != DRM_FORMAT_XRGB8888 && + plane->formats[i] != DRM_FORMAT_ARGB8888 && + plane->formats[i] != DRM_FORMAT_YUV420) { + TDM_BACKEND_WRN("plane(%d) zpos(%d) %c%c%c%c skipped", + layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i])); + continue; + } + caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]); + format_count++; + } + + caps->format_count = format_count; + + props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE); + if (!props) { + ret = HAL_TDM_ERROR_OPERATION_FAILED; + TDM_BACKEND_ERR("get plane properties failed: %m\n"); + goto failed_get; + } + + caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props); + if (!caps->props) { + ret = HAL_TDM_ERROR_OUT_OF_MEMORY; + TDM_BACKEND_ERR("alloc failed\n"); + goto failed_get; + } + + caps->prop_count = 0; + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]); + if (!prop) + continue; + if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) { + drmModeFreeProperty(prop); + continue; + } + if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) { + drmModeFreeProperty(prop); + continue; + } + snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name); + caps->props[caps->prop_count].id = props->props[i]; + caps->prop_count++; + drmModeFreeProperty(prop); + } + + drmModeFreeObjectProperties(props); + drmModeFreePlane(plane); + + return HAL_TDM_ERROR_NONE; +failed_get: + drmModeFreeObjectProperties(props); + drmModeFreePlane(plane); + free(caps->formats); + free(caps->props); + memset(caps, 0, sizeof(tdm_nexell_caps_layer)); + return ret; +} + +hal_tdm_error +nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value) +{ + tdm_nexell_display *display_data; + int ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = layer_data->display_data; + ret = drmModeObjectSetProperty(display_data->drm_fd, + layer_data->plane_id, DRM_MODE_OBJECT_PLANE, + id, value.u32); + if (ret < 0) { + TDM_BACKEND_ERR("set property failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value) +{ + tdm_nexell_display *display_data; + drmModeObjectPropertiesPtr props; + int i; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = layer_data->display_data; + props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id, + DRM_MODE_OBJECT_PLANE); + if (props == NULL) { + TDM_BACKEND_ERR("get property failed: %m"); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < props->count_props; i++) + if (props->props[i] == id) { + (*value).u32 = (uint)props->prop_values[i]; + break; + } + + drmModeFreeObjectProperties(props); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); + + layer_data->info = *info; + layer_data->info_changed = 1; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); + + *info = layer_data->info; + + return HAL_TDM_ERROR_NONE; +} + +static tdm_nexell_display_buffer * +_tdm_nexell_display_find_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer) +{ + tdm_nexell_display_buffer *display_buffer = NULL; + + LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) { + if (display_buffer->buffer == buffer) + return display_buffer; + } + + return NULL; +} + +static void +_tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data) +{ + tdm_nexell_display *display_data; + tdm_nexell_display_buffer *display_buffer; + tdm_nexell_layer *layer_data = NULL; + tdm_nexell_output *output_data = NULL; + char buf[256] = {0,}; + char *ret_tmp; + + if (!user_data) { + TDM_BACKEND_ERR("no user_data"); + return; + } + if (!buffer) { + TDM_BACKEND_ERR("no buffer"); + return; + } + + display_data = (tdm_nexell_display *) user_data; + + display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer); + if (!display_buffer) { + TDM_BACKEND_ERR("no display_buffer"); + return; + } + + LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) { + LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { + if (display_buffer == layer_data->display_buffer) + layer_data->display_buffer = NULL; + } + } + + if (display_buffer->fb_id > 0) { + if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) { + ret_tmp = strerror_r(errno, buf, sizeof(buf)); + TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp); + } + } + + TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer); + + LIST_DEL(&display_buffer->link); + free(display_buffer); +} + +static tdm_nexell_display_buffer * +_tdm_nexell_display_create_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer, hal_tdm_error *err) +{ + tdm_nexell_display_buffer *display_buffer = NULL; + int count, i, ret; + + display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer)); + if (!display_buffer) { + TDM_BACKEND_ERR("alloc failed"); + if (err) + *err = HAL_TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + display_buffer->buffer = buffer; + + ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); + if (ret == 0) { + TDM_BACKEND_ERR("add destroy handler fail"); + free(display_buffer); + if (err) + *err = HAL_TDM_ERROR_OPERATION_FAILED; + return NULL; + } + + display_buffer->width = tbm_surface_get_width(buffer); + display_buffer->height = tbm_surface_get_height(buffer); + display_buffer->format = tbm_surface_get_format(buffer); + display_buffer->count = tbm_surface_internal_get_num_bos(buffer); + count = tbm_surface_internal_get_num_planes(display_buffer->format); + TDM_BACKEND_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d", + buffer, display_buffer->width, display_buffer->height, + FOURCC_STR(display_buffer->format), display_buffer->count, count); + + for (i = 0; i < count; i++) { + int bo_idx = 0; + tbm_bo bo = NULL; + + bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i); + bo = tbm_surface_internal_get_bo(buffer, bo_idx); + display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; + + tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size, + &display_buffer->offsets[i], + &display_buffer->pitches[i]); + TDM_BACKEND_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)", + i, display_buffer->size, display_buffer->offsets[i], + display_buffer->pitches[i], bo_idx, display_buffer->handles[i]); + } + + ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height, + display_buffer->format, display_buffer->handles, display_buffer->pitches, + display_buffer->offsets, &display_buffer->fb_id, 0); + if (ret < 0) { + TDM_BACKEND_ERR("add fb failed: %m"); + free(display_buffer); + if (err) + *err = HAL_TDM_ERROR_OPERATION_FAILED; + tbm_surface_internal_remove_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); + return NULL; + } + + TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd, + display_buffer->fb_id); + + if (IS_RGB(display_buffer->format)) + display_buffer->width = display_buffer->pitches[0] >> 2; + else + display_buffer->width = display_buffer->pitches[0]; + + LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list); + + if (err) + *err = HAL_TDM_ERROR_NONE; + + return display_buffer; +} + +void +tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data) +{ + tdm_nexell_display_buffer *b = NULL, *bb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) { + tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, display_data); + _tdm_nexell_display_cb_destroy_buffer(b->buffer, display_data); + } +} + +hal_tdm_error +nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer) +{ + tdm_nexell_display *display_data; + tdm_nexell_display_buffer *display_buffer; + hal_tdm_error err = HAL_TDM_ERROR_NONE; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = layer_data->display_data; + display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer); + if (!display_buffer) { + display_buffer = _tdm_nexell_display_create_buffer(display_data, buffer, &err); + TDM_BACKEND_RETURN_VAL_IF_FAIL(display_buffer != NULL, err); + } + + if (layer_data->display_buffer != display_buffer) { + if (layer_data->display_buffer) + tbm_surface_internal_unref(layer_data->display_buffer->buffer); + + layer_data->display_buffer = display_buffer; + tbm_surface_internal_ref(layer_data->display_buffer->buffer); + layer_data->display_buffer_changed = 1; + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_layer_unset_buffer(tdm_nexell_layer *layer_data) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (!(layer_data->capabilities & TDM_NEXELL_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) { + tbm_surface_internal_unref(layer_data->display_buffer->buffer); + layer_data->display_buffer = NULL; + } + + layer_data->display_buffer_changed = 1; + + return HAL_TDM_ERROR_NONE; +} + +tdm_nexell_layer * +nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zpos) +{ + tdm_nexell_layer *l = NULL; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, NULL); + + LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) { + if (l->zpos == layer_zpos) + return l; + } + + return NULL; +} diff --git a/src/tdm_nexell_format.c b/src/tdm_nexell_format.c new file mode 100644 index 0000000..ffe5ef2 --- /dev/null +++ b/src/tdm_nexell_format.c @@ -0,0 +1,131 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +typedef struct { + tbm_format tbm_format; + uint32_t drm_format; +} tbm_drm_format_data; + +static const tbm_drm_format_data formats[] = { + {TBM_FORMAT_C8, DRM_FORMAT_C8}, + {TBM_FORMAT_RGB332, DRM_FORMAT_RGB332}, + {TBM_FORMAT_BGR233, DRM_FORMAT_BGR233}, + {TBM_FORMAT_XRGB4444, DRM_FORMAT_XRGB4444}, + {TBM_FORMAT_XBGR4444, DRM_FORMAT_XBGR4444}, + {TBM_FORMAT_RGBX4444, DRM_FORMAT_RGBX4444}, + {TBM_FORMAT_BGRX4444, DRM_FORMAT_BGRX4444}, + {TBM_FORMAT_ARGB4444, DRM_FORMAT_ARGB4444}, + {TBM_FORMAT_ABGR4444, DRM_FORMAT_ABGR4444}, + {TBM_FORMAT_RGBA4444, DRM_FORMAT_RGBA4444}, + {TBM_FORMAT_BGRA4444, DRM_FORMAT_BGRA4444}, + {TBM_FORMAT_XRGB1555, DRM_FORMAT_XRGB1555}, + {TBM_FORMAT_XBGR1555, DRM_FORMAT_XBGR1555}, + {TBM_FORMAT_RGBX5551, DRM_FORMAT_RGBX5551}, + {TBM_FORMAT_BGRX5551, DRM_FORMAT_BGRX5551}, + {TBM_FORMAT_ARGB1555, DRM_FORMAT_ARGB1555}, + {TBM_FORMAT_ABGR1555, DRM_FORMAT_ABGR1555}, + {TBM_FORMAT_RGBA5551, DRM_FORMAT_RGBA5551}, + {TBM_FORMAT_BGRA5551, DRM_FORMAT_BGRA5551}, + {TBM_FORMAT_RGB565, DRM_FORMAT_RGB565}, + {TBM_FORMAT_BGR565, DRM_FORMAT_BGR565}, + {TBM_FORMAT_RGB888, DRM_FORMAT_RGB888}, + {TBM_FORMAT_BGR888, DRM_FORMAT_BGR888}, + {TBM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888}, + {TBM_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888}, + {TBM_FORMAT_RGBX8888, DRM_FORMAT_RGBX8888}, + {TBM_FORMAT_BGRX8888, DRM_FORMAT_BGRX8888}, + {TBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888}, + {TBM_FORMAT_ABGR8888, DRM_FORMAT_ABGR8888}, + {TBM_FORMAT_RGBA8888, DRM_FORMAT_RGBA8888}, + {TBM_FORMAT_BGRA8888, DRM_FORMAT_BGRA8888}, + {TBM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB2101010}, + {TBM_FORMAT_XBGR2101010, DRM_FORMAT_XBGR2101010}, + {TBM_FORMAT_RGBX1010102, DRM_FORMAT_RGBX1010102}, + {TBM_FORMAT_BGRX1010102, DRM_FORMAT_BGRX1010102}, + {TBM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB2101010}, + {TBM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR2101010}, + {TBM_FORMAT_RGBA1010102, DRM_FORMAT_RGBA1010102}, + {TBM_FORMAT_BGRA1010102, DRM_FORMAT_BGRA1010102}, + {TBM_FORMAT_YUYV, DRM_FORMAT_YUYV}, + {TBM_FORMAT_YVYU, DRM_FORMAT_YVYU}, + {TBM_FORMAT_UYVY, DRM_FORMAT_UYVY}, + {TBM_FORMAT_VYUY, DRM_FORMAT_VYUY}, + {TBM_FORMAT_AYUV, DRM_FORMAT_AYUV}, + {TBM_FORMAT_NV12, DRM_FORMAT_NV12}, + {TBM_FORMAT_NV21, DRM_FORMAT_NV21}, + {TBM_FORMAT_NV16, DRM_FORMAT_NV16}, + {TBM_FORMAT_NV61, DRM_FORMAT_NV61}, + {TBM_FORMAT_YUV410, DRM_FORMAT_YUV410}, + {TBM_FORMAT_YVU410, DRM_FORMAT_YVU410}, + {TBM_FORMAT_YUV411, DRM_FORMAT_YUV411}, + {TBM_FORMAT_YVU411, DRM_FORMAT_YVU411}, + {TBM_FORMAT_YUV420, DRM_FORMAT_YUV420}, + {TBM_FORMAT_YVU420, DRM_FORMAT_YVU420}, + {TBM_FORMAT_YUV422, DRM_FORMAT_YUV422}, + {TBM_FORMAT_YVU422, DRM_FORMAT_YVU422}, + {TBM_FORMAT_YUV444, DRM_FORMAT_YUV444}, + {TBM_FORMAT_YVU444, DRM_FORMAT_YVU444}, +}; + +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) + +uint32_t +tdm_nexell_format_to_drm_format(tbm_format format) +{ + int i; + + for (i = 0; i < NUM_FORMATS; i++) + if (formats[i].tbm_format == format) + return formats[i].drm_format; + + TDM_BACKEND_ERR("tbm format '%c%c%c%c' not found", FOURCC_STR(format)); + + return 0; +} + +tbm_format +tdm_nexell_format_to_tbm_format(uint32_t format) +{ + int i; + + for (i = 0; i < NUM_FORMATS; i++) + if (formats[i].drm_format == format) + return formats[i].tbm_format; + + TDM_BACKEND_ERR("drm format '%c%c%c%c' not found", FOURCC_STR(format)); + + return 0; +} diff --git a/src/tdm_nexell_hwc.c b/src/tdm_nexell_hwc.c new file mode 100644 index 0000000..bec0ea3 --- /dev/null +++ b/src/tdm_nexell_hwc.c @@ -0,0 +1,980 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +#define MIN_WIDTH 32 + +tbm_format hwc_window_video_formats[] = { + TBM_FORMAT_NV12, + TBM_FORMAT_YUV420 +}; + +const char * +_comp_to_str(hal_tdm_hwc_window_composition composition_type) +{ + if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) + return "CLIENT"; + else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_DEVICE) + return "DEVICE"; + else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR) + return "CURSOR"; + else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_VIDEO) + return "VIDEO"; + else if (composition_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) + return "SKIP"; + + return "unknown"; +} + +static int +_nexell_hwc_cursor_buffer_image_render(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) +{ + tbm_surface_info_s tsurface_info; + tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE; + void *src_ptr = NULL, *dst_ptr = NULL; + int src_stride, transform, img_w, img_h; + pixman_image_t *src_img = NULL, *dst_img = NULL; + pixman_transform_t t; + struct pixman_f_transform ft; + int c = 0, s = 0, tx = 0, ty = 0; + int i; + + ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info); + if (ret != TBM_SURFACE_ERROR_NONE) { + TDM_BACKEND_ERR("Failed to map tsurface\n"); + return 0; + } + + src_ptr = hwc_window_data->cursor_img.ptr; + src_stride = hwc_window_data->cursor_img.stride; + img_w = hwc_window_data->cursor_img.width; + img_h = hwc_window_data->cursor_img.height; + transform = hwc_window_data->info.transform; + + dst_ptr = tsurface_info.planes[0].ptr; + + memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height); + + if (transform) { + src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride); + if (!src_img) { + TDM_BACKEND_ERR("Failed to create src pixman\n"); + return 0; + } + + dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info.width, tsurface_info.height, + (uint32_t*)dst_ptr, tsurface_info.planes[0].stride); + if (!dst_img) { + TDM_BACKEND_ERR("Failed to create dst pixman\n"); + pixman_image_unref(src_img); + return 0; + } + + pixman_f_transform_init_identity(&ft); + + if (transform >= HAL_TDM_TRANSFORM_FLIPPED) { + pixman_f_transform_scale(&ft, NULL, -1, 1); + pixman_f_transform_translate(&ft, NULL, tsurface_info.width, 0); + } + + switch (transform) { + case HAL_TDM_TRANSFORM_90: + case HAL_TDM_TRANSFORM_FLIPPED_90: + c = 0, s = 1, ty = -tsurface_info.height; + break; + case HAL_TDM_TRANSFORM_180: + case HAL_TDM_TRANSFORM_FLIPPED_180: + c = -1, s = 0, tx = -tsurface_info.width, ty = -tsurface_info.height; + break; + case HAL_TDM_TRANSFORM_270: + case HAL_TDM_TRANSFORM_FLIPPED_270: + c = 0, s = -1, tx = -tsurface_info.width; + break; + default: + break; + } + + pixman_f_transform_translate(&ft, NULL, tx, ty); + pixman_f_transform_rotate(&ft, NULL, c, s); + pixman_transform_from_pixman_f_transform(&t, &ft); + pixman_image_set_transform(src_img, &t); + pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, + tsurface_info.width, tsurface_info.height); + pixman_image_unref(src_img); + pixman_image_unref(dst_img); + } + else { + for (i = 0 ; i < img_h ; i++) { + memcpy(dst_ptr, src_ptr, src_stride); + dst_ptr += tsurface_info.planes[0].stride; + src_ptr += src_stride; + } + } + + tbm_surface_unmap(hwc_data->cursor_tsurface); + + return 1; +} + +static int +_nexell_hwc_cursor_window_surface_clear(tdm_nexell_hwc_window_data *hwc_window_data) +{ + hwc_window_data->surface = NULL; + hwc_window_data->cursor_img_surface = 0; + + hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width; + hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height; + hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width; + hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height; + + return 1; +} + +static void +_nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc *hwc_data) +{ + if (hwc_data->cursor_tsurface) { + tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); + hwc_data->cursor_tsurface = NULL; + } + + if (hwc_data->cursor_tqueue) { + tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->cursor_tqueue); + hwc_data->cursor_tqueue = NULL; + } +} + +static void +_nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) +{ + int x, y, width, height; + + width = tbm_surface_get_width(hwc_data->cursor_tsurface); + height = tbm_surface_get_height(hwc_data->cursor_tsurface); + + hwc_window_data->info.src_config.pos.w = width; + hwc_window_data->info.src_config.pos.h = height; + hwc_window_data->info.dst_pos.w = width; + hwc_window_data->info.dst_pos.h = height; + + /* dst pos of cursor is possible set by negative value + * this is temporary code. + */ + x = hwc_window_data->info.dst_pos.x; + y = hwc_window_data->info.dst_pos.y; + + if (x < 0) hwc_window_data->info.dst_pos.x = 0; + if (y < 0) hwc_window_data->info.dst_pos.y = 0; +} + +static int +_nexell_hwc_cursor_buffer_set(tdm_nexell_hwc *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data) +{ + tbm_surface_h cursor_tsurface = NULL; + tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE; + int img_w, img_h; + int tqueue_w, tqueue_h; + hal_tdm_error error; + + if (hwc_window_data->cursor_img_refresh || !hwc_window_data->surface) { + switch (hwc_window_data->info.transform) { + case HAL_TDM_TRANSFORM_90: + case HAL_TDM_TRANSFORM_FLIPPED_90: + case HAL_TDM_TRANSFORM_270: + case HAL_TDM_TRANSFORM_FLIPPED_270: + img_w = hwc_window_data->cursor_img.height; + img_h = hwc_window_data->cursor_img.width; + break; + default: + img_w = hwc_window_data->cursor_img.width; + img_h = hwc_window_data->cursor_img.height; + break; + } + + if (!hwc_data->cursor_tqueue) { + hwc_data->cursor_tqueue = tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hwc_window_data, &error); + if (error != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("Failed to create cursor buffer queue error:%d", error); + return 0; + } + } else { + tqueue_w = tbm_surface_queue_get_width(hwc_data->cursor_tqueue); + tqueue_h = tbm_surface_queue_get_height(hwc_data->cursor_tqueue); + if ((img_w != tqueue_w) || (img_h != tqueue_h)) + tbm_surface_queue_reset(hwc_data->cursor_tqueue, img_w, img_h, TBM_FORMAT_ARGB8888); + } + + if (hwc_data->cursor_tsurface) { + tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); + hwc_data->cursor_tsurface = NULL; + } + + if (!tbm_surface_queue_can_dequeue(hwc_data->cursor_tqueue, 0)) { + TDM_BACKEND_ERR("Can't dequeue cursor tqueue"); + return 0; + } + + tsq_error = tbm_surface_queue_dequeue(hwc_data->cursor_tqueue, &cursor_tsurface); + if (tsq_error != TBM_SURFACE_QUEUE_ERROR_NONE) { + TDM_BACKEND_ERR("Failed to dequeue cursor tqueue error:%d", tsq_error); + return 0; + } + + hwc_data->cursor_tsurface = cursor_tsurface; + + _nexell_hwc_cursor_buffer_image_render(hwc_data, hwc_window_data); + + hwc_window_data->surface = cursor_tsurface; + hwc_window_data->cursor_img_surface = 1; + hwc_window_data->cursor_img_refresh = 0; + } + + _nexell_hwc_cursor_adjust_pos(hwc_data, hwc_window_data); + + return 1; +} + +static void +_print_validate_result(tdm_nexell_hwc *hwc_data, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds) +{ + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + int i; + int lzpos_queue; + + for (i = 0; i < num_wnds; i++) { + hwc_window_data = composited_wnds[i]; + lzpos_queue = hwc_window_data->lzpos_queue; + switch (hwc_window_data->validated_type) { + case HAL_TDM_HWC_WIN_COMPOSITION_CLIENT: + TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data, + _comp_to_str(hwc_window_data->client_type), + _comp_to_str(hwc_window_data->validated_type), + hwc_data->target_hwc_window->lzpos, + lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, + lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, + hwc_window_data->name ? hwc_window_data->name : "NONE"); + break; + case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: + case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: + case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: + case HAL_TDM_HWC_WIN_COMPOSITION_NONE: + TDM_BACKEND_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s}", hwc_window_data, + _comp_to_str(hwc_window_data->client_type), + _comp_to_str(hwc_window_data->validated_type), + hwc_window_data->lzpos, + lzpos_queue, lzpos_queue == -1 ? NULL : hwc_data->ui_buffer_queue[lzpos_queue].tqueue, + lzpos_queue == -1 ? 0 : hwc_data->ui_buffer_queue[lzpos_queue].ref_cnt, + hwc_window_data->name ? hwc_window_data->name : "NONE"); + break; + default: + break; + } + } +} + +static int +_nexell_hwc_window_has_reserved_buffer(tdm_nexell_hwc_window_data *hwc_window_data) { + tbm_bo bo = NULL; + int flags = 0; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, 0); + + bo = tbm_surface_internal_get_bo(hwc_window_data->surface, 0); + TDM_BACKEND_RETURN_VAL_IF_FAIL(bo != NULL, 0); + + flags = tbm_bo_get_flags(bo); + + return flags & TBM_BO_SCANOUT; +} + +static int +_nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data, int bottom) +{ + if (!hwc_window_data->surface) + return 0; + + if (hwc_window_data->info.transform != HAL_TDM_TRANSFORM_NORMAL) + return 0; + + if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w) + return 0; + + if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h) + return 0; + + if (!IS_RGB(hwc_window_data->info.src_config.format)) + return 0; + + if ((hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || + (hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) + return 0; + + if (bottom) { + if ((hwc_window_data->info.dst_pos.w != hwc_window_data->hwc_data->output_data->current_mode->hdisplay) || + (hwc_window_data->info.dst_pos.h != hwc_window_data->hwc_data->output_data->current_mode->vdisplay)) + return 0; + } + + return 1; +} + +tbm_surface_queue_h +tdm_nexell_hwc_window_create_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) +{ + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + tbm_format format; + + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); + + hwc_window_data = hwc_window; + + width = hwc_window_data->info.src_config.pos.w; + height = hwc_window_data->info.src_config.pos.h; + format = hwc_window_data->info.src_config.format; + + tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); + if (error) + *error = HAL_TDM_ERROR_OPERATION_FAILED; + TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); + + if (error) + *error = HAL_TDM_ERROR_NONE; + + return tqueue; +} + +tbm_surface_queue_h +tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) +{ + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); + + hwc_window_data = hwc_window; + + switch (hwc_window_data->info.transform) { + case HAL_TDM_TRANSFORM_90: + case HAL_TDM_TRANSFORM_FLIPPED_90: + case HAL_TDM_TRANSFORM_270: + case HAL_TDM_TRANSFORM_FLIPPED_270: + width = hwc_window_data->cursor_img.height; + height = hwc_window_data->cursor_img.width; + break; + default: + width = hwc_window_data->cursor_img.width; + height = hwc_window_data->cursor_img.height; + break; + } + + tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT); + if (error) + *error = HAL_TDM_ERROR_OPERATION_FAILED; + TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); + + tbm_surface_queue_set_modes(tqueue, TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE); + + if (error) + *error = HAL_TDM_ERROR_NONE; + + return tqueue; +} + +void +tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue) +{ + tbm_surface_queue_destroy(tqueue); +} + +static hal_tdm_error +_nexell_hwc_layer_attach_window(tdm_nexell_layer *layer_data, tdm_nexell_hwc_window_data *hwc_window_data) +{ + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_OPERATION_FAILED); + + if (hwc_window_data == NULL || hwc_window_data->surface == NULL) { + if (layer_data->display_buffer) + ret = nexell_layer_unset_buffer(layer_data); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + } else { + ret = nexell_layer_set_info((tdm_nexell_layer *)layer_data, (tdm_nexell_layer_info *)&(hwc_window_data->info)); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + ret = nexell_layer_set_buffer(layer_data, hwc_window_data->surface); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + } + + return ret; +} + +static hal_tdm_error +_nexell_hwc_prepare_commit(tdm_nexell_hwc *hwc_data) +{ + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + tdm_nexell_layer *layer_data = NULL; + int use_layers_zpos[NUM_LAYERS] = {0,}; + int lzpos = 0; + int cursor_enabled = 0; + + /* set target hwc window to the layer_data */ + if (hwc_data->need_target_window) { + layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos); + _nexell_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window); + use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1; + } + + /* set the hwc_windows to the layers */ + LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE || + hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CLIENT) { + if (hwc_window_data->cursor_img_surface) + _nexell_hwc_cursor_window_surface_clear(hwc_window_data); + + continue; + } + + if (hwc_window_data == hwc_data->target_hwc_window) + continue; + + /* set the cursor buffer HERE if it needs */ + if (hwc_window_data->validated_type == HAL_TDM_HWC_WIN_COMPOSITION_CURSOR) { + _nexell_hwc_cursor_buffer_set(hwc_data, hwc_window_data); + cursor_enabled = 1; + } + + layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos); + _nexell_hwc_layer_attach_window(layer_data, hwc_window_data); + use_layers_zpos[hwc_window_data->lzpos] = 1; + } + + /* unset the unused layers */ + for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) { + if (use_layers_zpos[lzpos]) + continue; + + layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, lzpos); + if (!layer_data) + continue; + + _nexell_hwc_layer_attach_window(layer_data, NULL); + } + + if (!cursor_enabled) + _nexell_hwc_cursor_buffer_unset(hwc_data); + + /* for debug */ + for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) { + if (use_layers_zpos[lzpos]) + TDM_BACKEND_DBG(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET"); + } + + return HAL_TDM_ERROR_NONE; +} + +/* assign the validated_type to the composited_wnds + * assign the layer_zpos to the composited_wnds + */ +static void +_nexell_hwc_apply_policy(tdm_nexell_hwc *hwc_data , hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds) +{ + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + tdm_nexell_hwc_window_data **composited_list = NULL; + int client_count = 0; + int device_count = 0; + int video_count = 0; + int cursor_count = 0; + int ui_lzpos_top = ZPOS_2; + int ui_lzpos_bottom = ZPOS_1; + int num_ui_layers = NUM_UI_LAYERS; + int set_clients_below = 0; + int i = 0; + + composited_list = (tdm_nexell_hwc_window_data **)composited_wnds; + + /* initialize the need_target_window */ + hwc_data->need_target_window = 0; + + /* initialize the validated_types and constraints */ + LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { + hwc_window_data->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE; + hwc_window_data->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_NONE; + hwc_window_data->lzpos = -1; + hwc_window_data->lzpos_queue = -1; + } + + /* use the target_window to commit when there is no window. */ + if (num_wnds == 0) { + hwc_data->need_target_window = 1; + hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; + hwc_data->target_hwc_window->lzpos_queue = ui_lzpos_bottom; + return; + } + + /* 1. first check validate_type without target_window */ + for (i = 0; i < num_wnds; i++) { + switch (composited_list[i]->client_type) { + case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: + composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_VIDEO; + video_count++; + continue; + case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: + if (set_clients_below) break; + if (num_ui_layers <= 0) break; + + composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CURSOR; + cursor_count++; + num_ui_layers--; + continue; + case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: + if (set_clients_below) break; + if (num_ui_layers <= 0) break; + + if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i], (i == num_wnds - 1))) + break; + + if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i])) { + composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; + break; + } + + composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_DEVICE; + composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE; + device_count++; + num_ui_layers--; + continue; + default: + break; + } + + composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT; + client_count++; + set_clients_below = 1; + } + + /* 2. check need target window and set ui_lzpos top and bottom */ + num_ui_layers = NUM_UI_LAYERS; + if (client_count > 0) { + hwc_data->need_target_window = 1; + hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom; + ui_lzpos_bottom++; + num_ui_layers--; + } + + if (num_ui_layers > (device_count + cursor_count)) + ui_lzpos_top = ui_lzpos_bottom + device_count + cursor_count - 1; + + /* 3. set lzpos and modify validate_type with target_window */ + for (i = 0; i < num_wnds; i++) { + switch (composited_list[i]->validated_type) { + case HAL_TDM_HWC_WIN_COMPOSITION_VIDEO: + composited_list[i]->lzpos = ZPOS_VIDEO1; + continue; + case HAL_TDM_HWC_WIN_COMPOSITION_CURSOR: + case HAL_TDM_HWC_WIN_COMPOSITION_DEVICE: + if (num_ui_layers <= 0) break; + + composited_list[i]->lzpos = ui_lzpos_top; + composited_list[i]->lzpos_queue = ui_lzpos_top; + ui_lzpos_top--; + num_ui_layers--; + continue; + default: + break; + } + + composited_list[i]->validated_type = HAL_TDM_HWC_WIN_COMPOSITION_CLIENT; + + if (composited_list[i]->constraints == HAL_TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE) { + if (i == num_wnds - 1) //set target window queue zpos + composited_list[i]->lzpos_queue = ui_lzpos_top; + else if(num_ui_layers > 0) + composited_list[i]->lzpos_queue = ui_lzpos_top + 1; + else + composited_list[i]->constraints = HAL_TDM_HWC_WIN_CONSTRAINT_NONE; + } + } +} + +static int +_nexell_hwc_get_changed_number(tdm_nexell_hwc *hwc_data) +{ + int num = 0; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + + LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) + continue; + + if (hwc_window_data->client_type != hwc_window_data->validated_type) + num++; + } + + return num; +} + +hal_tdm_hwc_window * +_nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_hwc_window_info *info, hal_tdm_error *error) +{ + tdm_nexell_hwc *hwc_data = hwc; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + + if (error) + *error = HAL_TDM_ERROR_NONE; + + if (!hwc_data) { + TDM_BACKEND_ERR("invalid params"); + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + return NULL; + } + + hwc_window_data = calloc(1, sizeof(tdm_nexell_hwc_window_data)); + if (!hwc_window_data) { + TDM_BACKEND_ERR("alloc failed"); + if (error) + *error = HAL_TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + hwc_window_data->hwc_data = hwc_data; + + if (info) + memcpy(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info)); + + LIST_INITHEAD(&hwc_window_data->link); + + return hwc_window_data; +} + +hal_tdm_hwc_window * +nexell_hwc_create_window(hal_tdm_hwc *hwc, hal_tdm_error *error) +{ + tdm_nexell_hwc *hwc_data = hwc; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, NULL); + + hwc_window_data = _nexell_hwc_create_window(hwc_data, NULL, error); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data, NULL); + + LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list); + + TDM_BACKEND_DBG("hwc_window(%p) create", hwc_window_data); + if (error) + *error = HAL_TDM_ERROR_NONE; + + return hwc_window_data; +} + +hal_tdm_error +nexell_hwc_get_video_supported_formats(hal_tdm_hwc *hwc, const tbm_format **formats, int *count) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(formats != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + // TODO: fix these formats. + *formats = hwc_window_video_formats; + *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_get_capabilities(hal_tdm_hwc *hwc, hal_tdm_hwc_capability *capabilities) +{ + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(capabilities != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + *capabilities |= HAL_TDM_HWC_CAPABILITY_VIDEO_SCALE; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_get_available_properties(hal_tdm_hwc *hwc, const hal_tdm_prop **props, int *count) +{ + tdm_nexell_hwc *hwc_data = hwc; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(props != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(count != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + *props = NULL; + *count = 0; + + return HAL_TDM_ERROR_NONE; +} + +tbm_surface_queue_h +nexell_hwc_get_client_target_buffer_queue(hal_tdm_hwc *hwc, hal_tdm_error *error) +{ + tdm_nexell_hwc *hwc_data = hwc; + tbm_surface_queue_h tqueue = NULL; + + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); + + if (hwc_data->target_hwc_window == NULL) { + if (error) + *error = HAL_TDM_ERROR_OPERATION_FAILED; + return NULL; + } + + tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_data->target_hwc_window, error); + TDM_BACKEND_RETURN_VAL_IF_FAIL(tqueue, NULL); + + hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue; + hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1; + + if (error) + *error = HAL_TDM_ERROR_NONE; + + return tqueue; +} + +hal_tdm_error +nexell_hwc_set_client_target_buffer(hal_tdm_hwc *hwc, tbm_surface_h buffer, hal_tdm_region damage) +{ + tdm_nexell_hwc *hwc_data = hwc; + hal_tdm_error err; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, HAL_TDM_ERROR_OPERATION_FAILED); + + err = nexell_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer); + TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err); + + err = nexell_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage); + TDM_BACKEND_RETURN_VAL_IF_FAIL(err == HAL_TDM_ERROR_NONE, err); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_validate(hal_tdm_hwc *hwc, hal_tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) +{ + tdm_nexell_hwc *hwc_data = hwc; + tdm_nexell_output *output_data; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(num_types != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + output_data = hwc_data->output_data; + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + TDM_BACKEND_DBG(" ==============Validate================================="); + + /* adapt policy */ + _nexell_hwc_apply_policy(hwc_data, composited_wnds, num_wnds); + + *num_types = _nexell_hwc_get_changed_number(hwc_data); + + _print_validate_result(hwc_data, composited_wnds, num_wnds); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_get_changed_composition_types(hal_tdm_hwc *hwc, uint32_t *num_elements, + hal_tdm_hwc_window **hwc_wnds, hal_tdm_hwc_window_composition *composition_types) +{ + tdm_nexell_hwc *hwc_data = hwc; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + int num = 0; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(num_elements != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + if ((hwc_wnds == NULL) || (composition_types == NULL)) { + *num_elements = _nexell_hwc_get_changed_number(hwc_data); + return HAL_TDM_ERROR_NONE; + } + + LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->client_type == HAL_TDM_HWC_WIN_COMPOSITION_NONE) + continue; + + if (num >= *num_elements) + break; + + if (hwc_window_data->client_type != hwc_window_data->validated_type) { + composition_types[num] = hwc_window_data->validated_type; + hwc_wnds[num] = hwc_window_data; + num++; + } + } + + /* set real num of changed composition types */ + *num_elements = num; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_accept_validation(hal_tdm_hwc *hwc) +{ + tdm_nexell_hwc *hwc_data = hwc; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + TDM_BACKEND_DBG(" ==============Accept Changes Done================================="); + + ret = _nexell_hwc_prepare_commit(hwc_data); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_commit(hal_tdm_hwc *hwc, int sync, void *user_data) +{ + tdm_nexell_hwc *hwc_data = hwc; + tdm_nexell_output *output_data = NULL; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + output_data = hwc_data->output_data; + TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + TDM_BACKEND_DBG(" ==============COMMIT================================="); + + ret = nexell_output_commit(output_data, sync, user_data); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_set_commit_handler(hal_tdm_hwc *hwc, hal_tdm_hwc_commit_handler func) +{ + tdm_nexell_hwc *hwc_data = hwc; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); + + hwc_data->commit_func = func; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_target_window_set_info(tdm_nexell_hwc *hwc_data, int width, int height) +{ + hal_tdm_hwc_window_info info = {0}; + tdm_nexell_hwc_window_data *target_hwc_window; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, HAL_TDM_ERROR_INVALID_PARAMETER); + + target_hwc_window = hwc_data->target_hwc_window; + + info.dst_pos.x = 0; + info.dst_pos.y = 0; + info.dst_pos.w = width; + info.dst_pos.h = height; + + info.src_config.pos.x = 0; + info.src_config.pos.y = 0; + info.src_config.pos.w = width; + info.src_config.pos.h = height; + + info.src_config.size.h = width; + info.src_config.size.v = height; + info.src_config.format = TBM_FORMAT_ARGB8888; + + ret = nexell_hwc_window_set_info(target_hwc_window, &info); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +tdm_nexell_hwc_initailize_target_window(tdm_nexell_hwc *hwc_data) +{ + hal_tdm_hwc_window_info info = {0}; + hal_tdm_error ret = HAL_TDM_ERROR_NONE; + tdm_nexell_hwc_window_data *target_hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + info.dst_pos.x = 0; + info.dst_pos.y = 0; + info.dst_pos.w = 2; + info.dst_pos.h = 1; + + info.src_config.pos.x = 0; + info.src_config.pos.y = 0; + info.src_config.pos.w = 2; + info.src_config.pos.h = 1; + + info.src_config.size.h = 2; + info.src_config.size.v = 1; + info.src_config.format = TBM_FORMAT_ARGB8888; + + target_hwc_window = _nexell_hwc_create_window(hwc_data, &info, &ret); + if (ret != HAL_TDM_ERROR_NONE) { + TDM_BACKEND_ERR("create target hwc window failed (%d)", ret); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + if (hwc_data->target_hwc_window) + nexell_hwc_window_destroy(hwc_data->target_hwc_window); + + hwc_data->target_hwc_window = target_hwc_window; + hwc_data->need_set_crtc = 1; + + return HAL_TDM_ERROR_NONE; +} diff --git a/src/tdm_nexell_hwc_window.c b/src/tdm_nexell_hwc_window.c new file mode 100644 index 0000000..8e9c34c --- /dev/null +++ b/src/tdm_nexell_hwc_window.c @@ -0,0 +1,270 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +tbm_surface_queue_h +nexell_hwc_window_acquire_buffer_queue(hal_tdm_hwc_window *hwc_window, hal_tdm_error *error) +{ + tdm_nexell_hwc *hwc_data = NULL; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + + if (error) + *error = HAL_TDM_ERROR_INVALID_PARAMETER; + + hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, NULL); + + hwc_data = hwc_window_data->hwc_data; + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); + + if (error) + *error = HAL_TDM_ERROR_NONE; + + if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue >= NUM_LAYERS)) { + TDM_BACKEND_ERR("invliad hwc_window:%p lzpos_queue:%d", hwc_window_data, hwc_window_data->lzpos); + if (error) + *error = HAL_TDM_ERROR_OPERATION_FAILED; + + return NULL; + } + + if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue) { + tqueue = hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue; + hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; + } else { + tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window, error); + if (!tqueue) { + TDM_BACKEND_ERR("fail to create buffer queue"); + return NULL; + } + + hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue = tqueue; + hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++; + } + + // target buffer queue can't be reset + if (hwc_window_data->lzpos_queue != ZPOS_1) { + width = tbm_surface_queue_get_width(tqueue); + height = tbm_surface_queue_get_height(tqueue); + + if ((hwc_window_data->info.src_config.pos.w != width) || + (hwc_window_data->info.src_config.pos.h != height)) + { + tbm_surface_queue_reset(tqueue, + hwc_window_data->info.src_config.pos.w, + hwc_window_data->info.src_config.pos.h, + hwc_window_data->info.src_config.format); + } + } + + return tqueue; +} + +void +nexell_hwc_window_release_buffer_queue(hal_tdm_hwc_window *hwc_window, tbm_surface_queue_h queue) +{ + tdm_nexell_hwc *hwc_data = NULL; + tdm_nexell_hwc_window_data *hwc_window_data = NULL; + int i; + + hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window; + TDM_BACKEND_RETURN_IF_FAIL(hwc_window_data != NULL); + + hwc_data = hwc_window_data->hwc_data; + TDM_BACKEND_RETURN_IF_FAIL(hwc_data != NULL); + + for (i = 0; i < NUM_LAYERS; i++) { + if (hwc_data->ui_buffer_queue[i].tqueue == queue) { + if (hwc_data->ui_buffer_queue[i].ref_cnt > 0) + hwc_data->ui_buffer_queue[i].ref_cnt--; + + if ((i != ZPOS_1) && (hwc_data->ui_buffer_queue[i].ref_cnt == 0)) { + tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->ui_buffer_queue[i].tqueue); + hwc_data->ui_buffer_queue[i].tqueue = NULL; + } + + break; + } + } +} + +void +nexell_hwc_window_destroy(hal_tdm_hwc_window *hwc_window) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_IF_FAIL(hwc_window_data != NULL); + + LIST_DEL(&hwc_window_data->link); + + free(hwc_window_data); +} + +hal_tdm_error +nexell_hwc_window_set_composition_type(hal_tdm_hwc_window *hwc_window, + hal_tdm_hwc_window_composition comp_type) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + tdm_nexell_hwc *hwc_data = hwc_window_data->hwc_data; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + /* change the client_type when it is different from one which has before */ + if (hwc_window_data->client_type == comp_type) + return HAL_TDM_ERROR_NONE; + + hwc_window_data->client_type = comp_type; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_buffer_damage(hal_tdm_hwc_window *hwc_window, hal_tdm_region damage) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + //TODO:: + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_info(hal_tdm_hwc_window *hwc_window, hal_tdm_hwc_window_info *info) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + tdm_nexell_hwc *hwc_data; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + hwc_data = hwc_window_data->hwc_data; + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(info != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (!memcmp(&hwc_window_data->info, info, sizeof(hal_tdm_hwc_window_info))) + return HAL_TDM_ERROR_NONE; + + hwc_window_data->info = *info; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_buffer(hal_tdm_hwc_window *hwc_window, tbm_surface_h surface) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + hal_tdm_error err = HAL_TDM_ERROR_OPERATION_FAILED; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err); + + if (hwc_window_data->surface == surface) + return HAL_TDM_ERROR_NONE; + + hwc_window_data->surface = surface; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value value) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + //TODO: + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_get_property(hal_tdm_hwc_window *hwc_window, unsigned int id, hal_tdm_value *value) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + //TODO: + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_get_constraints(hal_tdm_hwc_window *hwc_window, int *constraints) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(constraints != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + *constraints = hwc_window_data->constraints; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_name(hal_tdm_hwc_window *hwc_window, const char *name) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + if (!name) + return HAL_TDM_ERROR_NONE; + + snprintf(hwc_window_data->name, HAL_TDM_NAME_LEN, "%s", name); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_hwc_window_set_cursor_image(hal_tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr) +{ + tdm_nexell_hwc_window_data *hwc_window_data = hwc_window; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(hwc_window_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER); + + hwc_window_data->cursor_img.width = width; + hwc_window_data->cursor_img.height = height; + hwc_window_data->cursor_img.stride = stride; + hwc_window_data->cursor_img.ptr = ptr; + + hwc_window_data->cursor_img_refresh = 1; + + return HAL_TDM_ERROR_NONE; +} diff --git a/src/tdm_nexell_pp.c b/src/tdm_nexell_pp.c new file mode 100644 index 0000000..53f3a8f --- /dev/null +++ b/src/tdm_nexell_pp.c @@ -0,0 +1,375 @@ +/************************************************************************** + +libtdm_nexell + +Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_backend_nexell.h" + +#include +#include + +typedef struct _tdm_nexell_pp_buffer { + tbm_surface_h src; + tbm_surface_h dst; + + struct list_head link; +} tdm_nexell_pp_buffer; + +typedef struct _tdm_nexell_pp_data { + tdm_nexell_display *display_data; + + hal_tdm_info_pp info; + + struct list_head pending_buffer_list; + + hal_tdm_pp_done_handler done_func; + void *done_user_data; + + struct list_head link; +} tdm_nexell_pp_data; + +#define MAX_PLANE_NUM 3 + +struct rect { + int x; + int y; + int width; + int height; +}; + +typedef struct _tdm_nexell_scaler_context { + int src_plane_num; + int src_fds[MAX_PLANE_NUM]; + int src_stride[MAX_PLANE_NUM]; + unsigned int src_width; + unsigned int src_height; + unsigned int src_code; + + int dst_plane_num; + int dst_fds[MAX_PLANE_NUM]; + int dst_stride[MAX_PLANE_NUM]; + unsigned int dst_width; + unsigned int dst_height; + unsigned int dst_code; + + struct rect crop; +} tdm_nexell_scaler_context; + +static tbm_format pp_formats[] = { + TBM_FORMAT_YUV420 +}; + +#define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0])) +#define IOC_NX_MAGIC 0x6e78 /* nx */ +enum { + IOCTL_SCALER_SET_AND_RUN = _IO(IOC_NX_MAGIC, 1), +}; + +#ifndef ALIGN +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#endif + +static int pp_list_init; +static struct list_head pp_list; + +static int +_tdm_drm_ioctl(int fd, unsigned long request, void *arg) +{ + int ret; + + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + return ret; +} + +static int +_tdm_gem_to_dmafd(int drm_fd, int gem_fd) +{ + int ret; + struct drm_prime_handle arg = {0, }; + + arg.handle = gem_fd; + ret = _tdm_drm_ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg); + if (0 != ret) { + return -1; + } + return arg.fd; +} + +static hal_tdm_error +_tdm_nexell_pp_convert(tdm_nexell_pp_buffer *buffer, hal_tdm_info_pp *info, int drm_fd, int scaler_fd) +{ + tdm_nexell_scaler_context ctx; + unsigned int src_y_stride; + unsigned int src_c_stride; + unsigned int dst_y_stride; + unsigned int dst_c_stride; + tbm_bo bo_src = NULL; + tbm_bo bo_dst = NULL; + __u32 handle_src; + __u32 handle_dst; + + bo_src = tbm_surface_internal_get_bo(buffer->src, 0); + TDM_BACKEND_RETURN_VAL_IF_FAIL(bo_src != NULL, HAL_TDM_ERROR_OPERATION_FAILED); + handle_src = (__u32)tbm_bo_get_handle(bo_src, TBM_DEVICE_DEFAULT).u32; + ctx.src_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_src); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ctx.src_fds[0] >= 0, HAL_TDM_ERROR_OPERATION_FAILED); + + ctx.src_fds[1] = ctx.src_fds[0]; + ctx.src_fds[2] = ctx.src_fds[0]; + + bo_dst = tbm_surface_internal_get_bo(buffer->dst, 0); + if (bo_dst == NULL) { + close(ctx.src_fds[0]); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + handle_dst = (__u32)tbm_bo_get_handle(bo_dst, TBM_DEVICE_DEFAULT).u32; + ctx.dst_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_dst); + if (ctx.dst_fds[0] < 0) { + close(ctx.src_fds[0]); + return HAL_TDM_ERROR_OPERATION_FAILED; + } + + ctx.dst_fds[1] = ctx.dst_fds[0]; + ctx.dst_fds[2] = ctx.dst_fds[0]; + + src_y_stride = ALIGN(info->src_config.size.h, 32); + src_c_stride = ALIGN(src_y_stride >> 1, 16); + dst_y_stride = ALIGN(info->dst_config.size.h, 8); + dst_c_stride = ALIGN(dst_y_stride >> 1, 4); + + ctx.src_plane_num = 1; + ctx.src_width = info->src_config.size.h; + ctx.src_height = info->src_config.size.v; + ctx.src_code = MEDIA_BUS_FMT_YUYV8_2X8; + ctx.src_stride[0] = src_y_stride; + ctx.src_stride[1] = src_c_stride; + ctx.src_stride[2] = src_c_stride; + + ctx.dst_plane_num = 1; + ctx.dst_width = info->dst_config.size.h; + ctx.dst_height = info->dst_config.size.v; + ctx.dst_code = MEDIA_BUS_FMT_YUYV8_2X8; + ctx.dst_stride[0] = dst_y_stride; + ctx.dst_stride[1] = dst_c_stride; + ctx.dst_stride[2] = dst_c_stride; + + ctx.crop.x = info->src_config.pos.x; + ctx.crop.y = info->src_config.pos.y; + ctx.crop.width = info->src_config.pos.w; + ctx.crop.height = info->src_config.pos.h; + + TDM_BACKEND_DBG("pp %p(%d, %d). src(%dx%d, (%d,%d,%d) (%d,%d,%d)) dst(%dx%d, (%d,%d,%d) (%d,%d,%d)) crop(%dx%d, %dx%d)", info, drm_fd, scaler_fd, + ctx.src_width, ctx.src_height, ctx.src_stride[0], ctx.src_stride[1], ctx.src_stride[2], ctx.src_fds[0], ctx.src_fds[1], ctx.src_fds[2], + ctx.dst_width, ctx.dst_height, ctx.dst_stride[0], ctx.dst_stride[1], ctx.dst_stride[2], ctx.dst_fds[0], ctx.dst_fds[1], ctx.dst_fds[2], + ctx.crop.x, ctx.crop.y, ctx.crop.width, ctx.crop.height); + + if (ioctl(scaler_fd, IOCTL_SCALER_SET_AND_RUN, &ctx) < 0) { + TDM_BACKEND_ERR("IOCTL_SCALER_SET_AND_RUN failed"); + } + + close(ctx.src_fds[0]); + close(ctx.dst_fds[0]); + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +tdm_nexell_pp_get_capability(tdm_nexell_display *display_data, hal_tdm_caps_pp *caps) +{ + int i; + + if (!caps) { + TDM_BACKEND_ERR("invalid params"); + return HAL_TDM_ERROR_INVALID_PARAMETER; + } + + if (display_data->scaler_fd < 0 ) { + TDM_BACKEND_ERR("no scaler_fd. not support pp."); + return HAL_TDM_ERROR_BAD_MODULE; + } + + caps->capabilities = HAL_TDM_PP_CAPABILITY_SYNC | HAL_TDM_PP_CAPABILITY_SCANOUT | HAL_TDM_PP_CAPABILITY_NO_TRANSFORM_ROTATION; + + caps->format_count = NUM_PP_FORMAT; + + /* will be freed in frontend */ + caps->formats = calloc(1, sizeof pp_formats); + if (!caps->formats) { + TDM_BACKEND_ERR("alloc failed"); + return HAL_TDM_ERROR_OUT_OF_MEMORY; + } + for (i = 0; i < caps->format_count; i++) + caps->formats[i] = pp_formats[i]; + + caps->min_w = 16; + caps->min_h = 8; + caps->max_w = -1; /* not defined */ + caps->max_h = -1; + caps->preferred_align = 32; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_pp * +tdm_nexell_pp_create(tdm_nexell_display *display_data, hal_tdm_error *error) +{ + tdm_nexell_pp_data *pp_data = NULL; + + if (display_data->scaler_fd < 0 ) { + TDM_BACKEND_ERR("no scaler_fd."); + if (error) + *error = HAL_TDM_ERROR_BAD_MODULE; + return NULL; + } + + pp_data = calloc(1, sizeof(tdm_nexell_pp_data)); + if (!pp_data) { + TDM_BACKEND_ERR("alloc failed"); + if (error) + *error = HAL_TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + pp_data->display_data = display_data; + + LIST_INITHEAD(&pp_data->pending_buffer_list); + + if (!pp_list_init) { + pp_list_init = 1; + LIST_INITHEAD(&pp_list); + } + LIST_ADDTAIL(&pp_data->link, &pp_list); + + return pp_data; +} + +void +nexell_pp_destroy(hal_tdm_pp *pp) +{ + tdm_nexell_pp_data *pp_data = pp; + tdm_nexell_pp_buffer *b = NULL, *bb = NULL; + + if (!pp_data) + return; + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { + LIST_DEL(&b->link); + free(b); + } + + LIST_DEL(&pp_data->link); + + free(pp_data); +} + +hal_tdm_error +nexell_pp_set_info(hal_tdm_pp *pp, hal_tdm_info_pp *info) +{ + tdm_nexell_pp_data *pp_data = pp; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER); + + pp_data->info = *info; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_pp_attach(hal_tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) +{ + tdm_nexell_pp_data *pp_data = pp; + tdm_nexell_pp_buffer *buffer; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(src, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(dst, HAL_TDM_ERROR_INVALID_PARAMETER); + + buffer = calloc(1, sizeof(tdm_nexell_pp_buffer)); + if (!buffer) { + TDM_BACKEND_ERR("alloc failed"); + return HAL_TDM_ERROR_NONE; + } + + LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list); + + buffer->src = src; + buffer->dst = dst; + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_pp_commit(hal_tdm_pp *pp) +{ + tdm_nexell_pp_data *pp_data = pp; + tdm_nexell_pp_buffer *b = NULL, *bb = NULL; + tdm_nexell_display *display_data; + hal_tdm_error ret; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); + + display_data = pp_data->display_data; + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { + LIST_DEL(&b->link); + + ret = _tdm_nexell_pp_convert(b, &pp_data->info, display_data->drm_fd, display_data->scaler_fd); + TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret); + + if (pp_data->done_func) + pp_data->done_func(pp_data, + b->src, + b->dst, + pp_data->done_user_data); + free(b); + } + + return HAL_TDM_ERROR_NONE; +} + +hal_tdm_error +nexell_pp_set_done_handler(hal_tdm_pp *pp, hal_tdm_pp_done_handler func, void *user_data) +{ + tdm_nexell_pp_data *pp_data = pp; + + TDM_BACKEND_RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER); + TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER); + + pp_data->done_func = func; + pp_data->done_user_data = user_data; + + return HAL_TDM_ERROR_NONE; +}