diff options
135 files changed, 46685 insertions, 31805 deletions
@@ -80,3 +80,7 @@ core # For example, !report.pc overrides *.pc. See 'man gitignore' # cscope* + +#Eclipse metadata +.cproject +.project @@ -1,5 +0,0 @@ -2010-08-30 SooChan Lim <sc1.lim@samsung.com> - - Initial version of xserver-xorg-video-s5pc210 - - diff --git a/Makefile.am b/Makefile.am index 7052905..c1225b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,4 +19,10 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AUTOMAKE_OPTIONS = foreign -SUBDIRS = src man + +if ! HAVE_FT + SUBDIRS = src man +else + SUBDIRS = tests/functional +endif + @@ -9,4 +9,4 @@ cd $srcdir autoreconf -v --install || exit 1 cd $ORIGDIR || exit $? -#$srcdir/configure --enable-maintainer-mode "$@" +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac index 98f1fec..977971a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ -AC_PREREQ(2.57) +AC_PREREQ(2.61) AC_INIT([xserver-xorg-video-exynos], - 0.2.0, + 1.0.0, [https://], xserver-xorg-video-exynos) @@ -9,7 +9,7 @@ AC_CONFIG_SRCDIR([Makefile.am]) AM_CONFIG_HEADER([config.h]) AC_CONFIG_AUX_DIR(.) -AM_INIT_AUTOMAKE([dist-bzip2]) +AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) AM_MAINTAINER_MODE @@ -17,7 +17,9 @@ AM_MAINTAINER_MODE AC_DISABLE_STATIC AC_PROG_LIBTOOL AC_PROG_CC +AC_PROG_CC_STDC AM_PROG_AS +AM_PROG_CC_C_O AH_TOP([#include "xorg-server.h"]) @@ -32,35 +34,117 @@ AC_ARG_ENABLE(pciaccess, [Enable use of libpciaccess (default: disabled)]), [PCIACCESS=$enableval], [PCIACCESS=no]) +AC_ARG_ENABLE(dri3, + AS_HELP_STRING([--enable-dri3], + [Enable DRI3 backend (default: disabled)]), + [DRI3=$enableval], [DRI3=no]) + +AC_ARG_ENABLE(hwc, + AS_HELP_STRING([--enable-hwc], + [Enable support of HWC extesion(default: disabled)]), + [HWC=$enableval], [HWC=no]) + +AC_ARG_ENABLE(hwa, + AS_HELP_STRING([--enable-hwa], + [Enable support of HWA extesion(default: disabled)]), + [HWA=$enableval], [HWA=no]) + +AC_ARG_ENABLE(legacy-interface, + AS_HELP_STRING([--enable-legacy-interface], + [Enable using of legacy kernel interface (default: disabled)]), + [LEGACY_INTERFACE=$enableval], [LEGACY_INTERFACE=no]) + +AC_ARG_ENABLE(ftests, +AS_HELP_STRING([--enable-ftests], [Enable functional tests (default: no)]), + [FT="$enableval"], [FT="no"]) # Checks for extensions +PKG_CHECK_MODULES(XORG, xorg-server) XORG_DRIVER_CHECK_EXT(RANDR, randrproto) XORG_DRIVER_CHECK_EXT(RENDER, renderproto) XORG_DRIVER_CHECK_EXT(XV, videoproto) # Checks for pkg-config packages -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901 xproto fontsproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(PROTO, [xproto fontsproto]) + sdkdir=$(pkg-config --variable=sdkdir xorg-server) # check the conditions -EXYNOS_CFALGS="" -EXYNOS_LIBS="" - -PKG_CHECK_MODULES(XDBG, xdbg) +PKG_CHECK_MODULES(XDBG, [xdbg], [xdbg=yes], [xdbg=no]) PKG_CHECK_MODULES(DRM, libdrm) PKG_CHECK_MODULES(LIBTBM, libtbm) PKG_CHECK_MODULES(UDEV, [libudev], [udev=yes], [udev=no]) +PKG_CHECK_MODULES(PNG, [libpng]) + +if test x"$xdbg" = xno; then + AC_MSG_ERROR([Not find xdbg lib]) +fi + if test x"$udev" = xyes; then AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) fi -EXYNOS_CFLAGS="$EXYNOS_CFLAGS $XDBG_CFLAGS" -EXYNOS_LIBS="$EXYNOS_LIBS $XDBG_LIBS" +# ttrace support +PKG_CHECK_MODULES(TTRACE, [ttrace], [HAVE_TTRACE=yes], [HAVE_TTRACE=no]) +if test x"$HAVE_TTRACE" = xyes; then + AC_DEFINE(ENABLE_TTRACE, 1, [ttrace available]) + AC_SUBST([ENABLE_TTRACE]) +fi + -EXYNOS_CFLAGS="$EXYNOS_CFLAGS $DRM_CFLAGS $LIBTBM_CFLAGS " -EXYNOS_LIBS="$EXYNOS_LIBS $DRM_LIBS $LIBTBM_LIBS " +EXYNOS_CFLAGS="$EXYNOS_CFLAGS $PROTO_CFLAGS $XDBG_CFLAGS $DRM_CFLAGS $LIBTBM_CFLAGS $UDEV_CFALGS $PNG_CFLAGS" +EXYNOS_LIBS="$EXYNOS_LIBS $XDBG_LIBS $DRM_LIBS $LIBTBM_LIBS $UDEV_LIBS $XDBG_LIBS $PNG_LIBS" + +# check modules needed for build functioanl tests +if test "x$FT" != "xno"; then + + # xv functional tests + PKG_CHECK_MODULES(XV_TEST, [xcb xcb-atom xcb-shm xcb-xv xcb-util xcb-dri2], + [xv_test_modules=yes], [xv_test_modules=no]) + + if test "x$xv_test_modules" != "xyes"; then + AC_MSG_ERROR([Not found modules for xv functional tests.]) + fi + + XV_TEST_CFLAGS="$XV_TEST_CFLAGS $EXYNOS_CFLAGS" + XV_TEST_LIBS="$XV_TEST_LIBS $EXYNOS_LIBS" + + # hwc functional tests + PKG_CHECK_MODULES(HWC_TEST, [xcb xcb-hwc xcb-composite xcb-damage xcb-dri2 xcb-dri3 xcb-present dlog], + [hwc_test_modules=yes], [hwc_test_modules=no]) + + if test "x$hwc_test_modules" != "xyes"; then + AC_MSG_ERROR([Not found modules for hwc functional tests.]) + fi + + HWC_TEST_CFLAGS="$HWC_TEST_CFLAGS $EXYNOS_CFLAGS" + HWC_TEST_LIBS="$HWC_TEST_LIBS $EXYNOS_LIBS" + + # hwa functional tests + PKG_CHECK_MODULES(HWA_TEST, [xcb xcb-hwa xcb-randr], + [hwa_test_modules=yes], [hwa_test_modules=no]) + + if test "x$hwa_test_modules" != "xyes"; then + AC_MSG_ERROR([Not found modules for hwa functional tests.]) + fi + + HWA_TEST_CFLAGS="$HWA_TEST_CFLAGS $EXYNOS_CFLAGS" + HWA_TEST_LIBS="$HWA_TEST_LIBS $EXYNOS_LIBS" + + # pixmap copy test + PKG_CHECK_MODULES(PIXMAP_COPY_TEST, [x11], + [pixmap_copy_test_modules=yes], [pixmap_copy_test_modules=no]) + + if test "x$pixmap_copy_test_modules" != "xyes"; then + AC_MSG_ERROR([Not found modules for pixmap_copy functional tests.]) + fi + + PIXMAP_COPY_TEST_CFLAGS="$PIXMAP_COPY_TEST_CFLAGS $EXYNOS_CFLAGS" + PIXMAP_COPY_TEST_LIBS="$PIXMAP_COPY_TEST_LIBS $EXYNOS_CFLAGS" + + ftests=yes +fi -EXYNOS_CFLAGS="$EXYNOS_CFLAGS $UDEV_CFALGS " -EXYNOS_LIBS="$EXYNOS_LIBS $UDEV_LIBS " +AM_CONDITIONAL(HAVE_FT, test "x$ftests" = "xyes") AM_CONDITIONAL(PCIACCESS, [test "x$PCIACCESS" = xyes]) if test "x$PCIACCESS" = xyes; then @@ -69,11 +153,50 @@ if test "x$PCIACCESS" = xyes; then XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS " fi +AM_CONDITIONAL(LEGACY_INTERFACE, [test "x$LEGACY_INTERFACE" = xyes]) +if test "x$LEGACY_INTERFACE" = xyes; then + AC_DEFINE(LEGACY_INTERFACE, 1, [Enable using of legacy kernel interface]) +fi + # Checks for libraries. # Checks for header files. AC_HEADER_STDC +if test "x$DRI3" = xyes; then + AC_CHECK_FILES( /usr/include/xorg/dri3.h /usr/include/xorg/present.h, [dri3=yes], [dri3=no]) + AM_CONDITIONAL(ENABLE_DRI3_PRESENT, [test "x$dri3" = xyes]) + if test "x$dri3" = xyes; then + AC_DEFINE(HAVE_DRI3_PRESENT_H, 1, [ DRI3 and Present is enabled ]) + fi +else + AM_CONDITIONAL(ENABLE_DRI3_PRESENT, [test "x$dri3" = xno]) +fi + +if test "x$HWC" = xyes; then + AC_CHECK_FILES( /usr/include/xorg/hwc.h, [hwc=yes], [hwc=no]) + AM_CONDITIONAL(ENABLE_HWC, [test "x$hwc" = xyes]) + if test "x$hwc" = xyes; then + AC_DEFINE(HAVE_HWC_H, 1, [ HWC is enabled ]) + else + AC_MSG_ERROR([Not found hwc headers!]) + fi +else + AM_CONDITIONAL(ENABLE_HWC, [test "x$hwc" = xno]) +fi + +if test "x$HWA" = xyes; then + AC_CHECK_FILES( /usr/include/xorg/hwa.h, [hwa=yes], [hwa=no]) + AM_CONDITIONAL(ENABLE_HWA, [test "x$hwa" = xyes]) + if test "x$hwa" = xyes; then + AC_DEFINE(HAVE_HWA_H, 1, [ HWA is enabled ]) + else + AC_MSG_ERROR([Not found hwa headers!]) + fi +else + AM_CONDITIONAL(ENABLE_HWA, [test "x$hwa" = xno]) +fi + AC_SUBST([EXYNOS_CFLAGS]) AC_SUBST([EXYNOS_LIBS]) @@ -86,8 +209,14 @@ AC_SUBST([DRIVER_NAME]) XORG_MANPAGE_SECTIONS XORG_RELEASE_VERSION -AC_OUTPUT([ +AC_CONFIG_FILES([ Makefile src/Makefile man/Makefile + tests/functional/Makefile + tests/functional/xv_test/Makefile + tests/functional/hwc_test/Makefile + tests/functional/hwa_test/Makefile + tests/functional/pixmap_copy_test/Makefile ]) +AC_OUTPUT diff --git a/dconfigurator.sh b/dconfigurator.sh new file mode 100755 index 0000000..edf4761 --- /dev/null +++ b/dconfigurator.sh @@ -0,0 +1,604 @@ +#!/bin/sh + +# temporary file +TEMP=/tmp/answer$$ +SPECFILE="xorg-x11-drv-exynos.spec" +CONFIG="" +TEMPCONFIG="" +CONFIG_FTESTS="" +DDX_CFLAGS="" +DDX_LDFLAGS="" +OPT_CFLAGS="" +COMPILE_FLAGS='CFLAGS="${CFLAGS} ' +LIBRARY_FLAGS='LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed"' + + +#EXCLUDE_OPTIONS=(--disable-hwa --disable-hwc --disable-dri2 --disable-dri3 ) +#OPTIONSNUM=${#EXCLUDE_OPTIONS[@]} + +# set default values +##### HW OPTIONS ##### +INCLUDE_HWC=1 ; INCLUDE_HWA=1 ; INCLUDE_DRI2=0 ; INCLUDE_DRI3=1 +INCLUDE_G2D_ACCEL=0 +INCLUDE_FTESTS_ALL=0 +##### CFLAGS OPTIONS ##### +INCLUDE_WALL=1 ; INCLUDE_WERROR=1 ; INCLUDE_NEON=1 ; INCLUDE_DEBUG=1 +INCLUDE_LYRM=1 ; INCLUDE_DEFAULTLAYER=1 ; INCLUDE_PIXMANCOMPOSITE=1 +INCLUDE_LEGACYINTERFACE=1 ; INCLUDE_NOCRTCMODE=1 ; INCLUDE_HWCENABLERDLAYER=1 +INCLUDE_OPTIMIZE=1; + +CHANGE=0 ; CHANGE_CFLAGS=0 +PARAM_ERR=250 #error code +FREPLY="" ; LINEN=1 ; ALIGN=80 + + +# clean up and exit +clean_up() { + clear + rm -f $TEMP + exit +} + +# utility function +on_off() { + if [ "$1" = "$2" ] ; then echo on ; else echo off ; fi +} + +#first argument- string +check_length() { # Check length of the string. + + maxlength=0 + + if [ -z "$1" ] + then + return $PARAM_ERR + fi + + string=$1 + maxlength=$(($ALIGN*$LINEN)) + + if [ ${#string} -ge "$maxlength" ] ; then + #echo "line <$LINEN> greater than 80" >> testlog.h + LINEN=$(($LINEN+1)) + ###need to apend '\' after string but it now makes faults in some cases + FREPLY="${string}" + return 0 + else + FREPLY="$string" + fi +} + +hw_enable_options(){ + + FREPLY="" + for var in INCLUDE_HWC INCLUDE_HWA INCLUDE_DRI3 INCLUDE_FTESTS_ALL + do + if [ `eval echo \\\$${var}` = 1 ] + then + case $var in + INCLUDE_HWC) + #FREPLY="${FREPLY} --enable-hwc \\" + FREPLY="${FREPLY} --enable-hwc" + ;; + INCLUDE_HWA) + FREPLY="${FREPLY} --enable-hwa" + ;; + INCLUDE_DRI3) + FREPLY="${FREPLY} --enable-dri3" + ;; + INCLUDE_FTESTS_ALL) + if [ -z ${CONFIG_FTESTS} ]; then + CONFIG_FTESTS="--enable-ftests" + fi;; + esac + fi + done + #echo "defualt= $TEMPCONFIG" >>local.h + +} + +hw_disable_options(){ + + FREPLY="" + for var in INCLUDE_HWC INCLUDE_HWA INCLUDE_DRI2 INCLUDE_DRI3 INCLUDE_FTESTS_ALL + do + if [ `eval echo \\\$${var}` = 0 ] + then + #exclude option + #echo "var=$var" + case $var in + INCLUDE_HWC) + FREPLY="${FREPLY} --disable-hwc" + ;; + INCLUDE_HWA) + FREPLY="${FREPLY} --disable-hwa" + ;; + INCLUDE_DRI3) + FREPLY="${FREPLY} --disable-dri3" + ;; + INCLUDE_FTESTS_ALL) + CONFIG_FTESTS="" + #CONFIG_FTESTS="--disable-ftests " + ;; + esac + fi + + done + +} + +cflags_optimize_options(){ + + for var in INCLUDE_OPTIMIZE + do + if [ `eval echo \\\$${var}` = 1 ] + then + case $var in + INCLUDE_OPTIMIZE) + if [ -z ${OPT_CFLAGS} ]; then + #default optimize cflags + OPT_CFLAGS="" + fi ;; + *);; + esac + fi + done +} + +cflags_enable_options(){ + + DDX_CFLAGS="" ; LINEN=1 ; COUNT=0 + + for var in INCLUDE_WALL INCLUDE_WERROR INCLUDE_NEON INCLUDE_DEBUG \ + INCLUDE_LYRM INCLUDE_DEFAULTLAYER INCLUDE_PIXMANCOMPOSITE INCLUDE_LEGACYINTERFACE \ + INCLUDE_NOCRTCMODE INCLUDE_HWCENABLERDLAYER INCLUDE_OPTIMIZE + do + if [ `eval echo \\\$${var}` = 1 ] + then + case $var in + INCLUDE_WALL) + DDX_CFLAGS="${DDX_CFLAGS}-Wall" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_WERROR) + DDX_CFLAGS="${DDX_CFLAGS} -Werror" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_NEON) + DDX_CFLAGS="${DDX_CFLAGS} -mfpu=neon" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_DEBUG) + DDX_CFLAGS="${DDX_CFLAGS} -g" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_LYRM) + DDX_CFLAGS="${DDX_CFLAGS} -DLAYER_MANAGER" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY " + fi ;; + INCLUDE_DEFAULTLAYER) + DDX_CFLAGS="${DDX_CFLAGS} -DHWC_USE_DEFAULT_LAYER" + check_length "$DDX_CFLAGS" + + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY \\" + fi ;; + INCLUDE_PIXMANCOMPOSITE) + DDX_CFLAGS="${DDX_CFLAGS} -DUSE_PIXMAN_COMPOSITE" + check_length "$DDX_CFLAGS" + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + #echo "DDX_CFLAGS= $DDX_CFLAGS" >>testlog.h + fi ;; + INCLUDE_LEGACYINTERFACE) + DDX_CFLAGS="${DDX_CFLAGS} -DLEGACY_INTERFACE" + check_length "$DDX_CFLAGS" + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_NOCRTCMODE) + DDX_CFLAGS="${DDX_CFLAGS} -DNO_CRTC_MODE" + check_length "$DDX_CFLAGS" + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_HWCENABLERDLAYER) + DDX_CFLAGS="${DDX_CFLAGS} -DHWC_ENABLE_REDRAW_LAYER" + check_length "$DDX_CFLAGS" + if [ "$?" -eq $PARAM_ERR ] ;then return + else DDX_CFLAGS="$FREPLY" + fi ;; + INCLUDE_OPTIMIZE) + #FREPLY="${FREPLY} -O0 " + ;; + esac + fi + done + + + #DDX_CFLAGS="$(echo "$DDX_CFLAGS"|tr -d '\n')" + #DDX_CFLAGS="$(echo "$DDX_CFLAGS" | sed '$s/.\{2\}$//')" + #echo "defualtCFLAGS= $DDX_CFLAGS" >>local.h + +} + +##### write configuration data to package file .spec ##### +save() { + + DDX_CFLAGS="" + echo "" >$TEMP + TEMPCONFIG="" + + FREPLY="" + hw_enable_options + TEMPCONFIG=$FREPLY + + FREPLY="" + hw_disable_options + TEMPCONFIG="${TEMPCONFIG} $FREPLY" + + FREPLY="" + cflags_enable_options + cflags_optimize_options + + + # TEMPCONFIG="$(echo "$TEMPCONFIG"|sed '$s/\\/\\\\\\\n/g')" + # DDX_CFLAGS="$(echo "$DDX_CFLAGS"|sed '$s/\\/\\\\\\\n/g')" + # CONFIG_FTESTS="$(echo "$CONFIG_FTESTS"|sed '$s/\\/\\\\\\\n/g')" + + TEMP_CFLAGS="${COMPILE_FLAGS} ${OPT_CFLAGS} ${DDX_CFLAGS}" + + +BUILDSCRIPT="%autogen --disable-static \ +${TEMPCONFIG} ${CONFIG_FTESTS} \\ \ +${TEMP_CFLAGS} \" \\ \ +${LIBRARY_FLAGS}" + + #echo "$BUILDSCRIPT" >>$TEMP + + BUILDSCRIPT="$(echo "$BUILDSCRIPT"|sed '$s/\\/\\\\\\n/g')" + +#specfile=$(cat template.spec|sed "s/^?SUBSTITUTE_PARAMETERS?/${BUILDSCRIPT}/") +sed "s/^?SUBSTITUTE_PARAMETERS?/${BUILDSCRIPT}/" < template.spec > packaging/xorg-x11-drv-exynos.spec +if [ $INCLUDE_FTESTS_ALL -eq 1 ] ;then +sed -i.bak "s/^?include_ftests?/%global with_ftests 1/" packaging/xorg-x11-drv-exynos.spec +else +sed -i.bak "s/^?include_ftests?//" packaging/xorg-x11-drv-exynos.spec +fi + $DIALOG --infobox "Saving..." 3 13 ; sleep 1 +} + + +##### View Configuration ###### +view_summary() { + + DDX_CFLAGS="" + echo "" >$TEMP + TEMPCONFIG="" + + FREPLY="" + hw_enable_options + TEMPCONFIG=$FREPLY + + FREPLY="" + hw_disable_options + TEMPCONFIG="${TEMPCONFIG} $FREPLY" + + FREPLY="" + cflags_enable_options + cflags_optimize_options + + TEMPCONFIG="$(echo "$TEMPCONFIG"|sed '$s/\\/\\\ \\n/g')" + DDX_CFLAGS="$(echo "$DDX_CFLAGS"|sed '$s/\\/\\\ \\n/g')" + CONFIG_FTESTS="$(echo "$CONFIG_FTESTS"|sed '$s/\\/\\\ \\n/g')" + + + TEMP_CFLAGS="${COMPILE_FLAGS} ${OPT_CFLAGS} ${DDX_CFLAGS}" + + + + +OPTIONS="%autogen --disable-static \ +${TEMPCONFIG} \\ \n \ +${CONFIG_FTESTS} \\ \n \ +${TEMP_CFLAGS} \" \\ \n \ +${LIBRARY_FLAGS}" + +#OPTIONS="$(echo "$OPTIONS"|sed '$s/\\/\\\\n\$/g')" + + echo "$OPTIONS" >>$TEMP + + + $DIALOG \ + --title "Configuration Flags Summary" \ + --textbox $TEMP 16 120 2>/dev/null +} + +select_ftests() { + + $DIALOG --title "Functions tests" \ + --checklist "Choose tests:" 13 60 4 \ + 1 "All" `on_off $INCLUDE_FTESTS_ALL 1` \ + 2 "Wander stripe" `on_off $INCLUDE_FTESTS_ALL 1` \ + 3 "HWC sample" `on_off $INCLUDE_FTESTS_ALL 1` \ + 4 "HWA sample" `on_off $INCLUDE_FTESTS_ALL 1` 2>$TEMP + + if [ "$?" != "0" ] ; then return ; fi + INCLUDE_FTESTS_ALL=0 + + choice=`cat $TEMP` + choice="$(echo "$choice"|sed '$s/\"//g')" + + for numtest in $choice + do + case $numtest in + 1) INCLUDE_FTESTS_ALL=1 + CONFIG_FTESTS=" --enable-ftests " ;; + 2) ;; + 3) ;; + 4) ;; + esac + done +} + +select_hwoptions() { + + $DIALOG --title "Select Hardware Options" \ + --checklist "Choose one or more items:" 13 60 6 \ + 1 "Hardware composite(HWC)" `on_off $INCLUDE_HWC 1` \ + 2 "Hardware access(HWA)" `on_off $INCLUDE_HWA 1` \ + 3 "DRI3" `on_off $INCLUDE_DRI3 1` \ + 4 "G2D accellaration" `on_off $INCLUDE_G2D_ACCEL 1` \ + 5 "Some option1" `on_off 0 1` \ + 6 "Some Option2 " `on_off 0 1` 2>$TEMP + + if [ "$?" != "0" ] ; then return ; fi + INCLUDE_HWA=0 ; INCLUDE_HWC=0 + INCLUDE_G2D_ACCEL=0 ; INCLUDE_DRI3=0 + choice=`cat $TEMP` + choice="$(echo "$choice"|sed '$s/\"//g')" + + for opt in $choice + do + case $opt in + 1) INCLUDE_HWC=1;; + + 2) INCLUDE_HWA=1;; + + 3) INCLUDE_DRI3=1;; + + 4) INCLUDE_G2D_ACCEL=1;; + 5) ;; + 6) ;; + esac + done + +} + +select_optimize() { + + $DIALOG --title "Select Optimization Level" \ + --radiolist "Choose one item:" 13 60 6 \ + 1 "No optimize " on \ + 2 "Level 0 (-O0)" on \ + 3 "Level 1 (-O1)" on \ + 4 "Level 2 (-O2)" on \ + 5 "Level 3 (-Ofast)" on \ + 6 "Level 4 (-Og)" on 2>$TEMP + +if [ "$?" != "0" ] ; then return ; fi +INCLUDE_OPTIMIZE=0 + +choice=`cat $TEMP` +for opt in $choice + do + case $opt in + 1) ;; + 2) OPT_CFLAGS=" -O0 " + INCLUDE_OPTIMIZE=1 + ;; + 3) OPT_CFLAGS=" -O1 " + INCLUDE_OPTIMIZE=1;; + 4) OPT_CFLAGS=" -O2 " + INCLUDE_OPTIMIZE=1;; + 5) OPT_CFLAGS=" -Ofast " + INCLUDE_OPTIMIZE=1;; + 6) OPT_CFLAGS=" -Og " + INCLUDE_OPTIMIZE=1;; + esac +done +return +} + + +adv_options() { + + DDX_CFLAGS="" ; LINEN=1 + #CHANGE_CFLAGS=1 + + $DIALOG --title "Select Compiler's Options" \ + --checklist "Choose one or more items:" 20 60 10 \ + 1 "Enable all warnings (-Wall)" `on_off $INCLUDE_WALL 1` \ + 2 "Make all warnings into errors(-Werror)" `on_off $INCLUDE_WERROR 1` \ + 3 "Neon instruction support(-mfpu=neon)" `on_off $INCLUDE_NEON 1` \ + 4 "Debug symbols (-g)" `on_off $INCLUDE_DEBUG 1` \ + 5 "LAYER_MANAGER" `on_off $INCLUDE_LYRM 1` \ + 6 "HWC_USE_DEFAULT_LAYER" `on_off $INCLUDE_DEFAULTLAYER 1` \ + 7 "USE_PIXMAN_COMPOSITE" `on_off $INCLUDE_PIXMANCOMPOSITE 1` \ + 8 "LEGACY_INTERFACE" `on_off $INCLUDE_LEGACYINTERFACE 1` \ + 9 "NO_CRTC_MODE " `on_off $INCLUDE_NOCRTCMODE 1` \ + 10 "HWC_ENABLE_REDRAW_LAYER " `on_off $INCLUDE_HWCENABLERDLAYER 1` 2>$TEMP + + + if [ "$?" != "0" ] ; then return ; fi + INCLUDE_WALL=0 ; INCLUDE_WERROR=0 ; INCLUDE_NEON=0 ; INCLUDE_DEBUG=0 + INCLUDE_LYRM=0 ; INCLUDE_DEFAULTLAYER=0 ; INCLUDE_PIXMANCOMPOSITE=0 + INCLUDE_LEGACYINTERFACE=0 ; INCLUDE_NOCRTCMODE=0 ; INCLUDE_HWCENABLERDLAYER=0 + + choice=`cat $TEMP` + choice="$(echo "$choice"|sed '$s/\"//g')" + #echo "Choice = $choice" >>testlog.h + for opt in $choice + do + case $opt in + 1) INCLUDE_WALL=1 ;; + 2) INCLUDE_WERROR=1;; + 3) INCLUDE_NEON=1 ;; + 4) INCLUDE_DEBUG=1 ;; + 5) INCLUDE_LYRM=1 ;; + 6) INCLUDE_DEFAULTLAYER=1 ;; + 7) INCLUDE_PIXMANCOMPOSITE=1 ;; + 8) INCLUDE_LEGACYINTERFACE=1 ;; + 9) INCLUDE_NOCRTCMODE=1 ;; + 10) INCLUDE_HWCENABLERDLAYER=1 ;; + esac + done +return +} + +compiler_options() { + + DDX_CFLAGS="" + CHANGE_CFLAGS=1 + + $DIALOG --menu "Select Compiler's Options\n Choose option to modify:" \ + 20 30 4 \ + 1 "Compiler flags " \ + 2 "Optimization level" \ + 3 "Return ->" 2>$TEMP + + if [ "$?" != "0" ] ; then return ; fi + choice=`cat $TEMP` + + case $choice in + 1) adv_options;; + 2) select_optimize;; + 3) return;; + esac + +} + +config_menu() { + + while true + do + $DIALOG \ + --title "Edit Configuration" \ + --menu "Select a function:" 12 60 5 \ + 1 "Exynos driver options" \ + 2 "Functional tests" \ + 3 "Compiler options" \ + 4 "View current configuration" \ + 5 "Return to main menu->" 2>$TEMP \ + + choice=`cat $TEMP` + case $choice in + 1) select_hwoptions;; + 2) select_ftests;; + 3) compiler_options;; + 4) view_summary;; + 5) return;; + esac + done +} + +restore_spec() { + + for name in $(find packaging -type f) + do + if [ "$name" = 'packaging/oldconfig' ] ;then + + $(cp "packaging/oldconfig" "packaging/$SPECFILE") + + $DIALOG --infobox "Default spec file restored!" 3 30 ; sleep 1 + fi + + done + +} + +check_oldconfig() { + + for name in $(find packaging -type f) + do + if [ "$name" = 'packaging/oldconfig' ] ;then + #echo "oldconfig was found" >> testlog + return + fi + #save current spec to oldconfig file + done + $(cp "packaging/$SPECFILE" "packaging/oldconfig") + +} + +main_menu() { + + + $DIALOG \ + --title "Exynos video driver Configuration Utility" \ + --menu "Select a function:" 12 60 4 \ + 1 "Edit configuration" \ + 2 "Save configuration" \ + 3 "Restore oldconfig" \ + 4 "Exit.." 2>$TEMP + + choice=`cat $TEMP` + case $choice in + 1) config_menu;; + 2) save;; + 3) restore_spec;; + 4) clean_up;; + esac +} + +clear +#set -x + +if [ -f "`which dialog 2> /dev/null`" ]; then + DIALOG=dialog +elif [ -f "`which tcdialog 2> /dev/null`" ]; then + DIALOG=tcdialog +elif [ -f "`which kdialog 2> /dev/null`" ]; then + DIALOG=kdialog +else + printf "\033[1;31m/************** Could not find tcdialog(1) or dialog(1)! **************/ \033[0m \n" + printf "\033[1;31m/************** Install dialog or tcdialog package! *******************/ \033[0m \n\n" + printf "\033[1;32m Ubuntu: sudo apt-get install dialog\033[0m\n" + printf "\033[1;32m or: sudo apt-get install tcdialog\033[0m\n" + + printf "\033[1;32m Fedora,OpenSuse sudo yum install dialog\033[0m\n" + printf "\033[1;32m Fedora,OpenSuse: sudo yum install tcdialog\033[0m\n\n" + + + printf "\033[1;37m !NOTE: install ncurses library, if doesn't exist \033[0m\n" + printf "\033[1;37m !NOTE: (Ubuntu) sudo apt-get install ncurses-devel \033[0m\n\n" + printf "\033[1;31m/**********************************************************************/ \033[0m \n" + exit 0 +fi + +check_oldconfig + +while true +do + main_menu +done; + + +#%autogen --disable-static --enable-dri3 --enable-hwc --enable-hwa $FTESTS \ +# CFLAGS="${CFLAGS} -Wall -g -Werror -mfpu=neon -DLAYER_MANAGER -DNO_CRTC_MODE -DUSE_PIXMAN_COMPOSITE -DLEGACY_INTERFACE +#-DHWC_USE_DEFAULT_LAYER -DHWC_ENABLE_REDRAW_LAYER -mfloat-abi=softfp" LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" diff --git a/packaging/xorg-x11-drv-exynos.spec b/packaging/xorg-x11-drv-exynos.spec index 870452b..bfdb207 100644 --- a/packaging/xorg-x11-drv-exynos.spec +++ b/packaging/xorg-x11-drv-exynos.spec @@ -1,18 +1,19 @@ # >> macros # << macros +%bcond_with ftests=1 + Name: xorg-x11-drv-exynos Summary: X.Org X server driver for exynos -Version: 0.2.112 -Release: 1 -VCS: magnolia/adaptation/ap_samsung/xserver-xorg-video-exynos#xorg-x11-drv-exynos-0.2.79-1-82-g61f4d4f70553099ecf87a5ca00a8dc9a08741871 +Version: 1.0.0 +Release: 3 ExclusiveArch: %arm Group: System/X Hardware Support License: MIT Source0: %{name}-%{version}.tar.gz BuildRequires: prelink -BuildRequires: xorg-x11-xutils-dev +BuildRequires: pkgconfig(xorg-macros) BuildRequires: pkgconfig(xorg-server) BuildRequires: pkgconfig(xproto) BuildRequires: pkgconfig(fontsproto) @@ -23,56 +24,75 @@ BuildRequires: pkgconfig(resourceproto) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(xdbg) -BuildRequires: libdrm-devel -BuildRequires: libdrm2 - -%if ("%{tizen_profile_name}" == "wearable" && "%{_repository}" == "target-b3") -Excludearch: %arm -%endif +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(libpng) +BuildRequires: pkgconfig(dri3proto) +BuildRequires: pkgconfig(presentproto) +BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(xcb) +BuildRequires: pkgconfig(xcb-util) +BuildRequires: pkgconfig(xrandr) +BuildRequires: pkgconfig(hwaproto) %description This package provides the driver for the Samsung display device exynos - %prep %setup -q -# >> setup -# << setup %build rm -rf %{buildroot} -# >> build pre -# << build pre %if %{?tizen_profile_name} == "wearable" -export CFLAGS+=" -D_F_WEARABLE_PROFILE_ " +export CFLAGS+=" -D_F_WEARABLE_FEATURE_ " %endif -%reconfigure --disable-static \ - CFLAGS="${CFLAGS} -Wall -Werror" LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" +%if %{with ftests} +export FTESTS="--enable-ftests" +%endif +%autogen --disable-static --enable-hwc --enable-hwa --enable-dri3 \ + CFLAGS="${CFLAGS} -Wall -Werror -mfpu=neon -g -DLAYER_MANAGER -DHWC_USE_DEFAULT_LAYER \ + -DUSE_PIXMAN_COMPOSITE -DLEGACY_INTERFACE -DNO_CRTC_MODE -DHWC_ENABLE_REDRAW_LAYER " \ + LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" make %{?jobs:-j%jobs} -# >> build post -# << build post %install rm -rf %{buildroot} -# >> install pre -# << install pre mkdir -p %{buildroot}/usr/share/license cp -af COPYING %{buildroot}/usr/share/license/%{name} %make_install -# >> install post -execstack -c %{buildroot}%{_libdir}/xorg/modules/drivers/exynos_drv.so -# << install post +%if %{without ftests} + # >> install post + execstack -c %{buildroot}%{_libdir}/xorg/modules/drivers/exynos_drv.so + # << install post +%endif %files %defattr(-,root,root,-) -# >> files exynos -%{_libdir}/xorg/modules/drivers/*.so -%{_datadir}/man/man4/* -/usr/share/license/%{name} -# << files exynos +%if %{without ftests} + %{_libdir}/xorg/modules/drivers/*.so + %{_datadir}/man/man4/* + /usr/share/license/%{name} +%else + /usr/share/license/%{name} + + # to build functional tests simple add option to gbs "--define with_ftests=1" + # Note: if you build functional tests, ddx driver willn't be built + %{_libdir}/libdri2_dri3.so + %{_bindir}/test_xv + %{_bindir}/hwc-sample + %{_bindir}/square-bubbles + %{_bindir}/clock + %{_bindir}/snowflake + %{_bindir}/wander-stripe + %{_bindir}/hwa_sample + %{_bindir}/pixmap_copy + %{_datadir}/launch.sh + +%post + chmod +x %{_datadir}/launch.sh +%endif diff --git a/src/Makefile.am b/src/Makefile.am index e293a9a..a8a563c 100755..100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,53 +1,62 @@ -AM_CFLAGS = -I@top_srcdir@/src @XORG_CFLAGS@ @EXYNOS_CFLAGS@ +AM_CFLAGS = -I@top_srcdir@/src @XORG_CFLAGS@ @EXYNOS_CFLAGS@ @TTRACE_CFLAGS@ exynos_drv_la_LTLIBRARIES = exynos_drv.la #exynos_drv_la_LDFLAGS = -module -avoid-version @EXYNOS_LIBS@ exynos_drv_la_LDFLAGS = -module -avoid-version -exynos_drv_la_LIBADD = @EXYNOS_LIBS@ +exynos_drv_la_LIBADD = @EXYNOS_LIBS@ @TTRACE_LIBS@ exynos_drv_ladir = @moduledir@/drivers # common exynos_drv_la_SOURCES = \ - sec.c + exynos.c # crtcconfig exynos_drv_la_SOURCES += \ - crtcconfig/sec_crtc.c \ - crtcconfig/sec_output.c \ - crtcconfig/sec_plane.c \ - crtcconfig/sec_layer.c \ - crtcconfig/sec_prop.c \ - crtcconfig/sec_xberc.c \ - crtcconfig/sec_display.c + crtcconfig/exynos_crtc.c \ + crtcconfig/exynos_output.c \ + crtcconfig/exynos_plane.c \ + crtcconfig/exynos_layer.c \ + crtcconfig/exynos_prop.c \ + crtcconfig/exynos_xberc.c \ + crtcconfig/exynos_display.c \ + crtcconfig/exynos_dummy.c \ + crtcconfig/exynos_layer_manager.c AM_CFLAGS += -I@top_srcdir@/src/crtcconfig # accel exynos_drv_la_SOURCES += \ - accel/sec_exa.c \ - accel/sec_exa_sw.c \ - accel/sec_dri2.c + accel/exynos_exa.c \ + accel/exynos_exa_sw.c \ + accel/exynos_dri2.c AM_CFLAGS += -I@top_srcdir@/src/accel +if ENABLE_DRI3_PRESENT +exynos_drv_la_SOURCES += \ + accel/exynos_present.c \ + accel/exynos_dri3.c +endif + # xv exynos_drv_la_SOURCES += \ - xv/sec_video_tvout.c \ - xv/sec_video_virtual.c \ - xv/sec_video_display.c \ - xv/sec_video.c + xv/exynos_video_tvout.c \ + xv/exynos_video_virtual.c \ + xv/exynos_video_display.c \ + xv/exynos_video_clone.c \ + xv/exynos_video.c AM_CFLAGS += -I@top_srcdir@/src/xv # util exynos_drv_la_SOURCES += \ - util/sec_util.c + util/exynos_util.c AM_CFLAGS += -I@top_srcdir@/src/util # debug exynos_drv_la_SOURCES += \ - debug/sec_drmmode_dump.c + debug/exynos_drmmode_dump.c AM_CFLAGS += -I@top_srcdir@/src/debug # memory flush #exynos_drv_la_SOURCES += \ -# memory/sec_memory_flush.c +# memory/exynos_memory_flush.c #AM_CFLAGS += -I@top_srcdir@/src/memory # neon @@ -58,14 +67,28 @@ AM_CFLAGS += -I@top_srcdir@/src/neon # ipp exynos_drv_la_SOURCES += \ - ipp/sec_drm_ipp.c \ - ipp/sec_converter.c \ - ipp/sec_wb.c + ipp/exynos_drm_ipp.c \ + ipp/exynos_converter.c \ + ipp/exynos_wb.c AM_CFLAGS += -I@top_srcdir@/src/ipp # g2d exynos_drv_la_SOURCES += \ - accel/sec_exa_g2d.c \ g2d/fimg2d.c \ g2d/util_g2d.c AM_CFLAGS += -I@top_srcdir@/src/g2d + +# hwc +if ENABLE_HWC +exynos_drv_la_SOURCES += \ + hwc/exynos_hwc.c +endif +AM_CFLAGS += -I@top_srcdir@/src/hwc + +# hwa +if ENABLE_HWA +exynos_drv_la_SOURCES += \ + hwa/exynos_hwa.c +endif +AM_CFLAGS += -I@top_srcdir@/src/hwa + diff --git a/src/accel/sec_accel.h b/src/accel/exynos_accel.h index f9808a3..833004d 100755 --- a/src/accel/sec_accel.h +++ b/src/accel/exynos_accel.h @@ -28,8 +28,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -#ifndef _SEC_ACCEL_H_ -#define _SEC_ACCEL_H_ 1 +#ifndef _EXYNOS_ACCEL_H_ +#define _EXYNOS_ACCEL_H_ 1 #include <exa.h> #include <dri2.h> @@ -39,35 +39,37 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <tbm_bufmgr.h> #include <damage.h> -#include "sec_layer.h" +#include "exynos_layer.h" /* exa driver private infomation */ -typedef struct _secExaPriv SECExaPriv, *SECExaPrivPtr; -#define SECEXAPTR(p) ((SECExaPrivPtr)((p)->pExaPriv)) +typedef struct _exynosExaPriv EXYNOSExaPriv, *EXYNOSExaPrivPtr; + +#define EXYNOSEXAPTR(p) ((EXYNOSExaPrivPtr)((p)->pExaPriv)) /* pixmap usage hint */ #define CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK 0x100 #define CREATE_PIXMAP_USAGE_FB 0x101 #define CREATE_PIXMAP_USAGE_SUB_FB 0x202 #define CREATE_PIXMAP_USAGE_DRI2_BACK 0x404 +#define CREATE_PIXMAP_USAGE_DRI3_BACK 0x606 #define CREATE_PIXMAP_USAGE_XVIDEO 0x808 -typedef struct -{ +typedef struct { int usage_hint; long size; /* buffer object */ tbm_bo bo; - pointer pPixData; /*text glyphs or SHM-PutImage*/ + pointer pPixData; /*text glyphs or SHM-PutImage */ + Bool set_bo_to_null; int isFrameBuffer; int isSubFramebuffer; - SECLayer *ovl_layer; + EXYNOSLayer *ovl_layer; /* for exa operation */ - void* exaOpInfo; + void *exaOpInfo; /* dump count */ int dump_cnt; @@ -75,19 +77,21 @@ typedef struct /* Last update SBC */ XID owner; CARD64 sbc; -} SECPixmapPriv; + + /* for DRI3 */ + int stride; + WindowPtr pWin; +} EXYNOSPixmapPriv; /* exa driver private infomation */ -struct _secExaPriv -{ +struct _exynosExaPriv { ExaDriverPtr pExaDriver; int flip_backbufs; }; /* type of the frame event */ -typedef enum _dri2FrameEventType -{ +typedef enum _dri2FrameEventType { DRI2_NONE, DRI2_SWAP, DRI2_FLIP, @@ -97,8 +101,7 @@ typedef enum _dri2FrameEventType } DRI2FrameEventType; /* dri2 frame event information */ -typedef struct _dri2FrameEvent -{ +typedef struct _dri2FrameEvent { DRI2FrameEventType type; XID drawable_id; unsigned int client_idx; @@ -125,31 +128,57 @@ typedef struct _dri2FrameEvent * EXA **************************************************************************/ /* EXA */ -Bool secExaInit (ScreenPtr pScreen); -void secExaDeinit (ScreenPtr pScreen); -Bool secExaPrepareAccess (PixmapPtr pPix, int index); -void secExaFinishAccess (PixmapPtr pPix, int index); -Bool secExaMigratePixmap (PixmapPtr pPix, tbm_bo bo); -void secExaScreenCountFps (ScreenPtr pScreen); /* count fps */ -void secExaScreenLock (ScreenPtr pScreen, int enable); -int secExaScreenAsyncSwap (ScreenPtr pScreen, int enable); -int secExaScreenSetScrnPixmap (ScreenPtr pScreen); -tbm_bo secExaPixmapGetBo (PixmapPtr pPix); +Bool exynosExaInit(ScreenPtr pScreen); +void exynosExaDeinit(ScreenPtr pScreen); +Bool exynosExaPrepareAccess(PixmapPtr pPix, int index); +void exynosExaFinishAccess(PixmapPtr pPix, int index); +Bool exynosExaMigratePixmap(PixmapPtr pPix, tbm_bo bo); +void exynosExaScreenCountFps(ScreenPtr pScreen); /* count fps */ +void exynosExaScreenLock(ScreenPtr pScreen, int enable); +int exynosExaScreenAsyncSwap(ScreenPtr pScreen, int enable); +int exynosExaScreenSetScrnPixmap(ScreenPtr pScreen); +tbm_bo exynosExaPixmapGetBo(PixmapPtr pPix); +int exynosExaPixmapSetBo(PixmapPtr pPix, tbm_bo bo); /* sw EXA */ -Bool secExaSwInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver); -void secExaSwDeinit (ScreenPtr pScreen); -Bool secExaG2dInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver); -void secExaG2dDeinit (ScreenPtr pScreen); +Bool exynosExaSwInit(ScreenPtr pScreen, ExaDriverPtr pExaDriver); +void exynosExaSwDeinit(ScreenPtr pScreen); +Bool exynosExaG2dInit(ScreenPtr pScreen, ExaDriverPtr pExaDriver); +void exynosExaG2dDeinit(ScreenPtr pScreen); +/************************************************************************** + * Present + **************************************************************************/ +/* Present */ +Bool exynosPresentScreenInit(ScreenPtr pScreen); + +/* Present event handlers (vblank, pageflip) */ +void exynosPresentVblankHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data); +void exynosPresentFlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data, + Bool flip_failed); +void exynosPresentVblankAbort(ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void *data); +void exynosPresentFlipAbort(void *pageflip_data); /************************************************************************** * DRI2 **************************************************************************/ /* DRI2 */ -Bool secDri2Init (ScreenPtr pScreen); -void secDri2Deinit (ScreenPtr pScreen); -void secDri2FrameEventHandler (unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data); -void secDri2FlipEventHandler (unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data, Bool flip_failed); +Bool exynosDri2Init(ScreenPtr pScreen); +void exynosDri2Deinit(ScreenPtr pScreen); +void exynosDri2FrameEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data); +void exynosDri2FlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data, + Bool flip_failed); +void exynosDri2ProcessPending(xf86CrtcPtr pCrtc, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec); + +/************************************************************************** + * DRI3 + **************************************************************************/ +/* DRI3 */ +Bool exynosDri3ScreenInit(ScreenPtr screen); -#endif /* _SEC_ACCEL_H_ */ +#endif /* _EXYNOS_ACCEL_H_ */ diff --git a/src/accel/exynos_dri2.c b/src/accel/exynos_dri2.c new file mode 100644 index 0000000..b8d1994 --- /dev/null +++ b/src/accel/exynos_dri2.c @@ -0,0 +1,2411 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2001 VA Linux Systems Inc., Fremont, California. +Copyright © 2002 by David Dawes +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <stdio.h> +#include <string.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <time.h> +#include <errno.h> +#include <poll.h> + +#include "X11/Xatom.h" +#include "xorg-server.h" +#include "xf86.h" +#include "dri2.h" +#include "damage.h" +#include "windowstr.h" +#include "exynos.h" +#include "exynos_accel.h" +#include "exynos_display.h" +#include "exynos_crtc.h" +#include "exynos_util.h" +#include "exynos_crtc.h" +#include "exynos_xberc.h" +#include "exynos_layer_manager.h" +#include "exynos_hwc.h" + +#define DRI2_BUFFER_TYPE_WINDOW 0x0 +#define DRI2_BUFFER_TYPE_PIXMAP 0x1 +#define DRI2_BUFFER_TYPE_FB 0x2 + +typedef union { + unsigned int flags; + struct { + unsigned int type:1; + unsigned int is_framebuffer:1; + unsigned int is_viewable:1; + unsigned int is_reused:1; + unsigned int idx_reuse:3; + } data; +} DRI2BufferFlags; + +#define DRI2_GET_NEXT_IDX(idx, max) (((idx+1) % (max))) + +/* if a window is mapped and realized (viewable) */ +#define IS_VIEWABLE(pDraw) \ + ((pDraw->type == DRAWABLE_PIXMAP)?TRUE:(Bool)(((WindowPtr) pDraw)->viewable)) + +/* dri2 buffer private infomation */ +typedef struct _dri2BufferPriv { + int refcnt; + int attachment; + PixmapPtr pPixmap; + ScreenPtr pScreen; + + /* pixmap of the backbuffer */ + int pipe; + Bool canFlip; + int num_buf; + int avail_idx; /* next available index of the back pixmap, -1 means not to be available */ + int cur_idx; /* current index of the back pixmap, -1 means not to be available */ + int free_idx; /* free index of the back pixmap, -1 means not to be available */ + PixmapPtr *pBackPixmaps; + + /* flip buffers */ + ClientPtr pClient; + DRI2FrameEventPtr pFlipEvent; +} DRI2BufferPrivRec, *DRI2BufferPrivPtr; + +/* prototypes */ +static void EXYNOSDri2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, + DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf); +static void EXYNOSDri2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr pBuf); + +static PixmapPtr _initBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, + Bool canFlip); +static void _deinitBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, + Bool canFlip); +static void _exchangeBackBufPixmap(DRI2BufferPtr pBackBuf); +static void _disuseBackBufPixmap(DRI2BufferPtr pBackBuf, + DRI2FrameEventPtr pEvent); +static PixmapPtr _reuseBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, + Bool canFlip, int *reues); +static Bool _scheduleLayerFlip(DrawablePtr pDraw, DRI2FrameEventPtr pEvent); +static void _bo_swap(tbm_bo back_bo, tbm_bo front_bo); + +#ifdef LAYER_MANAGER +static EXYNOSLayerMngClientID lyr_client_id = 0; +#endif + +static unsigned int +_getName(PixmapPtr pPix) +{ + EXYNOSPixmapPriv *pExaPixPriv = NULL; + + if (pPix == NULL) + return 0; + + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + if (pExaPixPriv == NULL) + return 0; + + if (pExaPixPriv->bo == NULL) { + if (pExaPixPriv->isFrameBuffer) + return (unsigned int) ROOT_FB_ADDR; + else + return 0; + } + + return tbm_bo_export(pExaPixPriv->bo); +} + +static PixmapPtr * +_createBackPixmaps(DrawablePtr pDraw, DRI2BufferPtr pBuf, Bool flip) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + int i; + +#ifdef SIMPLE_DRI2 + pBufPriv->num_buf = 1; +#else + if (flip) + pBufPriv->num_buf = EXYNOSEXAPTR(pExynos)->flip_backbufs; + else + pBufPriv->num_buf = 1; +#endif + + pBufPriv->pBackPixmaps = + calloc(EXYNOSEXAPTR(pExynos)->flip_backbufs, sizeof(void *)); + XDBG_RETURN_VAL_IF_FAIL(pBufPriv->pBackPixmaps != NULL, NULL); + + for (i = 0; i < pBufPriv->num_buf; i++) { + pBufPriv->pBackPixmaps[i] = + (*pScreen->CreatePixmap) (pScreen, pDraw->width, pDraw->height, + pDraw->depth, + CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK); + XDBG_GOTO_IF_FAIL(pBufPriv->pBackPixmaps[i] != NULL, fail); +#if USE_XDBG + xDbgLogPListDrawAddRefPixmap(pDraw, pBufPriv->pBackPixmaps[i]); +#endif + + EXYNOSPixmapPriv *pPixPriv = + exaGetPixmapDriverPrivate(pBufPriv->pBackPixmaps[i]); + XDBG_DEBUG(MDRI2, "[%p] Allocate Backbuffer(%d): pix=%p name=%d\n", + (void *) pDraw->id, i, pBufPriv->pBackPixmaps[i], + tbm_bo_export(pPixPriv->bo)); + } + + pBufPriv->canFlip = flip; + pBufPriv->avail_idx = 0; + pBufPriv->free_idx = 0; + pBufPriv->cur_idx = 0; + pBufPriv->pipe = 0; //at this case it is unimportant + + return pBufPriv->pBackPixmaps; + + fail: + for (i = 0; i < pBufPriv->num_buf; i++) { + if (pBufPriv->pBackPixmaps[i] != NULL) { + xDbgLogPListDrawRemoveRefPixmap(pDraw, pBufPriv->pBackPixmaps[i]); + (*pScreen->DestroyPixmap) (pBufPriv->pBackPixmaps[i]); + pBufPriv->pBackPixmaps[i] = NULL; + } + } + + if (pBufPriv->pBackPixmaps) { + free(pBufPriv->pBackPixmaps); + pBufPriv->pBackPixmaps = NULL; + } + + return NULL; +} + +static PixmapPtr +_getBackPixmap(DrawablePtr pDraw, DRI2BufferPtr pBuf, Bool flip) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + + PixmapPtr pPixmap = NULL; + EXYNOSPixmapPriv *pPixPriv = NULL; + + if (!pBufPriv->pBackPixmaps) { + XDBG_RETURN_VAL_IF_FAIL(_createBackPixmaps(pDraw, pBuf, flip), NULL); + XDBG_RETURN_VAL_IF_FAIL(pBufPriv->pBackPixmaps != NULL, NULL); + } + else { + //increase the number of back buffers when SWAP->FLIP, but never decrease + if (flip && pBufPriv->num_buf < 2) + pBufPriv->num_buf = 2; + } + + if (pBufPriv->pBackPixmaps[pBufPriv->avail_idx] == NULL) { + pBufPriv->pBackPixmaps[pBufPriv->avail_idx] = + (*pScreen->CreatePixmap) (pScreen, pDraw->width, pDraw->height, + pDraw->depth, + CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK); + XDBG_RETURN_VAL_IF_FAIL(pBufPriv->pBackPixmaps[pBufPriv->avail_idx] != + NULL, NULL); +#if USE_XDBG + xDbgLogPListDrawAddRefPixmap(pDraw, pBufPriv->pBackPixmaps[pBufPriv->avail_idx]); +#endif + + pPixmap = pBufPriv->pBackPixmaps[pBufPriv->avail_idx]; + + pPixPriv = + exaGetPixmapDriverPrivate(pBufPriv->pBackPixmaps + [pBufPriv->avail_idx]); + XDBG_DEBUG(MDRI2, "[%p] Allocate Backbuffer(%d): pix=%p name=%d\n", + (void *) pDraw->id, pBufPriv->avail_idx, + pBufPriv->pBackPixmaps[pBufPriv->avail_idx], + tbm_bo_export(pPixPriv->bo)); + } + else { + pPixmap = pBufPriv->pBackPixmaps[pBufPriv->avail_idx]; + + pPixPriv = exaGetPixmapDriverPrivate(pPixmap); + XDBG_DEBUG(MDRI2, "[%p] Get Backbuffer(%d): pix=%p name=%d\n", + (void *) pDraw->id, pBufPriv->avail_idx, pPixmap, + tbm_bo_export(pPixPriv->bo)); + } + + return pPixmap; +} + +/* initialize the pixmap of the backbuffer */ +static PixmapPtr +_initBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSExaPrivPtr pExaPriv = EXYNOSEXAPTR(pExynos); + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK; + PixmapPtr pPixmap = NULL; + int pipe = -1; + + /* HWComposite */ + if (pExynos->hwc_active) { + return _getBackPixmap(pDraw, pBackBuf, canFlip); + } + + /* if a drawable can be flip, check whether the flip buffer is available */ + if (canFlip) { + usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; + pipe = exynosDisplayDrawablePipe(pDraw); + if (pipe != -1) { + /* get the flip pixmap from crtc */ + pPixmap = + exynosCrtcGetFreeFlipPixmap(pScrn, pipe, pDraw, usage_hint); + if (!pPixmap) { + /* fail to get a flip pixmap from crtc */ + canFlip = FALSE; + XDBG_WARNING(MDRI2, "fail to get a flip pixmap from crtc\n"); + } + } + else { + /* pipe is -1 */ + canFlip = FALSE; +#ifndef NO_CRTC_MODE + XDBG_WARNING(MDRI2, "pipe is -1\n"); +#endif + } + } + + /* if canflip is false, get the dri2_back pixmap */ + if (!canFlip) { + pPixmap = (*pScreen->CreatePixmap) (pScreen, + pDraw->width, + pDraw->height, + pDraw->depth, usage_hint); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); +#if USE_XDBG + xDbgLogPListDrawAddRefPixmap(pDraw, pPixmap); +#endif + } + + if (canFlip) { + pBackBufPriv->num_buf = pExaPriv->flip_backbufs; + pBackBufPriv->pBackPixmaps = + calloc(pBackBufPriv->num_buf, sizeof(void *)); + } + else { + pBackBufPriv->num_buf = 1; /* num of backbuffer for swap/blit */ + pBackBufPriv->pBackPixmaps = + calloc(pBackBufPriv->num_buf, sizeof(void *)); + } + + XDBG_RETURN_VAL_IF_FAIL((pBackBufPriv->pBackPixmaps != NULL), NULL); + + pBackBufPriv->pBackPixmaps[0] = pPixmap; + pBackBufPriv->canFlip = canFlip; + pBackBufPriv->avail_idx = 0; + pBackBufPriv->free_idx = 0; + pBackBufPriv->cur_idx = 0; + pBackBufPriv->pipe = pipe; + + return pPixmap; +} + +/* deinitialize the pixmap of the backbuffer */ +static void +_deinitBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip) +{ + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + ScreenPtr pScreen = pBackBufPriv->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int i; + int pipe = -1; + + for (i = 0; i < pBackBufPriv->num_buf; i++) { + if (pBackBufPriv->pBackPixmaps) { + if (pBackBufPriv->pBackPixmaps[i]) { + if (canFlip && (!EXYNOSPTR(pScrn)->hwc_active)) { + /* have to release the flip pixmap */ + pipe = pBackBufPriv->pipe; + if (pipe != -1) + exynosCrtcRelAllFlipPixmap(pScrn, pipe); + else + XDBG_WARNING(MDRI2, "pipe is -1\n"); + } + else { +#if USE_XDBG + xDbgLogPListDrawRemoveRefPixmap(pDraw, + pBackBufPriv->pBackPixmaps + [i]); +#endif + (*pScreen->DestroyPixmap) (pBackBufPriv->pBackPixmaps[i]); + } + pBackBufPriv->pBackPixmaps[i] = NULL; + pBackBufPriv->pPixmap = NULL; + } + } + } + free(pBackBufPriv->pBackPixmaps); + pBackBufPriv->pBackPixmaps = NULL; +} + +/* increase the next available index of the backbuffer */ +static void +_exchangeBackBufPixmap(DRI2BufferPtr pBackBuf) +{ + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + + /* increase avail_idx when buffers exchange */ + pBackBufPriv->avail_idx = + DRI2_GET_NEXT_IDX(pBackBufPriv->avail_idx, pBackBufPriv->num_buf); +} + +/* return the next available pixmap of the backbuffer */ +static PixmapPtr +_reuseBackBufPixmap(DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip, + int *reues) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + PixmapPtr pPixmap = NULL; + int avail_idx = pBackBufPriv->avail_idx; + unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK; + int pipe = -1; + + if (EXYNOSPTR(pScrn)->hwc_active) { + *reues = 1; + pPixmap = _getBackPixmap(pDraw, pBackBuf, canFlip); + pBackBufPriv->canFlip = canFlip; + return pPixmap; + } + + if (pBackBufPriv->canFlip != canFlip) { + /* flip buffer -> swap buffer */ + if (pBackBufPriv->canFlip && !canFlip) { + /* return the next available pixmap */ + _deinitBackBufPixmap(pBackBuf, pDraw, pBackBufPriv->canFlip); + pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); + return pPixmap; + } + + /* swap buffer -> flip buffer */ + if (!pBackBufPriv->canFlip && canFlip) { + pipe = exynosDisplayDrawablePipe(pDraw); + if (pipe != -1) { + /* return the next available pixmap */ + _deinitBackBufPixmap(pBackBuf, pDraw, pBackBufPriv->canFlip); + pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); + return pPixmap; + } + else { + canFlip = FALSE; + XDBG_WARNING(MDRI2, "pipe is -1\n"); + } + } + } + + /* set the next available pixmap */ + /* if pBackPixmap is available, reuse it */ + if (pBackBufPriv->pBackPixmaps[avail_idx]) { + if (canFlip) { + usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; + pipe = exynosDisplayDrawablePipe(pDraw); + if (pipe != -1) { + if (avail_idx != pBackBufPriv->cur_idx) { + /* get the flip pixmap from crtc */ + pBackBufPriv->pBackPixmaps[avail_idx] = + exynosCrtcGetFreeFlipPixmap(pScrn, pipe, pDraw, + usage_hint); + if (!pBackBufPriv->pBackPixmaps[avail_idx]) { + /* fail to get a flip pixmap from crtc */ + XDBG_WARNING(MDRI2, + "@@[reuse]: draw(0x%x) fail to get a flip pixmap from crtc to reset the index of pixmap\n", + (unsigned int) pDraw->id); + + _deinitBackBufPixmap(pBackBuf, pDraw, + pBackBufPriv->canFlip); + pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); + *reues = 0; + return pPixmap; + } + pBackBufPriv->cur_idx = avail_idx; + } + } + else { + XDBG_WARNING(MDRI2, "pipe is -1(%d)\n", pipe); + return NULL; + } + } + else { + if (avail_idx != pBackBufPriv->cur_idx) { + pBackBufPriv->cur_idx = avail_idx; + } + } + + *reues = 1; + } + else { + if (canFlip) { + usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; + pipe = exynosDisplayDrawablePipe(pDraw); + if (pipe != -1) { + if (avail_idx != pBackBufPriv->cur_idx) { + /* get the flip pixmap from crtc */ + pBackBufPriv->pBackPixmaps[avail_idx] = + exynosCrtcGetFreeFlipPixmap(pScrn, pipe, pDraw, + usage_hint); + if (!pBackBufPriv->pBackPixmaps[avail_idx]) { + /* fail to get a flip pixmap from crtc */ + XDBG_WARNING(MDRI2, + "@@[initial set]: draw(0x%x) fail to get a flip pixmap from crtc to generate and to set the next available pixmap.\n", + (unsigned int) pDraw->id); + + _deinitBackBufPixmap(pBackBuf, pDraw, TRUE); + pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); + *reues = 0; + return pPixmap; + } + pBackBufPriv->cur_idx = avail_idx; + } + } + } + else { + if (avail_idx != pBackBufPriv->cur_idx) { + + pBackBufPriv->pBackPixmaps[avail_idx] = + (*pScreen->CreatePixmap) (pScreen, pDraw->width, + pDraw->height, pDraw->depth, + usage_hint); + XDBG_RETURN_VAL_IF_FAIL(pBackBufPriv->pBackPixmaps[avail_idx] != + NULL, NULL); + pBackBufPriv->cur_idx = avail_idx; +#if USE_XDBG + xDbgLogPListDrawAddRefPixmap(pDraw, pPixmap); +#endif + } + } + + *reues = 0; + } + pPixmap = pBackBufPriv->pBackPixmaps[avail_idx]; + + pBackBufPriv->canFlip = canFlip; + return pPixmap; +} + +static void +_disuseBackBufPixmap(DRI2BufferPtr pBackBuf, DRI2FrameEventPtr pEvent) +{ + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + ScreenPtr pScreen = pBackBufPriv->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (pEvent->type == DRI2_FLIP) { + if (!EXYNOSPTR(pScrn)->hwc_active) { + exynosCrtcRelFlipPixmap(pScrn, pEvent->crtc_pipe, + pBackBufPriv->pBackPixmaps[pBackBufPriv-> + free_idx]); + } + /* increase free_idx when buffers destory or when frame is deleted */ + pBackBufPriv->free_idx = + DRI2_GET_NEXT_IDX(pBackBufPriv->free_idx, pBackBufPriv->num_buf); + } +} + +static void +_setDri2Property(DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) { + static Atom atom_use_dri2 = 0; + static int use = 1; + + if (!atom_use_dri2) { + atom_use_dri2 = MakeAtom("X_WIN_USE_DRI2", 14, TRUE); + } + + dixChangeWindowProperty(serverClient, + (WindowPtr) pDraw, atom_use_dri2, XA_CARDINAL, + 32, PropModeReplace, 1, &use, TRUE); + } +} + +static unsigned int +_getBufferFlag(DrawablePtr pDraw, Bool canFlip) +{ + DRI2BufferFlags flag; + + flag.flags = 0; + + switch (pDraw->type) { + case DRAWABLE_WINDOW: + flag.data.type = DRI2_BUFFER_TYPE_WINDOW; + break; + case DRAWABLE_PIXMAP: + flag.data.type = DRI2_BUFFER_TYPE_PIXMAP; + break; + } + + if (IS_VIEWABLE(pDraw)) { + flag.data.is_viewable = 1; + } + + if (canFlip) { + flag.data.is_framebuffer = 1; + } + + return flag.flags; +} + +static inline PixmapPtr +_getPixmapFromDrawable(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + PixmapPtr pPix; + + if (pDraw->type == DRAWABLE_WINDOW) + pPix = (*pScreen->GetWindowPixmap) ((WindowPtr) pDraw); + else + pPix = (PixmapPtr) pDraw; + + return pPix; +} + +/* Can this drawable be page flipped? */ +static Bool +_canFlip(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + WindowPtr pWin, pRoot; + PixmapPtr pWinPixmap, pRootPixmap; + int ret; + + if (!pExynos->use_flip) + return FALSE; + + if (pDraw->type == DRAWABLE_PIXMAP) + return FALSE; + + if (!IS_VIEWABLE(pDraw)) + return FALSE; + if (pExynos->isLcdOff) + return FALSE; + if (pExynos->hwc_active && !pExynos->hwc_use_def_layer) { + if (exynosHwcIsDrawExist(pDraw)) + return TRUE; + return FALSE; + } + + pRoot = pScreen->root; + pRootPixmap = pScreen->GetWindowPixmap(pRoot); + pWin = (WindowPtr) pDraw; + pWinPixmap = pScreen->GetWindowPixmap(pWin); + if (pRootPixmap != pWinPixmap) + return FALSE; + + ret = exynosFbFindBo(pExynos->pFb, + pDraw->x, pDraw->y, pDraw->width, pDraw->height, + NULL, NULL); + if (ret != rgnSAME) + return FALSE; + + return TRUE; +} + +static DRI2FrameEventType +_getSwapType(DrawablePtr pDraw, DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf) +{ + DRI2BufferPrivPtr pFrontBufPriv; + DRI2BufferPrivPtr pBackBufPriv; + PixmapPtr pFrontPix; + PixmapPtr pBackPix; + EXYNOSPixmapPriv *pFrontExaPixPriv = NULL; + EXYNOSPixmapPriv *pBackExaPixPriv = NULL; + DRI2FrameEventType swap_type = DRI2_NONE; + + if (!pFrontBuf || !pBackBuf) + return DRI2_NONE; + + /* if a buffer is not viewable at DRI2GetBuffers, return none */ + if (!IS_VIEWABLE(pDraw)) { + //XDBG_WARNING(MDRI2, "DRI2_NONE: window is not viewable.(%d,%d)\n", pDraw->width, pDraw->height); + return DRI2_NONE; + } + + pFrontBufPriv = pFrontBuf->driverPrivate; + pBackBufPriv = pBackBuf->driverPrivate; + pFrontPix = pFrontBufPriv->pPixmap; + pBackPix = pBackBufPriv->pPixmap; + if (!pFrontPix || !pBackPix) { + XDBG_WARNING(MDRI2, + "Warning: pFrontPix or pBackPix is null.(DRI2_NONE)\n"); + return DRI2_NONE; + } + + pFrontExaPixPriv = exaGetPixmapDriverPrivate(pFrontBufPriv->pPixmap); + pBackExaPixPriv = exaGetPixmapDriverPrivate(pBackBufPriv->pPixmap); + if (!pFrontExaPixPriv || !pBackExaPixPriv) { + XDBG_WARNING(MDRI2, + "Warning: pFrontPixPriv or pBackPixPriv is null.(DRI2_NONE)\n"); + return DRI2_NONE; + } + + /* Check Exchange */ + if (pFrontBufPriv->canFlip == 1) { + if (pBackBufPriv->canFlip == 1) { + swap_type = DRI2_FLIP; + + if (!_canFlip(pDraw)) { + ErrorF("@@@ [%10.3f] %" PRIXID " : flip to blit\n", + GetTimeInMillis() / 1000.0, pDraw->id); + swap_type = DRI2_BLIT; + } + } + else { + XDBG_WARNING(MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) \n", + pFrontBufPriv->canFlip, pBackBufPriv->canFlip); + swap_type = DRI2_FB_BLIT; + } + } + else { + if (pFrontExaPixPriv->isFrameBuffer == 1) { + //XDBG_WARNING (MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) : front is framebuffer \n", + // pFrontBufPriv->canFlip, pBackBufPriv->canFlip); + swap_type = DRI2_FB_BLIT; + } + else { + if (pFrontPix->drawable.width == pBackPix->drawable.width && + pFrontPix->drawable.height == pBackPix->drawable.height && + pFrontPix->drawable.bitsPerPixel == + pBackPix->drawable.bitsPerPixel) { + /*use swap only if flip is enable */ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDraw->pScreen); + + if (EXYNOSPTR(pScrn)->use_flip) + swap_type = DRI2_SWAP; + else + swap_type = DRI2_BLIT; + } + else { + swap_type = DRI2_BLIT; + } + } + } + + return swap_type; +} + +static void +_referenceBufferPriv(DRI2BufferPtr pBuf) +{ + if (pBuf) { + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + + pBufPriv->refcnt++; + } +} + +static void +_unreferenceBufferPriv(DRI2BufferPtr pBuf) +{ + if (pBuf) { + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + + pBufPriv->refcnt--; + } +} + +static Bool +_resetBufPixmap(DrawablePtr pDraw, DRI2BufferPtr pBuf) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + PixmapPtr pPix = NULL, pNewPix = NULL, pOldPix = NULL; + Bool canFlip = FALSE; + int reuse = 0; + + canFlip = _canFlip(pDraw); + + if (pBufPriv->attachment == DRI2BufferFrontLeft) { + pPix = _getPixmapFromDrawable(pDraw); + if (pPix != pBufPriv->pPixmap || + ((DRI2BufferFlags) pBuf->flags).data.is_viewable != + IS_VIEWABLE(pDraw)) { + pOldPix = pBufPriv->pPixmap; + + /* reset the pixmap and the name of the buffer */ + pNewPix = _getPixmapFromDrawable(pDraw); + pPix->refcnt++; + pBufPriv->canFlip = canFlip; + + /* Destroy Old buffer */ + if (pOldPix) { + (*pScreen->DestroyPixmap) (pOldPix); + } + } + else { + pBufPriv->canFlip = canFlip; + return FALSE; + } + } + else { + pNewPix = _reuseBackBufPixmap(pBuf, pDraw, canFlip, &reuse); + if (pNewPix == NULL) { + XDBG_WARNING(MDRI2, "Error pixmap is null\n"); + return FALSE; + } + + if (reuse) { + pBufPriv->pPixmap = pNewPix; + return FALSE; + } + } + + pBufPriv->pPixmap = pNewPix; + + pBuf->name = _getName(pNewPix); + pBuf->flags = _getBufferFlag(pDraw, canFlip); + + XDBG_TRACE(MDRI2, + "id:0x%lx(%d) can_flip:%d attach:%d, name:%d, flags:0x%x geo(%dx%d+%d+%d)\n", + pDraw->id, pDraw->type, pBufPriv->canFlip, pBuf->attachment, + pBuf->name, pBuf->flags, pDraw->width, pDraw->height, pDraw->x, + pDraw->y); + + return TRUE; +} + +static void +_generateDamage(DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent) +{ + BoxRec box; + RegionRec region; + + if (pFrameEvent->pRegion) { + /* translate the regions with drawable */ + BoxPtr pBox = RegionRects(pFrameEvent->pRegion); + int nBox = RegionNumRects(pFrameEvent->pRegion); + + while (nBox--) { + box.x1 = pBox->x1; + box.y1 = pBox->y1; + box.x2 = pBox->x2; + box.y2 = pBox->y2; + XDBG_DEBUG(MDRI2, + "Damage Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ", + nBox, box.x1, box.x2, box.y1, box.y2); + RegionInit(®ion, &box, 0); + DamageDamageRegion(pDraw, ®ion); + pBox++; + } + } + else { + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + RegionInit(®ion, &box, 0); + DamageDamageRegion(pDraw, ®ion); + } +} + +static void +_blitBuffers(DrawablePtr pDraw, DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf) +{ + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDraw->width; + box.y2 = pDraw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + EXYNOSDri2CopyRegion(pDraw, ®ion, pFrontBuf, pBackBuf); +} + +static void +_exchangeBuffers(DrawablePtr pDraw, DRI2FrameEventType type, + DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + DRI2BufferPrivPtr pFrontBufPriv = pFrontBuf->driverPrivate; + DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; + EXYNOSPixmapPriv *pFrontExaPixPriv = + exaGetPixmapDriverPrivate(pFrontBufPriv->pPixmap); + EXYNOSPixmapPriv *pBackExaPixPriv = + exaGetPixmapDriverPrivate(pBackBufPriv->pPixmap); + +// if(pFrontBufPriv->canFlip != pBackBufPriv->canFlip) +// { +// XDBG_WARNING (MDRI2, "Cannot exchange buffer(0x%x): Front(%d, canFlip:%d), Back(%d, canFlip:%d)\n", +// (unsigned int)pDraw->id, pFrontBuf->name, pFrontBufPriv->canFlip, +// pBackBuf->name, pBackBufPriv->canFlip); +// +// return; +// } + + /* exchange the buffers + * 1. exchange the bo of the exa pixmap private + * 2. get the name of the front buffer (the name of the back buffer will get next DRI2GetBuffers.) + */ + if (pFrontBufPriv->canFlip && !pExynos->hwc_active) { + XDBG_RETURN_IF_FAIL(NULL != + exynosFbSwapBo(pExynos->pFb, pBackExaPixPriv->bo)); + pFrontBuf->name = _getName(pFrontBufPriv->pPixmap); + } + else { + //Front pixmap can be screen pixmap which doesn't have bo. In this case + //exynosExaPrepareAccess() should be called. + tbm_bo front_bo = pFrontExaPixPriv->bo; + + if (front_bo == NULL) { + exynosExaPrepareAccess(pFrontBufPriv->pPixmap, EXA_PREPARE_DEST); + front_bo = pFrontExaPixPriv->bo; + exynosExaFinishAccess(pFrontBufPriv->pPixmap, EXA_PREPARE_DEST); + XDBG_RETURN_IF_FAIL(front_bo != NULL); + } + _bo_swap(front_bo, pBackExaPixPriv->bo); + pFrontBuf->name = _getName(pFrontBufPriv->pPixmap); + } + + /*Exchange pixmap owner and sbc */ + { + XID owner; + CARD64 sbc; + + owner = pFrontExaPixPriv->owner; + sbc = pFrontExaPixPriv->sbc; + + pFrontExaPixPriv->owner = pBackExaPixPriv->owner; + pFrontExaPixPriv->sbc = pBackExaPixPriv->sbc; + + pBackExaPixPriv->owner = owner; + pBackExaPixPriv->sbc = sbc; + } + + /* exchange the index of the available buffer */ + _exchangeBackBufPixmap(pBackBuf); +} + +static DRI2FrameEventPtr +_newFrame(ClientPtr pClient, DrawablePtr pDraw, + DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf, + DRI2SwapEventPtr swap_func, void *data, RegionPtr pRegion) +{ + DRI2FrameEventPtr pFrameEvent = NULL; + DRI2FrameEventType swap_type = DRI2_NONE; + + /* check and get the swap_type */ + swap_type = _getSwapType(pDraw, pFrontBuf, pBackBuf); + if (swap_type == DRI2_NONE) + return NULL; + + pFrameEvent = calloc(1, sizeof(DRI2FrameEventRec)); + if (!pFrameEvent) + return NULL; + + pFrameEvent->type = swap_type; + pFrameEvent->drawable_id = pDraw->id; + pFrameEvent->client_idx = pClient->index; + pFrameEvent->pClient = pClient; + pFrameEvent->event_complete = swap_func; + pFrameEvent->event_data = data; + pFrameEvent->pFrontBuf = pFrontBuf; + pFrameEvent->pBackBuf = pBackBuf; + + if (pRegion) { + pFrameEvent->pRegion = RegionCreate(RegionExtents(pRegion), + RegionNumRects(pRegion)); + if (!RegionCopy(pFrameEvent->pRegion, pRegion)) { + RegionDestroy(pFrameEvent->pRegion); + pFrameEvent->pRegion = NULL; + } + } + else { + pFrameEvent->pRegion = NULL; + } + + _referenceBufferPriv(pFrontBuf); + _referenceBufferPriv(pBackBuf); + + return pFrameEvent; +} + +static void +_swapFrame(DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent) +{ + switch (pFrameEvent->type) { + case DRI2_FLIP: + //_generateDamage (pDraw, pFrameEvent); + break; + case DRI2_SWAP: + _exchangeBuffers(pDraw, pFrameEvent->type, + pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf); + _generateDamage(pDraw, pFrameEvent); + break; + case DRI2_BLIT: + case DRI2_FB_BLIT: + /* copy the region from back buffer to front buffer */ + _blitBuffers(pDraw, pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf); + break; + default: + /* Unknown type */ + XDBG_WARNING(MDRI2, "%s: unknown swap_type received\n", __func__); + _generateDamage(pDraw, pFrameEvent); + break; + } +} + +static void +_deleteFrame(DrawablePtr pDraw, DRI2FrameEventPtr pEvent) +{ + /* some special case */ + DRI2BufferPrivPtr pFrontBufPriv; + DRI2BufferPrivPtr pBackBufPriv; + + if (pEvent->pBackBuf && pEvent->pFrontBuf) { + pFrontBufPriv = pEvent->pFrontBuf->driverPrivate; + pBackBufPriv = pEvent->pBackBuf->driverPrivate; + + /* + * Even though pFrontBufPriv->canFlip and pBackBufPriv->canFlip is 1, pEvent->type can have DRI2_BLIT. + * When it requests EXYNOSDri2ScheduleSwapWithRegion(), _canFlip(pDraw) is FALSE. So it has DRI2_BLIT type. + * In this case we should change pEvent->type to DRI2_FLIP. So we can call exynosCrtcRelFlipPixmap() for pEvent->pBackBuf + */ + if ((pFrontBufPriv->canFlip == 1) && (pBackBufPriv->canFlip == 1)) { + pEvent->type = DRI2_FLIP; + } + } + + if (pEvent->pBackBuf) { + /* disuse the backbuffer */ + _disuseBackBufPixmap(pEvent->pBackBuf, pEvent); + EXYNOSDri2DestroyBuffer(pDraw, pEvent->pBackBuf); + } + + if (pEvent->pFrontBuf) { + EXYNOSDri2DestroyBuffer(pDraw, pEvent->pFrontBuf); + } + + if (pEvent->pRegion) { + RegionDestroy(pEvent->pRegion); + } + + free(pEvent); + pEvent = NULL; +} + +static void +_asyncSwapBuffers(ClientPtr pClient, DrawablePtr pDraw, + DRI2FrameEventPtr pFrameEvent) +{ + XDBG_DEBUG(MDRI2, + "id:0x%x(%d) Client:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + (unsigned int) pDraw->id, pDraw->type, pClient->index, + pFrameEvent->pFrontBuf->attachment, pFrameEvent->pFrontBuf->name, + pFrameEvent->pFrontBuf->flags, pFrameEvent->pBackBuf->attachment, + pFrameEvent->pBackBuf->name, pFrameEvent->pBackBuf->flags); + + _swapFrame(pDraw, pFrameEvent); + + switch (pFrameEvent->type) { + case DRI2_SWAP: + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, + DRI2_EXCHANGE_COMPLETE, + pFrameEvent->event_complete, pFrameEvent->event_data); + break; + case DRI2_FLIP: + _exchangeBuffers(pDraw, pFrameEvent->type, pFrameEvent->pFrontBuf, + pFrameEvent->pBackBuf); + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE, + pFrameEvent->event_complete, pFrameEvent->event_data); + break; + case DRI2_BLIT: + case DRI2_FB_BLIT: + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, + DRI2_BLIT_COMPLETE, + pFrameEvent->event_complete, pFrameEvent->event_data); + break; + default: + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, + 0, + pFrameEvent->event_complete, pFrameEvent->event_data); + break; + } +} + +static Bool +_doPageFlip(DrawablePtr pDraw, int crtc_pipe, xf86CrtcPtr pCrtc, + DRI2FrameEventPtr pEvent) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; + EXYNOSPixmapPriv *pBackExaPixPriv = + exaGetPixmapDriverPrivate(pBackBufPriv->pPixmap); + + /* Reset buffer position */ + exynosRenderBoSetPos(pBackExaPixPriv->bo, pDraw->x, pDraw->y); + + if (!exynosModePageFlip(pScrn, NULL, pEvent, crtc_pipe, pBackExaPixPriv->bo, + pEvent->pRegion, pEvent->client_idx, + pEvent->drawable_id, exynosDri2FlipEventHandler, + FALSE)) { + XDBG_WARNING(MDRI2, "fail to exynosModePageFlip\n"); + return FALSE; + } + else { + XDBG_DEBUG(MDRI2, + "doPageFlip id:0x%x(%d) Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), " + "Back(attach:%d, name:%d, flag:0x%x )\n", + (unsigned int) pDraw->id, pDraw->type, + pEvent->pClient->index, crtc_pipe, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + + _exchangeBuffers(pDraw, pEvent->type, pEvent->pFrontBuf, + pEvent->pBackBuf); + } + + return TRUE; +} + +void +exynosDri2LayerFlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data, + Bool flip_failed) +{ + DRI2FrameEventPtr pEvent = NULL; + DRI2FrameEventPtr pPendingEvent = NULL; + DRI2BufferPrivPtr pBackBufPriv = NULL; + DrawablePtr pDraw = NULL; + ClientPtr pClient = NULL; + + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:LAYER_FLIP_HANDLER"); + + pEvent = (DRI2FrameEventPtr) event_data; + XDBG_RETURN_IF_FAIL(pEvent != NULL); + pClient = pEvent->pClient; + pBackBufPriv = pEvent->pBackBuf->driverPrivate; + + if (pEvent->drawable_id) + dixLookupDrawable(&pDraw, pEvent->drawable_id, serverClient, M_ANY, + DixWriteAccess); + + if (!pDraw) { + XDBG_WARNING(MDRI2, + "pDraw is null... Client:%d pipe:%d " + "Front(attach:%d, name:%d, flag:0x%x)," + " Back(attach:%d, name:%d, flag:0x%x)\n", pClient->index, + pBackBufPriv->pipe, pEvent->pFrontBuf->attachment, + pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, + pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, + pEvent->pBackBuf->flags); + + //delete event and save pending event + pPendingEvent = pEvent->pPendingEvent; + _deleteFrame(pDraw, pEvent); + pBackBufPriv->pFlipEvent = NULL; + + //delete pending event + if (pPendingEvent) { + XDBG_TRACE(MDRI2, + "FlipEvent(%d,0x%x) (Break pending flip:draw is not found) Client:%d pipe:%d " + "Front(attach:%d, name:%d, flag:0x%x)," + " Back(attach:%d, name:%d, flag:0x%x)\n", 0, 0, + pClient->index, pBackBufPriv->pipe, + pPendingEvent->pFrontBuf->attachment, + pPendingEvent->pFrontBuf->name, + pPendingEvent->pFrontBuf->flags, + pPendingEvent->pBackBuf->attachment, + pPendingEvent->pBackBuf->name, + pPendingEvent->pBackBuf->flags); + _deleteFrame(pDraw, pPendingEvent); + } + + TTRACE_GRAPHICS_END(); + return; + } + + XDBG_TRACE(MDRI2, + "FlipEvent(%d,0x%x) Client:%d pipe:%d " + "Front(attach:%d, name:%d, flag:0x%x)," + " Back(attach:%d, name:%d, flag:0x%x)\n", pDraw->type, + (unsigned int) pDraw->id, pClient->index, pBackBufPriv->pipe, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + + if (pBackBufPriv->num_buf == 1) { + DRI2SwapComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec, + DRI2_FLIP_COMPLETE, pEvent->event_complete, + pEvent->event_data); + } + + if (pBackBufPriv->pFlipEvent == pEvent) { + pPendingEvent = pEvent->pPendingEvent; + _deleteFrame(pDraw, pEvent); + pBackBufPriv->pFlipEvent = NULL; + + if (pPendingEvent) { + _scheduleLayerFlip(pDraw, pPendingEvent); + } + } + else { + XDBG_NEVER_GET_HERE(MDRI2); + } + + TTRACE_GRAPHICS_END(); + +} + +static void +_bo_swap(tbm_bo front_bo, tbm_bo back_bo) +{ + if (tbm_bo_swap(front_bo, back_bo)) { + EXYNOSFbBoDataPtr back_bo_data = NULL; + EXYNOSFbBoDataPtr bo_data = NULL; + EXYNOSFbBoDataRec tmp_bo_data; + + tbm_bo_get_user_data(front_bo, TBM_BO_DATA_FB, (void * *) &bo_data); + tbm_bo_get_user_data(back_bo, TBM_BO_DATA_FB, (void * *) &back_bo_data); + if (back_bo_data && bo_data) { + memcpy(&tmp_bo_data, bo_data, sizeof(EXYNOSFbBoDataRec)); + memcpy(bo_data, back_bo_data, sizeof(EXYNOSFbBoDataRec)); + memcpy(back_bo_data, &tmp_bo_data, sizeof(EXYNOSFbBoDataRec)); + XDBG_DEBUG(MDRI2, + "swap complete: front(bo:%p name:%d(%d) fb:%d) <-> back(bo:%p name:%d(%d) fb:%d)\n", + front_bo, tbm_bo_export(front_bo), bo_data->gem_handle, + bo_data->fb_id, back_bo, tbm_bo_export(back_bo), + back_bo_data->gem_handle, back_bo_data->fb_id); + } + else { + XDBG_DEBUG(MDRI2, + "swap complete: front(bo:%p name:%d) <-> back(bo:%p name:%d)\n", + front_bo, tbm_bo_export(front_bo), back_bo, + tbm_bo_export(back_bo)); + XDBG_WARNING(MDRI2, "user data is NULL: front(%p) back(%p)\n", + bo_data, back_bo_data); + } + } + else { + XDBG_ERROR(MDRI2, "swap fails\n"); + } +} + +static Bool +_scheduleLayerFlip(DrawablePtr pDraw, DRI2FrameEventPtr pEvent) +{ + + EXYNOSVideoBuf *vbuf = NULL; + + /* TODO: the Draw can be in several layers and + * we should update frame buffer for each of them + */ + XDBG_RETURN_VAL_IF_FAIL(pDraw != NULL, FALSE); + DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; + EXYNOSPtr pExynos = EXYNOSPTR(xf86Screens[pDraw->pScreen->myNum]); + + XDBG_RETURN_VAL_IF_FAIL(pExynos != NULL, FALSE; + ) + if (pExynos->isLcdOff) { + XDBG_WARNING(MDRI2, + "LCD OFF : Request a pageflip pending even if the lcd is off.\n"); + + _exchangeBuffers(pDraw, DRI2_FLIP, pEvent->pFrontBuf, pEvent->pBackBuf); + + DRI2SwapComplete(pEvent->pClient, pDraw, + 0, 0, 0, + 0, pEvent->event_complete, pEvent->event_data); + + pBackBufPriv->pFlipEvent = NULL; + _deleteFrame(pDraw, pEvent); + return TRUE; + } +#ifdef LAYER_MANAGER + EXYNOSLayerPos lpos = exynosHwcGetDrawLpos(pDraw); + + if (pExynos->hwc_use_def_layer) { + EXYNOSLayerPos p_lpos[5]; + int max_lpos = + exynosLayerMngGetListOfOwnedPos(lyr_client_id, 0, p_lpos); + + lpos = p_lpos[max_lpos - 1]; + } + if (lpos == LAYER_NONE) { + XDBG_WARNING(MDRI2, "Drawable(0x%x) was deleted from hwc\n", + (unsigned int) pDraw->id); + goto fail; + } + + if (pBackBufPriv->pFlipEvent) { + if (pBackBufPriv->pFlipEvent->pPendingEvent) { + XDBG_ERROR(MDRI2, "Pending event is exist\n"); + goto fail; + } + if (pBackBufPriv->num_buf < 2) { + XDBG_ERROR(MDRI2, "Pending event is exist\n"); + goto fail; + } + + pBackBufPriv->pFlipEvent->pPendingEvent = pEvent; + XDBG_TRACE(MDRI2, "FrameEvent(%d,0x%x) set to pending SwapType:%d " + "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pEvent->type, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + return TRUE; + } + + vbuf = + exynosUtilCreateVideoBufferByDraw((DrawablePtr) pBackBufPriv->pPixmap); + XDBG_GOTO_IF_FAIL(vbuf != NULL, fail); + vbuf->vblank_handler = exynosDri2LayerFlipEventHandler; + vbuf->vblank_user_data = pEvent; + exynosHwcSetDriFlag(pDraw, TRUE); + XDBG_GOTO_IF_FAIL(exynosLayerMngSet + (lyr_client_id, 0, 0, NULL, NULL, NULL, vbuf, 0, lpos, + NULL, NULL), fail); +#else + EXYNOSLayerPtr pLayer = NULL; + + pLayer = exynosLayerFindByDraw(pDraw); + XDBG_GOTO_IF_FAIL(pLayer != NULL, fail); + if (pLayer == NULL) { + XDBG_WARNING(MDRI2, "Drawable(0x%x) was deleted from hwc\n", + (unsigned int) pDraw->id); + goto fail; + } + + if (pBackBufPriv->pFlipEvent) { + if (pBackBufPriv->pFlipEvent->pPendingEvent) { + XDBG_ERROR(MDRI2, "Pending event is exist\n"); + goto fail; + } + if (pBackBufPriv->num_buf == 1) { + XDBG_ERROR(MDRI2, "Pending event is exist\n"); + goto fail; + } + pBackBufPriv->pFlipEvent->pPendingEvent = pEvent; + XDBG_TRACE(MDRI2, "FrameEvent(%d,0x%x) set to pending SwapType:%d " + "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pEvent->type, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + return TRUE; + } + vbuf = + exynosUtilCreateVideoBufferByDraw((DrawablePtr) pBackBufPriv->pPixmap); + XDBG_GOTO_IF_FAIL(vbuf != NULL, fail); + + exynosLayerFreezeUpdate(pLayer, FALSE); + exynosLayerEnableVBlank(pLayer, TRUE); + exynosLayerUpdateDRI(pLayer, TRUE); + vbuf->vblank_handler = exynosDri2LayerFlipEventHandler; + vbuf->vblank_user_data = pEvent; + XDBG_GOTO_IF_FAIL(exynosLayerSetBuffer(pLayer, vbuf), fail); +#endif + + exynosUtilVideoBufferUnref(vbuf); //do unref for vbuf because vbuf is local variable + _exchangeBuffers(pDraw, DRI2_FLIP, pEvent->pFrontBuf, pEvent->pBackBuf); + pBackBufPriv->pFlipEvent = pEvent; + + if (pBackBufPriv->num_buf > 1) { + DRI2SwapComplete(pEvent->pClient, pDraw, 0, 0, 0, 0, + pEvent->event_complete, pEvent->event_data); + } + return TRUE; + fail: + if (vbuf) + exynosUtilFreeVideoBuffer(vbuf); + XDBG_WARNING(MDRI2, "fail to FLIP. Do blit\n"); + _blitBuffers(pDraw, pEvent->pFrontBuf, pEvent->pBackBuf); + DRI2SwapComplete(pEvent->pClient, pDraw, + 0, 0, 0, 0, pEvent->event_complete, pEvent->event_data); + + XDBG_TRACE(MDRI2, + "FrameEvent(%d,0x%x) SwapType:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pEvent->type, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + + _deleteFrame(pDraw, pEvent); + return FALSE; +} + +static Bool +_scheduleFlip(DrawablePtr pDraw, DRI2FrameEventPtr pEvent, Bool bFlipChain) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + BoxRec box; + + /* main crtc for this drawable shall finally deliver pageflip event */ + int crtc_pipe = exynosDisplayDrawablePipe(pDraw); + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + pCrtc = exynosModeCoveringCrtc(pScrn, &box, NULL, NULL); + + if (!pCrtc) { + XDBG_WARNING(MDRI2, "fail to get a crtc from a drawable\n"); + DRI2SwapComplete(pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE, + pEvent->event_complete, pEvent->event_data); + _deleteFrame(pDraw, pEvent); + return FALSE; + } + + pEvent->pCrtc = (void *) pCrtc; + pEvent->crtc_pipe = crtc_pipe; + + pCrtcPriv = pCrtc->driver_private; + + DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; + + if (exynosCrtcIsFlipping(pCrtc) || pBackBufPriv->pFlipEvent) { + /* Set the pending filp frame_event to the back buffer + * if the previous flip frmae_event is not completed. + */ + if (pBackBufPriv->pFlipEvent) { + if (pBackBufPriv->pFlipEvent->pPendingEvent) { + XDBG_WARNING(MDRI2, "waring : pPendingEvent exist.\n"); + return FALSE; + } + pBackBufPriv->pFlipEvent->pPendingEvent = pEvent; + } + + if (pCrtcPriv->is_fb_blit_flipping || !bFlipChain) { + exynosCrtcAddPendingFlip(pCrtc, pEvent); + return TRUE; + } + } + + if (!_doPageFlip(pDraw, crtc_pipe, pCrtc, pEvent)) { + XDBG_WARNING(MDRI2, "_doPageflip failed\n"); + _deleteFrame(pDraw, pEvent); + } + else { + /* set the flip frame_event */ + pBackBufPriv->pFlipEvent = pEvent; + DRI2SwapComplete(pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE, + pEvent->event_complete, pEvent->event_data); + } + + return TRUE; +} + +static void +_saveDrawable(ClientPtr pClient, DrawablePtr pDraw, DRI2BufferPtr pBackBuf, + DRI2FrameEventType swap_type) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + char *type[5] = { "none", "swap", "flip", "blit", "fbblit" }; + char file[128]; + PixmapPtr pPix; + DRI2BufferPrivPtr pBackBufPriv; + EXYNOSPixmapPriv *pExaPixPriv; + char *appName = NULL; + const char *cmdName = NULL; + + if (!pExynos->dump_info) + return; + + XDBG_RETURN_IF_FAIL(pDraw != NULL); + XDBG_RETURN_IF_FAIL(pBackBuf != NULL); + + pPix = _getPixmapFromDrawable(pDraw); + XDBG_RETURN_IF_FAIL(pPix != NULL); + pBackBufPriv = pBackBuf->driverPrivate; + XDBG_RETURN_IF_FAIL(pBackBufPriv != NULL); + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + XDBG_RETURN_IF_FAIL(pExaPixPriv != NULL); + + cmdName = GetClientCmdName(pClient); + + if (cmdName) + appName = strrchr(cmdName, '/'); + + snprintf(file, sizeof(file), "%03d_%s_%s_%x_%03d.%s", + pExynos->flip_cnt, type[swap_type], + (appName ? (++appName) : ("none")), (unsigned int) pDraw->id, + pExaPixPriv->dump_cnt, pExynos->dump_type); + + if (!strcmp(pExynos->dump_type, DUMP_TYPE_RAW)) { + Bool need_finish = FALSE; + EXYNOSPixmapPriv *privPixmap = + exaGetPixmapDriverPrivate(pBackBufPriv->pPixmap); + int size; + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pBackBufPriv->pPixmap, EXA_PREPARE_DEST); + XDBG_RETURN_IF_FAIL(privPixmap->bo != NULL); + } + size = tbm_bo_size(privPixmap->bo); + exynosUtilDoDumpRaws(pExynos->dump_info, &privPixmap->bo, &size, 1, + file); + + if (need_finish) + exynosExaFinishAccess(pBackBufPriv->pPixmap, EXA_PREPARE_DEST); + } + else + exynosUtilDoDumpPixmaps(pExynos->dump_info, pBackBufPriv->pPixmap, file, + pExynos->dump_type); + + XDBG_DEBUG(MSEC, "dump done\n"); + + pExaPixPriv->dump_cnt++; +} + +static DRI2BufferPtr +EXYNOSDri2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, + unsigned int format) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:CREATE_BUF"); + + ScreenPtr pScreen = pDraw->pScreen; + DRI2BufferPtr pBuf = NULL; + DRI2BufferPrivPtr pBufPriv = NULL; + PixmapPtr pPix = NULL; + Bool canFlip = FALSE; + + /* create dri2 buffer */ + pBuf = calloc(1, sizeof(DRI2BufferRec)); + if (pBuf == NULL) + goto fail; + + /* create dri2 buffer private */ + pBufPriv = calloc(1, sizeof(DRI2BufferPrivRec)); + if (pBufPriv == NULL) + goto fail; + + /* check canFlip */ + canFlip = _canFlip(pDraw); + + pBuf->driverPrivate = pBufPriv; + pBuf->format = format; + pBuf->flags = _getBufferFlag(pDraw, canFlip); + + /* check the attachments */ + if (attachment == DRI2BufferFrontLeft) { + pPix = _getPixmapFromDrawable(pDraw); + pPix->refcnt++; + pBufPriv->canFlip = canFlip; + } + else { + switch (attachment) { + case DRI2BufferDepth: + case DRI2BufferDepthStencil: + case DRI2BufferFakeFrontLeft: + case DRI2BufferFakeFrontRight: + case DRI2BufferBackRight: + case DRI2BufferBackLeft: + pPix = _initBackBufPixmap(pBuf, pDraw, canFlip); + if (pPix == NULL) { + goto fail; + } + break; + default: + XDBG_ERROR(MDRI2, "Unsupported attachmemt:%d\n", attachment); + goto fail; + break; + } + + //Set DRI2 property for selective-composite mode + _setDri2Property(pDraw); + } + + pBuf->cpp = pPix->drawable.bitsPerPixel / 8; + pBuf->attachment = attachment; + pBuf->pitch = pPix->devKind; + pBuf->name = _getName(pPix); + if (pBuf->name == 0) { + goto fail; + } + + pBufPriv->refcnt = 1; + pBufPriv->attachment = attachment; + pBufPriv->pPixmap = pPix; + pBufPriv->pScreen = pScreen; + + XDBG_DEBUG(MDRI2, + "id:0x%lx(%d) attach:%d, name:%d, flags:0x%x, flip:%d geo(%dx%d+%d+%d)\n", + pDraw->id, pDraw->type, pBuf->attachment, pBuf->name, + pBuf->flags, pBufPriv->canFlip, pDraw->width, pDraw->height, + pDraw->x, pDraw->y); + + TTRACE_GRAPHICS_END(); + return pBuf; + fail: + XDBG_WARNING(MDRI2, "Failed: id:0x%lx(%d) attach:%d,geo(%dx%d+%d+%d)\n", + pDraw->id, pDraw->type, attachment, pDraw->width, + pDraw->height, pDraw->x, pDraw->y); + if (pPix) { +#if USE_XDBG + xDbgLogPListDrawRemoveRefPixmap(pDraw, pPix); +#endif + (*pScreen->DestroyPixmap) (pPix); + } + if (pBufPriv) + free(pBufPriv); + if (pBuf) + free(pBuf); + + TTRACE_GRAPHICS_END(); + + return NULL; +} + +static void +EXYNOSDri2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr pBuf) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:DESTROY_BUF"); + + ScreenPtr pScreen = NULL; + DRI2BufferPrivPtr pBufPriv = NULL; + + if (pBuf == NULL) { + TTRACE_GRAPHICS_END(); + return; + } + + pBufPriv = pBuf->driverPrivate; + pScreen = pBufPriv->pScreen; + + _unreferenceBufferPriv(pBuf); + + if (pBufPriv->refcnt == 0) { + XDBG_DEBUG(MDRI2, "DestroyBuffer(%d:0x%x) name:%d flip:%d\n", + pDraw ? pDraw->type : 0, + pDraw ? (unsigned int) pDraw->id : 0, + pBuf->name, pBufPriv->canFlip); + + if (pBuf->attachment == DRI2BufferFrontLeft) { + (*pScreen->DestroyPixmap) (pBufPriv->pPixmap); + } + else { + _deinitBackBufPixmap(pBuf, pDraw, pBufPriv->canFlip); + } + + pBufPriv->pPixmap = NULL; + free(pBufPriv); + free(pBuf); + } + + TTRACE_GRAPHICS_END(); +} + +static void +EXYNOSDri2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, + DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:COPY_REGION"); + + DRI2BufferPrivPtr pSrcBufPriv = pSrcBuf->driverPrivate; + DRI2BufferPrivPtr pDstBufPriv = pDstBuf->driverPrivate; + ScreenPtr pScreen = pDraw->pScreen; + RegionPtr pCopyClip; + GCPtr pGc; + + DrawablePtr pSrcDraw = (pSrcBufPriv->attachment == DRI2BufferFrontLeft) + ? pDraw : &pSrcBufPriv->pPixmap->drawable; + DrawablePtr pDstDraw = (pDstBufPriv->attachment == DRI2BufferFrontLeft) + ? pDraw : &pDstBufPriv->pPixmap->drawable; + + pGc = GetScratchGC(pDstDraw->depth, pScreen); + if (!pGc) { + TTRACE_GRAPHICS_END(); + return; + } + + XDBG_DEBUG(MDRI2, + "CopyRegion(%d,0x%x) Dst(attach:%d, name:%d, flag:0x%x), Src(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pDstBuf->attachment, + pDstBuf->name, pDstBuf->flags, pSrcBuf->attachment, + pSrcBuf->name, pSrcBuf->flags); + + pCopyClip = REGION_CREATE(pScreen, NULL, 0); + REGION_COPY(pScreen, pCopyClip, pRegion); + (*pGc->funcs->ChangeClip) (pGc, CT_REGION, pCopyClip, 0); + ValidateGC(pDstDraw, pGc); + + /* Wait for the scanline to be outside the region to be copied */ + /* [TODO] Something Do ??? */ + + /* It's important that this copy gets submitted before the + * direct rendering client submits rendering for the next + * frame, but we don't actually need to submit right now. The + * client will wait for the DRI2CopyRegion reply or the swap + * buffer event before rendering, and we'll hit the flush + * callback chain before those messages are sent. We submit + * our batch buffers from the flush callback chain so we know + * that will happen before the client tries to render + * again. */ + + (*pGc->ops->CopyArea) (pSrcDraw, pDstDraw, + pGc, 0, 0, pDraw->width, pDraw->height, 0, 0); + (*pGc->funcs->DestroyClip) (pGc); + FreeScratchGC(pGc); + + TTRACE_GRAPHICS_END(); +} + +/* + * ScheduleSwap is responsible for requesting a DRM vblank event for the + * appropriate frame. + * + * In the case of a blit (e.g. for a windowed swap) or buffer exchange, + * the vblank requested can simply be the last queued swap frame + the swap + * interval for the drawable. + * + * In the case of a page flip, we request an event for the last queued swap + * frame + swap interval - 1, since we'll need to queue the flip for the frame + * immediately following the received event. + * + * The client will be blocked if it tries to perform further GL commands + * after queueing a swap, though in the Intel case after queueing a flip, the + * client is free to queue more commands; they'll block in the kernel if + * they access buffers busy with the flip. + * + * When the swap is complete, the driver should call into the server so it + * can send any swap complete events that have been requested. + */ +static int +EXYNOSDri2ScheduleSwapWithRegion(ClientPtr pClient, DrawablePtr pDraw, + DRI2BufferPtr pFrontBuf, + DRI2BufferPtr pBackBuf, CARD64 * target_msc, + CARD64 divisor, CARD64 remainder, + DRI2SwapEventPtr swap_func, void *data, + RegionPtr pRegion) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:SWAP_WITH_REGION"); + + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int pipe = 0; /* default */ + int flip = 0; + DRI2FrameEventPtr pFrameEvent = NULL; + DRI2FrameEventType swap_type = DRI2_SWAP; + CARD64 current_msc; + CARD64 ust, msc; + + pFrameEvent = + _newFrame(pClient, pDraw, pFrontBuf, pBackBuf, swap_func, data, + pRegion); + if (!pFrameEvent) { + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, 0, swap_func, data); + + TTRACE_GRAPHICS_END(); + return TRUE; + } + + /* Set frame count to back */ + { + PixmapPtr pPix; + EXYNOSPixmapPriv *pExaPixPriv = NULL; + DRI2BufferPrivPtr pBufPriv = pBackBuf->driverPrivate; + CARD64 sbc; + unsigned int pending; + + pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx]; + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + DRI2GetSBC(pDraw, &sbc, &pending); + pExaPixPriv->owner = pDraw->id; + pExaPixPriv->sbc = sbc + pending; + } + + swap_type = pFrameEvent->type; + + XDBG_DEBUG(MSEC, "dump_mode(%x) dump_xid(0x%lx:0x%lx) swap_type(%d)\n", + pExynos->dump_mode, pExynos->dump_xid, pDraw->id, swap_type); + + if ((pExynos->dump_mode & XBERC_DUMP_MODE_DRAWABLE) && + (swap_type != DRI2_NONE && swap_type != DRI2_WAITMSC) && + (pExynos->dump_xid == 0 || pExynos->dump_xid == pDraw->id)) + _saveDrawable(pClient, pDraw, pBackBuf, swap_type); + +#ifdef NO_CRTC_MODE + if (pExynos->isCrtcOn == FALSE) { + XDBG_DEBUG(MDRI2, "Not found active crtc using async swa\n"); + _asyncSwapBuffers(pClient, pDraw, pFrameEvent); + _deleteFrame(pDraw, pFrameEvent); + TTRACE_GRAPHICS_END(); + return TRUE; + } + else +#endif //NO_CRTC_MODE + /* If lcd is off status, SwapBuffers do not consider the vblank sync. + * The client that launches after lcd is off wants to render the frame + * on the fly. + */ + if (pExynos->isLcdOff == TRUE || pExynos->useAsyncSwap == TRUE) { + XDBG_DEBUG(MDRI2, "LCD is %s. %s Async\n", + pExynos->isLcdOff ? "Disable" : "Enable", + pExynos->useAsyncSwap ? "Use" : "Not use"); + _asyncSwapBuffers(pClient, pDraw, pFrameEvent); + _deleteFrame(pDraw, pFrameEvent); + TTRACE_GRAPHICS_END(); + return TRUE; + } + + if (!pExynos->hwc_active) { + pipe = exynosDisplayDrawablePipe(pDraw); + + /* check if the pipe is -1 */ + if (pipe == -1) { + /* if swap_type is DRI2_FLIP, fall into the async swap */ + if (swap_type == DRI2_FLIP) { + XDBG_WARNING(MDRI2, "Warning: flip pipe is -1 \n"); + _asyncSwapBuffers(pClient, pDraw, pFrameEvent); + _deleteFrame(pDraw, pFrameEvent); + TTRACE_GRAPHICS_END(); + return TRUE; + } + } + } + + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal */ + *target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + + /* Get current count */ + if (!exynosDisplayGetCurMSC(pScrn, pipe, &ust, &msc)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to get current_msc\n"); + goto blit_fallback; + } + current_msc = msc; + + /* Flips need to be submitted one frame before */ + if (swap_type == DRI2_FLIP) { + flip = 1; + } + + /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. + * Do it early, so handling of different timing constraints + * for divisor, remainder and msc vs. target_msc works. + */ + if (*target_msc > 0) + *target_msc -= flip; + + /* + * If divisor is zero, or current_msc is smaller than target_msc + * we just need to make sure target_msc passes before initiating + * the swap. + */ + if (divisor == 0 || current_msc < *target_msc) { + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This makes swap_interval logic more robust. + */ + if (current_msc >= *target_msc) + *target_msc = current_msc; + + if (!exynosDisplayVBlank + (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); + goto blit_fallback; + } + + pFrameEvent->frame = (unsigned int) *target_msc; + + XDBG_DEBUG(MDRI2, + "id:0x%x(%d) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), " + "Back(attach:%d, name:%d, flag:0x%x )\n", + (unsigned int) pDraw->id, pDraw->type, swap_type, + pClient->index, pipe, pFrontBuf->attachment, pFrontBuf->name, + pFrontBuf->flags, pBackBuf->attachment, pBackBuf->name, + pBackBuf->flags); + + if (pFrameEvent->pRegion) { + BoxPtr pBox = RegionRects(pFrameEvent->pRegion); + int nBox = RegionNumRects(pFrameEvent->pRegion); + + while (nBox--) { + XDBG_DEBUG(MDRI2, + "Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ", + nBox, pBox->x1, pBox->y1, pBox->x2, pBox->y2); + pBox++; + } + } + + _swapFrame(pDraw, pFrameEvent); + + TTRACE_GRAPHICS_END(); + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * and we need to queue an event that will satisfy the divisor/remainder + * equation. + */ + *target_msc = current_msc - (current_msc % divisor) + remainder; + + /* + * If the calculated deadline vbl.request.sequence is smaller than + * or equal to current_msc, it means we've passed the last point + * when effective onset frame seq could satisfy + * seq % divisor == remainder, so we need to wait for the next time + * this will happen. + + * This comparison takes the 1 frame swap delay in pageflipping mode + * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay + * if we are blitting/exchanging instead of flipping. + */ + if (*target_msc <= current_msc) + *target_msc += divisor; + + /* Account for 1 frame extra pageflip delay if flip > 0 */ + *target_msc -= flip; + + if (!exynosDisplayVBlank + (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); + goto blit_fallback; + } + + pFrameEvent->frame = *target_msc; + + XDBG_DEBUG(MDRI2, + "ScaduleSwap_ex(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, swap_type, pClient->index, + pipe, pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags, + pBackBuf->attachment, pBackBuf->name, pBackBuf->flags); + + _swapFrame(pDraw, pFrameEvent); + + TTRACE_GRAPHICS_END(); + return TRUE; + + blit_fallback: + XDBG_WARNING(MDRI2, + "blit_fallback(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, swap_type, + pClient->index, pipe, pFrontBuf->attachment, pFrontBuf->name, + pFrontBuf->flags, pBackBuf->attachment, pBackBuf->name, + pBackBuf->flags); + + _blitBuffers(pDraw, pFrontBuf, pBackBuf); + + DRI2SwapComplete(pClient, pDraw, 0, 0, 0, DRI2_BLIT_COMPLETE, swap_func, + data); + + if (pFrameEvent) { + _deleteFrame(pDraw, pFrameEvent); + } + *target_msc = 0; /* offscreen, so zero out target vblank count */ + + TTRACE_GRAPHICS_END(); + + return TRUE; +} + +/* + * Get current frame count and frame count timestamp, based on drawable's + * crtc. + */ +static int +EXYNOSDri2GetMSC(DrawablePtr pDraw, CARD64 * ust, CARD64 * msc) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int pipe; + + pipe = exynosDisplayDrawablePipe(pDraw); + + /* Get current count */ + if (!exynosDisplayGetCurMSC(pScrn, pipe, ust, msc)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to get current_msc\n"); + return FALSE; + } + + return TRUE; +} + +/* + * Request a DRM event when the requested conditions will be satisfied. + * + * We need to handle the event and ask the server to wake up the client when + * we receive it. + */ +static int +EXYNOSDri2ScheduleWaitMSC(ClientPtr pClient, DrawablePtr pDraw, + CARD64 target_msc, CARD64 divisor, CARD64 remainder) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRI2FrameEventPtr wait_info = NULL; + CARD64 current_msc; + CARD64 ust, msc; + + int pipe = 0; + + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal */ + target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + + /* Drawable not visible, return immediately */ + pipe = exynosDisplayDrawablePipe(pDraw); + if (pipe == -1) + goto out_complete; + + wait_info = calloc(1, sizeof(DRI2FrameEventRec)); + if (!wait_info) + goto out_complete; + + wait_info->drawable_id = pDraw->id; + wait_info->pClient = pClient; + wait_info->type = DRI2_WAITMSC; + + /* Get current count */ + if (!exynosDisplayGetCurMSC(pScrn, pipe, &ust, &msc)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to get current_msc\n"); + goto out_complete; + } + current_msc = msc; + + /* + * If divisor is zero, or current_msc is smaller than target_msc, + * we just need to make sure target_msc passes before waking up the + * client. + */ + if (divisor == 0 || current_msc < target_msc) { + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This keeps the client from continually + * sending us MSC targets from the past by forcibly updating + * their count on this call. + */ + if (current_msc >= target_msc) + target_msc = current_msc; + + /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */ + if (!exynosDisplayVBlank + (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); + goto out_complete; + } + + wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in exynosDisplayVBlank */ + DRI2BlockClient(pClient, pDraw); + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * so we queue an event that will satisfy the divisor/remainder equation. + */ + target_msc = current_msc - (current_msc % divisor) + remainder; + + /* + * If calculated remainder is larger than requested remainder, + * it means we've passed the last point where + * seq % divisor == remainder, so we need to wait for the next time + * that will happen. + */ + if ((current_msc % divisor) >= remainder) + target_msc += divisor; + + /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */ + if (!exynosDisplayVBlank + (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); + goto out_complete; + } + + wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in exynosDisplayVBlank */ + DRI2BlockClient(pClient, pDraw); + + return TRUE; + + out_complete: + free(wait_info); + DRI2WaitMSCComplete(pClient, pDraw, target_msc, 0, 0); + return TRUE; +} + +static int +EXYNOSDri2AuthMagic(int fd, uint32_t magic) +{ + int ret; + + ret = drmAuthMagic(fd, (drm_magic_t) magic); + + XDBG_TRACE(MDRI2, "AuthMagic: %d\n", ret); + + return ret; +} + +static void +EXYNOSDri2ReuseBufferNotify(DrawablePtr pDraw, DRI2BufferPtr pBuf) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:REUSE_BUF_NOTIFY"); + + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + + if (!_resetBufPixmap(pDraw, pBuf)) { + DRI2BufferFlags *flags = (DRI2BufferFlags *) & pBuf->flags; + + pBuf->name = _getName(pBufPriv->pPixmap); + flags->flags = _getBufferFlag(pDraw, pBufPriv->canFlip); + flags->data.is_reused = 1; + + /*Set reuse index */ + if (pBuf->attachment != DRI2BufferFrontLeft) { + DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; + PixmapPtr pPix; + EXYNOSPixmapPriv *pExaPixPriv = NULL; + CARD64 sbc; + unsigned int pending; + + pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx]; + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + + DRI2GetSBC(pDraw, &sbc, &pending); + /*Get current count */ + if (pExaPixPriv->owner == pDraw->id) { + unsigned int idx_reuse = sbc + pending - pExaPixPriv->sbc + 1; + + if (idx_reuse > pBufPriv->num_buf + 1) { + flags->data.idx_reuse = 0; + } + else { + flags->data.idx_reuse = idx_reuse; + } + } + else { + flags->data.idx_reuse = 0; + } + } + else { + flags->data.idx_reuse = 0; + } + } + + XDBG_DEBUG(MDRI2, + "id:0x%lx(%d) attach:%d, name:%d, flags:0x%x, flip:%d, geo(%dx%d+%d+%d)\n", + pDraw->id, pDraw->type, pBuf->attachment, pBuf->name, + pBuf->flags, pBufPriv->canFlip, pDraw->width, pDraw->height, + pDraw->x, pDraw->y); + + TTRACE_GRAPHICS_END(); +} + +void +exynosDri2ProcessPending(xf86CrtcPtr pCrtc, + unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec) +{ + DRI2BufferPrivPtr pBackBufPriv = NULL; + DrawablePtr pCrtcPendingDraw = NULL; + DRI2FrameEventPtr pCrtcPendingFlip = NULL; + + pCrtcPendingFlip = exynosCrtcGetFirstPendingFlip(pCrtc); + if (pCrtcPendingFlip) { + pBackBufPriv = pCrtcPendingFlip->pBackBuf->driverPrivate; + ScreenPtr pScreen = pBackBufPriv->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + exynosCrtcRemovePendingFlip(pCrtc, pCrtcPendingFlip); + + if (pCrtcPendingFlip->drawable_id) + dixLookupDrawable(&pCrtcPendingDraw, pCrtcPendingFlip->drawable_id, + serverClient, M_ANY, DixWriteAccess); + if (!pCrtcPendingDraw) { + XDBG_WARNING(MDRI2, "pCrtcPendingDraw is null.\n"); + _deleteFrame(pCrtcPendingDraw, pCrtcPendingFlip); + return; + } + else { + if (pExynos->isLcdOff) { + XDBG_WARNING(MDRI2, + "LCD OFF : Request a pageflip pending even if the lcd is off.\n"); + + _exchangeBuffers(pCrtcPendingDraw, DRI2_FLIP, + pCrtcPendingFlip->pFrontBuf, + pCrtcPendingFlip->pBackBuf); + + DRI2SwapComplete(pCrtcPendingFlip->pClient, pCrtcPendingDraw, + frame, tv_sec, tv_usec, + 0, pCrtcPendingFlip->event_complete, + pCrtcPendingFlip->event_data); + + pBackBufPriv = pCrtcPendingFlip->pBackBuf->driverPrivate; + pBackBufPriv->pFlipEvent = NULL; + _deleteFrame(pCrtcPendingDraw, pCrtcPendingFlip); + } + else { + if (!_scheduleFlip(pCrtcPendingDraw, pCrtcPendingFlip, TRUE)) { + XDBG_WARNING(MDRI2, + "fail to _scheduleFlip in exynosDri2FlipEventHandler\n"); + } + } + } + } + +} + +void +exynosDri2FlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data, + Bool flip_failed) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:FLIP_HANDLER"); + + DRI2FrameEventPtr pEvent = event_data; + + if (event_data == NULL) { + TTRACE_GRAPHICS_END(); + XDBG_NEVER_GET_HERE(MDRI2); + return; + } + + DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; + DrawablePtr pDraw = NULL; + ClientPtr pClient = pEvent->pClient; + xf86CrtcPtr pCrtc = (xf86CrtcPtr) pEvent->pCrtc; + + if (pEvent->drawable_id) + dixLookupDrawable(&pDraw, pEvent->drawable_id, serverClient, M_ANY, + DixWriteAccess); + if (!pDraw) { + XDBG_WARNING(MDRI2, "pDraw is null... Client:%d pipe:%d " + "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pClient->index, pBackBufPriv->pipe, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + exynosDri2ProcessPending(pCrtc, frame, tv_sec, tv_usec); + _deleteFrame(pDraw, pEvent); + + TTRACE_GRAPHICS_END(); + return; + } + + XDBG_TRACE(MDRI2, "FlipEvent(%d,0x%x) Client:%d pipe:%d " + "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pClient->index, + pBackBufPriv->pipe, pEvent->pFrontBuf->attachment, + pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, + pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, + pEvent->pBackBuf->flags); + + /* check the failure of the pageflip */ + if (flip_failed) { + _exchangeBuffers(pDraw, DRI2_FLIP, pEvent->pFrontBuf, pEvent->pBackBuf); + + DRI2SwapComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec, + 0, pEvent->event_complete, pEvent->event_data); + _deleteFrame(pDraw, pEvent); + + TTRACE_GRAPHICS_END(); + return; + } + + assert(pBackBufPriv->pFlipEvent == pEvent); + pBackBufPriv->pFlipEvent = NULL; + _deleteFrame(pDraw, pEvent); + + /* get the next pending flip event */ + exynosDri2ProcessPending(pCrtc, frame, tv_sec, tv_usec); + + TTRACE_GRAPHICS_END(); +} + +void +exynosDri2FrameEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + TTRACE_GRAPHICS_BEGIN("XORG:DRI2:FRAME_HANDLER"); + + DRI2FrameEventPtr pEvent = event_data; + DrawablePtr pDraw = NULL; + ScrnInfoPtr pScrn; + int status; + + status = dixLookupDrawable(&pDraw, pEvent->drawable_id, serverClient, + M_ANY, DixWriteAccess); + if (status != Success) { + XDBG_WARNING(MDRI2, "drawable is not found\n"); + + _deleteFrame(NULL, pEvent); + + TTRACE_GRAPHICS_END(); + return; + } + + pScrn = xf86ScreenToScrn(pDraw->pScreen); + + XDBG_RETURN_IF_FAIL(pEvent->pFrontBuf != NULL); + XDBG_RETURN_IF_FAIL(pEvent->pBackBuf != NULL); + + switch (pEvent->type) { + case DRI2_FLIP: + if (EXYNOSPTR(pScrn)->hwc_active) { + if (!_scheduleLayerFlip(pDraw, pEvent)) + XDBG_WARNING(MDRI2, "set_layer fails.\n"); + } + else { + if (!_scheduleFlip(pDraw, pEvent, FALSE)) + XDBG_WARNING(MDRI2, "pageflip fails.\n"); + } + TTRACE_GRAPHICS_END(); + return; + break; + case DRI2_SWAP: + DRI2SwapComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec, + DRI2_EXCHANGE_COMPLETE, pEvent->event_complete, + pEvent->event_data); + break; + case DRI2_BLIT: + case DRI2_FB_BLIT: + DRI2SwapComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec, + DRI2_BLIT_COMPLETE, pEvent->event_complete, + pEvent->event_data); + break; + case DRI2_NONE: + DRI2SwapComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec, + 0, pEvent->event_complete, pEvent->event_data); + break; + case DRI2_WAITMSC: + DRI2WaitMSCComplete(pEvent->pClient, pDraw, frame, tv_sec, tv_usec); + break; + default: + /* Unknown type */ + break; + } + + XDBG_DEBUG(MDRI2, + "FrameEvent(%d,0x%x) SwapType:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", + pDraw->type, (unsigned int) pDraw->id, pEvent->type, + pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, + pEvent->pFrontBuf->flags, pEvent->pBackBuf->attachment, + pEvent->pBackBuf->name, pEvent->pBackBuf->flags); + + _deleteFrame(pDraw, pEvent); + TTRACE_GRAPHICS_END(); +} + +Bool +exynosDri2Init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSExaPrivPtr pExaPriv = EXYNOSEXAPTR(pExynos); + DRI2InfoRec info; + int ret; + const char *driverNames[1]; + + info.driverName = "exynos-drm"; + info.deviceName = pExynos->drm_device_name; + info.version = 106; + info.fd = pExynos->drm_fd; + info.CreateBuffer = EXYNOSDri2CreateBuffer; + info.DestroyBuffer = EXYNOSDri2DestroyBuffer; + info.CopyRegion = EXYNOSDri2CopyRegion; + info.ScheduleSwap = NULL; + info.GetMSC = EXYNOSDri2GetMSC; + info.ScheduleWaitMSC = EXYNOSDri2ScheduleWaitMSC; + info.AuthMagic = EXYNOSDri2AuthMagic; + info.ReuseBufferNotify = EXYNOSDri2ReuseBufferNotify; + info.SwapLimitValidate = NULL; + /* added in version 7 */ + info.GetParam = NULL; + + /* added in version 8 */ + /* AuthMagic callback which passes extra context */ + /* If this is NULL the AuthMagic callback is used */ + /* If this is non-NULL the AuthMagic callback is ignored */ + info.AuthMagic2 = NULL; + + /* added in version 9 */ + info.CreateBuffer2 = NULL; + info.DestroyBuffer2 = NULL; + info.CopyRegion2 = NULL; + + /* add in for Tizen extension */ + info.ScheduleSwapWithRegion = EXYNOSDri2ScheduleSwapWithRegion; + + info.Wait = NULL; + info.numDrivers = 1; + info.driverNames = driverNames; + driverNames[0] = info.driverName; + + ret = DRI2ScreenInit(pScreen, &info); + if (ret == FALSE) { + return FALSE; + } + + /* set the number of the flip back buffers */ + pExaPriv->flip_backbufs = pExynos->flip_bufs - 1; + + //TODO: Own client_id for layer manager +#ifdef LAYER_MANAGER + if (lyr_client_id == 0) + lyr_client_id = exynosLayerMngRegisterClient(pScrn, "HWC", 1); +#endif + + //xDbgLogSetLevel (MDRI2, 0); + return ret; +} + +void +exynosDri2Deinit(ScreenPtr pScreen) +{ + DRI2CloseScreen(pScreen); +} diff --git a/src/accel/exynos_dri3.c b/src/accel/exynos_dri3.c new file mode 100755 index 0000000..bc748a4 --- /dev/null +++ b/src/accel/exynos_dri3.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2013 Keith Packard + * Copyright 2010 - 2014 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Roman Marchenko <r.marchenko@samsung.com> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <time.h> +#include <errno.h> + +#include <tbm_bufmgr.h> + +#include "xorg-server.h" +#include "xf86.h" + +#include "xf86drm.h" +#include "misyncshm.h" + +#include "dri3.h" + +#include "exynos.h" +#include "exynos_accel.h" + +// -------------------------- Private functions-------------------------------- +static void +_dri3SaveDrawable(ScrnInfoPtr pScrn, PixmapPtr pPix, int type) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + char file[128]; + char *str_type[3] = { "none", "FDFromPIX", "PIXFromFD" }; + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + + if (!pExynos->dump_info || !(pExynos->dump_mode & XBERC_DUMP_MODE_DRI3)) + return; + + XDBG_RETURN_IF_FAIL(pPix != NULL); + + snprintf(file, sizeof(file), "[DRI3]%s_%x_%p_%03d.%s", + str_type[type], + (unsigned int) pPix->drawable.id, + (void *) pPix, pExaPixPriv->dump_cnt, pExynos->dump_type); + + exynosUtilDoDumpPixmaps(pExynos->dump_info, pPix, file, pExynos->dump_type); + + XDBG_DEBUG(MSEC, "dump done\n"); + + pExaPixPriv->dump_cnt++; +} + +// -------------------------- Callback functions-------------------------------- +static int +EXYNOSDRI3Open(ScreenPtr screen, RRProviderPtr provider, int *fdp) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + drm_magic_t magic; + int fd; + + /* Open the device for the client */ + fd = open(pExynos->drm_device_name, O_RDWR | O_CLOEXEC); + if (fd == -1 && errno == EINVAL) { + fd = open(pExynos->drm_device_name, O_RDWR); + if (fd != -1) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + + if (fd < 0) + return BadAlloc; + + /* Go through the auth dance locally */ + if (drmGetMagic(fd, &magic) < 0) { + close(fd); + return BadMatch; + } + + if (drmAuthMagic(pExynos->drm_fd, magic) < 0) { + close(fd); + return BadMatch; + } + + /* And we're done */ + *fdp = fd; + return Success; +} + +static PixmapPtr +EXYNOSDRI3PixmapFromFd(ScreenPtr pScreen, + int fd, + CARD16 width, + CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + PixmapPtr pPixmap = NULL; + + TTRACE_GRAPHICS_BEGIN("XORG:DRI3:PIXMAP_FROM_FD"); + + XDBG_DEBUG(MDRI3, "fd:%d width:%d height:%d stride:%d depth:%d bpp:%d\n", + fd, width, height, stride, depth, bpp); + + XDBG_RETURN_VAL_IF_FAIL((width <= INT16_MAX && height <= INT16_MAX), NULL); + + XDBG_RETURN_VAL_IF_FAIL(((uint32_t) width * bpp <= (uint32_t) stride * 8), + NULL); + + XDBG_RETURN_VAL_IF_FAIL((depth > 8), NULL); + + XDBG_RETURN_VAL_IF_FAIL((bpp == 8 || bpp == 16 || bpp == 24 || + bpp == 32), NULL); + + tbm_bo tbo = tbm_bo_import_fd(pExynos->tbm_bufmgr, fd); + + XDBG_RETURN_VAL_IF_FAIL(tbo != NULL, NULL); + + uint32_t real_size = tbm_bo_size(tbo); + uint32_t target_size = (uint32_t) height * stride; + + if (real_size < target_size) { + XDBG_WARNING(MDRI3, + "the real size of bo(%p) less then target: %d, %d\n", tbo, + real_size, target_size); + goto free_bo; + } + + pPixmap = + (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, + CREATE_PIXMAP_USAGE_DRI3_BACK); + + XDBG_GOTO_IF_FAIL(pPixmap != NULL, free_bo); + + if (!pScreen->ModifyPixmapHeader(pPixmap, width, height, 0, 0, stride, 0)) + goto free_pix; + + exynosExaMigratePixmap(pPixmap, tbo); + tbm_bo_unref(tbo); + + /* dump pixmap */ + _dri3SaveDrawable(xf86ScreenToScrn(pScreen), pPixmap, 2); + + XDBG_DEBUG(MDRI3, + "pixmap(sn:%ld p:%p ID:0x%x %dx%d stride:%d depth:%d bpp:%d) bo(name:%d p:%p)\n", + pPixmap->drawable.serialNumber, pPixmap, pPixmap->drawable.id, + pPixmap->drawable.width, pPixmap->drawable.height, + pPixmap->devKind, pPixmap->drawable.depth, + pPixmap->drawable.bitsPerPixel, tbm_bo_export(tbo), tbo); + + TTRACE_GRAPHICS_END(); + return pPixmap; + + free_pix: + (*pScreen->DestroyPixmap) (pPixmap); + free_bo: + tbm_bo_unref(tbo); + + TTRACE_GRAPHICS_END(); + return NULL; +} + +static int +EXYNOSDRI3FdFromPixmap(ScreenPtr pScreen, + PixmapPtr pPixmap, CARD16 *stride, CARD32 *size) +{ + EXYNOSPixmapPriv *priv = NULL; + int fd; + + TTRACE_GRAPHICS_BEGIN("XORG:DRI3:FD_FROM_PIXMAP"); + + XDBG_DEBUG(MDRI3, "pixmap(sn:%ld p:%p ID:0x%x) (%dx%d)\n", + pPixmap->drawable.serialNumber, pPixmap, pPixmap->drawable.id, + pPixmap->drawable.width, pPixmap->drawable.height); + + priv = exaGetPixmapDriverPrivate(pPixmap); + XDBG_RETURN_VAL_IF_FAIL(priv, -1); + + fd = tbm_bo_export_fd(priv->bo); + XDBG_RETURN_VAL_IF_FAIL(fd > 0, -1); + + *stride = pPixmap->devKind; + *size = tbm_bo_size(priv->bo); + + /* dump pixmap */ + _dri3SaveDrawable(xf86ScreenToScrn(pScreen), pPixmap, 1); + + XDBG_DEBUG(MDRI3, "fd:%d stride:%d size:%d bo_name:%d\n", + fd, *stride, *size, tbm_bo_export(priv->bo)); + + TTRACE_GRAPHICS_END(); + return fd; +} + +static dri3_screen_info_rec exynos_dri3_screen_info = { + .version = DRI3_SCREEN_INFO_VERSION, + + .open = EXYNOSDRI3Open, + .pixmap_from_fd = EXYNOSDRI3PixmapFromFd, + .fd_from_pixmap = EXYNOSDRI3FdFromPixmap +}; + +// -------------------------- Public functions-------------------------------- +Bool +exynosDri3ScreenInit(ScreenPtr screen) +{ + if (!miSyncShmScreenInit(screen)) + return FALSE; + + return dri3_screen_init(screen, &exynos_dri3_screen_info); +} diff --git a/src/accel/exynos_exa.c b/src/accel/exynos_exa.c new file mode 100755 index 0000000..1b2d828 --- /dev/null +++ b/src/accel/exynos_exa.c @@ -0,0 +1,733 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <fcntl.h> +#include <sys/mman.h> +#include "exynos.h" +#include "exynos_accel.h" +#include "exynos_display.h" +#include "exynos_crtc.h" +#include <X11/Xatom.h> +#include "windowstr.h" +#include "fbpict.h" +#include "exynos_util.h" +#include "exynos_converter.h" + +static void +_setScreenRotationProperty(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + Atom atom_screen_rotaion; + WindowPtr pWin = pScreen->root; + int rc; + + atom_screen_rotaion = MakeAtom("X_SCREEN_ROTATION", 17, TRUE); + unsigned int rotation = (unsigned int) pExynos->rotate; + + rc = dixChangeWindowProperty(serverClient, + pWin, atom_screen_rotaion, XA_CARDINAL, 32, + PropModeReplace, 1, &rotation, FALSE); + if (rc != Success) + XDBG_ERROR(MEXAS, "failed : set X_SCREEN_ROTATION to %d\n", rotation); +} + +static void +_exynosExaBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[0]; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + /* add screen rotation property to the root window */ + _setScreenRotationProperty(pScrn); + + RemoveBlockAndWakeupHandlers(_exynosExaBlockHandler /*blockHandler */ , + (void *) NULL /*wakeupHandler */ , + (void *) NULL /*blockData */ ); +} + +static void +EXYNOSExaWaitMarker(ScreenPtr pScreen, int marker) +{ +} + +static Bool +EXYNOSExaPrepareAccess(PixmapPtr pPix, int index) +{ + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSPixmapPriv *privPixmap = exaGetPixmapDriverPrivate(pPix); + int opt = TBM_OPTION_READ; + tbm_bo_handle bo_handle; + + XDBG_RETURN_VAL_IF_FAIL((privPixmap != NULL), FALSE); + if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB && privPixmap->bo == NULL) { + privPixmap->bo = exynosRenderBoRef(pExynos->pFb->default_bo); + XDBG_RETURN_VAL_IF_FAIL((privPixmap->bo != NULL), FALSE); + privPixmap->set_bo_to_null = TRUE; + XDBG_TRACE(MEXAS, " FRAMEBUFFER\n"); + } + else { + XDBG_TRACE(MEXAS, "\n"); + } + + if (privPixmap->bo) { + if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) + opt |= TBM_OPTION_WRITE; + + bo_handle = tbm_bo_map(privPixmap->bo, TBM_DEVICE_CPU, opt); + pPix->devPrivate.ptr = bo_handle.ptr; + } + else { + if (privPixmap->pPixData) { + pPix->devPrivate.ptr = privPixmap->pPixData; + } + } + + XDBG_DEBUG(MEXA, "pix:%p index:%d hint:%d ptr:%p\n", + pPix, index, pPix->usage_hint, pPix->devPrivate.ptr); + return TRUE; +} + +static void +EXYNOSExaFinishAccess(PixmapPtr pPix, int index) +{ + XDBG_TRACE(MEXAS, "\n"); + if (!pPix) + return; + + EXYNOSPixmapPriv *privPixmap = + (EXYNOSPixmapPriv *) exaGetPixmapDriverPrivate(pPix); + + if (privPixmap == NULL) + return; + + if (privPixmap->bo) + tbm_bo_unmap(privPixmap->bo); + + if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB && + privPixmap->set_bo_to_null) { + exynosRenderBoUnref(privPixmap->bo); + privPixmap->bo = NULL; + privPixmap->set_bo_to_null = FALSE; + } +/* + if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) + exynosLayerUpdate (exynosLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER)); +*/ + XDBG_DEBUG(MEXA, "pix:%p index:%d hint:%d ptr:%p\n", + pPix, index, pPix->usage_hint, pPix->devPrivate.ptr); + pPix->devPrivate.ptr = NULL; + +} + +static void * +EXYNOSExaCreatePixmap(ScreenPtr pScreen, int size, int align) +{ + TTRACE_GRAPHICS_BEGIN("XORG:EXA:CREATE_PIXMAP"); + + EXYNOSPixmapPriv *privPixmap = calloc(1, sizeof(EXYNOSPixmapPriv)); + + TTRACE_GRAPHICS_END(); + + return privPixmap; +} + +static void +EXYNOSExaDestroyPixmap(ScreenPtr pScreen, void *driverPriv) +{ + TTRACE_GRAPHICS_BEGIN("XORG:EXA:DESTROY_PIXMAP"); + + XDBG_RETURN_IF_FAIL(driverPriv != NULL); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + EXYNOSPixmapPriv *privPixmap = (EXYNOSPixmapPriv *) driverPriv; + + XDBG_TRACE(MEXA, "DESTROY_PIXMAP : bo:%p name:%d usage_hint:0x%x\n", + privPixmap->bo, tbm_bo_export(privPixmap->bo), + privPixmap->usage_hint); + + switch (privPixmap->usage_hint) { + case CREATE_PIXMAP_USAGE_FB: + pExynos->pix_fb = pExynos->pix_fb - privPixmap->size; + exynosRenderBoUnref(privPixmap->bo); + privPixmap->bo = NULL; + break; + case CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK: + pExynos->pix_dri2_flip_back = + pExynos->pix_dri2_flip_back - privPixmap->size; + exynosRenderBoUnref(privPixmap->bo); + privPixmap->bo = NULL; + break; + case CREATE_PIXMAP_USAGE_SUB_FB: + /* TODO ???? */ + pExynos->pix_sub_fb = pExynos->pix_sub_fb - privPixmap->size; + privPixmap->bo = NULL; + break; +#if 0 + case CREATE_PIXMAP_USAGE_OVERLAY: + /* TODO ???? */ + pExynos->pix_overlay = pExynos->pix_overlay - privPixmap->size; + exynosRenderBoUnref(privPixmap->bo); + privPixmap->bo = NULL; + + if (privPixmap->ovl_layer) { + exynosLayerUnref(privPixmap->ovl_layer); + privPixmap->ovl_layer = NULL; + } + + pExynos->ovl_drawable = NULL; + + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + xf86CrtcPtr pCrtc = exynosCrtcGetAtGeometry(pScrn, 0, 0, + pExynosMode->main_lcd_mode. + hdisplay, + pExynosMode->main_lcd_mode. + vdisplay); + exynosCrtcOverlayRef(pCrtc, FALSE); + + break; +#endif + case CREATE_PIXMAP_USAGE_DRI2_BACK: + pExynos->pix_dri2_back = pExynos->pix_dri2_back - privPixmap->size; + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = NULL; + break; + case CREATE_PIXMAP_USAGE_DRI3_BACK: + pExynos->pix_dri3_back = pExynos->pix_dri3_back - privPixmap->size; + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = NULL; + break; + case CREATE_PIXMAP_USAGE_BACKING_PIXMAP: + case CREATE_PIXMAP_USAGE_OVERLAY: + pExynos->pix_backing_pixmap = + pExynos->pix_backing_pixmap - privPixmap->size; + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = NULL; + break; + default: + pExynos->pix_normal = pExynos->pix_normal - privPixmap->size; + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = NULL; + break; + } + + /* free pixmap private */ + free(privPixmap); + TTRACE_GRAPHICS_END(); +} + +static Bool +EXYNOSExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, + int depth, int bitsPerPixel, int devKind, + pointer pPixData) +{ + XDBG_RETURN_VAL_IF_FAIL(pPixmap, FALSE); + + TTRACE_GRAPHICS_BEGIN("XORG:EXA:MODIFY_PIXMAP_HEADER"); + + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSPixmapPriv *privPixmap = + (EXYNOSPixmapPriv *) exaGetPixmapDriverPrivate(pPixmap); + long lSizeInBytes; + + /* set the default headers of the pixmap */ + miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, + devKind, pPixData); + + /* screen pixmap : set a framebuffer pixmap */ + if (pPixData == (void *) ROOT_FB_ADDR) { + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + pExynos->pix_fb = pExynos->pix_fb + lSizeInBytes; + pPixmap->usage_hint = CREATE_PIXMAP_USAGE_FB; + privPixmap->usage_hint = pPixmap->usage_hint; + privPixmap->isFrameBuffer = TRUE; + privPixmap->bo = NULL; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, "CREATE_PIXMAP_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, + height); + + TTRACE_GRAPHICS_END(); + return TRUE; + } + + if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_SUB_FB) { + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + pExynos->pix_sub_fb = pExynos->pix_sub_fb + lSizeInBytes; + + pPixmap->devPrivate.ptr = NULL; + privPixmap->usage_hint = pPixmap->usage_hint; + privPixmap->isSubFramebuffer = TRUE; + privPixmap->bo = (tbm_bo) pPixData; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, "CREATE_PIXMAP_SUB_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, + height); + + TTRACE_GRAPHICS_END(); + return TRUE; + } +#if 0 + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) { + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSLayer *layer; + EXYNOSVideoBuf *vbuf; + int width, height; + + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + pExynos->pix_overlay = pExynos->pix_overlay + lSizeInBytes; + + privPixmap->usage_hint = pPixmap->usage_hint; + privPixmap->size = lSizeInBytes; + + pExynos->ovl_drawable = &pPixmap->drawable; + + /* change buffer if needed. */ + xf86CrtcPtr pCrtc = exynosCrtcGetAtGeometry(pScrn, 0, 0, + pExynosMode->main_lcd_mode. + hdisplay, + pExynosMode->main_lcd_mode. + vdisplay); + exynosCrtcOverlayRef(pCrtc, TRUE); + + layer = exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_UPPER); + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + + vbuf = exynosLayerGetBuffer(layer); + XDBG_RETURN_VAL_IF_FAIL(vbuf != NULL, FALSE); + + width = vbuf->width; + height = vbuf->height; + + if (width != pExynosMode->main_lcd_mode.hdisplay || + height != pExynosMode->main_lcd_mode.vdisplay) { + XDBG_ERROR(MEXA, + "layer size(%d,%d) should be (%dx%d). pixmap(%d,%d %dx%d)\n", + width, height, pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay, pPixmap->screen_x, + pPixmap->screen_y, pPixmap->drawable.width, + pPixmap->drawable.height); + return FALSE; + } + + privPixmap->bo = exynosRenderBoRef(vbuf->bo[0]); + + privPixmap->ovl_layer = exynosLayerRef(layer); + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_OVERLAY(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, + height); + + TTRACE_GRAPHICS_END(); + return TRUE; + } +#endif + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_XVIDEO) { + EXYNOSCvtProp prop = { 0, }; + tbm_bo old_bo = privPixmap->bo; + + prop.id = FOURCC_RGB32; + prop.width = width; + prop.height = height; + prop.crop.width = width; + prop.crop.height = height; + + if (!exynosCvtEnsureSize(NULL, &prop)) + return FALSE; + + privPixmap->bo = exynosRenderBoCreate(pScrn, prop.width, prop.height); + if (!privPixmap->bo) { + XDBG_ERROR(MEXA, "Error: cannot create a xvideo buffer\n"); + privPixmap->bo = old_bo; + + TTRACE_GRAPHICS_END(); + return FALSE; + } + + pPixmap->devKind = prop.width * 4; + + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + pExynos->pix_dri2_flip_back = + pExynos->pix_dri2_flip_back + lSizeInBytes; + + privPixmap->usage_hint = pPixmap->usage_hint; + privPixmap->isFrameBuffer = FALSE; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_USAGE_XVIDEO(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, privPixmap->bo, pPixmap->drawable.x, + pPixmap->drawable.y, width, height); + + if (old_bo) + tbm_bo_unref(old_bo); + + TTRACE_GRAPHICS_END(); + return TRUE; + } + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK) { + privPixmap->bo = + exynosRenderBoCreate(pScrn, pPixmap->devKind / 4, height); + if (!privPixmap->bo) { + XDBG_ERROR(MEXA, "Error: cannot create a back flip buffer\n"); + TTRACE_GRAPHICS_END(); + return FALSE; + } + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + pExynos->pix_dri2_flip_back = + pExynos->pix_dri2_flip_back + lSizeInBytes; + + privPixmap->usage_hint = pPixmap->usage_hint; + privPixmap->isFrameBuffer = TRUE; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_DRI2_FLIP_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, privPixmap->bo, pPixmap->drawable.x, + pPixmap->drawable.y, width, height); + + TTRACE_GRAPHICS_END(); + return TRUE; + } + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_BACK) { + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + privPixmap->usage_hint = pPixmap->usage_hint; + + if (pExynos->use_hwc && pExynos->hwc_active) + privPixmap->bo = + exynosRenderBoCreate(pScrn, pPixmap->devKind / 4, height); + else + privPixmap->bo = + tbm_bo_alloc(pExynos->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT); + if (privPixmap->bo == NULL) { + XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%ld\n", + lSizeInBytes); + TTRACE_GRAPHICS_END(); + return FALSE; + } + pExynos->pix_dri2_back = pExynos->pix_dri2_back + lSizeInBytes; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_USAGE_DRI2_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, privPixmap->bo, pPixmap->drawable.x, + pPixmap->drawable.y, width, height); + + TTRACE_GRAPHICS_END(); + return TRUE; + + } + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI3_BACK) { + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + privPixmap->usage_hint = pPixmap->usage_hint; + + /* [cyeon] pixmap tbm bo will be attached in EXYNOSDRI3PixmapFromFd + */ + privPixmap->bo = NULL; + + pExynos->pix_dri3_back = pExynos->pix_dri3_back + lSizeInBytes; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_USAGE_DRI3_BACK(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, + height); + + TTRACE_GRAPHICS_END(); + return TRUE; + } +#if 1 + else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP || + pPixmap->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) { + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + privPixmap->usage_hint = pPixmap->usage_hint; + + /* + * Each "backing pixmap" can be used as frame buffer through HWC extension. + * We may use a map/unmap construction in HWC extension before + * frame buffer will be used (look drmModeSetPlane()), but this way + * works better (without artifacts). + */ + if (pExynos->use_hwc && pExynos->hwc_active) + privPixmap->bo = + exynosRenderBoCreate(pScrn, pPixmap->devKind / 4, height); + else + privPixmap->bo = + tbm_bo_alloc(pExynos->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT); + if (privPixmap->bo == NULL) { + XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%ld\n", + lSizeInBytes); + TTRACE_GRAPHICS_END(); + return FALSE; + } + pExynos->pix_backing_pixmap = + pExynos->pix_backing_pixmap + lSizeInBytes; + privPixmap->size = lSizeInBytes; + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_USAGE_BACKING_PIXMAP(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", + pPixmap, privPixmap->bo, pPixmap->drawable.x, + pPixmap->drawable.y, width, height); + + TTRACE_GRAPHICS_END(); + return TRUE; + + } +#endif + if (privPixmap->bo != NULL) { + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = NULL; + } + + lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; + privPixmap->usage_hint = pPixmap->usage_hint; + + /* pPixData is also set for text glyphs or SHM-PutImage */ + if (pPixData) { + privPixmap->pPixData = pPixData; + /* + privPixmap->bo = tbm_bo_attach(pExynos->tbm_bufmgr, + NULL, + TBM_MEM_USERPTR, + lSizeInBytes, (unsigned int)pPixData); + */ + } + else { + /* create the pixmap private memory */ + if (lSizeInBytes && privPixmap->bo == NULL) { + if (pExynos->hwc_active) + privPixmap->bo = + exynosRenderBoCreate(pScrn, pPixmap->devKind / 4, height); + else + privPixmap->bo = + tbm_bo_alloc(pExynos->tbm_bufmgr, lSizeInBytes, + TBM_BO_DEFAULT); + if (privPixmap->bo == NULL) { + XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%ld\n", + lSizeInBytes); + TTRACE_GRAPHICS_END(); + return FALSE; + } + } + pExynos->pix_normal = pExynos->pix_normal + lSizeInBytes; + } + + XDBG_TRACE(MEXA, + "CREATE_PIXMAP_NORMAL(%p) : bo:%p, pPixData:%p (%dx%d+%d+%d)\n", + pPixmap, privPixmap->bo, pPixData, width, height, + pPixmap->drawable.x, pPixmap->drawable.y); + + TTRACE_GRAPHICS_END(); + return TRUE; +} + +static Bool +EXYNOSExaPixmapIsOffscreen(PixmapPtr pPix) +{ + return TRUE; +} + +Bool +exynosExaInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ExaDriverPtr pExaDriver; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSExaPrivPtr pExaPriv; + unsigned int cpp = 4; + + /* allocate the pExaPriv private */ + pExaPriv = calloc(1, sizeof(*pExaPriv)); + if (pExaPriv == NULL) + return FALSE; + + /* allocate the EXA driver private */ + pExaDriver = exaDriverAlloc(); + if (pExaDriver == NULL) { + free(pExaPriv); + return FALSE; + } + + /* version of exa */ + pExaDriver->exa_major = EXA_VERSION_MAJOR; + pExaDriver->exa_minor = EXA_VERSION_MINOR; + + /* setting the memory stuffs */ + pExaDriver->memoryBase = (void *) ROOT_FB_ADDR; + pExaDriver->memorySize = pScrn->videoRam * 1024; + pExaDriver->offScreenBase = pScrn->displayWidth * cpp * pScrn->virtualY; + + pExaDriver->maxX = 1 << 16; + pExaDriver->maxY = 1 << 16; + pExaDriver->pixmapOffsetAlign = 0; + pExaDriver->pixmapPitchAlign = 64; + pExaDriver->flags = (EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS + | EXA_SUPPORTS_OFFSCREEN_OVERLAPS + | EXA_SUPPORTS_PREPARE_AUX); + + pExaDriver->WaitMarker = EXYNOSExaWaitMarker; + pExaDriver->PrepareAccess = EXYNOSExaPrepareAccess; + pExaDriver->FinishAccess = EXYNOSExaFinishAccess; + + pExaDriver->CreatePixmap = EXYNOSExaCreatePixmap; + pExaDriver->DestroyPixmap = EXYNOSExaDestroyPixmap; + pExaDriver->ModifyPixmapHeader = EXYNOSExaModifyPixmapHeader; + pExaDriver->PixmapIsOffscreen = EXYNOSExaPixmapIsOffscreen; + + /* call init function */ + if (pExynos->is_sw_exa) { + if (exynosExaSwInit(pScreen, pExaDriver)) { + XDBG_INFO(MEXA, "Initialized EXYNOS SW_EXA acceleration OK !\n"); + } + else { + free(pExaPriv); + free(pExaDriver); + FatalError("Failed to initialize SW_EXA\n"); + return FALSE; + } + } + + /* exa driver init with exa driver private */ + if (exaDriverInit(pScreen, pExaDriver)) { + pExaPriv->pExaDriver = pExaDriver; + pExynos->pExaPriv = pExaPriv; + } + else { + free(pExaDriver); + free(pExaPriv); + FatalError("Failed to initialize EXA...exaDriverInit\n"); + return FALSE; + } + + /* block handler */ + RegisterBlockAndWakeupHandlers(_exynosExaBlockHandler /*blockHandler */ , + NULL /*wakeupHandler */ , + NULL /*blockData */ ); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA driver is Loaded successfully\n"); + + return TRUE; +} + +void +exynosExaDeinit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + /* call Fini function */ + if (pExynos->is_sw_exa) { + exynosExaSwDeinit(pScreen); + XDBG_INFO(MEXA, "Finish SW EXA acceleration.\n"); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA driver is UnLoaded successfully\n"); +} + +Bool +exynosExaPrepareAccess(PixmapPtr pPix, int index) +{ + return EXYNOSExaPrepareAccess(pPix, index); +} + +void +exynosExaFinishAccess(PixmapPtr pPix, int index) +{ + EXYNOSExaFinishAccess(pPix, index); +} + +int +exynosExaScreenAsyncSwap(ScreenPtr pScreen, int enable) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (enable == -1) + return pExynos->useAsyncSwap; + + if (enable == 1) + pExynos->useAsyncSwap = TRUE; + else + pExynos->useAsyncSwap = FALSE; + + return pExynos->useAsyncSwap; +} + +int +exynosExaScreenSetScrnPixmap(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + PixmapPtr pPix = (*pScreen->GetScreenPixmap) (pScreen); + unsigned int pitch = pScrn->virtualX * 4; + + (*pScreen->ModifyPixmapHeader) (pPix, pScrn->virtualX, pScrn->virtualY, + -1, -1, pitch, (void *) ROOT_FB_ADDR); + pScrn->displayWidth = pitch / 4; + return 1; +} + +Bool +exynosExaMigratePixmap(PixmapPtr pPix, tbm_bo bo) +{ + EXYNOSPixmapPriv *privPixmap = exaGetPixmapDriverPrivate(pPix); + + if (privPixmap->bo) + tbm_bo_unref(privPixmap->bo); + privPixmap->bo = tbm_bo_ref(bo); + + return TRUE; +} + +tbm_bo +exynosExaPixmapGetBo(PixmapPtr pPix) +{ + tbm_bo bo = NULL; + EXYNOSPixmapPriv *pExaPixPriv = NULL; + + if (pPix == NULL) + return 0; + + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + if (pExaPixPriv == NULL) + return 0; + + bo = pExaPixPriv->bo; + + return bo; +} diff --git a/src/accel/exynos_exa_sw.c b/src/accel/exynos_exa_sw.c new file mode 100755 index 0000000..23fe1fa --- /dev/null +++ b/src/accel/exynos_exa_sw.c @@ -0,0 +1,1217 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 "exynos.h" +#include "exynos_accel.h" +#include "exynos_util.h" +#include "exynos_layer.h" +#include "exa.h" +#include "fbpict.h" +#include "neonmem.h" + +typedef struct { + BoxRec pos; + PixmapPtr pixmap; + tbm_bo bo; + void *addr; +} ExaOpBuf; + +typedef struct { + int refcnt; + int opt; + int num; + int isSame; + + ExaOpBuf buf[5]; +} ExaOpInfo; + +typedef struct { + BoxRec box; + int state; /*state of region */ + + struct xorg_list link; + + ExaOpBuf *pSrc; + ExaOpBuf *pMask; + ExaOpBuf *pDst; +} ExaBox; + +typedef struct { + Bool bDo; + + int alu; + Pixel planemask; + Pixel fg; + PixmapPtr pixmap; + + int x, y, w, h; + GCPtr pGC; + ExaOpInfo *pOpDst; + struct xorg_list opBox; +} OpSolid; + +typedef struct { + Bool bDo; + Pixel pm; + int alu; + int reverse; + int upsidedown; + PixmapPtr pSrcPix; + PixmapPtr pDstPix; + + /*copy param */ + int srcX; + int srcY; + int dstX; + int dstY; + int width, height; + + ExaOpInfo *pOpDst; + ExaOpInfo *pOpSrc; + struct xorg_list opBox; +} OpCopy; + +typedef struct { + Bool bDo; + int op; + + PicturePtr pSrcPicture; + PicturePtr pMaskPicture; + PicturePtr pDstPicture; + PixmapPtr pSrcPixmap; + PixmapPtr pMaskPixmap; + PixmapPtr pDstPixmap; + + /*copy param */ + int srcX, srcY; + int maskX, maskY; + int dstX, dstY; + int width, height; + + ExaOpInfo *pOpSrc; + ExaOpInfo *pOpMask; + ExaOpInfo *pOpDst; + struct xorg_list opBox; +} OpComposite; + +typedef struct { + Bool bDo; + + PixmapPtr pDst; + int x, y, w, h; + char *src; + int src_pitch; + + ExaOpInfo *pOpDst; + struct xorg_list opBox; +} OpUTS; + +typedef struct { + Bool bDo; + + PixmapPtr pSrc; + int x, y, w, h; + char *dst; + int dst_pitch; + + ExaOpInfo *pOpSrc; + struct xorg_list opBox; +} OpDFS; + +typedef void (*DoDrawProcPtr) (PixmapPtr pPix, Bool isPart, + int x, int y, + int clip_x, int clip_y, + int w, int h, void *data); + +typedef void (*DoDrawProcPtrEx) (ExaBox * box, void *data); + +static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES]; +static OpSolid gOpSolid; +static OpCopy gOpCopy; +static OpComposite gOpComposite; +static OpUTS gOpUTS; +static OpDFS gOpDFS; + +ExaBox * +_swBoxAdd(struct xorg_list *l, BoxPtr b1, BoxPtr b2) +{ + ExaBox *rgn = NULL; + + rgn = calloc(1, sizeof(ExaBox)); + XDBG_RETURN_VAL_IF_FAIL((rgn != NULL), NULL); + + rgn->state = exynosUtilBoxIntersect(&rgn->box, b1, b2); + if (rgnOUT == rgn->state) { + free(rgn); + return NULL; + } + + xorg_list_add(&rgn->link, l); + return rgn; +} + +void +_swBoxMerge(struct xorg_list *l, struct xorg_list *b, struct xorg_list *t) +{ + ExaBox *b1 = NULL, *b2 = NULL; + ExaBox *r = NULL; + + xorg_list_for_each_entry(b1, b, link) { + xorg_list_for_each_entry(b2, t, link) { + r = _swBoxAdd(l, &b1->box, &b2->box); + if (r) { + r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc; + r->pMask = b1->pMask ? b1->pMask : b2->pMask; + r->pDst = b1->pDst ? b1->pDst : b2->pDst; + } + } + } +} + +void +_swBoxMove(struct xorg_list *l, int tx, int ty) +{ + ExaBox *b = NULL; + + xorg_list_for_each_entry(b, l, link) { + exynosUtilBoxMove(&b->box, tx, ty); + } +} + +void +_swBoxRemoveAll(struct xorg_list *l) +{ + ExaBox *ref = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(ref, next, l, link) { + xorg_list_del(&ref->link); + free(ref); + } +} + +int +_swBoxIsOne(struct xorg_list *l) +{ + if (l->next != l) { + if (l->next == l->prev) + return 1; + else + return -1; + } + + return 0; +} + +void +_swBoxPrint(ExaBox * sb1, const char *name) +{ + ExaBox *b = NULL; + + xorg_list_for_each_entry(b, &sb1->link, link) { + XDBG_DEBUG(MEXA, "[%s] %d,%d - %d,%d\n", name, + b->box.x1, b->box.y1, b->box.x2, b->box.y2); + } +} + +static ExaOpInfo * +_swPrepareAccess(PixmapPtr pPix, int index) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSPixmapPriv *privPixmap = + (EXYNOSPixmapPriv *) exaGetPixmapDriverPrivate(pPix); + ExaOpInfo *op = &OpInfo[index]; + int opt = TBM_OPTION_READ; + tbm_bo *bos; + tbm_bo_handle bo_handle; + int num_bo = 0; + int ret; + + XDBG_RETURN_VAL_IF_FAIL((privPixmap != NULL), NULL); + + if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) + opt |= TBM_OPTION_WRITE; + + /* Check mapped */ + if (privPixmap->exaOpInfo) { + op = (ExaOpInfo *) privPixmap->exaOpInfo; + op->refcnt++; + XDBG_TRACE(MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", + pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, + op->refcnt); + return op; + } + + /*Set buffer info */ + memset(op, 0x00, sizeof(ExaOpInfo)); + op->refcnt = 1; + op->opt = opt; + op->isSame = 0; + + if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB) { + ret = exynosFbFindBo(pExynos->pFb, + pPix->drawable.x, pPix->drawable.y, + pPix->drawable.width, pPix->drawable.height, + &num_bo, &bos); + XDBG_TRACE(MEXAS, "FB ret:%d num_pix:%d, %dx%d+%d+%d\n", + ret, num_bo, + pPix->drawable.width, pPix->drawable.height, + pPix->drawable.x, pPix->drawable.y); + + if (ret == rgnSAME && num_bo == 1) { + op->num = 1; + op->isSame = 1; + + op->buf[0].pixmap = pPix; + op->buf[0].bo = tbm_bo_ref(bos[0]); + bo_handle = tbm_bo_map(op->buf[0].bo, TBM_DEVICE_CPU, op->opt); + op->buf[0].addr = bo_handle.ptr; + op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr; + op->buf[0].pos.x1 = 0; + op->buf[0].pos.y1 = 0; + op->buf[0].pos.x2 = pPix->drawable.width; + op->buf[0].pos.y2 = pPix->drawable.height; + } + else { + +#ifdef NO_CRTC_MODE + if (num_bo == 0) { + num_bo = 1; + + if (bos) + free(bos); + + bos = (tbm_bo *) calloc(1, sizeof(tbm_bo)); + XDBG_RETURN_VAL_IF_FAIL((bos != NULL), NULL); + + bos[0] = pExynos->pFb->default_bo; + } +#endif //NO_CRTC_MODE +#if 1 + int i; + EXYNOSFbBoDataPtr bo_data; + + op->num = num_bo; + op->isSame = 0; + + for (i = 0; i < num_bo; i++) { + tbm_bo_get_user_data(bos[i], TBM_BO_DATA_FB, + (void **) &bo_data); + op->buf[i].pixmap = + exynosRenderBoGetPixmap(pExynos->pFb, bos[i]); + op->buf[i].bo = tbm_bo_ref(bos[i]); + bo_handle = tbm_bo_map(bos[i], TBM_DEVICE_CPU, op->opt); + op->buf[i].addr = bo_handle.ptr; + op->buf[i].pixmap->devPrivate.ptr = op->buf[i].addr; + op->buf[i].pos = bo_data->pos; + } +#endif + } + + if (bos) { + free(bos); + bos = NULL; + } + } + else { + op->num = 1; + op->isSame = 1; + + op->buf[0].pixmap = pPix; + if (privPixmap->bo) { + op->buf[0].bo = privPixmap->bo; + bo_handle = tbm_bo_map(op->buf[0].bo, TBM_DEVICE_CPU, op->opt); + op->buf[0].addr = bo_handle.ptr; + } + else { + op->buf[0].bo = privPixmap->bo; + op->buf[0].addr = privPixmap->pPixData; + } + op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr; + op->buf[0].pos.x1 = 0; + op->buf[0].pos.y1 = 0; + op->buf[0].pos.x2 = pPix->drawable.width; + op->buf[0].pos.y2 = pPix->drawable.height; + } + + privPixmap->exaOpInfo = op; + + XDBG_TRACE(MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", + pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); + return op; +} + +static void +_swFinishAccess(PixmapPtr pPix, int index) +{ + XDBG_RETURN_IF_FAIL(pPix != NULL); + + EXYNOSPixmapPriv *privPixmap = + (EXYNOSPixmapPriv *) exaGetPixmapDriverPrivate(pPix); + ExaOpInfo *op; + int i; + + XDBG_RETURN_IF_FAIL(privPixmap != NULL); + XDBG_RETURN_IF_FAIL(privPixmap->exaOpInfo != NULL); + + op = (ExaOpInfo *) privPixmap->exaOpInfo; + op->refcnt--; + + if (op->refcnt == 0) { + for (i = 0; i < op->num; i++) { + if (op->buf[i].bo) { + tbm_bo_unmap(op->buf[i].bo); + + if (index == EXA_PREPARE_DEST && + pPix->usage_hint == CREATE_PIXMAP_USAGE_FB) { + // In this case, DEST is framebuffer. It is updated by CPU. + // After that LCD will use this buffer. + // So we should call cache op!! + tbm_bo_map(op->buf[i].bo, TBM_DEVICE_3D, TBM_OPTION_READ); + tbm_bo_unmap(op->buf[i].bo); + + ScreenPtr pScreen; + + pScreen = pPix->drawable.pScreen; + + if (pScreen != NULL) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + pExynos->is_fb_touched = TRUE; + } + tbm_bo_unref(op->buf[i].bo); + } + op->buf[i].bo = NULL; + } + + if (op->buf[i].pixmap) { + op->buf[i].pixmap->devPrivate.ptr = NULL; + op->buf[i].pixmap = NULL; + } + op->buf[i].addr = NULL; + } + + privPixmap->exaOpInfo = NULL; + } + + if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) + exynosLayerUpdate(exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_UPPER)); + + XDBG_TRACE(MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", + pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); +} + +void +_swDoDraw(struct xorg_list *l, DoDrawProcPtrEx do_draw, void *data) +{ + ExaBox *box = NULL; + + xorg_list_for_each_entry(box, l, link) { + do_draw(box, data); + } +} + +static void +_swDoSolid(ExaBox * box, void *data) +{ + XDBG_TRACE(MEXAS, "(%d,%d), (%d,%d) off(%d,%d)\n", + box->box.x1, + box->box.y1, box->box.x2, box->box.y2, gOpSolid.x, gOpSolid.y); + + fbFill(&box->pDst->pixmap->drawable, + gOpSolid.pGC, + box->box.x1 + gOpSolid.x - box->pDst->pos.x1, + box->box.y1 + gOpSolid.y - box->pDst->pos.y1, + box->box.x2 - box->box.x1, box->box.y2 - box->box.y1); +} + +static void +_swDoCopy(ExaBox * box, void *data) +{ + CARD8 alu = gOpCopy.alu; + FbBits pm = gOpCopy.pm; + FbBits *src; + FbStride srcStride; + int srcBpp; + FbBits *dst; + FbStride dstStride; + int dstBpp; + _X_UNUSED int srcXoff, srcYoff; + _X_UNUSED int dstXoff, dstYoff; + int srcX, srcY, dstX, dstY, width, height; + + XDBG_TRACE(MEXAS, "box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n", + box->box.x1, + box->box.y1, + box->box.x2, + box->box.y2, + gOpCopy.srcX, gOpCopy.srcY, gOpCopy.dstX, gOpCopy.dstY); + + if (gOpCopy.srcX < 0 || gOpCopy.srcY < 0 || gOpCopy.dstX < 0 || + gOpCopy.dstY < 0) { + XDBG_WARNING(MEXAS, "Sikp copy srcX:%d srcY:%d dstX:%d dstY:%d\n", + gOpCopy.srcX, gOpCopy.srcY, gOpCopy.dstX, gOpCopy.dstY); + return; + } + + srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1; + srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1; + dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1; + dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1; + width = box->box.x2 - box->box.x1; + height = box->box.y2 - box->box.y1; + + fbGetDrawable(&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, + srcYoff); + fbGetDrawable(&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, + dstYoff); + /* temp fix : do right things later */ + if (!src || !dst) { + return; + } + + if (pm != FB_ALLONES || + alu != GXcopy || + gOpCopy.reverse || + gOpCopy.upsidedown || + !pixman_blt((uint32_t *) src, (uint32_t *) dst, + srcStride, + dstStride, + srcBpp, dstBpp, srcX, srcY, dstX, dstY, width, height)) { + fbBlt(src + srcY * srcStride, + srcStride, + srcX * srcBpp, + dst + dstY * dstStride, + dstStride, + dstX * dstBpp, + width * dstBpp, + height, alu, pm, dstBpp, gOpCopy.reverse, gOpCopy.upsidedown); + } +} + +static void +_swDoComposite(ExaBox * box, void *data) +{ + PicturePtr pDstPicture; + pixman_image_t *src, *mask, *dest; + int src_xoff, src_yoff, msk_xoff, msk_yoff; + FbBits *bits; + FbStride stride; + int bpp; + + if (box->state == rgnPART) { + XDBG_RETURN_IF_FAIL(gOpComposite.pSrcPicture->transform == NULL); + XDBG_RETURN_IF_FAIL(gOpComposite.pMaskPicture && + gOpComposite.pMaskPicture->transform == NULL); + } + + pDstPicture = gOpComposite.pDstPicture; + + src = + image_from_pict(gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff); + mask = + image_from_pict(gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff); + + fbGetPixmapBitsData(box->pDst->pixmap, bits, stride, bpp); + dest = pixman_image_create_bits(pDstPicture->format, + box->pDst->pixmap->drawable.width, + box->pDst->pixmap->drawable.height, + (uint32_t *) bits, + stride * sizeof(FbStride)); + XDBG_RETURN_IF_FAIL(dest != NULL); + + pixman_image_composite(gOpComposite.op, + src, mask, dest, + gOpComposite.srcX + box->box.x1, + gOpComposite.srcY + box->box.y1, + gOpComposite.maskX + box->box.x1, + gOpComposite.maskY + box->box.y1, + gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1, + gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1, + box->box.x2 - box->box.x1, + box->box.y2 - box->box.y1); + + free_pixman_pict(gOpComposite.pSrcPicture, src); + free_pixman_pict(gOpComposite.pMaskPicture, mask); + pixman_image_unref(dest); +} + +static void +_swDoUploadToScreen(ExaBox * box, void *data) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + _X_UNUSED int dstXoff, dstYoff; + int srcStride; + int dstX, dstY; + int width, height; + + fbGetDrawable(&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, + dstYoff); + + srcStride = gOpUTS.src_pitch / sizeof(uint32_t); + dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1; + dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1; + width = box->box.x2 - box->box.x1; + height = box->box.y2 - box->box.y1; + + XDBG_TRACE(MEXAS, "src(%p, %d) %d,%d,%d,%d\n", + gOpUTS.src, srcStride, dstX, dstY, width, height); + + if (dstBpp < 8) { + XDBG_WARNING(MEXAS, "dstBpp:%d\n", dstBpp); + return; + } + + if (!pixman_blt((uint32_t *) gOpUTS.src, + (uint32_t *) dst, + srcStride, + dstStride, + dstBpp, dstBpp, + box->box.x1, box->box.y1, dstX, dstY, width, height)) { + unsigned char *pDst, *pSrc; + int dst_pitch, src_pitch, cpp; + + pDst = (unsigned char *) dst; + pSrc = (unsigned char *) gOpUTS.src; + cpp = dstBpp / 8; + src_pitch = gOpUTS.src_pitch; + dst_pitch = box->pDst->pixmap->devKind; + + pSrc += box->box.y1 * src_pitch + box->box.x1 * cpp; + pDst += dstY * dst_pitch + dstX * cpp; + + for (; height > 0; height--) { + memcpy(pDst, pSrc, width * cpp); + pDst += dst_pitch; + pSrc += src_pitch; + } + } +} + +static void +_swDoDownladFromScreen(ExaBox * box, void *data) +{ + FbBits *src; + FbStride srcStride; + int srcBpp; + _X_UNUSED int srcXoff, srcYoff; + int dstStride; + int srcX, srcY; + int width, height; + + fbGetDrawable(&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, + srcYoff); + + dstStride = gOpDFS.dst_pitch / sizeof(uint32_t); + srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1; + srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1; + width = box->box.x2 - box->box.x1; + height = box->box.y2 - box->box.y1; + + XDBG_TRACE(MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", + gOpDFS.dst, dstStride, srcX, srcY, width, height); + + if (srcBpp < 8) { + XDBG_WARNING(MEXAS, "srcBpp:%d\n", srcBpp); + return; + } + + if (!pixman_blt((uint32_t *) src, + (uint32_t *) gOpDFS.dst, + srcStride, + dstStride, + srcBpp, srcBpp, + srcX, srcY, box->box.x1, box->box.y1, width, height)) { + unsigned char *pDst, *pSrc; + int dst_pitch, src_pitch, cpp; + + pDst = (unsigned char *) gOpDFS.dst; + pSrc = (unsigned char *) src; + cpp = srcBpp / 8; + src_pitch = box->pSrc->pixmap->devKind; + dst_pitch = gOpDFS.dst_pitch; + + pSrc += srcY * src_pitch + srcX * cpp; + pDst += box->box.y1 * dst_pitch + box->box.x1 * cpp; + + for (; height > 0; height--) { + memcpy(pDst, pSrc, width * cpp); + pDst += dst_pitch; + pSrc += src_pitch; + } + } +} + +static Bool +EXYNOSExaSwPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ChangeGCVal tmpval[3]; + + XDBG_TRACE(MEXAS, "\n"); + memset(&gOpSolid, 0x00, sizeof(gOpSolid)); + + /* Put ff at the alpha bits when transparency is set to xv */ + if (pPixmap->drawable.depth == 24) + fg = fg | (~(pScrn->mask.red | pScrn->mask.green | pScrn->mask.blue)); + gOpSolid.alu = alu; + gOpSolid.fg = fg; + gOpSolid.planemask = planemask; + gOpSolid.pixmap = pPixmap; + + gOpSolid.pOpDst = _swPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(gOpSolid.pOpDst, bail); + gOpSolid.pGC = GetScratchGC(pPixmap->drawable.depth, pScreen); + + tmpval[0].val = alu; + tmpval[1].val = planemask; + tmpval[2].val = fg; + ChangeGC(NullClient, gOpSolid.pGC, GCFunction | GCPlaneMask | GCForeground, + tmpval); + ValidateGC(&pPixmap->drawable, gOpSolid.pGC); + + gOpSolid.bDo = TRUE; + + return TRUE; + + bail: + XDBG_TRACE(MEXAS, "FAIL: pix:%p hint:%d, num_pix:%d\n", + pPixmap, pPixmap->usage_hint, gOpSolid.pOpDst->num); + gOpSolid.bDo = FALSE; + gOpSolid.pGC = NULL; + + return TRUE; +} + +static void +EXYNOSExaSwSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + XDBG_TRACE(MEXAS, " (%d,%d), (%d,%d)\n", x1, y1, x2, y2); + if (gOpSolid.bDo == FALSE) + return; + + gOpSolid.x = x1; + gOpSolid.y = y1; + gOpSolid.w = x2 - x1; + gOpSolid.h = y2 - y1; + + if (gOpSolid.pOpDst->isSame) { + ExaBox box; + + box.state = rgnIN; + box.box.x1 = 0; + box.box.y1 = 0; + box.box.x2 = x2 - x1; + box.box.y2 = y2 - y1; + box.pDst = &gOpSolid.pOpDst->buf[0]; + _swDoSolid(&box, NULL); + } + else { + int i; + ExaBox *box; + BoxRec b; + + /*Init box list */ + xorg_list_init(&gOpSolid.opBox); + + b.x1 = x1; + b.y1 = y1; + b.x2 = x2; + b.y2 = y2; + + for (i = 0; i < gOpSolid.pOpDst->num; i++) { + box = _swBoxAdd(&gOpSolid.opBox, &gOpSolid.pOpDst->buf[i].pos, &b); + if (box) { + box->pDst = &gOpSolid.pOpDst->buf[i]; + } + } + _swBoxMove(&gOpSolid.opBox, -x1, -y1); + + /* Call solid function */ + _swDoDraw(&gOpSolid.opBox, _swDoSolid, NULL); + + /*Remove box list */ + _swBoxRemoveAll(&gOpSolid.opBox); + } +} + +static void +EXYNOSExaSwDoneSolid(PixmapPtr pPixmap) +{ + XDBG_TRACE(MEXAS, "\n"); + if (gOpSolid.pGC) { + FreeScratchGC(gOpSolid.pGC); + gOpSolid.pGC = NULL; + } + + if (gOpSolid.pixmap) + _swFinishAccess(gOpSolid.pixmap, EXA_PREPARE_DEST); +} + +static Bool +EXYNOSExaSwPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, + int dx, int dy, int alu, Pixel planemask) +{ + int num_dst_pix = -1; + int num_src_pix = -1; + + XDBG_TRACE(MEXAS, "\n"); + memset(&gOpCopy, 0x00, sizeof(gOpCopy)); + + gOpCopy.alu = alu; + gOpCopy.pm = planemask; + gOpCopy.reverse = (dx == 1) ? 0 : 1; + gOpCopy.upsidedown = (dy == 1) ? 0 : 1; + gOpCopy.pDstPix = pDstPixmap; + gOpCopy.pSrcPix = pSrcPixmap; + + gOpCopy.pOpDst = _swPrepareAccess(pDstPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(gOpCopy.pOpDst, bail); + gOpCopy.pOpSrc = _swPrepareAccess(pSrcPixmap, EXA_PREPARE_SRC); + XDBG_GOTO_IF_FAIL(gOpCopy.pOpDst, bail); + + gOpCopy.bDo = TRUE; + + return TRUE; + + bail: + XDBG_TRACE(MEXAS, "FAIL\n"); + XDBG_TRACE(MEXAS, " SRC pix:%p, hint:%d, num_pix:%d\n", + pSrcPixmap, pSrcPixmap->usage_hint, num_src_pix); + XDBG_TRACE(MEXAS, " DST pix:%p, hint:%d, num_pix:%d\n", + pDstPixmap, pDstPixmap->usage_hint, num_dst_pix); + gOpCopy.bDo = FALSE; + + return TRUE; +} + +static void +EXYNOSExaSwCopy(PixmapPtr pDstPixmap, int srcX, int srcY, + int dstX, int dstY, int width, int height) +{ + XDBG_TRACE(MEXAS, "src(%d,%d) dst(%d,%d) %dx%d\n", + srcX, srcY, dstX, dstY, width, height); + + if (gOpSolid.bDo == FALSE) + return; + + gOpCopy.srcX = srcX; + gOpCopy.srcY = srcY; + gOpCopy.dstX = dstX; + gOpCopy.dstY = dstY; + gOpCopy.width = width; + gOpCopy.height = height; + + if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame) { + ExaBox box; + + box.state = rgnIN; + box.box.x1 = 0; + box.box.y1 = 0; + box.box.x2 = width; + box.box.y2 = height; + box.pDst = &gOpCopy.pOpDst->buf[0]; + box.pSrc = &gOpCopy.pOpSrc->buf[0]; + _swDoCopy(&box, NULL); + } + else { + int i; + struct xorg_list lSrc, lDst; + ExaBox *box; + BoxRec b; + + //Set Dest + b.x1 = dstX; + b.y1 = dstY; + b.x2 = dstX + width; + b.y2 = dstY + height; + xorg_list_init(&lDst); + for (i = 0; i < gOpCopy.pOpDst->num; i++) { + box = _swBoxAdd(&lDst, &gOpCopy.pOpDst->buf[i].pos, &b); + if (box) { + box->pDst = &gOpCopy.pOpDst->buf[i]; + } + } + _swBoxMove(&lDst, -dstX, -dstY); + + //Set Src + b.x1 = srcX; + b.y1 = srcY; + b.x2 = srcX + width; + b.y2 = srcY + height; + + xorg_list_init(&lSrc); + for (i = 0; i < gOpCopy.pOpSrc->num; i++) { + box = _swBoxAdd(&lSrc, &gOpCopy.pOpSrc->buf[i].pos, &b); + if (box) { + box->pSrc = &gOpCopy.pOpSrc->buf[i]; + } + } + _swBoxMove(&lSrc, -srcX, -srcY); + + //Merge and call copy + xorg_list_init(&gOpCopy.opBox); + _swBoxMerge(&gOpCopy.opBox, &lSrc, &lDst); + _swDoDraw(&gOpCopy.opBox, _swDoCopy, NULL); + + //Remove box list + _swBoxRemoveAll(&lSrc); + _swBoxRemoveAll(&lDst); + _swBoxRemoveAll(&gOpCopy.opBox); + } +} + +static void +EXYNOSExaSwDoneCopy(PixmapPtr pDstPixmap) +{ + XDBG_TRACE(MEXAS, "\n"); + + if (gOpCopy.pDstPix) + _swFinishAccess(gOpCopy.pDstPix, EXA_PREPARE_DEST); + if (gOpCopy.pSrcPix) + _swFinishAccess(gOpCopy.pSrcPix, EXA_PREPARE_SRC); +} + +static Bool +EXYNOSExaSwCheckComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture) +{ + return TRUE; +} + +static Bool +EXYNOSExaSwPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrcPixmap, + PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap) +{ + XDBG_TRACE(MEXAS, "\n"); + memset(&gOpComposite, 0x00, sizeof(gOpComposite)); + XDBG_GOTO_IF_FAIL(pDstPixmap != NULL, bail); + + gOpComposite.op = op; + gOpComposite.pDstPicture = pDstPicture; + gOpComposite.pSrcPicture = pSrcPicture; + gOpComposite.pMaskPicture = pMaskPicture; + gOpComposite.pSrcPixmap = pSrcPixmap; + gOpComposite.pMaskPixmap = pMaskPixmap; + gOpComposite.pDstPixmap = pDstPixmap; + + gOpComposite.pOpDst = _swPrepareAccess(pDstPixmap, EXA_PREPARE_DEST); + + if (pSrcPixmap) { + gOpComposite.pOpSrc = _swPrepareAccess(pSrcPixmap, EXA_PREPARE_SRC); + XDBG_GOTO_IF_FAIL(gOpComposite.pOpSrc->num == 1, bail); + } + + if (pMaskPixmap) { + gOpComposite.pOpMask = _swPrepareAccess(pMaskPixmap, EXA_PREPARE_MASK); + XDBG_GOTO_IF_FAIL(gOpComposite.pOpMask->num == 1, bail); + } + + gOpComposite.bDo = TRUE; + + return TRUE; + + bail: + XDBG_TRACE(MEXAS, "FAIL: op%d\n", op); + XDBG_TRACE(MEXAS, " SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap); + XDBG_TRACE(MEXAS, " MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap); + XDBG_TRACE(MEXAS, " DST picture:%p pix:%p\n", pDstPicture, pDstPixmap); + + gOpComposite.bDo = FALSE; + + return TRUE; +} + +static void +EXYNOSExaSwComposite(PixmapPtr pDstPixmap, int srcX, int srcY, + int maskX, int maskY, int dstX, int dstY, + int width, int height) +{ + XDBG_TRACE(MEXAS, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n", + srcX, srcY, maskX, maskY, dstX, dstY, width, height); + if (!gOpComposite.bDo) + return; + + gOpComposite.srcX = srcX; + gOpComposite.srcY = srcY; + gOpComposite.maskX = maskX; + gOpComposite.maskY = maskY; + gOpComposite.dstX = dstX; + gOpComposite.dstY = dstY; + gOpComposite.width = width; + gOpComposite.height = height; + + if (gOpComposite.pOpDst->isSame) { + ExaBox box; + + box.state = rgnIN; + box.box.x1 = 0; + box.box.y1 = 0; + box.box.x2 = width; + box.box.y2 = height; + box.pDst = &gOpComposite.pOpDst->buf[0]; + box.pSrc = + (gOpComposite.pOpSrc) ? (&gOpComposite.pOpSrc->buf[0]) : NULL; + box.pSrc = + (gOpComposite.pOpMask) ? (&gOpComposite.pOpMask->buf[0]) : NULL; + + _swDoComposite(&box, NULL); + } + else { + int i; + ExaBox *box; + BoxRec b; + + /*Init box list */ + xorg_list_init(&gOpComposite.opBox); + + b.x1 = dstX; + b.y1 = dstY; + b.x2 = dstX + width; + b.y2 = dstY + height; + + for (i = 0; i < gOpComposite.pOpDst->num; i++) { + box = _swBoxAdd(&gOpComposite.opBox, + &gOpComposite.pOpDst->buf[i].pos, &b); + if (box) { + box->pDst = &gOpComposite.pOpDst->buf[i]; + box->pSrc = + (gOpComposite.pOpSrc) ? (&gOpComposite.pOpSrc-> + buf[0]) : NULL; + box->pMask = + (gOpComposite.pOpMask) ? (&gOpComposite.pOpMask-> + buf[0]) : NULL; + } + } + _swBoxMove(&gOpComposite.opBox, -dstX, -dstY); + + /* Call solid function */ + _swDoDraw(&gOpComposite.opBox, _swDoComposite, NULL); + + /*Remove box list */ + _swBoxRemoveAll(&gOpComposite.opBox); + } +} + +/* done composite : sw done composite, not using pvr2d */ +static void +EXYNOSExaSwDoneComposite(PixmapPtr pDst) +{ + XDBG_TRACE(MEXAS, "\n"); + if (gOpComposite.pDstPixmap != NULL) + _swFinishAccess(gOpComposite.pDstPixmap, EXA_PREPARE_DEST); + if (gOpComposite.pSrcPixmap != NULL) + _swFinishAccess(gOpComposite.pSrcPixmap, EXA_PREPARE_SRC); + if (gOpComposite.pMaskPixmap != NULL) + _swFinishAccess(gOpComposite.pMaskPixmap, EXA_PREPARE_MASK); +} + +static Bool +EXYNOSExaSwUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, + char *src, int src_pitch) +{ + XDBG_RETURN_VAL_IF_FAIL(src != NULL, TRUE); + XDBG_TRACE(MEXAS, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x, y, w, h); + XDBG_TRACE(MEXAS, "\tdst depth:%d, bpp:%d, pitch:%d, %dx%d\n", + pDst->drawable.depth, pDst->drawable.bitsPerPixel, pDst->devKind, + pDst->drawable.width, pDst->drawable.height); + + gOpUTS.pDst = pDst; + gOpUTS.x = x; + gOpUTS.y = y; + gOpUTS.w = w; + gOpUTS.h = h; + gOpUTS.src = src; + gOpUTS.src_pitch = src_pitch; + gOpUTS.pOpDst = _swPrepareAccess(pDst, EXA_PREPARE_DEST); + + if (gOpUTS.pOpDst->isSame) { + ExaBox box; + + box.box.x1 = 0; + box.box.y1 = 0; + box.box.x2 = w; + box.box.y2 = h; + box.state = rgnIN; + box.pDst = &gOpUTS.pOpDst->buf[0]; + _swDoUploadToScreen(&box, NULL); + } + else { + int i; + ExaBox *box; + BoxRec b; + + /*Init box list */ + xorg_list_init(&gOpUTS.opBox); + + b.x1 = x; + b.y1 = y; + b.x2 = x + w; + b.y2 = y + h; + + for (i = 0; i < gOpUTS.pOpDst->num; i++) { + box = _swBoxAdd(&gOpUTS.opBox, &gOpUTS.pOpDst->buf[i].pos, &b); + if (box) { + box->pDst = &gOpUTS.pOpDst->buf[i]; + } + } + _swBoxMove(&gOpUTS.opBox, -x, -y); + + /* Call solid function */ + _swDoDraw(&gOpUTS.opBox, _swDoUploadToScreen, NULL); + + /*Remove box list */ + _swBoxRemoveAll(&gOpUTS.opBox); + } + + _swFinishAccess(pDst, EXA_PREPARE_DEST); + return TRUE; +} + +static Bool +EXYNOSExaSwDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + XDBG_RETURN_VAL_IF_FAIL(dst != NULL, TRUE); + XDBG_TRACE(MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x, y, w, h); + + gOpDFS.pSrc = pSrc; + gOpDFS.x = x; + gOpDFS.y = y; + gOpDFS.w = w; + gOpDFS.h = h; + gOpDFS.dst = dst; + gOpDFS.dst_pitch = dst_pitch; + gOpDFS.pOpSrc = _swPrepareAccess(pSrc, EXA_PREPARE_SRC); + + if (gOpDFS.pOpSrc->isSame) { + ExaBox box; + + box.box.x1 = 0; + box.box.y1 = 0; + box.box.x2 = w; + box.box.y2 = h; + box.state = rgnIN; + box.pSrc = &gOpDFS.pOpSrc->buf[0]; + _swDoDownladFromScreen(&box, NULL); + } + else { + int i; + ExaBox *box; + BoxRec b; + + /*Init box list */ + xorg_list_init(&gOpDFS.opBox); + + b.x1 = x; + b.y1 = y; + b.x2 = x + w; + b.y2 = y + h; + + for (i = 0; i < gOpDFS.pOpSrc->num; i++) { + box = _swBoxAdd(&gOpDFS.opBox, &gOpDFS.pOpSrc->buf[i].pos, &b); + if (box) { + box->pSrc = &gOpDFS.pOpSrc->buf[i]; + } + } + _swBoxMove(&gOpDFS.opBox, -x, -y); + + /* Call solid function */ + _swDoDraw(&gOpDFS.opBox, _swDoDownladFromScreen, NULL); + + /*Remove box list */ + _swBoxRemoveAll(&gOpDFS.opBox); + } + + _swFinishAccess(pSrc, EXA_PREPARE_SRC); + return TRUE; +} + +int +EXYNOSExaMarkSync(ScreenPtr pScreen) +{ + XDBG_RETURN_VAL_IF_FAIL(pScreen != NULL, TRUE); + int ret = 0; + + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (pExynos && pExynos->is_fb_touched == TRUE) { + XDBG_TRACE(MEXAS, "UpdateRequest to the display!\n"); + + ret = exynosDisplayUpdateRequest(pScrn); + pExynos->is_fb_touched = FALSE; + } + + return ret; +} + +Bool +exynosExaSwInit(ScreenPtr pScreen, ExaDriverPtr pExaDriver) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + pExaDriver->PrepareSolid = EXYNOSExaSwPrepareSolid; + pExaDriver->Solid = EXYNOSExaSwSolid; + pExaDriver->DoneSolid = EXYNOSExaSwDoneSolid; + + pExaDriver->PrepareCopy = EXYNOSExaSwPrepareCopy; + pExaDriver->Copy = EXYNOSExaSwCopy; + pExaDriver->DoneCopy = EXYNOSExaSwDoneCopy; + + pExaDriver->CheckComposite = EXYNOSExaSwCheckComposite; + pExaDriver->PrepareComposite = EXYNOSExaSwPrepareComposite; + pExaDriver->Composite = EXYNOSExaSwComposite; + pExaDriver->DoneComposite = EXYNOSExaSwDoneComposite; + + pExaDriver->UploadToScreen = EXYNOSExaSwUploadToScreen; + pExaDriver->DownloadFromScreen = EXYNOSExaSwDownloadFromScreen; + + pExaDriver->MarkSync = EXYNOSExaMarkSync; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Succeed to Initialize SW EXA\n"); + + return TRUE; +} + +void +exynosExaSwDeinit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Succeed to finish SW EXA\n"); +} diff --git a/src/accel/exynos_present.c b/src/accel/exynos_present.c new file mode 100755 index 0000000..602c855 --- /dev/null +++ b/src/accel/exynos_present.c @@ -0,0 +1,595 @@ +/* + * + * xserver-xorg-video-exynos + * + * Copyright © 2013 Keith Packard + * Copyright 2010 - 2014 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Roman Marchenko <r.marchenko@samsung.com> + * Contact: Roman Peresipkyn<r.peresipkyn@samsung.com> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <errno.h> + +#include <tbm_bufmgr.h> + +#include "xorg-server.h" +#include "xf86.h" +#include "xf86drm.h" + +#include "windowstr.h" + +#include "present.h" + +#include "exynos.h" +#include "exynos_accel.h" +#include "exynos_display.h" +#include "exynos_crtc.h" +#include "exynos_layer_manager.h" + +static int EXYNOSPresentGetUstMsc(RRCrtcPtr pRRcrtc, CARD64 * ust, + CARD64 * msc); + +static EXYNOSLayerMngClientID lyr_client_id = 0; + +/*-------------------------- Private structures -----------------------------*/ +typedef struct _presentVblankEvent { + + uint64_t event_id; + + RRCrtcPtr pRRcrtc; //jast for info + +} PresentVblankEventRec, *PresentVblankEventPtr; + +/*-------------------------- Private functions -----------------------------*/ + +static void +_saveDrawable(ScrnInfoPtr pScrn, PixmapPtr pPix, WindowPtr pWin, int type) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + char file[128]; + char *str_type[7] = + { "none", "swap", "flip", "unflip", "flush", "blit", "fbblit" }; + char *appName = NULL; + const char *clientName = NULL; + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + + if (!pExynos->dump_info || !(pExynos->dump_mode & XBERC_DUMP_MODE_PRESENT)) + return; + + XDBG_RETURN_IF_FAIL(pPix != NULL); + + if (pWin) + clientName = GetClientCmdName(wClient(pWin)); + + if (clientName) + appName = strrchr(clientName, '/'); + + snprintf(file, sizeof(file), "[Present]%03d_%s_%s_%x_%x_%p_%03d.%s", + pExynos->flip_cnt, + str_type[type], + (appName ? (++appName) : ("none")), + (pWin ? (unsigned int) pWin->drawable.id : 0), + (unsigned int) pPix->drawable.id, + (void *) pPix, pExaPixPriv->dump_cnt, pExynos->dump_type); + + exynosUtilDoDumpPixmaps(pExynos->dump_info, pPix, file, pExynos->dump_type); + + XDBG_DEBUG(MSEC, "dump done\n"); + + pExaPixPriv->dump_cnt++; +} + +/*-------------------------- Public functions -----------------------------*/ +/* + * Called when the queued vblank event has occurred + */ +void +exynosPresentVblankHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + TTRACE_GRAPHICS_BEGIN("XORG:PRESENT:VBLANK_HANDLER"); + + uint64_t usec = (uint64_t) tv_sec * 1000000 + tv_usec; + + PresentVblankEventRec *pEvent = event_data; + + XDBG_DEBUG(MDRI3, "event_id %llu ust:%llu msc:%u\n", pEvent->event_id, usec, + frame); + present_event_notify(pEvent->event_id, usec, frame); + free(pEvent); + + TTRACE_GRAPHICS_END(); +} + +/* + * Called when the queued vblank is aborted + */ +void +exynosPresentVblankAbort(ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void *data) +{ + PresentVblankEventRec *pEvent = data; + + if (pEvent) + free(pEvent); +} + +/* + * Once the flip has been completed on all pipes, notify the + * extension code telling it when that happened + */ + +void +exynosPresentFlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data, + Bool flip_failed) +{ + PresentVblankEventRec *pEvent = event_data; + uint64_t ust = (uint64_t) tv_sec * 1000000 + tv_usec; + uint64_t msc = (uint64_t) frame; + + TTRACE_GRAPHICS_BEGIN("XORG:PRESENT:FLIP_HANDLER"); + + if (msc == 0) { + uint64_t tmp_ust; + + EXYNOSPresentGetUstMsc(pEvent->pRRcrtc, &tmp_ust, &msc); + } + + XDBG_DEBUG(MDRI3, "event_id %llu ust:%llu msc:%llu(%u)\n", pEvent->event_id, + ust, msc, frame); + present_event_notify(pEvent->event_id, ust, msc); + free(pEvent); + + TTRACE_GRAPHICS_END(); +} + +/* + * The flip has been aborted, free the structure + */ +void +exynosPresentFlipAbort(void *pageflip_data) +{ + PresentVblankEventRec *pEvent = pageflip_data; + + free(pEvent); +} + +/*-------------------------- Callback functions -----------------------------*/ +static RRCrtcPtr +EXYNOSPresentGetCrtc(WindowPtr pWindow) +{ + XDBG_RETURN_VAL_IF_FAIL(pWindow != NULL, NULL); + + ScreenPtr pScreen = pWindow->drawable.pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + BoxRec box, crtcbox; + xf86CrtcPtr pCrtc = NULL; + RRCrtcPtr pRandrCrtc = NULL; + + box.x1 = pWindow->drawable.x; + box.y1 = pWindow->drawable.y; + box.x2 = box.x1 + pWindow->drawable.width; + box.y2 = box.y1 + pWindow->drawable.height; + + pCrtc = exynosModeCoveringCrtc(pScrn, &box, NULL, &crtcbox); + + /* Make sure the CRTC is valid and this is the real front buffer */ + if (pCrtc != NULL && !pCrtc->rotatedData) //TODO what is pCrtc->rotatedData pointing on? + pRandrCrtc = pCrtc->randr_crtc; + + XDBG_DEBUG(MDRI3, "%s\n", pRandrCrtc ? "OK" : "ERROR"); + + return pRandrCrtc; +} + +/* + * The kernel sometimes reports bogus MSC values, especially when + * suspending and resuming the machine. Deal with this by tracking an + * offset to ensure that the MSC seen by applications increases + * monotonically, and at a reasonable pace. + */ +static int +EXYNOSPresentGetUstMsc(RRCrtcPtr pRRcrtc, CARD64 * ust, CARD64 * msc) +{ + XDBG_RETURN_VAL_IF_FAIL(pRRcrtc != NULL, 0); + + xf86CrtcPtr pCrtc = pRRcrtc->devPrivate; + ScreenPtr pScreen = pRRcrtc->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + //Get the current msc/ust value from the kernel + Bool ret = exynosDisplayGetCurMSC(pScrn, pCrtcPriv->pipe, ust, msc); + + XDBG_DEBUG(MDRI3, "%s: pipe:%d ust:%llu msc:%llu\n", + (ret ? "OK" : "ERROR"), pCrtcPriv->pipe, *ust, *msc); + return (int) ret; +} + +static int +EXYNOSPresentQueueVblank(RRCrtcPtr pRRcrtc, uint64_t event_id, uint64_t msc) +{ + xf86CrtcPtr pCrtc = pRRcrtc->devPrivate; + ScreenPtr pScreen = pRRcrtc->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + int pipe = exynosModeGetCrtcPipe(pCrtc); + PresentVblankEventPtr pEvent = NULL; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + pEvent = calloc(sizeof(PresentVblankEventRec), 1); + if (!pEvent) { + XDBG_ERROR(MDRI3, "fail to Vblank: event_id %llu msc %llu \n", event_id, + msc); + return BadAlloc; + } + pEvent->event_id = event_id; + pEvent->pRRcrtc = pRRcrtc; + + if (pExynos->isCrtcOn == FALSE || pExynos->isLcdOff == TRUE) { + CARD64 ust, msc; + + XDBG_DEBUG(MDRI3, "LCD is OFF... call present_event_notify.\n"); + EXYNOSPresentGetUstMsc(pRRcrtc, &ust, &msc); + present_event_notify(pEvent->event_id, ust, msc); + free(pEvent); + return Success; + } + + /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */ + if (!exynosDisplayVBlank(pScrn, pipe, &msc, 0, VBLANK_INFO_PRESENT, pEvent)) { + XDBG_WARNING(MDRI3, "fail to Vblank: event_id %llu msc %llu \n", + event_id, msc); + exynosPresentVblankAbort(pScrn, pCrtc, pEvent); + return BadAlloc; + } + + XDBG_DEBUG(MDRI3, "OK to Vblank event_id:%llu msc:%llu \n", event_id, msc); + return Success; +} + +static void +EXYNOSPresentAbortVblank(RRCrtcPtr pRRcrtc, uint64_t event_id, uint64_t msc) +{ + XDBG_INFO(MDRI3, "isn't implamentation\n"); + +} + +static void +EXYNOSPresentFlush(WindowPtr window) +{ + XDBG_INFO(MDRI3, "isn't implamentation\n"); + + ScreenPtr pScreen = window->drawable.pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (window); + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPixmap); + + _saveDrawable(pScrn, pPixmap, window, 4); + + XDBG_DEBUG(MDRI3, "doPresentFlush id:0x%x\n" + "pix(sn:%ld p:%p ID:0x%x), bo(ptr:%p name:%d)\n", + (unsigned int) window->drawable.id, + pPixmap->drawable.serialNumber, pPixmap, pPixmap->drawable.id, + (pExaPixPriv->bo ? pExaPixPriv->bo : 0), + (pExaPixPriv->bo ? tbm_bo_export(pExaPixPriv->bo) : -1)); +} + +static Bool +EXYNOSPresentCheckFlip(RRCrtcPtr pRRcrtc, + WindowPtr pWin, PixmapPtr pPixmap, Bool sync_flip) +{ + + ScrnInfoPtr pScrn = xf86ScreenToScrn(pWin->drawable.pScreen); + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPixmap); + + if (!EXYNOSPTR(pScrn)->use_flip) + return FALSE; + + if (!pExaPixPriv) + return FALSE; + + if (EXYNOSPTR(pScrn)->hwc_active && !EXYNOSPTR(pScrn)->hwc_use_def_layer) { + return FALSE; + } + + if (pExaPixPriv->isFrameBuffer == FALSE) { + XDBG_RETURN_VAL_IF_FAIL(exynosSwapToRenderBo + (pScrn, pWin->drawable.width, + pWin->drawable.height, pExaPixPriv->bo, FALSE), + FALSE); + + pExaPixPriv->isFrameBuffer = TRUE; + pExaPixPriv->sbc = 0; + pExaPixPriv->size = pPixmap->drawable.height * pPixmap->devKind; + pExaPixPriv->pWin = pWin; + } + pExaPixPriv->owner = pWin->drawable.id; + return TRUE; +} + +#ifdef PRESENT_WINDOW_FLIP +static Bool +EXYNOSPresentWindowFlip(RRCrtcPtr pRRcrtc, uint64_t event_id, + uint64_t target_msc, WindowPtr pWindow, + PixmapPtr pPixmap, Bool sync_flip) +{ + TTRACE_GRAPHICS_BEGIN("XORG:PRESENT:FLIP"); + +#ifdef LAYER_MANAGER + EXYNOSVideoBuf *vbuf = NULL; + + /* TODO - process "sync_flip" flag */ + + ScreenPtr pScreen = pRRcrtc->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + PresentVblankEventPtr pEvent = NULL; + + pEvent = calloc(sizeof(PresentVblankEventRec), 1); + XDBG_GOTO_IF_FAIL(pEvent != NULL, fail); + pEvent->event_id = event_id; + pEvent->pRRcrtc = pRRcrtc; + + _saveDrawable(pScrn, pPixmap, pWindow, 2); + + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPixmap); + + XDBG_DEBUG(MDRI3, + "event:%lld target_msc:%lld Drawable(0x%x) Pixmap:(sn:%ld p:%p ID:0x%x, bo(ptr:%p name:%d))\n", + event_id, target_msc, (unsigned int) pWindow->drawable.id, + pPixmap->drawable.serialNumber, pPixmap, pPixmap->drawable.id, + pExaPixPriv->bo, tbm_bo_export(pExaPixPriv->bo)); + + DrawablePtr pDraw = &pWindow->drawable; + EXYNOSLayerPos lpos = exynosHwcGetDrawLpos(pDraw); + + if (lpos == LAYER_NONE) { + XDBG_ERROR(MDRI3, "Drawable(0x%x) was deleted from HWC\n", + (unsigned int) pDraw->id); + goto fail; + } + + vbuf = exynosUtilCreateVideoBufferByDraw((DrawablePtr) pPixmap); + XDBG_GOTO_IF_FAIL(vbuf != NULL, fail); + vbuf->vblank_handler = exynosPresentFlipEventHandler; + vbuf->vblank_user_data = pEvent; + exynosHwcSetDriFlag(pDraw, TRUE); + XDBG_GOTO_IF_FAIL(exynosLayerMngSet + (lyr_client_id, 0, 0, NULL, NULL, NULL, vbuf, 0, lpos, + NULL, NULL), fail); + + TTRACE_GRAPHICS_END(); + return TRUE; + + fail:if (vbuf) + exynosUtilFreeVideoBuffer(vbuf); + if (pEvent) + exynosPresentFlipAbort(pEvent); + XDBG_WARNING(MDRI3, "fail to flip\n"); + TTRACE_GRAPHICS_END(); + return FALSE; + +#else + XDBG_WARNING(MDRI3, "hwc flip not implemented\n"); + TTRACE_GRAPHICS_END(); + return FALSE; +#endif +} +#endif + +static Bool +EXYNOSPresentFlip(RRCrtcPtr pRRcrtc, + uint64_t event_id, + uint64_t target_msc, PixmapPtr pPixmap, Bool sync_flip) +{ + xf86CrtcPtr pCrtc = pRRcrtc->devPrivate; + ScreenPtr pScreen = pRRcrtc->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + int pipe = exynosModeGetCrtcPipe(pCrtc); + PresentVblankEventPtr pEvent = NULL; + Bool ret; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + /* TODO - process sync_flip flag + * if (sync_flip) + * -//- + * else + * -//- + * */ + + TTRACE_GRAPHICS_BEGIN("XORG:PRESENT:FLIP"); + + if (pExynos->isCrtcOn == FALSE || pExynos->isLcdOff == TRUE) { + XDBG_DEBUG(MDRI3, "LCD is OFF... return false.\n"); + TTRACE_GRAPHICS_END(); + return FALSE; + } + + pEvent = calloc(sizeof(PresentVblankEventRec), 1); + if (!pEvent) { + XDBG_ERROR(MDRI3, "fail to flip\n"); + TTRACE_GRAPHICS_END(); + return BadAlloc; + } + pEvent->event_id = event_id; + pEvent->pRRcrtc = pRRcrtc; + + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPixmap); + + /*FIXME - get client id by draw id */ + unsigned int client_idx = 0; + + _saveDrawable(pScrn, pPixmap, pExaPixPriv->pWin, 2); + + exynosRenderBoSetPos(pExaPixPriv->bo, pExaPixPriv->pWin->drawable.x, + pExaPixPriv->pWin->drawable.y); + + ret = exynosModePageFlip(pScrn, NULL, pEvent, pipe, pExaPixPriv->bo, + NULL, client_idx, pExaPixPriv->pWin->drawable.id, + exynosPresentFlipEventHandler, TRUE); + if (!ret) { + exynosPresentFlipAbort(pEvent); + XDBG_WARNING(MDRI3, + "fail to flip, error while exynosModePageFlip call\n"); + } + else { + PixmapPtr pRootPix = pScreen->GetWindowPixmap(pScreen->root); + EXYNOSPixmapPriv *pRootPixPriv = exaGetPixmapDriverPrivate(pRootPix); + PixmapPtr pScreenPix = pScreen->GetScreenPixmap(pScreen); + EXYNOSPixmapPriv *pScreenPixPriv = + exaGetPixmapDriverPrivate(pScreenPix); + + XDBG_DEBUG(MDRI3, "doPageFlip id:0x%x Client:%d pipe:%d\n" + "Present:pix(sn:%ld p:%p ID:0x%x), bo(ptr:%p name:%d)\n" + "Root: pix(sn:%ld p:%p ID:0x%x), bo(ptr:%p name:%d)\n" + "Screen: pix(sn:%ld p:%p ID:0x%x), bo(ptr:%p name:%d)\n", + (unsigned int) pExaPixPriv->owner, client_idx, pipe, + pPixmap->drawable.serialNumber, pPixmap, + pPixmap->drawable.id, pExaPixPriv->bo, + tbm_bo_export(pExaPixPriv->bo), + pRootPix->drawable.serialNumber, pRootPix, + pRootPix->drawable.id, pRootPixPriv->bo, + (pRootPixPriv->bo ? tbm_bo_export(pRootPixPriv->bo) : -1), + pScreenPix->drawable.serialNumber, pScreenPix, + pScreenPix->drawable.id, pScreenPixPriv->bo, + (pScreenPixPriv->bo ? tbm_bo_export(pScreenPixPriv->bo) : + -1)); + + } + + TTRACE_GRAPHICS_END(); + return ret; +} + +/* + * Queue a flip back to the normal frame buffer + */ +static void +EXYNOSPresentUnflip(ScreenPtr pScreen, uint64_t event_id) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + PresentVblankEventPtr pEvent = NULL; + PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen); + int ret; + + if (!EXYNOSPresentCheckFlip(NULL, pScreen->root, pPixmap, TRUE)) { + XDBG_WARNING(MDRI3, "fail to check flip for screen pixmap\n"); + return; + } + + pEvent = calloc(sizeof(PresentVblankEventRec), 1); + if (!pEvent) + return; + + pEvent->event_id = event_id; + pEvent->pRRcrtc = NULL; + + EXYNOSPixmapPriv *pExaPixPriv = exaGetPixmapDriverPrivate(pPixmap); + + _saveDrawable(pScrn, pPixmap, pExaPixPriv->pWin, 3); + + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(pExaPixPriv->bo != NULL, fail); + + ret = exynosModePageFlip(pScrn, NULL, pEvent, -1, pExaPixPriv->bo, NULL, 0, + 0, exynosPresentFlipEventHandler, TRUE); + + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + if (!ret) { + exynosPresentFlipAbort(pEvent); + XDBG_WARNING(MDRI3, "fail to flip\n"); + } + else { + XDBG_DEBUG(MDRI3, "Unflip doPageFlip id:0x%x Client:%d pipe:%d\n" + "Present: screen pix(sn:%ld p:%p ID:0x%x)\n", + (unsigned int) pExaPixPriv->owner, 0, -1, + pPixmap->drawable.serialNumber, pPixmap, + pPixmap->drawable.id); + } + + return; + + fail: + if (pEvent) + free(pEvent); +} + +/* The main structure which contains callback functions */ +static present_screen_info_rec exynosPresentScreenInfo = { + + .version = PRESENT_SCREEN_INFO_VERSION, + + .get_crtc = EXYNOSPresentGetCrtc, + .get_ust_msc = EXYNOSPresentGetUstMsc, + .queue_vblank = EXYNOSPresentQueueVblank, + .abort_vblank = EXYNOSPresentAbortVblank, + .flush = EXYNOSPresentFlush, + .capabilities = PresentCapabilityNone, + .check_flip = EXYNOSPresentCheckFlip, + .flip = EXYNOSPresentFlip, + .unflip = EXYNOSPresentUnflip, +#ifdef PRESENT_WINDOW_FLIP + /* add in for Tizen extension */ + .window_flip = EXYNOSPresentWindowFlip, +#endif +}; + +static Bool +_hasAsyncFlip(ScreenPtr pScreen) +{ +#ifdef DRM_CAP_ASYNC_PAGE_FLIP + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int ret = 0; + uint64_t value = 0; + + ret = drmGetCap(pExynos->drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); + if (ret == 0) + return value == 1; +#endif + return FALSE; +} + +Bool +exynosPresentScreenInit(ScreenPtr pScreen) +{ + + if (_hasAsyncFlip(pScreen)) + exynosPresentScreenInfo.capabilities |= PresentCapabilityAsync; + + lyr_client_id = + exynosLayerMngRegisterClient(xf86ScreenToScrn(pScreen), "HWC", 1); + + int ret = present_screen_init(pScreen, &exynosPresentScreenInfo); + + if (!ret) + return FALSE; + + return TRUE; +} diff --git a/src/accel/sec_dri2.c b/src/accel/sec_dri2.c deleted file mode 100755 index 1808979..0000000 --- a/src/accel/sec_dri2.c +++ /dev/null @@ -1,1991 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2001 VA Linux Systems Inc., Fremont, California. -Copyright © 2002 by David Dawes -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <stdio.h> -#include <string.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/time.h> -#include <time.h> -#include <errno.h> -#include <poll.h> - -#include "X11/Xatom.h" -#include "xorg-server.h" -#include "xf86.h" -#include "dri2.h" -#include "damage.h" -#include "windowstr.h" -#include "sec.h" -#include "sec_accel.h" -#include "sec_display.h" -#include "sec_crtc.h" -#include "sec_util.h" -#include "sec_crtc.h" -#include "sec_xberc.h" - -#define DRI2_BUFFER_TYPE_WINDOW 0x0 -#define DRI2_BUFFER_TYPE_PIXMAP 0x1 -#define DRI2_BUFFER_TYPE_FB 0x2 - -typedef union{ - unsigned int flags; - struct { - unsigned int type:1; - unsigned int is_framebuffer:1; - unsigned int is_viewable:1; - unsigned int is_reused:1; - unsigned int idx_reuse:3; - }data; -}DRI2BufferFlags; - -#define DRI2_GET_NEXT_IDX(idx, max) (((idx+1) % (max))) - -/* if a window is mapped and realized (viewable) */ -#define IS_VIEWABLE(pDraw) \ - ((pDraw->type == DRAWABLE_PIXMAP)?TRUE:(Bool)(((WindowPtr) pDraw)->viewable)) - -/* dri2 buffer private infomation */ -typedef struct _dri2BufferPriv -{ - int refcnt; - int attachment; - PixmapPtr pPixmap; - ScreenPtr pScreen; - - /* pixmap of the backbuffer */ - int pipe; - Bool canFlip; - int num_buf; - int avail_idx; /* next available index of the back pixmap, -1 means not to be available */ - int cur_idx; /* current index of the back pixmap, -1 means not to be available */ - int free_idx; /* free index of the back pixmap, -1 means not to be available */ - PixmapPtr *pBackPixmaps; - - /* flip buffers */ - ClientPtr pClient; - DRI2FrameEventPtr pFlipEvent; -} DRI2BufferPrivRec, *DRI2BufferPrivPtr; - -/* prototypes */ -static void SECDri2CopyRegion (DrawablePtr pDraw, RegionPtr pRegion, - DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf); -static void SECDri2DestroyBuffer (DrawablePtr pDraw, DRI2BufferPtr pBuf); - -static PixmapPtr _initBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip); -static void _deinitBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip); -static void _exchangeBackBufPixmap (DRI2BufferPtr pBackBuf); -static PixmapPtr _reuseBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip, int *reues); -static void _disuseBackBufPixmap (DRI2BufferPtr pBackBuf, DRI2FrameEventPtr pEvent); - -static unsigned int -_getName (PixmapPtr pPix) -{ - SECPixmapPriv *pExaPixPriv = NULL; - - if (pPix == NULL) - return 0; - - pExaPixPriv = exaGetPixmapDriverPrivate (pPix); - if (pExaPixPriv == NULL) - return 0; - - if (pExaPixPriv->bo == NULL) - { - if(pExaPixPriv->isFrameBuffer) - return (unsigned int)ROOT_FB_ADDR; - else - return 0; - } - - return tbm_bo_export (pExaPixPriv->bo); -} - -/* initialize the pixmap of the backbuffer */ -static PixmapPtr -_initBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR(pScrn); - SECExaPrivPtr pExaPriv = SECEXAPTR (pSec); - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK; - PixmapPtr pPixmap = NULL; - int pipe = -1; - - /* if a drawable can be flip, check whether the flip buffer is available */ - if (canFlip) - { - usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; - pipe = secDisplayDrawablePipe (pDraw); - if (pipe != -1) - { - /* get the flip pixmap from crtc */ - pPixmap = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint); - if (!pPixmap) - { - /* fail to get a flip pixmap from crtc */ - canFlip = FALSE; - XDBG_WARNING(MDRI2, "fail to get a flip pixmap from crtc\n"); - } - } - else - { - /* pipe is -1 */ - canFlip = FALSE; - XDBG_WARNING(MDRI2, "pipe is -1"); - } - } - - /* if canflip is false, get the dri2_back pixmap */ - if (!canFlip) - { - pPixmap = (*pScreen->CreatePixmap) (pScreen, - pDraw->width, - pDraw->height, - pDraw->depth, - usage_hint); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); -#if USE_XDBG - xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap); -#endif - } - - if (canFlip) - { - pBackBufPriv->num_buf = pExaPriv->flip_backbufs; - pBackBufPriv->pBackPixmaps = calloc (pBackBufPriv->num_buf, sizeof (void*)); - } - else - { - pBackBufPriv->num_buf = 1; /* num of backbuffer for swap/blit */ - pBackBufPriv->pBackPixmaps = calloc (pBackBufPriv->num_buf, sizeof (void*)); - } - - XDBG_RETURN_VAL_IF_FAIL ((pBackBufPriv->pBackPixmaps != NULL), NULL); - - pBackBufPriv->pBackPixmaps[0] = pPixmap; - pBackBufPriv->canFlip = canFlip; - pBackBufPriv->avail_idx = 0; - pBackBufPriv->free_idx = 0; - pBackBufPriv->cur_idx = 0; - pBackBufPriv->pipe = pipe; - - return pPixmap; -} - -/* deinitialize the pixmap of the backbuffer */ -static void -_deinitBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip) -{ - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - ScreenPtr pScreen = pBackBufPriv->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int i; - int pipe = -1; - - for (i = 0; i < pBackBufPriv->num_buf; i++) - { - if (pBackBufPriv->pBackPixmaps) - { - if(pBackBufPriv->pBackPixmaps[i]) - { - if (canFlip) - { - /* have to release the flip pixmap */ - pipe = pBackBufPriv->pipe; - if (pipe != -1) - secCrtcRelAllFlipPixmap (pScrn, pipe); - else - XDBG_WARNING(MDRI2, "pipe is -1\n"); - } - else - { -#if USE_XDBG - xDbgLogPListDrawRemoveRefPixmap (pDraw, pBackBufPriv->pBackPixmaps[i]); -#endif - (*pScreen->DestroyPixmap) (pBackBufPriv->pBackPixmaps[i]); - } - pBackBufPriv->pBackPixmaps[i] = NULL; - pBackBufPriv->pPixmap = NULL; - } - free(pBackBufPriv->pBackPixmaps); - pBackBufPriv->pBackPixmaps = NULL; - } - } -} - -/* increase the next available index of the backbuffer */ -static void -_exchangeBackBufPixmap (DRI2BufferPtr pBackBuf) -{ - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - - /* increase avail_idx when buffers exchange */ - pBackBufPriv->avail_idx = DRI2_GET_NEXT_IDX(pBackBufPriv->avail_idx, pBackBufPriv->num_buf); -} - -/* return the next available pixmap of the backbuffer */ -static PixmapPtr -_reuseBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip, int *reues) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - PixmapPtr pPixmap = NULL; - int avail_idx = pBackBufPriv->avail_idx; - unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK; - int pipe = -1; - - if (pBackBufPriv->canFlip != canFlip) - { - /* flip buffer -> swap buffer */ - if (pBackBufPriv->canFlip && !canFlip) - { - /* return the next available pixmap */ - _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip); - pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); - return pPixmap; - } - - /* swap buffer -> flip buffer */ - if (!pBackBufPriv->canFlip && canFlip) - { - pipe = secDisplayDrawablePipe (pDraw); - if (pipe != -1) - { - /* return the next available pixmap */ - _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip); - pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); - return pPixmap; - } - else - { - canFlip = FALSE; - XDBG_WARNING (MDRI2, "pipe is -1\n"); - } - } - } - - /* set the next available pixmap */ - /* if pBackPixmap is available, reuse it */ - if (pBackBufPriv->pBackPixmaps[avail_idx]) - { - if (canFlip) - { - usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; - pipe = secDisplayDrawablePipe (pDraw); - if (pipe != -1) - { - if (avail_idx != pBackBufPriv->cur_idx) - { - /* get the flip pixmap from crtc */ - pBackBufPriv->pBackPixmaps[avail_idx] = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint); - if (!pBackBufPriv->pBackPixmaps[avail_idx]) - { - /* fail to get a flip pixmap from crtc */ - XDBG_WARNING(MDRI2, "@@[reuse]: draw(0x%x) fail to get a flip pixmap from crtc to reset the index of pixmap\n", - (unsigned int)pDraw->id); - - _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip); - pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); - *reues = 0; - return pPixmap; - } - pBackBufPriv->cur_idx = avail_idx; - } - } - else - { - XDBG_WARNING (MDRI2, "pipe is -1(%d)\n", pipe); - return NULL; - } - } - else - { - if (avail_idx != pBackBufPriv->cur_idx) - { - pBackBufPriv->cur_idx = avail_idx; - } - } - - *reues = 1; - } - else - { - if (canFlip) - { - usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK; - pipe = secDisplayDrawablePipe (pDraw); - if (pipe != -1) - { - if (avail_idx != pBackBufPriv->cur_idx) - { - /* get the flip pixmap from crtc */ - pBackBufPriv->pBackPixmaps[avail_idx] = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint); - if (!pBackBufPriv->pBackPixmaps[avail_idx]) - { - /* fail to get a flip pixmap from crtc */ - XDBG_WARNING(MDRI2, "@@[initial set]: draw(0x%x) fail to get a flip pixmap from crtc to generate and to set the next available pixmap.\n", - (unsigned int)pDraw->id); - - _deinitBackBufPixmap (pBackBuf, pDraw, TRUE); - pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); - *reues = 0; - return pPixmap; - } - pBackBufPriv->cur_idx = avail_idx; - } - } - } - else - { - if (avail_idx != pBackBufPriv->cur_idx) - { - - pBackBufPriv->pBackPixmaps[avail_idx] = (*pScreen->CreatePixmap) (pScreen, - pDraw->width, - pDraw->height, - pDraw->depth, - usage_hint); - XDBG_RETURN_VAL_IF_FAIL(pBackBufPriv->pBackPixmaps[avail_idx] != NULL, NULL); - pBackBufPriv->cur_idx = avail_idx; -#if USE_XDBG - xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap); -#endif - } - } - - *reues = 0; - } - pPixmap = pBackBufPriv->pBackPixmaps[avail_idx]; - - pBackBufPriv->canFlip = canFlip; - - return pPixmap; -} - -static void -_disuseBackBufPixmap (DRI2BufferPtr pBackBuf, DRI2FrameEventPtr pEvent) -{ - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - ScreenPtr pScreen = pBackBufPriv->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (pEvent->type == DRI2_FLIP) - { - secCrtcRelFlipPixmap (pScrn, pEvent->crtc_pipe, - pBackBufPriv->pBackPixmaps[pBackBufPriv->free_idx]); - - /* increase free_idx when buffers destory or when frame is deleted */ - pBackBufPriv->free_idx = DRI2_GET_NEXT_IDX(pBackBufPriv->free_idx, pBackBufPriv->num_buf); - } -} - -static void -_setDri2Property (DrawablePtr pDraw) -{ - if(pDraw->type == DRAWABLE_WINDOW) - { - static Atom atom_use_dri2= 0; - static int use = 1; - - if(!atom_use_dri2) - { - atom_use_dri2 = MakeAtom ("X_WIN_USE_DRI2", 14, TRUE); - } - - dixChangeWindowProperty (serverClient, - (WindowPtr)pDraw, atom_use_dri2, XA_CARDINAL, 32, - PropModeReplace, 1, &use, TRUE); - } -} - -static unsigned int -_getBufferFlag (DrawablePtr pDraw, Bool canFlip) -{ - DRI2BufferFlags flag; - flag.flags = 0; - - switch (pDraw->type) - { - case DRAWABLE_WINDOW: - flag.data.type = DRI2_BUFFER_TYPE_WINDOW; - break; - case DRAWABLE_PIXMAP: - flag.data.type = DRI2_BUFFER_TYPE_PIXMAP; - break; - } - - if (IS_VIEWABLE(pDraw)) - { - flag.data.is_viewable = 1; - } - - if (canFlip) - { - flag.data.is_framebuffer = 1; - } - - return flag.flags; -} - -static inline PixmapPtr -_getPixmapFromDrawable (DrawablePtr pDraw) -{ - ScreenPtr pScreen = pDraw->pScreen; - PixmapPtr pPix; - - if (pDraw->type == DRAWABLE_WINDOW) - pPix = (*pScreen->GetWindowPixmap) ((WindowPtr) pDraw); - else - pPix = (PixmapPtr) pDraw; - - return pPix; -} - -/* Can this drawable be page flipped? */ -static Bool -_canFlip (DrawablePtr pDraw) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR(pScrn); - WindowPtr pWin, pRoot; - PixmapPtr pWinPixmap, pRootPixmap; - int ret; - - if (pDraw->type == DRAWABLE_PIXMAP) - return FALSE; - - pRoot = pScreen->root; - pRootPixmap = pScreen->GetWindowPixmap (pRoot); - pWin = (WindowPtr) pDraw; - pWinPixmap = pScreen->GetWindowPixmap (pWin); - if (pRootPixmap != pWinPixmap) - return FALSE; - - if (!IS_VIEWABLE(pDraw)) - return FALSE; - - ret = secFbFindBo(pSec->pFb, - pDraw->x, pDraw->y, pDraw->width, pDraw->height, - NULL, NULL); - if (ret != rgnSAME) - return FALSE; - - return TRUE; -} - -static DRI2FrameEventType -_getSwapType (DrawablePtr pDraw, DRI2BufferPtr pFrontBuf, - DRI2BufferPtr pBackBuf) -{ - DRI2BufferPrivPtr pFrontBufPriv; - DRI2BufferPrivPtr pBackBufPriv; - PixmapPtr pFrontPix; - PixmapPtr pBackPix; - SECPixmapPriv *pFrontExaPixPriv = NULL; - SECPixmapPriv *pBackExaPixPriv = NULL; - DRI2FrameEventType swap_type = DRI2_NONE; - - if (!pFrontBuf || !pBackBuf) - return DRI2_NONE; - - /* if a buffer is not viewable at DRI2GetBuffers, return none */ - if (!IS_VIEWABLE(pDraw)) - { - //XDBG_WARNING(MDRI2, "DRI2_NONE: window is not viewable.(%d,%d)\n", pDraw->width, pDraw->height); - return DRI2_NONE; - } - - pFrontBufPriv = pFrontBuf->driverPrivate; - pBackBufPriv = pBackBuf->driverPrivate; - pFrontPix = pFrontBufPriv->pPixmap; - pBackPix = pBackBufPriv->pPixmap; - if (!pFrontPix || !pBackPix) - { - XDBG_WARNING(MDRI2, "Warning: pFrontPix or pBackPix is null.(DRI2_NONE)\n"); - return DRI2_NONE; - } - - pFrontExaPixPriv = exaGetPixmapDriverPrivate (pFrontBufPriv->pPixmap); - pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap); - if (!pFrontExaPixPriv || !pBackExaPixPriv) - { - XDBG_WARNING(MDRI2, "Warning: pFrontPixPriv or pBackPixPriv is null.(DRI2_NONE)\n"); - return DRI2_NONE; - } - - - /* Check Exchange */ - if (pFrontBufPriv->canFlip == 1) - { - if(pBackBufPriv->canFlip == 1) - { - swap_type = DRI2_FLIP; - - if (!_canFlip(pDraw)) - { - ErrorF ("@@@ [%10.3f] %lx : flip to blit\n", GetTimeInMillis()/1000.0, pDraw->id); - swap_type = DRI2_BLIT; - } - } - else - { - XDBG_WARNING (MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) \n", - pFrontBufPriv->canFlip, pBackBufPriv->canFlip); - swap_type = DRI2_FB_BLIT; - } - } - else - { - if (pFrontExaPixPriv->isFrameBuffer == 1) - { - //XDBG_WARNING (MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) : front is framebuffer \n", - // pFrontBufPriv->canFlip, pBackBufPriv->canFlip); - swap_type = DRI2_FB_BLIT; - } - else - { - if (pFrontPix->drawable.width == pBackPix->drawable.width && - pFrontPix->drawable.height == pBackPix->drawable.height && - pFrontPix->drawable.bitsPerPixel == pBackPix->drawable.bitsPerPixel) - { - swap_type = DRI2_SWAP; - } - else - { - swap_type = DRI2_BLIT; - } - } - } - - return swap_type; -} - -static void -_referenceBufferPriv (DRI2BufferPtr pBuf) -{ - if (pBuf) - { - DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; - pBufPriv->refcnt++; - } -} - -static void -_unreferenceBufferPriv (DRI2BufferPtr pBuf) -{ - if (pBuf) - { - DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; - pBufPriv->refcnt--; - } -} - -static Bool -_resetBufPixmap (DrawablePtr pDraw, DRI2BufferPtr pBuf) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; - PixmapPtr pPix = NULL, pNewPix=NULL, pOldPix=NULL; - Bool canFlip = FALSE; - int reuse = 0; - - canFlip = _canFlip (pDraw); - - if (pBufPriv->attachment == DRI2BufferFrontLeft) - { - pPix = _getPixmapFromDrawable (pDraw); - if (pPix != pBufPriv->pPixmap || - ((DRI2BufferFlags)pBuf->flags).data.is_viewable != IS_VIEWABLE(pDraw)) - { - pOldPix = pBufPriv->pPixmap; - - /* reset the pixmap and the name of the buffer */ - pNewPix = _getPixmapFromDrawable (pDraw); - pPix->refcnt++; - pBufPriv->canFlip = canFlip; - - /* Destroy Old buffer */ - if (pOldPix) - { - (*pScreen->DestroyPixmap) (pOldPix); - } - } - else - { - pBufPriv->canFlip = canFlip; - return FALSE; - } - } - else - { - pNewPix = _reuseBackBufPixmap(pBuf, pDraw, canFlip, &reuse); - if (pNewPix == NULL) - { - XDBG_WARNING (MDRI2, "Error pixmap is null\n", pipe); - return FALSE; - } - - if (reuse) - { - pBufPriv->pPixmap = pNewPix; - return FALSE; - } - } - - pBufPriv->pPixmap = pNewPix; - - pBuf->name = _getName (pNewPix); - pBuf->flags = _getBufferFlag(pDraw, canFlip); - - XDBG_TRACE (MDRI2,"id:0x%x(%d) can_flip:%d attach:%d, name:%d, flags:0x%x geo(%dx%d+%d+%d)\n", - pDraw->id, pDraw->type, - pBufPriv->canFlip, - pBuf->attachment, pBuf->name, pBuf->flags, - pDraw->width, pDraw->height, pDraw->x, pDraw->y); - - return TRUE; -} - -static void -_generateDamage (DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent) -{ - BoxRec box; - RegionRec region; - - if (pFrameEvent->pRegion) - { - /* translate the regions with drawable */ - BoxPtr pBox = RegionRects(pFrameEvent->pRegion); - int nBox = RegionNumRects(pFrameEvent->pRegion); - - while (nBox--) - { - box.x1 = pBox->x1; - box.y1 = pBox->y1; - box.x2 = pBox->x2; - box.y2 = pBox->y2; - XDBG_DEBUG(MDRI2,"Damage Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ", - nBox, box.x1, box.x2, box.y1, box.y2); - RegionInit (®ion, &box, 0); - DamageDamageRegion (pDraw, ®ion); - pBox++; - } - } - else - { - - box.x1 = pDraw->x; - box.y1 = pDraw->y; - box.x2 = box.x1 + pDraw->width; - box.y2 = box.y1 + pDraw->height; - RegionInit (®ion, &box, 0); - DamageDamageRegion (pDraw, ®ion); - } -} - -static void -_blitBuffers (DrawablePtr pDraw, DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf) -{ - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pDraw->width; - box.y2 = pDraw->height; - REGION_INIT (pScreen, ®ion, &box, 0); - - SECDri2CopyRegion (pDraw, ®ion, pFrontBuf, pBackBuf); -} - -static void -_exchangeBuffers (DrawablePtr pDraw, DRI2FrameEventType type, - DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - DRI2BufferPrivPtr pFrontBufPriv = pFrontBuf->driverPrivate; - DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate; - SECPixmapPriv *pFrontExaPixPriv = exaGetPixmapDriverPrivate (pFrontBufPriv->pPixmap); - SECPixmapPriv *pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap); - - if(pFrontBufPriv->canFlip != pBackBufPriv->canFlip) - { - XDBG_WARNING (MDRI2, "Cannot exchange buffer(0x%x): Front(%d, canFlip:%d), Back(%d, canFlip:%d)\n", - (unsigned int)pDraw->id, pFrontBuf->name, pFrontBufPriv->canFlip, - pBackBuf->name, pBackBufPriv->canFlip); - - return; - } - - /* exchange the buffers - * 1. exchange the bo of the exa pixmap private - * 2. get the name of the front buffer (the name of the back buffer will get next DRI2GetBuffers.) - */ - if (pFrontBufPriv->canFlip) - { - XDBG_RETURN_IF_FAIL(NULL != secFbSwapBo(pSec->pFb, pBackExaPixPriv->bo)); - pFrontBuf->name = _getName (pFrontBufPriv->pPixmap); - } - else - { - tbm_bo_swap(pFrontExaPixPriv->bo, pBackExaPixPriv->bo); - pFrontBuf->name = _getName (pFrontBufPriv->pPixmap); - } - - /*Exchange pixmap owner and sbc*/ - { - XID owner; - CARD64 sbc; - - owner = pFrontExaPixPriv->owner; - sbc = pFrontExaPixPriv->sbc; - - pFrontExaPixPriv->owner = pBackExaPixPriv->owner; - pFrontExaPixPriv->sbc = pBackExaPixPriv->sbc; - - pBackExaPixPriv->owner = owner; - pBackExaPixPriv->sbc = sbc; - } - - /* exchange the index of the available buffer*/ - _exchangeBackBufPixmap(pBackBuf); -} - -static DRI2FrameEventPtr -_newFrame (ClientPtr pClient, DrawablePtr pDraw, - DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf, - DRI2SwapEventPtr swap_func, void *data, RegionPtr pRegion) -{ - DRI2FrameEventPtr pFrameEvent = NULL; - DRI2FrameEventType swap_type = DRI2_NONE; - - /* check and get the swap_type */ - swap_type = _getSwapType (pDraw, pFrontBuf, pBackBuf); - if (swap_type == DRI2_NONE) - return NULL; - - pFrameEvent = calloc (1, sizeof (DRI2FrameEventRec)); - if (!pFrameEvent) - return NULL; - - pFrameEvent->type = swap_type; - pFrameEvent->drawable_id = pDraw->id; - pFrameEvent->client_idx = pClient->index; - pFrameEvent->pClient = pClient; - pFrameEvent->event_complete = swap_func; - pFrameEvent->event_data = data; - pFrameEvent->pFrontBuf = pFrontBuf; - pFrameEvent->pBackBuf = pBackBuf; - - if (pRegion) - { - pFrameEvent->pRegion = RegionCreate(RegionExtents(pRegion), - RegionNumRects(pRegion)); - if (!RegionCopy(pFrameEvent->pRegion, pRegion)) - { - RegionDestroy(pFrameEvent->pRegion); - pFrameEvent->pRegion = NULL; - } - } - else - { - pFrameEvent->pRegion = NULL; - } - - _referenceBufferPriv (pFrontBuf); - _referenceBufferPriv (pBackBuf); - - return pFrameEvent; -} - -static void -_swapFrame (DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent) -{ - switch (pFrameEvent->type) - { - case DRI2_FLIP: - _generateDamage (pDraw, pFrameEvent); - break; - case DRI2_SWAP: - _exchangeBuffers (pDraw, pFrameEvent->type, - pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf); - _generateDamage (pDraw, pFrameEvent); - break; - case DRI2_BLIT: - case DRI2_FB_BLIT: - /* copy the region from back buffer to front buffer */ - _blitBuffers (pDraw, pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf); - break; - default: - /* Unknown type */ - XDBG_WARNING (MDRI2, "%s: unknown swap_type received\n", __func__); - _generateDamage (pDraw, pFrameEvent); - break; - } -} - -static void -_deleteFrame (DrawablePtr pDraw, DRI2FrameEventPtr pEvent) -{ - /* some special case */ - DRI2BufferPrivPtr pFrontBufPriv; - DRI2BufferPrivPtr pBackBufPriv; - - if (pEvent->pBackBuf && pEvent->pFrontBuf) - { - pFrontBufPriv = pEvent->pFrontBuf->driverPrivate; - pBackBufPriv = pEvent->pBackBuf->driverPrivate; - - /* - * Even though pFrontBufPriv->canFlip and pBackBufPriv->canFlip is 1, pEvent->type can have DRI2_BLIT. - * When it requests SECDri2ScheduleSwapWithRegion(), _canFlip(pDraw) is FALSE. So it has DRI2_BLIT type. - * In this case we should change pEvent->type to DRI2_FLIP. So we can call secCrtcRelFlipPixmap() for pEvent->pBackBuf - */ - if( (pFrontBufPriv->canFlip == 1) && (pBackBufPriv->canFlip == 1) ) - { - pEvent->type = DRI2_FLIP; - } - } - - if (pEvent->pBackBuf) - { - /* disuse the backbuffer */ - _disuseBackBufPixmap(pEvent->pBackBuf, pEvent); - - SECDri2DestroyBuffer (pDraw, pEvent->pBackBuf); - } - - if (pEvent->pFrontBuf) - { - SECDri2DestroyBuffer (pDraw, pEvent->pFrontBuf); - } - - if (pEvent->pRegion) - { - RegionDestroy(pEvent->pRegion); - } - - free (pEvent); - pEvent = NULL; -} - -static void -_asyncSwapBuffers (ClientPtr pClient, DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent) -{ - XDBG_DEBUG(MDRI2,"id:0x%x(%d) Client:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - (unsigned int)pDraw->id, pDraw->type, - pClient->index, - pFrameEvent->pFrontBuf->attachment, pFrameEvent->pFrontBuf->name, pFrameEvent->pFrontBuf->flags, - pFrameEvent->pBackBuf->attachment, pFrameEvent->pBackBuf->name, pFrameEvent->pBackBuf->flags); - - _swapFrame (pDraw, pFrameEvent); - - switch (pFrameEvent->type) - { - case DRI2_SWAP: - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, - DRI2_EXCHANGE_COMPLETE, - pFrameEvent->event_complete, pFrameEvent->event_data); - break; - case DRI2_FLIP: - _exchangeBuffers (pDraw, pFrameEvent->type, pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf); - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, - DRI2_FLIP_COMPLETE, - pFrameEvent->event_complete, pFrameEvent->event_data); - break; - case DRI2_BLIT: - case DRI2_FB_BLIT: - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, - DRI2_BLIT_COMPLETE, - pFrameEvent->event_complete, pFrameEvent->event_data); - break; - default: - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, - 0, - pFrameEvent->event_complete, pFrameEvent->event_data); - break; - } -} - -static Bool -_doPageFlip (DrawablePtr pDraw, int crtc_pipe, xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; - SECPixmapPriv *pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap); - - /* Reset buffer position */ - secRenderBoSetPos(pBackExaPixPriv->bo, pDraw->x, pDraw->y); - - if (!secModePageFlip (pScrn, NULL, pEvent, crtc_pipe, pBackExaPixPriv->bo)) - { - XDBG_WARNING (MDRI2, "fail to secModePageFlip\n"); - return FALSE; - } - else - { - XDBG_DEBUG (MDRI2,"doPageFlip id:0x%x(%d) Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), " - "Back(attach:%d, name:%d, flag:0x%x )\n", - (unsigned int)pDraw->id, pDraw->type, - pEvent->pClient->index, crtc_pipe, - pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, - pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags); - - _exchangeBuffers (pDraw, pEvent->type, pEvent->pFrontBuf, pEvent->pBackBuf); - } - - return TRUE; -} - - -static Bool -_scheduleFlip (DrawablePtr pDraw, DRI2FrameEventPtr pEvent, Bool bFlipChain) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - BoxRec box; - - /* main crtc for this drawable shall finally deliver pageflip event */ - int crtc_pipe = secDisplayDrawablePipe (pDraw); - - box.x1 = pDraw->x; - box.y1 = pDraw->y; - box.x2 = box.x1 + pDraw->width; - box.y2 = box.y1 + pDraw->height; - pCrtc = secModeCoveringCrtc (pScrn, &box, NULL, NULL); - - if (!pCrtc) - { - XDBG_WARNING(MDRI2, "fail to get a crtc from a drawable\n"); - DRI2SwapComplete (pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE, - pEvent->event_complete, pEvent->event_data); - _deleteFrame (pDraw, pEvent); - return FALSE; - } - - pEvent->pCrtc = (void*)pCrtc; - pEvent->crtc_pipe = crtc_pipe; - - pCrtcPriv = pCrtc->driver_private; - - DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; - - if (secCrtcIsFlipping(pCrtc) || pBackBufPriv->pFlipEvent) - { - /* Set the pending filp frame_event to the back buffer - * if the previous flip frmae_event is not completed. - */ - if (pBackBufPriv->pFlipEvent) - { - if (pBackBufPriv->pFlipEvent->pPendingEvent) - { - XDBG_WARNING(MDRI2, "waring : pPendingEvent exist.\n"); - return FALSE; - } - pBackBufPriv->pFlipEvent->pPendingEvent = pEvent; - } - - if ( pCrtcPriv->is_fb_blit_flipping || !bFlipChain) - { - secCrtcAddPendingFlip (pCrtc, pEvent); - return TRUE; - } - } - - if (!_doPageFlip (pDraw, crtc_pipe, pCrtc, pEvent)) - XDBG_WARNING (MDRI2, "_doPageflip failed\n"); - else - { - /* set the flip frame_event */ - pBackBufPriv->pFlipEvent = pEvent; - DRI2SwapComplete (pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE, - pEvent->event_complete, pEvent->event_data); - } - - return TRUE; -} - -static void -_saveDrawable (DrawablePtr pDraw, DRI2BufferPtr pBackBuf, DRI2FrameEventType swap_type) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR(pScrn); - char *type[5] = {"none", "swap", "flip", "blit", "fbblit"}; - char file[128]; - PixmapPtr pPix; - DRI2BufferPrivPtr pBackBufPriv; - SECPixmapPriv *pExaPixPriv; - - if (!pSec->dump_info) - return; - - XDBG_RETURN_IF_FAIL (pDraw != NULL); - XDBG_RETURN_IF_FAIL (pBackBuf != NULL); - - pPix = _getPixmapFromDrawable (pDraw); - XDBG_RETURN_IF_FAIL (pPix != NULL); - pBackBufPriv = pBackBuf->driverPrivate; - XDBG_RETURN_IF_FAIL (pBackBufPriv != NULL); - pExaPixPriv = exaGetPixmapDriverPrivate (pPix); - XDBG_RETURN_IF_FAIL (pExaPixPriv != NULL); - - snprintf (file, sizeof(file), "%03d_%s_%lx_%03d.%s", - pSec->flip_cnt, type[swap_type], pDraw->id, pExaPixPriv->dump_cnt, - pSec->dump_type); - - if (!strcmp (pSec->dump_type, "raw")) - { - Bool need_finish = FALSE; - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap); - int size; - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pBackBufPriv->pPixmap, EXA_PREPARE_DEST); - XDBG_RETURN_IF_FAIL (privPixmap->bo != NULL); - } - size = tbm_bo_size (privPixmap->bo); - secUtilDoDumpRaws (pSec->dump_info, &privPixmap->bo, &size, 1, file); - - if (need_finish) - secExaFinishAccess (pBackBufPriv->pPixmap, EXA_PREPARE_DEST); - } - else - secUtilDoDumpPixmaps (pSec->dump_info, pBackBufPriv->pPixmap, file); - - XDBG_DEBUG (MSEC, "dump done\n"); - - pExaPixPriv->dump_cnt++; -} - -static void -_SendSyncDrawDoneMessage(ScreenPtr screen, ClientPtr client, DrawablePtr pDraw) -{ - XDBG_RETURN_IF_FAIL (screen != NULL); - XDBG_RETURN_IF_FAIL (client != NULL); - XDBG_RETURN_IF_FAIL (pDraw != NULL); - - static Atom sync_draw_done = None; - xEvent event; - DeviceIntPtr dev = PickPointer(client); - - XDBG_RETURN_IF_FAIL (dev != NULL); - - if (sync_draw_done == None) - sync_draw_done = MakeAtom ("_E_COMP_SYNC_DRAW_DONE", strlen ("_E_COMP_SYNC_DRAW_DONE"), TRUE); - - memset (&event, 0, sizeof (xEvent)); - event.u.u.type = ClientMessage; - event.u.u.detail = 32; - event.u.clientMessage.u.l.type = sync_draw_done; - event.u.clientMessage.u.l.longs0 = pDraw->id; // window id - event.u.clientMessage.u.l.longs1 = 1; // version - event.u.clientMessage.u.l.longs2 = pDraw->width; // window's width - event.u.clientMessage.u.l.longs3 = pDraw->height; // window's height - - XDBG_DEBUG(MDRI2, "client=%d pDraw->id=%x width=%d height=%d\n", client->index, pDraw->id, pDraw->width, pDraw->height); - - DeliverEventsToWindow(dev, screen->root, &event, 1, SubstructureRedirectMask | SubstructureNotifyMask, NullGrab); -} - -static DRI2BufferPtr -SECDri2CreateBuffer (DrawablePtr pDraw, unsigned int attachment, unsigned int format) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2BufferPtr pBuf = NULL; - DRI2BufferPrivPtr pBufPriv = NULL; - PixmapPtr pPix = NULL; - Bool canFlip = FALSE; - - /* create dri2 buffer */ - pBuf = calloc (1, sizeof (DRI2BufferRec)); - if (pBuf == NULL) - goto fail; - - /* create dri2 buffer private */ - pBufPriv = calloc (1, sizeof (DRI2BufferPrivRec)); - if (pBufPriv == NULL) - goto fail; - - /* check canFlip */ - canFlip = _canFlip (pDraw); - - pBuf->driverPrivate = pBufPriv; - pBuf->format = format; - pBuf->flags = _getBufferFlag (pDraw, canFlip); - - /* check the attachments */ - if (attachment == DRI2BufferFrontLeft) - { - pPix = _getPixmapFromDrawable (pDraw); - pPix->refcnt++; - pBufPriv->canFlip = canFlip; - } - else - { - switch (attachment) - { - case DRI2BufferDepth: - case DRI2BufferDepthStencil: - case DRI2BufferFakeFrontLeft: - case DRI2BufferFakeFrontRight: - case DRI2BufferBackRight: - case DRI2BufferBackLeft: - pPix = _initBackBufPixmap (pBuf, pDraw, canFlip); - if (pPix == NULL) - { - goto fail; - } - break; - default: - XDBG_ERROR(MDRI2, "Unsupported attachmemt:%d\n", attachment); - goto fail; - break; - } - - //Set DRI2 property for selective-composite mode - _setDri2Property (pDraw); - } - - pBuf->cpp = pPix->drawable.bitsPerPixel / 8; - pBuf->attachment = attachment; - pBuf->pitch = pPix->devKind; - pBuf->name = _getName (pPix); - if (pBuf->name == 0) - { - goto fail; - } - - pBufPriv->refcnt = 1; - pBufPriv->attachment = attachment; - pBufPriv->pPixmap = pPix; - pBufPriv->pScreen = pScreen; - - XDBG_DEBUG(MDRI2, "id:0x%x(%d) attach:%d, name:%d, flags:0x%x, flip:%d geo(%dx%d+%d+%d)\n", - pDraw->id, pDraw->type, - pBuf->attachment, pBuf->name, pBuf->flags, pBufPriv->canFlip, - pDraw->width, pDraw->height, pDraw->x, pDraw->y); - - return pBuf; -fail: - XDBG_WARNING(MDRI2, "Failed: id:0x%x(%d) attach:%d,geo(%dx%d+%d+%d)\n", - pDraw->id, pDraw->type, attachment, pDraw->width, pDraw->height, pDraw->x, pDraw->y); - if (pPix) - { -#if USE_XDBG - xDbgLogPListDrawRemoveRefPixmap (pDraw, pPix); -#endif - (*pScreen->DestroyPixmap) (pPix); - } - if (pBufPriv) - free (pBufPriv); - if (pBuf) - free (pBuf); - return NULL; -} - -static void -SECDri2DestroyBuffer (DrawablePtr pDraw, DRI2BufferPtr pBuf) -{ - ScreenPtr pScreen = NULL; - DRI2BufferPrivPtr pBufPriv = NULL; - - if (pBuf == NULL) - return; - - pBufPriv = pBuf->driverPrivate; - pScreen = pBufPriv->pScreen; - - _unreferenceBufferPriv(pBuf); - - if (pBufPriv->refcnt == 0) - { - XDBG_DEBUG(MDRI2, "DestroyBuffer(%d:0x%x) name:%d flip:%d\n", - pDraw?pDraw->type:0, - pDraw?(unsigned int)pDraw->id:0, - pBuf->name, - pBufPriv->canFlip); - - if (pBuf->attachment == DRI2BufferFrontLeft) - { - (*pScreen->DestroyPixmap) (pBufPriv->pPixmap); - } - else - { - _deinitBackBufPixmap(pBuf, pDraw, pBufPriv->canFlip); - } - - pBufPriv->pPixmap = NULL; - free (pBufPriv); - free (pBuf); - } -} - -static void -SECDri2CopyRegion (DrawablePtr pDraw, RegionPtr pRegion, - DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf) -{ - DRI2BufferPrivPtr pSrcBufPriv = pSrcBuf->driverPrivate; - DRI2BufferPrivPtr pDstBufPriv = pDstBuf->driverPrivate; - ScreenPtr pScreen = pDraw->pScreen; - RegionPtr pCopyClip; - GCPtr pGc; - - DrawablePtr pSrcDraw = (pSrcBufPriv->attachment == DRI2BufferFrontLeft) - ? pDraw : &pSrcBufPriv->pPixmap->drawable; - DrawablePtr pDstDraw = (pDstBufPriv->attachment == DRI2BufferFrontLeft) - ? pDraw : &pDstBufPriv->pPixmap->drawable; - - pGc = GetScratchGC (pDstDraw->depth, pScreen); - if (!pGc) - return; - - XDBG_DEBUG(MDRI2,"CopyRegion(%d,0x%x) Dst(attach:%d, name:%d, flag:0x%x), Src(attach:%d, name:%d, flag:0x%x)\n", - pDraw->type, (unsigned int)pDraw->id, - pDstBuf->attachment, pDstBuf->name, pDstBuf->flags, - pSrcBuf->attachment, pSrcBuf->name, pSrcBuf->flags); - - pCopyClip = REGION_CREATE (pScreen, NULL, 0); - REGION_COPY (pScreen, pCopyClip, pRegion); - (*pGc->funcs->ChangeClip) (pGc, CT_REGION, pCopyClip, 0); - ValidateGC (pDstDraw, pGc); - - /* Wait for the scanline to be outside the region to be copied */ - /* [TODO] Something Do ??? */ - - /* It's important that this copy gets submitted before the - * direct rendering client submits rendering for the next - * frame, but we don't actually need to submit right now. The - * client will wait for the DRI2CopyRegion reply or the swap - * buffer event before rendering, and we'll hit the flush - * callback chain before those messages are sent. We submit - * our batch buffers from the flush callback chain so we know - * that will happen before the client tries to render - * again. */ - - (*pGc->ops->CopyArea) (pSrcDraw, pDstDraw, - pGc, - 0, 0, - pDraw->width, pDraw->height, - 0, 0); - (*pGc->funcs->DestroyClip) (pGc); - FreeScratchGC (pGc); -} - - -/* - * ScheduleSwap is responsible for requesting a DRM vblank event for the - * appropriate frame. - * - * In the case of a blit (e.g. for a windowed swap) or buffer exchange, - * the vblank requested can simply be the last queued swap frame + the swap - * interval for the drawable. - * - * In the case of a page flip, we request an event for the last queued swap - * frame + swap interval - 1, since we'll need to queue the flip for the frame - * immediately following the received event. - * - * The client will be blocked if it tries to perform further GL commands - * after queueing a swap, though in the Intel case after queueing a flip, the - * client is free to queue more commands; they'll block in the kernel if - * they access buffers busy with the flip. - * - * When the swap is complete, the driver should call into the server so it - * can send any swap complete events that have been requested. - */ -static int -SECDri2ScheduleSwapWithRegion (ClientPtr pClient, DrawablePtr pDraw, - DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf, - CARD64 *target_msc, CARD64 divisor, CARD64 remainder, - DRI2SwapEventPtr swap_func, void *data, RegionPtr pRegion) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - int pipe = 0; /* default */ - int flip = 0; - DRI2FrameEventPtr pFrameEvent = NULL; - DRI2FrameEventType swap_type = DRI2_SWAP; - CARD64 current_msc; - CARD64 ust, msc; - - pFrameEvent = _newFrame (pClient, pDraw, pFrontBuf, pBackBuf, swap_func, data, pRegion); - if (!pFrameEvent) - { - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, 0, swap_func, data); - return TRUE; - } - - /* Set frame count to back*/ - { - PixmapPtr pPix; - SECPixmapPriv *pExaPixPriv = NULL; - DRI2BufferPrivPtr pBufPriv = pBackBuf->driverPrivate; - CARD64 sbc; - unsigned int pending; - - pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx]; - pExaPixPriv = exaGetPixmapDriverPrivate (pPix); - DRI2GetSBC(pDraw, &sbc, &pending); - pExaPixPriv->owner = pDraw->id; - pExaPixPriv->sbc = sbc+pending; - } - - - swap_type = pFrameEvent->type; - - XDBG_DEBUG (MSEC, "dump_mode(%x) dump_xid(0x%x:0x%x) swap_type(%d)\n", - pSec->dump_mode, pSec->dump_xid, pDraw->id, swap_type); - - if ((pSec->dump_mode & XBERC_DUMP_MODE_DRAWABLE) && - (swap_type != DRI2_NONE && swap_type != DRI2_WAITMSC) && - (pSec->dump_xid == 0 || pSec->dump_xid == pDraw->id)) - _saveDrawable (pDraw, pBackBuf, swap_type); - - /* If lcd is off status, SwapBuffers do not consider the vblank sync. - * The client that launches after lcd is off wants to render the frame - * on the fly. - */ - if (pSec->isLcdOff == TRUE || - pSec->useAsyncSwap == TRUE) - { - _asyncSwapBuffers (pClient, pDraw, pFrameEvent); - _SendSyncDrawDoneMessage(pScreen, pClient, pDraw); - _deleteFrame (pDraw, pFrameEvent); - return TRUE; - } - - pipe = secDisplayDrawablePipe (pDraw); - - /* check if the pipe is -1 */ - if (pipe == -1) - { - /* if swap_type is DRI2_FLIP, fall into the async swap */ - if (swap_type == DRI2_FLIP) - { - XDBG_WARNING(MDRI2, "Warning: flip pipe is -1 \n"); - _asyncSwapBuffers (pClient, pDraw, pFrameEvent); - _SendSyncDrawDoneMessage(pScreen, pClient, pDraw); - _deleteFrame (pDraw, pFrameEvent); - return TRUE; - } - } - - /* Truncate to match kernel interfaces; means occasional overflow - * misses, but that's generally not a big deal */ - *target_msc &= 0xffffffff; - divisor &= 0xffffffff; - remainder &= 0xffffffff; - - /* Get current count */ - if (!secDisplayGetCurMSC (pScrn, pipe, &ust, &msc)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "fail to get current_msc\n"); - goto blit_fallback; - } - current_msc = msc; - - /* Flips need to be submitted one frame before */ - if (swap_type == DRI2_FLIP) - { - flip = 1; - } - - /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. - * Do it early, so handling of different timing constraints - * for divisor, remainder and msc vs. target_msc works. - */ - if (*target_msc > 0) - *target_msc -= flip; - - /* - * If divisor is zero, or current_msc is smaller than target_msc - * we just need to make sure target_msc passes before initiating - * the swap. - */ - if (divisor == 0 || current_msc < *target_msc) - { - /* If target_msc already reached or passed, set it to - * current_msc to ensure we return a reasonable value back - * to the caller. This makes swap_interval logic more robust. - */ - if (current_msc >= *target_msc) - *target_msc = current_msc; - - if (!secDisplayVBlank (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); - goto blit_fallback; - } - - pFrameEvent->frame = (unsigned int )*target_msc; - - XDBG_DEBUG(MDRI2,"id:0x%x(%d) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), " - "Back(attach:%d, name:%d, flag:0x%x )\n", - (unsigned int)pDraw->id, pDraw->type, - swap_type, pClient->index, pipe, - pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags, - pBackBuf->attachment, pBackBuf->name, pBackBuf->flags); - - if (pFrameEvent->pRegion) - { - BoxPtr pBox = RegionRects(pFrameEvent->pRegion); - int nBox = RegionNumRects(pFrameEvent->pRegion); - - while (nBox--) - { - XDBG_DEBUG(MDRI2,"Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ", - nBox, pBox->x1, pBox->y1, pBox->x2, pBox->y2); - pBox++; - } - } - - _swapFrame (pDraw, pFrameEvent); - _SendSyncDrawDoneMessage(pScreen, pClient, pDraw); - - return TRUE; - } - - /* - * If we get here, target_msc has already passed or we don't have one, - * and we need to queue an event that will satisfy the divisor/remainder - * equation. - */ - *target_msc = current_msc - (current_msc % divisor) + - remainder; - - /* - * If the calculated deadline vbl.request.sequence is smaller than - * or equal to current_msc, it means we've passed the last point - * when effective onset frame seq could satisfy - * seq % divisor == remainder, so we need to wait for the next time - * this will happen. - - * This comparison takes the 1 frame swap delay in pageflipping mode - * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay - * if we are blitting/exchanging instead of flipping. - */ - if (*target_msc <= current_msc) - *target_msc += divisor; - - /* Account for 1 frame extra pageflip delay if flip > 0 */ - *target_msc -= flip; - - if (!secDisplayVBlank (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); - goto blit_fallback; - } - - pFrameEvent->frame = *target_msc; - - XDBG_DEBUG(MDRI2,"ScaduleSwap_ex(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - pDraw->type, (unsigned int)pDraw->id, - swap_type, pClient->index, pipe, - pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags, - pBackBuf->attachment, pBackBuf->name, pBackBuf->flags); - - _swapFrame (pDraw, pFrameEvent); - _SendSyncDrawDoneMessage(pScreen, pClient, pDraw); - - return TRUE; - -blit_fallback: - XDBG_WARNING(MDRI2,"blit_fallback(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - pDraw->type, (unsigned int)pDraw->id, - swap_type, pClient->index, pipe, - pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags, - pBackBuf->attachment, pBackBuf->name, pBackBuf->flags); - - _blitBuffers (pDraw, pFrontBuf, pBackBuf); - - DRI2SwapComplete (pClient, pDraw, 0, 0, 0, DRI2_BLIT_COMPLETE, swap_func, data); - _SendSyncDrawDoneMessage(pScreen, pClient, pDraw); - - if (pFrameEvent) - { - _deleteFrame (pDraw, pFrameEvent); - } - *target_msc = 0; /* offscreen, so zero out target vblank count */ - return TRUE; -} - - -/* - * Get current frame count and frame count timestamp, based on drawable's - * crtc. - */ -static int -SECDri2GetMSC (DrawablePtr pDraw, CARD64 *ust, CARD64 *msc) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int pipe; - - pipe = secDisplayDrawablePipe (pDraw); - - /* Get current count */ - if (!secDisplayGetCurMSC (pScrn, pipe, ust, msc)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "fail to get current_msc\n"); - return FALSE; - } - - return TRUE; -} - -/* - * Request a DRM event when the requested conditions will be satisfied. - * - * We need to handle the event and ask the server to wake up the client when - * we receive it. - */ -static int -SECDri2ScheduleWaitMSC (ClientPtr pClient, DrawablePtr pDraw, - CARD64 target_msc, CARD64 divisor, CARD64 remainder) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DRI2FrameEventPtr wait_info = NULL; - CARD64 current_msc; - CARD64 ust, msc; - - int pipe = 0; - - /* Truncate to match kernel interfaces; means occasional overflow - * misses, but that's generally not a big deal */ - target_msc &= 0xffffffff; - divisor &= 0xffffffff; - remainder &= 0xffffffff; - - /* Drawable not visible, return immediately */ - pipe = secDisplayDrawablePipe (pDraw); - if (pipe == -1) - goto out_complete; - - wait_info = calloc (1, sizeof (DRI2FrameEventRec)); - if (!wait_info) - goto out_complete; - - wait_info->drawable_id = pDraw->id; - wait_info->pClient = pClient; - wait_info->type = DRI2_WAITMSC; - - /* Get current count */ - if (!secDisplayGetCurMSC (pScrn, pipe, &ust, &msc)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "fail to get current_msc\n"); - goto out_complete; - } - current_msc = msc; - - /* - * If divisor is zero, or current_msc is smaller than target_msc, - * we just need to make sure target_msc passes before waking up the - * client. - */ - if (divisor == 0 || current_msc < target_msc) - { - /* If target_msc already reached or passed, set it to - * current_msc to ensure we return a reasonable value back - * to the caller. This keeps the client from continually - * sending us MSC targets from the past by forcibly updating - * their count on this call. - */ - if (current_msc >= target_msc) - target_msc = current_msc; - - /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */ - if (!secDisplayVBlank (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); - goto out_complete; - } - - wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in secDisplayVBlank */ - DRI2BlockClient (pClient, pDraw); - return TRUE; - } - - /* - * If we get here, target_msc has already passed or we don't have one, - * so we queue an event that will satisfy the divisor/remainder equation. - */ - target_msc = current_msc - (current_msc % divisor) + - remainder; - - /* - * If calculated remainder is larger than requested remainder, - * it means we've passed the last point where - * seq % divisor == remainder, so we need to wait for the next time - * that will happen. - */ - if ((current_msc % divisor) >= remainder) - target_msc += divisor; - - /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */ - if (!secDisplayVBlank (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n"); - goto out_complete; - } - - wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in secDisplayVBlank */ - DRI2BlockClient (pClient, pDraw); - - return TRUE; - -out_complete: - free(wait_info); - DRI2WaitMSCComplete (pClient, pDraw, target_msc, 0, 0); - return TRUE; -} - -static int -SECDri2AuthMagic (int fd, uint32_t magic) -{ - int ret; - ret = drmAuthMagic (fd, (drm_magic_t) magic); - - XDBG_TRACE(MDRI2, "AuthMagic: %d\n", ret); - - return ret; -} - -static void -SECDri2ReuseBufferNotify (DrawablePtr pDraw, DRI2BufferPtr pBuf) -{ - DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; - - if(!_resetBufPixmap(pDraw, pBuf)) - { - DRI2BufferFlags *flags = (DRI2BufferFlags*)&pBuf->flags; - - pBuf->name = _getName(pBufPriv->pPixmap); - flags->flags = _getBufferFlag(pDraw, pBufPriv->canFlip); - flags->data.is_reused = 1; - - /*Set reuse index*/ - if (pBuf->attachment != DRI2BufferFrontLeft) - { - DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate; - PixmapPtr pPix; - SECPixmapPriv *pExaPixPriv = NULL; - CARD64 sbc; - unsigned int pending; - - pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx]; - pExaPixPriv = exaGetPixmapDriverPrivate (pPix); - - DRI2GetSBC(pDraw, &sbc, &pending); - /*Get current count */ - if(pExaPixPriv->owner == pDraw->id) - { - unsigned int idx_reuse = sbc+pending - pExaPixPriv->sbc + 1; - if(idx_reuse > pBufPriv->num_buf + 1) - { - flags->data.idx_reuse = 0; - } - else - { - flags->data.idx_reuse = idx_reuse; - } - } - else - { - flags->data.idx_reuse = 0; - } - } - else - { - flags->data.idx_reuse = 0; - } - } - - XDBG_DEBUG(MDRI2, "id:0x%x(%d) attach:%d, name:%d, flags:0x%x, flip:%d, geo(%dx%d+%d+%d)\n", - pDraw->id, pDraw->type, - pBuf->attachment, pBuf->name, pBuf->flags, pBufPriv->canFlip, - pDraw->width, pDraw->height, pDraw->x, pDraw->y); -} - -static void -_secDri2ProcessPending (xf86CrtcPtr pCrtc, ScreenPtr pScreen, - unsigned int frame, unsigned int tv_sec, unsigned int tv_usec) -{ - DRI2BufferPrivPtr pBackBufPriv = NULL; - DrawablePtr pCrtcPendingDraw = NULL; - DRI2FrameEventPtr pCrtcPendingFlip = NULL; - - pCrtcPendingFlip = secCrtcGetFirstPendingFlip (pCrtc); - if (pCrtcPendingFlip) - { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - secCrtcRemovePendingFlip (pCrtc, pCrtcPendingFlip); - - if (pCrtcPendingFlip->drawable_id) - dixLookupDrawable (&pCrtcPendingDraw, pCrtcPendingFlip->drawable_id, - serverClient, M_ANY, DixWriteAccess); - if (!pCrtcPendingDraw) - { - XDBG_WARNING (MDRI2, "pCrtcPendingDraw is null.\n"); - _deleteFrame (pCrtcPendingDraw, pCrtcPendingFlip); - return; - } - else - { - if(pSec->isLcdOff) - { - XDBG_WARNING (MDRI2, "LCD OFF : Request a pageflip pending even if the lcd is off.\n"); - - _exchangeBuffers(pCrtcPendingDraw, DRI2_FLIP, pCrtcPendingFlip->pFrontBuf, pCrtcPendingFlip->pBackBuf); - - DRI2SwapComplete (pCrtcPendingFlip->pClient, pCrtcPendingDraw, - frame, tv_sec, tv_usec, - 0, pCrtcPendingFlip->event_complete, - pCrtcPendingFlip->event_data); - - pBackBufPriv = pCrtcPendingFlip->pBackBuf->driverPrivate; - pBackBufPriv->pFlipEvent = NULL; - _deleteFrame (pCrtcPendingDraw, pCrtcPendingFlip); - } - else - { - if(!_scheduleFlip (pCrtcPendingDraw, pCrtcPendingFlip, TRUE)) - { - XDBG_WARNING (MDRI2, "fail to _scheduleFlip in secDri2FlipEventHandler\n"); - } - } - } - } - -} - -void -secDri2FlipEventHandler (unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data, Bool flip_failed) -{ - DRI2FrameEventPtr pEvent = event_data; - DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate; - ScreenPtr pScreen = pBackBufPriv->pScreen; - DrawablePtr pDraw = NULL; - ClientPtr pClient = pEvent->pClient; - xf86CrtcPtr pCrtc = (xf86CrtcPtr) pEvent->pCrtc; - - if (pEvent->drawable_id) - dixLookupDrawable (&pDraw, pEvent->drawable_id, serverClient, M_ANY, DixWriteAccess); - if (!pDraw) - { - XDBG_WARNING (MDRI2,"pDraw is null... Client:%d pipe:%d " - "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - pClient->index, pBackBufPriv->pipe, - pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, - pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags); - _secDri2ProcessPending (pCrtc, pScreen, frame, tv_sec, tv_usec); - _deleteFrame (pDraw, pEvent); - return; - } - - XDBG_TRACE (MDRI2,"FlipEvent(%d,0x%x) Client:%d pipe:%d " - "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - pDraw->type, (unsigned int)pDraw->id, pClient->index, pBackBufPriv->pipe, - pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, - pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags); - - /* check the failure of the pageflip */ - if (flip_failed) - { - _exchangeBuffers(pDraw, DRI2_FLIP, pEvent->pFrontBuf, pEvent->pBackBuf); - - DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec, - 0, pEvent->event_complete, pEvent->event_data); - _deleteFrame (pDraw, pEvent); - return; - } - - assert (pBackBufPriv->pFlipEvent == pEvent); - pBackBufPriv->pFlipEvent = NULL; - _deleteFrame (pDraw, pEvent); - - /* get the next pending flip event */ - _secDri2ProcessPending (pCrtc, pScreen, frame, tv_sec, tv_usec); - -} - -void -secDri2FrameEventHandler (unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - DRI2FrameEventPtr pEvent = event_data; - DrawablePtr pDraw = NULL; - int status; - - status = dixLookupDrawable (&pDraw, pEvent->drawable_id, serverClient, - M_ANY, DixWriteAccess); - if (status != Success) - { - XDBG_WARNING(MDRI2,"drawable is not found\n"); - - _deleteFrame (NULL, pEvent); - return; - } - - XDBG_RETURN_IF_FAIL(pEvent->pFrontBuf != NULL); - XDBG_RETURN_IF_FAIL(pEvent->pBackBuf != NULL); - - switch (pEvent->type) - { - case DRI2_FLIP: - if(!_scheduleFlip (pDraw, pEvent, FALSE)) - XDBG_WARNING(MDRI2, "pageflip fails.\n"); - return; - break; - case DRI2_SWAP: - DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec, - DRI2_EXCHANGE_COMPLETE, pEvent->event_complete, pEvent->event_data); - break; - case DRI2_BLIT: - case DRI2_FB_BLIT: - DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec, - DRI2_BLIT_COMPLETE, pEvent->event_complete, pEvent->event_data); - break; - case DRI2_NONE: - DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec, - 0, pEvent->event_complete, pEvent->event_data); - break; - case DRI2_WAITMSC: - DRI2WaitMSCComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec); - break; - default: - /* Unknown type */ - break; - } - - XDBG_DEBUG (MDRI2,"FrameEvent(%d,0x%x) SwapType:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n", - pDraw->type, (unsigned int)pDraw->id, pEvent->type, - pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags, - pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags); - - - _deleteFrame (pDraw, pEvent); -} - - -Bool secDri2Init (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - SECExaPrivPtr pExaPriv = SECEXAPTR (pSec); - DRI2InfoRec info; - int ret; - const char *driverNames[1]; - - info.driverName = "exynos-drm"; - info.deviceName = pSec->drm_device_name; - info.version = 106; - info.fd = pSec->drm_fd; - info.CreateBuffer = SECDri2CreateBuffer; - info.DestroyBuffer = SECDri2DestroyBuffer; - info.CopyRegion = SECDri2CopyRegion; - info.ScheduleSwap = NULL; - info.GetMSC = SECDri2GetMSC; - info.ScheduleWaitMSC = SECDri2ScheduleWaitMSC; - info.AuthMagic = SECDri2AuthMagic; - info.ReuseBufferNotify = SECDri2ReuseBufferNotify; - info.SwapLimitValidate = NULL; - /* added in version 7 */ - info.GetParam = NULL; - - /* added in version 8 */ - /* AuthMagic callback which passes extra context */ - /* If this is NULL the AuthMagic callback is used */ - /* If this is non-NULL the AuthMagic callback is ignored */ - info.AuthMagic2 = NULL; - - /* added in version 9 */ - info.CreateBuffer2 = NULL; - info.DestroyBuffer2 = NULL; - info.CopyRegion2 = NULL; - - /* add in for Tizen extension */ - info.ScheduleSwapWithRegion = SECDri2ScheduleSwapWithRegion; - - info.Wait = NULL; - info.numDrivers = 1; - info.driverNames = driverNames; - driverNames[0] = info.driverName; - - ret = DRI2ScreenInit (pScreen, &info); - if (ret == FALSE) - { - return FALSE; - } - - /* set the number of the flip back buffers */ - pExaPriv->flip_backbufs = pSec->flip_bufs - 1; - - //xDbgLogSetLevel (MDRI2, 0); - return ret; -} - -void secDri2Deinit (ScreenPtr pScreen) -{ - DRI2CloseScreen (pScreen); -} diff --git a/src/accel/sec_exa.c b/src/accel/sec_exa.c deleted file mode 100755 index c62ede5..0000000 --- a/src/accel/sec_exa.c +++ /dev/null @@ -1,664 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <fcntl.h> -#include <sys/mman.h> -#include "sec.h" -#include "sec_accel.h" -#include "sec_display.h" -#include "sec_crtc.h" -#include <X11/Xatom.h> -#include "windowstr.h" -#include "fbpict.h" -#include "sec_util.h" -#include "sec_converter.h" - -static void -_setScreenRotationProperty (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - ScreenPtr pScreen = pScrn->pScreen; - Atom atom_screen_rotaion; - WindowPtr pWin = pScreen->root; - int rc; - atom_screen_rotaion = MakeAtom ("X_SCREEN_ROTATION", 17, TRUE); - unsigned int rotation = (unsigned int) pSec->rotate; - - rc = dixChangeWindowProperty (serverClient, - pWin, atom_screen_rotaion, XA_CARDINAL, 32, - PropModeReplace, 1, &rotation, FALSE); - if (rc != Success) - XDBG_ERROR (MEXAS, "failed : set X_SCREEN_ROTATION to %d\n", rotation); -} - -static void -_secExaBlockHandler (pointer blockData, OSTimePtr pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[0]; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - /* add screen rotation property to the root window */ - _setScreenRotationProperty (pScrn); - - RemoveBlockAndWakeupHandlers (_secExaBlockHandler /*blockHandler*/, - (void*)NULL /*wakeupHandler*/, - (void*)NULL /*blockData*/); -} - -static void -SECExaWaitMarker (ScreenPtr pScreen, int marker) -{ -} - -static Bool -SECExaPrepareAccess (PixmapPtr pPix, int index) -{ - ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPix); - int opt = TBM_OPTION_READ; - tbm_bo_handle bo_handle; - - XDBG_RETURN_VAL_IF_FAIL((privPixmap != NULL), FALSE); - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB && - privPixmap->bo == NULL) - { - privPixmap->bo = secRenderBoRef(pSec->pFb->default_bo); - XDBG_RETURN_VAL_IF_FAIL((privPixmap->bo != NULL), FALSE); - XDBG_TRACE(MEXAS, " FRAMEBUFFER\n"); - } - else - { - XDBG_TRACE(MEXAS, "\n"); - } - - if(privPixmap->bo) - { - if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) - opt |= TBM_OPTION_WRITE; - - bo_handle = tbm_bo_map(privPixmap->bo, TBM_DEVICE_CPU, opt); - pPix->devPrivate.ptr = bo_handle.ptr; - } - else - { - if(privPixmap->pPixData) - { - pPix->devPrivate.ptr = privPixmap->pPixData; - } - } - - XDBG_DEBUG (MEXA, "pix:%p index:%d hint:%d ptr:%p\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr); - return TRUE; -} - -static void -SECExaFinishAccess (PixmapPtr pPix, int index) -{ - XDBG_TRACE(MEXAS, "\n"); - if (!pPix) - return; - - SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - - if(privPixmap == NULL) - return; - - if (privPixmap->bo) - tbm_bo_unmap (privPixmap->bo); - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB) - { - secRenderBoUnref(privPixmap->bo); - privPixmap->bo = NULL; - } - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) - secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER)); - - pPix->devPrivate.ptr = NULL; - XDBG_DEBUG (MEXA, "pix:%p index:%d hint:%d ptr:%p\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr); -} - -static void * -SECExaCreatePixmap (ScreenPtr pScreen, int size, int align) -{ - SECPixmapPriv *privPixmap = calloc (1, sizeof (SECPixmapPriv)); - - return privPixmap; -} - -static void -SECExaDestroyPixmap (ScreenPtr pScreen, void *driverPriv) -{ - XDBG_RETURN_IF_FAIL (driverPriv != NULL); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - SECPixmapPriv *privPixmap = (SECPixmapPriv*)driverPriv; - - XDBG_TRACE (MEXA, "DESTROY_PIXMAP : usage_hint:0x%x\n", privPixmap->usage_hint); - - switch(privPixmap->usage_hint) - { - case CREATE_PIXMAP_USAGE_FB: - pSec->pix_fb = pSec->pix_fb - privPixmap->size; - secRenderBoUnref (privPixmap->bo); - privPixmap->bo = NULL; - break; - case CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK: - pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back - privPixmap->size; - secRenderBoUnref (privPixmap->bo); - privPixmap->bo = NULL; - break; - case CREATE_PIXMAP_USAGE_SUB_FB: - /* TODO ???? */ - pSec->pix_sub_fb = pSec->pix_sub_fb - privPixmap->size; - privPixmap->bo = NULL; - break; - case CREATE_PIXMAP_USAGE_OVERLAY: - /* TODO ???? */ - pSec->pix_overlay = pSec->pix_overlay - privPixmap->size; - secRenderBoUnref (privPixmap->bo); - privPixmap->bo = NULL; - - if (privPixmap->ovl_layer) - { - secLayerUnref (privPixmap->ovl_layer); - privPixmap->ovl_layer = NULL; - } - - pSec->ovl_drawable = NULL; - - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pScrn, 0, 0, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay); - secCrtcOverlayRef (pCrtc, FALSE); - - break; - case CREATE_PIXMAP_USAGE_DRI2_BACK: - pSec->pix_dri2_back = pSec->pix_dri2_back - privPixmap->size; - tbm_bo_unref (privPixmap->bo); - privPixmap->bo = NULL; - break; - case CREATE_PIXMAP_USAGE_BACKING_PIXMAP: - pSec->pix_backing_pixmap = pSec->pix_backing_pixmap - privPixmap->size; - tbm_bo_unref (privPixmap->bo); - privPixmap->bo = NULL; - break; - default: - pSec->pix_normal = pSec->pix_normal - privPixmap->size; - tbm_bo_unref (privPixmap->bo); - privPixmap->bo = NULL; - break; - } - - /* free pixmap private */ - free (privPixmap); -} - -static Bool -SECExaModifyPixmapHeader (PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, pointer pPixData) -{ - XDBG_RETURN_VAL_IF_FAIL(pPixmap, FALSE); - - ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - SECPixmapPriv * privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPixmap); - long lSizeInBytes; - - /* set the default headers of the pixmap */ - miModifyPixmapHeader (pPixmap, width, height, depth, bitsPerPixel, - devKind, pPixData); - - /* screen pixmap : set a framebuffer pixmap */ - if (pPixData == (void*)ROOT_FB_ADDR) - { - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - pSec->pix_fb = pSec->pix_fb + lSizeInBytes; - pPixmap->usage_hint = CREATE_PIXMAP_USAGE_FB; - privPixmap->usage_hint = pPixmap->usage_hint; - privPixmap->isFrameBuffer = TRUE; - privPixmap->bo = NULL; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - } - - if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_SUB_FB) - { - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - pSec->pix_sub_fb = pSec->pix_sub_fb + lSizeInBytes; - - pPixmap->devPrivate.ptr = NULL; - privPixmap->usage_hint = pPixmap->usage_hint; - privPixmap->isSubFramebuffer = TRUE; - privPixmap->bo = (tbm_bo)pPixData; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_SUB_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - } - else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) - { - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - SECLayer *layer; - SECVideoBuf *vbuf; - int width, height; - - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - pSec->pix_overlay = pSec->pix_overlay + lSizeInBytes; - - privPixmap->usage_hint = pPixmap->usage_hint; - privPixmap->size = lSizeInBytes; - - pSec->ovl_drawable = &pPixmap->drawable; - - /* change buffer if needed. */ - xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pScrn, 0, 0, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay); - secCrtcOverlayRef (pCrtc, TRUE); - - layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER); - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - - vbuf = secLayerGetBuffer (layer); - XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE); - - width = vbuf->width; - height = vbuf->height; - - if (width != pSecMode->main_lcd_mode.hdisplay || height != pSecMode->main_lcd_mode.vdisplay) - { - XDBG_ERROR (MEXA, "layer size(%d,%d) should be (%dx%d). pixmap(%d,%d %dx%d)\n", - width, height, pSecMode->main_lcd_mode.hdisplay, pSecMode->main_lcd_mode.vdisplay, - pPixmap->screen_x, pPixmap->screen_y, pPixmap->drawable.width, pPixmap->drawable.height); - return FALSE; - } - - privPixmap->bo = secRenderBoRef (vbuf->bo[0]); - - privPixmap->ovl_layer = secLayerRef (layer); - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_OVERLAY(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - } - else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_XVIDEO) - { - SECCvtProp prop = {0,}; - tbm_bo old_bo = privPixmap->bo; - - prop.id = FOURCC_RGB32; - prop.width = width; - prop.height = height; - prop.crop.width = width; - prop.crop.height = height; - - secCvtEnsureSize (NULL, &prop); - - privPixmap->bo = secRenderBoCreate(pScrn, prop.width, prop.height); - if (!privPixmap->bo) - { - XDBG_ERROR (MEXA, "Error: cannot create a xvideo buffer\n"); - privPixmap->bo = old_bo; - return FALSE; - } - - pPixmap->devKind = prop.width * 4; - - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back + lSizeInBytes; - - privPixmap->usage_hint = pPixmap->usage_hint; - privPixmap->isFrameBuffer = FALSE; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_XVIDEO(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, privPixmap->bo, pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - if (old_bo) - tbm_bo_unref (old_bo); - - return TRUE; - } - else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK) - { - privPixmap->bo = secRenderBoCreate(pScrn, width, height); - if (!privPixmap->bo) - { - XDBG_ERROR (MEXA, "Error: cannot create a back flip buffer\n"); - return FALSE; - } - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back + lSizeInBytes; - - privPixmap->usage_hint = pPixmap->usage_hint; - privPixmap->isFrameBuffer = TRUE; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_DRI2_FLIP_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, privPixmap->bo, pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - } - else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_BACK) - { - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - privPixmap->usage_hint = pPixmap->usage_hint; - - privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT); - if (privPixmap->bo == NULL) - { - XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes); - return FALSE; - } - pSec->pix_dri2_back = pSec->pix_dri2_back + lSizeInBytes; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_DRI2_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, privPixmap->bo, - pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - - } - else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) - { - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - privPixmap->usage_hint = pPixmap->usage_hint; - - privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT); - if (privPixmap->bo == NULL) - { - XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes); - return FALSE; - } - pSec->pix_backing_pixmap = pSec->pix_backing_pixmap + lSizeInBytes; - privPixmap->size = lSizeInBytes; - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_BACKING_PIXMAP(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n", - pPixmap, privPixmap->bo, - pPixmap->drawable.x, pPixmap->drawable.y, width, height); - - return TRUE; - - } - - if(privPixmap->bo != NULL) - { - tbm_bo_unref (privPixmap->bo); - privPixmap->bo = NULL; - } - - lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind; - privPixmap->usage_hint = pPixmap->usage_hint; - - /* pPixData is also set for text glyphs or SHM-PutImage */ - if (pPixData) - { - privPixmap->pPixData = pPixData; - /* - privPixmap->bo = tbm_bo_attach(pSec->tbm_bufmgr, - NULL, - TBM_MEM_USERPTR, - lSizeInBytes, (unsigned int)pPixData); - */ - } - else - { - /* create the pixmap private memory */ - if (lSizeInBytes && privPixmap->bo == NULL) - { - privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT); - if (privPixmap->bo == NULL) - { - XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes); - return FALSE; - } - } - pSec->pix_normal = pSec->pix_normal + lSizeInBytes; - } - - XDBG_TRACE (MEXA, "CREATE_PIXMAP_NORMAL(%p) : bo:%p, pPixData:%p (%dx%d+%d+%d)\n", - pPixmap, privPixmap->bo, pPixData, - width, height, - pPixmap->drawable.x, pPixmap->drawable.y); - - return TRUE; -} - -static Bool -SECExaPixmapIsOffscreen (PixmapPtr pPix) -{ - return TRUE; -} - -Bool -secExaInit (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ExaDriverPtr pExaDriver; - SECPtr pSec = SECPTR (pScrn); - SECExaPrivPtr pExaPriv; - unsigned int cpp = 4; - - /* allocate the pExaPriv private */ - pExaPriv = calloc (1, sizeof (*pExaPriv)); - if (pExaPriv == NULL) - return FALSE; - - /* allocate the EXA driver private */ - pExaDriver = exaDriverAlloc(); - if (pExaDriver == NULL) - { - free (pExaPriv); - return FALSE; - } - - /* version of exa */ - pExaDriver->exa_major = EXA_VERSION_MAJOR; - pExaDriver->exa_minor = EXA_VERSION_MINOR; - - /* setting the memory stuffs */ - pExaDriver->memoryBase = (void*)ROOT_FB_ADDR; - pExaDriver->memorySize = pScrn->videoRam * 1024; - pExaDriver->offScreenBase = pScrn->displayWidth * cpp * pScrn->virtualY; - - pExaDriver->maxX = 1 << 16; - pExaDriver->maxY = 1 << 16; - pExaDriver->pixmapOffsetAlign = 0; - pExaDriver->pixmapPitchAlign = 8; - pExaDriver->flags = (EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS - |EXA_SUPPORTS_OFFSCREEN_OVERLAPS - |EXA_SUPPORTS_PREPARE_AUX); - - pExaDriver->WaitMarker = SECExaWaitMarker; - pExaDriver->PrepareAccess = SECExaPrepareAccess; - pExaDriver->FinishAccess = SECExaFinishAccess; - - pExaDriver->CreatePixmap = SECExaCreatePixmap; - pExaDriver->DestroyPixmap = SECExaDestroyPixmap; - pExaDriver->ModifyPixmapHeader = SECExaModifyPixmapHeader; - pExaDriver->PixmapIsOffscreen = SECExaPixmapIsOffscreen; - - /* call init function */ - if (pSec->is_sw_exa) - { - if (secExaSwInit (pScreen, pExaDriver)) - { - XDBG_INFO (MEXA, "Initialized SEC SW_EXA acceleration OK !\n"); - } - else - { - free (pExaPriv); - free (pExaDriver); - FatalError ("Failed to initialize SW_EXA\n"); - return FALSE; - } - } - else - { - if (secExaG2dInit (pScreen, pExaDriver)) - { - XDBG_INFO (MEXA, "Initialized SEC HW_EXA acceleration OK !\n"); - } - else - { - free (pExaPriv); - free (pExaDriver); - FatalError ("Failed to initialize HW_EXA\n"); - return FALSE; - } - } - - /* exa driver init with exa driver private */ - if (exaDriverInit (pScreen, pExaDriver)) - { - pExaPriv->pExaDriver = pExaDriver; - pSec->pExaPriv = pExaPriv; - } - else - { - free (pExaDriver); - free (pExaPriv); - FatalError ("Failed to initialize EXA...exaDriverInit\n"); - return FALSE; - } - - /* block handler */ - RegisterBlockAndWakeupHandlers (_secExaBlockHandler /*blockHandler*/, - NULL /*wakeupHandler*/, - NULL /*blockData*/); - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "EXA driver is Loaded successfully\n"); - - return TRUE; -} - -void -secExaDeinit (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - /* call Fini function */ - if (pSec->is_sw_exa) - { - secExaSwDeinit (pScreen); - XDBG_INFO (MEXA, "Finish SW EXA acceleration.\n"); - } - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "EXA driver is UnLoaded successfully\n"); -} - -Bool -secExaPrepareAccess (PixmapPtr pPix, int index) -{ - return SECExaPrepareAccess (pPix, index); -} - -void -secExaFinishAccess (PixmapPtr pPix, int index) -{ - SECExaFinishAccess (pPix, index); -} - -int -secExaScreenAsyncSwap (ScreenPtr pScreen, int enable) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - if(enable == -1) - return pSec->useAsyncSwap; - - if ( enable == 1) - pSec->useAsyncSwap = TRUE; - else - pSec->useAsyncSwap = FALSE; - - return pSec->useAsyncSwap; -} - -int -secExaScreenSetScrnPixmap (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - PixmapPtr pPix = (*pScreen->GetScreenPixmap) (pScreen); - unsigned int pitch = pScrn->virtualX * 4; - (*pScreen->ModifyPixmapHeader) (pPix, pScrn->virtualX, pScrn->virtualY, - -1, -1, pitch, (void*)ROOT_FB_ADDR); - pScrn->displayWidth = pitch / 4; - return 1; -} - -Bool -secExaMigratePixmap (PixmapPtr pPix, tbm_bo bo) -{ - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPix); - - tbm_bo_unref (privPixmap->bo); - privPixmap->bo = tbm_bo_ref(bo); - - return TRUE; -} - -tbm_bo -secExaPixmapGetBo (PixmapPtr pPix) -{ - tbm_bo bo = NULL; - SECPixmapPriv *pExaPixPriv = NULL; - - if (pPix == NULL) - return 0; - - pExaPixPriv = exaGetPixmapDriverPrivate (pPix); - if (pExaPixPriv == NULL) - return 0; - - bo = pExaPixPriv->bo; - - return bo; -} diff --git a/src/accel/sec_exa_g2d.c b/src/accel/sec_exa_g2d.c deleted file mode 100755 index c0e4858..0000000 --- a/src/accel/sec_exa_g2d.c +++ /dev/null @@ -1,1726 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 "sec.h" -#include "sec_accel.h" -#include "sec_util.h" -#include "sec_layer.h" -#include "exa.h" -#include "fbpict.h" -#include "neonmem.h" -#include "g2d/fimg2d.h" - -#define DO(x) ((x.bDo==DO_DRAW_NONE)?"SKIP": \ - ((x.bDo==DO_DRAW_SW)?"SW":"HW")) - -#define PIXINFO(pPixmap) if(pPixmap) { \ - XDBG_TRACE(MEXAH, "%s:%p(0x%x) %dx%d depth:%d(%d) pitch:%d\n", \ - #pPixmap, \ - pPixmap, ID(pPixmap), \ - pPixmap->drawable.width, pPixmap->drawable.height, \ - pPixmap->drawable.depth, \ - pPixmap->drawable.bitsPerPixel, \ - pPixmap->devKind); \ - } - -#define PICINFO(pPic) if(pPic) { \ - XDBG_TRACE(MEXAH, "%s, draw:%p, repeat:%d(%d), ca:%d, srcPict:%p\n", \ - #pPic, \ - pPic->pDrawable, \ - pPic->repeat, pPic->repeatType, \ - pPic->componentAlpha, \ - pPic->pSourcePict); \ - if(pPic->transform) { \ - XDBG_TRACE("EXA2D", "\t0x%08x 0x%08x 0x%08x\n", \ - pPic->transform->matrix[0][0], \ - pPic->transform->matrix[0][1], \ - pPic->transform->matrix[0][2]); \ - XDBG_TRACE("EXA2D", "\t0x%08x 0x%08x 0x%08x\n", \ - pPic->transform->matrix[1][0], \ - pPic->transform->matrix[1][1], \ - pPic->transform->matrix[1][2]); \ - XDBG_TRACE("EXA2D", "\t0x%08x 0x%08x 0x%08x\n", \ - pPic->transform->matrix[1][0], \ - pPic->transform->matrix[1][1], \ - pPic->transform->matrix[1][2]); \ - }\ - } - -typedef struct -{ - BoxRec pos; - PixmapPtr pixmap; - tbm_bo bo; - - unsigned int access_device; /*TBM_DEVICE_XXX*/ - unsigned int access_data; /*pointer or gem*/ - G2dImage* imgG2d; -} ExaOpBuf; - -typedef struct -{ - int refcnt; - int opt; - int num; - int isSame; - - ExaOpBuf buf[5]; -} ExaOpInfo; - -typedef struct -{ - BoxRec box; - int state; /*state of region*/ - - struct xorg_list link; - - ExaOpBuf *pSrc; - ExaOpBuf *pMask; - ExaOpBuf *pDst; -} ExaBox; - -enum{ - DO_DRAW_NONE, - DO_DRAW_SW, - DO_DRAW_HW -}; - -typedef struct -{ - char bDo; - - int alu; - Pixel planemask; - Pixel fg; - PixmapPtr pixmap; - - int x,y,w,h; - GCPtr pGC; - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpSolid; - -typedef struct -{ - char bDo; - - Pixel pm; - int alu; - int reverse; - int upsidedown; - PixmapPtr pSrcPix; - PixmapPtr pDstPix; - - /*copy param*/ - int srcX; - int srcY; - int dstX; - int dstY; - int width, height; - - ExaOpInfo* pOpDst; - ExaOpInfo* pOpSrc; - struct xorg_list opBox; -} OpCopy; - -typedef struct -{ - char bDo; - - int op; - PicturePtr pSrcPicture; - PicturePtr pMaskPicture; - PicturePtr pDstPicture; - PixmapPtr pSrcPixmap; - PixmapPtr pMaskPixmap; - PixmapPtr pDstPixmap; - - /*copy param*/ - int srcX, srcY; - int maskX, maskY; - int dstX, dstY; - int width, height; - - char srcRepeat; - char srcRotate; - double srcScaleX; - double srcScaleY; - - char maskRepeat; - char maskRotate; - double maskScaleX; - double maskScaleY; - - ExaOpInfo* pOpSrc; - ExaOpInfo* pOpMask; - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpComposite; - -typedef struct -{ - char bDo; - - PixmapPtr pDst; - int x,y,w,h; - char* src; - int src_pitch; - - G2dImage* imgSrc; - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpUTS; - -typedef struct -{ - char bDo; - - PixmapPtr pSrc; - int x,y,w,h; - char* dst; - int dst_pitch; - - G2dImage* imgDst; - ExaOpInfo* pOpSrc; - struct xorg_list opBox; -} OpDFS; - -typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart, - int x, int y, - int clip_x, int clip_y, - int w, int h, void* data); - -typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data); - -static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES]; -static OpSolid gOpSolid; -static OpCopy gOpCopy; -static OpComposite gOpComposite; -static OpUTS gOpUTS; -static OpDFS gOpDFS; - -ExaBox* _g2dBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2) -{ - ExaBox* rgn; - - rgn = calloc (1, sizeof (ExaBox)); - XDBG_RETURN_VAL_IF_FAIL ((rgn != NULL), NULL); - - rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2); - if (rgnOUT == rgn->state) - { - free (rgn); - return NULL; - } - - xorg_list_add (&rgn->link, l); - return rgn; -} - -void _g2dBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t) -{ - ExaBox *b1 = NULL, *b2 = NULL; - ExaBox* r = NULL; - - xorg_list_for_each_entry (b1, b, link) - { - xorg_list_for_each_entry (b2, t, link) - { - r = _g2dBoxAdd (l, &b1->box, &b2->box); - if (r) - { - r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc; - r->pMask= b1->pMask ? b1->pMask : b2->pMask; - r->pDst = b1->pDst ? b1->pDst : b2->pDst; - } - } - } -} - -void _g2dBoxMove (struct xorg_list* l, int tx, int ty) -{ - ExaBox *b = NULL; - - xorg_list_for_each_entry (b, l, link) - { - secUtilBoxMove (&b->box, tx, ty); - } -} - -void _g2dBoxRemoveAll (struct xorg_list* l) -{ - ExaBox *ref = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (ref, next, l, link) - { - xorg_list_del (&ref->link); - free (ref); - } -} - -int _g2dBoxIsOne (struct xorg_list* l) -{ - if (l->next != l) - { - if (l->next == l->prev) - return 1; - else - return -1; - } - - return 0; -} - -void _g2dBoxPrint (ExaBox* sb1, const char* name) -{ - ExaBox *b = NULL; - - xorg_list_for_each_entry (b, &sb1->link, link) - { - XDBG_DEBUG (MEXAS, "[%s] %d,%d - %d,%d\n", name, - b->box.x1, b->box.y1, b->box.x2, b->box.y2); - } -} - -static pixman_bool_t -_g2d_check_within_epsilon (pixman_fixed_t a, - pixman_fixed_t b, - pixman_fixed_t epsilon) -{ - pixman_fixed_t t = a - b; - - if (t < 0) - t = -t; - - return t <= epsilon; -} - -static Bool -_g2d_check_picture(PicturePtr pPicture, char *rot90, double *scaleX, double *scaleY, char* repeat) -{ - struct pixman_transform* t; - -#define EPSILON (pixman_fixed_t) (2) - -#define IS_SAME(a, b) (_g2d_check_within_epsilon (a, b, EPSILON)) -#define IS_ZERO(a) (_g2d_check_within_epsilon (a, 0, EPSILON)) -#define IS_ONE(a) (_g2d_check_within_epsilon (a, F (1), EPSILON)) -#define IS_UNIT(a) \ - (_g2d_check_within_epsilon (a, F (1), EPSILON) || \ - _g2d_check_within_epsilon (a, F (-1), EPSILON) || \ - IS_ZERO (a)) -#define IS_INT(a) (IS_ZERO (pixman_fixed_frac (a))) - -/*RepeatNormal*/ - - if(pPicture == NULL) - { - return TRUE; - } - - if(pPicture->repeat) - { - switch(pPicture->repeatType) - { - case RepeatNormal: - *repeat = G2D_REPEAT_MODE_REPEAT; - break; - case RepeatPad: - *repeat = G2D_REPEAT_MODE_PAD; - break; - case RepeatReflect: - *repeat = G2D_REPEAT_MODE_REFLECT; - break; - default: - *repeat = G2D_REPEAT_MODE_NONE; - break; - } - } - else - { - *repeat = G2D_REPEAT_MODE_NONE; - } - - if(pPicture->transform == NULL) - { - *rot90 = 0; - *scaleX = 1.0; - *scaleY = 1.0; - return TRUE; - } - - t= pPicture->transform; - - if(!IS_ZERO(t->matrix[0][0]) && IS_ZERO(t->matrix[0][1]) && IS_ZERO(t->matrix[1][0]) && !IS_ZERO(t->matrix[1][1])) - { - *rot90 = FALSE; - *scaleX = pixman_fixed_to_double(t->matrix[0][0]); - *scaleY = pixman_fixed_to_double(t->matrix[1][1]); - } - else if(IS_ZERO(t->matrix[0][0]) && !IS_ZERO(t->matrix[0][1]) && !IS_ZERO(t->matrix[1][0]) && IS_ZERO(t->matrix[1][1])) - { - /* FIMG2D 90 => PIXMAN 270 */ - *rot90 = TRUE; - *scaleX = pixman_fixed_to_double(t->matrix[0][1]); - *scaleY = pixman_fixed_to_double(t->matrix[1][0]*-1); - } - else - { - return FALSE; - } - - return TRUE; -} - -static Bool -_g2dIsSupport(PixmapPtr pPix, Bool forMask) -{ - SECPixmapPriv *privPixmap; - - if(!pPix) return TRUE; - - if(!forMask && pPix->drawable.depth < 8) - return FALSE; - - privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - if(!privPixmap->isFrameBuffer && !privPixmap->bo) - return FALSE; - - return TRUE; -} - -static G2dImage* -_g2dGetImageFromPixmap(PixmapPtr pPix, unsigned int gem) -{ - G2dImage* img; - G2dColorKeyMode mode; - - if(gem == 0) - { - gem = (unsigned int)pPix->devPrivate.ptr; - } - - XDBG_RETURN_VAL_IF_FAIL((pPix != NULL && gem != 0), NULL); - - switch(pPix->drawable.depth) - { - case 32: - mode = G2D_COLOR_FMT_ARGB8888|G2D_ORDER_AXRGB; - break; - case 24: - mode = G2D_COLOR_FMT_XRGB8888|G2D_ORDER_AXRGB; - break; - case 16: - mode = G2D_COLOR_FMT_RGB565|G2D_ORDER_AXRGB; - break; - case 8: - mode = G2D_COLOR_FMT_A8|G2D_ORDER_AXRGB; - break; - case 1: - mode = G2D_COLOR_FMT_A1|G2D_ORDER_AXRGB; - break; - default: - XDBG_ERROR(MEXA, "Unsupport format depth:%d(%d),pitch:%d \n", - pPix->drawable.depth, pPix->drawable.bitsPerPixel, pPix->devKind); - return NULL; - } - - img = g2d_image_create_bo(mode, - pPix->drawable.width, - pPix->drawable.height, - gem, - pPix->devKind); - - return img; -} - -static ExaOpInfo* _g2dPrepareAccess (PixmapPtr pPix, int index, unsigned int device) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - ExaOpInfo* op = &OpInfo[index]; - int opt = TBM_OPTION_READ; - int i; - tbm_bo *bos = NULL; - tbm_bo_handle bo_handle; - SECFbBoDataPtr bo_data; - int num_bo; - int ret; - - XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL); - - if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) - opt |= TBM_OPTION_WRITE; - - /* Check mapped */ - if (privPixmap->exaOpInfo) - { - op = (ExaOpInfo*)privPixmap->exaOpInfo; - op->refcnt++; - XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); - return op; - } - - /*Set buffer info*/ - memset (op, 0x00, sizeof (ExaOpInfo)); - op->refcnt = 1; - op->opt = opt; - op->isSame = 0; - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB) - { - ret = secFbFindBo (pSec->pFb, - pPix->drawable.x, pPix->drawable.y, - pPix->drawable.width, pPix->drawable.height, - &num_bo, &bos); - XDBG_TRACE (MEXAH,"FB ret:%d num_pix:%d, %dx%d+%d+%d\n", - ret, num_bo, - pPix->drawable.width, pPix->drawable.height, - pPix->drawable.x, pPix->drawable.y); - - if (ret == rgnSAME && num_bo == 1) - { - op->num = 1; - op->isSame = 1; - - op->buf[0].pixmap = pPix; - op->buf[0].bo = bos[0]; - op->buf[0].pos.x1 = 0; - op->buf[0].pos.y1 = 0; - op->buf[0].pos.x2 = pPix->drawable.width; - op->buf[0].pos.y2 = pPix->drawable.height; - - op->buf[0].access_device = device; - bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt); - op->buf[0].access_data = bo_handle.u32; - op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data; - if(device == TBM_DEVICE_2D) - { - op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap, - op->buf[0].access_data); - } - } - else - { - op->num = num_bo; - op->isSame = 0; - - for (i = 0; i < num_bo; i++) - { - tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data); - op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]); - op->buf[i].bo = bos[i]; - op->buf[i].pos = bo_data->pos; - - op->buf[i].access_device = device; - bo_handle = tbm_bo_map (op->buf[i].bo, device, op->opt); - op->buf[i].access_data = bo_handle.u32; - op->buf[i].pixmap->devPrivate.ptr = (pointer)op->buf[i].access_data; - if(device == TBM_DEVICE_2D) - { - op->buf[i].imgG2d = _g2dGetImageFromPixmap(op->buf[i].pixmap, - op->buf[i].access_data); - } - } - } - if (bos) - free (bos); - } - else - { - op->num = 1; - op->isSame = 1; - - op->buf[0].pixmap = pPix; - op->buf[0].bo = privPixmap->bo; - op->buf[0].pos.x1 = 0; - op->buf[0].pos.y1 = 0; - op->buf[0].pos.x2 = pPix->drawable.width; - op->buf[0].pos.y2 = pPix->drawable.height; - - op->buf[0].access_device = device; - if (privPixmap->bo) - { - bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt); - op->buf[0].access_data = bo_handle.u32; - if(device == TBM_DEVICE_2D) - { - op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap, op->buf[0].access_data); - } - } - else - { - op->buf[0].access_data = (unsigned int)privPixmap->pPixData; - op->buf[0].imgG2d = NULL; - } - op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data; - } - - privPixmap->exaOpInfo = op; - - XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); - return op; -} - -static void _g2dFinishAccess (PixmapPtr pPix, int index) -{ - XDBG_RETURN_IF_FAIL (pPix!=NULL); - - SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - ExaOpInfo* op; - int i; - - XDBG_RETURN_IF_FAIL (privPixmap!=NULL); - XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL); - - op = (ExaOpInfo*)privPixmap->exaOpInfo; - op->refcnt --; - - if (op->refcnt == 0) - { - for (i=0; i<op->num; i++) - { - if(op->buf[i].bo) - { - tbm_bo_unmap(op->buf[i].bo); - op->buf[i].bo = NULL; - } - - if(op->buf[i].pixmap) - { - op->buf[i].pixmap->devPrivate.ptr = NULL; - op->buf[i].pixmap = NULL; - } - - if(op->buf[i].imgG2d) - { - g2d_image_free(op->buf[i].imgG2d); - op->buf[i].imgG2d = NULL; - } - - op->buf[i].access_data = (unsigned int)NULL; - } - - privPixmap->exaOpInfo = NULL; - } - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) - secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER)); - - XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); -} - -void -_g2dDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data) -{ - ExaBox *box = NULL; - xorg_list_for_each_entry (box, l, link) - { - do_draw (box, data); - } -} - -static void -_g2dDoSolid (ExaBox* box, void* data) -{ - XDBG_TRACE (MEXAH, "[%s] (%d,%d), (%d,%d) off(%d,%d)\n", - DO(gOpSolid), - box->box.x1, - box->box.y1, - box->box.x2, - box->box.y2, - gOpSolid.x, - gOpSolid.y); - - if(gOpSolid.bDo == DO_DRAW_SW) - { - fbFill (&box->pDst->pixmap->drawable, - gOpSolid.pGC, - box->box.x1 + gOpSolid.x - box->pDst->pos.x1, - box->box.y1 + gOpSolid.y - box->pDst->pos.y1, - box->box.x2- box->box.x1, - box->box.y2- box->box.y1); - } - else - { - util_g2d_fill_alu(box->pDst->imgG2d, - box->box.x1 + gOpSolid.x - box->pDst->pos.x1, - box->box.y1 + gOpSolid.y - box->pDst->pos.y1, - box->box.x2- box->box.x1, - box->box.y2- box->box.y1, - gOpSolid.fg, - (G2dAlu)gOpSolid.alu); - } -} - -static void -_g2dDoCopy (ExaBox* box, void* data) -{ - CARD8 alu = gOpCopy.alu; - FbBits pm = gOpCopy.pm; - FbBits *src; - FbStride srcStride; - int srcBpp; - FbBits *dst; - FbStride dstStride; - int dstBpp; - _X_UNUSED int srcXoff, srcYoff; - _X_UNUSED int dstXoff, dstYoff; - int srcX, srcY, dstX, dstY, width, height; - - XDBG_TRACE (MEXAH, "[%s] box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n", - DO(gOpCopy), - box->box.x1, - box->box.y1, - box->box.x2, - box->box.y2, - gOpCopy.srcX, - gOpCopy.srcY); - - srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1; - srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1; - dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1; - dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - if(gOpCopy.bDo == DO_DRAW_SW) - { - fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff); - fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); - /* temp fix : do right things later */ - if (!src || !dst) - { - return; - } - - if (pm != FB_ALLONES || - alu != GXcopy || - gOpCopy.reverse || - gOpCopy.upsidedown || - !pixman_blt ((uint32_t *)src, (uint32_t *)dst, - srcStride, - dstStride, - srcBpp, dstBpp, - srcX, srcY, dstX, dstY, width, height)) - { - fbBlt (src + srcY * srcStride, - srcStride, - srcX * srcBpp, - - dst + dstY * dstStride, - dstStride, - dstX * dstBpp, - - width * dstBpp, - height, - - alu, - pm, - dstBpp, - - gOpCopy.reverse, - gOpCopy.upsidedown); - } - } - else - { - util_g2d_copy_alu(box->pSrc->imgG2d, - box->pDst->imgG2d, - srcX, srcY, - dstX, dstY, - width, height, - gOpCopy.alu); - } -} - -static void -_g2dDoComposite (ExaBox* box, void* data) -{ - - if (box->state == rgnPART) - { - XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL); - XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture && - gOpComposite.pMaskPicture->transform == NULL); - } - - if (gOpComposite.bDo == DO_DRAW_SW) - { - PicturePtr pDstPicture; - pixman_image_t *src, *mask, *dest; - int src_xoff, src_yoff, msk_xoff, msk_yoff; - FbBits *bits; - FbStride stride; - int bpp; - - pDstPicture = gOpComposite.pDstPicture; - - src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff); - mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff); - - fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp); - dest = pixman_image_create_bits (pDstPicture->format, - box->pDst->pixmap->drawable.width, - box->pDst->pixmap->drawable.height, - (uint32_t *)bits, stride * sizeof (FbStride)); - XDBG_RETURN_IF_FAIL (dest != NULL); - - pixman_image_composite (gOpComposite.op, - src, mask, dest, - gOpComposite.srcX + box->box.x1, - gOpComposite.srcY + box->box.y1, - gOpComposite.maskX + box->box.x1, - gOpComposite.maskY + box->box.y1, - gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1, - gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1, - box->box.x2 - box->box.x1, - box->box.y2 - box->box.y1); - - free_pixman_pict (gOpComposite.pSrcPicture, src); - free_pixman_pict (gOpComposite.pMaskPicture, mask); - pixman_image_unref (dest); - } - else - { - util_g2d_composite (gOpComposite.op, - box->pSrc->imgG2d, - box->pMask ? box->pMask->imgG2d:NULL, - box->pDst->imgG2d, - gOpComposite.srcX + box->box.x1, - gOpComposite.srcY + box->box.y1, - gOpComposite.maskX + box->box.x1, - gOpComposite.maskY + box->box.y1, - gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1, - gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1, - box->box.x2 - box->box.x1, - box->box.y2 - box->box.y1); - } -} - -static void -_g2dDoUploadToScreen (ExaBox* box, void* data) -{ - int dstX, dstY; - int width, height; - - dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1; - dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - if(gOpUTS.bDo == DO_DRAW_SW) - { - FbBits *dst; - FbStride dstStride; - int dstBpp; - _X_UNUSED int dstXoff, dstYoff; - int srcStride; - - fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); - - srcStride = gOpUTS.src_pitch/sizeof (uint32_t); - - XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n", - gOpUTS.src, srcStride, dstX, dstY, width, height); - - if (!pixman_blt ((uint32_t *)gOpUTS.src, - (uint32_t *)dst, - srcStride, - dstStride, - dstBpp, dstBpp, - box->box.x1, box->box.y1, - dstX, dstY, - width, height)) - { - fbBlt ((FbBits*) ((FbBits*)gOpUTS.src), - srcStride, - box->box.x1, - - dst + dstY * dstStride, - dstStride, - dstX, - - width, - height, - - GXcopy, - ~0, - dstBpp, - - 0, - 0); - } - } - else - { - util_g2d_copy(gOpUTS.imgSrc, - box->pDst->imgG2d, - box->box.x1, box->box.y1, - dstX, dstY, - width, height); - } -} - -static void -_g2dDoDownladFromScreen (ExaBox* box, void* data) -{ - int srcX, srcY; - int width, height; - int dstStride; - - dstStride = gOpDFS.dst_pitch/sizeof (uint32_t); - srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1; - srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n", - gOpDFS.dst, dstStride, srcX, srcY, width, height); - - if(gOpDFS.bDo == DO_DRAW_SW) - { - FbBits *src; - FbStride srcStride; - int srcBpp; - _X_UNUSED int srcXoff, srcYoff; - - fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff); - - if (!pixman_blt ((uint32_t *)src, - (uint32_t *)gOpDFS.dst, - srcStride, - dstStride, - srcBpp, srcBpp, - srcX, srcY, - box->box.x1, box->box.y1, - width, height)) - { - fbBlt (src + srcY * srcStride, - srcStride, - srcX, - - (FbBits*) ((FbBits*)gOpDFS.dst), - dstStride, - box->box.x1, - - width, - height, - - GXcopy, - ~0, - srcBpp, - - 0, - 0); - } - } - else - { - util_g2d_copy (box->pSrc->imgG2d, - gOpDFS.imgDst, - srcX, srcY, - box->box.x1, box->box.y1, - width, height); - } -} - -static Bool -SECExaG2dPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ChangeGCVal tmpval[3]; - - XDBG_TRACE (MEXAH, "\n"); - memset (&gOpSolid, 0x00, sizeof (gOpSolid)); - - /* Put ff at the alpha bits when transparency is set to xv */ - if (pPixmap->drawable.depth == 24) - fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue)); - - gOpSolid.alu = alu; - gOpSolid.fg = fg; - gOpSolid.planemask = planemask; - gOpSolid.pixmap = pPixmap; - - if (!_g2dIsSupport(pPixmap, 0)) - { - gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap, - EXA_PREPARE_DEST, - TBM_DEVICE_CPU); - XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail); - - gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); - tmpval[0].val = alu; - tmpval[1].val = planemask; - tmpval[2].val = fg; - ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval); - ValidateGC (&pPixmap->drawable, gOpSolid.pGC); - - gOpSolid.bDo = DO_DRAW_SW; - } - else - { - gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap, - EXA_PREPARE_DEST, - TBM_DEVICE_2D); - XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail); - gOpSolid.bDo = DO_DRAW_HW; - } - - return TRUE; - -bail: - XDBG_TRACE (MEXAH, "FAIL: pix:%p hint:%d, num_pix:%d\n", - pPixmap, index, pPixmap->usage_hint, gOpSolid.pOpDst->num); - gOpSolid.bDo = DO_DRAW_NONE; - gOpSolid.pGC = NULL; - - return TRUE; -} - - -static void -SECExaG2dSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2) -{ - XDBG_TRACE (MEXAH, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2); - XDBG_TRACE (MEXAH, "%s\n", DO(gOpSolid)); - if (gOpSolid.bDo == DO_DRAW_NONE) return; - - gOpSolid.x = x1; - gOpSolid.y = y1; - gOpSolid.w = x2-x1; - gOpSolid.h = y2-y1; - - if (gOpSolid.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = x2-x1; - box.box.y2 = y2-y1; - box.pDst = &gOpSolid.pOpDst->buf[0]; - _g2dDoSolid (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpSolid.opBox); - - b.x1 = x1; - b.y1 = y1; - b.x2 = x2; - b.y2 = y2; - - for (i=0; i<gOpSolid.pOpDst->num; i++) - { - box = _g2dBoxAdd (&gOpSolid.opBox, - &gOpSolid.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpSolid.pOpDst->buf[i]; - } - } - _g2dBoxMove (&gOpSolid.opBox, -x1, -y1); - - /* Call solid function */ - _g2dDoDraw (&gOpSolid.opBox, - _g2dDoSolid, NULL); - - /*Remove box list*/ - _g2dBoxRemoveAll (&gOpSolid.opBox); - } -} - -static void -SECExaG2dDoneSolid (PixmapPtr pPixmap) -{ - XDBG_TRACE (MEXAH, "\n"); - - if (gOpSolid.bDo) - g2d_exec(); - - if (gOpSolid.pGC) - { - FreeScratchGC (gOpSolid.pGC); - gOpSolid.pGC = NULL; - } - - if (gOpSolid.pixmap) - _g2dFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST); -} - -static Bool -SECExaG2dPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, - int dx, int dy, int alu, Pixel planemask) -{ - int num_dst_pix = -1; - int num_src_pix = -1; - unsigned int draw_type = DO_DRAW_HW; - unsigned int access_device = TBM_DEVICE_2D; - - XDBG_TRACE (MEXAH, "\n"); - memset (&gOpCopy, 0x00, sizeof (gOpCopy)); - - gOpCopy.alu = alu; - gOpCopy.pm = planemask; - gOpCopy.reverse = (dx == 1)?0:1; - gOpCopy.upsidedown = (dy == 1)?0:1; - gOpCopy.pDstPix = pDstPixmap; - gOpCopy.pSrcPix = pSrcPixmap; - - /* Check capability */ - if(!_g2dIsSupport(pSrcPixmap, 0) || - !_g2dIsSupport(pDstPixmap, 0) || - gOpCopy.reverse || - gOpCopy.upsidedown) - { - draw_type = DO_DRAW_SW; - access_device = TBM_DEVICE_CPU; - } - - gOpCopy.pOpDst = _g2dPrepareAccess (pDstPixmap, EXA_PREPARE_DEST, access_device); - XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail); - gOpCopy.pOpSrc = _g2dPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC, access_device); - XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail); - - gOpCopy.bDo = draw_type; - - return TRUE; - -bail: - XDBG_TRACE (MEXAH, "FAIL\n"); - XDBG_TRACE (MEXAH, " SRC pix:%p, index:%d, hint:%d, num_pix:%d\n", - pSrcPixmap, index, pSrcPixmap->usage_hint, num_src_pix); - XDBG_TRACE (MEXAH, " DST pix:%p, index:%d, hint:%d, num_pix:%d\n", - pDstPixmap, index, pDstPixmap->usage_hint, num_dst_pix); - gOpCopy.bDo = DO_DRAW_NONE; - - return TRUE; -} - - -static void -SECExaG2dCopy (PixmapPtr pDstPixmap, int srcX, int srcY, - int dstX, int dstY, int width, int height) -{ - XDBG_TRACE (MEXAH, "%s\n", DO(gOpCopy)); - XDBG_TRACE (MEXAH, "src(%d,%d) dst(%d,%d) %dx%d\n", - srcX, srcY, dstX, dstY, width, height); - - if (gOpSolid.bDo == FALSE) return; - - gOpCopy.srcX = srcX; - gOpCopy.srcY = srcY; - gOpCopy.dstX = dstX; - gOpCopy.dstY = dstY; - gOpCopy.width = width; - gOpCopy.height = height; - - if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = width; - box.box.y2 = height; - box.pDst = &gOpCopy.pOpDst->buf[0]; - box.pSrc = &gOpCopy.pOpSrc->buf[0]; - _g2dDoCopy (&box, NULL); - } - else - { - int i; - struct xorg_list lSrc, lDst; - ExaBox *box; - BoxRec b; - - //Set Dest - b.x1 = dstX; - b.y1 = dstY; - b.x2 = dstX + width; - b.y2 = dstY + height; - xorg_list_init (&lDst); - for (i=0; i<gOpCopy.pOpDst->num; i++) - { - box = _g2dBoxAdd (&lDst, - &gOpCopy.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpCopy.pOpDst->buf[i]; - } - } - _g2dBoxMove (&lDst, -dstX, -dstY); - - //Set Src - b.x1 = srcX; - b.y1 = srcY; - b.x2 = srcX + width; - b.y2 = srcY + height; - - xorg_list_init (&lSrc); - for (i=0; i<gOpCopy.pOpSrc->num; i++) - { - box = _g2dBoxAdd (&lSrc, - &gOpCopy.pOpSrc->buf[i].pos, - &b); - if (box) - { - box->pSrc = &gOpCopy.pOpSrc->buf[i]; - } - } - _g2dBoxMove (&lSrc, -srcX, -srcY); - - //Merge and call copy - xorg_list_init (&gOpCopy.opBox); - _g2dBoxMerge (&gOpCopy.opBox, &lSrc, &lDst); - _g2dDoDraw (&gOpCopy.opBox, - _g2dDoCopy, NULL); - - //Remove box list - _g2dBoxRemoveAll (&lSrc); - _g2dBoxRemoveAll (&lDst); - _g2dBoxRemoveAll (&gOpCopy.opBox); - } -} - -static void -SECExaG2dDoneCopy (PixmapPtr pDstPixmap) -{ - XDBG_TRACE (MEXAH, "\n"); - if (gOpCopy.bDo == DO_DRAW_HW) - g2d_exec(); - - if (gOpCopy.pDstPix) - _g2dFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST); - if (gOpCopy.pSrcPix) - _g2dFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC); -} - -static Bool -SECExaG2dCheckComposite (int op, PicturePtr pSrcPicture, - PicturePtr pMaskPicture, PicturePtr pDstPicture) -{ - return TRUE; -} - -static Bool -SECExaG2dPrepareComposite (int op, PicturePtr pSrcPicture, - PicturePtr pMaskPicture, PicturePtr pDstPicture, - PixmapPtr pSrcPixmap, - PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap) -{ - XDBG_GOTO_IF_FAIL (pDstPixmap, bail); - XDBG_GOTO_IF_FAIL (pSrcPicture && pDstPicture, bail); - - unsigned int draw_type = DO_DRAW_HW; - unsigned int access_device = TBM_DEVICE_2D; - - XDBG_TRACE (MEXAH, "\n"); - memset (&gOpComposite, 0x00, sizeof (gOpComposite)); - - gOpComposite.op = op; - gOpComposite.pDstPicture = pDstPicture; - gOpComposite.pSrcPicture = pSrcPicture; - gOpComposite.pMaskPicture = pMaskPicture; - gOpComposite.pSrcPixmap = pSrcPixmap; - gOpComposite.pMaskPixmap = pMaskPixmap; - gOpComposite.pDstPixmap = pDstPixmap; - - if (!_g2dIsSupport(pSrcPixmap, 0) || - !_g2dIsSupport(pDstPixmap, 0) || - !_g2dIsSupport(pMaskPixmap, 1)) - { - draw_type = DO_DRAW_SW; - } - - if (!_g2d_check_picture(pSrcPicture, - &gOpComposite.srcRotate, - &gOpComposite.srcScaleX, - &gOpComposite.srcScaleY, - &gOpComposite.srcRepeat) || - !_g2d_check_picture(pMaskPicture, - &gOpComposite.maskRotate, - &gOpComposite.maskScaleX, - &gOpComposite.maskScaleY, - &gOpComposite.maskRepeat)) - { - draw_type = DO_DRAW_SW; - } - - if(draw_type == DO_DRAW_SW) - { - access_device = TBM_DEVICE_CPU; - } - - gOpComposite.pOpDst = _g2dPrepareAccess (pDstPixmap, - EXA_PREPARE_DEST, - access_device); - - if (pSrcPixmap) - { - gOpComposite.pOpSrc = _g2dPrepareAccess (pSrcPixmap, - EXA_PREPARE_SRC, - access_device); - XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail); - } - - if (pMaskPixmap) - { - gOpComposite.pOpMask = _g2dPrepareAccess (pMaskPixmap, - EXA_PREPARE_MASK, - access_device); - XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail); - } - - if(draw_type == DO_DRAW_HW) - { - G2dImage *imgSrc = NULL, *imgMask = NULL; - - if(pSrcPicture) - { - if(gOpComposite.pOpSrc == NULL) - { - gOpComposite.pOpSrc = &OpInfo[EXA_PREPARE_SRC]; - gOpComposite.pOpSrc->buf[0].imgG2d = - g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color); - } - - imgSrc = gOpComposite.pOpSrc->buf[0].imgG2d; - } - - - if(pMaskPicture) - { - if(gOpComposite.pOpMask == NULL) - { - gOpComposite.pOpMask = &OpInfo[EXA_PREPARE_MASK]; - gOpComposite.pOpMask->buf[0].imgG2d = - g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color); - } - - imgMask = gOpComposite.pOpMask->buf[0].imgG2d; - } - - /*Set Repeat*/ - imgSrc->repeat_mode = gOpComposite.srcRepeat; - - /*Set Rotate */ - imgSrc->rotate_90 = gOpComposite.srcRotate; - imgSrc->xDir = (gOpComposite.srcScaleX < 0.0); - imgSrc->yDir = (gOpComposite.srcScaleY < 0.0); - - /*Set Scale*/ - if(((gOpComposite.srcScaleX != 1.0 && gOpComposite.srcScaleX != -1.0) || - (gOpComposite.srcScaleY != 1.0 && gOpComposite.srcScaleY != -1.0))) - { - imgSrc->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleX); - imgSrc->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleY); - imgSrc->scale_mode = G2D_SCALE_MODE_BILINEAR; - } - - if(imgMask) - { - /*Set Repeat*/ - imgMask->repeat_mode = gOpComposite.maskRepeat; - - /*Set Rotate */ - imgMask->rotate_90 = gOpComposite.maskRotate; - imgMask->xDir = (gOpComposite.maskScaleX < 0.0); - imgMask->yDir = (gOpComposite.maskScaleY < 0.0); - - /*Set Scale*/ - if(((gOpComposite.maskScaleX != 1.0 && gOpComposite.maskScaleX != -1.0) || - (gOpComposite.maskScaleY != 1.0 && gOpComposite.maskScaleY != -1.0))) - { - imgMask->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleX); - imgMask->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleY); - imgMask->scale_mode = G2D_SCALE_MODE_BILINEAR; - } - } - } - - gOpComposite.bDo = draw_type; - - return TRUE; - -bail: - XDBG_TRACE (MEXAH, "FAIL: op%d\n", op); - XDBG_TRACE (MEXAH, " SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap); - XDBG_TRACE (MEXAH, " MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap); - XDBG_TRACE (MEXAH, " DST picture:%p pix:%p\n", pDstPicture, pDstPixmap); - - gOpComposite.bDo = DO_DRAW_NONE; - - return TRUE; -} - -static void -SECExaG2dComposite (PixmapPtr pDstPixmap, int srcX, int srcY, - int maskX, int maskY, int dstX, int dstY, - int width, int height) -{ - XDBG_TRACE (MEXAH, "%s\n", DO(gOpComposite)); - XDBG_TRACE (MEXAH, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n", - srcX, srcY, - maskX, maskY, - dstX, dstY, - width, height); - if (gOpComposite.bDo == DO_DRAW_NONE) return; - - gOpComposite.srcX = srcX; - gOpComposite.srcY = srcY; - gOpComposite.maskX = maskX; - gOpComposite.maskY = maskY; - gOpComposite.dstX = dstX; - gOpComposite.dstY = dstY; - gOpComposite.width = width; - gOpComposite.height = height; - - if (gOpComposite.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = width; - box.box.y2 = height; - box.pDst = &gOpComposite.pOpDst->buf[0]; - box.pSrc = &gOpComposite.pOpSrc->buf[0]; - box.pMask = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL; - - _g2dDoComposite (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpComposite.opBox); - - b.x1 = dstX; - b.y1 = dstY; - b.x2 = dstX+width; - b.y2 = dstY+height; - - for (i=0; i<gOpComposite.pOpDst->num; i++) - { - box = _g2dBoxAdd (&gOpComposite.opBox, - &gOpComposite.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpComposite.pOpDst->buf[i]; - box->pSrc = &gOpComposite.pOpSrc->buf[0]; - box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL; - } - } - _g2dBoxMove (&gOpComposite.opBox, -dstX, -dstY); - - /* Call solid function */ - _g2dDoDraw (&gOpComposite.opBox, - _g2dDoComposite, NULL); - - /*Remove box list*/ - _g2dBoxRemoveAll (&gOpComposite.opBox); - } -} - -/* done composite : sw done composite, not using pvr2d */ -static void -SECExaG2dDoneComposite (PixmapPtr pDst) -{ - XDBG_TRACE (MEXAH, "\n"); - - if(gOpComposite.bDo == DO_DRAW_HW) - g2d_exec(); - - if (gOpComposite.pDstPixmap != NULL) - _g2dFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST); - - if (gOpComposite.pSrcPixmap != NULL) - _g2dFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC); - else if (gOpComposite.pOpSrc) - { - g2d_image_free (gOpComposite.pOpSrc->buf[0].imgG2d); - gOpComposite.pOpSrc->buf[0].imgG2d = NULL; - } - - if (gOpComposite.pMaskPixmap != NULL) - _g2dFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK); - else if (gOpComposite.pOpMask != NULL) - { - g2d_image_free (gOpComposite.pOpMask->buf[0].imgG2d); - gOpComposite.pOpMask->buf[0].imgG2d = NULL; - } -} - -static Bool -SECExaG2dUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h, - char *src, int src_pitch) -{ - XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE); - XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h); - - gOpUTS.pDst = pDst; - gOpUTS.x = x; - gOpUTS.y = y; - gOpUTS.w = w; - gOpUTS.h = h; - gOpUTS.src = src; - gOpUTS.src_pitch = src_pitch; - - if(_g2dIsSupport(pDst, FALSE)) - { - gOpUTS.pOpDst = _g2dPrepareAccess (pDst, - EXA_PREPARE_DEST, - TBM_DEVICE_2D); - gOpUTS.imgSrc = g2d_image_create_data (gOpUTS.pOpDst->buf[0].imgG2d->color_mode, - w, h, (void*)src, src_pitch); - gOpUTS.bDo = DO_DRAW_HW; - } - else - { - gOpUTS.pOpDst = _g2dPrepareAccess (pDst, - EXA_PREPARE_DEST, - TBM_DEVICE_CPU); - gOpUTS.imgSrc = NULL; - gOpUTS.bDo = DO_DRAW_SW; - } - - XDBG_TRACE (MEXAH, "%s\n", DO(gOpUTS)); - if (gOpUTS.pOpDst->isSame) - { - ExaBox box; - - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = w; - box.box.y2 = h; - box.state = rgnIN; - box.pDst = &gOpUTS.pOpDst->buf[0]; - _g2dDoUploadToScreen (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpUTS.opBox); - - b.x1 = x; - b.y1 = y; - b.x2 = x+w; - b.y2 = y+h; - - for (i=0; i<gOpUTS.pOpDst->num; i++) - { - box = _g2dBoxAdd (&gOpUTS.opBox, - &gOpUTS.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpUTS.pOpDst->buf[i]; - } - } - _g2dBoxMove (&gOpUTS.opBox, -x, -y); - - /* Call solid function */ - _g2dDoDraw (&gOpUTS.opBox, - _g2dDoUploadToScreen, NULL); - - /*Remove box list*/ - _g2dBoxRemoveAll (&gOpUTS.opBox); - } - - if(gOpUTS.bDo == DO_DRAW_HW) - g2d_exec(); - - _g2dFinishAccess (pDst, EXA_PREPARE_DEST); - if(gOpUTS.imgSrc) - { - g2d_image_free(gOpUTS.imgSrc); - } - return TRUE; -} - - - -static Bool -SECExaG2dDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h, - char *dst, int dst_pitch) -{ - XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE); - XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h); - - gOpDFS.pSrc = pSrc; - gOpDFS.x = x; - gOpDFS.y = y; - gOpDFS.w = w; - gOpDFS.h = h; - gOpDFS.dst = dst; - gOpDFS.dst_pitch = dst_pitch; - - if(_g2dIsSupport(pSrc, FALSE)) - { - gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc, - EXA_PREPARE_DEST, - TBM_DEVICE_2D); - gOpDFS.imgDst = g2d_image_create_data (gOpDFS.pOpSrc->buf[0].imgG2d->color_mode, - w, h, (void*)dst, dst_pitch); - gOpDFS.bDo = DO_DRAW_HW; - } - else - { - gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc, - EXA_PREPARE_DEST, - TBM_DEVICE_CPU); - gOpDFS.imgDst = NULL; - gOpDFS.bDo = DO_DRAW_SW; - } - - XDBG_TRACE (MEXAH, "%s\n", DO(gOpDFS)); - if (gOpDFS.pOpSrc->isSame) - { - ExaBox box; - - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = w; - box.box.y2 = h; - box.state = rgnIN; - box.pSrc = &gOpDFS.pOpSrc->buf[0]; - _g2dDoDownladFromScreen (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpDFS.opBox); - - b.x1 = x; - b.y1 = y; - b.x2 = x+w; - b.y2 = y+h; - - for (i=0; i<gOpDFS.pOpSrc->num; i++) - { - box = _g2dBoxAdd (&gOpDFS.opBox, - &gOpDFS.pOpSrc->buf[i].pos, - &b); - if (box) - { - box->pSrc = &gOpDFS.pOpSrc->buf[i]; - } - } - _g2dBoxMove (&gOpDFS.opBox, -x, -y); - - /* Call solid function */ - _g2dDoDraw (&gOpDFS.opBox, - _g2dDoDownladFromScreen, NULL); - - /*Remove box list*/ - _g2dBoxRemoveAll (&gOpDFS.opBox); - } - - if(gOpDFS.bDo == DO_DRAW_HW) - g2d_exec(); - - _g2dFinishAccess (pSrc, EXA_PREPARE_SRC); - if(gOpDFS.imgDst) - { - g2d_image_free(gOpDFS.imgDst); - } - return TRUE; -} - -Bool secExaG2dInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - if(!g2d_init (pSec->drm_fd)) - { - XDBG_WARNING (MEXA, "[EXAG2D] fail to g2d_init(%d)\n", pSec->drm_fd); - } - - pExaDriver->PrepareSolid = SECExaG2dPrepareSolid; - pExaDriver->Solid = SECExaG2dSolid; - pExaDriver->DoneSolid = SECExaG2dDoneSolid; - - pExaDriver->PrepareCopy = SECExaG2dPrepareCopy; - pExaDriver->Copy = SECExaG2dCopy; - pExaDriver->DoneCopy = SECExaG2dDoneCopy; - - pExaDriver->CheckComposite = SECExaG2dCheckComposite; - pExaDriver->PrepareComposite = SECExaG2dPrepareComposite; - pExaDriver->Composite = SECExaG2dComposite; - pExaDriver->DoneComposite = SECExaG2dDoneComposite; - - pExaDriver->UploadToScreen = SECExaG2dUploadToScreen; - pExaDriver->DownloadFromScreen = SECExaG2dDownloadFromScreen; - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "Succeed to Initialize G2D EXA\n"); - - return TRUE; -} - -void secExaG2dDeinit (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "Succeed to finish SW EXA\n"); -} diff --git a/src/accel/sec_exa_sw.c b/src/accel/sec_exa_sw.c deleted file mode 100755 index d8c3537..0000000 --- a/src/accel/sec_exa_sw.c +++ /dev/null @@ -1,1266 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 "sec.h" -#include "sec_accel.h" -#include "sec_util.h" -#include "sec_layer.h" -#include "exa.h" -#include "fbpict.h" -#include "neonmem.h" - -typedef struct -{ - BoxRec pos; - PixmapPtr pixmap; - tbm_bo bo; - void* addr; -} ExaOpBuf; - -typedef struct -{ - int refcnt; - int opt; - int num; - int isSame; - - ExaOpBuf buf[5]; -} ExaOpInfo; - -typedef struct -{ - BoxRec box; - int state; /*state of region*/ - - struct xorg_list link; - - ExaOpBuf *pSrc; - ExaOpBuf *pMask; - ExaOpBuf *pDst; -} ExaBox; - -typedef struct -{ - Bool bDo; - - int alu; - Pixel planemask; - Pixel fg; - PixmapPtr pixmap; - - int x,y,w,h; - GCPtr pGC; - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpSolid; - -typedef struct -{ - Bool bDo; - Pixel pm; - int alu; - int reverse; - int upsidedown; - PixmapPtr pSrcPix; - PixmapPtr pDstPix; - - /*copy param*/ - int srcX; - int srcY; - int dstX; - int dstY; - int width, height; - - ExaOpInfo* pOpDst; - ExaOpInfo* pOpSrc; - struct xorg_list opBox; -} OpCopy; - -typedef struct -{ - Bool bDo; - int op; - - PicturePtr pSrcPicture; - PicturePtr pMaskPicture; - PicturePtr pDstPicture; - PixmapPtr pSrcPixmap; - PixmapPtr pMaskPixmap; - PixmapPtr pDstPixmap; - - /*copy param*/ - int srcX, srcY; - int maskX, maskY; - int dstX, dstY; - int width, height; - - ExaOpInfo* pOpSrc; - ExaOpInfo* pOpMask; - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpComposite; - -typedef struct -{ - Bool bDo; - - PixmapPtr pDst; - int x,y,w,h; - char* src; - int src_pitch; - - ExaOpInfo* pOpDst; - struct xorg_list opBox; -} OpUTS; - -typedef struct -{ - Bool bDo; - - PixmapPtr pSrc; - int x,y,w,h; - char* dst; - int dst_pitch; - - ExaOpInfo* pOpSrc; - struct xorg_list opBox; -} OpDFS; - -typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart, - int x, int y, - int clip_x, int clip_y, - int w, int h, void* data); - -typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data); - -static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES]; -static OpSolid gOpSolid; -static OpCopy gOpCopy; -static OpComposite gOpComposite; -static OpUTS gOpUTS; -static OpDFS gOpDFS; - -ExaBox* _swBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2) -{ - ExaBox* rgn; - - rgn = calloc (1, sizeof (ExaBox)); - XDBG_RETURN_VAL_IF_FAIL ((rgn != NULL), NULL); - - rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2); - if (rgnOUT == rgn->state) - { - free (rgn); - return NULL; - } - - xorg_list_add (&rgn->link, l); - return rgn; -} - -void _swBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t) -{ - ExaBox *b1 = NULL, *b2 = NULL; - ExaBox* r=NULL; - - xorg_list_for_each_entry (b1, b, link) - { - xorg_list_for_each_entry (b2, t, link) - { - r = _swBoxAdd (l, &b1->box, &b2->box); - if (r) - { - r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc; - r->pMask= b1->pMask ? b1->pMask : b2->pMask; - r->pDst = b1->pDst ? b1->pDst : b2->pDst; - } - } - } -} - -void _swBoxMove (struct xorg_list* l, int tx, int ty) -{ - ExaBox *b = NULL; - - xorg_list_for_each_entry (b, l, link) - { - secUtilBoxMove (&b->box, tx, ty); - } -} - -void _swBoxRemoveAll (struct xorg_list* l) -{ - ExaBox *ref = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (ref, next, l, link) - { - xorg_list_del (&ref->link); - free (ref); - } -} - -int _swBoxIsOne (struct xorg_list* l) -{ - if (l->next != l) - { - if (l->next == l->prev) - return 1; - else - return -1; - } - - return 0; -} - -void _swBoxPrint (ExaBox* sb1, const char* name) -{ - ExaBox *b = NULL; - - xorg_list_for_each_entry (b, &sb1->link, link) - { - XDBG_DEBUG (MEXA, "[%s] %d,%d - %d,%d\n", name, - b->box.x1, b->box.y1, b->box.x2, b->box.y2); - } -} - -static ExaOpInfo* _swPrepareAccess (PixmapPtr pPix, int index) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - ExaOpInfo* op = &OpInfo[index]; - int opt = TBM_OPTION_READ; - int i; - tbm_bo *bos; - tbm_bo_handle bo_handle; - SECFbBoDataPtr bo_data; - int num_bo; - int ret; - - XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL); - - if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) - opt |= TBM_OPTION_WRITE; - - /* Check mapped */ - if (privPixmap->exaOpInfo) - { - op = (ExaOpInfo*)privPixmap->exaOpInfo; - op->refcnt++; - XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); - return op; - } - - /*Set buffer info*/ - memset (op, 0x00, sizeof (ExaOpInfo)); - op->refcnt = 1; - op->opt = opt; - op->isSame = 0; - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB) - { - ret = secFbFindBo (pSec->pFb, - pPix->drawable.x, pPix->drawable.y, - pPix->drawable.width, pPix->drawable.height, - &num_bo, &bos); - XDBG_TRACE (MEXAS,"FB ret:%d num_pix:%d, %dx%d+%d+%d\n", - ret, num_bo, - pPix->drawable.width, pPix->drawable.height, - pPix->drawable.x, pPix->drawable.y); - - if (ret == rgnSAME && num_bo == 1) - { - op->num = 1; - op->isSame = 1; - - op->buf[0].pixmap = pPix; - op->buf[0].bo = bos[0]; - bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt); - op->buf[0].addr = bo_handle.ptr; - op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr; - op->buf[0].pos.x1 = 0; - op->buf[0].pos.y1 = 0; - op->buf[0].pos.x2 = pPix->drawable.width; - op->buf[0].pos.y2 = pPix->drawable.height; - } - else - { - op->num = num_bo; - op->isSame = 0; - - for (i = 0; i < num_bo; i++) - { - tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data); - op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]); - op->buf[i].bo = bos[i]; - bo_handle = tbm_bo_map (bos[i], TBM_DEVICE_CPU, op->opt); - op->buf[i].addr = bo_handle.ptr; - op->buf[i].pixmap->devPrivate.ptr = op->buf[i].addr; - op->buf[i].pos = bo_data->pos; - } - } - - if (bos) - { - free (bos); - bos=NULL; - } - } - else - { - op->num = 1; - op->isSame = 1; - - op->buf[0].pixmap = pPix; - if (privPixmap->bo) - { - op->buf[0].bo = privPixmap->bo; - bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt); - op->buf[0].addr = bo_handle.ptr; - } - else - { - op->buf[0].bo = privPixmap->bo; - op->buf[0].addr = privPixmap->pPixData; - } - op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr; - op->buf[0].pos.x1 = 0; - op->buf[0].pos.y1 = 0; - op->buf[0].pos.x2 = pPix->drawable.width; - op->buf[0].pos.y2 = pPix->drawable.height; - } - - privPixmap->exaOpInfo = op; - - XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); - return op; -} - -static void _swFinishAccess (PixmapPtr pPix, int index) -{ - XDBG_RETURN_IF_FAIL (pPix!=NULL); - - SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix); - ExaOpInfo* op; - int i; - - XDBG_RETURN_IF_FAIL (privPixmap!=NULL); - XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL); - - op = (ExaOpInfo*)privPixmap->exaOpInfo; - op->refcnt --; - - if (op->refcnt == 0) - { - for (i=0; i < op->num; i++) - { - if (op->buf[i].bo) - { - tbm_bo_unmap (op->buf[i].bo); - - if( index == EXA_PREPARE_DEST && pPix->usage_hint == CREATE_PIXMAP_USAGE_FB ) - { - // In this case, DEST is framebuffer. It is updated by CPU. - // After that LCD will use this buffer. - // So we should call cache op!! - tbm_bo_map(op->buf[i].bo, TBM_DEVICE_3D, TBM_OPTION_READ); - tbm_bo_unmap(op->buf[i].bo); - - ScreenPtr pScreen; - pScreen = pPix->drawable.pScreen; - - if( pScreen != NULL ) - { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR(pScrn); - - pSec->is_fb_touched = TRUE; - } - } - op->buf[i].bo = NULL; - } - - if (op->buf[i].pixmap) - { - op->buf[i].pixmap->devPrivate.ptr = NULL; - op->buf[i].pixmap = NULL; - } - op->buf[i].addr = NULL; - } - - privPixmap->exaOpInfo = NULL; - } - - if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY) - secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER)); - - XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n", - pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt); -} - -void -_swDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data) -{ - ExaBox *box = NULL; - xorg_list_for_each_entry (box, l, link) - { - do_draw (box, data); - } -} - -static void -_swDoSolid (ExaBox* box, void* data) -{ - XDBG_TRACE (MEXAS, "(%d,%d), (%d,%d) off(%d,%d)\n", - box->box.x1, - box->box.y1, - box->box.x2, - box->box.y2, - gOpSolid.x, - gOpSolid.y); - - fbFill (&box->pDst->pixmap->drawable, - gOpSolid.pGC, - box->box.x1 + gOpSolid.x - box->pDst->pos.x1, - box->box.y1 + gOpSolid.y - box->pDst->pos.y1, - box->box.x2- box->box.x1, - box->box.y2- box->box.y1); -} - -static void -_swDoCopy (ExaBox* box, void* data) -{ - CARD8 alu = gOpCopy.alu; - FbBits pm = gOpCopy.pm; - FbBits *src; - FbStride srcStride; - int srcBpp; - FbBits *dst; - FbStride dstStride; - int dstBpp; - _X_UNUSED int srcXoff, srcYoff; - _X_UNUSED int dstXoff, dstYoff; - int srcX, srcY, dstX, dstY, width, height; - - XDBG_TRACE (MEXAS, "box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n", - box->box.x1, - box->box.y1, - box->box.x2, - box->box.y2, - gOpCopy.srcX, - gOpCopy.srcY); - - srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1; - srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1; - dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1; - dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff); - fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); - /* temp fix : do right things later */ - if (!src || !dst) - { - return; - } - - if (pm != FB_ALLONES || - alu != GXcopy || - gOpCopy.reverse || - gOpCopy.upsidedown || - !pixman_blt ((uint32_t *)src, (uint32_t *)dst, - srcStride, - dstStride, - srcBpp, dstBpp, - srcX, srcY, dstX, dstY, width, height)) - { - fbBlt (src + srcY * srcStride, - srcStride, - srcX * srcBpp, - - dst + dstY * dstStride, - dstStride, - dstX * dstBpp, - - width * dstBpp, - height, - - alu, - pm, - dstBpp, - - gOpCopy.reverse, - gOpCopy.upsidedown); - } -} - -static void -_swDoComposite (ExaBox* box, void* data) -{ - PicturePtr pDstPicture; - pixman_image_t *src, *mask, *dest; - int src_xoff, src_yoff, msk_xoff, msk_yoff; - FbBits *bits; - FbStride stride; - int bpp; - - if (box->state == rgnPART) - { - XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL); - XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture && - gOpComposite.pMaskPicture->transform == NULL); - } - - pDstPicture = gOpComposite.pDstPicture; - - src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff); - mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff); - - fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp); - dest = pixman_image_create_bits (pDstPicture->format, - box->pDst->pixmap->drawable.width, - box->pDst->pixmap->drawable.height, - (uint32_t *)bits, stride * sizeof (FbStride)); - XDBG_RETURN_IF_FAIL (dest != NULL); - - pixman_image_composite (gOpComposite.op, - src, mask, dest, - gOpComposite.srcX + box->box.x1, - gOpComposite.srcY + box->box.y1, - gOpComposite.maskX + box->box.x1, - gOpComposite.maskY + box->box.y1, - gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1, - gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1, - box->box.x2 - box->box.x1, - box->box.y2 - box->box.y1); - - free_pixman_pict (gOpComposite.pSrcPicture, src); - free_pixman_pict (gOpComposite.pMaskPicture, mask); - pixman_image_unref (dest); -} - -static void -_swDoUploadToScreen (ExaBox* box, void* data) -{ - FbBits *dst; - FbStride dstStride; - int dstBpp; - _X_UNUSED int dstXoff, dstYoff; - int srcStride; - int dstX, dstY; - int width, height; - - fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); - - srcStride = gOpUTS.src_pitch/sizeof (uint32_t); - dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1; - dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n", - gOpUTS.src, srcStride, dstX, dstY, width, height); - - if(dstBpp < 8) - { - XDBG_WARNING(MEXAS, "dstBpp:%d\n", dstBpp); - return; - } - - if (!pixman_blt ((uint32_t *)gOpUTS.src, - (uint32_t *)dst, - srcStride, - dstStride, - dstBpp, dstBpp, - box->box.x1, box->box.y1, - dstX, dstY, - width, height)) - { - unsigned char *pDst, *pSrc; - int dst_pitch, src_pitch, cpp; - - pDst = (unsigned char*)dst; - pSrc = (unsigned char*)gOpUTS.src; - cpp = dstBpp / 8; - src_pitch = gOpUTS.src_pitch; - dst_pitch = box->pDst->pixmap->devKind; - - pSrc += box->box.y1 * src_pitch + box->box.x1 * cpp; - pDst += dstY * dst_pitch + dstX * cpp; - - for (; height > 0; height--) { - memcpy(pDst, pSrc, width * cpp); - pDst += dst_pitch; - pSrc += src_pitch; - } - } -} - -static void -_swDoDownladFromScreen (ExaBox* box, void* data) -{ - FbBits *src; - FbStride srcStride; - int srcBpp; - _X_UNUSED int srcXoff, srcYoff; - int dstStride; - int srcX, srcY; - int width, height; - - fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff); - - dstStride = gOpDFS.dst_pitch/sizeof (uint32_t); - srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1; - srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1; - width = box->box.x2 - box->box.x1; - height = box->box.y2 - box->box.y1; - - XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", - gOpDFS.dst, dstStride, srcX, srcY, width, height); - - if(srcBpp < 8) - { - XDBG_WARNING(MEXAS, "srcBpp:%d\n", srcBpp); - return; - } - - if (!pixman_blt ((uint32_t *)src, - (uint32_t *)gOpDFS.dst, - srcStride, - dstStride, - srcBpp, srcBpp, - srcX, srcY, - box->box.x1, box->box.y1, - width, height)) - { - unsigned char *pDst, *pSrc; - int dst_pitch, src_pitch, cpp; - - pDst = (unsigned char*)gOpDFS.dst; - pSrc = (unsigned char*)src; - cpp = srcBpp / 8; - src_pitch = box->pSrc->pixmap->devKind; - dst_pitch = gOpDFS.dst_pitch; - - pSrc += srcY * src_pitch + srcX * cpp; - pDst += box->box.y1 * dst_pitch + box->box.x1 * cpp; - - for (; height > 0; height--) { - memcpy(pDst, pSrc, width * cpp); - pDst += dst_pitch; - pSrc += src_pitch; - } - } -} - -static Bool -SECExaSwPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ChangeGCVal tmpval[3]; - - XDBG_TRACE (MEXAS, "\n"); - memset (&gOpSolid, 0x00, sizeof (gOpSolid)); - - /* Put ff at the alpha bits when transparency is set to xv */ - if (pPixmap->drawable.depth == 24) - fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue)); - gOpSolid.alu = alu; - gOpSolid.fg = fg; - gOpSolid.planemask = planemask; - gOpSolid.pixmap = pPixmap; - - gOpSolid.pOpDst = _swPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail); - gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); - - tmpval[0].val = alu; - tmpval[1].val = planemask; - tmpval[2].val = fg; - ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval); - ValidateGC (&pPixmap->drawable, gOpSolid.pGC); - - gOpSolid.bDo = TRUE; - - return TRUE; - -bail: - XDBG_TRACE (MEXAS, "FAIL: pix:%p hint:%d, num_pix:%d\n", - pPixmap, index, pPixmap->usage_hint, gOpSolid.pOpDst->num); - gOpSolid.bDo = FALSE; - gOpSolid.pGC = NULL; - - return TRUE; -} - - -static void -SECExaSwSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2) -{ - XDBG_TRACE (MEXAS, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2); - if (gOpSolid.bDo == FALSE) return; - - gOpSolid.x = x1; - gOpSolid.y = y1; - gOpSolid.w = x2-x1; - gOpSolid.h = y2-y1; - - if (gOpSolid.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = x2-x1; - box.box.y2 = y2-y1; - box.pDst = &gOpSolid.pOpDst->buf[0]; - _swDoSolid (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpSolid.opBox); - - b.x1 = x1; - b.y1 = y1; - b.x2 = x2; - b.y2 = y2; - - for (i=0; i<gOpSolid.pOpDst->num; i++) - { - box = _swBoxAdd (&gOpSolid.opBox, - &gOpSolid.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpSolid.pOpDst->buf[i]; - } - } - _swBoxMove (&gOpSolid.opBox, -x1, -y1); - - /* Call solid function */ - _swDoDraw (&gOpSolid.opBox, - _swDoSolid, NULL); - - /*Remove box list*/ - _swBoxRemoveAll (&gOpSolid.opBox); - } -} - -static void -SECExaSwDoneSolid (PixmapPtr pPixmap) -{ - XDBG_TRACE (MEXAS, "\n"); - if (gOpSolid.pGC) - { - FreeScratchGC (gOpSolid.pGC); - gOpSolid.pGC = NULL; - } - - if (gOpSolid.pixmap) - _swFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST); -} - -static Bool -SECExaSwPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, - int dx, int dy, int alu, Pixel planemask) -{ - int num_dst_pix = -1; - int num_src_pix = -1; - - XDBG_TRACE (MEXAS, "\n"); - memset (&gOpCopy, 0x00, sizeof (gOpCopy)); - - gOpCopy.alu = alu; - gOpCopy.pm = planemask; - gOpCopy.reverse = (dx == 1)?0:1; - gOpCopy.upsidedown = (dy == 1)?0:1; - gOpCopy.pDstPix = pDstPixmap; - gOpCopy.pSrcPix = pSrcPixmap; - - gOpCopy.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST); - XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail); - gOpCopy.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC); - XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail); - - gOpCopy.bDo = TRUE; - - return TRUE; - -bail: - XDBG_TRACE (MEXAS, "FAIL\n"); - XDBG_TRACE (MEXAS, " SRC pix:%p, index:%d, hint:%d, num_pix:%d\n", - pSrcPixmap, index, pSrcPixmap->usage_hint, num_src_pix); - XDBG_TRACE (MEXAS, " DST pix:%p, index:%d, hint:%d, num_pix:%d\n", - pDstPixmap, index, pDstPixmap->usage_hint, num_dst_pix); - gOpCopy.bDo = FALSE; - - return TRUE; -} - - -static void -SECExaSwCopy (PixmapPtr pDstPixmap, int srcX, int srcY, - int dstX, int dstY, int width, int height) -{ - XDBG_TRACE (MEXAS, "src(%d,%d) dst(%d,%d) %dx%d\n", - srcX, srcY, dstX, dstY, width, height); - - if (gOpSolid.bDo == FALSE) return; - - gOpCopy.srcX = srcX; - gOpCopy.srcY = srcY; - gOpCopy.dstX = dstX; - gOpCopy.dstY = dstY; - gOpCopy.width = width; - gOpCopy.height = height; - - if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = width; - box.box.y2 = height; - box.pDst = &gOpCopy.pOpDst->buf[0]; - box.pSrc = &gOpCopy.pOpSrc->buf[0]; - _swDoCopy (&box, NULL); - } - else - { - int i; - struct xorg_list lSrc, lDst; - ExaBox *box; - BoxRec b; - - //Set Dest - b.x1 = dstX; - b.y1 = dstY; - b.x2 = dstX + width; - b.y2 = dstY + height; - xorg_list_init (&lDst); - for (i=0; i<gOpCopy.pOpDst->num; i++) - { - box = _swBoxAdd (&lDst, - &gOpCopy.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpCopy.pOpDst->buf[i]; - } - } - _swBoxMove (&lDst, -dstX, -dstY); - - //Set Src - b.x1 = srcX; - b.y1 = srcY; - b.x2 = srcX + width; - b.y2 = srcY + height; - - xorg_list_init (&lSrc); - for (i=0; i<gOpCopy.pOpSrc->num; i++) - { - box = _swBoxAdd (&lSrc, - &gOpCopy.pOpSrc->buf[i].pos, - &b); - if (box) - { - box->pSrc = &gOpCopy.pOpSrc->buf[i]; - } - } - _swBoxMove (&lSrc, -srcX, -srcY); - - //Merge and call copy - xorg_list_init (&gOpCopy.opBox); - _swBoxMerge (&gOpCopy.opBox, &lSrc, &lDst); - _swDoDraw (&gOpCopy.opBox, - _swDoCopy, NULL); - - //Remove box list - _swBoxRemoveAll (&lSrc); - _swBoxRemoveAll (&lDst); - _swBoxRemoveAll (&gOpCopy.opBox); - } -} - -static void -SECExaSwDoneCopy (PixmapPtr pDstPixmap) -{ - XDBG_TRACE (MEXAS, "\n"); - - if (gOpCopy.pDstPix) - _swFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST); - if (gOpCopy.pSrcPix) - _swFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC); -} - -static Bool -SECExaSwCheckComposite (int op, PicturePtr pSrcPicture, - PicturePtr pMaskPicture, PicturePtr pDstPicture) -{ - return TRUE; -} - -static Bool -SECExaSwPrepareComposite (int op, PicturePtr pSrcPicture, - PicturePtr pMaskPicture, PicturePtr pDstPicture, - PixmapPtr pSrcPixmap, - PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap) -{ - XDBG_TRACE (MEXAS, "\n"); - memset (&gOpComposite, 0x00, sizeof (gOpComposite)); - XDBG_GOTO_IF_FAIL (pDstPixmap != NULL, bail); - - gOpComposite.op = op; - gOpComposite.pDstPicture = pDstPicture; - gOpComposite.pSrcPicture = pSrcPicture; - gOpComposite.pMaskPicture = pMaskPicture; - gOpComposite.pSrcPixmap = pSrcPixmap; - gOpComposite.pMaskPixmap = pMaskPixmap; - gOpComposite.pDstPixmap = pDstPixmap; - - gOpComposite.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST); - - if (pSrcPixmap) - { - gOpComposite.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC); - XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail); - } - - if (pMaskPixmap) - { - gOpComposite.pOpMask = _swPrepareAccess (pMaskPixmap, EXA_PREPARE_MASK); - XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail); - } - - gOpComposite.bDo = TRUE; - - return TRUE; - -bail: - XDBG_TRACE (MEXAS, "FAIL: op%d\n", op); - XDBG_TRACE (MEXAS, " SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap); - XDBG_TRACE (MEXAS, " MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap); - XDBG_TRACE (MEXAS, " DST picture:%p pix:%p\n", pDstPicture, pDstPixmap); - - gOpComposite.bDo = FALSE; - - return TRUE; -} - -static void -SECExaSwComposite (PixmapPtr pDstPixmap, int srcX, int srcY, - int maskX, int maskY, int dstX, int dstY, - int width, int height) -{ - XDBG_TRACE (MEXAS, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n", - srcX, srcY, - maskX, maskY, - dstX, dstY, - width, height); - if (!gOpComposite.bDo) return; - - gOpComposite.srcX = srcX; - gOpComposite.srcY = srcY; - gOpComposite.maskX = maskX; - gOpComposite.maskY = maskY; - gOpComposite.dstX = dstX; - gOpComposite.dstY = dstY; - gOpComposite.width = width; - gOpComposite.height = height; - - if (gOpComposite.pOpDst->isSame) - { - ExaBox box; - - box.state = rgnIN; - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = width; - box.box.y2 = height; - box.pDst = &gOpComposite.pOpDst->buf[0]; - box.pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL; - box.pSrc = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL; - - _swDoComposite (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpComposite.opBox); - - b.x1 = dstX; - b.y1 = dstY; - b.x2 = dstX+width; - b.y2 = dstY+height; - - for (i=0; i<gOpComposite.pOpDst->num; i++) - { - box = _swBoxAdd (&gOpComposite.opBox, - &gOpComposite.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpComposite.pOpDst->buf[i]; - box->pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL; - box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL; - } - } - _swBoxMove (&gOpComposite.opBox, -dstX, -dstY); - - /* Call solid function */ - _swDoDraw (&gOpComposite.opBox, - _swDoComposite, NULL); - - /*Remove box list*/ - _swBoxRemoveAll (&gOpComposite.opBox); - } -} - -/* done composite : sw done composite, not using pvr2d */ -static void -SECExaSwDoneComposite (PixmapPtr pDst) -{ - XDBG_TRACE (MEXAS, "\n"); - if (gOpComposite.pDstPixmap != NULL) - _swFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST); - if (gOpComposite.pSrcPixmap != NULL) - _swFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC); - if (gOpComposite.pMaskPixmap != NULL) - _swFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK); -} - -static Bool -SECExaSwUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h, - char *src, int src_pitch) -{ - XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE); - XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h); - XDBG_TRACE (MEXAS, "\tdst depth:%d, bpp:%d, pitch:%d, %dx%d\n", - pDst->drawable.depth, pDst->drawable.bitsPerPixel, pDst->devKind, - pDst->drawable.width, pDst->drawable.height); - - gOpUTS.pDst = pDst; - gOpUTS.x = x; - gOpUTS.y = y; - gOpUTS.w = w; - gOpUTS.h = h; - gOpUTS.src = src; - gOpUTS.src_pitch = src_pitch; - gOpUTS.pOpDst = _swPrepareAccess (pDst, EXA_PREPARE_DEST); - - if (gOpUTS.pOpDst->isSame) - { - ExaBox box; - - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = w; - box.box.y2 = h; - box.state = rgnIN; - box.pDst = &gOpUTS.pOpDst->buf[0]; - _swDoUploadToScreen (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpUTS.opBox); - - b.x1 = x; - b.y1 = y; - b.x2 = x+w; - b.y2 = y+h; - - for (i=0; i<gOpUTS.pOpDst->num; i++) - { - box = _swBoxAdd (&gOpUTS.opBox, - &gOpUTS.pOpDst->buf[i].pos, - &b); - if (box) - { - box->pDst = &gOpUTS.pOpDst->buf[i]; - } - } - _swBoxMove (&gOpUTS.opBox, -x, -y); - - /* Call solid function */ - _swDoDraw (&gOpUTS.opBox, - _swDoUploadToScreen, NULL); - - /*Remove box list*/ - _swBoxRemoveAll (&gOpUTS.opBox); - } - - _swFinishAccess (pDst, EXA_PREPARE_DEST); - return TRUE; -} - - - -static Bool -SECExaSwDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h, - char *dst, int dst_pitch) -{ - XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE); - XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h); - - gOpDFS.pSrc = pSrc; - gOpDFS.x = x; - gOpDFS.y = y; - gOpDFS.w = w; - gOpDFS.h = h; - gOpDFS.dst = dst; - gOpDFS.dst_pitch = dst_pitch; - gOpDFS.pOpSrc = _swPrepareAccess (pSrc, EXA_PREPARE_SRC); - - if (gOpDFS.pOpSrc->isSame) - { - ExaBox box; - - box.box.x1 = 0; - box.box.y1 = 0; - box.box.x2 = w; - box.box.y2 = h; - box.state = rgnIN; - box.pSrc = &gOpDFS.pOpSrc->buf[0]; - _swDoDownladFromScreen (&box, NULL); - } - else - { - int i; - ExaBox *box; - BoxRec b; - - /*Init box list*/ - xorg_list_init (&gOpDFS.opBox); - - b.x1 = x; - b.y1 = y; - b.x2 = x+w; - b.y2 = y+h; - - for (i=0; i<gOpDFS.pOpSrc->num; i++) - { - box = _swBoxAdd (&gOpDFS.opBox, - &gOpDFS.pOpSrc->buf[i].pos, - &b); - if (box) - { - box->pSrc = &gOpDFS.pOpSrc->buf[i]; - } - } - _swBoxMove (&gOpDFS.opBox, -x, -y); - - /* Call solid function */ - _swDoDraw (&gOpDFS.opBox, - _swDoDownladFromScreen, NULL); - - /*Remove box list*/ - _swBoxRemoveAll (&gOpDFS.opBox); - } - - _swFinishAccess (pSrc, EXA_PREPARE_SRC); - return TRUE; -} - -int SECExaMarkSync(ScreenPtr pScreen) -{ - XDBG_RETURN_VAL_IF_FAIL (pScreen != NULL, TRUE); - int ret=0; - - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR(pScrn); - - if( pSec && pSec->is_fb_touched == TRUE ) - { - XDBG_TRACE(MEXAS, "UpdateRequest to the display!\n"); - - ret = secDisplayUpdateRequest(pScrn); - pSec->is_fb_touched = FALSE; - } - - return ret; -} - -Bool secExaSwInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - pExaDriver->PrepareSolid = SECExaSwPrepareSolid; - pExaDriver->Solid = SECExaSwSolid; - pExaDriver->DoneSolid = SECExaSwDoneSolid; - - pExaDriver->PrepareCopy = SECExaSwPrepareCopy; - pExaDriver->Copy = SECExaSwCopy; - pExaDriver->DoneCopy = SECExaSwDoneCopy; - - pExaDriver->CheckComposite = SECExaSwCheckComposite; - pExaDriver->PrepareComposite = SECExaSwPrepareComposite; - pExaDriver->Composite = SECExaSwComposite; - pExaDriver->DoneComposite = SECExaSwDoneComposite; - - pExaDriver->UploadToScreen = SECExaSwUploadToScreen; - pExaDriver->DownloadFromScreen = SECExaSwDownloadFromScreen; - - pExaDriver->MarkSync = SECExaMarkSync; - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "Succeed to Initialize SW EXA\n"); - - return TRUE; -} - -void secExaSwDeinit (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "Succeed to finish SW EXA\n"); -} diff --git a/src/crtcconfig/exynos_crtc.c b/src/crtcconfig/exynos_crtc.c new file mode 100755 index 0000000..e4f6293 --- /dev/null +++ b/src/crtcconfig/exynos_crtc.c @@ -0,0 +1,2967 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011-2012 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <poll.h> + +#include <xace.h> +#include <xacestr.h> +#include <xorgVersion.h> +#include <tbm_bufmgr.h> +#include <xf86Crtc.h> +#include <xf86DDC.h> +#include <xf86cmap.h> +#include <xf86Xinput.h> +#include <exevents.h> +#include <list.h> +#include <X11/Xatom.h> +#include <X11/extensions/dpmsconst.h> +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_plane.h" +#include "exynos_layer.h" +#include "exynos_accel.h" +#include "exynos_drm_ipp.h" +#include "fimg2d.h" +#include "xf86RandR12.h" +#include "exynos_hwc.h" +#include "exynos_layer_manager.h" + +static void _cursorRegisterBlockHandler(xf86CrtcPtr pCrtc); +static void _cursorUnregisterBlockHandler(xf86CrtcPtr pCrtc); +static void _cursorShow(xf86CrtcPtr pCrtc); +static void _cursorMove(xf86CrtcPtr pCrtc, int x, int y); +static void _cursorDrawCursor(xf86CrtcPtr pCrtc); + +static Atom atom_rotate_root_angle; +static Atom atom_relative_device_exist; + +static int +_overlayGetXMoveOffset(xf86CrtcPtr pCrtc, int x) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + int offset = 0; + + if (pCrtcPriv->pipe != 0) + return 0; + + offset = x + EXYNOS_CURSOR_W - pExynosMode->main_lcd_mode.hdisplay; + + return (offset > 0) ? offset : 0; +} + +static Bool +_overlayEnsureBuffer(xf86CrtcPtr pCrtc, Bool move_layer) +{ + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + if (move_layer) { + if (!pCrtcPriv->ovl_vbuf_cursor) { + pCrtcPriv->ovl_vbuf_cursor = + exynosUtilAllocVideoBuffer(pCrtc->scrn, FOURCC_RGB32, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H, + FALSE, TRUE, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->ovl_vbuf_cursor != NULL, FALSE); + XDBG_TRACE(MCRS, "[%p] ovl_vbuf_cursor(%p) %dx%d created. \n", + pCrtc, pCrtcPriv->ovl_vbuf_cursor, EXYNOS_CURSOR_W, + EXYNOS_CURSOR_H); + } + } + else { + if (!pCrtcPriv->ovl_vbuf_pixmap) { + pCrtcPriv->ovl_vbuf_pixmap = + exynosUtilAllocVideoBuffer(pCrtc->scrn, FOURCC_RGB32, + pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay, + FALSE, TRUE, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->ovl_vbuf_pixmap != NULL, FALSE); + XDBG_TRACE(MCRS, "[%p] ovl_vbuf_pixmap(%p) %dx%d created. \n", + pCrtc, pCrtcPriv->ovl_vbuf_pixmap, + pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay); + } + } + + return TRUE; +} + +static Bool +_overlayEnsureLayer(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + int connector_type; + EXYNOSLayerOutput output = LAYER_OUTPUT_LCD; + + if (pCrtcPriv->ovl_layer) + return TRUE; + + connector_type = exynosCrtcGetConnectType(pCrtc); + + if (connector_type == DRM_MODE_CONNECTOR_LVDS || + connector_type == DRM_MODE_CONNECTOR_Unknown) { + output = LAYER_OUTPUT_LCD; + } + else if (connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector_type == DRM_MODE_CONNECTOR_HDMIB || + connector_type == DRM_MODE_CONNECTOR_VIRTUAL) { + output = LAYER_OUTPUT_EXT; + } + else { + XDBG_NEVER_GET_HERE(MDISP); + return FALSE; + } +#ifndef LAYER_MANAGER + EXYNOSLayer *layer; + + layer = exynosLayerFind(output, LAYER_UPPER); + XDBG_RETURN_VAL_IF_FAIL(layer == NULL, FALSE); +#endif + pCrtcPriv->ovl_layer = exynosLayerCreate(pCrtc->scrn, output, LAYER_UPPER); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->ovl_layer != NULL, FALSE); + + XDBG_TRACE(MCRS, "[%p] ovl_layer(%p) created. \n", pCrtc, + pCrtcPriv->ovl_layer); + + return TRUE; +} + +static Bool +_overlaySelectBuffer(xf86CrtcPtr pCrtc, Bool move_layer) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + + if (!_overlayEnsureLayer(pCrtc)) + return FALSE; + + if (!_overlayEnsureBuffer(pCrtc, move_layer)) + return FALSE; + + if (move_layer) { + if (exynosLayerGetBuffer(pCrtcPriv->ovl_layer) == + pCrtcPriv->ovl_vbuf_cursor) + return TRUE; + + exynosLayerFreezeUpdate(pCrtcPriv->ovl_layer, TRUE); + _cursorDrawCursor(pCrtc); + exynosLayerSetBuffer(pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_cursor); + exynosLayerFreezeUpdate(pCrtcPriv->ovl_layer, FALSE); + + int offset = _overlayGetXMoveOffset(pCrtc, pCrtcPriv->cursor_win_x); + + _cursorMove(pCrtc, pCrtcPriv->cursor_win_x - offset, + pCrtcPriv->cursor_win_y); + + XDBG_TRACE(MCRS, "[%p] Set ovl_vbuf_cursor. \n", pCrtc); + } + else { + xRectangle rect = { 0, }; + + if (exynosLayerGetBuffer(pCrtcPriv->ovl_layer) == + pCrtcPriv->ovl_vbuf_pixmap) + return TRUE; + + rect.width = pExynosMode->main_lcd_mode.hdisplay; + rect.height = pExynosMode->main_lcd_mode.vdisplay; + exynosLayerFreezeUpdate(pCrtcPriv->ovl_layer, TRUE); + exynosLayerSetBuffer(pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_pixmap); + exynosLayerFreezeUpdate(pCrtcPriv->ovl_layer, FALSE); + + exynosLayerSetRect(pCrtcPriv->ovl_layer, &rect, &rect); + + XDBG_TRACE(MCRS, "[%p] Set ovl_vbuf_pixmap. \n", pCrtc); + } + + return TRUE; +} + +static Bool +_cursorEnsureCursorImage(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + int x, y, cursor_x, cursor_y; + int win_x, win_y; + int rotate; + int tx = 0, ty = 0; + double c, s; + pixman_transform_t t; + + x = pCrtcPriv->cursor_pos_x; + y = pCrtcPriv->cursor_pos_y; + + //Determine cursor image transform + rotate = exynosUtilRotateAdd(pExynos->rotate, pCrtcPriv->user_rotate); + + //Transform cursor position and screen size + switch (pExynos->rotate) { + case RR_Rotate_0: + default: + cursor_x = x; + cursor_y = y; + break; + case RR_Rotate_90: + cursor_x = y; + cursor_y = pCrtc->scrn->virtualX - 1 - x; + break; + case RR_Rotate_180: + cursor_x = pCrtc->scrn->virtualX - 1 - x; + cursor_y = pCrtc->scrn->virtualY - 1 - y; + break; + case RR_Rotate_270: + cursor_x = pCrtc->scrn->virtualY - 1 - y; + cursor_y = x; + break; + } + + switch (rotate) { + case RR_Rotate_0: + default: + c = 1.0; + s = 0.0; + win_x = cursor_x; + win_y = cursor_y; + break; + case RR_Rotate_90: + c = 0.0; + s = 1.0; + tx = EXYNOS_CURSOR_W; + ty = 0; + + win_x = cursor_x; + win_y = cursor_y - EXYNOS_CURSOR_W; + break; + case RR_Rotate_180: + c = -1.0; + s = 0.0; + tx = EXYNOS_CURSOR_W; + ty = EXYNOS_CURSOR_H; + + win_x = cursor_x - EXYNOS_CURSOR_W; + win_y = cursor_y - EXYNOS_CURSOR_H; + break; + case RR_Rotate_270: + c = 0.0; + s = -1.0; + tx = 0; + ty = EXYNOS_CURSOR_H; + + win_x = cursor_x - EXYNOS_CURSOR_H; + win_y = cursor_y; + break; + } + + pCrtcPriv->cursor_win_x = win_x; + pCrtcPriv->cursor_win_y = win_y; + + if (pCrtcPriv->cursor_image == NULL) { + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->backup_image != NULL, FALSE); + + XDBG_DEBUG(MCRS, "[%p] (%d + %d) => %d \n", pCrtc, + pExynos->rotate, pCrtcPriv->user_rotate, rotate); + + if (rotate == RR_Rotate_0) { + pCrtcPriv->cursor_image = pCrtcPriv->backup_image; + pixman_image_ref(pCrtcPriv->cursor_image); + } + else { + //Clear cursor image + pCrtcPriv->cursor_image = + pixman_image_create_bits(PIXMAN_a8r8g8b8, EXYNOS_CURSOR_W, + EXYNOS_CURSOR_H, NULL, 0); + + //Copy Cursor image + pixman_transform_init_rotate(&t, pixman_double_to_fixed(c), + pixman_double_to_fixed(s)); + pixman_transform_translate(&t, NULL, pixman_int_to_fixed(tx), + pixman_int_to_fixed(ty)); + pixman_image_set_transform(pCrtcPriv->backup_image, &t); + pixman_image_composite(PIXMAN_OP_SRC, pCrtcPriv->backup_image, NULL, + pCrtcPriv->cursor_image, 0, 0, 0, 0, 0, 0, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + pixman_transform_init_rotate(&t, pixman_double_to_fixed(1.0), + pixman_double_to_fixed(0.0)); + pixman_image_set_transform(pCrtcPriv->backup_image, &t); + } + } + + return TRUE; +} + +static Bool +_cursorEnsureCanvas(xf86CrtcPtr pCrtc, EXYNOSVideoBuf * vbuf, int width, + int height) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + tbm_bo_handle bo_handle; + + if (pCrtcPriv->ovl_canvas) + return TRUE; + + if (!_overlayEnsureBuffer(pCrtc, pCrtcPriv->move_layer)) + return FALSE; + + XDBG_RETURN_VAL_IF_FAIL(vbuf != NULL, FALSE); + + bo_handle = tbm_bo_get_handle(vbuf->bo[0], TBM_DEVICE_CPU); + XDBG_RETURN_VAL_IF_FAIL(bo_handle.ptr != NULL, FALSE); + + pCrtcPriv->ovl_canvas = pixman_image_create_bits(PIXMAN_a8r8g8b8, + width, height, + (uint32_t *) bo_handle.ptr, + width * 4); + + XDBG_TRACE(MCRS, "[%p] ovl_canvas(%p) %dx%d created.\n", pCrtc, + pCrtcPriv->ovl_canvas, width, height); + + return TRUE; +} + +static Bool +_cursorEnsureSavedImage(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + if (pCrtcPriv->saved_image) + return TRUE; + + pCrtcPriv->saved_image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + EXYNOS_CURSOR_W, + EXYNOS_CURSOR_H, NULL, 0); + XDBG_TRACE(MCRS, "[%p] saved_image(%p) %dx%d created.\n", pCrtc, + pCrtcPriv->saved_image, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + + return TRUE; +} + +static void +_cursorSaveImage(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + + XDBG_RETURN_IF_FAIL(pCrtcPriv->move_layer == FALSE); + + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_pixmap, + pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay); + + _cursorEnsureSavedImage(pCrtc); + + pixman_image_composite(PIXMAN_OP_SRC, + pCrtcPriv->ovl_canvas, + NULL, + pCrtcPriv->saved_image, + pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y, + 0, 0, 0, 0, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + + pCrtcPriv->saved_box.x1 = pCrtcPriv->cursor_win_x; + pCrtcPriv->saved_box.y1 = pCrtcPriv->cursor_win_y; + pCrtcPriv->saved_box.x2 = pCrtcPriv->cursor_win_x + EXYNOS_CURSOR_W; + pCrtcPriv->saved_box.y2 = pCrtcPriv->cursor_win_y + EXYNOS_CURSOR_H; + + XDBG_DEBUG(MCRS, "[%p] (%d,%d %dx%d) saved. \n", pCrtc, + pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); +} + +static void +_cursorRestoreImage(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + if (!pCrtcPriv->saved_image || !pCrtcPriv->ovl_canvas) + return; + + pixman_image_composite(PIXMAN_OP_SRC, + pCrtcPriv->saved_image, + NULL, + pCrtcPriv->ovl_canvas, + 0, 0, 0, 0, + pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + + if (pCrtcPriv->ovl_layer && exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerUpdate(pCrtcPriv->ovl_layer); + + XDBG_DEBUG(MCRS, "[%p] (%d,%d %dx%d) restored. \n", pCrtc, + pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); +} + +static void +_cursorDrawCursor(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + int x, y; + + XDBG_RETURN_IF_FAIL(pCrtcPriv->ovl_canvas != NULL); + XDBG_RETURN_IF_FAIL(pCrtcPriv->cursor_image != NULL); + + if (pCrtcPriv->move_layer) { + /* clear */ + pixman_color_t color = { 0, }; + pixman_rectangle16_t rect = { 0, 0, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H }; + pixman_image_fill_rectangles(PIXMAN_OP_CLEAR, pCrtcPriv->ovl_canvas, + &color, 1, &rect); + + x = _overlayGetXMoveOffset(pCrtc, pCrtcPriv->cursor_win_x); + y = 0; + } + else { + x = pCrtcPriv->cursor_win_x; + y = pCrtcPriv->cursor_win_y; + } + + pixman_image_composite(PIXMAN_OP_OVER, + pCrtcPriv->cursor_image, + NULL, + pCrtcPriv->ovl_canvas, + 0, 0, 0, 0, x, y, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + + XDBG_DEBUG(MCRS, "[%p] (%d,%d %dx%d) drawn. \n", pCrtc, + x, y, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + + exynosUtilCacheFlush(pCrtc->scrn); + + if (pCrtcPriv->ovl_layer && exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerUpdate(pCrtcPriv->ovl_layer); +} + +static void +_cursorReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + xf86CrtcPtr pCrtc = (xf86CrtcPtr) closure; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + if (pCrtcPriv->move_layer) + return; + + if (!pExynos->enableCursor || !pCrtcPriv->cursor_show) + return; + + if (RegionContainsRect(pRegion, &pCrtcPriv->saved_box) != rgnOUT) { + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); + pCrtcPriv->need_cursor_update = TRUE; + _cursorRestoreImage(pCrtc); + _cursorRegisterBlockHandler(pCrtc); + } +} + +static void +_cursorDamageDestroy(DamagePtr pDamage, void *closure) +{ + xf86CrtcPtr pCrtc = (xf86CrtcPtr) closure; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + if (!pExynos->ovl_damage) + return; + + pExynos->ovl_damage = NULL; +} + +static void +_cursorBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + xf86CrtcPtr pCrtc = (xf86CrtcPtr) data; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + XDBG_RETURN_IF_FAIL(pCrtcPriv->move_layer == FALSE); + + if (pExynos->ovl_drawable) { + if (pExynos->ovl_damage == NULL) { + pExynos->ovl_damage = + DamageCreate((DamageReportFunc) _cursorReportDamage, + (DamageDestroyFunc) _cursorDamageDestroy, + DamageReportRawRegion, TRUE, pCrtc->scrn->pScreen, + pCrtc); + XDBG_RETURN_IF_FAIL(pExynos->ovl_damage); + DamageRegister(pExynos->ovl_drawable, pExynos->ovl_damage); + } + } + else { + if (pExynos->ovl_damage) { + DamageDestroy(pExynos->ovl_damage); + pExynos->ovl_damage = NULL; + } + } + + XDBG_DEBUG(MCRS, + "[%p] enable(%d) cursor_show(%d) need_update(%d) show(%d) \n", + pCrtc, pExynos->enableCursor, pCrtcPriv->cursor_show, + pCrtcPriv->need_cursor_update, pCrtcPriv->cursor_show); + + if (pExynos->enableCursor && pCrtcPriv->need_cursor_update) { + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + + _cursorEnsureCursorImage(pCrtc); + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_pixmap, + pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay); + + _cursorSaveImage(pCrtc); + + /*Draw Cursor */ + if (pCrtcPriv->cursor_show) + _cursorDrawCursor(pCrtc); + + _overlaySelectBuffer(pCrtc, pCrtcPriv->move_layer); + _cursorMove(pCrtc, pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y); + + pCrtcPriv->need_cursor_update = FALSE; + } + + if (!exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerShow(pCrtcPriv->ovl_layer); + + if (!pExynos->enableCursor || !pCrtcPriv->cursor_show || + !pCrtcPriv->need_cursor_update) + _cursorUnregisterBlockHandler(pCrtc); +} + +static Bool +_cursorSetPointerDeviceRotate(DeviceIntPtr dev, int rotate) +{ +#define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion" /* BOOL, 2 values [x, y], 1 inverts axis */ +#define EVDEV_PROP_SWAP_AXES "Evdev Axes Swap" /* BOOL */ + + int swap = 0; + char inv[2]; + + static Atom swap_axes = 0; + static Atom invert_axes = 0; + int rc; + + if (!dev) + return FALSE; + + XDBG_TRACE(MCRS, "device %s (valuator:%p)\n", dev->name, dev->valuator); + + if (!swap_axes) + swap_axes = + MakeAtom(EVDEV_PROP_SWAP_AXES, strlen(EVDEV_PROP_SWAP_AXES), TRUE); + + if (!invert_axes) + invert_axes = + MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), + TRUE); + + switch (rotate) { + case RR_Rotate_0: + swap = 0; + inv[0] = 0; + inv[1] = 0; + break; + case RR_Rotate_90: + swap = 1; + inv[0] = 0; + inv[1] = 1; + break; + case RR_Rotate_180: + swap = 0; + inv[0] = 1; + inv[1] = 1; + break; + case RR_Rotate_270: + swap = 1; + inv[0] = 1; + inv[1] = 0; + break; + default: + XDBG_ERROR(MCRS, "Error.. cursor_rotate:%d\n", rotate); + return FALSE; + } + + XDBG_TRACE(MCRS, "%s change(swap:%d, inv:%d,%d rotate:%d)\n", dev->name, + swap, inv[0], inv[1], rotate); + rc = XIChangeDeviceProperty(dev, swap_axes, XA_INTEGER, 8, PropModeReplace, + 1, &swap, TRUE); + if (rc != Success) { + XDBG_ERROR(MCRS, "Fail change swap(%s , swap:%d)\n", dev->name, swap); + } + + rc = XIChangeDeviceProperty(dev, invert_axes, XA_INTEGER, 8, + PropModeReplace, 2, inv, TRUE); + if (rc != Success) { + XDBG_ERROR(MCRS, "Fail change invert(%s , invert:%d,%d)\n", dev->name, + inv[0], inv[1]); + } + + return TRUE; +} + +static Bool +_cursorFindRelativeDevice(xf86CrtcPtr pCrtc) +{ + if (pCrtc == NULL) { + return FALSE; + } + InputInfoPtr localDevices; + DeviceIntPtr dev; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); + + localDevices = xf86FirstLocalDevice(); + while (localDevices) { + dev = localDevices->dev; + _cursorSetPointerDeviceRotate(dev, pCrtcPriv->user_rotate); + localDevices = localDevices->next; + } + + return TRUE; +} + +static void +_cursorRotateHook(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + ScrnInfoPtr pScrn = (ScrnInfoPtr) unused; + xf86CrtcPtr pCrtc = xf86CompatCrtc(pScrn); + + if (pCrtc == NULL) + return; + XacePropertyAccessRec *rec = (XacePropertyAccessRec *) calldata; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + /* Don't care about the new content check */ + if (rec->pWin != pScrn->pScreen->root) //Check Rootwindow + return; + + if (name == atom_rotate_root_angle && (rec->access_mode & DixWriteAccess)) { + int rotate_degree = *(int *) pProp->data; + + XDBG_TRACE(MCRS, "[%p] Change root angle(%d)\n", pCrtc, rotate_degree); + exynosCrtcCursorRotate(pCrtc, exynosUtilDegreeToRotate(rotate_degree)); + } + + if (name == atom_relative_device_exist + && (rec->access_mode & DixWriteAccess)) { + int exist = *(int *) pProp->data; + + if (exist) { + _cursorFindRelativeDevice(pCrtc); + XDBG_TRACE(MCRS, "[%p] Change device exist(%d)\n", pCrtc, exist); + } + } + + return; +} + +static void +_cursorRegisterBlockHandler(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + XDBG_RETURN_IF_FAIL(pCrtcPriv->move_layer == FALSE); + + if (pCrtcPriv->registered_block_handler) + return; + + XDBG_DEBUG(MCRS, "[%p] \n", pCrtc); + + RegisterBlockAndWakeupHandlers(_cursorBlockHandler, + (WakeupHandlerProcPtr) NoopDDA, pCrtc); + + pCrtcPriv->registered_block_handler = TRUE; +} + +static void +_cursorUnregisterBlockHandler(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + if (!pCrtcPriv->registered_block_handler) + return; + + XDBG_DEBUG(MCRS, "[%p] \n", pCrtc); + + RemoveBlockAndWakeupHandlers(_cursorBlockHandler, + (WakeupHandlerProcPtr) NoopDDA, pCrtc); + + pCrtcPriv->registered_block_handler = FALSE; +} + +static void +_cursorMove(xf86CrtcPtr pCrtc, int x, int y) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + if (!pCrtcPriv->move_layer) + return; + + if (pCrtcPriv->ovl_layer) { + xRectangle src = { 0, }; + xRectangle dst = { 0, }; + + src.width = EXYNOS_CURSOR_W; + src.height = EXYNOS_CURSOR_H; + + dst.x = x; + dst.y = y; + dst.width = EXYNOS_CURSOR_W; + dst.height = EXYNOS_CURSOR_H; + + XDBG_DEBUG(MCRS, "[%p] to (%d,%d)\n", pCrtc, x, y); + + exynosLayerSetRect(pCrtcPriv->ovl_layer, &src, &dst); + } +} + +static void +_cursorInit(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); + + //Damage Create + if (!pCrtcPriv->move_layer) + _cursorRegisterBlockHandler(pCrtc); +} + +static int +_cursorDestroy(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); + + if (pCrtcPriv->saved_image) { + pixman_image_unref(pCrtcPriv->saved_image); + pCrtcPriv->saved_image = NULL; + } + + if (pCrtcPriv->cursor_image) { + pixman_image_unref(pCrtcPriv->cursor_image); + pCrtcPriv->cursor_image = NULL; + } + + if (pCrtcPriv->ovl_canvas) { + XDBG_TRACE(MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, + pCrtcPriv->ovl_canvas); + pixman_image_unref(pCrtcPriv->ovl_canvas); + pCrtcPriv->ovl_canvas = NULL; + pCrtcPriv->need_draw_cursor = TRUE; + } + + if (pCrtcPriv->ovl_layer) { + XDBG_TRACE(MCRS, "[%p] ovl_layer(%p) destroy.\n", pCrtc, + pCrtcPriv->ovl_layer); + exynosLayerUnref(pCrtcPriv->ovl_layer); + pCrtcPriv->ovl_layer = NULL; + } + + return TRUE; +} + +static void +_cursorShow(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + if (!pExynos->enableCursor) + return; + + if (pCrtcPriv->ovl_layer && !exynosLayerTurnStatus(pCrtcPriv->ovl_layer)) + exynosLayerTurn(pCrtcPriv->ovl_layer, TRUE, FALSE); + + XDBG_TRACE(MCRS, "[%p] user_rotate(%d)\n", pCrtc, pCrtcPriv->user_rotate); + + if (pCrtcPriv->move_layer) { + _overlayEnsureBuffer(pCrtc, pCrtcPriv->move_layer); + _overlayEnsureLayer(pCrtc); + + _cursorEnsureCursorImage(pCrtc); + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_cursor, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + _cursorDrawCursor(pCrtc); + + _overlaySelectBuffer(pCrtc, pCrtcPriv->move_layer); + + int offset = _overlayGetXMoveOffset(pCrtc, pCrtcPriv->cursor_win_x); + + _cursorMove(pCrtc, pCrtcPriv->cursor_win_x - offset, + pCrtcPriv->cursor_win_y); + + if (!exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerShow(pCrtcPriv->ovl_layer); + } + else { + pCrtcPriv->need_cursor_update = TRUE; + _cursorRestoreImage(pCrtc); + _cursorRegisterBlockHandler(pCrtc); + } +} + +static void +_cursorHide(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); + + if (pCrtcPriv->move_layer) { + if (pCrtcPriv->ovl_layer && exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerHide(pCrtcPriv->ovl_layer); + } + else { + _cursorRestoreImage(pCrtc); + + if (pCrtcPriv->need_off && !pCrtcPriv->cursor_show) { + if (pCrtcPriv->ovl_layer && + exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerHide(pCrtcPriv->ovl_layer); + return; + } + } + + if (pCrtcPriv->ovl_layer && exynosLayerTurnStatus(pCrtcPriv->ovl_layer)) { + Bool turnoff = FALSE; + + if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off) + turnoff = TRUE; + if (!pCrtcPriv->ref_overlay) + turnoff = TRUE; + + if (turnoff) + _cursorDestroy(pCrtc); + } + + pCrtcPriv->cursor_old_offset = 0; + pCrtcPriv->need_cursor_update = TRUE; +} + +static Bool +_cursorEnable(xf86CrtcPtr pCrtc, Bool enable) +{ + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + if (!pCrtcPriv->cursor_show) + return FALSE; + + XDBG_TRACE(MCRS, "[%p] enable(%d) \n", pCrtc, enable); + + if (enable) { + _cursorShow(pCrtc); + + if (pCrtc == xf86CompatCrtc(pScrn)) { + PropertyPtr rotate_prop; + + /* Set Current Root Rotation */ + rotate_prop = exynosUtilGetWindowProperty(pScrn->pScreen->root, + "_E_ILLUME_ROTATE_ROOT_ANGLE"); + if (rotate_prop) { + int rotate = + exynosUtilDegreeToRotate(*(int *) rotate_prop->data); + + pCrtcPriv->user_rotate = rotate; + + //Send swap property to relative input device + _cursorFindRelativeDevice(pCrtc); + } + } + + /* Hook for window rotate */ + atom_rotate_root_angle = + MakeAtom("_E_ILLUME_ROTATE_ROOT_ANGLE", + strlen("_E_ILLUME_ROTATE_ROOT_ANGLE"), FALSE); + atom_relative_device_exist = + MakeAtom("X Mouse Exist", strlen("X Mouse Exist"), TRUE); + + if (atom_rotate_root_angle != None) { + if (!XaceRegisterCallback + (XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn)) + XDBG_ERROR(MCRS, + "[%p] Fail XaceRegisterCallback:XACE_PROPERTY_ACCESS\n", + pCrtc); + + XDBG_TRACE(MCRS, + "[%p] Hook property : _E_ILLUME_ROTATE_ROOT_ANGLE\n", + pCrtc); + } + else + XDBG_TRACE(MCRS, "[%p] Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n", + pCrtc); + } + else { + XaceDeleteCallback(XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn); + + _cursorHide(pCrtc); + } + + pCrtcPriv->cursor_old_offset = 0; + + return TRUE; +} + +static Bool +_cursorRotate(xf86CrtcPtr pCrtc, int rotate) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + if (pCrtcPriv->user_rotate == rotate) + return TRUE; + + if (!pCrtcPriv->cursor_show) + return TRUE; + + XDBG_TRACE(MCRS, "[%p] rotate(%d) \n", pCrtc, rotate); + + pCrtcPriv->user_rotate = rotate; + + if (pExynos->enableCursor && pCrtcPriv->cursor_show) { + //Send swap property to relative input device + _cursorFindRelativeDevice(pCrtc); + + if (pCrtcPriv->cursor_image) { + pixman_image_unref(pCrtcPriv->cursor_image); + pCrtcPriv->cursor_image = NULL; + } + + if (pCrtcPriv->move_layer) { + _overlayEnsureBuffer(pCrtc, pCrtcPriv->move_layer); + _overlayEnsureLayer(pCrtc); + + _cursorEnsureCursorImage(pCrtc); + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_cursor, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + _cursorDrawCursor(pCrtc); + + int offset = _overlayGetXMoveOffset(pCrtc, pCrtcPriv->cursor_win_x); + + _cursorMove(pCrtc, pCrtcPriv->cursor_win_x - offset, + pCrtcPriv->cursor_win_y); + } + else { + pCrtcPriv->need_cursor_update = TRUE; + _cursorRestoreImage(pCrtc); + _cursorRegisterBlockHandler(pCrtc); + } + } + + pCrtcPriv->cursor_old_offset = 0; + + return TRUE; +} + +static Bool +_cursorChangeStatus(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + int new_value; + + if (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off) + new_value = FALSE; + else + new_value = TRUE; + + XDBG_TRACE(MCRS, "[%p] ref(%d) off(%d) value(%d=>%d) cursor(%d,%d) \n", + pCrtc, pCrtcPriv->ref_overlay, pCrtcPriv->need_off, + pCrtcPriv->move_layer, new_value, pCrtcPriv->cursor_show, + pExynos->enableCursor); + + /* layer off if needed */ + if (!pExynos->enableCursor && pCrtcPriv->ovl_layer && + exynosLayerTurnStatus(pCrtcPriv->ovl_layer)) { + Bool turnoff = FALSE; + + if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off) + turnoff = TRUE; + if (!pCrtcPriv->ref_overlay) + turnoff = TRUE; + + if (turnoff) { + _cursorDestroy(pCrtc); + return TRUE; + } + } + + /* layer on if needed */ + if (pCrtcPriv->ovl_layer && !exynosLayerTurnStatus(pCrtcPriv->ovl_layer)) + if (pExynos->enableCursor || + (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off)) + exynosLayerTurn(pCrtcPriv->ovl_layer, TRUE, FALSE); + + if (pCrtcPriv->move_layer == new_value) + return TRUE; + + pCrtcPriv->move_layer = new_value; + + if (pCrtcPriv->ovl_canvas) { + XDBG_TRACE(MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, + pCrtcPriv->ovl_canvas); + pixman_image_unref(pCrtcPriv->ovl_canvas); + pCrtcPriv->ovl_canvas = NULL; + pCrtcPriv->need_draw_cursor = TRUE; + } + + if (pCrtcPriv->cursor_show) + _cursorShow(pCrtc); + + if (new_value && pCrtcPriv->ovl_vbuf_pixmap) { + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pCrtc->scrn)->pExynosMode; + pixman_image_t *old = pCrtcPriv->ovl_canvas; + + pCrtcPriv->ovl_canvas = NULL; + + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_pixmap, + pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay); + + _cursorRestoreImage(pCrtc); + + if (pCrtcPriv->ovl_canvas) + pixman_image_unref(pCrtcPriv->ovl_canvas); + + pCrtcPriv->ovl_canvas = old; + } + + if (!pCrtcPriv->ovl_layer) + _overlaySelectBuffer(pCrtc, pCrtcPriv->move_layer); + + if (pCrtcPriv->ovl_layer) + if (!exynosLayerIsVisible(pCrtcPriv->ovl_layer)) + exynosLayerShow(pCrtcPriv->ovl_layer); + + return TRUE; +} + +static void +_flipPixmapInit(xf86CrtcPtr pCrtc) +{ + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + int flip_backbufs = pExynos->flip_bufs - 1; + int i; + + pCrtcPriv->flip_backpixs.lub = -1; + pCrtcPriv->flip_backpixs.num = flip_backbufs; + + pCrtcPriv->flip_backpixs.pix_free = calloc(flip_backbufs, sizeof(void *)); + XDBG_RETURN_IF_FAIL(pCrtcPriv->flip_backpixs.pix_free != NULL); + for (i = 0; i < flip_backbufs; i++) + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + pCrtcPriv->flip_backpixs.flip_pixmaps = + calloc(flip_backbufs, sizeof(void *)); + pCrtcPriv->flip_backpixs.flip_draws = calloc(flip_backbufs, sizeof(void *)); +} + +static void +_flipPixmapDeinit(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + ScreenPtr pScreen = pCrtc->scrn->pScreen; + int i; + + for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) { + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + if (pCrtcPriv->flip_backpixs.flip_pixmaps[i]) { +#if USE_XDBG + if (pCrtcPriv->flip_backpixs.flip_draws[i]) + xDbgLogPListDrawRemoveRefPixmap(pCrtcPriv->flip_backpixs. + flip_draws[i], + pCrtcPriv->flip_backpixs. + flip_pixmaps[i]); +#endif + + (*pScreen->DestroyPixmap) (pCrtcPriv->flip_backpixs. + flip_pixmaps[i]); + pCrtcPriv->flip_backpixs.flip_pixmaps[i] = NULL; + pCrtcPriv->flip_backpixs.flip_draws[i] = NULL; + } + } + pCrtcPriv->flip_backpixs.lub = -1; +} + +static xf86CrtcPtr +_exynosCrtcGetFromPipe(ScrnInfoPtr pScrn, int pipe) +{ + xf86CrtcConfigPtr pXf86CrtcConfig; + + pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int i; + + for (i = 0; i < pXf86CrtcConfig->num_output; i++) { + pCrtc = pXf86CrtcConfig->crtc[i]; + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + continue; + if (pCrtcPriv->pipe == pipe) { + return pCrtc; + } + } + + return NULL; +} + +static void +EXYNOSCrtcDpms(xf86CrtcPtr pCrtc, int pMode) +{ + +} + +static Bool +EXYNOSCrtcSetModeMajor(xf86CrtcPtr pCrtc, DisplayModePtr pMode, + Rotation rotation, int x, int y) +{ + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSFbPtr pFb = pExynos->pFb; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return TRUE; + } + EXYNOSModePtr pExynosMode = pCrtcPriv->pExynosMode; + tbm_bo bo = NULL, old_bo = NULL; + tbm_bo bo_accessibility[2] = { 0, } + , old_bo_accessibility[2] = { + 0,}; + int saved_x, saved_y; + Rotation saved_rotation; + DisplayModeRec saved_mode; + Bool ret = FALSE; + + XDBG_DEBUG(MDISP, + "SetModeMajor pMode:%d cur(%dx%d+%d+%d),rot:%d new(%dx%d+%d+%d),refresh(%f)rot:%d\n", + exynosCrtcID(pCrtcPriv), + pCrtc->mode.HDisplay, pCrtc->mode.VDisplay, pCrtc->x, pCrtc->y, + pCrtc->rotation, + pMode->HDisplay, pMode->VDisplay, x, y, pMode->VRefresh, + rotation); + + memcpy(&saved_mode, &pCrtc->mode, sizeof(DisplayModeRec)); + saved_x = pCrtc->x; + saved_y = pCrtc->y; + saved_rotation = pCrtc->rotation; + + memcpy(&pCrtc->mode, pMode, sizeof(DisplayModeRec)); + pCrtc->x = x; + pCrtc->y = y; + pCrtc->rotation = rotation; + + if (pExynos->fake_root) + exynosDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); + else + exynosDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); + + /* accessibility */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + XDBG_GOTO_IF_FAIL(pCrtcPriv->accessibility_front_bo != NULL, fail); + XDBG_GOTO_IF_FAIL(pCrtcPriv->accessibility_back_bo != NULL, fail); + + old_bo_accessibility[0] = pCrtcPriv->accessibility_front_bo; + old_bo_accessibility[1] = pCrtcPriv->accessibility_back_bo; + + bo_accessibility[0] = + exynosRenderBoCreate(pScrn, pMode->HDisplay, pMode->VDisplay); + bo_accessibility[1] = + exynosRenderBoCreate(pScrn, pMode->HDisplay, pMode->VDisplay); + + pCrtcPriv->accessibility_front_bo = bo_accessibility[0]; + pCrtcPriv->accessibility_back_bo = bo_accessibility[1]; + } + + /* find bo which covers the requested mode of crtc */ + old_bo = pCrtcPriv->front_bo; + bo = exynosFbGetBo(pFb, x, y, pMode->HDisplay, pMode->VDisplay, FALSE); + XDBG_GOTO_IF_FAIL(bo != NULL, fail); + pCrtcPriv->front_bo = bo; + + ret = exynosCrtcApply(pCrtc); + XDBG_GOTO_IF_FAIL(ret == TRUE, fail); + int i; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr pOutput = xf86_config->output[i]; + EXYNOSOutputPrivPtr pOutputPriv; + + if (pOutput->crtc != pCrtc) + continue; + + pOutputPriv = pOutput->driver_private; + + /* TODO :: soolim :: check this out */ + exynosOutputDpmsSet(pOutput, DPMSModeOn); + pOutputPriv->dpms_mode = DPMSModeOn; + + /* update mode_encoder */ +#ifdef NO_CRTC_MODE + if (pOutputPriv->is_dummy == FALSE) +#endif + { + drmModeFreeEncoder(pOutputPriv->mode_encoder); + pOutputPriv->mode_encoder = + drmModeGetEncoder(pExynosMode->fd, + pOutputPriv->mode_output->encoders[0]); + } +#if 1 + /* set display connector and display set mode */ + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA + || pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIB) { + + exynosDisplaySetDispConnMode(pScrn, DISPLAY_CONN_MODE_HDMI); + /* TODO : find the display mode */ + exynosDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_EXT); + + /* should be shown again when crtc on. */ +// exynosLayerShowAll (pScrn, LAYER_OUTPUT_EXT); + } + else if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) { + exynosDisplaySetDispConnMode(pScrn, DISPLAY_CONN_MODE_VIRTUAL); + /* TODO : find the display mode */ + exynosDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_EXT); + + /* should be shown again when crtc on. */ +// exynosLayerShowAll (pScrn, LAYER_OUTPUT_EXT); + } + else if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_LVDS) { + /* should be shown again when crtc on. */ +// exynosDisplaySetDispConnMode(pScrn, DISPLAY_CONN_MODE_LVDS); + exynosLayerShowAll(pScrn, LAYER_OUTPUT_LCD); + } + + else + XDBG_NEVER_GET_HERE(MDISP); +#endif + } + +#ifdef NO_CRTC_MODE + pExynos->isCrtcOn = exynosCrtcCheckInUseAll(pScrn); +#endif + /* set the default external mode */ + exynosDisplayModeToKmode(pCrtc->scrn, &pExynosMode->ext_connector_mode, + pMode); + + /* accessibility */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + if (ret) { + if (old_bo_accessibility[0]) + exynosRenderBoUnref(old_bo_accessibility[0]); + if (old_bo_accessibility[1]) + exynosRenderBoUnref(old_bo_accessibility[1]); + } + } + exynosOutputDrmUpdate(pScrn); + return ret; + fail: + XDBG_ERROR(MDISP, "Fail crtc apply(crtc_id:%d, rotate:%d, %dx%d+%d+%d\n", + exynosCrtcID(pCrtcPriv), rotation, x, y, pCrtc->mode.HDisplay, + pCrtc->mode.VDisplay); + + pCrtcPriv->front_bo = old_bo; + + /* accessibility */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + if (bo_accessibility[0]) + exynosRenderBoUnref(bo_accessibility[0]); + if (bo_accessibility[1]) + exynosRenderBoUnref(bo_accessibility[1]); + + pCrtcPriv->accessibility_front_bo = old_bo_accessibility[0]; + pCrtcPriv->accessibility_back_bo = old_bo_accessibility[1]; + } + + if (pExynos->fake_root) + exynosDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, + &saved_mode); + else + exynosDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode); + + memcpy(&pCrtc->mode, &saved_mode, sizeof(DisplayModeRec)); + pCrtc->x = saved_x; + pCrtc->y = saved_y; + pCrtc->rotation = saved_rotation; + exynosOutputDrmUpdate(pScrn); + return ret; +} + +static void +EXYNOSCrtcSetCursorColors(xf86CrtcPtr pCrtc, int bg, int fg) +{ + XDBG_TRACE(MCRS, "[%p] \n", pCrtc); +} + +static void +EXYNOSCrtcSetCursorPosition(xf86CrtcPtr pCrtc, int x, int y) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + pCrtcPriv->cursor_pos_x = x; + pCrtcPriv->cursor_pos_y = y; + + XDBG_DEBUG(MCRS, "[%p] (%d,%d) \n", pCrtc, x, y); + + if (!pExynos->enableCursor) + return; + + if (!pCrtcPriv->cursor_show) + return; + + if (pCrtcPriv->move_layer) { + _cursorEnsureCanvas(pCrtc, pCrtcPriv->ovl_vbuf_cursor, + EXYNOS_CURSOR_W, EXYNOS_CURSOR_H); + _cursorEnsureCursorImage(pCrtc); + + int offset = _overlayGetXMoveOffset(pCrtc, pCrtcPriv->cursor_win_x); + + if (pCrtcPriv->cursor_old_offset != offset) { + _cursorDrawCursor(pCrtc); + pCrtcPriv->cursor_old_offset = offset; + } + + _cursorMove(pCrtc, pCrtcPriv->cursor_win_x - offset, + pCrtcPriv->cursor_win_y); + } + else { + /* Draw cursor in block handler */ + pCrtcPriv->need_cursor_update = TRUE; + _cursorRestoreImage(pCrtc); + _cursorRegisterBlockHandler(pCrtc); + } +} + +static void +EXYNOSCrtcShowCursor(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + + XDBG_TRACE(MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show); + + if (pCrtcPriv->cursor_show) + return; + + pCrtcPriv->cursor_show = TRUE; + + _cursorShow(pCrtc); +} + +static void +EXYNOSCrtcHideCursor(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + + XDBG_TRACE(MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show); + + if (!pCrtcPriv->cursor_show) + return; + + pCrtcPriv->cursor_show = FALSE; + + _cursorHide(pCrtc); +} + +static void +EXYNOSCrtcLoadCursorArgb(xf86CrtcPtr pCrtc, CARD32 *image) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL || image == NULL) { + return; + } + XDBG_TRACE(MCRS, "[%p] image(%p) \n", pCrtc, image); + + if (pCrtcPriv->backup_image) + pixman_image_unref(pCrtcPriv->backup_image); + + pCrtcPriv->backup_image = + pixman_image_create_bits(PIXMAN_a8r8g8b8, EXYNOS_CURSOR_W, + EXYNOS_CURSOR_H, NULL, 0); + + XDBG_RETURN_IF_FAIL(pCrtcPriv->backup_image != NULL); + + memcpy(pixman_image_get_data(pCrtcPriv->backup_image), image, + EXYNOS_CURSOR_W * EXYNOS_CURSOR_H * 4); + + if (pCrtcPriv->cursor_image) { + pixman_image_unref(pCrtcPriv->cursor_image); + pCrtcPriv->cursor_image = NULL; + } + + pCrtcPriv->need_cursor_update = TRUE; +} + +static void * +EXYNOSCrtcShadowAllocate(xf86CrtcPtr pCrtc, int width, int height) +{ +#if 0 + ScrnInfoPtr scrn = pCrtc->scrn; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + EXYNOSModePtr pExynosMode = pCrtcPriv->pExynosMode; + unsigned long rotate_pitch; + uint32_t tiling; + int ret; + + pCrtcPriv->rotate_bo = intel_allocate_framebuffer(scrn, + width, height, + pExynosMode->cpp, + &rotate_pitch, &tiling); + + if (!pCrtcPriv->rotate_bo) { + xf86DrvMsg(pCrtc->scrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + + ret = drmModeAddFB(pExynosMode->fd, width, height, pCrtc->scrn->depth, + pCrtc->scrn->bitsPerPixel, rotate_pitch, + pCrtcPriv->rotate_bo->handle, &pCrtcPriv->rotate_fb_id); + if (ret < 0) { + ErrorF("failed to add rotate fb\n"); + drm_intel_bo_unreference(pCrtcPriv->rotate_bo); + return NULL; + } + + pCrtcPriv->rotate_pitch = rotate_pitch; + return pCrtcPriv->rotate_bo; +#else + return NULL; +#endif +} + +static PixmapPtr +EXYNOSCrtcShadowCreate(xf86CrtcPtr pCrtc, void *data, int width, int height) +{ +#if 0 + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pSEC = EXYNOSPtr(pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + PixmapPtr rotate_pixmap; + + if (!data) { + data = EXYNOSCrtcShadowAllocate(pCrtc, width, height); + if (!data) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + return NULL; + } + } + if (pCrtcPriv->rotate_bo == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + return NULL; + } + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + pCrtcPriv->rotate_pitch, NULL); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + return NULL; + } + +// intel_set_pixmap_bo(rotate_pixmap, pCrtcPriv->rotate_bo); + + pSEC->shadow_present = TRUE; + + return rotate_pixmap; +#else + return NULL; +#endif +} + +static void +EXYNOSCrtcShadowDestroy(xf86CrtcPtr pCrtc, PixmapPtr rotate_pixmap, void *data) +{ +#if 0 + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pSEC = EXYNOSPtr(pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + EXYNOSModePtr pExynosMode = pCrtcPriv->mode; + + if (rotate_pixmap) { + intel_set_pixmap_bo(rotate_pixmap, NULL); + FreeScratchPixmapHeader(rotate_pixmap); + } + + if (data) { + /* Be sure to sync acceleration before the memory gets + * unbound. */ + drmModeRmFB(pExynosMode->fd, pCrtcPriv->rotate_fb_id); + pCrtcPriv->rotate_fb_id = 0; + + tbm_bo_unreference(pCrtcPriv->rotate_bo); + pCrtcPriv->rotate_bo = NULL; + } + + pSEC->shadow_present = pSEC->use_shadow; +#else + return; +#endif +} + +static void +EXYNOSCrtcGammaSet(xf86CrtcPtr pCrtc, + CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + EXYNOSModePtr pExynosMode = pCrtcPriv->pExynosMode; + + drmModeCrtcSetGamma(pExynosMode->fd, exynosCrtcID(pCrtcPriv), + size, red, green, blue); +} + +static void +EXYNOSCrtcDestroy(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + DRI2FrameEventPtr event_ref = NULL, event_next = NULL; + + xorg_list_for_each_entry_safe(event_ref, event_next, + &pCrtcPriv->pending_flips, + crtc_pending_link) { + free(event_ref); + } + + _flipPixmapDeinit(pCrtc); + + _cursorDestroy(pCrtc); + _cursorUnregisterBlockHandler(pCrtc); + +#if 1 + if (pCrtcPriv->pFpsDebug) { + xDbgLogFpsDebugDestroy(pCrtcPriv->pFpsDebug); + pCrtcPriv->pFpsDebug = NULL; + } +#endif + + if (pCrtcPriv->accessibility_front_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + } + + if (pCrtcPriv->accessibility_back_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_back_bo); + pCrtcPriv->accessibility_back_bo = NULL; + } + + if (pCrtcPriv->backup_image) { + pixman_image_unref(pCrtcPriv->backup_image); + pCrtcPriv->backup_image = NULL; + } + + if (pCrtcPriv->ovl_vbuf_cursor) { + exynosUtilVideoBufferUnref(pCrtcPriv->ovl_vbuf_cursor); + pCrtcPriv->ovl_vbuf_cursor = NULL; + } + + if (pCrtcPriv->ovl_vbuf_pixmap) { + exynosUtilVideoBufferUnref(pCrtcPriv->ovl_vbuf_pixmap); + pCrtcPriv->ovl_vbuf_pixmap = NULL; + } + + if (pCrtcPriv->ovl_layer) { + exynosLayerUnref(pCrtcPriv->ovl_layer); + pCrtcPriv->ovl_layer = NULL; + } + + if (pCrtcPriv->mode_crtc) + drmModeFreeCrtc(pCrtcPriv->mode_crtc); + + if (pCrtcPriv->front_bo) { + pCrtcPriv->front_bo = NULL; + } + + if (pCrtcPriv->back_bo) { + exynosRenderBoUnref(pCrtcPriv->back_bo); + pCrtcPriv->back_bo = NULL; + } + + if (pCrtcPriv->flip_backpixs.pix_free != NULL) { + free(pCrtcPriv->flip_backpixs.pix_free); + pCrtcPriv->flip_backpixs.pix_free = NULL; + } + + if (pCrtcPriv->flip_backpixs.flip_pixmaps != NULL) { + free(pCrtcPriv->flip_backpixs.flip_pixmaps); + pCrtcPriv->flip_backpixs.flip_pixmaps = NULL; + } + + if (pCrtcPriv->flip_backpixs.flip_draws != NULL) { + free(pCrtcPriv->flip_backpixs.flip_draws); + pCrtcPriv->flip_backpixs.flip_draws = NULL; + } + + xorg_list_del(&pCrtcPriv->link); + free(pCrtcPriv); + + pCrtc->driver_private = NULL; +} + +static const xf86CrtcFuncsRec exynos_crtc_funcs = { + .dpms = EXYNOSCrtcDpms, + .set_mode_major = EXYNOSCrtcSetModeMajor, + .set_cursor_colors = EXYNOSCrtcSetCursorColors, + .set_cursor_position = EXYNOSCrtcSetCursorPosition, + .show_cursor = EXYNOSCrtcShowCursor, + .hide_cursor = EXYNOSCrtcHideCursor, + .load_cursor_argb = EXYNOSCrtcLoadCursorArgb, + .shadow_create = EXYNOSCrtcShadowCreate, + .shadow_allocate = EXYNOSCrtcShadowAllocate, + .shadow_destroy = EXYNOSCrtcShadowDestroy, + .gamma_set = EXYNOSCrtcGammaSet, + .destroy = EXYNOSCrtcDestroy, +}; + +void +exynosCrtcInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num) +{ + xf86CrtcPtr pCrtc; + EXYNOSCrtcPrivPtr pCrtcPriv; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + +// exynosLogSetLevel("CRTC", 0); + + pCrtcPriv = calloc(sizeof(EXYNOSCrtcPrivRec), 1); + if (pCrtcPriv == NULL) + return; + + pCrtc = xf86CrtcCreate(pScrn, &exynos_crtc_funcs); + if (pCrtc == NULL) { + free(pCrtcPriv); + return; + } + + pCrtcPriv->idx = num; + pCrtcPriv->mode_crtc = drmModeGetCrtc(pExynosMode->fd, + pExynosMode->mode_res->crtcs[num]); + pCrtcPriv->move_layer = TRUE; + pCrtcPriv->user_rotate = RR_Rotate_0; + + pCrtcPriv->pExynosMode = pExynosMode; + pCrtc->driver_private = pCrtcPriv; + + pCrtcPriv->pipe = num; + pCrtcPriv->onoff = TRUE; + + xorg_list_init(&pCrtcPriv->pending_flips); + + pCrtcPriv->pCrtc = pCrtc; + +#ifdef USE_XDBG + pCrtcPriv->pFpsDebug = xDbgLogFpsDebugCreate(); + if (pCrtcPriv->pFpsDebug == NULL) { + free(pCrtcPriv); + return; + } +#endif + + if (pExynos->enableCursor) + _cursorInit(pCrtc); + + _flipPixmapInit(pCrtc); + + xorg_list_add(&(pCrtcPriv->link), &(pExynosMode->crtcs)); +#ifdef NO_CRTC_MODE + pExynosMode->num_real_crtc++; +#endif +} + +/* check the crtc is on */ +Bool +exynosCrtcOn(xf86CrtcPtr pCrtc) +{ + ScrnInfoPtr pScrn = pCrtc->scrn; + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + if (!pCrtc->enabled) + return FALSE; + + /* Kernel manage CRTC status based out output config */ + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + + if (pOutput->crtc == pCrtc && + exynosOutputDpmsStatus(pOutput) == DPMSModeOn) + return TRUE; + } + + return TRUE; +} + +Bool +exynosCrtcApply(xf86CrtcPtr pCrtc) +{ + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + EXYNOSModePtr pExynosMode = pCrtcPriv->pExynosMode; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + uint32_t *output_ids; + int output_count = 0; + int fb_id, x, y; + int i; + Bool ret = FALSE; + EXYNOSFbBoDataPtr bo_data; + tbm_bo bo; + + output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); + if (!output_ids) + return FALSE; + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr pOutput = xf86_config->output[i]; + EXYNOSOutputPrivPtr pOutputPriv; + + if (pOutput->crtc != pCrtc) + continue; + + pOutputPriv = pOutput->driver_private; + if (pOutputPriv == NULL) { + continue; + } + + /* modify the physical size of monitor */ +#if 0 + if (!strcmp(pOutput->name, "LVDS1")) { + exynosDisplaySetDispConnMode(pScrn, DISPLAY_CONN_MODE_LVDS); + } +#endif + { + pOutput->mm_width = pOutputPriv->mode_output->mmWidth; + pOutput->mm_height = pOutputPriv->mode_output->mmHeight; + if (pOutput->conf_monitor) { + pOutput->conf_monitor->mon_width = + pOutputPriv->mode_output->mmWidth; + pOutput->conf_monitor->mon_height = + pOutputPriv->mode_output->mmHeight; + } + } + + output_ids[output_count] = pOutputPriv->mode_output->connector_id; + output_count++; + } +#if 0 + if (!xf86CrtcRotate(pCrtc)) + goto done; +#endif + pCrtc->funcs->gamma_set(pCrtc, pCrtc->gamma_red, pCrtc->gamma_green, + pCrtc->gamma_blue, pCrtc->gamma_size); + + /* accessilitity */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo temp; + + bo = pCrtcPriv->accessibility_front_bo; + temp = pCrtcPriv->accessibility_front_bo; + pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo; + pCrtcPriv->accessibility_back_bo = temp; + } + else { + bo = pCrtcPriv->front_bo; + } + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + x = pCrtc->x - bo_data->pos.x1; + y = pCrtc->y - bo_data->pos.y1; + fb_id = bo_data->fb_id; + + if (pCrtcPriv->rotate_fb_id) { + fb_id = pCrtcPriv->rotate_fb_id; + x = 0; + y = 0; + } + + XDBG_INFO(MDISP, + "fb_id,%d name,%s width,%d height,%d, vrefresh,%d, accessibility,%d\n", + fb_id, pCrtcPriv->kmode.name, pCrtcPriv->kmode.hdisplay, + pCrtcPriv->kmode.vdisplay, pCrtcPriv->kmode.vrefresh, + pCrtcPriv->bAccessibility); + + /* turn off the crtc if the same crtc is set already by another display mode + * before the set crtcs + */ +// exynosDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_OFF); + +// if (!pCrtcPriv->onoff) +// exynosCrtcTurn (pCrtc, TRUE, FALSE, FALSE); + + /* for cache control */ + tbm_bo_map(bo, TBM_DEVICE_2D, TBM_OPTION_READ); + tbm_bo_unmap(bo); + ret = drmModeSetCrtc(pExynosMode->fd, exynosCrtcID(pCrtcPriv), + fb_id, x, y, output_ids, output_count, + &pCrtcPriv->kmode); + if (ret) { + XDBG_INFO(MDISP, "failed to set mode: %s\n", strerror(-ret)); + ret = FALSE; + } + else { + ret = TRUE; + + /* Force DPMS to On for all outputs, which the kernel will have done + * with the mode set. Also, restore the backlight level + */ + } + +#if 1 + if (pScrn->pScreen) + xf86_reload_cursors(pScrn->pScreen); +#endif +#if 0 + done: +#endif + free(output_ids); + return ret; +} + +Bool +exynosCrtcOverlayNeedOff(xf86CrtcPtr pCrtc, Bool need_off) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + pCrtcPriv = pCrtc->driver_private; + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv != NULL, FALSE); + + pCrtcPriv->need_off = need_off; + + XDBG_TRACE(MCRS, "[%p] need_off(%d) \n", pCrtc, need_off); + + _cursorChangeStatus(pCrtc); + + return TRUE; +} + +Bool +exynosCrtcOverlayRef(xf86CrtcPtr pCrtc, Bool refer) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + pCrtcPriv = pCrtc->driver_private; + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv != NULL, FALSE); + + pCrtcPriv->ref_overlay = refer; + + XDBG_TRACE(MCRS, "[%p] refer(%d) \n", pCrtc, refer); + + _cursorChangeStatus(pCrtc); + + return TRUE; +} + +Bool +exynosCrtcCursorEnable(ScrnInfoPtr pScrn, Bool enable) +{ + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSCrtcPrivPtr pCur = NULL, pNext = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &pExynosMode->crtcs, link) { + xf86CrtcPtr pCrtc = pCur->pCrtc; + int connector_type = exynosCrtcGetConnectType(pCrtc); + + if (connector_type != DRM_MODE_CONNECTOR_Unknown) + _cursorEnable(pCrtc, enable); + } + + return TRUE; +} + +Bool +exynosCrtcCursorRotate(xf86CrtcPtr pCrtc, int rotate) +{ + return _cursorRotate(pCrtc, rotate); +} + +xf86CrtcPtr +exynosCrtcGetAtGeometry(ScrnInfoPtr pScrn, int x, int y, int width, int height) +{ + BoxRec box; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, NULL); + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + + return exynosModeCoveringCrtc(pScrn, &box, NULL, NULL); +} + +int +exynosCrtcGetConnectType(xf86CrtcPtr pCrtc) +{ + xf86CrtcConfigPtr pCrtcConfig; + int i; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, DRM_MODE_CONNECTOR_Unknown); + + pCrtcConfig = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + XDBG_RETURN_VAL_IF_FAIL(pCrtcConfig != NULL, DRM_MODE_CONNECTOR_Unknown); + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutput->crtc == pCrtc) { + if (pOutputPriv != NULL) + return pOutputPriv->mode_output->connector_type; + else + return DRM_MODE_CONNECTOR_Unknown; + } + } + + return DRM_MODE_CONNECTOR_Unknown; +} + +Bool +exynosCrtcIsFlipping(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return FALSE; + + /* if isFlipping is true, return true */ + if (pCrtcPriv->is_flipping) + return TRUE; + + /* if there is pending_flips in the list, return true */ + if (!xorg_list_is_empty(&pCrtcPriv->pending_flips)) + return TRUE; + + return FALSE; +} + +DRI2FrameEventPtr +exynosCrtcGetPendingFlip(xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + DRI2FrameEventPtr item = NULL, tmp = NULL; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, NULL); + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return NULL; + + if (xorg_list_is_empty(&pCrtcPriv->pending_flips)) + return NULL; + + xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, + crtc_pending_link) { + if (item == pEvent) + return item; + } + + return NULL; +} + +DRI2FrameEventPtr +exynosCrtcGetFirstPendingFlip(xf86CrtcPtr pCrtc) +{ + DRI2FrameEventPtr pEvent = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv; + DRI2FrameEventPtr item = NULL, tmp = NULL; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, NULL); + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return NULL; + + if (xorg_list_is_empty(&pCrtcPriv->pending_flips)) + return NULL; + + xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, + crtc_pending_link) { + /* get the last item in the circular list ( last item is at last_item.next==head) */ + if (item->crtc_pending_link.next == &pCrtcPriv->pending_flips) { + pEvent = item; + break; + } + } + + return pEvent; +} + +void +exynosCrtcAddPendingFlip(xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return; + + xorg_list_add(&(pEvent->crtc_pending_link), &(pCrtcPriv->pending_flips)); +} + +void +exynosCrtcRemovePendingFlip(xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) +{ + EXYNOSCrtcPrivPtr pCrtcPriv; + DRI2FrameEventPtr item = NULL, tmp = NULL; + + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return; + + if (xorg_list_is_empty(&pCrtcPriv->pending_flips)) + return; + + xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, + crtc_pending_link) { + if (item == pEvent) { + xorg_list_del(&item->crtc_pending_link); + } + } +} + +static Bool +_exynosCrtcExecAccessibilityScaleNegative(xf86CrtcPtr pCrtc, tbm_bo src_bo, + tbm_bo dst_bo) +{ + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + if (pExynos->isLcdOff) { + XDBG_INFO(MDISP, "Accessibility execute : LCD IS OFF\n"); + return TRUE; + } + + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + XDBG_RETURN_VAL_IF_FAIL(src_bo != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_bo != NULL, FALSE); + + EXYNOSFbBoDataPtr src_bo_data; + EXYNOSFbBoDataPtr dst_bo_data; + G2dColorKeyMode mode; + G2dImage *srcImg = NULL, *dstImg = NULL; + unsigned int src_bo_w, src_bo_h, src_bo_stride; + unsigned int dst_bo_w, dst_bo_h, dst_bo_stride; + int src_x, src_y; + unsigned int src_w, src_h; + int negative = 0; + tbm_bo_handle src_bo_handle; + tbm_bo_handle dst_bo_handle; + + tbm_bo_get_user_data(src_bo, TBM_BO_DATA_FB, (void * *) &src_bo_data); + XDBG_RETURN_VAL_IF_FAIL(src_bo_data != NULL, FALSE); + + tbm_bo_get_user_data(dst_bo, TBM_BO_DATA_FB, (void * *) &dst_bo_data); + XDBG_RETURN_VAL_IF_FAIL(dst_bo_data != NULL, FALSE); + + src_bo_w = src_bo_data->pos.x2 - src_bo_data->pos.x1; + src_bo_h = src_bo_data->pos.y2 - src_bo_data->pos.y1; + src_bo_stride = src_bo_w * 4; + + dst_bo_w = dst_bo_data->pos.x2 - dst_bo_data->pos.x1; + dst_bo_h = dst_bo_data->pos.y2 - dst_bo_data->pos.y1; + dst_bo_stride = dst_bo_w * 4; + + mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + src_bo_handle = tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + dst_bo_handle = tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); + + srcImg = + g2d_image_create_bo(mode, src_bo_w, src_bo_h, src_bo_handle.u32, + src_bo_stride); + dstImg = + g2d_image_create_bo(mode, dst_bo_w, dst_bo_h, dst_bo_handle.u32, + dst_bo_stride); + if (!srcImg || !dstImg) { + XDBG_ERROR(MDISP, "Accessibility : Fail to create g2d_image\n"); + tbm_bo_unmap(src_bo); + tbm_bo_unmap(dst_bo); + + if (srcImg) + g2d_image_free(srcImg); + + if (dstImg) + g2d_image_free(dstImg); + + return FALSE; + } + + if (pCrtcPriv->accessibility_status == ACCESSIBILITY_MODE_NEGATIVE) { + negative = 1; + } + + if (pCrtcPriv->bScale) { + src_x = pCrtcPriv->sx; + src_y = pCrtcPriv->sy; + src_w = pCrtcPriv->sw; + src_h = pCrtcPriv->sh; + } + else { + src_x = 0; + src_y = 0; + src_w = src_bo_w; + src_h = src_bo_h; + } + + util_g2d_copy_with_scale(srcImg, dstImg, + src_x, src_y, src_w, src_h, + 0, 0, dst_bo_w, dst_bo_h, negative); + g2d_exec(); + + tbm_bo_unmap(src_bo); + tbm_bo_unmap(dst_bo); + + g2d_image_free(srcImg); + g2d_image_free(dstImg); + + return TRUE; +} + +static Bool +_exynosCrtcExecRotate(xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo) +{ + EXYNOSPtr pExynos; + EXYNOSCrtcPrivPtr pCrtcPriv; + struct drm_exynos_ipp_queue_buf buf; + + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return FALSE; + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->screen_rotate_prop_id > 0, FALSE); + + pExynos = EXYNOSPTR(pCrtc->scrn); + if (pExynos->isLcdOff) { + XDBG_INFO(MDISP, "screen rotate execute : LCD IS OFF\n"); + return TRUE; + } + + CLEAR(buf); + buf.ops_id = EXYNOS_DRM_OPS_SRC; + buf.buf_type = IPP_BUF_ENQUEUE; + buf.prop_id = pCrtcPriv->screen_rotate_prop_id; + buf.handle[0] = (__u32) tbm_bo_get_handle(src_bo, TBM_DEVICE_DEFAULT).u32; + + if (!exynosDrmIppQueueBuf(pCrtc->scrn, &buf)) + return FALSE; + + CLEAR(buf); + buf.ops_id = EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_ENQUEUE; + buf.prop_id = pCrtcPriv->screen_rotate_prop_id; + buf.handle[0] = (__u32) tbm_bo_get_handle(dst_bo, TBM_DEVICE_DEFAULT).u32; + + if (!exynosDrmIppQueueBuf(pCrtc->scrn, &buf)) + return FALSE; + + if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_STOP) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; + ctrl.ctrl = IPP_CTRL_PLAY; + exynosDrmIppCmdCtrl(pCrtc->scrn, &ctrl); + pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PLAY; + + XDBG_INFO(MDISP, "screen rotate ipp(id:%d) play\n", + pCrtcPriv->screen_rotate_prop_id); + } + else if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_PAUSE) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; + ctrl.ctrl = IPP_CTRL_RESUME; + exynosDrmIppCmdCtrl(pCrtc->scrn, &ctrl); + pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_RESUME; + + XDBG_INFO(MDISP, "screen rotate ipp(id:%d) resume\n", + pCrtcPriv->screen_rotate_prop_id); + } + + return TRUE; +} + +Bool +exynosCrtcExecAccessibility(xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + Bool ret = FALSE; + CARD32 elapsed = 0; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + + tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_ACCESS) + elapsed = GetTimeInMillis(); + + if (pCrtcPriv->screen_rotate_degree > 0) + ret = _exynosCrtcExecRotate(pCrtc, src_bo, dst_bo); + else if (pCrtcPriv->bAccessibility) + ret = _exynosCrtcExecAccessibilityScaleNegative(pCrtc, src_bo, dst_bo); + else + XDBG_NEVER_GET_HERE(MDISP); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_ACCESS) + ErrorF("Access exec: %3" PRIXID " ms \n", GetTimeInMillis() - elapsed); + + tbm_bo_unmap(src_bo); + tbm_bo_unmap(dst_bo); + + return ret; +} + +Bool +exynosCrtcEnableAccessibility(xf86CrtcPtr pCrtc) +{ + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + /* accessibility and screen rotate can't be enable at the same time */ + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->screen_rotate_degree == 0, FALSE); + + int bAccessibility = (pCrtcPriv->accessibility_status | pCrtcPriv->bScale); + int width = pCrtc->mode.HDisplay; + int height = pCrtc->mode.VDisplay; + + EXYNOSLayer *pLayer = NULL; + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + xf86OutputPtr pOutput = NULL; + int i; + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pTemp = pCrtcConfig->output[i]; + + if (pTemp->crtc == pCrtc) { + pOutput = pTemp; + break; + } + } + XDBG_RETURN_VAL_IF_FAIL(pOutput != NULL, FALSE); + + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + EXYNOSLayerOutput output = LAYER_OUTPUT_LCD; + + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || + pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown) + { + output = LAYER_OUTPUT_LCD; + } + else if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIB || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) { + output = LAYER_OUTPUT_EXT; + } + else + XDBG_NEVER_GET_HERE(MACCE); + + if (bAccessibility) { + if (!pCrtcPriv->accessibility_front_bo) { + pCrtcPriv->accessibility_front_bo = + exynosRenderBoCreate(pScrn, width, height); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->accessibility_front_bo != NULL, + FALSE); + } + + pCrtcPriv->bAccessibility = TRUE; + + /* do accessibility */ + if (!exynosCrtcExecAccessibility + (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_front_bo)) { + XDBG_ERROR(MDISP, + "Accessibility : Fail to execute accessibility\n"); + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + pCrtcPriv->bAccessibility = FALSE; + return FALSE; + } + + XDBG_INFO(MDISP, + "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n", + pCrtcPriv->accessibility_status, pCrtcPriv->bScale, + pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh); + + /* layer update */ + pLayer = exynosLayerFind(output, LAYER_UPPER); + if (pLayer && exynosLayerIsVisible(pLayer)) + exynosLayerUpdate(pLayer); + + /* set crtc when accessibility buffer destroy, or drmvlank is error */ + if (!exynosCrtcApply(pCrtc)) { + + XDBG_ERROR(MDISP, "Accessibility : Fail to set crtc\n"); + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + pCrtcPriv->bAccessibility = FALSE; + return FALSE; + } + + } + else { + pCrtcPriv->bAccessibility = FALSE; + + XDBG_INFO(MDISP, + "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n", + pCrtcPriv->accessibility_status, pCrtcPriv->bScale, + pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh); + + if (!exynosCrtcApply(pCrtc)) { + XDBG_ERROR(MDISP, "Accessibility : Fail to set crtc\n"); + pCrtcPriv->bAccessibility = TRUE; + return FALSE; + } + + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSHwcPtr pHwc = pExynos->pHwc; + + if (pHwc && EXYNOSPTR(pCrtc->scrn)->hwc_active) { + /* hwc active,release accessibility layers */ + EXYNOSLayerPos p_lpos[PLANE_MAX]; + EXYNOSLayerOutput output = LAYER_OUTPUT_LCD; + + EXYNOSLayerMngClientID lyr_clientid = exynosHwcGetLyrClientId(pHwc); + int max_lpos = + exynosLayerMngGetListOfOwnedPos(lyr_clientid, output, p_lpos); + + for (i = 0; i < max_lpos; ++i) { + exynosLayerMngRelease(lyr_clientid, output, p_lpos[i]); + } + exynosHwcUpdate(pCrtc->scrn); + } + /* layer update */ + pLayer = exynosLayerFind(output, LAYER_UPPER); + if (pLayer && exynosLayerIsVisible(pLayer)) + exynosLayerUpdate(pLayer); + } + + return TRUE; +} + +Bool +exynosCrtcEnableScreenRotate(xf86CrtcPtr pCrtc, Bool enable) +{ +#ifdef _F_WEARABLE_FEATURE_ + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + int width = pCrtc->mode.HDisplay; + int height = pCrtc->mode.VDisplay; + int degree = pCrtcPriv->screen_rotate_degree; + + /* accessibility and screen rotate can't be enable at the same time */ + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->bAccessibility == FALSE, FALSE); + + if (enable) { + struct drm_exynos_ipp_property property; + int prop_id; + + if (!pCrtcPriv->accessibility_front_bo) { + pCrtcPriv->accessibility_front_bo = + exynosRenderBoCreate(pScrn, width, height); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->accessibility_front_bo != NULL, + FALSE); + + pCrtcPriv->accessibility_back_bo = + exynosRenderBoCreate(pScrn, width, height); + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->accessibility_back_bo != NULL, + FALSE); + } + + prop_id = pCrtcPriv->screen_rotate_prop_id; + if (prop_id != 0) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; + ctrl.ctrl = IPP_CTRL_PAUSE; + exynosDrmIppCmdCtrl(pScrn, &ctrl); + pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PAUSE; + XDBG_INFO(MDISP, "screen rotate ipp(id:%d) pause\n", + pCrtcPriv->screen_rotate_prop_id); + } + else + pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP; + + CLEAR(property); + property.config[0].ops_id = EXYNOS_DRM_OPS_SRC; + property.config[0].fmt = DRM_FORMAT_ARGB8888; + property.config[0].sz.hsize = (__u32) width; + property.config[0].sz.vsize = (__u32) height; + property.config[0].pos.x = 0; + property.config[0].pos.y = 0; + property.config[0].pos.w = (__u32) width; + property.config[0].pos.h = (__u32) height; + property.config[1].ops_id = EXYNOS_DRM_OPS_DST; + if (degree % 360 == 90) + property.config[1].degree = EXYNOS_DRM_DEGREE_90; + else if (degree % 360 == 180) + property.config[1].degree = EXYNOS_DRM_DEGREE_180; + else if (degree % 360 == 270) + property.config[1].degree = EXYNOS_DRM_DEGREE_270; + else + property.config[1].degree = EXYNOS_DRM_DEGREE_0; + property.config[1].fmt = DRM_FORMAT_ARGB8888; + property.config[1].sz.hsize = width; + property.config[1].sz.vsize = height; + property.config[1].pos.x = (__u32) 0; + property.config[1].pos.y = (__u32) 0; + property.config[1].pos.w = (__u32) width; + property.config[1].pos.h = (__u32) height; + + property.cmd = IPP_CMD_M2M; + property.type = IPP_SYNC_WORK; + property.prop_id = prop_id; + + prop_id = exynosDrmIppSetProperty(pScrn, &property); + XDBG_RETURN_VAL_IF_FAIL(prop_id != 0, FALSE); + pCrtcPriv->screen_rotate_prop_id = prop_id; + + XDBG_INFO(MDISP, "screen rotate ipp(id:%d) start\n", prop_id); + } + else { + if (pCrtcPriv->screen_rotate_prop_id > 0) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; + ctrl.ctrl = IPP_CTRL_STOP; + exynosDrmIppCmdCtrl(pScrn, &ctrl); + pCrtcPriv->screen_rotate_prop_id = 0; + pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP; + XDBG_INFO(MDISP, "screen rotate ipp(id:%d) stop\n", + pCrtcPriv->screen_rotate_prop_id); + } + } +#endif + return TRUE; +} + +Bool +exynosCrtcScreenRotate(xf86CrtcPtr pCrtc, int degree) +{ +#ifdef _F_WEARABLE_FEATURE_ + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pExynos = EXYNOSPTR(pCrtc->scrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + CARD32 elapsed[3] = { 0, }; + + if (pCrtcPriv->screen_rotate_degree == degree) + return TRUE; + + /* accessibility and screen rotate can't be enable at the same time */ + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->bAccessibility == FALSE, FALSE); + + pCrtcPriv->screen_rotate_degree = degree; + + if (pExynos->isLcdOff) { + XDBG_INFO(MDISP, "screen rotate(degree:%d)\n", degree); + exynosVideoScreenRotate(pScrn, degree); + return TRUE; + } + + elapsed[0] = GetTimeInMillis(); + + if (degree > 0) { + exynosCrtcEnableScreenRotate(pCrtc, TRUE); + + /* do accessibility */ + if (!exynosCrtcExecAccessibility + (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_back_bo)) { + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + exynosRenderBoUnref(pCrtcPriv->accessibility_back_bo); + pCrtcPriv->accessibility_back_bo = NULL; + return FALSE; + } + } + else + exynosCrtcEnableScreenRotate(pCrtc, FALSE); + + elapsed[1] = GetTimeInMillis(); + + exynosCrtcApply(pCrtc); + + elapsed[2] = GetTimeInMillis(); + + exynosVideoScreenRotate(pScrn, degree); + + XDBG_INFO(MDISP, "screen rotate done(degree:%d, dur:%ld~%ld~%ld ms)\n", + degree, elapsed[1] - elapsed[0], elapsed[2] - elapsed[1], + GetTimeInMillis() - elapsed[2]); +#endif + return TRUE; +} + +Bool +exynosCrtcTurn(xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user) +{ + EXYNOSModePtr pExynosMode = EXYNOSPTR(pCrtc->scrn)->pExynosMode; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + int crtc_id = exynosCrtcID(pCrtcPriv); + int mode; + + mode = (onoff > 0) ? 0 : 1; + + if (pCrtcPriv->onoff == onoff) { + pCrtcPriv->onoff_always = always; + XDBG_ERROR(MDISP, "Crtc(%d) UI layer is '%s'%s\n", + crtc_id, (onoff) ? "ON" : "OFF", + (always) ? "(always)." : "."); + return TRUE; + } + + if (pCrtcPriv->onoff_always) + if (!always) { + XDBG_ERROR(MDISP, "Crtc(%d) UI layer can't be '%s'.\n", crtc_id, + (onoff) ? "ON" : "OFF"); + return FALSE; + } + + /* 0 : normal, 1 : blank, 2 : defer */ + if (pCrtcPriv->is_dummy == FALSE) { + if (!exynosUtilSetDrmProperty(pExynosMode, crtc_id, + DRM_MODE_OBJECT_CRTC, "mode", mode)) { + XDBG_ERROR(MDISP, "SetDrmProperty failed. crtc(%d) onoff(%d) \n", + crtc_id, onoff); + return FALSE; + } + } + + pCrtcPriv->onoff = onoff; + pCrtcPriv->onoff_always = always; + + XDBG_INFO(MDISP, "%s >> crtc(%d) UI layer '%s'%s\n", + (user) ? "user" : "Xorg", crtc_id, (onoff) ? "ON" : "OFF", + (always) ? "(always)." : "."); + + return TRUE; +} + +Bool +exynosCrtcCheckOn(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + return pCrtcPriv->onoff; +} + +/* return true if there is no flip pixmap available */ +Bool +exynosCrtcFullFreeFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe) +{ + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int i; + + pCrtc = _exynosCrtcGetFromPipe(pScrn, crtc_pipe); + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return FALSE; + + /* there is a free flip pixmap, return false */ + for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) { + if (pCrtcPriv->flip_backpixs.pix_free[i]) { + return FALSE; + } + } + + XDBG_WARNING(MFLIP, "no free flip pixmap\n"); + + return TRUE; +} + +#define GET_NEXT_IDX(idx, max) (((idx+1) % (max))) +PixmapPtr +exynosCrtcGetFreeFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe, DrawablePtr pDraw, + unsigned int usage_hint) +{ + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + PixmapPtr pPixmap = NULL; + ScreenPtr pScreen = pScrn->pScreen; + int i; + int check_release = 0; + + pCrtc = _exynosCrtcGetFromPipe(pScrn, crtc_pipe); + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + + pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return NULL; + + /* check if there is free flip pixmaps */ + if (exynosCrtcFullFreeFlipPixmap(pScrn, crtc_pipe)) { + /* case : flip pixmap is never release + if flip_count is 0 where there is no uncompleted pageflipping, + release the flip_pixmap which occupied by a drawable. */ + if (pCrtcPriv->flip_count == 0) { + exynosCrtcRelAllFlipPixmap(pScrn, crtc_pipe); + check_release = 1; + XDBG_WARNING(MFLIP, + "@@ release the drawable pre-occuiped the flip_pixmap\n"); + } + + /* return null, if there is no flip_backpixmap which can release */ + if (!check_release) + return NULL; + } + + /* return flip pixmap */ + for (i = + GET_NEXT_IDX(pCrtcPriv->flip_backpixs.lub, + pCrtcPriv->flip_backpixs.num); + i < pCrtcPriv->flip_backpixs.num; + i = GET_NEXT_IDX(i, pCrtcPriv->flip_backpixs.num)) { + if (pCrtcPriv->flip_backpixs.pix_free[i]) { + if (pCrtcPriv->flip_backpixs.flip_pixmaps[i]) { + pPixmap = pCrtcPriv->flip_backpixs.flip_pixmaps[i]; + XDBG_DEBUG(MFLIP, + "the index(%d, %d) of the flip pixmap in pipe(%d) is set\n", + i, tbm_bo_export(exynosExaPixmapGetBo(pPixmap)), + crtc_pipe); + } + else { + pPixmap = (*pScreen->CreatePixmap) (pScreen, + pDraw->width, + pDraw->height, + pDraw->depth, usage_hint); + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); + pCrtcPriv->flip_backpixs.flip_pixmaps[i] = pPixmap; + + XDBG_DEBUG(MFLIP, + "the index(%d, %d) of the flip pixmap in pipe(%d) is created\n", + i, tbm_bo_export(exynosExaPixmapGetBo(pPixmap)), + crtc_pipe); + } + +#if USE_XDBG + if (pCrtcPriv->flip_backpixs.flip_draws[i] && + (pCrtcPriv->flip_backpixs.flip_draws[i] != pDraw)) { + xDbgLogPListDrawRemoveRefPixmap(pCrtcPriv->flip_backpixs. + flip_draws[i], + pCrtcPriv->flip_backpixs. + flip_pixmaps[i]); + } +#endif + + pCrtcPriv->flip_backpixs.pix_free[i] = FALSE; + pCrtcPriv->flip_backpixs.flip_draws[i] = pDraw; + pCrtcPriv->flip_backpixs.lub = i; + +#if USE_XDBG + xDbgLogPListDrawAddRefPixmap(pDraw, pPixmap); +#endif + break; + } + } + + return pPixmap; +} + +void +exynosCrtcRelFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe, PixmapPtr pPixmap) +{ + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int i; + + pCrtc = _exynosCrtcGetFromPipe(pScrn, crtc_pipe); + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + + /* release flip pixmap */ + for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) { + if (pPixmap == pCrtcPriv->flip_backpixs.flip_pixmaps[i]) { + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL; */ + + XDBG_DEBUG(MFLIP, + "the index(%d, %d) of the flip pixmap in pipe(%d) is unset\n", + i, tbm_bo_export(exynosExaPixmapGetBo(pPixmap)), + crtc_pipe); + break; + } + } +} + +void +exynosCrtcRelAllFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe) +{ + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int i; + + pCrtc = _exynosCrtcGetFromPipe(pScrn, crtc_pipe); + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return; + + /* release flip pixmap */ + for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) { + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL; */ + + XDBG_DEBUG(MFLIP, + "the index(%d) of the flip draw in pipe(%d) is unset\n", + i, crtc_pipe); + } +} + +void +exynosCrtcRemoveFlipPixmap(xf86CrtcPtr pCrtc) +{ + _flipPixmapDeinit(pCrtc); +} + +void +exynosCrtcCountFps(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int conn_type; + + if (!pCrtc->enabled) + return; + + pCrtcPriv = pCrtc->driver_private; + if (pCrtcPriv == NULL) + return; + conn_type = exynosCrtcGetConnectType(pCrtc); + + xDbgLogFpsDebugCount(pCrtcPriv->pFpsDebug, conn_type); +} + +#ifdef NO_CRTC_MODE +Bool +exynosCrtcCheckInUseAll(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + Bool ret = FALSE; + + if (config == NULL) + return ret; + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr pCrtc = config->crtc[i]; + + if (xf86CrtcInUse(pCrtc)) { + ret = TRUE; + pCrtc->enabled = TRUE; + } + else + pCrtc->enabled = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%s found active CRTC\n", ret ? "" : "NOT"); + return ret; +} +#endif //NO_CRTC_MODE + +xf86CrtcPtr +exynosCrtcGetByID(ScrnInfoPtr pScrn, int crtc_id) +{ + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < pCrtcConfig->num_crtc; i++) { + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtcConfig->crtc[i]->driver_private; + + if (pCrtcPriv != NULL) { + if (pCrtcPriv->mode_crtc != NULL) { + if (pCrtcPriv->mode_crtc->crtc_id == crtc_id) + return pCrtcConfig->crtc[i]; + } + } + } + return NULL; +} diff --git a/src/crtcconfig/exynos_crtc.h b/src/crtcconfig/exynos_crtc.h new file mode 100755 index 0000000..0e0da6d --- /dev/null +++ b/src/crtcconfig/exynos_crtc.h @@ -0,0 +1,179 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 __SEC_CRTC_H__ +#define __SEC_CRTC_H__ + +#include "exynos_display.h" +#include "exynos_layer.h" +#include "exynos_util.h" + +typedef enum { + ACCESSIBILITY_MODE_NONE, + ACCESSIBILITY_MODE_NEGATIVE, +} ACCESSIBILITY_STATUS; + +typedef struct _exynosCrtcPriv { + EXYNOSModePtr pExynosMode; + drmModeModeInfo kmode; + drmModeCrtcPtr mode_crtc; + intptr_t pipe; + + int idx; + tbm_bo front_bo; + tbm_bo back_bo; + + /* for pageflip */ + unsigned int fe_frame; + unsigned int fe_tv_sec; + unsigned int fe_tv_usec; + DRI2FrameEventPtr flip_info; /* pending flips : flipping must garauntee to do it sequentially */ + struct xorg_list pending_flips; + Bool is_flipping; /* check flipping */ + Bool is_fb_blit_flipping; + int flip_count; /* check flipping completed (check pairs of request_flip and complete_flip */ + struct { + int num; /* number of flip back pixmaps */ + int lub; /* Last used backbuffer */ + Bool *pix_free; /* flags for a flip pixmap to be free */ + DrawablePtr *flip_draws; + PixmapPtr *flip_pixmaps; /* back flip pixmaps in a crtc */ + } flip_backpixs; + +#if 1 + /* for fps debug */ + FpsDebugPtr pFpsDebug; +#endif + + /* overlay(cursor) */ + Bool need_off; + Bool ref_overlay; + Bool move_layer; + Bool cursor_show; + Bool need_draw_cursor; + EXYNOSLayer *ovl_layer; + EXYNOSVideoBuf *ovl_vbuf_cursor; + EXYNOSVideoBuf *ovl_vbuf_pixmap; + Bool need_cursor_update; + Bool registered_block_handler; + int user_rotate; + int cursor_old_offset; + int cursor_pos_x; + int cursor_pos_y; + int cursor_win_x; + int cursor_win_y; + BoxRec saved_box; + pixman_image_t *ovl_canvas; + pixman_image_t *saved_image; + pixman_image_t *cursor_image; + pixman_image_t *backup_image; + + tbm_bo rotate_bo; + uint32_t rotate_pitch; + uint32_t rotate_fb_id; + + /* crtc rotate by display conf */ + Rotation rotate; + + /* Accessibility */ + tbm_bo accessibility_front_bo; + tbm_bo accessibility_back_bo; + Bool bAccessibility; + ACCESSIBILITY_STATUS accessibility_status; + Bool bScale; + int sx, sy, sw, sh; + + /* screen rotate */ + int screen_rotate_degree; + int screen_rotate_prop_id; + int screen_rotate_ipp_status; + + Bool onoff; + Bool onoff_always; + + xf86CrtcPtr pCrtc; + Bool is_dummy; + struct xorg_list link; +} EXYNOSCrtcPrivRec, *EXYNOSCrtcPrivPtr; + +#if 0 +xf86CrtcPtr exynosCrtcDummyInit(ScrnInfoPtr pScrn); +#endif +Bool exynosCrtcCheckInUseAll(ScrnInfoPtr pScrn); +void exynosCrtcInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num); +Bool exynosCrtcOn(xf86CrtcPtr pCrtc); +Bool exynosCrtcApply(xf86CrtcPtr pCrtc); + +Bool exynosCrtcOverlayNeedOff(xf86CrtcPtr pCrtc, Bool need_off); +Bool exynosCrtcOverlayRef(xf86CrtcPtr pCrtc, Bool refer); +Bool exynosCrtcCursorEnable(ScrnInfoPtr pScrn, Bool enable); +Bool exynosCrtcCursorRotate(xf86CrtcPtr pCrtc, int rotate); + +Bool exynosCrtcScreenRotate(xf86CrtcPtr pCrtc, int degree); +Bool exynosCrtcEnableScreenRotate(xf86CrtcPtr pCrtc, Bool enable); + +xf86CrtcPtr exynosCrtcGetAtGeometry(ScrnInfoPtr pScrn, int x, int y, int width, + int height); +int exynosCrtcGetConnectType(xf86CrtcPtr pCrtc); + +Bool exynosCrtcIsFlipping(xf86CrtcPtr pCrtc); +void exynosCrtcAddPendingFlip(xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent); +void exynosCrtcRemovePendingFlip(xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent); +DRI2FrameEventPtr exynosCrtcGetPendingFlip(xf86CrtcPtr pCrtc, + DRI2FrameEventPtr pEvent); +DRI2FrameEventPtr exynosCrtcGetFirstPendingFlip(xf86CrtcPtr pCrtc); + +Bool exynosCrtcEnableAccessibility(xf86CrtcPtr pCrtc); +Bool exynosCrtcExecAccessibility(xf86CrtcPtr pCrtc, tbm_bo src_bo, + tbm_bo dst_bo); + +Bool exynosCrtcTurn(xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user); +Bool exynosCrtcCheckOn(xf86CrtcPtr pCrtc); + +Bool exynosCrtcFullFreeFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe); +PixmapPtr exynosCrtcGetFreeFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe, + DrawablePtr pDraw, + unsigned int usage_hint); +void exynosCrtcRelFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe, + PixmapPtr pPixmap); +void exynosCrtcRelAllFlipPixmap(ScrnInfoPtr pScrn, int crtc_pipe); +void exynosCrtcRemoveFlipPixmap(xf86CrtcPtr pCrtc); + +void exynosCrtcCountFps(xf86CrtcPtr pCrtc); + +xf86CrtcPtr exynosCrtcGetByID(ScrnInfoPtr pScrn, int crtc_id); + +static inline int +exynosCrtcID(EXYNOSCrtcPrivPtr pCrtcPriv) +{ + return pCrtcPriv->mode_crtc->crtc_id; +} + +#endif /* __SEC_CRTC_H__ */ diff --git a/src/crtcconfig/exynos_display.c b/src/crtcconfig/exynos_display.c new file mode 100644 index 0000000..712fcb7 --- /dev/null +++ b/src/crtcconfig/exynos_display.c @@ -0,0 +1,1827 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * + * 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, sublicense, + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <poll.h> +#include <dirent.h> + +#include <X11/extensions/dpmsconst.h> +#include <xorgVersion.h> +#include <X11/Xatom.h> +#include <xf86Crtc.h> +#include <xf86DDC.h> +#include <xf86cmap.h> +#include <exynos.h> + +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_plane.h" +#include "exynos_display.h" +#include "exynos_video_fourcc.h" +#include "exynos_wb.h" +#include "exynos_converter.h" +#include "exynos_util.h" +#include "exynos_xberc.h" +#include <xf86RandR12.h> +#include <exynos/exynos_drm.h> +#include "exynos_dummy.h" + +static Bool EXYNOSCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height); +static void EXYNOSModeVblankHandler(int fd, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + void *event); +static void EXYNOSModePageFlipHandler(int fd, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data); +static void EXYNOSModeG2dHandler(int fd, unsigned int cmdlist_no, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data); +static void EXYNOSModeIppHandler(int fd, unsigned int prop_id, + unsigned int *buf_idx, unsigned int tv_sec, + unsigned int tv_usec, void *event_data); + +static const xf86CrtcConfigFuncsRec exynos_xf86crtc_config_funcs = { + EXYNOSCrtcConfigResize +}; + +static void +_exynosDisplaySetDrmEventCtx(EXYNOSModePtr pExynosMode) +{ + pExynosMode->event_context.vblank_handler = EXYNOSModeVblankHandler; + pExynosMode->event_context.page_flip_handler = EXYNOSModePageFlipHandler; + pExynosMode->event_context.g2d_handler = EXYNOSModeG2dHandler; + pExynosMode->event_context.ipp_handler = EXYNOSModeIppHandler; +} + +static int +_exynosSetMainMode(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode) +{ + xf86CrtcConfigPtr pXf86CrtcConfig; + + pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < pXf86CrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pXf86CrtcConfig->output[i]; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (!pOutputPriv) + continue; + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS + || pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_Unknown) { + memcpy(&pExynosMode->main_lcd_mode, pOutputPriv->mode_output->modes, + sizeof(drmModeModeInfo)); + return 1; + } + } + if (pExynosMode->main_lcd_mode.hdisplay == 0 || + pExynosMode->main_lcd_mode.vdisplay == 0) { + pExynosMode->main_lcd_mode.hdisplay = 640; + pExynosMode->main_lcd_mode.vdisplay = 480; + return 1; + } + return -1; +} + +static void +_exynosDisplayRemoveFlipPixmaps(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; + int conn_type = exynosCrtcGetConnectType(pCrtc); + + if (conn_type == DRM_MODE_CONNECTOR_Unknown) + exynosCrtcRemoveFlipPixmap(pCrtc); + } +} + +static void +_saveFrameBuffer(ScrnInfoPtr pScrn, tbm_bo bo, int w, int h) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + char file[128]; + EXYNOSFbBoDataPtr bo_data; + + if (!pExynos->dump_info) + return; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + XDBG_RETURN_IF_FAIL(bo_data != NULL); + + snprintf(file, sizeof(file), "%03d_fb_%" PRIdPTR ".bmp", pExynos->flip_cnt, + bo_data->fb_id); + exynosUtilDoDumpBmps(pExynos->dump_info, bo, w, h, NULL, file, + DUMP_TYPE_BMP); +} + +static int +exynosHandleEvent(int fd, exynosDrmEventContextPtr evctx) +{ +#define MAX_BUF_SIZE 1024 + + char buffer[MAX_BUF_SIZE]; + unsigned int len, i; + struct drm_event *e; + + /* The DRM read semantics guarantees that we always get only + * complete events. */ + len = read(fd, buffer, sizeof buffer); + if (len == 0) { + XDBG_WARNING(MDISP, "warning: the size of the drm_event is 0.\n"); + return 0; + } + if (len < sizeof *e) { + XDBG_WARNING(MDISP, + "warning: the size of the drm_event is less than drm_event structure.\n"); + return -1; + } + if (len > MAX_BUF_SIZE - sizeof(struct drm_exynos_ipp_event)) { + XDBG_WARNING(MDISP, + "warning: the size of the drm_event can be over the maximum size.\n"); + return -1; + } + + i = 0; + while (i < len && i < MAX_BUF_SIZE) { + e = (struct drm_event *) &buffer[i]; + switch (e->type) { + case DRM_EVENT_VBLANK: + { + struct drm_event_vblank *vblank; + + if (evctx->vblank_handler == NULL) + break; + + vblank = (struct drm_event_vblank *) e; + evctx->vblank_handler(fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, + (void *) ((unsigned long) vblank->user_data)); + } + break; + case DRM_EVENT_FLIP_COMPLETE: + { + struct drm_event_vblank *vblank; + + if (evctx->page_flip_handler == NULL) + break; + + vblank = (struct drm_event_vblank *) e; + evctx->page_flip_handler(fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, (void *) ((unsigned long) + vblank-> + user_data)); + } + break; + case DRM_EXYNOS_G2D_EVENT: + { + struct drm_exynos_g2d_event *g2d; + + if (evctx->g2d_handler == NULL) + break; + + g2d = (struct drm_exynos_g2d_event *) e; + evctx->g2d_handler(fd, + g2d->cmdlist_no, + g2d->tv_sec, + g2d->tv_usec, + (void *) ((unsigned long) g2d->user_data)); + } + break; + case DRM_EXYNOS_IPP_EVENT: + { + struct drm_exynos_ipp_event *ipp; + + if (evctx->ipp_handler == NULL) + break; + + ipp = (struct drm_exynos_ipp_event *) e; + evctx->ipp_handler(fd, + ipp->prop_id, + ipp->buf_id, + ipp->tv_sec, + ipp->tv_usec, + (void *) ((unsigned long) ipp->user_data)); + } + break; + default: + break; + } + i += e->length; + } + + return 0; +} + +static Bool +EXYNOSCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height) +{ + ScreenPtr pScreen = pScrn->pScreen; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_DEBUG(MDISP, "Resize cur(%dx%d) new(%d,%d)\n", + pScrn->virtualX, pScrn->virtualY, width, height); +#ifdef NO_CRTC_MODE + pExynos->isCrtcOn = exynosCrtcCheckInUseAll(pScrn); +#endif + if (pScrn->virtualX == width && pScrn->virtualY == height) { + return TRUE; + } + exynosFbResize(pExynos->pFb, width, height); + + /* set the new size of pScrn */ + pScrn->virtualX = width; + pScrn->virtualY = height; + pScrn->displayWidth = width; + exynosExaScreenSetScrnPixmap(pScreen); + + exynosOutputDrmUpdate(pScrn); + + _exynosDisplayRemoveFlipPixmaps(pScrn); + + return TRUE; +} + +static void +EXYNOSModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event) +{ + EXYNOSVBlankInfoPtr pVblankInfo = event; + EXYNOSVBlankInfoType vblank_type; + void *data; + + XDBG_RETURN_IF_FAIL(pVblankInfo != NULL); + + vblank_type = pVblankInfo->type; + data = pVblankInfo->data; + +#if DBG_DRM_EVENT + xDbgLogDrmEventRemoveVblank(pVblankInfo->xdbg_log_vblank); +#endif + + if (vblank_type == VBLANK_INFO_SWAP) { + XDBG_TRACE(MDISP, "vblank handler (%p, %ld, %ld)\n", + pVblankInfo, pVblankInfo->time, + GetTimeInMillis() - pVblankInfo->time); + exynosDri2FrameEventHandler(frame, tv_sec, tv_usec, data); + } + else if (vblank_type == VBLANK_INFO_PLANE) + exynosLayerVBlankEventHandler(frame, tv_sec, tv_usec, data); + else if (vblank_type == VBLANK_INFO_PRESENT) { + XDBG_TRACE(MDISP, "vblank handler (%p, %ld, %ld)\n", + pVblankInfo, pVblankInfo->time, + GetTimeInMillis() - pVblankInfo->time); + exynosPresentVblankHandler(frame, tv_sec, tv_usec, data); + } + else + XDBG_ERROR(MDISP, "unknown the vblank type\n"); + + free(pVblankInfo); + pVblankInfo = NULL; +} + +static void +EXYNOSModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + EXYNOSPageFlipPtr flip = event_data; + xf86CrtcPtr pCrtc; + EXYNOSCrtcPrivPtr pCrtcPriv; + + if (!flip) { + XDBG_ERROR(MDISP, "flip is null\n"); + return; + } + + XDBG_TRACE(MDISP, "pageflip handler (%p, %ld, %ld)\n", + flip, flip->time, GetTimeInMillis() - flip->time); + +#if DBG_DRM_EVENT + if (flip->xdbg_log_pageflip != NULL) + xDbgLogDrmEventRemovePageflip(flip->xdbg_log_pageflip); +#endif + + pCrtc = flip->pCrtc; + pCrtcPriv = pCrtc->driver_private; + pCrtcPriv->is_flipping = FALSE; + pCrtcPriv->is_fb_blit_flipping = FALSE; + pCrtcPriv->flip_count--; /* check flipping completed */ + + /* Is this the event whose info shall be delivered to higher level? */ + /* Yes: Cache msc, ust for later delivery. */ + pCrtcPriv->fe_frame = frame; + pCrtcPriv->fe_tv_sec = tv_sec; + pCrtcPriv->fe_tv_usec = tv_usec; + + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) + if (pCrtcPriv->accessibility_front_bo && + pCrtcPriv->accessibility_back_bo) { + tbm_bo temp; + + temp = pCrtcPriv->accessibility_front_bo; + pCrtcPriv->accessibility_front_bo = + pCrtcPriv->accessibility_back_bo; + pCrtcPriv->accessibility_back_bo = temp; + } + + /* accessibility */ + if (flip->accessibility_back_bo) { + exynosRenderBoUnref(flip->accessibility_back_bo); + flip->accessibility_back_bo = NULL; + } + + /* if accessibility is diabled, remove the accessibility_bo + when the pageflip is occurred once after the accessibility is disabled */ + if (!pCrtcPriv->bAccessibility && pCrtcPriv->screen_rotate_degree == 0) { + if (pCrtcPriv->accessibility_front_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + } + if (pCrtcPriv->accessibility_back_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_back_bo); + pCrtcPriv->accessibility_back_bo = NULL; + } + } + + /* Release back framebuffer */ + if (flip->back_bo) { + exynosRenderBoUnref(flip->back_bo); + flip->back_bo = NULL; + } + + XDBG_DEBUG(MDISP, + "ModePageFlipHandler ctrc_id:%d dispatch_me:%d, frame:%d, flip_count=%d is_pending=%p\n", + exynosCrtcID(pCrtcPriv), flip->dispatch_me, frame, + pCrtcPriv->flip_count, exynosCrtcGetFirstPendingFlip(pCrtc)); + + /* Last crtc completed flip? */ + if (flip->dispatch_me) { + exynosCrtcCountFps(pCrtc); + + /* Deliver cached msc, ust from reference crtc to flip event handler */ + if (flip->handler) { + if (pCrtcPriv->flip_info != flip->data) { + XDBG_NEVER_GET_HERE(MDISP); + pCrtcPriv->flip_info = flip->data; + } + flip->handler(pCrtcPriv->fe_frame, pCrtcPriv->fe_tv_sec, + pCrtcPriv->fe_tv_usec, pCrtcPriv->flip_info, + flip->flip_failed); + } + } + + if (pCrtcPriv->flip_info == NULL) { + /** + * If pCrtcPriv->flip_info is failed and exynosCrtcGetFirstPendingFlip (pCrtc) has data, + * ModePageFlipHandler is triggered by exynosDisplayUpdateRequest(). - Maybe FB_BLIT or FB is updated by CPU. + * In this case we should call exynosDri2ProcessPending(). + */ + XDBG_DEBUG(MDISP, + "FB_BLIT or FB is updated by CPU. But there's exynosCrtcGetFirstPendingFlip(). So called it manually\n"); + exynosDri2ProcessPending(pCrtc, frame, tv_sec, tv_usec); + } + + free(flip); +} + +static void +EXYNOSModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ +} + +static void +EXYNOSModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data) +{ + XDBG_DEBUG(MDRM, "wb_prop_id(%d) prop_id(%d), buf_idx(%d, %d) \n", + exynosWbGetPropID(), prop_id, buf_idx[0], buf_idx[1]); + + if (exynosWbGetPropID() == prop_id) + exynosWbHandleIppEvent(fd, buf_idx, event_data); + else + exynosCvtHandleIppEvent(fd, buf_idx, event_data, FALSE); +} + +static void +EXYNOSModeWakeupHanlder(pointer data, int err, pointer p) +{ + EXYNOSModePtr pExynosMode; + fd_set *read_mask; + + if (data == NULL || err < 0) + return; + + pExynosMode = data; + read_mask = p; + if (FD_ISSET(pExynosMode->fd, read_mask)) + exynosHandleEvent(pExynosMode->fd, &pExynosMode->event_context); +} + +Bool +exynosModePreInit(ScrnInfoPtr pScrn, int drm_fd) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode; + unsigned int i; + int cpp; + +// exynosLogSetLevel(MDISP, 0); + + pExynosMode = calloc(1, sizeof *pExynosMode); + if (!pExynosMode) + return FALSE; + + pExynosMode->fd = drm_fd; + xorg_list_init(&pExynosMode->crtcs); + xorg_list_init(&pExynosMode->outputs); + xorg_list_init(&pExynosMode->planes); + + xf86CrtcConfigInit(pScrn, &exynos_xf86crtc_config_funcs); + + cpp = pScrn->bitsPerPixel / 8; + + pExynosMode->cpp = cpp; + pExynosMode->mode_res = drmModeGetResources(pExynosMode->fd); + if (!pExynosMode->mode_res) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to get resources: %s\n", strerror(errno)); + free(pExynosMode); + return FALSE; + } + + pExynosMode->plane_res = drmModeGetPlaneResources(pExynosMode->fd); + if (!pExynosMode->plane_res) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to get plane resources: %s\n", strerror(errno)); + drmModeFreeResources(pExynosMode->mode_res); + free(pExynosMode); + return FALSE; + } + + xf86CrtcSetSizeRange(pScrn, 320, 200, pExynosMode->mode_res->max_width, + pExynosMode->mode_res->max_height); +#if 1 + for (i = 0; i < pExynosMode->mode_res->count_crtcs; i++) + exynosCrtcInit(pScrn, pExynosMode, i); + + for (i = 0; i < pExynosMode->mode_res->count_connectors; i++) + exynosOutputInit(pScrn, pExynosMode, i); +#endif + for (i = 0; i < pExynosMode->plane_res->count_planes; i++) + exynosPlaneInit(pScrn, pExynosMode, i); +#if 0 + exynosDummyOutputInit(pScrn, pExynosMode, FALSE); +#endif //NO_CRTC_MODE + _exynosSetMainMode(pScrn, pExynosMode); + + /* virtaul x and virtual y of the screen is ones from main lcd mode */ + pScrn->virtualX = pExynosMode->main_lcd_mode.hdisplay; + pScrn->virtualY = pExynosMode->main_lcd_mode.vdisplay; + xf86InitialConfiguration(pScrn, TRUE); + + /* soolim:: + * we assume that kernel always support the pageflipping + * and the drm vblank + */ + /* set the drm event context */ + _exynosDisplaySetDrmEventCtx(pExynosMode); + + pExynos->pExynosMode = pExynosMode; + + /* virtaul x and virtual y of the screen is ones from main lcd mode */ + pScrn->virtualX = pExynosMode->main_lcd_mode.hdisplay; + pScrn->virtualY = pExynosMode->main_lcd_mode.vdisplay; +#ifdef USE_XDBG +#if DBG_DRM_EVENT + xDbgLogDrmEventInit(); +#endif +#endif + return TRUE; +} + +void +exynosModeInit(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + /* We need to re-register the mode->fd for the synchronisation + * feedback on every server generation, so perform the + * registration within ScreenInit and not PreInit. + */ + //pExynosMode->flip_count = 0; + AddGeneralSocket(pExynosMode->fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr) NoopDDA, + EXYNOSModeWakeupHanlder, pExynosMode); + +} + +void +exynosModeDeinit(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) pExynos->pExynosMode; + xf86CrtcPtr pCrtc = NULL; + xf86OutputPtr pOutput = NULL; + + exynosDisplayDeinitDispMode(pScrn); + + EXYNOSCrtcPrivPtr crtc_ref = NULL, crtc_next = NULL; + + xorg_list_for_each_entry_safe(crtc_ref, crtc_next, &pExynosMode->crtcs, + link) { + pCrtc = crtc_ref->pCrtc; + xf86CrtcDestroy(pCrtc); + } + + EXYNOSOutputPrivPtr output_ref = NULL, output_next = NULL; + + xorg_list_for_each_entry_safe(output_ref, output_next, + &pExynosMode->outputs, link) { + pOutput = output_ref->pOutput; + xf86OutputDestroy(pOutput); + } + + EXYNOSPlanePrivPtr plane_ref = NULL, plane_next = NULL; + + xorg_list_for_each_entry_safe(plane_ref, plane_next, &pExynosMode->planes, + link) { + exynosPlaneDeinit(pScrn, plane_ref); + } + + if (pExynosMode->mode_res) + drmModeFreeResources(pExynosMode->mode_res); + + if (pExynosMode->plane_res) + drmModeFreePlaneResources(pExynosMode->plane_res); + + /* mode->rotate_fb_id should have been destroyed already */ + +#ifdef NO_CRTC_MODE + if (pExynosMode->num_dummy_output > 0) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr pCrtc = xf86_config->crtc[i]; + + xf86CrtcDestroy(pCrtc); + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr pOutput = xf86_config->output[i]; + + xf86OutputDestroy(pOutput); + } + } +#endif //NO_CRTC_MODE + + free(pExynosMode); + pExynos->pExynosMode = NULL; +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc + * with greater coverage + */ +xf86CrtcPtr +exynosModeCoveringCrtc(ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, + BoxPtr pBoxCrtc) +{ + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr pCrtc, pBestCrtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + XDBG_RETURN_VAL_IF_FAIL(pBox != NULL, NULL); + + pBestCrtc = NULL; + best_coverage = 0; + + if (pBoxCrtc) { + pBoxCrtc->x1 = 0; + pBoxCrtc->y1 = 0; + pBoxCrtc->x2 = 0; + pBoxCrtc->y2 = 0; + } + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + pCrtc = pCrtcConfig->crtc[c]; + + /* If the CRTC is off, treat it as not covering */ + if (!exynosCrtcOn(pCrtc)) + continue; + + crtc_box.x1 = pCrtc->x; + crtc_box.x2 = pCrtc->x + xf86ModeWidth(&pCrtc->mode, pCrtc->rotation); + crtc_box.y1 = pCrtc->y; + crtc_box.y2 = pCrtc->y + xf86ModeHeight(&pCrtc->mode, pCrtc->rotation); + + exynosUtilBoxIntersect(&cover_box, &crtc_box, pBox); + coverage = exynosUtilBoxArea(&cover_box); + + if (coverage && pCrtc == pDesiredCrtc) { + if (pBoxCrtc) + *pBoxCrtc = crtc_box; + return pCrtc; + } + + if (coverage > best_coverage) { + if (pBoxCrtc) + *pBoxCrtc = crtc_box; + pBestCrtc = pCrtc; + best_coverage = coverage; + } + } + + return pBestCrtc; +} + +int +exynosModeGetCrtcPipe(xf86CrtcPtr pCrtc) +{ + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return -1; + return pCrtcPriv->pipe; +} + +Bool +exynosModePageFlip(ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void *flip_info, + int pipe, tbm_bo back_bo, RegionPtr pFlipRegion, + unsigned int client_idx, XID drawable_id, + EXYNOSFlipEventHandler handler, Bool change_front) +{ + EXYNOSPageFlipPtr pPageFlip = NULL; + EXYNOSFbBoDataPtr bo_data; + EXYNOSCrtcPrivPtr pCrtcPriv; + EXYNOSModePtr pExynosMode; + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr pCurCrtc; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int ret; + int fb_id = 0; + + BoxRec b1; + int retBox, found = 0; + int i; + + tbm_bo_get_user_data(back_bo, TBM_BO_DATA_FB, (void * *) &bo_data); + XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE); + + for (i = 0; i < pCrtcConfig->num_crtc; i++) { + pCurCrtc = pCrtcConfig->crtc[i]; + if (!pCurCrtc->enabled) + continue; + pCrtcPriv = pCurCrtc->driver_private; + pExynosMode = pCrtcPriv->pExynosMode; + + b1.x1 = pCurCrtc->x; + b1.y1 = pCurCrtc->y; + b1.x2 = pCurCrtc->x + pCurCrtc->mode.HDisplay; + b1.y2 = pCurCrtc->y + pCurCrtc->mode.VDisplay; + + retBox = exynosUtilBoxInBox(&bo_data->pos, &b1); + if (retBox == rgnSAME || retBox == rgnIN) { + pPageFlip = calloc(1, sizeof(EXYNOSPageFlipRec)); + if (pPageFlip == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Page flip alloc failed\n"); + return FALSE; + } + + /* Only the reference crtc will finally deliver its page flip + * completion event. All other crtc's events will be discarded. + */ + pPageFlip->dispatch_me = 0; + pPageFlip->pCrtc = pCurCrtc; + pPageFlip->clone = TRUE; + pPageFlip->back_bo = exynosRenderBoRef(back_bo); + pPageFlip->data = flip_info; + pPageFlip->flip_failed = FALSE; + pPageFlip->handler = handler; + + /* accessilitity */ + if (pCrtcPriv->bAccessibility || + pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo; + EXYNOSFbBoDataPtr accessibility_bo_data; + + tbm_bo_get_user_data(accessibility_bo, TBM_BO_DATA_FB, + (void * *) &accessibility_bo_data); + XDBG_GOTO_IF_FAIL(accessibility_bo_data != NULL, fail); + + fb_id = accessibility_bo_data->fb_id; + + /*Buffer is already changed by bo_swap */ + if (!exynosCrtcExecAccessibility + (pCurCrtc, back_bo, accessibility_bo)) + goto fail; + + pPageFlip->accessibility_back_bo = + exynosRenderBoRef(accessibility_bo); + } + else { + fb_id = bo_data->fb_id; + + tbm_bo_map(pPageFlip->back_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + tbm_bo_unmap(pPageFlip->back_bo); + } + + pCrtcPriv->is_flipping = TRUE; + + if (!pCrtcPriv->onoff && !pCrtcPriv->onoff_always) + exynosCrtcTurn(pCrtcPriv->pCrtc, TRUE, FALSE, FALSE); + +#if DBG_DRM_EVENT + pPageFlip->xdbg_log_pageflip = + xDbgLogDrmEventAddPageflip(pipe, client_idx, drawable_id); +#endif + + XDBG_DEBUG(MSEC, "dump_mode(%x)\n", pExynos->dump_mode); + + if (pExynos->dump_mode & XBERC_DUMP_MODE_FB) + _saveFrameBuffer(pScrn, back_bo, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1); + + pPageFlip->time = GetTimeInMillis(); + + /*Set DirtyFB */ + if (pExynos->use_partial_update && pFlipRegion) { + int nBox; + BoxPtr pBox; + RegionRec new_region; + RegionPtr pRegion = pFlipRegion; + + for (nBox = RegionNumRects(pRegion), + pBox = RegionRects(pRegion); nBox--; pBox++) { + XDBG_DEBUG(MDISP, "dirtfb region(%d): (%d,%d %dx%d)\n", + nBox, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + } + + if (pCrtcPriv->screen_rotate_degree > 0) { + RegionCopy(&new_region, pFlipRegion); + exynosUtilRotateRegion(pCrtc->mode.HDisplay, + pCrtc->mode.VDisplay, &new_region, + pCrtcPriv->screen_rotate_degree); + pRegion = &new_region; + + for (nBox = RegionNumRects(pRegion), + pBox = RegionRects(pRegion); nBox--; pBox++) { + XDBG_DEBUG(MDISP, + "(R)dirtfb region(%d): (%d,%d %dx%d)\n", + nBox, pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); + } + } + + drmModeDirtyFB(pExynos->drm_fd, fb_id, + (drmModeClipPtr) RegionRects(pRegion), + (uint32_t) RegionNumRects(pRegion)); + } + + /* DRM Page Flip */ + ret = + drmModePageFlip(pExynos->drm_fd, exynosCrtcID(pCrtcPriv), fb_id, + DRM_MODE_PAGE_FLIP_EVENT, pPageFlip); + pExynos->flip_cnt++; + + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Page flip failed: %s\n", strerror(errno)); + goto fail; + } + + XDBG_TRACE(MDISP, "pageflip do (%p, %ld)\n", pPageFlip, + pPageFlip->time); + + pCrtcPriv->flip_count++; /* check flipping completed */ + pCrtcPriv->flip_info = (DRI2FrameEventPtr) flip_info; + if (change_front) + pCrtcPriv->front_bo = back_bo; + + found++; + XDBG_DEBUG(MDISP, + "ModePageFlip crtc_id:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d\n", + exynosCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, + tbm_bo_export(back_bo), pCrtcPriv->bAccessibility); + } + } + + if (found == 0) { + XDBG_WARNING(MDISP, "Cannot find CRTC in (%d,%d)-(%d,%d)\n", + bo_data->pos.x1, bo_data->pos.y1, bo_data->pos.x2, + bo_data->pos.y2); + return FALSE; + } + + /* Set dispatch_me to last pageflip */ + pPageFlip->dispatch_me = 1; + + return TRUE; + + fail: + pCrtcPriv->flip_count++; /* check flipping completed */ + pCrtcPriv->flip_info = (DRI2FrameEventPtr) flip_info; + pPageFlip->dispatch_me = 1; + pPageFlip->flip_failed = TRUE; + + EXYNOSModePageFlipHandler(pExynosMode->fd, 0, 0, 0, pPageFlip); + + XDBG_ERROR(MDISP, + "drmModePageFlip error(crtc:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d)\n", + exynosCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, + tbm_bo_export(back_bo), pCrtcPriv->bAccessibility); + + return TRUE; +} + +/* load palette per a crtc */ +void +exynosModeLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual) +{ + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int i, j, index; + int p; + uint16_t lut_r[256], lut_g[256], lut_b[256]; + + for (p = 0; p < pCrtcConfig->num_crtc; p++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[p]; + + switch (pScrn->depth) { + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + if (index <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } + break; + default: + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + + } + break; + } + + /* make the change through RandR */ + RRCrtcGammaSet(pCrtc->randr_crtc, lut_r, lut_g, lut_b); + } +} + +void +exynosDisplaySwapModeFromKmode(ScrnInfoPtr pScrn, + drmModeModeInfoPtr kmode, DisplayModePtr pMode) +{ + char fake_name[32] = "fake_mode"; + + memset(pMode, 0, sizeof(DisplayModeRec)); + pMode->status = MODE_OK; + + pMode->Clock = kmode->clock; + + pMode->HDisplay = kmode->vdisplay; + pMode->HSyncStart = kmode->vsync_start; + pMode->HSyncEnd = kmode->vsync_end; + pMode->HTotal = kmode->vtotal; + pMode->HSkew = kmode->vscan; + + pMode->VDisplay = kmode->hdisplay; + pMode->VSyncStart = kmode->hsync_start; + pMode->VSyncEnd = kmode->hsync_end; + pMode->VTotal = kmode->htotal; + pMode->VScan = kmode->hskew; + + pMode->Flags = kmode->flags; //& FLAG_BITS; + pMode->name = strdup(fake_name); + + if (kmode->type & DRM_MODE_TYPE_DRIVER) + pMode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + pMode->type |= M_T_PREFERRED; + + xf86SetModeCrtc(pMode, pScrn->adjustFlags); +} + +void +exynosDisplayModeFromKmode(ScrnInfoPtr pScrn, + drmModeModeInfoPtr kmode, DisplayModePtr pMode) +{ + memset(pMode, 0, sizeof(DisplayModeRec)); + pMode->status = MODE_OK; + + pMode->Clock = kmode->clock; + + pMode->HDisplay = kmode->hdisplay; + pMode->HSyncStart = kmode->hsync_start; + pMode->HSyncEnd = kmode->hsync_end; + pMode->HTotal = kmode->htotal; + pMode->HSkew = kmode->hskew; + + pMode->VDisplay = kmode->vdisplay; + pMode->VSyncStart = kmode->vsync_start; + pMode->VSyncEnd = kmode->vsync_end; + pMode->VTotal = kmode->vtotal; + pMode->VScan = kmode->vscan; + + pMode->Flags = kmode->flags; //& FLAG_BITS; + pMode->name = strdup(kmode->name); + pMode->VRefresh = kmode->vrefresh; + + if (kmode->type & DRM_MODE_TYPE_DRIVER) + pMode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + pMode->type |= M_T_PREFERRED; + + xf86SetModeCrtc(pMode, pScrn->adjustFlags); +} + +void +exynosDisplaySwapModeToKmode(ScrnInfoPtr pScrn, + drmModeModeInfoPtr kmode, DisplayModePtr pMode) +{ + memset(kmode, 0, sizeof(*kmode)); + + kmode->clock = pMode->Clock; + kmode->hdisplay = pMode->VDisplay; + kmode->hsync_start = pMode->VSyncStart; + kmode->hsync_end = pMode->VSyncEnd; + kmode->htotal = pMode->VTotal; + kmode->hskew = pMode->VScan; + + kmode->vdisplay = pMode->HDisplay; + kmode->vsync_start = pMode->HSyncStart; + kmode->vsync_end = pMode->HSyncEnd; + kmode->vtotal = pMode->HTotal; + kmode->vscan = pMode->HSkew; + kmode->vrefresh = xf86ModeVRefresh(pMode); + + kmode->flags = pMode->Flags; //& FLAG_BITS; + if (pMode->name) + strncpy(kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN); + kmode->name[DRM_DISPLAY_MODE_LEN - 1] = 0; +} + +void +exynosDisplayModeToKmode(ScrnInfoPtr pScrn, + drmModeModeInfoPtr kmode, DisplayModePtr pMode) +{ + memset(kmode, 0, sizeof(*kmode)); + + kmode->clock = pMode->Clock; + kmode->hdisplay = pMode->HDisplay; + kmode->hsync_start = pMode->HSyncStart; + kmode->hsync_end = pMode->HSyncEnd; + kmode->htotal = pMode->HTotal; + kmode->hskew = pMode->HSkew; + + kmode->vdisplay = pMode->VDisplay; + kmode->vsync_start = pMode->VSyncStart; + kmode->vsync_end = pMode->VSyncEnd; + kmode->vtotal = pMode->VTotal; + kmode->vscan = pMode->VScan; + kmode->vrefresh = xf86ModeVRefresh(pMode); + + kmode->flags = pMode->Flags; //& FLAG_BITS; + if (pMode->name) + strncpy(kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN); + + kmode->name[DRM_DISPLAY_MODE_LEN - 1] = 0; +} + +static uint32_t crtc_id; +static tbm_bo hdmi_bo; + +static Bool connect_crtc; + +static int +_exynosDisplayGetAvailableCrtcID(ScrnInfoPtr pScrn) +{ + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + int i; + int crtc_id = 0; + + for (i = 0; i < pExynosMode->mode_res->count_crtcs; i++) { + drmModeCrtcPtr kcrtc = NULL; + + kcrtc = + drmModeGetCrtc(pExynosMode->fd, pExynosMode->mode_res->crtcs[i]); + if (!kcrtc) { + XDBG_ERROR(MSEC, "fail to get kcrtc. \n"); + return 0; + } + + if (kcrtc->buffer_id > 0) { + drmModeFreeCrtc(kcrtc); + continue; + } + + crtc_id = kcrtc->crtc_id; + drmModeFreeCrtc(kcrtc); + + return crtc_id; + } + + return 0; +} + +static void +_exynosDisplayWbCloseFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, void *noti_data, + void *user_data) +{ + ScrnInfoPtr pScrn = (ScrnInfoPtr) user_data; + EXYNOSPtr pExynos; + + if (!pScrn) + return; + + pExynos = EXYNOSPTR(pScrn); + + pExynos->wb_clone = NULL; +} + +Bool +exynosDisplayInitDispMode(ScrnInfoPtr pScrn, EXYNOSDisplayConnMode conn_mode) +{ + XDBG_DEBUG(MDISP, "E. pScrn %p, conn_mode %d\n", pScrn, conn_mode); + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + Bool ret = FALSE; + uint32_t *output_ids = NULL; + int output_cnt = 1; + uint32_t fb_id; + drmModeModeInfoPtr pKmode = NULL; + drmModeCrtcPtr kcrtc = NULL; + EXYNOSFbBoDataPtr bo_data = NULL; + EXYNOSOutputPrivPtr pOutputPriv = NULL, pNext = NULL; + int connector_type = -1; + int width, height; + + if (connect_crtc) { + XDBG_DEBUG(MDISP, "Q. Connect_crtc is %s. ret = TRUE\n", + connect_crtc ? "TRUE" : "FALSE"); + return TRUE; + } + + /* get output ids */ + output_ids = calloc(output_cnt, sizeof(uint32_t)); + XDBG_GOTO_IF_FAIL(output_ids != NULL, fail_to_init); + + xorg_list_for_each_entry_safe(pOutputPriv, pNext, &pExynosMode->outputs, + link) { + if (conn_mode == DISPLAY_CONN_MODE_HDMI) { + if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIB) { + output_ids[0] = pOutputPriv->mode_output->connector_id; + pKmode = &pExynosMode->ext_connector_mode; + connector_type = pOutputPriv->mode_output->connector_type; + break; + } + } + else if (conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) { + output_ids[0] = pOutputPriv->mode_output->connector_id; + pKmode = &pExynosMode->ext_connector_mode; + connector_type = pOutputPriv->mode_output->connector_type; + break; + } + + } + else { + XDBG_NEVER_GET_HERE(MTVO); + goto fail_to_init; + } + } + XDBG_GOTO_IF_FAIL(output_ids[0] > 0, fail_to_init); + XDBG_GOTO_IF_FAIL(pKmode != NULL, fail_to_init); + + width = pKmode->hdisplay; + height = pKmode->vdisplay; + + pOutputPriv = exynosOutputGetPrivateForConnType(pScrn, connector_type); + if (pOutputPriv && pOutputPriv->mode_encoder) + XDBG_GOTO_IF_FAIL(pOutputPriv->mode_encoder->crtc_id == 0, + fail_to_init); + + crtc_id = _exynosDisplayGetAvailableCrtcID(pScrn); + XDBG_GOTO_IF_FAIL(crtc_id > 0, fail_to_init); + + /* get crtc_id */ + kcrtc = drmModeGetCrtc(pExynosMode->fd, crtc_id); + XDBG_GOTO_IF_FAIL(kcrtc != NULL, fail_to_init); + + if (kcrtc->buffer_id > 0) { + XDBG_ERROR(MTVO, "crtc(%d) already has buffer(%d) \n", + crtc_id, kcrtc->buffer_id); + goto fail_to_init; + } + + /* get fb_id */ + hdmi_bo = exynosRenderBoCreate(pScrn, width, height); + XDBG_GOTO_IF_FAIL(hdmi_bo != NULL, fail_to_init); + + tbm_bo_get_user_data(hdmi_bo, TBM_BO_DATA_FB, (void * *) &bo_data); + XDBG_GOTO_IF_FAIL(bo_data != NULL, fail_to_init); + + fb_id = bo_data->fb_id; + + /* set crtc */ + if (drmModeSetCrtc + (pExynosMode->fd, crtc_id, fb_id, 0, 0, output_ids, output_cnt, + pKmode)) { + XDBG_ERRNO(MTVO, "drmModeSetCrtc failed. \n"); + goto fail_to_init; + } + else { + ret = TRUE; + } + + exynosUtilSetDrmProperty(pExynosMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", + 1); + + exynosOutputDrmUpdate(pScrn); + + XDBG_INFO(MDISP, "** ModeSet : (%dx%d) %dHz !!\n", pKmode->hdisplay, + pKmode->vdisplay, pKmode->vrefresh); + + connect_crtc = TRUE; + + fail_to_init: + free(output_ids); + if (kcrtc) + drmModeFreeCrtc(kcrtc); + XDBG_DEBUG(MDISP, "Q. ret = %s\n", ret ? "TRUE" : "FALSE"); + return ret; +} + +void +exynosDisplayDeinitDispMode(ScrnInfoPtr pScrn) +{ + XDBG_DEBUG(MDISP, "E. pScrn %p\n", pScrn); + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + + if (!connect_crtc) { + XDBG_DEBUG(MDISP, "Q. connect_crtc is %s\n", + connect_crtc ? "TRUE" : "FALSE"); + return; + } + + XDBG_INFO(MDISP, "** ModeUnset. !!\n"); + + exynosUtilSetDrmProperty(pExynosMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", + 0); + + if (hdmi_bo) { + exynosRenderBoUnref(hdmi_bo); + hdmi_bo = NULL; + } + + exynosOutputDrmUpdate(pScrn); + + crtc_id = 0; + connect_crtc = FALSE; + XDBG_DEBUG(MDISP, "Q.\n"); +} + +Bool +exynosDisplaySetDispSetMode(ScrnInfoPtr pScrn, EXYNOSDisplaySetMode set_mode) +{ + XDBG_DEBUG(MDISP, "E. pScrn %p set_mode %u\n", pScrn, set_mode); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + if (pExynosMode->set_mode == set_mode) { + XDBG_TRACE(MDISP, "set_mode(%u) is already set\n", set_mode); + XDBG_DEBUG(MDISP, "Q. ret = TRUE\n"); + return TRUE; + } + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_NONE) { + XDBG_WARNING(MDISP, + "set_mode(%d) is failed : output is not connected yet\n", + set_mode); + XDBG_DEBUG(MDISP, "Q. ret = FALSE\n"); + return FALSE; + } + + switch (set_mode) { + case DISPLAY_SET_MODE_OFF: + if (exynosWbIsOpened()) { + EXYNOSWb *wb = exynosWbGet(); + + exynosWbClose(wb); + } + exynosDisplayDeinitDispMode(pScrn); + break; + case DISPLAY_SET_MODE_CLONE: + /* In case of DISPLAY_CONN_MODE_VIRTUAL, we will open writeback + * on GetStill. + */ + if (pExynosMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) { + int wb_hz; + + if (pExynos->wb_clone) { + XDBG_ERROR(MWB, "Fail : wb_clone(%p) already exists.\n", + pExynos->wb_clone); + break; + } + + if (exynosWbIsOpened()) { + XDBG_ERROR(MWB, "Fail : wb(%p) already opened.\n", + exynosWbGet()); + break; + } + + wb_hz = + (pExynos->wb_hz > + 0) ? pExynos->wb_hz : pExynosMode->ext_connector_mode.vrefresh; + + XDBG_TRACE(MWB, "wb_hz(%d) vrefresh(%d)\n", pExynos->wb_hz, + pExynosMode->ext_connector_mode.vrefresh); + + pExynos->wb_clone = + exynosWbOpen(pScrn, FOURCC_RGB32, 0, 0, + (pExynos->scanout) ? TRUE : FALSE, wb_hz, TRUE); + if (pExynos->wb_clone) { + exynosWbAddNotifyFunc(pExynos->wb_clone, WB_NOTI_CLOSED, + _exynosDisplayWbCloseFunc, pScrn); + exynosWbSetRotate(pExynos->wb_clone, pExynosMode->rotate); + exynosWbSetTvout(pExynos->wb_clone, TRUE); + if (!exynosWbStart(pExynos->wb_clone)) { + exynosWbClose(pExynos->wb_clone); + XDBG_DEBUG(MDISP, "Q. Can't start WB. ret = FALSE\n"); + return FALSE; + } + } + } + break; + case DISPLAY_SET_MODE_EXT: + if (exynosWbIsOpened()) { + EXYNOSWb *wb = exynosWbGet(); + + exynosWbClose(wb); + } + exynosDisplayDeinitDispMode(pScrn); + break; + default: + break; + } + + pExynosMode->set_mode = set_mode; + XDBG_DEBUG(MDISP, "Q. ret = TRUE\n"); + + return TRUE; +} + +EXYNOSDisplaySetMode +exynosDisplayGetDispSetMode(ScrnInfoPtr pScrn) +{ + EXYNOSDisplaySetMode set_mode; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + set_mode = pExynosMode->set_mode; + + return set_mode; +} + +Bool +exynosDisplaySetDispRotate(ScrnInfoPtr pScrn, int rotate) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + if (pExynosMode->rotate == rotate) + return TRUE; + + pExynosMode->rotate = rotate; + + if (pExynos->wb_clone) + exynosWbSetRotate(pExynos->wb_clone, rotate); + + return TRUE; +} + +int +exynosDisplayGetDispRotate(ScrnInfoPtr pScrn) +{ + int rotate; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + rotate = pExynosMode->rotate; + + return rotate; +} + +Bool +exynosDisplaySetDispConnMode(ScrnInfoPtr pScrn, EXYNOSDisplayConnMode conn_mode) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + if (pExynosMode->conn_mode == conn_mode) { + XDBG_DEBUG(MDISP, "conn_mode(%d) is already set\n", conn_mode); + return TRUE; + } + + switch (conn_mode) { + case DISPLAY_CONN_MODE_NONE: + break; + case DISPLAY_CONN_MODE_HDMI: + break; + case DISPLAY_CONN_MODE_VIRTUAL: + break; + default: + break; + } + + pExynosMode->conn_mode = conn_mode; + + return TRUE; +} + +EXYNOSDisplayConnMode +exynosDisplayGetDispConnMode(ScrnInfoPtr pScrn) +{ + EXYNOSDisplayConnMode conn_mode; + + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + conn_mode = pExynosMode->conn_mode; + + return conn_mode; +} + +Bool +exynosDisplayGetCurMSC(ScrnInfoPtr pScrn, intptr_t pipe, CARD64 * ust, + CARD64 * msc) +{ + drmVBlank vbl; + int ret; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + /* if lcd is off, return true with msc = 0 */ +#ifdef NO_CRTC_MODE + if (pExynos->isCrtcOn == FALSE) { + *ust = 0; + *msc = 0; + return TRUE; + } +#endif //NO_CRTC_MODE +// if (pExynos->isLcdOff) +// { +// *ust = 0; +// *msc = 0; +// return TRUE; +// } + + /* if pipe is -1, return the current msc of the main crtc */ + if (pipe == -1) + pipe = 0; + + vbl.request.type = DRM_VBLANK_RELATIVE; + + if (pipe > 0) { +#ifdef LEGACY_INTERFACE + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI; + else +#endif + vbl.request.type |= DRM_VBLANK_SECONDARY; + } + + vbl.request.sequence = 0; + ret = drmWaitVBlank(pExynos->drm_fd, &vbl); + if (ret) { + *ust = 0; + *msc = 0; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "first get vblank counter failed: %s\n", strerror(errno)); + return FALSE; + } + + *ust = ((CARD64) vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; + *msc = vbl.reply.sequence; + + return TRUE; +} + +Bool +exynosDisplayVBlank(ScrnInfoPtr pScrn, intptr_t pipe, CARD64 * target_msc, + intptr_t flip, EXYNOSVBlankInfoType type, void *vblank_info) +{ + drmVBlank vbl; + int ret; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSVBlankInfoPtr pVblankInfo = NULL; + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + pVblankInfo = calloc(1, sizeof(EXYNOSVBlankInfoRec)); + if (pVblankInfo == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "vblank_info alloc failed\n"); + return FALSE; + } + + pVblankInfo->type = type; + pVblankInfo->data = vblank_info; + pVblankInfo->time = GetTimeInMillis(); + + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + + if (pipe > 0) { +#ifdef LEGACY_INTERFACE + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI; + else +#endif + vbl.request.type |= DRM_VBLANK_SECONDARY; + } + + /* If non-pageflipping, but blitting/exchanging, we need to use + * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later + * on. + */ + if (flip == 0) { + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL && pipe > 0); /* do not set the DRM_VBLANK_NEXTMISS */ + else + vbl.request.type |= DRM_VBLANK_NEXTONMISS; + } + + vbl.request.sequence = *target_msc; + vbl.request.signal = (unsigned long) pVblankInfo; + +#if DBG_DRM_EVENT + DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) vblank_info; + + if (type == VBLANK_INFO_SWAP) + pVblankInfo->xdbg_log_vblank = + xDbgLogDrmEventAddVblank(pipe, pEvent->client_idx, + pEvent->drawable_id, type); + else + pVblankInfo->xdbg_log_vblank = + xDbgLogDrmEventAddVblank(pipe, 0, 0, type); +#endif + ret = drmWaitVBlank(pExynos->drm_fd, &vbl); + if (ret) { +#if DBG_DRM_EVENT + xDbgLogDrmEventRemoveVblank(pVblankInfo->xdbg_log_vblank); +#endif + if (pVblankInfo) { + free(pVblankInfo); + pVblankInfo = NULL; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "divisor 0 get vblank counter failed: %s\n", + strerror(errno)); + return FALSE; + } + + XDBG_TRACE(MDISP, "vblank do (%p, %ld)\n", pVblankInfo, pVblankInfo->time); + + /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ + *target_msc = vbl.reply.sequence + flip; + + return TRUE; +} + +int +exynosDisplayDrawablePipe(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + BoxRec box, crtc_box; + xf86CrtcPtr pCrtc; + int pipe = -1; + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + + pCrtc = exynosModeCoveringCrtc(pScrn, &box, NULL, &crtc_box); + + if (pCrtc != NULL && !pCrtc->rotatedData) + pipe = exynosModeGetCrtcPipe(pCrtc); + + return pipe; +} + +intptr_t +exynosDisplayCrtcPipe(ScrnInfoPtr pScrn, int crtc_id) +{ + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv->mode_crtc->crtc_id == crtc_id) + return pCrtcPriv->pipe; + } + + XDBG_ERROR(MDISP, "%s(%d): crtc(%d) not found.\n", __func__, __LINE__, + crtc_id); + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + XDBG_ERROR(MDISP, "%s(%d) : crtc(%d) != crtc(%d)\n", __func__, __LINE__, + pCrtcPriv->mode_crtc->crtc_id, crtc_id); + } + + return 0; +} + +Bool +exynosDisplayUpdateRequest(ScrnInfoPtr pScrn) +{ + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, FALSE); + + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + xf86CrtcPtr pCrtc = xf86CompatCrtc(pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv; + tbm_bo bo; + Bool ret = FALSE; + EXYNOSPageFlipPtr pPageFlip = NULL; + +#ifdef NO_CRTC_MODE + if (pCrtc == NULL) + return FALSE; +#else + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); +#endif + pCrtcPriv = pCrtc->driver_private; +#ifdef NO_CRTC_MODE + if (pCrtcPriv == NULL) + return TRUE; +#else + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv != NULL, FALSE); +#endif + + bo = pCrtcPriv->front_bo; + + if ((pExynos->use_hwc && pExynos->hwc_active) || !pExynos->use_flip) { + XDBG_DEBUG(MDISP, "hwc enable\n"); + } + else if (pCrtcPriv->is_fb_blit_flipping || pCrtcPriv->is_flipping || + exynosCrtcGetFirstPendingFlip(pCrtc)) { + XDBG_DEBUG(MDISP, "drmModePageFlip is already requested!\n"); + } + else { + // Without buffer swap, we need to request drmModePageFlip(). + if (bo != NULL) { + EXYNOSFbBoDataPtr bo_data; + int fb_id = 0; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE); + + fb_id = bo_data->fb_id; + + pPageFlip = calloc(1, sizeof(EXYNOSPageFlipRec)); + if (pPageFlip == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Page flip alloc failed\n"); + return FALSE; + } + + /* Only the reference crtc will finally deliver its page flip + * completion event. All other crtc's events will be discarded. + */ + pPageFlip->dispatch_me = 0; + pPageFlip->pCrtc = pCrtc; + pPageFlip->clone = TRUE; + pPageFlip->back_bo = exynosRenderBoRef(bo); + pPageFlip->data = NULL; + pPageFlip->flip_failed = FALSE; + pPageFlip->xdbg_log_pageflip = NULL; + pPageFlip->time = GetTimeInMillis(); + /*TODO: add own handler */ + pPageFlip->handler = NULL; + + /* accessilitity */ + if (pCrtcPriv->bAccessibility || + pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo; + EXYNOSFbBoDataPtr accessibility_bo_data; + + tbm_bo_get_user_data(accessibility_bo, TBM_BO_DATA_FB, + (void * *) &accessibility_bo_data); + XDBG_GOTO_IF_FAIL(accessibility_bo_data != NULL, fail); + + fb_id = accessibility_bo_data->fb_id; + + /*Buffer is already changed by bo_swap */ + if (!exynosCrtcExecAccessibility(pCrtc, bo, accessibility_bo)) + goto fail; + + pPageFlip->accessibility_back_bo = + exynosRenderBoRef(accessibility_bo); + } + + /* + * DRM Page Flip + * If pPageFlip->dispatch_me is NULL, then in EXYNOSModePageFlipHandler, nothing to happen. + * That means only LCD buffer is updated. + * Frame buffer is not swapped. Because these request is only for FB_BLIT case! + */ + if (drmModePageFlip(pExynos->drm_fd, exynosCrtcID(pCrtcPriv), fb_id, + DRM_MODE_PAGE_FLIP_EVENT, pPageFlip)) { + XDBG_ERRNO(MDISP, "Page flip failed: %s\n", strerror(errno)); + goto fail; + } + + pCrtcPriv->flip_info = NULL; + pCrtcPriv->flip_count++; + pCrtcPriv->is_fb_blit_flipping = TRUE; + } + else { + XDBG_DEBUG(MDISP, "pCrtcPriv->front_bo is NULL!\n"); + } + } + + ret = TRUE; + + return ret; + + fail: + + if (pPageFlip != NULL) { + if (pPageFlip->accessibility_back_bo) { + exynosRenderBoUnref(pPageFlip->accessibility_back_bo); + pPageFlip->accessibility_back_bo = NULL; + } + + if (pPageFlip->back_bo) { + exynosRenderBoUnref(pPageFlip->back_bo); + pPageFlip->back_bo = NULL; + } + + free(pPageFlip); + } + + return ret; +} + +#ifdef NO_CRTC_MODE +Bool +exynosDisplayChangeMode(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + xf86CrtcPtr pCrtc = NULL; + xf86OutputPtr pOutput = NULL; + int temp = 99, i = 0; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + + for (i = 0; i < config->num_crtc; i++) { + if (config->crtc[i]->active == TRUE) { + /* Nothing to do */ + return TRUE; + } + } + EXYNOSOutputPrivPtr output_ref = NULL, output_next = NULL; + +/* Priority LVDS > HDMI > Virtual */ + xorg_list_for_each_entry_safe(output_ref, output_next, + &pExynosMode->outputs, link) { + if (output_ref->pOutput->crtc == NULL) + continue; + if (output_ref->mode_output == NULL) + continue; + if (output_ref->mode_output->connector_type == + DRM_MODE_CONNECTOR_Unknown) + continue; + if (output_ref->mode_output->connector_type < temp) { + pOutput = output_ref->pOutput; + pCrtc = output_ref->pOutput->crtc; + temp = (int) output_ref->mode_output->connector_type; + } + } + + if (pCrtc != NULL && pOutput != NULL && pCrtc->active == FALSE) { + DisplayModePtr max_mode = xf86CVTMode(4096, 4096, 60, 0, 0); + DisplayModePtr mode = xf86OutputFindClosestMode(pOutput, max_mode); + + if (mode == NULL) { + XDBG_ERROR(MDISP, + "Can't find display mode for output: %s\n", + pOutput->name); + if (max_mode) + free(max_mode); + return FALSE; + } + if (!RRScreenSizeSet(pScrn->pScreen, + mode->HDisplay, mode->VDisplay, + pOutput->mm_width, pOutput->mm_height)) { + XDBG_ERROR(MDISP, + "Can't setup screen size H:%d V:%d for output: %s\n", + mode->HDisplay, mode->VDisplay, pOutput->name); + if (max_mode) + free(max_mode); + return FALSE; + } + if (!xf86CrtcSetModeTransform(pCrtc, mode, RR_Rotate_0, NULL, 0, 0)) { + XDBG_ERROR(MDISP, "Can't transform Crtc to mode: %s\n", mode->name); + if (max_mode) + free(max_mode); + RRScreenSizeSet(pScrn->pScreen, 640, 480, 0, 0); + return FALSE; + } + if (max_mode) + free(max_mode); + pExynos->enableCursor = TRUE; + exynosCrtcCursorEnable(pScrn, TRUE); +// xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +// for (temp = 0; temp < config->num_output; temp++) +// { +// if (config->output[temp] == pOutput) +// { +// config->compat_output = temp; +// break; +// } +// } + xf86SetScrnInfoModes(pScrn); + xf86RandR12TellChanged(pScrn->pScreen); + } + + if (pExynos->isCrtcOn == FALSE) { + pExynos->enableCursor = FALSE; + exynosCrtcCursorEnable(pScrn, FALSE); + } + + if (pCrtc == NULL) { + RRScreenSizeSet(pScrn->pScreen, 640, 480, 0, 0); + xf86SetScrnInfoModes(pScrn); + xf86RandR12TellChanged(pScrn->pScreen); + } + + return TRUE; +} +#endif diff --git a/src/crtcconfig/exynos_display.h b/src/crtcconfig/exynos_display.h new file mode 100755 index 0000000..914706e --- /dev/null +++ b/src/crtcconfig/exynos_display.h @@ -0,0 +1,207 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 __SEC_DISPLAY_H__ +#define __SEC_DISPLAY_H__ + +#include <xf86drmMode.h> +#include <xf86Crtc.h> +#include <tbm_bufmgr.h> +#include <list.h> + +#define DBG_DRM_EVENT 1 + +typedef enum { + DISPLAY_SET_MODE_OFF, + DISPLAY_SET_MODE_CLONE, + DISPLAY_SET_MODE_EXT, + DISPLAY_SET_MODE_MIRROR, +} EXYNOSDisplaySetMode; + +typedef enum { + DISPLAY_CONN_MODE_NONE, + DISPLAY_CONN_MODE_LVDS, + DISPLAY_CONN_MODE_HDMI, + DISPLAY_CONN_MODE_VIRTUAL, + DISPLAY_CONN_MODE_DUMMY, + DISPLAY_CONN_MODE_MAX, +} EXYNOSDisplayConnMode; + +typedef enum { + VBLNAK_INFO_NONE, + VBLANK_INFO_SWAP, + VBLANK_INFO_PLANE, + VBLANK_INFO_PRESENT, + VBLANK_INFO_PAGE_FLIP, + VBLANK_INFO_MAX +} EXYNOSVBlankInfoType; + +typedef struct _exynosDrmEventContext { + void (*vblank_handler) (int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, void *user_data); + + void (*page_flip_handler) (int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, void *user_data); + + void (*g2d_handler) (int fd, + unsigned int cmdlist_no, + unsigned int tv_sec, + unsigned int tv_usec, void *user_data); + + void (*ipp_handler) (int fd, + unsigned int prop_id, + unsigned int *buf_idx, + unsigned int tv_sec, + unsigned int tv_usec, void *user_data); +} exynosDrmEventContext, *exynosDrmEventContextPtr; + +typedef struct _exynosDrmMode { + int type; + int fd; + drmModeResPtr mode_res; + drmModePlaneResPtr plane_res; + int cpp; + drmModeModeInfo main_lcd_mode; + drmModeModeInfo ext_connector_mode; + + exynosDrmEventContext event_context; + + struct xorg_list outputs; + struct xorg_list crtcs; + struct xorg_list planes; +#ifdef NO_CRTC_MODE + int num_dummy_output; + int num_real_output; + int num_real_crtc; + int num_dummy_crtc; +#endif + EXYNOSDisplaySetMode set_mode; + EXYNOSDisplayConnMode conn_mode; + int rotate; + + int unset_connector_type; +} EXYNOSModeRec, *EXYNOSModePtr; + +typedef void (*EXYNOSFlipEventHandler) (unsigned int frame, + unsigned int tv_exynos, + unsigned int tv_uexynos, + void *event_data, Bool flip_failed); + +typedef struct _exynosPageFlip { + xf86CrtcPtr pCrtc; + Bool dispatch_me; + Bool clone; + Bool flip_failed; + + tbm_bo back_bo; + tbm_bo accessibility_back_bo; + int fb_id; + + void *data; + CARD32 time; + + EXYNOSFlipEventHandler handler; + +#if DBG_DRM_EVENT + void *xdbg_log_pageflip; +#endif +} EXYNOSPageFlipRec, *EXYNOSPageFlipPtr; + +typedef struct _exynosVBlankInfo { + EXYNOSVBlankInfoType type; + void *data; /* request data pointer */ + CARD32 time; + +#if DBG_DRM_EVENT + void *xdbg_log_vblank; +#endif +} EXYNOSVBlankInfoRec, *EXYNOSVBlankInfoPtr; + +typedef struct _exynosProperty { + drmModePropertyPtr mode_prop; + uint64_t value; + int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ + Atom *atoms; +} EXYNOSPropertyRec, *EXYNOSPropertyPtr; + +Bool exynosModePreInit(ScrnInfoPtr pScrn, int drm_fd); +void exynosModeInit(ScrnInfoPtr pScrn); +void exynosModeDeinit(ScrnInfoPtr pScrn); +xf86CrtcPtr exynosModeCoveringCrtc(ScrnInfoPtr pScrn, BoxPtr pBox, + xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc); +int exynosModeGetCrtcPipe(xf86CrtcPtr pCrtc); +Bool exynosModePageFlip(ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void *flip_info, + int pipe, tbm_bo back_bo, RegionPtr pFlipRegion, + unsigned int client_idx, XID drawable_id, + EXYNOSFlipEventHandler handler, Bool change_front); +void exynosModeLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual); + +void exynosDisplaySwapModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, + DisplayModePtr pMode); +void exynosDisplayModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, + DisplayModePtr pMode); +void exynosDisplaySwapModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, + DisplayModePtr pMode); +void exynosDisplayModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, + DisplayModePtr pMode); + +Bool exynosDisplaySetDispSetMode(ScrnInfoPtr pScrn, + EXYNOSDisplaySetMode disp_mode); +EXYNOSDisplaySetMode exynosDisplayGetDispSetMode(ScrnInfoPtr pScrn); +Bool exynosDisplaySetDispRotate(ScrnInfoPtr pScrn, int disp_rotate); +int exynosDisplayGetDispRotate(ScrnInfoPtr pScrn); +Bool exynosDisplaySetDispConnMode(ScrnInfoPtr pScrn, + EXYNOSDisplayConnMode disp_conn); +EXYNOSDisplayConnMode exynosDisplayGetDispConnMode(ScrnInfoPtr pScrn); + +Bool exynosDisplayInitDispMode(ScrnInfoPtr pScrn, + EXYNOSDisplayConnMode conn_mode); +void exynosDisplayDeinitDispMode(ScrnInfoPtr pScrn); + +Bool exynosDisplayGetCurMSC(ScrnInfoPtr pScrn, intptr_t pipe, CARD64 * ust, + CARD64 * msc); +Bool exynosDisplayVBlank(ScrnInfoPtr pScrn, intptr_t pipe, CARD64 * target_msc, + intptr_t flip, EXYNOSVBlankInfoType type, + void *vblank_info); +int exynosDisplayDrawablePipe(DrawablePtr pDraw); + +intptr_t exynosDisplayCrtcPipe(ScrnInfoPtr pScrn, int crtc_id); + +Bool exynosDisplayUpdateRequest(ScrnInfoPtr pScrn); + +#ifdef NO_CRTC_MODE +Bool exynosDisplayChangeMode(ScrnInfoPtr pScrn); +#endif +#endif /* __SEC_DISPLAY_H__ */ diff --git a/src/crtcconfig/exynos_dummy.c b/src/crtcconfig/exynos_dummy.c new file mode 100644 index 0000000..64c389d --- /dev/null +++ b/src/crtcconfig/exynos_dummy.c @@ -0,0 +1,766 @@ +/* + * Copyright © 2013 Intel Corporation + * + * 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, sublicense, + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ +#include "exynos_dummy.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_util.h" +#include "exynos_display.h" +#include "exynos_accel.h" +#ifdef NO_CRTC_MODE +static void +_dummyFlipPixmapInit(xf86CrtcPtr pCrtc) +{ + XDBG_DEBUG(MDOUT, "\n"); + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + XDBG_RETURN_IF_FAIL(pCrtc != NULL); + + int flip_backbufs = pExynos->flip_bufs - 1; + int i; + + pCrtcPriv->flip_backpixs.lub = -1; + pCrtcPriv->flip_backpixs.num = flip_backbufs; + + pCrtcPriv->flip_backpixs.pix_free = calloc(flip_backbufs, sizeof(void *)); + XDBG_RETURN_IF_FAIL(pCrtcPriv->flip_backpixs.pix_free != NULL); + + for (i = 0; i < flip_backbufs; i++) + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + pCrtcPriv->flip_backpixs.flip_pixmaps = + calloc(flip_backbufs, sizeof(void *)); + pCrtcPriv->flip_backpixs.flip_draws = calloc(flip_backbufs, sizeof(void *)); +} + +static void +_dummyFlipPixmapDeinit(xf86CrtcPtr pCrtc) +{ + XDBG_DEBUG(MDOUT, "\n"); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) + return; + ScreenPtr pScreen = pCrtc->scrn->pScreen; + int i; + + for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) { + pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; + if (pCrtcPriv->flip_backpixs.flip_pixmaps[i]) { +#if USE_XDBG + if (pCrtcPriv->flip_backpixs.flip_draws[i]) + xDbgLogPListDrawRemoveRefPixmap(pCrtcPriv->flip_backpixs. + flip_draws[i], + pCrtcPriv->flip_backpixs. + flip_pixmaps[i]); +#endif + + (*pScreen->DestroyPixmap) (pCrtcPriv->flip_backpixs. + flip_pixmaps[i]); + pCrtcPriv->flip_backpixs.flip_pixmaps[i] = NULL; + pCrtcPriv->flip_backpixs.flip_draws[i] = NULL; + } + } + pCrtcPriv->flip_backpixs.lub = -1; +} + +static void +EXYNOSDummyCrtcDpms(xf86CrtcPtr pCrtc, int pMode) +{ + XDBG_DEBUG(MDOUT, "\n"); +} + +static Bool +EXYNOSDummyCrtcSetModeMajor(xf86CrtcPtr pCrtc, DisplayModePtr pMode, + Rotation rotation, int x, int y) +{ + XDBG_DEBUG(MDOUT, "\n"); + ScrnInfoPtr pScrn = pCrtc->scrn; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSFbPtr pFb = pExynos->pFb; + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + int i = 0; + + if (pCrtcPriv == NULL) { + return TRUE; + } + EXYNOSModePtr pExynosMode = pCrtcPriv->pExynosMode; + tbm_bo bo = NULL, old_bo = NULL; + tbm_bo bo_accessibility[2] = { 0, } + , old_bo_accessibility[2] = { + 0,}; + int saved_x, saved_y; + Rotation saved_rotation; + DisplayModeRec saved_mode; + + XDBG_DEBUG(MDOUT, + "SetModeMajor pMode:%d cur(%dx%d+%d+%d),rot:%d new(%dx%d+%d+%d),refresh(%f)rot:%d\n", + exynosCrtcID(pCrtcPriv), + pCrtc->mode.HDisplay, pCrtc->mode.VDisplay, pCrtc->x, pCrtc->y, + pCrtc->rotation, + pMode->HDisplay, pMode->VDisplay, x, y, pMode->VRefresh, + rotation); + + memcpy(&saved_mode, &pCrtc->mode, sizeof(DisplayModeRec)); + saved_x = pCrtc->x; + saved_y = pCrtc->y; + saved_rotation = pCrtc->rotation; + + memcpy(&pCrtc->mode, pMode, sizeof(DisplayModeRec)); + pCrtc->x = x; + pCrtc->y = y; + pCrtc->rotation = rotation; + + if (pExynos->fake_root) + exynosDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); + else + exynosDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); + + /* accessibility */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + XDBG_GOTO_IF_FAIL(pCrtcPriv->accessibility_front_bo != NULL, fail); + XDBG_GOTO_IF_FAIL(pCrtcPriv->accessibility_back_bo != NULL, fail); + + old_bo_accessibility[0] = pCrtcPriv->accessibility_front_bo; + old_bo_accessibility[1] = pCrtcPriv->accessibility_back_bo; + + bo_accessibility[0] = + exynosRenderBoCreate(pScrn, pMode->HDisplay, pMode->VDisplay); + bo_accessibility[1] = + exynosRenderBoCreate(pScrn, pMode->HDisplay, pMode->VDisplay); + + pCrtcPriv->accessibility_front_bo = bo_accessibility[0]; + pCrtcPriv->accessibility_back_bo = bo_accessibility[1]; + } + + /* find bo which covers the requested mode of crtc */ + old_bo = pCrtcPriv->front_bo; + bo = exynosFbGetBo(pFb, x, y, pMode->HDisplay, pMode->VDisplay, FALSE); + XDBG_GOTO_IF_FAIL(bo != NULL, fail); + pCrtcPriv->front_bo = bo; + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo temp; + + bo = pCrtcPriv->accessibility_back_bo; + temp = pCrtcPriv->accessibility_front_bo; + pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo; + pCrtcPriv->accessibility_back_bo = temp; + } + + /* turn off the crtc if the same crtc is set already by another display mode + * before the set crtcs + */ + exynosDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_OFF); + + if (!pCrtcPriv->onoff) + exynosCrtcTurn(pCrtc, TRUE, FALSE, FALSE); + + /* for cache control */ + tbm_bo_map(bo, TBM_DEVICE_2D, TBM_OPTION_READ); + tbm_bo_unmap(bo); + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr pOutput = xf86_config->output[i]; + EXYNOSOutputPrivPtr pOutputPriv; + + if (pOutput->crtc != pCrtc) + continue; + + pOutputPriv = pOutput->driver_private; + +#if 1 + memcpy(&pExynosMode->main_lcd_mode, pOutputPriv->mode_output->modes, + sizeof(drmModeModeInfo)); +#endif + + pOutputPriv->dpms_mode = DPMSModeOn; + } + exynosOutputDrmUpdate(pScrn); + if (pScrn->pScreen) + xf86_reload_cursors(pScrn->pScreen); + +#ifdef NO_CRTC_MODE + pExynos->isCrtcOn = exynosCrtcCheckInUseAll(pScrn); +#endif + /* set the default external mode */ + exynosDisplayModeToKmode(pCrtc->scrn, &pExynosMode->ext_connector_mode, + pMode); + + return TRUE; + fail: + XDBG_ERROR(MDOUT, "Fail crtc apply(crtc_id:%d, rotate:%d, %dx%d+%d+%d\n", + exynosCrtcID(pCrtcPriv), rotation, x, y, pCrtc->mode.HDisplay, + pCrtc->mode.VDisplay); + + pCrtcPriv->front_bo = old_bo; + + /* accessibility */ + if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) { + if (bo_accessibility[0]) + exynosRenderBoUnref(bo_accessibility[0]); + if (bo_accessibility[1]) + exynosRenderBoUnref(bo_accessibility[1]); + + pCrtcPriv->accessibility_front_bo = old_bo_accessibility[0]; + pCrtcPriv->accessibility_back_bo = old_bo_accessibility[1]; + } + + if (pExynos->fake_root) + exynosDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, + &saved_mode); + else + exynosDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode); + + memcpy(&pCrtc->mode, &saved_mode, sizeof(DisplayModeRec)); + pCrtc->x = saved_x; + pCrtc->y = saved_y; + pCrtc->rotation = saved_rotation; + + return FALSE; +} + +static void +EXYNOSDummyCrtcGammaSet(xf86CrtcPtr pCrtc, + CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + XDBG_DEBUG(MDOUT, "\n"); +} + +static void +EXYNOSDummyCrtcDestroy(xf86CrtcPtr pCrtc) +{ + XDBG_DEBUG(MDOUT, "\n"); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + if (pCrtcPriv == NULL) { + return; + } + DRI2FrameEventPtr event_ref = NULL, event_next = NULL; + + xorg_list_for_each_entry_safe(event_ref, event_next, + &pCrtcPriv->pending_flips, + crtc_pending_link) { + free(event_ref); + } + + _dummyFlipPixmapDeinit(pCrtc); + +#if 0 + if (pCrtcPriv->pFpsDebug) { + xDbgLogFpsDebugDestroy(pCrtcPriv->pFpsDebug); + pCrtcPriv->pFpsDebug = NULL; + } +#endif + + if (pCrtcPriv->accessibility_front_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_front_bo); + pCrtcPriv->accessibility_front_bo = NULL; + } + + if (pCrtcPriv->accessibility_back_bo) { + exynosRenderBoUnref(pCrtcPriv->accessibility_back_bo); + pCrtcPriv->accessibility_back_bo = NULL; + } + + if (pCrtcPriv->backup_image) { + pixman_image_unref(pCrtcPriv->backup_image); + pCrtcPriv->backup_image = NULL; + } + + if (pCrtcPriv->ovl_vbuf_cursor) { + exynosUtilVideoBufferUnref(pCrtcPriv->ovl_vbuf_cursor); + pCrtcPriv->ovl_vbuf_cursor = NULL; + } + + if (pCrtcPriv->ovl_vbuf_pixmap) { + exynosUtilVideoBufferUnref(pCrtcPriv->ovl_vbuf_pixmap); + pCrtcPriv->ovl_vbuf_pixmap = NULL; + } + + if (pCrtcPriv->ovl_layer) { + exynosLayerUnref(pCrtcPriv->ovl_layer); + pCrtcPriv->ovl_layer = NULL; + } + + if (pCrtcPriv->mode_crtc) + drmModeFreeCrtc(pCrtcPriv->mode_crtc); + + if (pCrtcPriv->front_bo) { + pCrtcPriv->front_bo = NULL; + } + + if (pCrtcPriv->back_bo) { + exynosRenderBoUnref(pCrtcPriv->back_bo); + pCrtcPriv->back_bo = NULL; + } + + if (pCrtcPriv->flip_backpixs.pix_free != NULL) { + free(pCrtcPriv->flip_backpixs.pix_free); + pCrtcPriv->flip_backpixs.pix_free = NULL; + } + + if (pCrtcPriv->flip_backpixs.flip_pixmaps != NULL) { + free(pCrtcPriv->flip_backpixs.flip_pixmaps); + pCrtcPriv->flip_backpixs.flip_pixmaps = NULL; + } + + if (pCrtcPriv->flip_backpixs.flip_draws != NULL) { + free(pCrtcPriv->flip_backpixs.flip_draws); + pCrtcPriv->flip_backpixs.flip_draws = NULL; + } + (pCrtcPriv->pExynosMode->num_dummy_crtc)--; + xorg_list_del(&pCrtcPriv->link); + free(pCrtcPriv); + + pCrtc->driver_private = NULL; +} + +static xf86OutputStatus +EXYNOSDummyOutputDetect(xf86OutputPtr pOutput) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { + return XF86OutputStatusUnknown; + } + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + + if (pExynos == NULL) { + return XF86OutputStatusUnknown; + } + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + + if (pExynosMode == NULL) { + return XF86OutputStatusUnknown; + } +#if 0 + if (pOutput->randr_output && pOutput->randr_output->numUserModes) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pOutput->scrn); + + if (xf86_config->output[xf86_config->num_output - 1] == pOutput) { + EXYNOSPtr pExynos = (EXYNOSPtr) pOutput->scrn->driverPrivate; + + exynosDummyOutputInit(pOutput->scrn, pExynos->pExynosMode, TRUE); + } + } +#endif + EXYNOSOutputPrivPtr pCur = NULL, pNext = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &pExynosMode->outputs, link) { + if (pCur->is_dummy == FALSE && + pCur->mode_output->connection == DRM_MODE_CONNECTED) { + /* TODO: Need to change flag useAsyncSwap not here */ + pExynos->useAsyncSwap = FALSE; + return XF86OutputStatusDisconnected; + } + } + pExynos->useAsyncSwap = TRUE; + return XF86OutputStatusConnected; +} + +static Bool +EXYNOSDummyOutputModeValid(xf86OutputPtr pOutput, DisplayModePtr pModes) +{ + int ret = MODE_OK; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { + ret = MODE_ERROR; + } + else if (pModes->type & M_T_DEFAULT) + ret = MODE_BAD; + XDBG_DEBUG(MDOUT, "ret = %d\n", ret); + return ret; + +} + +static DisplayModePtr +EXYNOSDummyOutputGetModes(xf86OutputPtr pOutput) +{ + XDBG_DEBUG(MDOUT, "\n"); + DisplayModePtr Modes = NULL; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) + return Modes; + + Modes = xf86ModesAdd(Modes, xf86CVTMode(1024, 768, 60, 0, 0)); + Modes = xf86ModesAdd(Modes, xf86CVTMode(720, 1280, 60, 0, 0)); + return Modes; +} + +static void +EXYNOSDummyOutputDestory(xf86OutputPtr pOutput) +{ + XDBG_DEBUG(MDOUT, "\n"); + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) + return; + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + + if (pExynos->resume_timer) { + TimerFree(pExynos->resume_timer); + pExynos->resume_timer = NULL; + } + + if (pOutputPriv->mode_output) { + if (pOutputPriv->mode_output->modes) + free(pOutputPriv->mode_output->modes); + free(pOutputPriv->mode_output); + } + + if (pOutputPriv->mode_encoder) + free(pOutputPriv->mode_encoder); + + (pExynos->pExynosMode->num_dummy_output)--; + xorg_list_del(&pOutputPriv->link); + free(pOutputPriv); + pOutput->driver_private = NULL; +} + +static void +EXYNOSDummyOutputDpms(xf86OutputPtr pOutput, int dpms) +{ + XDBG_DEBUG(MDOUT, "\n"); +} + +static void +EXYNOSDummyOutputCreateResources(xf86OutputPtr pOutput) +{ + XDBG_DEBUG(MDOUT, "\n"); +} + +static Bool +EXYNOSDummyOutputSetProperty(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + XDBG_DEBUG(MDOUT, "\n"); + return TRUE; +} + +static Bool +EXYNOSDummyOutputGetProperty(xf86OutputPtr pOutput, Atom property) +{ + XDBG_DEBUG(MDOUT, "\n"); + return FALSE; +} + +static void +EXYNOSDummyCrtcSetCursorColors(xf86CrtcPtr pCrtc, int bg, int fg) +{ + XDBG_TRACE(MDOUT, "[%p] \n", pCrtc); +} + +static void +EXYNOSDummyCrtcSetCursorPosition(xf86CrtcPtr pCrtc, int x, int y) +{ + XDBG_TRACE(MDOUT, "[%p] \n", pCrtc); + return; +} + +static void +EXYNOSDummyCrtcShowCursor(xf86CrtcPtr pCrtc) +{ + XDBG_TRACE(MDOUT, "[%p] \n", pCrtc); + return; +} + +static void +EXYNOSDummyCrtcHideCursor(xf86CrtcPtr pCrtc) +{ + XDBG_TRACE(MDOUT, "[%p] \n", pCrtc); + return; +} + +static void +EXYNOSDummyCrtcLoadCursorArgb(xf86CrtcPtr pCrtc, CARD32 *image) +{ + XDBG_TRACE(MDOUT, "[%p] \n", pCrtc); + return; +} + +static const xf86CrtcFuncsRec exynos_crtc_dummy_funcs = { + .dpms = EXYNOSDummyCrtcDpms, + .set_mode_major = EXYNOSDummyCrtcSetModeMajor, + .set_cursor_colors = EXYNOSDummyCrtcSetCursorColors, + .set_cursor_position = EXYNOSDummyCrtcSetCursorPosition, + .show_cursor = EXYNOSDummyCrtcShowCursor, + .hide_cursor = EXYNOSDummyCrtcHideCursor, + .load_cursor_argb = EXYNOSDummyCrtcLoadCursorArgb, +#if 0 + .shadow_create = EXYNOSCrtcShadowCreate, + .shadow_allocate = EXYNOSCrtcShadowAllocate, + .shadow_destroy = EXYNOSCrtcShadowDestroy, +#endif + .gamma_set = EXYNOSDummyCrtcGammaSet, + .destroy = EXYNOSDummyCrtcDestroy, +}; + +static const xf86OutputFuncsRec exynos_output_dummy_funcs = { + .create_resources = EXYNOSDummyOutputCreateResources, +#ifdef RANDR_12_INTERFACE + .set_property = EXYNOSDummyOutputSetProperty, + .get_property = EXYNOSDummyOutputGetProperty, +#endif + .dpms = EXYNOSDummyOutputDpms, +#if 0 + .save = drmmode_crt_save, + .restore = drmmode_crt_restore, + .mode_fixup = drmmode_crt_mode_fixup, + .prepare = exynos_output_prepare, + .mode_set = drmmode_crt_mode_set, + .commit = exynos_output_commit, +#endif + .detect = EXYNOSDummyOutputDetect, + .mode_valid = EXYNOSDummyOutputModeValid, + + .get_modes = EXYNOSDummyOutputGetModes, + .destroy = EXYNOSDummyOutputDestory +}; + +Bool +exynosDummyOutputInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, Bool late) +{ + XDBG_DEBUG(MDOUT, "\n"); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr pOutput; + xf86CrtcPtr pCrtc; + EXYNOSOutputPrivPtr pOutputPriv; + RROutputPtr clones[32]; + RRCrtcPtr crtcs[32]; + DisplayModePtr pModes = NULL; + char buf[80]; + int i, len; + + if (pExynosMode->num_dummy_output >= 32) + return FALSE; + + XDBG_DEBUG(MDISP, "(late=%d, num_dummy=%d)\n", late, + pExynosMode->num_dummy_output + 1); + + len = + snprintf(buf, sizeof(buf), "DUMMY%d", + pExynosMode->num_dummy_output + 1); + pOutput = xf86OutputCreate(pScrn, &exynos_output_dummy_funcs, buf); + if (!pOutput) { + return FALSE; + } + + pCrtc = exynosDummyCrtcInit(pScrn, pExynosMode); + + if (pCrtc == NULL) { + xf86OutputDestroy(pOutput); + return FALSE; + } + + pOutputPriv = calloc(sizeof(EXYNOSOutputPrivRec), 1); + if (!pOutputPriv) { + xf86OutputDestroy(pOutput); + xf86CrtcDestroy(pCrtc); + return FALSE; + } + + pOutput->mm_width = 0; + pOutput->mm_height = 0; + pOutput->interlaceAllowed = FALSE; + pOutput->subpixel_order = SubPixelNone; + + pOutput->possible_crtcs = ~((1 << pExynosMode->num_real_crtc) - 1); + pOutput->possible_clones = ~((1 << pExynosMode->num_real_output) - 1); + pOutputPriv->is_dummy = TRUE; + pOutputPriv->output_id = 1000 + pExynosMode->num_dummy_output; + + pOutputPriv->mode_output = calloc(1, sizeof(drmModeConnector)); + if (pOutputPriv->mode_output == NULL) { + free(pOutputPriv); + goto err; + } + pOutputPriv->mode_output->connector_type = DRM_MODE_CONNECTOR_Unknown; + pOutputPriv->mode_output->connector_type_id = + pExynosMode->num_dummy_output + 1; + pOutputPriv->mode_output->connector_id = + 1000 + pExynosMode->num_dummy_output; + pOutputPriv->mode_output->connection = DRM_MODE_UNKNOWNCONNECTION; + pOutputPriv->mode_output->count_props = 0; + pOutputPriv->mode_output->count_encoders = 0; + pOutputPriv->mode_encoder = NULL; + pOutputPriv->mode_output->count_modes = 1; + pOutputPriv->mode_output->modes = calloc(2, sizeof(drmModeModeInfo)); + if (pOutputPriv->mode_output->modes == NULL) { + free(pOutputPriv->mode_output); + free(pOutputPriv); + goto err; + } +#if 0 + pOutputPriv->mode_encoder = calloc(1, sizeof(drmModeEncoder)); + if (pOutputPriv->mode_encoder == NULL) + goto err; + pOutputPriv->mode_encoder->possible_clones = + ~((1 << pExynosMode->num_real_output) - 1); + pOutputPriv->mode_encoder->possible_crtcs = + ~((1 << pExynosMode->num_real_crtc) - 1); + pOutputPriv->mode_encoder->encoder_type = DRM_MODE_ENCODER_NONE; +#endif + pModes = xf86CVTMode(1024, 768, 60, 0, 0); + exynosDisplayModeToKmode(pScrn, &pOutputPriv->mode_output->modes[0], + pModes); + free(pModes); + pOutputPriv->pExynosMode = pExynosMode; + + pOutput->driver_private = pOutputPriv; + pOutputPriv->pOutput = pOutput; + /* TODO : soolim : management crtc privates */ + xorg_list_add(&pOutputPriv->link, &pExynosMode->outputs); + + if (late) { + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + + pCrtc->randr_crtc = RRCrtcCreate(pScreen, pCrtc); + pOutput->randr_output = RROutputCreate(pScreen, buf, len, pOutput); + if (pCrtc->randr_crtc == NULL || pOutput->randr_output == NULL) { + xf86OutputDestroy(pOutput); + xf86CrtcDestroy(pCrtc); + return FALSE; + } + + RRPostPendingProperties(pOutput->randr_output); + + for (i = pExynosMode->num_real_output; i < xf86_config->num_output; i++) + clones[i - pExynosMode->num_real_output] = + xf86_config->output[i]->randr_output; + XDBG_RETURN_VAL_IF_FAIL(i - pExynosMode->num_real_output == + pExynosMode->num_dummy_output + 1, FALSE); + + for (i = pExynosMode->num_real_crtc; i < xf86_config->num_crtc; i++) + crtcs[i - pExynosMode->num_real_crtc] = + xf86_config->crtc[i]->randr_crtc; + XDBG_RETURN_VAL_IF_FAIL(i - pExynosMode->num_real_crtc == + pExynosMode->num_dummy_output + 1, FALSE); + + for (i = pExynosMode->num_real_output; i < xf86_config->num_output; i++) { + RROutputPtr rr_output = xf86_config->output[i]->randr_output; + + if (!RROutputSetCrtcs + (rr_output, crtcs, pExynosMode->num_dummy_output + 1) || + !RROutputSetClones(rr_output, clones, + pExynosMode->num_dummy_output + 1)) + goto err; + } + + RRCrtcSetRotations(pCrtc->randr_crtc, RR_Rotate_All | RR_Reflect_All); + } + pExynosMode->num_dummy_output++; + return TRUE; + + err: + for (i = 0; i < xf86_config->num_output; i++) { + pOutput = xf86_config->output[i]; + if (pOutput->driver_private == NULL) + continue; + pOutputPriv = (EXYNOSOutputPrivPtr) pOutput->driver_private; + if (pOutputPriv->is_dummy) { + xf86OutputDestroy(pOutput); + } + } + + for (i = 0; i < xf86_config->num_crtc; i++) { + pCrtc = xf86_config->crtc[i]; + + if (pCrtc->driver_private == NULL) + continue; + EXYNOSCrtcPrivPtr pCrtcPriv = (EXYNOSCrtcPrivPtr) pCrtc->driver_private; + + if (pCrtcPriv->is_dummy) { + xf86CrtcDestroy(pCrtc); + } + } + pExynosMode->num_dummy_output = 0; + return FALSE; +} + +xf86CrtcPtr +exynosDummyCrtcInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode) +{ + XDBG_DEBUG(MDOUT, "\n"); + xf86CrtcPtr pCrtc = NULL; + +// DisplayModePtr pModes = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv; + + pCrtcPriv = calloc(sizeof(EXYNOSCrtcPrivRec), 1); + if (pCrtcPriv == NULL) + return NULL; + + pCrtc = xf86CrtcCreate(pScrn, &exynos_crtc_dummy_funcs); + if (pCrtc == NULL) { + free(pCrtcPriv); + return NULL; + } + pCrtcPriv->is_dummy = TRUE; + pCrtcPriv->idx = 1000 + pExynosMode->num_dummy_crtc; + pCrtcPriv->mode_crtc = calloc(1, sizeof(drmModeCrtc)); + if (!pCrtcPriv->mode_crtc) { + free(pCrtcPriv); + return NULL; + } +#if 0 + pModes = xf86CVTMode(720, 1280, 60, 0, 0); + exynosDisplayModeToKmode(pScrn, &pCrtcPriv->kmode, pModes); + exynosDisplayModeToKmode(pScrn, &pCrtcPriv->mode_crtc->mode, pModes); + free(pModes); +#endif + /* TODO: Unique crtc_id */ + pCrtcPriv->mode_crtc->crtc_id = 1000 + pExynosMode->num_dummy_crtc; + + pCrtcPriv->move_layer = FALSE; + pCrtcPriv->user_rotate = RR_Rotate_0; + + pCrtcPriv->pExynosMode = pExynosMode; + pCrtc->driver_private = pCrtcPriv; + + pCrtcPriv->pipe = 1000 + pExynosMode->num_dummy_crtc; + pCrtcPriv->onoff = TRUE; + + xorg_list_init(&pCrtcPriv->pending_flips); + + pCrtcPriv->pCrtc = pCrtc; + +#ifdef USE_XDBG + pCrtcPriv->pFpsDebug = xDbgLogFpsDebugCreate(); + if (pCrtcPriv->pFpsDebug == NULL) { + free(pCrtcPriv); + return NULL; + } +#endif + + _dummyFlipPixmapInit(pCrtc); + pExynosMode->num_dummy_crtc++; + xorg_list_add(&(pCrtcPriv->link), &(pExynosMode->crtcs)); + return pCrtc; +} +#endif //NO_CRTC_MODE diff --git a/src/crtcconfig/exynos_dummy.h b/src/crtcconfig/exynos_dummy.h new file mode 100644 index 0000000..3aff88e --- /dev/null +++ b/src/crtcconfig/exynos_dummy.h @@ -0,0 +1,17 @@ +#ifndef EXYNOS_DUMMY_H +#define EXYNOS_DUMMY_H + +#include "exynos.h" + +#ifndef RR_Rotate_All +#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) +#endif //RR_Rotate_All +#ifndef RR_Reflect_All +#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y) +#endif //RR_Reflect_All +#ifdef NO_CRTC_MODE +Bool exynosDummyOutputInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, + Bool late); +xf86CrtcPtr exynosDummyCrtcInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode); +#endif +#endif // EXYNOS_DUMMY_H diff --git a/src/crtcconfig/exynos_layer.c b/src/crtcconfig/exynos_layer.c new file mode 100644 index 0000000..304160a --- /dev/null +++ b/src/crtcconfig/exynos_layer.c @@ -0,0 +1,1635 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_plane.h" +#include "exynos_layer.h" +#include "exynos_video_fourcc.h" +#include "exynos_video_tvout.h" +#include "exynos_video_virtual.h" +#include "exynos_layer_manager.h" +#include <exynos/exynos_drm.h> + +//#define DEBUG_REFCNT + +#ifdef DEBUG_REFCNT +#define EXYNOS_LAYER_PRINT_REFCNT(b) \ + XDBG_TRACE(MLYR, "layer(%p) ref_cnt(%d) \n", b, b->ref_cnt) +#else +#define EXYNOS_LAYER_PRINT_REFCNT(b) +#endif + +typedef struct _NotifyFuncData { + NotifyFunc func; + void *user_data; + + struct xorg_list link; +} NotifyFuncData; + +struct _EXYNOSLayer { + ScrnInfoPtr pScrn; + + EXYNOSLayerOutput output; + EXYNOSLayerPos lpos; + + int plane_id; + int crtc_id; + + /* for buffer */ + intptr_t fb_id; + + int offset_x; + int offset_y; + + xRectangle *src; + xRectangle *dst; + + EXYNOSVideoBuf *vbuf; + Bool visible; + Bool need_update; + + /* vblank */ + Bool enable_vblank; + Bool wait_vblank; + EXYNOSVideoBuf *wait_vbuf; + EXYNOSVideoBuf *pending_vbuf; + EXYNOSVideoBuf *showing_vbuf; + + struct xorg_list noti_data; + struct xorg_list link; + + Bool onoff; + int ref_cnt; + Bool freeze_update; + + /* count */ + unsigned int put_counts; + OsTimerPtr timer; + + /* for hwc */ + /* drawable id associated with this overlay */ + unsigned int xid; + DrawablePtr pDraw; + Bool default_layer; + /* when a layer is updated by DRI2(and maybe Present) we should forbid update layer (frame buffer) by HWC, + * HWC have to updata only SRC, DST and zpos. + * */ + Bool is_updated_dri; + +}; + +static Bool crtc_layers_init; +static struct xorg_list crtc_layers; +static Bool wait_vblank[LAYER_OUTPUT_MAX]; + +#define LAYER_VBLANK_FLAG 0xFFFF + +static CARD32 +_countPrint(OsTimerPtr timer, CARD32 now, pointer arg) +{ + EXYNOSLayer *layer = (EXYNOSLayer *) arg; + + if (layer->timer) { + TimerFree(layer->timer); + layer->timer = NULL; + } + + XDBG_DEBUG(MEXA, "crtc(%d) pos(%d) : %d fps. \n", + layer->crtc_id, layer->lpos, layer->put_counts); + + layer->put_counts = 0; + + return 0; +} + +static void +_countFps(EXYNOSLayer * layer) +{ + layer->put_counts++; + + if (layer->timer) + return; + + layer->timer = TimerSet(NULL, 0, 1000, _countPrint, layer); +} + +static void +_exynosLayerInitList(void) +{ + if (!crtc_layers_init) { + xorg_list_init(&crtc_layers); + crtc_layers_init = TRUE; + } +} + +static void +_exynosLayerNotify(EXYNOSLayer * layer, int type, void *type_data) +{ + NotifyFuncData *data = NULL, *data_next = NULL; + + xorg_list_for_each_entry_safe(data, data_next, &layer->noti_data, link) { + if (data->func) + data->func(layer, type, type_data, data->user_data); + } +} + +static int +_GetCrtcIdForOutput(ScrnInfoPtr pScrn, EXYNOSLayerOutput output) +{ + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSOutputPrivPtr pOutputPriv = NULL; + int crtc_id = 0; + + switch (output) { + case LAYER_OUTPUT_LCD: + pOutputPriv = + exynosOutputGetPrivateForConnType(pScrn, DRM_MODE_CONNECTOR_LVDS); + if (!pOutputPriv) + pOutputPriv = + exynosOutputGetPrivateForConnType(pScrn, + DRM_MODE_CONNECTOR_Unknown); + if (pOutputPriv && pOutputPriv->mode_encoder) + crtc_id = pOutputPriv->mode_encoder->crtc_id; + break; + case LAYER_OUTPUT_EXT: + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_HDMI) { + pOutputPriv = + exynosOutputGetPrivateForConnType(pScrn, + DRM_MODE_CONNECTOR_HDMIA); + if (!pOutputPriv) + pOutputPriv = + exynosOutputGetPrivateForConnType(pScrn, + DRM_MODE_CONNECTOR_HDMIB); + if (pOutputPriv && pOutputPriv->mode_encoder) + crtc_id = pOutputPriv->mode_encoder->crtc_id; + } + else if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + pOutputPriv = + exynosOutputGetPrivateForConnType(pScrn, + DRM_MODE_CONNECTOR_VIRTUAL); + if (pOutputPriv && pOutputPriv->mode_encoder) + crtc_id = pOutputPriv->mode_encoder->crtc_id; + } + break; + default: + break; + } + + XDBG_DEBUG(MLYR, "crtc(%d) for output(%d) \n", crtc_id, output); + + if (crtc_id == 0) + XDBG_ERROR(MLYR, "no crtc for output(%d) \n", output); + + return crtc_id; +} + +static int +_GetCrtcID(EXYNOSLayer * layer) +{ + if (layer->crtc_id > 0) + return layer->crtc_id; + + layer->crtc_id = _GetCrtcIdForOutput(layer->pScrn, layer->output); + + XDBG_RETURN_VAL_IF_FAIL(layer->crtc_id > 0, 0); + + return layer->crtc_id; +} + +static int +_exynosLayerGetPlanePos(EXYNOSLayer * layer, EXYNOSLayerPos lpos) +{ + if (layer->output == LAYER_OUTPUT_LCD) { + XDBG_DEBUG(MLYR, "lpos(%d) => ppos(%d) (1)\n", lpos, + PLANE_POS_3 + lpos); + return PLANE_POS_3 + lpos; + } + else if (layer->output == LAYER_OUTPUT_EXT) { + if (lpos == -1) { + XDBG_DEBUG(MLYR, "lpos(%d) => ppos(%d) (2)\n", lpos, PLANE_POS_2); + return PLANE_POS_2; + } + else { + XDBG_DEBUG(MLYR, "lpos(%d) => ppos(%d) (3)\n", lpos, + PLANE_POS_0 + lpos); + return PLANE_POS_0 + lpos; + } + } + else { + XDBG_NEVER_GET_HERE(MLYR); + } + + return -1; +} + +static void +_exynosLayerDestroy(EXYNOSLayer * layer) +{ + NotifyFuncData *data = NULL, *data_next = NULL; + + XDBG_RETURN_IF_FAIL(layer != NULL); + xorg_list_del(&layer->link); + + if (layer->src) + free(layer->src); + if (layer->dst) + free(layer->dst); + + if (layer->wait_vbuf) { + if (layer->wait_vbuf->vblank_handler) { + layer->wait_vbuf->vblank_handler(0, 0, 0, + layer->wait_vbuf->vblank_user_data, + TRUE); + layer->wait_vbuf->vblank_handler = NULL; + layer->wait_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->wait_vbuf); + } + if (layer->pending_vbuf) { + if (layer->pending_vbuf->vblank_handler) { + layer->pending_vbuf->vblank_handler(0, 0, 0, + layer->pending_vbuf-> + vblank_user_data, TRUE); + layer->pending_vbuf->vblank_handler = NULL; + layer->pending_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->pending_vbuf); + } + if (layer->showing_vbuf) { + if (layer->showing_vbuf->vblank_handler) { + layer->showing_vbuf->vblank_handler(0, 0, 0, + layer->showing_vbuf-> + vblank_user_data, TRUE); + layer->showing_vbuf->vblank_handler = NULL; + layer->showing_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->showing_vbuf); + } + if (layer->vbuf) { + if (layer->vbuf->vblank_handler) { + layer->vbuf->vblank_handler(0, 0, 0, layer->vbuf->vblank_user_data, + TRUE); + layer->vbuf->vblank_handler = NULL; + layer->vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->vbuf); + layer->vbuf = NULL; + } + + XDBG_TRACE(MLYR, "layer(%p) destroyed. \n", layer); + EXYNOS_LAYER_PRINT_REFCNT(layer); + + _exynosLayerNotify(layer, LAYER_DESTROYED, NULL); + + xorg_list_for_each_entry_safe(data, data_next, &layer->noti_data, link) { + xorg_list_del(&data->link); + free(data); + } + + if (layer->plane_id > 0) + exynosPlaneFreeId(layer->plane_id); + + free(layer); +} + +void +exynosLayerDestroy(EXYNOSLayer * layer) +{ + _exynosLayerDestroy(layer); +} + +static void +_exynosLayerWatchVblank(EXYNOSLayer * layer) +{ + CARD64 ust, msc, target_msc; + intptr_t pipe, flip = 1; + EXYNOSPtr pExynos = EXYNOSPTR(layer->pScrn); + + /* if lcd is off, do not request vblank information */ +#ifdef NO_CRTC_MODE + if (pExynos->isCrtcOn == FALSE) + return; + else +#endif //NO_CRTC_MODE +// if (pExynos->isLcdOff) +// { +// XDBG_DEBUG(MLYR, "pExynos->isLcdOff (%d)\n", pExynos->isLcdOff); +// return; +// } + + pipe = exynosDisplayCrtcPipe(layer->pScrn, _GetCrtcID(layer)); + + layer->wait_vblank = TRUE; + + if (wait_vblank[pipe]) + return; + + wait_vblank[pipe] = TRUE; + + if (!exynosDisplayGetCurMSC(layer->pScrn, pipe, &ust, &msc)) + XDBG_WARNING(MLYR, "fail to get current_msc.\n"); + + target_msc = msc + 1; + + XDBG_TRACE(MLYR, "layer(%p) wait vblank : cur(%lld) target(%lld). \n", + layer, msc, target_msc); + + if (!exynosDisplayVBlank + (layer->pScrn, pipe, &target_msc, flip, VBLANK_INFO_PLANE, + (void *) pipe)) + XDBG_WARNING(MLYR, "fail to Vblank.\n"); +} + +static Bool +_exynosLayerShowInternal(EXYNOSLayer * layer, Bool need_update) +{ + int crtc_id, plane_pos; + + XDBG_RETURN_VAL_IF_FAIL(layer->fb_id > 0, FALSE); + + crtc_id = _GetCrtcID(layer); + plane_pos = _exynosLayerGetPlanePos(layer, layer->lpos); + + if (!exynosPlaneShow(layer->plane_id, crtc_id, + layer->src->x, layer->src->y, + layer->src->width, layer->src->height, + layer->offset_x + layer->dst->x, + layer->offset_y + layer->dst->y, + layer->dst->width, layer->dst->height, + plane_pos, need_update)) + return FALSE; + layer->need_update = FALSE; + + return TRUE; +} + +static void +_exynosLayerGetBufferID(EXYNOSLayer * layer, EXYNOSVideoBuf * vbuf) +{ + EXYNOSModePtr pExynosMode; + unsigned int drmfmt; + unsigned int handles[4] = { 0, }; + unsigned int pitches[4] = { 0, }; + unsigned int offsets[4] = { 0, }; + int i; + + if (vbuf->fb_id > 0) + return; + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + drmfmt = exynosUtilGetDrmFormat(vbuf->id); + + for (i = 0; i < PLANAR_CNT; i++) { + handles[i] = (unsigned int) vbuf->handles[i]; + pitches[i] = (unsigned int) vbuf->pitches[i]; + offsets[i] = (unsigned int) vbuf->offsets[i]; + } + + if (drmModeAddFB2(pExynosMode->fd, vbuf->width, vbuf->height, drmfmt, + handles, pitches, offsets, (uint32_t *) & vbuf->fb_id, 0)) + { + XDBG_ERRNO(MLYR, + "drmModeAddFB2 failed. handles(%d %d %d) pitches(%d %d %d) offsets(%d %d %d) '%c%c%c%c'\n", + handles[0], handles[1], handles[2], pitches[0], pitches[1], + pitches[2], offsets[0], offsets[1], offsets[2], + FOURCC_STR(drmfmt)); + } + + XDBG_DEBUG(MVBUF, + "layer(%p) vbuf(%" PRIuPTR ") fb_id(%" PRIdPTR ") added. \n", + layer, vbuf->stamp, vbuf->fb_id); +} + +Bool +exynosLayerSupport(ScrnInfoPtr pScrn, EXYNOSLayerOutput output, + EXYNOSLayerPos lpos, unsigned int id) +{ + EXYNOSModePtr pExynosMode; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(output < LAYER_OUTPUT_MAX, FALSE); + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + + if (output == LAYER_OUTPUT_EXT && lpos == LAYER_LOWER1) { + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_HDMI) { + if (id == FOURCC_SN12 || id == FOURCC_ST12) + return TRUE; + else + return FALSE; + } + else if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + if (id == FOURCC_SN12 || id == FOURCC_RGB32) + return TRUE; + else + return FALSE; + } + } + + return (id == FOURCC_RGB32 || id == FOURCC_SR32) ? TRUE : FALSE; +} + +EXYNOSLayer * +exynosLayerFind(EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ + EXYNOSLayer *layer = NULL, *layer_next = NULL; + + XDBG_RETURN_VAL_IF_FAIL(output < LAYER_OUTPUT_MAX, NULL); + + _exynosLayerInitList(); + + xorg_list_for_each_entry_safe(layer, layer_next, &crtc_layers, link) { + if (layer->output == output && layer->lpos == lpos) + return layer; + } + + return NULL; +} + +EXYNOSLayer * +exynosLayerFindByDraw(DrawablePtr pDraw) +{ + EXYNOSLayer *layer = NULL, *layer_next = NULL; + + XDBG_RETURN_VAL_IF_FAIL(pDraw != NULL, NULL); + + _exynosLayerInitList(); + + xorg_list_for_each_entry_safe(layer, layer_next, &crtc_layers, link) { + if (layer->pDraw == pDraw) + return layer; + } + + return NULL; +} + +void +exynosLayerDestroyAll(void) +{ + EXYNOSLayer *layer = NULL, *layer_next = NULL; + + _exynosLayerInitList(); + + xorg_list_for_each_entry_safe(layer, layer_next, &crtc_layers, link) { + _exynosLayerDestroy(layer); + } +} + +void +exynosLayerShowAll(ScrnInfoPtr pScrn, EXYNOSLayerOutput output) +{ + int crtc_id = _GetCrtcIdForOutput(pScrn, output); + + exynosPlaneShowAll(crtc_id); +} + +EXYNOSLayer * +exynosLayerCreate(ScrnInfoPtr pScrn, EXYNOSLayerOutput output, + EXYNOSLayerPos lpos) +{ + EXYNOSLayer *layer; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(output < LAYER_OUTPUT_MAX, NULL); +/* Temporary solution */ +#ifdef LAYER_MANAGER + if (lpos != FOR_LAYER_MNG) { + XDBG_WARNING(MLYR, + "Layer manager is enable, avoid direct create layers\n"); + return ((EXYNOSLayer *) + exynosLayerMngTempGetHWLayer(pScrn, output, lpos)); + } +#endif + +#if defined (HAVE_HWC_H) && !defined(LAYER_MANAGER) + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (!pExynos->use_hwc) + + XDBG_RETURN_VAL_IF_FAIL(lpos != LAYER_DEFAULT, NULL); +#endif +#ifndef LAYER_MANAGER + layer = exynosLayerFind(output, lpos); + if (layer) { + XDBG_ERROR(MLYR, "layer(%p) already is at output(%d) lpos(%d). \n", + layer, output, lpos); + + return NULL; + } +#endif + layer = calloc(sizeof(EXYNOSLayer), 1); + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + + layer->pScrn = pScrn; + layer->output = output; + layer->lpos = lpos; + + layer->plane_id = exynosPlaneGetID(); + if (layer->plane_id < 0) { + free(layer); + return NULL; + } + + layer->ref_cnt = 1; + xorg_list_init(&layer->noti_data); + + _exynosLayerInitList(); + + xorg_list_add(&layer->link, &crtc_layers); + + XDBG_TRACE(MLYR, "layer(%p) output(%d) lpos(%d) created. \n", layer, output, + lpos); + EXYNOS_LAYER_PRINT_REFCNT(layer); + + return layer; +} + +EXYNOSLayer * +exynosLayerRef(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + + layer->ref_cnt++; + + EXYNOS_LAYER_PRINT_REFCNT(layer); + + return layer; +} + +void +exynosLayerUnref(EXYNOSLayer * layer) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + layer->ref_cnt--; + + EXYNOS_LAYER_PRINT_REFCNT(layer); + + if (layer->ref_cnt == 0) { + exynosLayerHide(layer); +#ifdef LAYER_MANAGER + if (exynosLayerMngTempDestroyHWLayer(layer)) { + return; + } +#else + _exynosLayerDestroy(layer); +#endif + } +} + +void +exynosLayerAddNotifyFunc(EXYNOSLayer * layer, NotifyFunc func, void *user_data) +{ + NotifyFuncData *data = NULL, *data_next = NULL; + + XDBG_RETURN_IF_FAIL(layer != NULL); + XDBG_RETURN_IF_FAIL(func != NULL); + + xorg_list_for_each_entry_safe(data, data_next, &layer->noti_data, link) { + if (data->func == func && data->user_data == user_data) + return; + } + + data = calloc(sizeof(NotifyFuncData), 1); + XDBG_RETURN_IF_FAIL(data != NULL); + + data->func = func; + data->user_data = user_data; + + xorg_list_add(&data->link, &layer->noti_data); +} + +void +exynosLayerRemoveNotifyFunc(EXYNOSLayer * layer, NotifyFunc func) +{ + NotifyFuncData *data = NULL, *data_next = NULL; + + XDBG_RETURN_IF_FAIL(layer != NULL); + XDBG_RETURN_IF_FAIL(func != NULL); + + xorg_list_for_each_entry_safe(data, data_next, &layer->noti_data, link) { + if (data->func == func) { + xorg_list_del(&data->link); + free(data); + } + } +} + +Bool +exynosLayerExistNotifyFunc(EXYNOSLayer * layer, NotifyFunc func) +{ + NotifyFuncData *data = NULL, *data_next = NULL; + + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(func != NULL, FALSE); + + xorg_list_for_each_entry_safe(data, data_next, &layer->noti_data, link) { + if (data->func == func) { + return TRUE; + } + } + return FALSE; +} + +Bool +exynosLayerIsVisible(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + + return layer->visible; +} + +void +exynosLayerShow(EXYNOSLayer * layer) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + XDBG_RETURN_IF_FAIL(layer->src != NULL); + XDBG_RETURN_IF_FAIL(layer->dst != NULL); + XDBG_RETURN_IF_FAIL(layer->fb_id > 0); + if (!layer->src || !layer->dst) { + EXYNOSVideoBuf *grab_vbuf = NULL; + + if (layer->vbuf) + grab_vbuf = layer->vbuf; + else if (layer->showing_vbuf) + grab_vbuf = layer->showing_vbuf; + else if (layer->wait_vbuf) + grab_vbuf = layer->wait_vbuf; + else if (layer->pending_vbuf) + grab_vbuf = layer->pending_vbuf; + else + return; + { + xRectangle src = {.x = 0,.y = 0,.width = grab_vbuf->width,.height = + grab_vbuf->height + }; + xRectangle dst = {.x = 0,.y = 0,.width = grab_vbuf->width,.height = + grab_vbuf->height + }; + exynosLayerSetRect(layer, &src, &dst); + } + } + +#ifndef HWC_ENABLE_REDRAW_LAYER + if (layer->visible) + return; +#endif + +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + layer->visible = TRUE; + XDBG_TRACE(MLYR, "layer(%p) shown. \n", layer); + return; + } +#endif +#ifndef HWC_ENABLE_REDRAW_LAYER + if (!_exynosLayerShowInternal(layer, FALSE)) + return; +#else + if (!_exynosLayerShowInternal(layer, TRUE)) + return; +#endif + + if (layer->enable_vblank) + _exynosLayerWatchVblank(layer); + + layer->visible = TRUE; + + XDBG_TRACE(MLYR, "layer(%p) shown. \n", layer); + + _exynosLayerNotify(layer, LAYER_SHOWN, (void *) layer->fb_id); +} + +void +exynosLayerClearQueue(EXYNOSLayer * layer) +{ + +#if 1 + if (layer->wait_vbuf && VBUF_IS_VALID(layer->wait_vbuf)) { + XDBG_DEBUG(MVBUF, "layer(%p) <-- %s (%" PRIuPTR ",%d,%d) \n", layer, + (layer->output == LAYER_OUTPUT_LCD) ? "LCD" : "TV", + layer->wait_vbuf->stamp, + VBUF_IS_CONVERTING(layer->wait_vbuf), + layer->wait_vbuf->showing); + layer->wait_vbuf->showing = FALSE; + if (layer->wait_vbuf->vblank_handler) { + layer->wait_vbuf->vblank_handler(0, 0, 0, + layer->wait_vbuf->vblank_user_data, + TRUE); + layer->wait_vbuf->vblank_handler = NULL; + layer->wait_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->wait_vbuf); + } + + if (layer->pending_vbuf && VBUF_IS_VALID(layer->pending_vbuf)) { + layer->pending_vbuf->showing = FALSE; + if (layer->pending_vbuf->vblank_handler) { + layer->pending_vbuf->vblank_handler(0, 0, 0, + layer->pending_vbuf-> + vblank_user_data, TRUE); + layer->pending_vbuf->vblank_handler = NULL; + layer->pending_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->pending_vbuf); + } +/* + if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf)) + { + layer->showing_vbuf->showing = FALSE; + XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%"PRIuPTR",%d,%d) \n", layer, + (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV", + layer->showing_vbuf->stamp, VBUF_IS_CONVERTING (layer->showing_vbuf), + layer->showing_vbuf->showing); + if (layer->showing_vbuf->vblank_handler) + { + layer->showing_vbuf->vblank_handler(0, 0, 0, layer->showing_vbuf->vblank_user_data, TRUE); + layer->showing_vbuf->vblank_handler = NULL; + layer->showing_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref (layer->showing_vbuf); + } +*/ + if (layer->showing_vbuf && VBUF_IS_VALID(layer->showing_vbuf)) { +// layer->showing_vbuf->showing = FALSE; + if (layer->showing_vbuf->vblank_handler) { + layer->showing_vbuf->vblank_handler(0, 0, 0, + layer->showing_vbuf-> + vblank_user_data, TRUE); + layer->showing_vbuf->vblank_handler = NULL; + layer->showing_vbuf->vblank_user_data = NULL; + } +// exynosUtilVideoBufferUnref (layer->showing_vbuf); + } + + if (layer->vbuf) { + if (layer->vbuf->vblank_handler) { + layer->vbuf->vblank_handler(0, 0, 0, layer->vbuf->vblank_user_data, + TRUE); + layer->vbuf->vblank_handler = NULL; + layer->vbuf->vblank_user_data = NULL; + } + } + + layer->wait_vbuf = NULL; + layer->pending_vbuf = NULL; +// layer->showing_vbuf = NULL; +#endif + if (layer->plane_id > 0) + exynosPlaneFlushFBId(layer->plane_id); + + XDBG_TRACE(MLYR, "layer(%p) flush. \n", layer); + +} + +void +exynosLayerHide(EXYNOSLayer * layer) +{ + + XDBG_RETURN_IF_FAIL(layer != NULL); + + if (!layer->visible || layer->ref_cnt > 1) + return; +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + layer->visible = FALSE; + XDBG_TRACE(MLYR, "layer(%p) hidden. \n", layer); + return; + } +#endif + if (!exynosPlaneHide(layer->plane_id)) + return; + + if (layer->wait_vbuf && VBUF_IS_VALID(layer->wait_vbuf)) { + layer->wait_vbuf->showing = FALSE; + XDBG_DEBUG(MVBUF, "layer(%p) <-- %s (%" PRIuPTR ",%d,%d) \n", layer, + (layer->output == LAYER_OUTPUT_LCD) ? "LCD" : "TV", + layer->wait_vbuf->stamp, + VBUF_IS_CONVERTING(layer->wait_vbuf), + layer->wait_vbuf->showing); + if (layer->wait_vbuf->vblank_handler) { + layer->wait_vbuf->vblank_handler(0, 0, 0, + layer->wait_vbuf->vblank_user_data, + TRUE); + layer->wait_vbuf->vblank_handler = NULL; + layer->wait_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->wait_vbuf); + } + + if (layer->pending_vbuf && VBUF_IS_VALID(layer->pending_vbuf)) { + layer->pending_vbuf->showing = FALSE; + if (layer->pending_vbuf->vblank_handler) { + layer->pending_vbuf->vblank_handler(0, 0, 0, + layer->pending_vbuf-> + vblank_user_data, TRUE); + layer->pending_vbuf->vblank_handler = NULL; + layer->pending_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->pending_vbuf); + } + + if (layer->showing_vbuf && VBUF_IS_VALID(layer->showing_vbuf)) { + layer->showing_vbuf->showing = FALSE; + XDBG_DEBUG(MVBUF, "layer(%p) <-- %s (%" PRIuPTR ",%d,%d) \n", layer, + (layer->output == LAYER_OUTPUT_LCD) ? "LCD" : "TV", + layer->showing_vbuf->stamp, + VBUF_IS_CONVERTING(layer->showing_vbuf), + layer->showing_vbuf->showing); + if (layer->showing_vbuf->vblank_handler) { + layer->showing_vbuf->vblank_handler(0, 0, 0, + layer->showing_vbuf-> + vblank_user_data, TRUE); + layer->showing_vbuf->vblank_handler = NULL; + layer->showing_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->showing_vbuf); + } + + layer->showing_vbuf = NULL; + layer->pending_vbuf = NULL; + layer->wait_vbuf = NULL; + layer->wait_vblank = FALSE; + layer->visible = FALSE; + layer->crtc_id = 0; + + XDBG_TRACE(MLYR, "layer(%p) hidden. \n", layer); + + _exynosLayerNotify(layer, LAYER_HIDDEN, (void *) layer->fb_id); +} + +void +exynosLayerFreezeUpdate(EXYNOSLayer * layer, Bool enable) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + layer->freeze_update = enable; + + XDBG_TRACE(MLYR, "layer(%p) freeze %d. \n", layer, enable); + + if (layer->plane_id > 0) + exynosPlaneFreezeUpdate(layer->plane_id, enable); +} + +Bool +exynosLayerIsNeedUpdate(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + return layer->need_update; +} + +void +exynosLayerUpdate(EXYNOSLayer * layer) +{ + XDBG_DEBUG(MLYR, "E. layer %p\n", layer); + + XDBG_RETURN_IF_FAIL(layer != NULL); + XDBG_RETURN_IF_FAIL(layer->fb_id > 0); + + if (!layer->visible) { + XDBG_DEBUG(MLYR, "Q. layer->visible == %s.\n", + layer->visible ? "TRUE" : "FALSE"); + return; + } + + xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR(layer->pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int c; + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; + EXYNOSCrtcPrivPtr pTemp = pCrtc->driver_private; + + if (pTemp == NULL) + continue; + if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == layer->crtc_id) { + pCrtcPriv = pTemp; + break; + } + } + + if (!pCrtcPriv || pCrtcPriv->bAccessibility) { + if (pCrtcPriv) + XDBG_DEBUG(MLYR, + "Q. pCrtcPriv == %p pCrtcPriv->bAccessibility == %s.\n", + pCrtcPriv, pCrtcPriv->bAccessibility ? "TRUE" : "FALSE"); + else + XDBG_DEBUG(MLYR, "Q, pCrtcPriv == NULL \n"); + + return; + } +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + return; +#endif + if (!_exynosLayerShowInternal(layer, TRUE)) { + XDBG_DEBUG(MLYR, "Q. _exynosLayerShowInternal == FALSE.\n"); + return; + } + XDBG_DEBUG(MLYR, "Q.\n"); +} + +void +exynosLayerTurn(EXYNOSLayer * layer, Bool onoff, Bool user) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + exynosPlaneTrun(layer->plane_id, onoff, user); +} + +Bool +exynosLayerTurnStatus(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + + return exynosPlaneTrunStatus(layer->plane_id); +} + +void +exynosLayerEnableVBlank(EXYNOSLayer * layer, Bool enable) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + layer->enable_vblank = (enable) ? TRUE : FALSE; +} + +Bool +exynosLayerSetOffset(EXYNOSLayer * layer, int x, int y) +{ + + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + + if (layer->offset_x == x && layer->offset_y == y) + return TRUE; + + /* display controller restriction. x+width=2's mutiple */ + XDBG_TRACE(MLYR, "layer(%p) offset(%d,%d => %d,%d).\n", + layer, x, y, x & (~0x1), y); + layer->offset_x = x & (~0x1); + layer->offset_y = y; +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + return TRUE; +#endif + layer->need_update = TRUE; + if (exynosLayerIsVisible(layer) && !layer->freeze_update) { + int crtc_id = _GetCrtcID(layer); + int plane_pos = _exynosLayerGetPlanePos(layer, layer->lpos); + + if (!exynosPlaneShow(layer->plane_id, crtc_id, + layer->src->x, layer->src->y, + layer->src->width, layer->src->height, + layer->offset_x + layer->dst->x, + layer->offset_y + layer->dst->y, + layer->dst->width, layer->dst->height, + plane_pos, FALSE)) + return FALSE; + layer->need_update = FALSE; + } + + return TRUE; +} + +void +exynosLayerGetOffset(EXYNOSLayer * layer, int *x, int *y) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + if (x) + *x = layer->offset_x; + if (y) + *y = layer->offset_y; +} + +Bool +exynosLayerSetOutput(EXYNOSLayer * layer, EXYNOSLayerOutput output) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + layer->output = output; + layer->crtc_id = 0; + return TRUE; +} + +Bool +exynosLayerSetPos(EXYNOSLayer * layer, EXYNOSLayerPos lpos) +{ + + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(lpos >= LAYER_NONE && lpos < LAYER_MAX, FALSE); + +#if 1 + EXYNOSModePtr pExynosMode; + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + layer->lpos = lpos; + return TRUE; + } +#endif + + if (layer->lpos == lpos) + return TRUE; + + if (exynosLayerFind(layer->output, lpos) && lpos != LAYER_NONE) + return FALSE; + + layer->need_update = TRUE; + if (exynosLayerIsVisible(layer) && !layer->freeze_update) { + if (lpos == LAYER_NONE) { + if (!exynosPlaneHide(layer->plane_id)) + return FALSE; + + layer->visible = FALSE; + layer->crtc_id = 0; + } + else { + int crtc_id = _GetCrtcID(layer); + int plane_pos = _exynosLayerGetPlanePos(layer, lpos); + + if (!exynosPlaneShow(layer->plane_id, crtc_id, + layer->src->x, layer->src->y, + layer->src->width, layer->src->height, + layer->offset_x + layer->dst->x, + layer->offset_y + layer->dst->y, + layer->dst->width, layer->dst->height, + plane_pos, FALSE)) + return FALSE; + layer->need_update = FALSE; + } + } + + XDBG_TRACE(MLYR, "layer(%p) lpos(%d). \n", layer, lpos); + + layer->lpos = lpos; + + return TRUE; +} + +Bool +exynosLayerSwapPos(EXYNOSLayer * layer1, EXYNOSLayer * layer2) +{ + EXYNOSLayer *lower, *upper; + EXYNOSLayerPos upper_lpos, lower_lpos; + + XDBG_RETURN_VAL_IF_FAIL(layer1 != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(layer2 != NULL, FALSE); + + XDBG_TRACE(MLYR, "layer1(%p) layer2(%p). \n", layer1, layer2); + + lower = (layer2->lpos < layer1->lpos) ? layer2 : layer1; + upper = (layer2->lpos < layer1->lpos) ? layer1 : layer2; + + upper_lpos = upper->lpos; + lower_lpos = lower->lpos; + + exynosLayerSetPos(upper, LAYER_NONE); + exynosLayerSetPos(lower, upper_lpos); + exynosLayerSetPos(upper, lower_lpos); + + return TRUE; +} + +EXYNOSLayerPos +exynosLayerGetPos(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, 0); + + return layer->lpos; +} + +Bool +exynosLayerSetRect(EXYNOSLayer * layer, xRectangle *src, xRectangle *dst) +{ + + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst != NULL, FALSE); + + if (!layer->src) + layer->src = calloc(sizeof(xRectangle), 1); + + XDBG_RETURN_VAL_IF_FAIL(layer->src != NULL, FALSE); + + if (!layer->dst) + layer->dst = calloc(sizeof(xRectangle), 1); + + XDBG_RETURN_VAL_IF_FAIL(layer->dst != NULL, FALSE); + + if (!memcmp(layer->src, src, sizeof(xRectangle)) && + !memcmp(layer->dst, dst, sizeof(xRectangle))) + return TRUE; + + *layer->src = *src; + *layer->dst = *dst; + + XDBG_TRACE(MLYR, "layer(%p) src(%d,%d %dx%d) dst(%d,%d %dx%d). \n", + layer, src->x, src->y, src->width, src->height, + dst->x, dst->y, dst->width, dst->height); +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + return TRUE; +#endif + if (layer->pending_vbuf && VBUF_IS_VALID(layer->pending_vbuf)) { + layer->pending_vbuf->showing = FALSE; + exynosUtilVideoBufferUnref(layer->pending_vbuf); + layer->pending_vbuf = NULL; + } + + layer->need_update = TRUE; + if (exynosLayerIsVisible(layer) && !layer->freeze_update) { + int plane_pos = _exynosLayerGetPlanePos(layer, layer->lpos); + + if (!exynosPlaneShow(layer->plane_id, _GetCrtcID(layer), + src->x, src->y, src->width, src->height, + layer->offset_x + dst->x, + layer->offset_y + dst->y, + dst->width, dst->height, plane_pos, FALSE)) + return FALSE; + layer->need_update = FALSE; + } + + return TRUE; +} + +void +exynosLayerGetRect(EXYNOSLayer * layer, xRectangle *src, xRectangle *dst) +{ + XDBG_RETURN_IF_FAIL(layer != NULL); + + if (src && layer->src) + *src = *layer->src; + + if (dst && layer->dst) + *dst = *layer->dst; +} + +Bool +exynosLayerIsPanding(EXYNOSLayer * layer) +{ + if (layer->wait_vbuf && layer->pending_vbuf) { + return TRUE; + } + return FALSE; +} + +int +exynosLayerSetBuffer(EXYNOSLayer * layer, EXYNOSVideoBuf * vbuf) +{ + XDBG_DEBUG(MLYR, "E. layer %p vbuf %p\n", layer, vbuf); + unsigned int fb_id = 0; + + if (!layer) { + XDBG_ERROR(MLYR, "Layer is NULL\n"); + XDBG_DEBUG(MLYR, "Q. ret = 0(fb_id)\n"); + return 0; + } + if (!VBUF_IS_VALID(vbuf)) { + XDBG_ERROR(MLYR, "vbuf %p is not valid\n", vbuf); + XDBG_DEBUG(MLYR, "Q. ret = 0(fb_id)\n"); + return 0; + } + + if (!exynosLayerSupport(layer->pScrn, layer->output, layer->lpos, vbuf->id)) { + XDBG_ERROR(MLYR, + "fail : layer(%p) output(%d) lpos(%d) vbuf(%c%c%c%c)\n", + layer, layer->output, layer->lpos, FOURCC_STR(vbuf->id)); + XDBG_DEBUG(MLYR, "Q. ret = 0(fb_id)\n"); + return 0; + } + +#if 1 + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(layer->pScrn)->pExynosMode; + + if (layer->output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + if (layer->enable_vblank == TRUE) + layer->enable_vblank = FALSE; + + XDBG_TRACE(MLYR, "layer(%p) vbuf('%c%c%c%c', %dx%d, %d,%d %dx%d)\n", + layer, FOURCC_STR(vbuf->id), vbuf->width, vbuf->height, + vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, + vbuf->crop.height); + + if (layer->vbuf) + exynosUtilVideoBufferUnref(layer->vbuf); + + layer->vbuf = exynosUtilVideoBufferRef(vbuf); + layer->fb_id = 1; + + _exynosLayerNotify(layer, LAYER_BUF_CHANGED, vbuf); + + return layer->fb_id; + } +#endif +#if 0 + if (layer->wait_vbuf && layer->pending_vbuf) { + XDBG_TRACE(MLYR, "pending_vbuf(%" PRIuPTR ") exists.\n", + layer->pending_vbuf->stamp); + return 0; + } +#endif + + _exynosLayerGetBufferID(layer, vbuf); + if (vbuf->fb_id <= 0) { + XDBG_ERROR(MLYR, "Can't set fb_id to vbuf %p\n", vbuf); + XDBG_DEBUG(MLYR, "Q. ret = 0(fb_id)\n"); + } + + if (layer->pending_vbuf) { + if (VBUF_IS_VALID(layer->pending_vbuf)) { + layer->pending_vbuf->showing = FALSE; + if (layer->pending_vbuf->vblank_handler) { + layer->pending_vbuf->vblank_handler(0, 0, 0, + layer->pending_vbuf-> + vblank_user_data, TRUE); + layer->pending_vbuf->vblank_handler = NULL; + layer->pending_vbuf->vblank_user_data = NULL; + } + exynosUtilVideoBufferUnref(layer->pending_vbuf); + layer->pending_vbuf = NULL; + } + else { + XDBG_NEVER_GET_HERE(MLYR); + } + } + + fb_id = exynosPlaneGetBuffer(layer->plane_id, NULL, vbuf); + if (fb_id == 0) { + fb_id = exynosPlaneAddBuffer(layer->plane_id, vbuf); + if (fb_id <= 0) { + XDBG_ERROR(MLYR, "Can't add vbuf %p to plane %d\n", vbuf, + layer->plane_id); + XDBG_DEBUG(MLYR, "Q. ret = 0(fb_id)\n"); + return 0; + } + } + + if (layer->wait_vbuf && !layer->pending_vbuf) { + layer->pending_vbuf = exynosUtilVideoBufferRef(vbuf); + XDBG_RETURN_VAL_IF_FAIL((layer->pending_vbuf != NULL), 0); + layer->pending_vbuf->showing = TRUE; + XDBG_TRACE(MLYR, "pending vbuf(%" PRIuPTR ").\n", + layer->pending_vbuf->stamp); + XDBG_DEBUG(MLYR, "Q. ret = %d(fb_id)\n", vbuf->fb_id); + return vbuf->fb_id; + } + + layer->fb_id = fb_id; + if (!exynosPlaneAttach(layer->plane_id, 0, vbuf)) { + XDBG_ERROR(MLYR, "Can't attach vbuf %p to plane %d\n", vbuf, + layer->plane_id); + XDBG_DEBUG(MLYR, "Q. exynosPlaneAttach == FALSE, ret = 0(fb_id)\n"); + return 0; + } + + if (exynosLayerIsVisible(layer) && !layer->freeze_update) + if (!_exynosLayerShowInternal(layer, TRUE)) { + XDBG_DEBUG(MLYR, + "Q. _exynosLayerShowInternal == FALSE, ret = 0(fb_id)\n"); + return 0; + } + + if (layer->enable_vblank) { + layer->wait_vbuf = exynosUtilVideoBufferRef(vbuf); + XDBG_RETURN_VAL_IF_FAIL((layer->wait_vbuf != NULL), 0); + layer->wait_vbuf->showing = TRUE; + XDBG_TRACE(MLYR, "layer(%p) --> %s (%" PRIuPTR ",%d,%d) \n", layer, + (layer->output == LAYER_OUTPUT_LCD) ? "LCD" : "TV", + layer->wait_vbuf->stamp, + VBUF_IS_CONVERTING(layer->wait_vbuf), + layer->wait_vbuf->showing); + + if (exynosLayerIsVisible(layer)) { + XDBG_TRACE(MLYR, "layer(%p) fb_id(%d) attached. \n", layer, fb_id); + _exynosLayerWatchVblank(layer); + } + } + + if (layer->vbuf) { +// if (layer->vbuf->vblank_handler) +// { +// layer->vbuf->vblank_handler(0, 0, 0, layer->vbuf->vblank_user_data, TRUE); +// layer->vbuf->vblank_handler = NULL; +// layer->vbuf->vblank_user_data = NULL; +// } + exynosUtilVideoBufferUnref(layer->vbuf); + } + layer->vbuf = exynosUtilVideoBufferRef(vbuf); + + _exynosLayerNotify(layer, LAYER_BUF_CHANGED, vbuf); + XDBG_DEBUG(MLYR, "Q. ret = %d(fb_id)\n", fb_id); + return fb_id; +} + +EXYNOSVideoBuf * +exynosLayerGetBuffer(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + + if (layer->showing_vbuf && layer->dst && layer->visible) + return layer->showing_vbuf; + else if (layer->wait_vbuf) + return layer->wait_vbuf; + else if (layer->pending_vbuf) + return layer->pending_vbuf; + else if (layer->vbuf) + return (layer->vbuf); + + return NULL; +} + +DrawablePtr +exynosLayerGetDraw(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + return layer->pDraw; +} + +EXYNOSVideoBuf * +exynosLayerGetMatchBuf(EXYNOSLayer * layer, tbm_bo bo) +{ +#if 0 + EXYNOSVideoBuf *pVbuf = NULL; + EXYNOSFbBoDataPtr bo_data = NULL; + int ret = tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + + if (ret == 0 || bo_data == NULL) { + return NULL; + } + + if (layer->showing_vbuf && layer->showing_vbuf->fb_id == bo_data->fb_id) + pVbuf = layer->showing_vbuf; + + else if (layer->wait_vbuf && layer->wait_vbuf->fb_id == bo_data->fb_id) + pVbuf = layer->wait_vbuf; + + else if (layer->pending_vbuf && + layer->pending_vbuf->fb_id == bo_data->fb_id) + pVbuf = layer->pending_vbuf; + + return pVbuf; +#endif + return NULL; + +} + +/* +* we should check new drawable with previous drawable. +* but "tbo" which is attached to drawable could be different (for example present extension) +*/ +Bool +exynosLayerSetDraw(EXYNOSLayer * layer, DrawablePtr pDraw) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pDraw != NULL, FALSE); + + EXYNOSVideoBuf *pVbuf = NULL; + PixmapPtr pPixmap; + EXYNOSPixmapPriv *privPixmap; + + if (pDraw->type == DRAWABLE_WINDOW) + pPixmap = (pDraw->pScreen->GetWindowPixmap) ((WindowPtr) pDraw); + else + pPixmap = (PixmapPtr) pDraw; + privPixmap = exaGetPixmapDriverPrivate(pPixmap); + XDBG_RETURN_VAL_IF_FAIL(privPixmap != NULL, FALSE); + + tbm_bo new_bo = privPixmap->bo; + + if (new_bo == NULL) { + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(privPixmap->bo != NULL, fail); + new_bo = privPixmap->bo; + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + } + + pVbuf = exynosLayerGetMatchBuf(layer, new_bo); + if (pVbuf == NULL) { + pVbuf = exynosUtilCreateVideoBufferByDraw(pDraw); + XDBG_RETURN_VAL_IF_FAIL(pVbuf != NULL, FALSE); + + XDBG_GOTO_IF_FAIL(exynosLayerSetBuffer(layer, pVbuf), fail); + + //do unref for videobuf because videobuf is local variable + exynosUtilVideoBufferUnref(pVbuf); + } + else { + XDBG_DEBUG(MVBUF, "frame buffer(%d) already set on layer(%p)\n", + pVbuf->fb_id, layer->lpos); + } + + layer->pDraw = pDraw; + + return TRUE; + fail: + exynosUtilFreeVideoBuffer(pVbuf); + return FALSE; +} + +Bool +exynosLayerSetAsDefault(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + EXYNOSLayer *lyr = NULL; + + _exynosLayerInitList(); + + xorg_list_for_each_entry(lyr, &crtc_layers, link) { + /* FIXME :: search old default for same crtc and reset it */ + if ( /*lyr->crtc_id == layer->crtc_id && */ lyr->default_layer) + lyr->default_layer = FALSE; + } + + layer->default_layer = TRUE; + return TRUE; +} + +EXYNOSLayerPtr +exynosLayerGetDefault(xf86CrtcPtr pCrtc) +{ + EXYNOSLayer *layer = NULL; + +// EXYNOSCrtcPrivPtr pPrivCrtc = (EXYNOSCrtcPrivPtr)pCrtc->driver_private; + + _exynosLayerInitList(); + + xorg_list_for_each_entry(layer, &crtc_layers, link) { + /* FIXME :: def layer can be in each crtc */ + if (layer->default_layer + /*&& layer->crtc_id == pPrivCrtc->mode_crtc->crtc_id */ ) + return layer; + } + + return NULL; +} + +ScrnInfoPtr +exynosLayerGetScrn(EXYNOSLayer * layer) +{ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + return layer->pScrn; +} + +Bool +exynosLayerIsUpdateDRI(EXYNOSLayer * layer) +{ + return layer->is_updated_dri; +} + +void +exynosLayerUpdateDRI(EXYNOSLayer * layer, Bool is_updated_dri) +{ + layer->is_updated_dri = is_updated_dri; +} + +void +exynosLayerVBlankEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + EXYNOSLayer *layer = NULL, *layer_next = NULL; + intptr_t pipe = (intptr_t) event_data; + + XDBG_RETURN_IF_FAIL(pipe < LAYER_OUTPUT_MAX); + + _exynosLayerInitList(); + + wait_vblank[pipe] = FALSE; + + XDBG_DEBUG(MLYR, "frame(%d), tv_sec(%d), tv_usec(%d) \n", frame, tv_sec, + tv_usec); + + xorg_list_for_each_entry_safe(layer, layer_next, &crtc_layers, link) { + intptr_t crtc_pipe = + exynosDisplayCrtcPipe(layer->pScrn, _GetCrtcID(layer)); + + if (!layer->enable_vblank || !layer->wait_vblank) + continue; + + if (crtc_pipe != pipe) + continue; + + layer->wait_vblank = FALSE; + + if (VBUF_IS_VALID(layer->wait_vbuf)) { + if (layer->showing_vbuf && VBUF_IS_VALID(layer->showing_vbuf)) { + layer->showing_vbuf->showing = FALSE; + exynosUtilVideoBufferUnref(layer->showing_vbuf); + } + + layer->showing_vbuf = layer->wait_vbuf; + layer->wait_vbuf = NULL; + + if (layer->pending_vbuf && VBUF_IS_VALID(layer->pending_vbuf)) { + intptr_t fb_id; + + layer->wait_vbuf = layer->pending_vbuf; + layer->pending_vbuf = NULL; + + fb_id = + exynosPlaneGetBuffer(layer->plane_id, NULL, + layer->wait_vbuf); + if (fb_id == 0) { + fb_id = + exynosPlaneAddBuffer(layer->plane_id, layer->wait_vbuf); + XDBG_RETURN_IF_FAIL(fb_id > 0); + + layer->fb_id = layer->wait_vbuf->fb_id; + } + + if (!exynosPlaneAttach(layer->plane_id, 0, layer->wait_vbuf)) + continue; + + if (exynosLayerIsVisible(layer) && !layer->freeze_update) + _exynosLayerShowInternal(layer, TRUE); + + _exynosLayerWatchVblank(layer); + } + + EXYNOSPtr pExynos = EXYNOSPTR(layer->pScrn); + + if (pExynos->pVideoPriv->video_fps) + _countFps(layer); + + XDBG_TRACE(MLYR, + "layer(%p) fb_id(%d) now showing frame(%d) (%ld,%ld,%ld) => crtc(%d) lpos(%d). \n", + layer, layer->fb_id, frame, VSTMAP(layer->pending_vbuf), + VSTMAP(layer->wait_vbuf), VSTMAP(layer->showing_vbuf), + _GetCrtcID(layer), layer->lpos); + + _exynosLayerNotify(layer, LAYER_VBLANK, + (void *) layer->showing_vbuf); + + //call the Vblank signal when vbuf has been showing; + if (layer->showing_vbuf->vblank_handler) { + layer->showing_vbuf->vblank_handler(frame, tv_sec, tv_usec, + layer->showing_vbuf-> + vblank_user_data, FALSE); + layer->showing_vbuf->vblank_handler = NULL; + layer->showing_vbuf->vblank_user_data = NULL; + } + } + } +} diff --git a/src/crtcconfig/exynos_layer.h b/src/crtcconfig/exynos_layer.h new file mode 100644 index 0000000..566623d --- /dev/null +++ b/src/crtcconfig/exynos_layer.h @@ -0,0 +1,136 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 __SEC_LAYER_H__ +#define __SEC_LAYER_H__ + +#include "exynos_video_types.h" +#include "exynos_video_fourcc.h" +#include <xf86Crtc.h> + +typedef enum { + LAYER_OUTPUT_LCD, + LAYER_OUTPUT_EXT, + LAYER_OUTPUT_MAX +} EXYNOSLayerOutput; + +typedef enum { + LAYER_NONE = -3, + LAYER_LOWER2 = -2, + LAYER_LOWER1 = -1, + LAYER_DEFAULT = 0, + LAYER_UPPER = +1, + LAYER_MAX = +2, +#ifdef LAYER_MANAGER + FOR_LAYER_MNG = +3, +#endif +} EXYNOSLayerPos; + +#define LAYER_DESTROYED 1 +#define LAYER_SHOWN 2 +#define LAYER_HIDDEN 3 +/* To manage buffer */ +#define LAYER_BUF_CHANGED 4 /* type_data: EXYNOSLayerBufInfo */ +#define LAYER_VBLANK 5 /* type_data: EXYNOSLayerVblankDatePtr */ + +typedef struct _layerVblankDate { + unsigned int frame; + unsigned int tv_sec; + unsigned int tv_usec; + EXYNOSVideoBuf *vbuf; +} EXYNOSLayerVblankDateRec, *EXYNOSLayerVblankDatePtr; + +typedef struct _EXYNOSLayer EXYNOSLayer, *EXYNOSLayerPtr; + +typedef void (*NotifyFunc) (EXYNOSLayer * layer, int type, void *type_data, + void *user_data); + +Bool exynosLayerSupport(ScrnInfoPtr pScrn, EXYNOSLayerOutput output, + EXYNOSLayerPos lpos, unsigned int id); + +EXYNOSLayer *exynosLayerFind(EXYNOSLayerOutput output, EXYNOSLayerPos lpos); +EXYNOSLayer *exynosLayerFindByDraw(DrawablePtr); +void exynosLayerDestroyAll(void); +void exynosLayerShowAll(ScrnInfoPtr pScrn, EXYNOSLayerOutput output); + +void exynosLayerAddNotifyFunc(EXYNOSLayer * layer, NotifyFunc func, + void *user_data); +void exynosLayerRemoveNotifyFunc(EXYNOSLayer * layer, NotifyFunc func); + +EXYNOSLayer *exynosLayerCreate(ScrnInfoPtr pScrn, EXYNOSLayerOutput output, + EXYNOSLayerPos lpos); +EXYNOSLayer *exynosLayerRef(EXYNOSLayer * layer); +void exynosLayerUnref(EXYNOSLayer * layer); + +Bool exynosLayerIsVisible(EXYNOSLayer * layer); +void exynosLayerShow(EXYNOSLayer * layer); +void exynosLayerHide(EXYNOSLayer * layer); +void exynosLayerFreezeUpdate(EXYNOSLayer * layer, Bool enable); +Bool exynosLayerIsNeedUpdate(EXYNOSLayer * layer); +void exynosLayerUpdate(EXYNOSLayer * layer); +void exynosLayerTurn(EXYNOSLayer * layer, Bool onoff, Bool user); +Bool exynosLayerTurnStatus(EXYNOSLayer * layer); + +void exynosLayerEnableVBlank(EXYNOSLayer * layer, Bool enable); +Bool exynosLayerIsPanding(EXYNOSLayer * layer); +Bool exynosLayerSetOffset(EXYNOSLayer * layer, int x, int y); +void exynosLayerGetOffset(EXYNOSLayer * layer, int *x, int *y); + +Bool exynosLayerSetPos(EXYNOSLayer * layer, EXYNOSLayerPos lpos); +EXYNOSLayerPos exynosLayerGetPos(EXYNOSLayer * layer); +Bool exynosLayerSwapPos(EXYNOSLayer * layer1, EXYNOSLayer * layer2); + +Bool exynosLayerSetRect(EXYNOSLayer * layer, xRectangle *src, xRectangle *dst); +void exynosLayerGetRect(EXYNOSLayer * layer, xRectangle *src, xRectangle *dst); + +int exynosLayerSetBuffer(EXYNOSLayer * layer, EXYNOSVideoBuf * vbuf); +EXYNOSVideoBuf *exynosLayerGetBuffer(EXYNOSLayer * layer); + +DrawablePtr exynosLayerGetDraw(EXYNOSLayer * layer); +Bool exynosLayerSetDraw(EXYNOSLayer * layer, DrawablePtr pDraw); + +EXYNOSVideoBuf *exynosLayerGetMatchBuf(EXYNOSLayer * layer, tbm_bo bo); + +Bool exynosLayerIsUpdateDRI(EXYNOSLayer * layer); +void exynosLayerUpdateDRI(EXYNOSLayer * layer, Bool); + +Bool exynosLayerSetAsDefault(EXYNOSLayer * layer); +EXYNOSLayerPtr exynosLayerGetDefault(xf86CrtcPtr pCrtc); + +ScrnInfoPtr exynosLayerGetScrn(EXYNOSLayer * layer); + +void exynosLayerVBlankEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data); +Bool exynosLayerExistNotifyFunc(EXYNOSLayer * layer, NotifyFunc func); + +void exynosLayerDestroy(EXYNOSLayer * layer); +void exynosLayerClearQueue(EXYNOSLayer * layer); +Bool exynosLayerSetOutput(EXYNOSLayer * layer, EXYNOSLayerOutput output); +#endif /* __SEC_LAYER_H__ */ diff --git a/src/crtcconfig/exynos_layer_manager.c b/src/crtcconfig/exynos_layer_manager.c new file mode 100644 index 0000000..3e71397 --- /dev/null +++ b/src/crtcconfig/exynos_layer_manager.c @@ -0,0 +1,1303 @@ +/************************************************************************** +xserver-xorg-video-exynos + +Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> +Contact: Andrii Sokolenko <a.sokolenko@samsung.com> + +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 LAYER_MANAGER +#include "exynos_layer_manager.h" +#include "exynos_util.h" +#include "exynos_plane.h" +#include "exynos_layer.h" +#include "exynos.h" +#include <string.h> + +typedef struct { + EXYNOSLayerMngClientID owner; + EXYNOSLayerPtr hwlayer; +// Bool enabled; +// EXYNOSLayerOutput output; +// EXYNOSLayerPos lpos; + struct xorg_list layer_link; +} exynosLayerMngHWLayerRec, *exynosLayerMngHWLayerPtr; + +typedef struct _EXYNOSLayerMng { + exynosLayerMngHWLayerPtr *array_p_layers; + int count_of_layers; + ScrnInfoPtr pScrn; + struct xorg_list Events[EVENT_LAYER_MAX]; +} SecLayerMngRec, *EXYNOSLayerMngPtr; + +typedef struct _EXYNOSLayerClient { + CARD32 stamp; + int lyr_client_priority; + char *lyr_client_name; + EXYNOSLayerMngPtr pLYRM; + struct xorg_list valid_link; + /*........... */ +} exynosLayerClientRec, *exynosLayerClientPtr; + +typedef struct { + exynosLayerClientPtr p_lyr_client; + LYRMNotifyFunc callback_func; + void *callback_user_data; + struct xorg_list callback_link; +} exynosLayerManagerEventRec, *exynosLayerManagerEventPtr; + +typedef struct _exynosLayerManagerEvent { + const char *event_name; + int expendable_callback; /* Did run one time */ +} exynosLayerManagerEventConfigRec; + +typedef struct { + EXYNOSLayerPos legacy_pos; + int hwpos; + int colorspace_type; /* 1 - RGB, 2-YUV */ + exynosLayerMngHWLayerPtr layer; +} exynosLayerMngPlaneRec; + +#define INVALID_HWPOS -10 +#define LPOSCONV(v) (v+2) +#define PPOSCONV(v) (v-2) +static exynosLayerMngPlaneRec layer_table[LAYER_OUTPUT_MAX][PLANE_MAX] = { + [LAYER_OUTPUT_LCD] = { + [PLANE_LOWER2] = {.legacy_pos = -2,.hwpos = + 1,.colorspace_type = 1, NULL}, + [PLANE_LOWER1] = {.legacy_pos = -1,.hwpos = + 2,.colorspace_type = 1, NULL}, + [PLANE_DEFAULT] = {.legacy_pos = 0,.hwpos = + 3,.colorspace_type = 1, NULL}, + [PLANE_UPPER] = {.legacy_pos = 1,.hwpos = + 4,.colorspace_type = 1, NULL} + }, + [LAYER_OUTPUT_EXT] = { + [PLANE_LOWER2] = {.legacy_pos = -2,.hwpos = + INVALID_HWPOS,.colorspace_type = + 0, NULL}, + [PLANE_LOWER1] = {.legacy_pos = -1,.hwpos = + 2,.colorspace_type = 2, NULL}, + [PLANE_DEFAULT] = {.legacy_pos = 0,.hwpos = + 0,.colorspace_type = 1, NULL}, + [PLANE_UPPER] = {.legacy_pos = 1,.hwpos = + 1,.colorspace_type = 1, NULL} + } +}; + +static exynosLayerManagerEventConfigRec LyrMngEvents[EVENT_LAYER_MAX] = { + [EVENT_LAYER_SHOW] = {"Showed", 0}, + [EVENT_LAYER_ANNEX] = {"Annexed", 0}, + [EVENT_LAYER_RELEASE] = {"Release", 0}, + [EVENT_LAYER_HIDE] = {"Hidden", 0}, + [EVENT_LAYER_BUFSET] = {"Set buffer", 1}, + [EVENT_LAYER_FREE_COUNTER] = {"Counter of free layer", 0} +}; + +static struct xorg_list client_valid_list; + +static exynosLayerClientPtr +_findLayerClient(CARD32 stamp) +{ + exynosLayerClientPtr cur = NULL, next = NULL; + + if (stamp == 0 || stamp == LYR_ERROR_ID) + return NULL; + xorg_list_for_each_entry_safe(cur, next, &client_valid_list, valid_link) { + if (stamp == cur->stamp) + return cur; + } + XDBG_DEBUG(MLYRM, "Layer client id %6" PRIXID " is not valid\n", stamp); + return NULL; +} + +static exynosLayerClientPtr +_findLayerClientByName(const char *p_client_name) +{ + exynosLayerClientPtr cur = NULL, next = NULL; + + xorg_list_for_each_entry_safe(cur, next, &client_valid_list, valid_link) { + if (!strcmp(p_client_name, cur->lyr_client_name)) { + return cur; + } + } + return NULL; +} + +static inline Bool +_clientIsOwner(exynosLayerClientPtr p_lyr_client, EXYNOSLayerOutput output, + EXYNOSLayerMngPlanePos plane_pos) +{ + Bool ret = FALSE; + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, FALSE); + exynosLayerMngHWLayerPtr check_layer = layer_table[output][plane_pos].layer; + + if (check_layer) { + if (check_layer->owner == p_lyr_client->stamp) { + ret = TRUE; + } + } + + XDBG_DEBUG(MLYRM, "Client %s %s own plane on output:%d, ppos:%d\n", + p_lyr_client->lyr_client_name, ret ? "" : "not", output, + plane_pos); + return ret; +} + +void +exynosLayerMngDelEvent(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerMngEventType event_type, + LYRMNotifyFunc callback_func) +{ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_IF_FAIL(p_lyr_client != NULL); + XDBG_RETURN_IF_FAIL((event_type >= 0 && event_type < EVENT_LAYER_MAX)); + exynosLayerManagerEventPtr data = NULL, data_next = NULL; + + xorg_list_for_each_entry_safe(data, data_next, + &p_lyr_client->pLYRM->Events[event_type], + callback_link) { + if (callback_func == NULL && data->p_lyr_client == p_lyr_client) { /* Remove all callback */ + xorg_list_del(&data->callback_link); + free(data); + XDBG_DEBUG(MLYRM, "Successful remove layer client %s event %s\n", + p_lyr_client->lyr_client_name, + LyrMngEvents[event_type].event_name); + } + else if (data->callback_func == callback_func && + data->p_lyr_client == p_lyr_client) { + xorg_list_del(&data->callback_link); + free(data); + XDBG_DEBUG(MLYRM, "Successful remove layer client %s event %s\n", + p_lyr_client->lyr_client_name, + LyrMngEvents[event_type].event_name); + } + } +} + +static int +_exynosLayerMngCountOfFreeLayer(EXYNOSLayerMngPtr pLYRM) +{ + XDBG_RETURN_VAL_IF_FAIL(pLYRM != NULL, -1); + int i, ret = 0; + + for (i = 0; i < pLYRM->count_of_layers; i++) { + if (pLYRM->array_p_layers[i]->owner == 0) + ret++; + } + return ret; +} + +static int +_exynosLayerMngCountOfAnnexLayer(EXYNOSLayerMngPtr pLYRM, int client_priority) +{ + XDBG_RETURN_VAL_IF_FAIL(pLYRM != NULL, -1); + int i, ret = 0; + + for (i = 0; i < pLYRM->count_of_layers; i++) { + if (pLYRM->array_p_layers[i]->owner != 0) { + exynosLayerClientPtr p_lyr_client = + _findLayerClient(pLYRM->array_p_layers[i]->owner); + if (p_lyr_client && + p_lyr_client->lyr_client_priority < client_priority) + ret++; + } + } + return ret; +} + +void +exynosLayerMngAddEvent(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerMngEventType event_type, + LYRMNotifyFunc callback_func, + void *callback_func_user_data) +{ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_IF_FAIL(p_lyr_client != NULL); + XDBG_RETURN_IF_FAIL((event_type >= 0 && event_type < EVENT_LAYER_MAX)); + XDBG_RETURN_IF_FAIL(callback_func != NULL); + exynosLayerManagerEventPtr data = NULL, data_next = NULL; + + xorg_list_for_each_entry_safe(data, data_next, + &p_lyr_client->pLYRM->Events[event_type], + callback_link) { + if (data->callback_func == callback_func && + data->callback_user_data == callback_func_user_data && + data->p_lyr_client == p_lyr_client) { + XDBG_WARNING(MLYRM, + "Client %s already had Callback on %s event type\n", + p_lyr_client->lyr_client_name, + LyrMngEvents[event_type].event_name); + return; + } + } + data = calloc(sizeof(exynosLayerManagerEventRec), 1); + XDBG_RETURN_IF_FAIL(data != NULL); + + data->callback_func = callback_func; + data->callback_user_data = callback_func_user_data; + data->p_lyr_client = p_lyr_client; + + xorg_list_add(&data->callback_link, + &p_lyr_client->pLYRM->Events[event_type]); + XDBG_DEBUG(MLYRM, "Lyr Client:%s registered callback on Event:%s\n", + p_lyr_client->lyr_client_name, + LyrMngEvents[event_type].event_name); +} + +void +exynosLayerMngEventDispatch(ScrnInfoPtr pScrn, + EXYNOSLayerMngEventType event_type, + EXYNOSLayerMngEventCallbackDataPtr p_callback_data) +{ + XDBG_RETURN_IF_FAIL(pScrn != NULL); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_RETURN_IF_FAIL(pExynos != NULL); + XDBG_RETURN_IF_FAIL(pExynos->pLYRM != NULL); + EXYNOSLayerMngPtr pLYRM = (EXYNOSLayerMngPtr) pExynos->pLYRM; + + XDBG_RETURN_IF_FAIL((event_type >= 0 && event_type < EVENT_LAYER_MAX)); + XDBG_RETURN_IF_FAIL(p_callback_data != NULL); + exynosLayerManagerEventPtr data = NULL, data_next = NULL; + + XDBG_DEBUG(MLYRM, "Dispatch Event:%s\n", + LyrMngEvents[event_type].event_name); + switch (event_type) { + case EVENT_LAYER_ANNEX: + xorg_list_for_each_entry_safe(data, data_next, + &pLYRM->Events[event_type], + callback_link) { + if (data->callback_func) { + /* Victim of annexation */ + if (p_callback_data->annex_callback.lyr_client_id + == data->p_lyr_client->stamp) { + XDBG_DEBUG(MLYRM, "Send Event:%s to client:%s\n", + LyrMngEvents[event_type].event_name, + data->p_lyr_client->lyr_client_name); + data->callback_func(data->callback_user_data, p_callback_data); + if (LyrMngEvents[event_type].expendable_callback) { + exynosLayerMngDelEvent(data->p_lyr_client->stamp, + event_type, data->callback_func); + } + } + } + } + break; + case EVENT_LAYER_RELEASE: + { + xorg_list_for_each_entry_safe(data, data_next, + &pLYRM->Events[event_type], + callback_link) { + if (data->callback_func) { + /* Not need send event to initiator */ + if (p_callback_data->release_callback.lyr_client_id != + data->p_lyr_client->stamp) { + XDBG_DEBUG(MLYRM, "Send Event:%s to client:%s\n", + LyrMngEvents[event_type].event_name, + data->p_lyr_client->lyr_client_name); + data->callback_func(data->callback_user_data, + p_callback_data); + if (LyrMngEvents[event_type].expendable_callback) { + exynosLayerMngDelEvent(data->p_lyr_client->stamp, + event_type, data->callback_func); + } + } + } + } + break; + } + default: + xorg_list_for_each_entry_safe(data, data_next, + &pLYRM->Events[event_type], + callback_link) { + if (data->callback_func) { + XDBG_DEBUG(MLYRM, "Send Event:%s to client:%s\n", + LyrMngEvents[event_type].event_name, + data->p_lyr_client->lyr_client_name); + data->callback_func(data->callback_user_data, p_callback_data); + if (LyrMngEvents[event_type].expendable_callback) { + exynosLayerMngDelEvent(data->p_lyr_client->stamp, event_type, + data->callback_func); + } + } + } + break; + } +} + +EXYNOSLayerMngClientID +exynosLayerMngRegisterClient(ScrnInfoPtr pScrn, char *p_client_name, + int priority) +{ + XDBG_RETURN_VAL_IF_FAIL(pScrn, LYR_ERROR_ID); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_RETURN_VAL_IF_FAIL(pExynos != NULL, LYR_ERROR_ID); + XDBG_RETURN_VAL_IF_FAIL(pExynos->pLYRM != NULL, LYR_ERROR_ID); + XDBG_RETURN_VAL_IF_FAIL(p_client_name != NULL, LYR_ERROR_ID); + EXYNOSLayerMngPtr pLYRM = (EXYNOSLayerMngPtr) pExynos->pLYRM; + exynosLayerClientPtr p_ret = _findLayerClientByName(p_client_name); + + if (p_ret) { + XDBG_DEBUG(MLYRM, + "Already Registered LYRID:%6" PRIXID + " client:%s priority:%d\n", p_ret->stamp, + p_ret->lyr_client_name, p_ret->lyr_client_priority); + return (EXYNOSLayerMngClientID) p_ret->stamp; + } + p_ret = calloc(1, sizeof(exynosLayerClientRec)); + if (!p_ret) { + XDBG_ERROR(MLYRM, "Can't alloc memory\n"); + return LYR_ERROR_ID; + } + CARD32 stamp = (CARD32) GetTimeInMillis(); + + while (_findLayerClient(stamp)) + stamp++; + int size = 0; + + while (p_client_name[size++] != '\0'); + p_ret->lyr_client_name = calloc(size, sizeof(char)); + if (!p_ret->lyr_client_name) { + free(p_ret); + XDBG_ERROR(MLYRM, "Can't alloc memory\n"); + return LYR_ERROR_ID; + } + memcpy(p_ret->lyr_client_name, p_client_name, size * sizeof(char)); + p_ret->lyr_client_priority = priority; + p_ret->pLYRM = pLYRM; + p_ret->stamp = stamp; + xorg_list_add(&p_ret->valid_link, &client_valid_list); + XDBG_DEBUG(MLYRM, "Registered LYRID:%6" PRIXID " client:%s priority:%d\n", + stamp, p_ret->lyr_client_name, p_ret->lyr_client_priority); +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Registered LYRID:%6" PRIXID " client:%s priority:%d\n", stamp, + p_ret->lyr_client_name, p_ret->lyr_client_priority); +#endif + return (EXYNOSLayerMngClientID) stamp; +} + +void +exynosLayerMngUnRegisterClient(EXYNOSLayerMngClientID lyr_client_id) +{ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_IF_FAIL(p_lyr_client != NULL); + XDBG_DEBUG(MLYRM, "Unregister LYRID:%6" PRIXID " client:%s\n", + lyr_client_id, p_lyr_client->lyr_client_name); + EXYNOSLayerOutput output; + EXYNOSLayerMngPlanePos plane_pos; + EXYNOSLayerMngEventType event; + + for (event = EVENT_LAYER_SHOW; event < EVENT_LAYER_MAX; event++) { + exynosLayerMngDelEvent(lyr_client_id, event, NULL); + } + for (output = LAYER_OUTPUT_LCD; output < LAYER_OUTPUT_MAX; output++) { + for (plane_pos = PLANE_LOWER2; plane_pos < PLANE_MAX; plane_pos++) { + exynosLayerMngHWLayerPtr search_layer = + layer_table[output][plane_pos].layer; + if (search_layer && search_layer->owner == lyr_client_id) { + exynosLayerMngRelease(lyr_client_id, output, + PPOSCONV(plane_pos)); + } + } + } + XDBG_DEBUG(MLYRM, "Client %s removed from Layer Manager\n", + p_lyr_client->lyr_client_name); + xorg_list_del(&p_lyr_client->valid_link); + free(p_lyr_client->lyr_client_name); + free(p_lyr_client); +} + +Bool +exynosLayerMngInit(ScrnInfoPtr pScrn) +{ + if (!pScrn) { + EARLY_ERROR_MSG("pScrn is NULL\n"); + return FALSE; + } + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (!pExynos) { + EARLY_ERROR_MSG("pExynos is NULL\n"); + return FALSE; + } + int count_of_layers = exynosPlaneGetCount(); + + if (count_of_layers == 0) { + EARLY_ERROR_MSG("Count of hardware layers = 0"); + return FALSE; + } + int i; + EXYNOSLayerMngPtr pLYRM = calloc(1, sizeof(SecLayerMngRec)); + + if (!pLYRM) { + EARLY_ERROR_MSG("Can't alloc memory\n"); + return FALSE; + } + xorg_list_init(&client_valid_list); + for (i = 0; i < EVENT_LAYER_MAX; i++) { + xorg_list_init(&pLYRM->Events[i]); + } + pLYRM->array_p_layers = + calloc(count_of_layers, sizeof(exynosLayerMngHWLayerPtr)); + pLYRM->count_of_layers = count_of_layers; + if (!pLYRM->array_p_layers) { + EARLY_ERROR_MSG("Can't alloc memory\n"); + goto bail; + } + for (i = 0; i < count_of_layers; i++) { + pLYRM->array_p_layers[i] = calloc(1, sizeof(exynosLayerMngHWLayerRec)); + if (!pLYRM->array_p_layers[i]) { + EARLY_ERROR_MSG("Can't alloc memory\n"); + goto bail; + } + pLYRM->array_p_layers[i]->hwlayer = + exynosLayerCreate(pScrn, LAYER_OUTPUT_LCD, FOR_LAYER_MNG); + if (!pLYRM->array_p_layers[i]->hwlayer) { + EARLY_ERROR_MSG("Can't alloc layer\n"); + goto bail; + } +// pLYRM->array_p_layers[i]->output = LAYER_OUTPUT_LCD; +// pLYRM->array_p_layers[i]->lpos = LAYER_NONE; + exynosLayerSetPos(pLYRM->array_p_layers[i]->hwlayer, LAYER_NONE); + } + pLYRM->pScrn = pScrn; + pExynos->pLYRM = pLYRM; + return TRUE; + bail: + if (pLYRM) { + if (pLYRM->array_p_layers) { + for (i = 0; i < count_of_layers; i++) { + if (pLYRM->array_p_layers[i]) { + exynosLayerUnref(pLYRM->array_p_layers[i]->hwlayer); + free(pLYRM->array_p_layers[i]); + } + } + free(pLYRM->array_p_layers); + } + free(pLYRM); + } + return FALSE; +} + +void +exynosLayerMngDeInit(ScrnInfoPtr pScrn) +{ + XDBG_RETURN_IF_FAIL(pScrn != NULL); + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_RETURN_IF_FAIL(pExynos != NULL); + XDBG_RETURN_IF_FAIL(pExynos->pLYRM != NULL); + EXYNOSLayerMngPtr pLYRM = (EXYNOSLayerMngPtr) pExynos->pLYRM; + exynosLayerClientPtr current_entry_client_list = + NULL, next_entry_client_list = NULL; + xorg_list_for_each_entry_safe(current_entry_client_list, + next_entry_client_list, &client_valid_list, + valid_link) { + exynosLayerMngUnRegisterClient((EXYNOSLayerMngClientID) + current_entry_client_list->stamp); + } + + if (pLYRM->array_p_layers) { + int i; + + for (i = 0; i < pLYRM->count_of_layers; i++) { + if (pLYRM->array_p_layers[i]) { + exynosLayerUnref(pLYRM->array_p_layers[i]->hwlayer); + free(pLYRM->array_p_layers[i]); + } + } + free(pLYRM->array_p_layers); + } + + free(pLYRM); + pExynos->pLYRM = NULL; +} + +/* TODO: Avoid LEGACY Layer function */ +static exynosLayerMngHWLayerPtr +_exynosLayerMngFindUnusedLayer(EXYNOSLayerMngPtr pLYRM) +{ + int i; + + for (i = 0; i < pLYRM->count_of_layers; i++) { + if (pLYRM->array_p_layers[i]->owner == 0) { + XDBG_DEBUG(MLYRM, "Find unused plane %p\n", + pLYRM->array_p_layers[i]); + return pLYRM->array_p_layers[i]; + } + } + return NULL; +} + +static Bool +_exynosLayerMngTestAnnexLayer(exynosLayerClientPtr p_lyr_client, + EXYNOSLayerOutput output, + EXYNOSLayerMngPlanePos plane_pos) +{ + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(plane_pos >= PLANE_LOWER2 && + plane_pos < PLANE_MAX, FALSE); + exynosLayerMngHWLayerPtr search_layer = + layer_table[output][plane_pos].layer; + + XDBG_RETURN_VAL_IF_FAIL(search_layer != NULL, FALSE); + exynosLayerClientPtr current_layer_owner = + _findLayerClient(search_layer->owner); + Bool ret_data = FALSE; + + if (!current_layer_owner) { + XDBG_NEVER_GET_HERE(MLYRM); + ret_data = TRUE; + } + else if (current_layer_owner == p_lyr_client) { + XDBG_NEVER_GET_HERE(MLYRM); + ret_data = TRUE; + } + else if (current_layer_owner->lyr_client_priority < + p_lyr_client->lyr_client_priority) { + ret_data = TRUE; + } + else { + ret_data = FALSE; + } + XDBG_DEBUG(MLYRM, "Client:%s %s annex, output:%d, ppos:%d, at owner:%s\n", + p_lyr_client->lyr_client_name, ret_data ? "Can" : "Can't", + output, plane_pos, + current_layer_owner ? current_layer_owner->lyr_client_name : + "not valid"); + return ret_data; +} + +/* Temp func + * TODO: save ppos and output on hw_layer struct +*/ +static Bool +_exynosLayerMngFindPlaneByLayer(exynosLayerMngHWLayerPtr hw_layer, + EXYNOSLayerOutput * p_ret_output, + EXYNOSLayerMngPlanePos * p_ret_plane_pos) +{ + EXYNOSLayerOutput output; + EXYNOSLayerMngPlanePos plane_pos; + Bool ret = FALSE; + + for (output = LAYER_OUTPUT_LCD; output < LAYER_OUTPUT_MAX; output++) { + for (plane_pos = PLANE_LOWER2; plane_pos < PLANE_MAX; plane_pos++) { + exynosLayerMngHWLayerPtr search_layer = + layer_table[output][plane_pos].layer; + if (search_layer && search_layer == hw_layer) { + ret = TRUE; + if (p_ret_output) + *p_ret_output = output; + if (p_ret_plane_pos) + *p_ret_plane_pos = plane_pos; + break; + } + } + if (ret) + break; + } + return ret; +} + +static exynosLayerMngHWLayerPtr +_exynosLayerMngAnnexLayer(exynosLayerClientPtr p_lyr_client, + EXYNOSLayerOutput desired_output, + EXYNOSLayerMngPlanePos desired_plane_pos) +{ + exynosLayerMngHWLayerPtr return_layer = NULL; + EXYNOSLayerMngPtr pLYRM = p_lyr_client->pLYRM; + ScrnInfoPtr pScrn = pLYRM->pScrn; + exynosLayerClientPtr current_layer_owner = NULL; + + /* Need any layer for annexing */ + if (desired_output == LAYER_OUTPUT_MAX && desired_plane_pos == PLANE_MAX) { + int i; + + for (i = 0; i < pLYRM->count_of_layers; i++) { + if (pLYRM->array_p_layers[i]->owner != p_lyr_client->stamp) { + current_layer_owner = + _findLayerClient(pLYRM->array_p_layers[i]->owner); + if (!current_layer_owner) { + XDBG_NEVER_GET_HERE(MLYRM); + return_layer = pLYRM->array_p_layers[i]; + break; + } + else if (current_layer_owner->lyr_client_priority < + p_lyr_client->lyr_client_priority) { + EXYNOSLayerOutput temp_output; + EXYNOSLayerMngPlanePos temp_plane_pos; + + XDBG_RETURN_VAL_IF_FAIL(_exynosLayerMngFindPlaneByLayer + (pLYRM->array_p_layers[i], + &temp_output, &temp_plane_pos), + NULL); + XDBG_DEBUG(MLYRM, + "Used other plane %p of layer client %s will be annex\n", + pLYRM->array_p_layers[i], + current_layer_owner->lyr_client_name); + pLYRM->array_p_layers[i]->owner = p_lyr_client->stamp; /* For callback */ + EXYNOSLayerMngEventCallbackDataRec callback_data = + {.annex_callback = {.lpos = + PPOSCONV(temp_plane_pos),.output = + temp_output, + .lyr_client_id = + current_layer_owner->stamp} + }; + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_ANNEX, + &callback_data); + exynosLayerHide(pLYRM->array_p_layers[i]->hwlayer); + layer_table[temp_output][temp_plane_pos].layer = NULL; + pLYRM->array_p_layers[i]->owner = 0; + return_layer = pLYRM->array_p_layers[i]; + break; + } + } + } + } + else { + XDBG_RETURN_VAL_IF_FAIL(desired_output >= LAYER_OUTPUT_LCD + && desired_output < LAYER_OUTPUT_MAX, NULL); + XDBG_RETURN_VAL_IF_FAIL(desired_plane_pos >= PLANE_LOWER2 + && desired_plane_pos < PLANE_MAX, NULL); + exynosLayerMngHWLayerPtr desired_layer = + layer_table[desired_output][desired_plane_pos].layer; + XDBG_RETURN_VAL_IF_FAIL(desired_layer != NULL, NULL); + current_layer_owner = _findLayerClient(desired_layer->owner); + if (!current_layer_owner) { + XDBG_NEVER_GET_HERE(MLYRM); + return_layer = desired_layer; + } + else if (current_layer_owner == p_lyr_client) { + XDBG_NEVER_GET_HERE(MLYRM); + return_layer = desired_layer; + } + else if (current_layer_owner->lyr_client_priority < + p_lyr_client->lyr_client_priority) { + XDBG_DEBUG(MLYRM, + "Used plane %p of layer client %s will be annex\n", + desired_layer, current_layer_owner->lyr_client_name); + desired_layer->owner = p_lyr_client->stamp; /* For callback */ + EXYNOSLayerMngEventCallbackDataRec callback_data = + {.annex_callback = {.lpos = + PPOSCONV(desired_plane_pos),.output = + desired_output, + .lyr_client_id = current_layer_owner->stamp} + }; + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_ANNEX, + &callback_data); + exynosLayerHide(desired_layer->hwlayer); + layer_table[desired_output][desired_plane_pos].layer = NULL; + desired_layer->owner = 0; + return_layer = desired_layer; + } + } + + XDBG_DEBUG(MLYRM, "Annex plane %p\n", return_layer); + + return return_layer; +} + +Bool +exynosLayerMngCheckFreePos(EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ + Bool ret = FALSE; + + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX, FALSE); + if (!layer_table[output][LPOSCONV(lpos)].layer && + layer_table[output][LPOSCONV(lpos)].hwpos != INVALID_HWPOS) { + ret = TRUE; + } + return ret; +} + +int +exynosLayerMngGetListOfOwnedPos(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, + EXYNOSLayerPos * p_lpos) +{ + int ret = 0; + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, 0); + EXYNOSLayerMngPlanePos plane_pos; + + for (plane_pos = PLANE_LOWER2; plane_pos < PLANE_MAX; plane_pos++) { + if (layer_table[output][plane_pos].layer) { + if (layer_table[output][plane_pos].layer->owner == lyr_client_id) { + if (p_lpos) + p_lpos[ret] = PPOSCONV(plane_pos); + ret++; + } + } + } + XDBG_DEBUG(MLYRM, "Client:%s used %d planes\n", + p_lyr_client->lyr_client_name, ret); + return ret; +} + +int +exynosLayerMngGetListOfAccessablePos(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, + EXYNOSLayerPos * p_lpos) +{ + + int ret = 0; + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, 0); + EXYNOSLayerMngPtr pLYRM = p_lyr_client->pLYRM; + + XDBG_RETURN_VAL_IF_FAIL(pLYRM != NULL, 0); + int count_of_free_plane = _exynosLayerMngCountOfFreeLayer(pLYRM); + int count_of_annex_plane = + _exynosLayerMngCountOfAnnexLayer(pLYRM, + p_lyr_client->lyr_client_priority); + XDBG_RETURN_VAL_IF_FAIL(count_of_free_plane != -1, 0); + XDBG_RETURN_VAL_IF_FAIL(count_of_annex_plane != -1, 0); + EXYNOSLayerMngPlanePos plane_pos; + + for (plane_pos = PLANE_LOWER2; plane_pos < PLANE_MAX; plane_pos++) { + if (layer_table[output][plane_pos].hwpos == INVALID_HWPOS) + continue; + if (layer_table[output][plane_pos].layer) { + if (layer_table[output][plane_pos].layer->owner == lyr_client_id) { + if (p_lpos) + p_lpos[ret] = PPOSCONV(plane_pos); + ret++; + } + else if (count_of_annex_plane > 0 + && _exynosLayerMngTestAnnexLayer(p_lyr_client, output, + plane_pos)) { + if (p_lpos) + p_lpos[ret] = PPOSCONV(plane_pos); + ret++; + count_of_annex_plane--; + } + } + else { + if (count_of_free_plane != 0) { + if (p_lpos) + p_lpos[ret] = PPOSCONV(plane_pos); + ret++; + count_of_free_plane--; + } + else if (count_of_annex_plane != 0) { + if (p_lpos) + p_lpos[ret] = PPOSCONV(plane_pos); + ret++; + count_of_annex_plane--; + } + } + } + + XDBG_DEBUG(MLYRM, "Client:%s can set %d planes\n", + p_lyr_client->lyr_client_name, ret); + return ret; +} + +static exynosLayerMngHWLayerPtr +_exynosLayerMngNeedPlane(exynosLayerClientPtr p_lyr_client, + EXYNOSLayerOutput output, + EXYNOSLayerMngPlanePos plane_pos) +{ + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, NULL); + XDBG_RETURN_VAL_IF_FAIL(plane_pos >= PLANE_LOWER2 && + plane_pos < PLANE_MAX, NULL); + exynosLayerMngHWLayerPtr search_layer = NULL, ret_layer = NULL; + + search_layer = layer_table[output][plane_pos].layer; + if (search_layer) { + if (search_layer->owner == (EXYNOSLayerMngClientID) p_lyr_client->stamp) { + XDBG_DEBUG(MLYRM, + "Found usable plane %p on output %d, pos %d, owner %s\n", + search_layer, output, plane_pos, + p_lyr_client->lyr_client_name); + ret_layer = search_layer; + } + else { + search_layer = + _exynosLayerMngAnnexLayer(p_lyr_client, output, plane_pos); + if (search_layer) { + XDBG_DEBUG(MLYRM, + "Annex usable plane %p on output %d, pos %d, for owner %s\n", + search_layer, output, plane_pos, + p_lyr_client->lyr_client_name); + ret_layer = search_layer; + } + } + } + else { + EXYNOSLayerMngPtr pLYRM = p_lyr_client->pLYRM; + + XDBG_RETURN_VAL_IF_FAIL(pLYRM != NULL, NULL); + search_layer = _exynosLayerMngFindUnusedLayer(pLYRM); + if (search_layer) { + XDBG_DEBUG(MLYRM, + "Found free plane %p on output %d, pos %d, owner %s\n", + search_layer, output, plane_pos, + p_lyr_client->lyr_client_name); + ret_layer = search_layer; + exynosLayerSetOutput(search_layer->hwlayer, output); + } + else { + search_layer = + _exynosLayerMngAnnexLayer(p_lyr_client, LAYER_OUTPUT_MAX, + PLANE_MAX); + if (search_layer) { + XDBG_DEBUG(MLYRM, "Annex usable plane %p, for owner %s\n", + search_layer, p_lyr_client->lyr_client_name); + ret_layer = search_layer; + exynosLayerSetOutput(search_layer->hwlayer, output); + } + } + } + + if (!ret_layer) { + XDBG_DEBUG(MLYRM, + "Didn't found free plane on output %d, pos %d, for owner %s\n", + output, plane_pos, p_lyr_client->lyr_client_name); + } + return ret_layer; +} + +Bool +exynosLayerMngReservation(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX, FALSE); + if (layer_table[output][LPOSCONV(lpos)].hwpos == INVALID_HWPOS) { + XDBG_ERROR(MLYRM, "Can't use lpos:%d for output:%d\n", lpos, output); + return FALSE; + } + exynosLayerMngHWLayerPtr tunable_layer = + _exynosLayerMngNeedPlane(p_lyr_client, output, LPOSCONV(lpos)); + if (tunable_layer) { + tunable_layer->owner = lyr_client_id; + layer_table[output][LPOSCONV(lpos)].layer = tunable_layer; + XDBG_DEBUG(MLYRM, + "Successful to reserve plane:%p, client:%s, output:%d, ppos:%d\n", + tunable_layer, p_lyr_client->lyr_client_name, output, + LPOSCONV(lpos)); + return TRUE; + } + XDBG_DEBUG(MLYRM, + "Failure to reserve plane:%p, client:%s, output:%d, ppos:%d\n", + tunable_layer, p_lyr_client->lyr_client_name, output, + LPOSCONV(lpos)); + return FALSE; +} + +Bool +exynosLayerMngSet(EXYNOSLayerMngClientID lyr_client_id, int offset_x, + int offset_y, xRectangle *src, xRectangle *dst, + DrawablePtr pDraw, EXYNOSVideoBuf * vbuf, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos, void *end_func, + void *data) +{ + /* TODO auto crop and scale mechanism */ + /* TODO: Rework to set new size of layer */ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, FALSE); + EXYNOSLayerMngPtr pLYRM = p_lyr_client->pLYRM; + + XDBG_RETURN_VAL_IF_FAIL(pLYRM != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(!(vbuf != NULL && pDraw != NULL), FALSE); + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX, FALSE); + if (layer_table[output][LPOSCONV(lpos)].hwpos == INVALID_HWPOS) { + XDBG_ERROR(MLYRM, "Can't use lpos:%d for output:%d\n", lpos, output); + return FALSE; + } + exynosLayerMngHWLayerPtr tunable_layer = + _exynosLayerMngNeedPlane(p_lyr_client, output, LPOSCONV(lpos)); + if (tunable_layer) { + exynosLayerEnableVBlank(tunable_layer->hwlayer, TRUE); + if (src && dst) { + exynosLayerFreezeUpdate(tunable_layer->hwlayer, TRUE); + XDBG_GOTO_IF_FAIL(exynosLayerSetOffset + (tunable_layer->hwlayer, offset_x, offset_y), + bail); + XDBG_GOTO_IF_FAIL(exynosLayerSetOutput + (tunable_layer->hwlayer, output), bail); + XDBG_GOTO_IF_FAIL(exynosLayerSetPos + (tunable_layer->hwlayer, + layer_table[output][LPOSCONV(lpos)].legacy_pos), + bail); + XDBG_GOTO_IF_FAIL(exynosLayerSetRect + (tunable_layer->hwlayer, src, dst), bail); + exynosLayerFreezeUpdate(tunable_layer->hwlayer, FALSE); + } + + if (vbuf) { + XDBG_GOTO_IF_FAIL(exynosLayerSetBuffer + (tunable_layer->hwlayer, vbuf), bail); + } + else if (pDraw) { + XDBG_GOTO_IF_FAIL(exynosLayerSetDraw(tunable_layer->hwlayer, pDraw), + bail); + } + +// vbuf->vblank_handler = end_func; +// vbuf->vblank_user_data = data; + + tunable_layer->owner = lyr_client_id; + layer_table[output][LPOSCONV(lpos)].layer = tunable_layer; + if (!exynosLayerIsVisible(tunable_layer->hwlayer)) { + exynosLayerShow(tunable_layer->hwlayer); + } + else if (exynosLayerIsNeedUpdate(tunable_layer->hwlayer)) { + exynosLayerUpdate(tunable_layer->hwlayer); + } + } + XDBG_DEBUG(MLYRM, + "Successful setup plane:%p, client:%s, output:%d, ppos:%d\n", + tunable_layer, p_lyr_client->lyr_client_name, output, + LPOSCONV(lpos)); + return TRUE; + bail: + XDBG_DEBUG(MLYRM, "Fail setup plane, client:%s, output:%d, ppos:%d\n", + p_lyr_client->lyr_client_name, output, LPOSCONV(lpos)); + return FALSE; +} + +void +exynosLayerMngRelease(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_IF_FAIL(p_lyr_client != NULL); + XDBG_RETURN_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX); + XDBG_RETURN_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX); + EXYNOSLayerMngPtr pLYRM = p_lyr_client->pLYRM; + + XDBG_RETURN_IF_FAIL(pLYRM != NULL); + ScrnInfoPtr pScrn = pLYRM->pScrn; + exynosLayerMngHWLayerPtr tunable_layer = + layer_table[output][LPOSCONV(lpos)].layer; + if (tunable_layer) { + if (tunable_layer->owner != lyr_client_id) { + XDBG_ERROR(MLYRM, + "Can't release plane. Client %s not own this plane %p\n", + p_lyr_client->lyr_client_name, tunable_layer); + exynosLayerClientPtr real_lyr_client = + _findLayerClient(tunable_layer->owner); + XDBG_ERROR(MLYRM, "Owner of plane %p is %s\n", tunable_layer, + real_lyr_client ? real_lyr_client->lyr_client_name : + "NONE"); + } + else { + XDBG_DEBUG(MLYRM, "Client:%s release plane:%p. lpos:%d output:%d\n", + p_lyr_client->lyr_client_name, tunable_layer, lpos, + output); + exynosLayerHide(tunable_layer->hwlayer); + exynosLayerDestroy(tunable_layer->hwlayer); + tunable_layer->hwlayer = + exynosLayerCreate(pScrn, LAYER_OUTPUT_LCD, FOR_LAYER_MNG); + exynosLayerSetPos(tunable_layer->hwlayer, LAYER_NONE); + tunable_layer->owner = 0; + layer_table[output][LPOSCONV(lpos)].layer = NULL; + EXYNOSLayerMngEventCallbackDataRec release_callback_data = + {.release_callback = {.output = output,.lpos = + lpos,.lyr_client_id = lyr_client_id} + }; + int old_count_of_free_layer = + _exynosLayerMngCountOfFreeLayer(pLYRM) - 1; + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_RELEASE, + &release_callback_data); + int new_count_of_free_layer = + _exynosLayerMngCountOfFreeLayer(pLYRM); + + if (new_count_of_free_layer != old_count_of_free_layer) { + EXYNOSLayerMngEventCallbackDataRec counter_callback_data = + {.counter_callback = {.new_count = new_count_of_free_layer} + }; + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_FREE_COUNTER, + &counter_callback_data); + } + } + } + else { + XDBG_DEBUG(MLYRM, "Not found any plane on output %d, lpos %d\n", output, + lpos); + } +} + +Bool +exynosLayerMngClearQueue(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX, FALSE); + exynosLayerClientPtr p_lyr_client = _findLayerClient(lyr_client_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, FALSE); + exynosLayerMngHWLayerPtr tunable_layer = + layer_table[output][LPOSCONV(lpos)].layer; + if (tunable_layer) { + if (tunable_layer->owner != lyr_client_id) { + XDBG_ERROR(MLYRM, + "Can't clear vbuf queue. Client %s not own this plane %p\n", + p_lyr_client->lyr_client_name, tunable_layer); + exynosLayerClientPtr real_lyr_client = + _findLayerClient(tunable_layer->owner); + XDBG_ERROR(MLYRM, "Owner of plane %p is %s\n", tunable_layer, + real_lyr_client ? real_lyr_client->lyr_client_name : + "NONE"); + } + else { + XDBG_DEBUG(MLYRM, + "Client:%s clear vbuf queue plane:%p. lpos:%d output:%d\n", + p_lyr_client->lyr_client_name, tunable_layer, lpos, + output); + exynosLayerClearQueue(tunable_layer->hwlayer); + } + } + else { + XDBG_DEBUG(MLYRM, "Not found any plane on output %d, lpos %d\n", output, + lpos); + } + return TRUE; +} + +Bool +exynosLayerMngSwapPos(EXYNOSLayerMngClientID lyr_client_id1, + EXYNOSLayerOutput output1, EXYNOSLayerPos lpos1, + EXYNOSLayerMngClientID lyr_client_id2, + EXYNOSLayerOutput output2, EXYNOSLayerPos lpos2) +{ +/* TODO: swap between output */ + if (output1 != output2) { + XDBG_ERROR(MLYRM, "Not implemented yet output:%d != output:%d\n", + output1, output2); + return FALSE; + } + XDBG_RETURN_VAL_IF_FAIL(output1 >= LAYER_OUTPUT_LCD && + output1 < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos1) >= PLANE_LOWER2 && + LPOSCONV(lpos1) < PLANE_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(output2 >= LAYER_OUTPUT_LCD && + output2 < LAYER_OUTPUT_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos2) >= PLANE_LOWER2 && + LPOSCONV(lpos2) < PLANE_MAX, FALSE); + exynosLayerClientPtr p_lyr_client1 = _findLayerClient(lyr_client_id1); + exynosLayerClientPtr p_lyr_client2 = _findLayerClient(lyr_client_id2); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client2 != NULL || + p_lyr_client1 != NULL, FALSE); + + if (!layer_table[output1][LPOSCONV(lpos1)].layer && + !layer_table[output2][LPOSCONV(lpos2)].layer) { + XDBG_DEBUG(MLYRM, + "Can't swap. output:%d, lpos:%d and output:%d lpos:%d not set\n", + output1, lpos1, output2, lpos2); + return TRUE; + } + if (!layer_table[output2][LPOSCONV(lpos2)].layer && !p_lyr_client2) { + XDBG_RETURN_VAL_IF_FAIL(_clientIsOwner + (p_lyr_client1, output1, LPOSCONV(lpos1)), + FALSE); + exynosLayerFreezeUpdate(layer_table[output1][LPOSCONV(lpos1)].layer-> + hwlayer, TRUE); + exynosLayerSetPos(layer_table[output1][LPOSCONV(lpos1)].layer->hwlayer, + lpos2); + exynosLayerFreezeUpdate(layer_table[output1][LPOSCONV(lpos1)].layer-> + hwlayer, FALSE); + layer_table[output2][LPOSCONV(lpos2)].layer = + layer_table[output1][LPOSCONV(lpos1)].layer; + layer_table[output1][LPOSCONV(lpos1)].layer = NULL; + EXYNOSLayerMngEventCallbackDataRec callback_data = + {.release_callback = {.output = output1,.lpos = + lpos1,.lyr_client_id = lyr_client_id1} + }; + ScrnInfoPtr pScrn = p_lyr_client1->pLYRM->pScrn; + + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_RELEASE, &callback_data); + } + else if (!layer_table[output1][LPOSCONV(lpos1)].layer && !p_lyr_client1) { + XDBG_RETURN_VAL_IF_FAIL(_clientIsOwner + (p_lyr_client2, output2, LPOSCONV(lpos2)), + FALSE); + exynosLayerFreezeUpdate(layer_table[output2][LPOSCONV(lpos2)].layer-> + hwlayer, TRUE); + exynosLayerSetPos(layer_table[output2][LPOSCONV(lpos2)].layer->hwlayer, + lpos1); + exynosLayerFreezeUpdate(layer_table[output2][LPOSCONV(lpos2)].layer-> + hwlayer, FALSE); + layer_table[output1][LPOSCONV(lpos1)].layer = + layer_table[output2][LPOSCONV(lpos2)].layer; + layer_table[output2][LPOSCONV(lpos2)].layer = NULL; + ScrnInfoPtr pScrn = p_lyr_client2->pLYRM->pScrn; + EXYNOSLayerMngEventCallbackDataRec callback_data = + {.release_callback = {.output = output2,.lpos = + lpos2,.lyr_client_id = lyr_client_id2} + }; + exynosLayerMngEventDispatch(pScrn, EVENT_LAYER_RELEASE, &callback_data); + } + else { + XDBG_RETURN_VAL_IF_FAIL(_clientIsOwner + (p_lyr_client2, output2, LPOSCONV(lpos2)), + FALSE); + XDBG_RETURN_VAL_IF_FAIL(_clientIsOwner + (p_lyr_client1, output1, LPOSCONV(lpos1)), + FALSE); + if (p_lyr_client2->lyr_client_priority != + p_lyr_client1->lyr_client_priority) { + XDBG_ERROR(MLYRM, + "Can't swap Client1:%s:%d and Client2:%s:%d different priority\n", + p_lyr_client1->lyr_client_name, + p_lyr_client2->lyr_client_name, + p_lyr_client1->lyr_client_priority, + p_lyr_client2->lyr_client_priority); + return FALSE; + } + exynosLayerSetPos(layer_table[output2][LPOSCONV(lpos2)].layer->hwlayer, + LAYER_NONE); + exynosLayerSetPos(layer_table[output1][LPOSCONV(lpos1)].layer->hwlayer, + LAYER_NONE); + exynosLayerFreezeUpdate(layer_table[output1][LPOSCONV(lpos1)].layer-> + hwlayer, TRUE); + exynosLayerFreezeUpdate(layer_table[output2][LPOSCONV(lpos2)].layer-> + hwlayer, TRUE); + exynosLayerSetPos(layer_table[output1][LPOSCONV(lpos1)].layer->hwlayer, + lpos2); + exynosLayerSetPos(layer_table[output2][LPOSCONV(lpos2)].layer->hwlayer, + lpos1); + exynosLayerFreezeUpdate(layer_table[output1][LPOSCONV(lpos1)].layer-> + hwlayer, FALSE); + exynosLayerFreezeUpdate(layer_table[output2][LPOSCONV(lpos2)].layer-> + hwlayer, FALSE); + exynosLayerMngHWLayerPtr temp = + layer_table[output1][LPOSCONV(lpos1)].layer; + layer_table[output1][LPOSCONV(lpos1)].layer = + layer_table[output2][LPOSCONV(lpos2)].layer; + layer_table[output2][LPOSCONV(lpos2)].layer = temp; + } + + XDBG_DEBUG(MLYRM, "Swap Client1:%s <-> Client2:%s\n", + p_lyr_client1 ? p_lyr_client1->lyr_client_name : "NULL", + p_lyr_client2 ? p_lyr_client2->lyr_client_name : "NULL"); + XDBG_DEBUG(MLYRM, "output1:%d <-> output2:%d\n", output1, output2); + XDBG_DEBUG(MLYRM, "lpos1:%d <-> lpos2:%d\n", lpos1, lpos2); + return TRUE; +} + +/* Temporary solution */ +EXYNOSLayerPtr +exynosLayerMngTempGetHWLayer(ScrnInfoPtr pScrn, EXYNOSLayerOutput output, + EXYNOSLayerPos lpos) +{ + XDBG_RETURN_VAL_IF_FAIL(output >= LAYER_OUTPUT_LCD && + output < LAYER_OUTPUT_MAX, NULL); + XDBG_RETURN_VAL_IF_FAIL(LPOSCONV(lpos) >= PLANE_LOWER2 && + LPOSCONV(lpos) < PLANE_MAX, NULL); + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, NULL); + EXYNOSLayerMngClientID temp_id = + exynosLayerMngRegisterClient(pScrn, "temp_client", 2); + exynosLayerClientPtr p_lyr_client = _findLayerClient(temp_id); + + XDBG_RETURN_VAL_IF_FAIL(p_lyr_client != NULL, NULL); + exynosLayerMngHWLayerPtr search_layer = + _exynosLayerMngNeedPlane(p_lyr_client, output, LPOSCONV(lpos)); + if (search_layer) { + search_layer->owner = temp_id; + layer_table[output][LPOSCONV(lpos)].layer = search_layer; + exynosLayerFreezeUpdate(search_layer->hwlayer, TRUE); + exynosLayerSetPos(search_layer->hwlayer, lpos); + exynosLayerFreezeUpdate(search_layer->hwlayer, FALSE); + XDBG_DEBUG(MLYRM, + "Allocate plane:%p for client:%s, output:%d, pos:%d\n", + search_layer, p_lyr_client->lyr_client_name, output, + LPOSCONV(lpos)); + return search_layer->hwlayer; + } + XDBG_DEBUG(MLYRM, "Can't find free layer output:%d lpos:%d\n", output, + lpos); + return NULL; +} + +/* Temporary solution */ +Bool +exynosLayerMngTempDestroyHWLayer(EXYNOSLayerPtr hw_layer) +{ + exynosLayerClientPtr current_entry_client_list = + NULL, next_entry_client_list = NULL; + int found_client = 0, break_flag = 0; + + xorg_list_for_each_entry_safe(current_entry_client_list, next_entry_client_list, &client_valid_list, valid_link) { /* Search any client */ + found_client++; + } + if (found_client == 0) + return FALSE; + + EXYNOSLayerOutput output; + EXYNOSLayerMngPlanePos plane_pos; + + for (output = LAYER_OUTPUT_LCD; output < LAYER_OUTPUT_MAX; output++) { + for (plane_pos = PLANE_LOWER2; plane_pos < PLANE_MAX; plane_pos++) { + exynosLayerMngHWLayerPtr search_layer = + layer_table[output][plane_pos].layer; + if (search_layer && search_layer->hwlayer == hw_layer) { + exynosLayerMngRelease(search_layer->owner, output, + PPOSCONV(plane_pos)); + break_flag = 1; + break; + } + } + if (break_flag) + break; + } + + XDBG_DEBUG(MLYRM, "Release Layer %p \n", hw_layer); + return TRUE; +} + +/* Temporary solution */ + +#endif diff --git a/src/crtcconfig/exynos_layer_manager.h b/src/crtcconfig/exynos_layer_manager.h new file mode 100644 index 0000000..eefe8c6 --- /dev/null +++ b/src/crtcconfig/exynos_layer_manager.h @@ -0,0 +1,99 @@ +#ifndef EXYNOS_LAYER_MANAGER_H +#define EXYNOS_LAYER_MANAGER_H +#ifdef LAYER_MANAGER +#include <stdint.h> +#include <X11/Xmd.h> +#include <xorg-server.h> +#include <xf86str.h> +#include <exynos_layer.h> +/* Private struct */ +typedef CARD32 EXYNOSLayerMngClientID; + +#define LYR_ERROR_ID 0 + +typedef enum { + EVENT_LAYER_SHOW = 0, + EVENT_LAYER_ANNEX, + EVENT_LAYER_RELEASE, + EVENT_LAYER_HIDE, + EVENT_LAYER_BUFSET, + EVENT_LAYER_FREE_COUNTER, + EVENT_LAYER_MAX +} EXYNOSLayerMngEventType; + +typedef enum { + PLANE_LOWER2 = 0, + PLANE_LOWER1 = 1, + PLANE_DEFAULT = 2, + PLANE_UPPER = 3, + PLANE_MAX = 4 +} EXYNOSLayerMngPlanePos; + +typedef union { + struct { + void *callback_data; + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t sequence; + } hardware_callback; + struct { + EXYNOSLayerOutput output; + EXYNOSLayerPos lpos; + EXYNOSLayerMngClientID lyr_client_id; + } annex_callback; + struct { + EXYNOSLayerOutput output; + EXYNOSLayerPos lpos; + EXYNOSLayerMngClientID lyr_client_id; + } release_callback; + struct { + int new_count; + } counter_callback; +} EXYNOSLayerMngEventCallbackDataRec, *EXYNOSLayerMngEventCallbackDataPtr; + +typedef void (*LYRMNotifyFunc) (void *user_data, + EXYNOSLayerMngEventCallbackDataPtr + callback_data); + +EXYNOSLayerMngClientID exynosLayerMngRegisterClient(ScrnInfoPtr pScrn, + char *p_client_name, + int priority); +void exynosLayerMngUnRegisterClient(EXYNOSLayerMngClientID lyr_client_id); +Bool exynosLayerMngInit(ScrnInfoPtr pScrn); +void exynosLayerMngDeInit(ScrnInfoPtr pScrn); +void exynosLayerMngAddEvent(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerMngEventType event_type, + LYRMNotifyFunc callback_func, + void *callback_func_user_data); +void exynosLayerMngDelEvent(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerMngEventType event_type, + LYRMNotifyFunc callback_func); +Bool exynosLayerMngSet(EXYNOSLayerMngClientID lyr_client_id, int offset_x, + int offset_y, xRectangle *src, xRectangle *dst, + DrawablePtr pDraw, EXYNOSVideoBuf * vbuf, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos, + void *end_func, void *data); +int exynosLayerMngGetListOfAccessablePos(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, + EXYNOSLayerPos * p_lpos); +void exynosLayerMngRelease(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos); +Bool exynosLayerMngReservation(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos); +Bool exynosLayerMngCheckFreePos(EXYNOSLayerOutput output, EXYNOSLayerPos lpos); +Bool exynosLayerMngSwapPos(EXYNOSLayerMngClientID lyr_client_id1, + EXYNOSLayerOutput output1, EXYNOSLayerPos lpos1, + EXYNOSLayerMngClientID lyr_client_id2, + EXYNOSLayerOutput output2, EXYNOSLayerPos lpos2); +int exynosLayerMngGetListOfOwnedPos(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, + EXYNOSLayerPos * p_lpos); +Bool exynosLayerMngClearQueue(EXYNOSLayerMngClientID lyr_client_id, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos); +/* Temporary solution */ +EXYNOSLayerPtr exynosLayerMngTempGetHWLayer(ScrnInfoPtr pScrn, + EXYNOSLayerOutput output, + EXYNOSLayerPos lpos); +Bool exynosLayerMngTempDestroyHWLayer(EXYNOSLayerPtr hw_layer); +#endif +#endif // EXYNOS_LAYER_MANAGER_H diff --git a/src/crtcconfig/exynos_output.c b/src/crtcconfig/exynos_output.c new file mode 100755 index 0000000..ec867f1 --- /dev/null +++ b/src/crtcconfig/exynos_output.c @@ -0,0 +1,1074 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. +Copyright 2013 Intel Corporation + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <poll.h> + +#include <xorgVersion.h> +#include <tbm_bufmgr.h> +#include <xf86Crtc.h> +#include <xf86DDC.h> +#include <xf86cmap.h> +#include <list.h> +#include <X11/Xatom.h> +#include <X11/extensions/dpmsconst.h> +#include <exynos.h> + +#include "exynos_util.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_prop.h" +#include "exynos_xberc.h" +#include "exynos_layer.h" +#include "exynos_wb.h" +#include "exynos_video_virtual.h" +#include "exynos_video_clone.h" + +static const int subpixel_conv_table[7] = { + 0, + SubPixelUnknown, + SubPixelHorizontalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalRGB, + SubPixelVerticalBGR, + SubPixelNone +}; + +static const char *output_names[] = { + "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", + "TV", + "eDP", + "Virtual", +}; + +#if 0 +static CARD32 +_exynosOutputResumeWbTimeout(OsTimerPtr timer, CARD32 now, pointer arg) +{ + XDBG_RETURN_VAL_IF_FAIL(arg, 0); + + xf86OutputPtr pOutput = (xf86OutputPtr) arg; + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + + pExynos = EXYNOSPTR(pOutput->scrn); + + if (pExynos->resume_timer) { + TimerFree(pExynos->resume_timer); + pExynos->resume_timer = NULL; + } + + exynosDisplaySetDispSetMode(pOutput->scrn, pExynos->set_mode); + pExynos->set_mode = DISPLAY_SET_MODE_OFF; + + return 0; +} +#endif +static void +_exynosOutputAttachEdid(xf86OutputPtr pOutput) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { + return; + } + drmModeConnectorPtr koutput = pOutputPriv->mode_output; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + drmModePropertyBlobPtr edid_blob = NULL; + xf86MonPtr mon = NULL; + int i; + + /* look for an EDID property */ + for (i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr props; + + props = drmModeGetProperty(pExynosMode->fd, koutput->props[i]); + if (!props) + continue; + + if (!(props->flags & DRM_MODE_PROP_BLOB)) { + drmModeFreeProperty(props); + continue; + } + + if (!strcmp(props->name, "EDID")) { + drmModeFreePropertyBlob(edid_blob); + edid_blob = + drmModeGetPropertyBlob(pExynosMode->fd, + koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + + if (edid_blob) { + mon = xf86InterpretEDID(pOutput->scrn->scrnIndex, edid_blob->data); + + if (mon && edid_blob->length > 128) + mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; + } + + xf86OutputSetEDID(pOutput, mon); + + if (edid_blob) + drmModeFreePropertyBlob(edid_blob); +} + +static Bool +_exynosOutputPropertyIgnore(drmModePropertyPtr prop) +{ + if (!prop) + return TRUE; + + /* ignore blob prop */ + if (prop->flags & DRM_MODE_PROP_BLOB) + return TRUE; + + /* ignore standard property */ + if (!strcmp(prop->name, "EDID") || !strcmp(prop->name, "DPMS")) + return TRUE; + + return FALSE; +} + +static xf86OutputStatus +EXYNOSOutputDetect(xf86OutputPtr pOutput) +{ + /* go to the hw and retrieve a new output struct */ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { + return XF86OutputStatusDisconnected; + } + + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + xf86OutputStatus status; + +// char *conn_str[] = {"connected", "disconnected", "unknow"}; + + /* update output */ + drmModeFreeConnector(pOutputPriv->mode_output); + pOutputPriv->mode_output = + drmModeGetConnector(pExynosMode->fd, pOutputPriv->output_id); + XDBG_RETURN_VAL_IF_FAIL(pOutputPriv->mode_output != NULL, + XF86OutputStatusUnknown); + + /* update encoder */ + drmModeFreeEncoder(pOutputPriv->mode_encoder); + pOutputPriv->mode_encoder = + drmModeGetEncoder(pExynosMode->fd, + pOutputPriv->mode_output->encoders[0]); + XDBG_RETURN_VAL_IF_FAIL(pOutputPriv->mode_encoder != NULL, + XF86OutputStatusUnknown); + + if (pExynosMode->unset_connector_type == + pOutputPriv->mode_output->connector_type) { + return XF86OutputStatusDisconnected; + } +#if 0 + XDBG_INFO(MSEC, + "detect : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n", + pOutputPriv->output_id, pOutputPriv->mode_output->connector_type, + conn_str[pOutputPriv->mode_output->connection - 1], + pOutputPriv->mode_encoder->encoder_id, + pOutputPriv->mode_encoder->crtc_id); +#endif + switch (pOutputPriv->mode_output->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + /* unset write-back clone */ + exynosPropUnSetDisplayMode(pOutput); + break; + default: + case DRM_MODE_UNKNOWNCONNECTION: + status = XF86OutputStatusUnknown; + break; + } + return status; +} + +static Bool +EXYNOSOutputModeValid(xf86OutputPtr pOutput, DisplayModePtr pModes) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { +#ifdef NO_CRTC_MODE + if (pModes->type & M_T_DEFAULT) + return MODE_BAD; + return MODE_OK; +#else + return MODE_ERROR; +#endif //NO_CRTC_MODE + } + drmModeConnectorPtr koutput = pOutputPriv->mode_output; + int i; + + /* driver want to remain available modes which is same as mode + supported from drmmode */ +#if NO_CRTC_MODE + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS) +#endif + { + for (i = 0; i < koutput->count_modes; i++) { + if (pModes->HDisplay == koutput->modes[i].hdisplay && + pModes->VDisplay == koutput->modes[i].vdisplay) + return MODE_OK; + } + return MODE_ERROR; + } + + return MODE_OK; +} + +static DisplayModePtr +EXYNOSOutputGetModes(xf86OutputPtr pOutput) +{ + DisplayModePtr Modes = NULL; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { +#ifdef NO_CRTC_MODE + Modes = xf86ModesAdd(Modes, xf86CVTMode(1024, 768, 60, 0, 0)); +#endif + return Modes; + } + + drmModeConnectorPtr koutput = pOutputPriv->mode_output; + int i; + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + DisplayModePtr Mode; + + /* LVDS1 (main LCD) does not provide edid data */ + if (pOutputPriv->mode_output->connector_type != DRM_MODE_CONNECTOR_LVDS) + _exynosOutputAttachEdid(pOutput); + + /* modes should already be available */ + for (i = 0; i < koutput->count_modes; i++) { + Mode = calloc(1, sizeof(DisplayModeRec)); + if (Mode) { + /* generate the fake modes when screen rotation is set */ + if (pExynos->fake_root) + exynosDisplaySwapModeFromKmode(pOutput->scrn, + &koutput->modes[i], Mode); + else + exynosDisplayModeFromKmode(pOutput->scrn, &koutput->modes[i], + Mode); + Modes = xf86ModesAdd(Modes, Mode); + } + } + + return Modes; +} + +static void +EXYNOSOutputDestory(xf86OutputPtr pOutput) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) { + return; + } + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + int i; + + if (pExynos->resume_timer) { + TimerFree(pExynos->resume_timer); + pExynos->resume_timer = NULL; + } + pExynos->set_mode = DISPLAY_SET_MODE_OFF; + + for (i = 0; i < pOutputPriv->num_props; i++) { + drmModeFreeProperty(pOutputPriv->props[i].mode_prop); + free(pOutputPriv->props[i].atoms); + } + free(pOutputPriv->props); + + drmModeFreeEncoder(pOutputPriv->mode_encoder); + drmModeFreeConnector(pOutputPriv->mode_output); + xorg_list_del(&pOutputPriv->link); + free(pOutputPriv); + + pOutput->driver_private = NULL; +} + +static void +EXYNOSOutputDpms(xf86OutputPtr pOutput, int dpms) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) + return; + drmModeConnectorPtr koutput = pOutputPriv->mode_output; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + int old_dpms = pOutputPriv->dpms_mode; + int i; + + if (!strcmp(pOutput->name, "Virtual1") || + !strcmp(pOutput->name, "HDMI1") || !strcmp(pOutput->name, "DUMMY1")) + return; + + if (dpms == DPMSModeSuspend) + return; + + for (i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr props; + + props = drmModeGetProperty(pExynosMode->fd, koutput->props[i]); + if (!props) + continue; + + if ((old_dpms == DPMSModeStandby && dpms == DPMSModeOn) || + (old_dpms == DPMSModeOn && dpms == DPMSModeStandby)) { + if (!strcmp(props->name, "panel")) { + int value = (dpms == DPMSModeStandby) ? 1 : 0; + + drmModeConnectorSetProperty(pExynosMode->fd, + pOutputPriv->output_id, + props->prop_id, value); + pOutputPriv->dpms_mode = dpms; + drmModeFreeProperty(props); + XDBG_INFO(MDPMS, "panel '%s'\n", (value) ? "OFF" : "ON"); + return; + } + } + else if (!strcmp(props->name, "DPMS")) { + int _tmp_dpms = dpms; + + switch (dpms) { + case DPMSModeStandby: + case DPMSModeOn: + if (pOutputPriv->isLcdOff == FALSE) { + drmModeFreeProperty(props); + return; + } + /* lcd on */ + XDBG_INFO(MDPMS, "\t Reqeust DPMS ON (%s)\n", pOutput->name); + _tmp_dpms = DPMSModeOn; + pOutputPriv->isLcdOff = FALSE; + + if (!strcmp(pOutput->name, "LVDS1")) { + pExynos->isLcdOff = FALSE; +#if 0 + /* if wb need to be started, start wb after timeout. */ + if (pExynos->set_mode == DISPLAY_SET_MODE_CLONE) { + pExynos->resume_timer = TimerSet(pExynos->resume_timer, + 0, 30, + _exynosOutputResumeWbTimeout, + pOutput); + } + + exynosVideoDpms(pOutput->scrn, TRUE); + exynosVirtualVideoDpms(pOutput->scrn, TRUE); +#endif + } + + /* accessibility */ + EXYNOSCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; + + if (pCrtcPriv->screen_rotate_degree > 0) + exynosCrtcEnableScreenRotate(pOutput->crtc, TRUE); + else + exynosCrtcEnableScreenRotate(pOutput->crtc, FALSE); + if (pCrtcPriv->bAccessibility || + pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo src_bo = pCrtcPriv->front_bo; + tbm_bo dst_bo = pCrtcPriv->accessibility_back_bo; + + if (!exynosCrtcExecAccessibility + (pOutput->crtc, src_bo, dst_bo)) { + XDBG_ERROR(MDPMS, + "Fail execute accessibility(output name, %s)\n", + pOutput->name); + } + } +#if 0 + /* set current fb to crtc */ + if (!exynosCrtcApply(pOutput->crtc)) { + XDBG_ERROR(MDPMS, "Fail crtc apply(output name, %s)\n", + pOutput->name); + } +#endif + if (!strcmp(pOutput->name, "LVDS1")) { +#ifdef HAVE_HWC_H + if (pExynos->use_hwc && pExynos->hwc_active) + exynosHwcUpdate(pOutput->scrn); +#endif + } + + if (pExynos->set_mode == DISPLAY_SET_MODE_MIRROR) { + /* start wb if wb is working. */ + EXYNOSCloneVideoSetDPMS(pOutput->scrn, TRUE); + } + + break; + case DPMSModeOff: + if (pOutputPriv->isLcdOff == TRUE) { + drmModeFreeProperty(props); + return; + } + /* lcd off */ + XDBG_INFO(MDPMS, "\t Reqeust DPMS OFF (%s)\n", pOutput->name); + _tmp_dpms = DPMSModeOff; + pOutputPriv->isLcdOff = TRUE; + exynosCrtcEnableScreenRotate(pOutput->crtc, FALSE); + + if (!strcmp(pOutput->name, "LVDS1")) { + pExynos->isLcdOff = TRUE; +#if 0 + exynosVideoDpms(pOutput->scrn, FALSE); +//#ifdef HAVE_HWC_H +// if (pExynos->use_hwc) +// EXYNOSHwcSetDrawables (pOutput->scrn->pScreen, NULL, NULL, NULL, 0); +//#endif + exynosVirtualVideoDpms(pOutput->scrn, FALSE); + + if (pExynos->resume_timer) { + TimerFree(pExynos->resume_timer); + drmModeFreeProperty(props); + pExynos->resume_timer = NULL; + return; + } + + /* keep previous pExynosMode's set_mode. */ + pExynos->set_mode = + exynosDisplayGetDispSetMode(pOutput->scrn); + + if (pExynos->set_mode == DISPLAY_SET_MODE_CLONE || + pExynos->set_mode == DISPLAY_SET_MODE_EXT) { + /* stop wb if wb is working. */ + exynosDisplaySetDispSetMode(pOutput->scrn, + DISPLAY_SET_MODE_OFF); + } +#endif + if (pExynos->set_mode == DISPLAY_SET_MODE_MIRROR) { + /* stop wb if wb is working. */ + EXYNOSCloneVideoSetDPMS(pOutput->scrn, FALSE); + } + } + + break; + default: + drmModeFreeProperty(props); + return; + } + + drmModeConnectorSetProperty(pExynosMode->fd, + pOutputPriv->output_id, + props->prop_id, _tmp_dpms); + + XDBG_INFO(MDPMS, "\t Success DPMS request (%s)\n", pOutput->name); + + pOutputPriv->dpms_mode = _tmp_dpms; + drmModeFreeProperty(props); + return; + } + + drmModeFreeProperty(props); + } +} + +static void +EXYNOSOutputCreateReaources(xf86OutputPtr pOutput) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) + return; + drmModeConnectorPtr mode_output = pOutputPriv->mode_output; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + int i, j, err; + + pOutputPriv->props = + calloc(mode_output->count_props, sizeof(EXYNOSPropertyRec)); + if (!pOutputPriv->props) + return; + + pOutputPriv->num_props = 0; + for (i = j = 0; i < mode_output->count_props; i++) { + drmModePropertyPtr drmmode_prop; + + drmmode_prop = + drmModeGetProperty(pExynosMode->fd, mode_output->props[i]); + if (_exynosOutputPropertyIgnore(drmmode_prop)) { + drmModeFreeProperty(drmmode_prop); + continue; + } + + pOutputPriv->props[j].mode_prop = drmmode_prop; + pOutputPriv->props[j].value = mode_output->prop_values[i]; + j++; + } + pOutputPriv->num_props = j; + + for (i = 0; i < pOutputPriv->num_props; i++) { + EXYNOSPropertyPtr p = &pOutputPriv->props[i]; + drmModePropertyPtr drmmode_prop = p->mode_prop; + + if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { + INT32 range[2]; + + p->num_atoms = 1; + p->atoms = calloc(p->num_atoms, sizeof(Atom)); + if (!p->atoms) + continue; + + p->atoms[0] = + MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); + range[0] = drmmode_prop->values[0]; + range[1] = drmmode_prop->values[1]; + err = RRConfigureOutputProperty(pOutput->randr_output, p->atoms[0], + FALSE, TRUE, + drmmode_prop->flags & + DRM_MODE_PROP_IMMUTABLE ? TRUE : + FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pOutput->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + err = RRChangeOutputProperty(pOutput->randr_output, p->atoms[0], + XA_INTEGER, 32, PropModeReplace, 1, + &p->value, FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pOutput->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { + p->num_atoms = drmmode_prop->count_enums + 1; + p->atoms = calloc(p->num_atoms, sizeof(Atom)); + if (!p->atoms) + continue; + + p->atoms[0] = + MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); + for (j = 1; j <= drmmode_prop->count_enums; j++) { + struct drm_mode_property_enum *e = &drmmode_prop->enums[j - 1]; + + p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); + } + + err = RRConfigureOutputProperty(pOutput->randr_output, p->atoms[0], + FALSE, FALSE, + drmmode_prop->flags & + DRM_MODE_PROP_IMMUTABLE ? TRUE : + FALSE, p->num_atoms - 1, + (INT32 *) &p->atoms[1]); + if (err != 0) { + xf86DrvMsg(pOutput->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + + for (j = 0; j < drmmode_prop->count_enums; j++) + if (drmmode_prop->enums[j].value == p->value) + break; + /* there's always a matching value */ + err = RRChangeOutputProperty(pOutput->randr_output, p->atoms[0], + XA_ATOM, 32, PropModeReplace, 1, + &p->atoms[j + 1], FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pOutput->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (p->atoms) + free(p->atoms); + } +} + +static Bool +EXYNOSOutputSetProperty(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + EXYNOSOutputPrivPtr pOutputPriv = output->driver_private; + + if (pOutputPriv == NULL) + return TRUE; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + int i; + + //EXYNOSOutputDpms(output, DPMSModeStandby); + + for (i = 0; i < pOutputPriv->num_props; i++) { + EXYNOSPropertyPtr p = &pOutputPriv->props[i]; + + if (p->atoms[0] != property) + continue; + + if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { + uint32_t val; + + if (value->type != XA_INTEGER || value->format != 32 || + value->size != 1) + return FALSE; + val = *(uint32_t *) value->data; + + drmModeConnectorSetProperty(pExynosMode->fd, pOutputPriv->output_id, + p->mode_prop->prop_id, (uint64_t) val); + return TRUE; + } + else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { + Atom atom; + const char *name; + int j; + + if (value->type != XA_ATOM || value->format != 32 || + value->size != 1) + return FALSE; + memcpy(&atom, value->data, 4); + name = NameForAtom(atom); + XDBG_RETURN_VAL_IF_FAIL((name != NULL), FALSE); + + /* search for matching name string, then set its value down */ + for (j = 0; j < p->mode_prop->count_enums; j++) { + if (!strcmp(p->mode_prop->enums[j].name, name)) { + drmModeConnectorSetProperty(pExynosMode->fd, + pOutputPriv->output_id, + p->mode_prop->prop_id, + p->mode_prop->enums[j].value); + return TRUE; + } + } + return FALSE; + } + } + + /* We didn't recognise this property, just report success in order + * to allow the set to continue, otherwise we break setting of + * common properties like EDID. + */ + /* set the hidden properties : features for exynos debugging */ + /* TODO : xberc can works on only LVDS????? */ +#ifdef NO_CRTC_MODE + if ((pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA) + || (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) || + (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS)) +#else + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS) +#endif + { + if (exynosPropSetLvdsFunc(output, property, value)) + return TRUE; + + if (exynosPropSetFbVisible(output, property, value)) + return TRUE; + + if (exynosPropSetVideoOffset(output, property, value)) + return TRUE; + + if (exynosPropSetScreenRotate(output, property, value)) + return TRUE; + + /* set the property for the display mode */ + if (exynosPropSetDisplayMode(output, property, value)) + return TRUE; + + if (exynosXbercSetProperty(output, property, value)) + return TRUE; + } + + return TRUE; +} + +static Bool +EXYNOSOutputGetProperty(xf86OutputPtr pOutput, Atom property) +{ + return FALSE; +} + +static const xf86OutputFuncsRec exynos_output_funcs = { + .create_resources = EXYNOSOutputCreateReaources, +#ifdef RANDR_12_INTERFACE + .set_property = EXYNOSOutputSetProperty, + .get_property = EXYNOSOutputGetProperty, +#endif + .dpms = EXYNOSOutputDpms, +#if 0 + .save = drmmode_crt_save, + .restore = drmmode_crt_restore, + .mode_fixup = drmmode_crt_mode_fixup, + .prepare = exynos_output_prepare, + .mode_set = drmmode_crt_mode_set, + .commit = exynos_output_commit, +#endif + .detect = EXYNOSOutputDetect, + .mode_valid = EXYNOSOutputModeValid, + + .get_modes = EXYNOSOutputGetModes, + .destroy = EXYNOSOutputDestory +}; + +Bool +exynosOutputDrmUpdate(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + Bool ret = TRUE; + int i; + + for (i = 0; i < pExynosMode->mode_res->count_connectors; i++) { +#ifdef NO_CRTC_MODE + ret = TRUE; +#endif + EXYNOSOutputPrivPtr pCur = NULL, pNext = NULL, pOutputPriv = NULL; + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + char *conn_str[] = { "connected", "disconnected", "unknow" }; + + xorg_list_for_each_entry_safe(pCur, pNext, &pExynosMode->outputs, link) { + if (pCur->output_id == pExynosMode->mode_res->connectors[i]) { + pOutputPriv = pCur; + break; + } + } + + if (!pOutputPriv) { +#ifdef NO_CRTC_MODE + continue; +#else + ret = FALSE; + break; +#endif + } +#ifdef NO_CRTC_MODE + if (pOutputPriv->is_dummy == TRUE) { + continue; + } + pOutputPriv->pOutput->crtc = NULL; +#endif + koutput = drmModeGetConnector(pExynosMode->fd, + pExynosMode->mode_res->connectors[i]); + if (!koutput) { +#ifdef NO_CRTC_MODE + continue; +#else + ret = FALSE; + break; +#endif + } + + kencoder = drmModeGetEncoder(pExynosMode->fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); +#ifdef NO_CRTC_MODE + continue; +#else + ret = FALSE; + break; +#endif + } + + if (pOutputPriv->mode_output) { + drmModeFreeConnector(pOutputPriv->mode_output); + pOutputPriv->mode_output = NULL; + } + pOutputPriv->mode_output = koutput; + + if (pOutputPriv->mode_encoder) { + drmModeFreeEncoder(pOutputPriv->mode_encoder); + pOutputPriv->mode_encoder = NULL; + } + pOutputPriv->mode_encoder = kencoder; +#ifdef NO_CRTC_MODE + EXYNOSCrtcPrivPtr crtc_ref = NULL, crtc_next = NULL; + + xorg_list_for_each_entry_safe(crtc_ref, crtc_next, &pExynosMode->crtcs, + link) { + if (pOutputPriv->mode_encoder->crtc_id == + crtc_ref->mode_crtc->crtc_id) { + if (pOutputPriv->mode_output->connection == DRM_MODE_CONNECTED) + pOutputPriv->pOutput->crtc = crtc_ref->pCrtc; + else { + exynosOutputDpmsSet(pOutputPriv->pOutput, DPMSModeOff); + drmModeSetCrtc(pExynosMode->fd, + pOutputPriv->mode_encoder->crtc_id, 0, 0, 0, + NULL, 0, NULL); + pOutputPriv->pOutput->crtc = NULL; + } + } + } +#endif + XDBG_INFO(MSEC, + "drm update : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n", + pExynosMode->mode_res->connectors[i], koutput->connector_type, + conn_str[pOutputPriv->mode_output->connection - 1], + kencoder->encoder_id, kencoder->crtc_id); +#ifdef NO_CRTC_MODE + /* Does these need to update? */ + pOutputPriv->pOutput->mm_width = koutput->mmWidth; + pOutputPriv->pOutput->mm_height = koutput->mmHeight; + pOutputPriv->pOutput->possible_crtcs = kencoder->possible_crtcs; + pOutputPriv->pOutput->possible_clones = kencoder->possible_clones; +#endif + } +#ifdef NO_CRTC_MODE + EXYNOSCrtcPrivPtr crtc_ref = NULL, crtc_next = NULL; + + xorg_list_for_each_entry_safe(crtc_ref, crtc_next, &pExynosMode->crtcs, + link) { + crtc_ref->pCrtc->enabled = xf86CrtcInUse(crtc_ref->pCrtc); + } + xf86DisableUnusedFunctions(pScrn); + pExynos->isCrtcOn = exynosCrtcCheckInUseAll(pScrn); +#else + if (!ret) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm(output) update error. (%s)\n", strerror(errno)); +#endif + return ret; +} + +#if 0 +Bool +exynosOutputDummyInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, Bool late) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr pOutput; + xf86CrtcPtr pCrtc; + RROutputPtr clones[32]; + RRCrtcPtr crtcs[32]; + char buf[80]; + int i, len; + + if (pExynosMode->num_dummy_output >= 32) + return FALSE; + + XDBG_DEBUG(MDISP, "(late=%d, num_dummy=%d)\n", late, + pExynosMode->num_dummy_output + 1); + + len = sprintf(buf, "DUMMY%d", pExynosMode->num_dummy_output + 1); + pOutput = xf86OutputCreate(pScrn, &exynos_output_funcs, buf); + if (!pOutput) { + return FALSE; + } + + pCrtc = exynosCrtcDummyInit(pScrn); + + if (pCrtc == NULL) { + xf86OutputDestroy(pOutput); + return FALSE; + } + + pOutput->mm_width = 0; + pOutput->mm_height = 0; + pOutput->interlaceAllowed = FALSE; + pOutput->subpixel_order = SubPixelNone; + + pOutput->possible_crtcs = ~((1 << pExynosMode->num_real_crtc) - 1); + pOutput->possible_clones = ~((1 << pExynosMode->num_real_output) - 1); + + if (late) { + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + + pCrtc->randr_crtc = RRCrtcCreate(pScreen, pCrtc); + pOutput->randr_output = RROutputCreate(pScreen, buf, len, pOutput); + if (pCrtc->randr_crtc == NULL || pOutput->randr_output == NULL) { + xf86OutputDestroy(pOutput); + xf86CrtcDestroy(pCrtc); + return FALSE; + } + + RRPostPendingProperties(pOutput->randr_output); + + for (i = pExynosMode->num_real_output; i < xf86_config->num_output; i++) + clones[i - pExynosMode->num_real_output] = + xf86_config->output[i]->randr_output; + XDBG_RETURN_VAL_IF_FAIL(i - pExynosMode->num_real_output == + pExynosMode->num_dummy_output + 1, FALSE); + + for (i = pExynosMode->num_real_crtc; i < xf86_config->num_crtc; i++) + crtcs[i - pExynosMode->num_real_crtc] = + xf86_config->crtc[i]->randr_crtc; + XDBG_RETURN_VAL_IF_FAIL(i - pExynosMode->num_real_crtc == + pExynosMode->num_dummy_output + 1, FALSE); + + for (i = pExynosMode->num_real_output; i < xf86_config->num_output; i++) { + RROutputPtr rr_output = xf86_config->output[i]->randr_output; + + if (!RROutputSetCrtcs + (rr_output, crtcs, pExynosMode->num_dummy_output + 1) || + !RROutputSetClones(rr_output, clones, + pExynosMode->num_dummy_output + 1)) + goto err; + } + + RRCrtcSetRotations(pCrtc->randr_crtc, RR_Rotate_All | RR_Reflect_All); + } + + pExynosMode->num_dummy_output++; + return TRUE; + + err: + for (i = 0; i < xf86_config->num_output; i++) { + pOutput = xf86_config->output[i]; + if (pOutput->driver_private) + continue; + + xf86OutputDestroy(pOutput); + } + + for (i = 0; i < xf86_config->num_crtc; i++) { + pCrtc = xf86_config->crtc[i]; + if (pCrtc->driver_private) + continue; + xf86CrtcDestroy(pCrtc); + } + pExynosMode->num_dummy_output = -1; + return FALSE; +} +#endif //NO_CRTC_MODE +void +exynosOutputInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num) +{ + xf86OutputPtr pOutput; + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + EXYNOSOutputPrivPtr pOutputPriv; + const char *output_name; + char name[32]; + + koutput = drmModeGetConnector(pExynosMode->fd, + pExynosMode->mode_res->connectors[num]); + if (!koutput) + return; + + kencoder = drmModeGetEncoder(pExynosMode->fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); + return; + } + + if (koutput->connector_type < ARRAY_SIZE(output_names)) + output_name = output_names[koutput->connector_type]; + else + output_name = "UNKNOWN"; + snprintf(name, 32, "%s%d", output_name, koutput->connector_type_id); + + pOutput = xf86OutputCreate(pScrn, &exynos_output_funcs, name); + if (!pOutput) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + pOutputPriv = calloc(sizeof(EXYNOSOutputPrivRec), 1); + if (!pOutputPriv) { + xf86OutputDestroy(pOutput); + drmModeFreeConnector(koutput); + drmModeFreeEncoder(kencoder); + return; + } + + pOutputPriv->output_id = pExynosMode->mode_res->connectors[num]; + pOutputPriv->mode_output = koutput; + pOutputPriv->mode_encoder = kencoder; + pOutputPriv->pExynosMode = pExynosMode; + + pOutput->mm_width = koutput->mmWidth; + pOutput->mm_height = koutput->mmHeight; + + pOutput->subpixel_order = subpixel_conv_table[koutput->subpixel]; + pOutput->driver_private = pOutputPriv; + + pOutput->possible_crtcs = kencoder->possible_crtcs; + pOutput->possible_clones = kencoder->possible_clones; + pOutput->interlaceAllowed = TRUE; + + pOutputPriv->pOutput = pOutput; + /* TODO : soolim : management crtc privates */ + xorg_list_add(&pOutputPriv->link, &pExynosMode->outputs); +#ifdef NO_CRTC_MODE + ++(pExynosMode->num_real_output); +#endif +} + +int +exynosOutputDpmsStatus(xf86OutputPtr pOutput) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv == NULL) + return 0; + return pOutputPriv->dpms_mode; +} + +void +exynosOutputDpmsSet(xf86OutputPtr pOutput, int mode) +{ + EXYNOSOutputDpms(pOutput, mode); +} + +EXYNOSOutputPrivPtr +exynosOutputGetPrivateForConnType(ScrnInfoPtr pScrn, int connect_type) +{ + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + int i; + + for (i = 0; i < pExynosMode->mode_res->count_connectors; i++) { + EXYNOSOutputPrivPtr pCur = NULL, pNext = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &pExynosMode->outputs, link) { + drmModeConnectorPtr koutput = pCur->mode_output; + + if (koutput && koutput->connector_type == connect_type) + return pCur; + } + } +#ifndef NO_CRTC_MODE + XDBG_ERROR(MSEC, "no output for connect_type(%d) \n", connect_type); +#endif + return NULL; +} diff --git a/src/crtcconfig/sec_output.h b/src/crtcconfig/exynos_output.h index 7b9b107..cb8bc8a 100644 --- a/src/crtcconfig/sec_output.h +++ b/src/crtcconfig/exynos_output.h @@ -31,16 +31,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef __SEC_OUTPUT_H__ #define __SEC_OUTPUT_H__ -#include "sec_display.h" +#include "exynos_display.h" -typedef struct _secOutputPriv -{ - SECModePtr pSecMode; +#ifndef RR_Rotate_All +#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) +#endif //RR_Rotate_All +#ifndef RR_Reflect_All +#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y) +#endif //RR_Reflect_All + +typedef struct _exynosOutputPriv { + EXYNOSModePtr pExynosMode; int output_id; drmModeConnectorPtr mode_output; drmModeEncoderPtr mode_encoder; int num_props; - SECPropertyPtr props; + EXYNOSPropertyPtr props; void *private_data; Bool isLcdOff; @@ -49,17 +55,21 @@ typedef struct _secOutputPriv int disp_mode; xf86OutputPtr pOutput; + Bool is_dummy; struct xorg_list link; -} SECOutputPrivRec, *SECOutputPrivPtr; - - -void secOutputInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num); -int secOutputDpmsStatus (xf86OutputPtr pOutput); -void secOutputDpmsSet (xf86OutputPtr pOutput, int mode); +} EXYNOSOutputPrivRec, *EXYNOSOutputPrivPtr; -Bool secOutputDrmUpdate (ScrnInfoPtr pScrn); +#if 0 +Bool exynosOutputDummyInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, + Bool late); +#endif +void exynosOutputInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num); +int exynosOutputDpmsStatus(xf86OutputPtr pOutput); +void exynosOutputDpmsSet(xf86OutputPtr pOutput, int mode); -SECOutputPrivPtr secOutputGetPrivateForConnType (ScrnInfoPtr pScrn, int connect_type); +Bool exynosOutputDrmUpdate(ScrnInfoPtr pScrn); -#endif /* __SEC_OUTPUT_H__ */ +EXYNOSOutputPrivPtr exynosOutputGetPrivateForConnType(ScrnInfoPtr pScrn, + int connect_type); +#endif /* __SEC_OUTPUT_H__ */ diff --git a/src/crtcconfig/exynos_plane.c b/src/crtcconfig/exynos_plane.c new file mode 100644 index 0000000..f18d271 --- /dev/null +++ b/src/crtcconfig/exynos_plane.c @@ -0,0 +1,1484 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <sys/ioctl.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <poll.h> + +#include <xorgVersion.h> +#include <tbm_bufmgr.h> +#include <xf86Crtc.h> +#include <xf86DDC.h> +#include <xf86cmap.h> +#include <list.h> +#include <X11/Xatom.h> +#include <X11/extensions/dpmsconst.h> +#include <exynos.h> +#include <exynos/exynos_drm.h> + +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_util.h" +#include "exynos_video_fourcc.h" +#include "exynos_plane.h" +#include "fimg2d.h" + +/* HW restriction */ +#define MIN_WIDTH 32 +#define MIN_HEIGHT 4 + +enum { + PLANE_FB_TYPE_NONE, + PLANE_FB_TYPE_DEFAULT, + PLANE_FB_TYPE_BO, + PLANE_FB_TYPE_MAX +}; + +typedef struct _EXYNOSPlaneAccess { + unsigned int fb_id; + + tbm_bo bo; + + int width; + int height; + + xRectangle src; + xRectangle dst; +} EXYNOSPlaneAccess; + +/* This is structure to manage a added buffer. */ +typedef struct _EXYNOSPlaneFb { + intptr_t id; + + int type; + union { + /* for framebuffer */ + tbm_bo bo; + EXYNOSVideoBuf *vbuf; + } buffer; + + int width; + int height; + + Bool buffer_gone; + + struct xorg_list link; +} EXYNOSPlaneFb; + +typedef struct _EXYNOSPlaneTable { + EXYNOSPlanePrivPtr pPlanePriv; + intptr_t plane_id; + + /* buffers which this plane has */ + struct xorg_list fbs; + EXYNOSPlaneFb *cur_fb; + + /* visibilitiy information */ + Bool visible; + int crtc_id; + int zpos; + xRectangle src; + xRectangle dst; + int conn_type; + + Bool onoff; + Bool in_use; + Bool freeze_update; + + /* accessibility */ + EXYNOSPlaneAccess *access; +} EXYNOSPlaneTable; + +/* table of planes which system has entirely */ +static EXYNOSPlaneTable *plane_table; +static int plane_table_size; + +static EXYNOSPlaneTable *_exynosPlaneTableFind(int plane_id); +static EXYNOSPlaneFb *_exynosPlaneTableFindBuffer(EXYNOSPlaneTable * table, + intptr_t fb_id, tbm_bo bo, + EXYNOSVideoBuf * vbuf); +static Bool _exynosPlaneHideInternal(EXYNOSPlaneTable * table); +static void _exynosPlaneTableFreeBuffer(EXYNOSPlaneTable * table, + EXYNOSPlaneFb * fb); + +static void +_exynosPlaneFreeVbuf(EXYNOSVideoBuf * vbuf, void *data) +{ + intptr_t plane_id = (intptr_t) data; + EXYNOSPlaneTable *table; + EXYNOSPlaneFb *fb; + + table = _exynosPlaneTableFind(plane_id); + XDBG_RETURN_IF_FAIL(table != NULL); + + fb = _exynosPlaneTableFindBuffer(table, 0, NULL, vbuf); + XDBG_RETURN_IF_FAIL(fb != NULL); + + fb->buffer_gone = TRUE; + _exynosPlaneTableFreeBuffer(table, fb); +} + +static EXYNOSPlaneTable * +_exynosPlaneTableFindPos(int crtc_id, int zpos) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(crtc_id > 0, NULL); + + for (i = 0; i < plane_table_size; i++) + if (plane_table[i].crtc_id == crtc_id && plane_table[i].zpos == zpos) + return &plane_table[i]; + + return NULL; +} + +static EXYNOSPlaneTable * +_exynosPlaneTableFind(int plane_id) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(plane_id > 0, NULL); + + for (i = 0; i < plane_table_size; i++) + if (plane_table[i].plane_id == plane_id) + return &plane_table[i]; + + XDBG_TRACE(MPLN, "plane(%d) not found. \n", plane_id); + + return NULL; +} + +static EXYNOSPlaneTable * +_exynosPlaneTableFindEmpty(void) +{ + int i; + + for (i = 0; i < plane_table_size; i++) + if (!plane_table[i].in_use) + return &plane_table[i]; + + return NULL; +} + +static EXYNOSPlaneFb * +_exynosPlaneTableFindBuffer(EXYNOSPlaneTable * table, + intptr_t fb_id, tbm_bo bo, EXYNOSVideoBuf * vbuf) +{ + EXYNOSPlaneFb *fb = NULL, *fb_next = NULL; + + xorg_list_for_each_entry_safe(fb, fb_next, &table->fbs, link) { + if (fb_id > 0) { + if (fb->id == fb_id) + return fb; + } + else if (bo) { + if (fb->type == PLANE_FB_TYPE_BO && fb->buffer.bo == bo) + return fb; + } + else if (vbuf) { + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(vbuf), NULL); + + if (fb->type == PLANE_FB_TYPE_DEFAULT) + if (fb->buffer.vbuf == vbuf && + fb->buffer.vbuf->stamp == vbuf->stamp) + return fb; + } + } + + return NULL; +} + +static void +_exynosPlaneTableFreeBuffer(EXYNOSPlaneTable * table, EXYNOSPlaneFb * fb) +{ + if (table->cur_fb == fb) + return; + + if (fb->type == PLANE_FB_TYPE_BO) { + if (fb->buffer.bo) + tbm_bo_unref(fb->buffer.bo); + } + else { + if (!fb->buffer_gone && fb->buffer.vbuf) + exynosUtilRemoveFreeVideoBufferFunc(fb->buffer.vbuf, + _exynosPlaneFreeVbuf, + (void *) table->plane_id); + } + + xorg_list_del(&fb->link); + + free(fb); +} + +static Bool +_exynosPlaneTableEnsure(ScrnInfoPtr pScrn, int count_planes) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(count_planes > 0, FALSE); + + if (plane_table) { + if (plane_table_size != count_planes) + XDBG_WARNING(MPLN, "%d != %d, need to re-create! \n", + plane_table_size, count_planes); + return TRUE; + } + + plane_table = calloc(sizeof(EXYNOSPlaneTable), count_planes); + XDBG_RETURN_VAL_IF_FAIL(plane_table != NULL, FALSE); + + plane_table_size = count_planes; + + for (i = 0; i < plane_table_size; i++) { + EXYNOSPlaneTable *table = &plane_table[i]; + + table->plane_id = -1; + table->onoff = TRUE; + } + + return TRUE; +} + +static void +_exynosPlaneExecAccessibility(tbm_bo src_bo, int sw, int sh, xRectangle *sr, + tbm_bo dst_bo, int dw, int dh, xRectangle *dr, + Bool bNegative) +{ + G2dImage *srcImg = NULL, *dstImg = NULL; + tbm_bo_handle src_bo_handle = { 0, }; + tbm_bo_handle dst_bo_handle = { 0, }; + G2dColorKeyMode mode; + + mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + src_bo_handle = tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(src_bo_handle.s32 > 0, access_done); + + dst_bo_handle = tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); + XDBG_GOTO_IF_FAIL(dst_bo_handle.s32 > 0, access_done); + + srcImg = g2d_image_create_bo(mode, sw, sh, src_bo_handle.s32, sw * 4); + XDBG_GOTO_IF_FAIL(srcImg != NULL, access_done); + + dstImg = g2d_image_create_bo(mode, dw, dh, dst_bo_handle.s32, dw * 4); + XDBG_GOTO_IF_FAIL(dstImg != NULL, access_done); + + util_g2d_copy_with_scale(srcImg, dstImg, + (int) sr->x, (int) sr->y, sr->width, sr->height, + (int) dr->x, (int) dr->y, dr->width, dr->height, + (int) bNegative); + g2d_exec(); + + access_done: + if (src_bo_handle.s32) + tbm_bo_unmap(src_bo); + if (dst_bo_handle.s32) + tbm_bo_unmap(dst_bo); + if (srcImg) + g2d_image_free(srcImg); + if (dstImg) + g2d_image_free(dstImg); +} + +static Bool +_alignLVDSPlane(xRectanglePtr src, xRectanglePtr dst, + xRectanglePtr aligned_src, xRectanglePtr aligned_dst, + int buf_w, int buf_h, int disp_w, int disp_h) +{ + Bool ret = TRUE; + + aligned_dst->x = dst->x; + aligned_dst->y = dst->y; + aligned_dst->width = dst->width & (~0x1); + aligned_dst->height = dst->height; + aligned_src->x = src->x < 0 ? 0 : src->x; + aligned_src->y = src->y < 0 ? 0 : src->y; + + if ((aligned_src->x + src->width > buf_w) || + (aligned_src->y + src->height > buf_h)) { + XDBG_WARNING(MPLN, + "hide: crop coord x %d y %d w %d h %d is higher than buf_w(%d) buf_h(%d)\n", + aligned_src->x, src->width, aligned_src->y, src->height, + buf_w, buf_h); + return FALSE; + } + + aligned_src->width = src->width & (~0x1); + aligned_src->height = src->height; + + if ((aligned_dst->width < MIN_WIDTH) || (aligned_dst->height < MIN_HEIGHT)) { + XDBG_WARNING(MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n", + aligned_dst->width, aligned_dst->height, buf_w, buf_h); + XDBG_WARNING(MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n", + src->x, src->y, src->width, src->height, + dst->x, dst->y, dst->width, dst->height); + XDBG_WARNING(MPLN, "start(x%d,y%d) end(w%d,h%d)\n", + aligned_dst->x, aligned_dst->y, + aligned_dst->width, aligned_dst->height); + ret = FALSE; + } + + if ((aligned_src->width < MIN_WIDTH) || (aligned_src->height < MIN_HEIGHT)) { + XDBG_WARNING(MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n", + aligned_src->width, aligned_src->height, buf_w, buf_h); + XDBG_WARNING(MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n", + src->x, src->y, src->width, src->height, + dst->x, dst->y, dst->width, dst->height); + XDBG_WARNING(MPLN, "start(x%d,y%d) end(w%d,h%d)\n", + aligned_src->x, aligned_src->y, + aligned_src->width, aligned_src->height); + ret = FALSE; + } + + return ret; +} + +static Bool +_alignHDMIPlane(xRectanglePtr src, xRectanglePtr dst, + xRectanglePtr aligned_src, xRectanglePtr aligned_dst, + int buf_w, int buf_h, int disp_w, int disp_h) +{ + Bool ret = TRUE; + + aligned_dst->x = (dst->x < 0) ? 0 : dst->x; + aligned_dst->y = (dst->y < 0) ? 0 : dst->y; + aligned_dst->width = + (((aligned_dst->x + dst->width) > + disp_w) ? disp_w : (dst->width)) & (~0x1); + aligned_dst->height = + ((aligned_dst->y + dst->height) > disp_h) ? disp_h : (dst->height); + aligned_src->x = (src->x < 0) ? 0 : src->x; + aligned_src->y = (src->y < 0) ? 0 : src->y; + aligned_src->width = + (((aligned_src->x + src->width) > + disp_w) ? disp_w : (src->width)) & (~0x1); + aligned_src->height = + ((aligned_src->y + src->height) > disp_h) ? disp_h : (src->height); + + if ((aligned_dst->width < MIN_WIDTH) || (aligned_dst->height < MIN_HEIGHT)) { + XDBG_WARNING(MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n", + aligned_dst->width, aligned_dst->height, buf_w, buf_h); + XDBG_WARNING(MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n", + src->x, src->y, src->width, src->height, + dst->x, dst->y, dst->width, dst->height); + XDBG_WARNING(MPLN, "start(x%d,y%d) end(w%d,h%d)\n", + aligned_dst->x, aligned_dst->y, + aligned_dst->width, aligned_dst->height); + ret = FALSE; + } + + if ((aligned_src->width < MIN_WIDTH) || (aligned_src->height < MIN_HEIGHT)) { + XDBG_WARNING(MPLN, "hide: %d, %d: buf_w(%d) buf_h(%d)\n", + aligned_src->width, aligned_src->height, buf_w, buf_h); + XDBG_WARNING(MPLN, "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d)\n", + src->x, src->y, src->width, src->height, + dst->x, dst->y, dst->width, dst->height); + XDBG_WARNING(MPLN, "start(x%d,y%d) end(w%d,h%d)\n", + aligned_src->x, aligned_src->y, + aligned_src->width, aligned_src->height); + ret = FALSE; + } + return ret; +} + +static Bool +_check_hw_restriction(ScrnInfoPtr pScrn, int crtc_id, int buf_w, int buf_h, + xRectanglePtr src, xRectanglePtr dst, + xRectanglePtr aligned_src, xRectanglePtr aligned_dst) +{ + /* Kernel manage CRTC status based out output config */ + Bool ret = FALSE; + xf86CrtcPtr pCrtc = exynosCrtcGetByID(pScrn, crtc_id); + + if (pCrtc == NULL) { + XDBG_ERROR(MPLN, "Can't found crtc_id(%d)\n", crtc_id); + return ret; + } + if (!pCrtc->enabled && !pCrtc->active) { + XDBG_ERROR(MPLN, "Current crtc_id(%d) not active\n", crtc_id); + return ret; + } + + int max_w = pCrtc->mode.CrtcHDisplay; + int max_h = pCrtc->mode.CrtcVDisplay; + + if (max_w == 0 || max_h == 0) { + max_w = pScrn->virtualX; + max_h = pScrn->virtualY; + } + switch (exynosCrtcGetConnectType(pCrtc)) { + case DRM_MODE_CONNECTOR_LVDS: + ret = _alignLVDSPlane(src, dst, aligned_src, aligned_dst, + buf_w, buf_h, max_w, max_h); + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + ret = _alignHDMIPlane(src, dst, aligned_src, aligned_dst, + buf_w, buf_h, max_w, max_h); + break; + default: + XDBG_WARNING(MPLN, "Not supported plane for current output %d\n", + exynosCrtcGetConnectType(pCrtc)); + break; + } + + if (buf_w < MIN_WIDTH || buf_w % 2) { + XDBG_WARNING(MPLN, "hide: buf_w(%d) not 2's multiple or less than %d\n", + buf_w, MIN_WIDTH); + ret = FALSE; + } + + if (buf_h < MIN_HEIGHT) { + XDBG_WARNING(MPLN, "hide: buf_h(%d) less than %d\n", buf_h, MIN_HEIGHT); + ret = FALSE; + } +#if 0 + if (src_x > dst_x || ((dst_x - src_x) + buf_w) > max_w) + virtual_screen = TRUE; + else + virtual_screen = FALSE; + + if (!virtual_screen) { + /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */ + if ((end_dst - start_dst) % 2) + end_dst--; + } + else { + /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */ + if (end_dst % 2) + end_dst--; + } + + *new_dst_x = start_dst; + *new_dst_w = end_dst - start_dst; + *new_src_w = end_src - start_src; +// diff = start_dst - dst_x; + *new_src_x = start_src; + + XDBG_RETURN_VAL_IF_FAIL(*new_src_w > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(*new_dst_w > 0, FALSE); + if (src_x != *new_src_x || src_w != *new_src_w || + dst_x != *new_dst_x || dst_w != *new_dst_w) + XDBG_TRACE(MPLN, + " => buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n", + buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, + virtual_screen, start_dst, end_dst); +#endif + XDBG_TRACE(MPLN, + "src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d) ratio_x %f ratio_y %f\n", + src->x, src->y, src->width, src->height, dst->x, dst->y, + dst->width, dst->height, (double) src->width / dst->width, + (double) src->height / dst->height); + if (memcmp(aligned_src, src, sizeof(xRectangle)) + || memcmp(aligned_dst, dst, sizeof(xRectangle))) { + XDBG_TRACE(MPLN, + "===> src(x%d,y%d w%d-h%d) dst(x%d,y%d w%d-h%d) ratio_x %f ratio_y %f\n", + aligned_src->x, aligned_src->y, aligned_src->width, + aligned_src->height, aligned_dst->x, aligned_dst->y, + aligned_dst->width, aligned_dst->height, + (double) aligned_src->width / aligned_dst->width, + (double) aligned_src->height / aligned_dst->height); + } + return ret; +} + +static Bool +_exynosPlaneShowInternal(EXYNOSPlaneTable * table, + EXYNOSPlaneFb * old_fb, EXYNOSPlaneFb * new_fb, + xRectangle *new_src, xRectangle *new_dst, int new_zpos, + Bool need_set_plane) +{ + EXYNOSPtr pExynos; + EXYNOSModePtr pExynosMode; + + XDBG_RETURN_VAL_IF_FAIL(old_fb != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(new_fb != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(new_src != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(new_dst != NULL, FALSE); + xRectangle old_src = table->src; + xRectangle old_dst = table->dst; + int old_zpos = table->zpos; + Bool change_zpos = FALSE; + tbm_bo_handle bo_handle; + + pExynos = EXYNOSPTR(table->pPlanePriv->pScrn); + pExynosMode = table->pPlanePriv->pExynosMode; + +// if (pExynos->isLcdOff) +// { +// XDBG_TRACE (MPLN, "lcd off, can't show : plane(%d) crtc(%d) pos(%d). \n", +// table->plane_id, table->crtc_id, new_zpos); +// return FALSE; +// } + + if (!table->onoff) { + XDBG_TRACE(MPLN, + "plane off, can't show : plane(%d) crtc(%d) pos(%d). \n", + table->plane_id, table->crtc_id, new_zpos); + return FALSE; + } + + /* should set zpos before doing drmModeSetPlane */ + if (new_zpos != old_zpos) { + if (!exynosUtilSetDrmProperty + (pExynosMode, table->plane_id, DRM_MODE_OBJECT_PLANE, "zpos", + new_zpos)) + return FALSE; + + table->zpos = new_zpos; + change_zpos = TRUE; + + XDBG_TRACE(MPLN, "plane(%d) => crtc(%d) zpos(%d)\n", + table->plane_id, table->crtc_id, table->zpos); + } + + if (!table->visible || need_set_plane || + change_zpos || + (!old_fb || (old_fb != new_fb)) || + (memcmp(&old_src, new_src, sizeof(xRectangle))) || + (memcmp(&old_dst, new_dst, sizeof(xRectangle)))) { + xf86CrtcConfigPtr pCrtcConfig = + XF86_CRTC_CONFIG_PTR(table->pPlanePriv->pScrn); + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int c; + + for (c = 0; c < pCrtcConfig->num_crtc; c++) { + xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; + EXYNOSCrtcPrivPtr pTemp = pCrtc->driver_private; + + if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == table->crtc_id) { + pCrtcPriv = pTemp; + break; + } + } + + XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv != NULL, FALSE); + + XDBG_TRACE(MPLN, + "plane(%d) => crtc(%d) fb(%d) (%d,%d %dx%d) => (%d,%d %dx%d) [%d,%d,%c%c%c%c]\n", + table->plane_id, table->crtc_id, new_fb->id, new_src->x, + new_src->y, new_src->width, new_src->height, new_dst->x, + new_dst->y, new_dst->width, new_dst->height, + pCrtcPriv->bAccessibility, new_fb->type, + FOURCC_STR(new_fb->buffer.vbuf->id)); + + if (!pCrtcPriv->bAccessibility || + (new_fb->type == PLANE_FB_TYPE_DEFAULT && + new_fb->buffer.vbuf->id != FOURCC_RGB32)) { +#if 0 + int aligned_src_x = new_src->x; + int aligned_src_w = new_src->width; + int aligned_dst_x = new_dst->x; + int aligned_dst_w = new_dst->width; +#endif + xRectangle aligned_src; + xRectangle aligned_dst; + + if (!_check_hw_restriction(table->pPlanePriv->pScrn, table->crtc_id, + table->cur_fb->width, + table->cur_fb->height, new_src, new_dst, + &aligned_src, &aligned_dst)) { + XDBG_TRACE(MPLN, + "out of range: plane(%d) crtc(%d) pos(%d) crtc(x%d,y%d w%d-h%d)\n", + table->plane_id, table->crtc_id, new_zpos, + new_dst->x, new_dst->y, new_dst->width, + new_dst->height); + XDBG_TRACE(MPLN, "src(x%d,y%d w%d-h%d)\n", new_src->x, + new_src->y, new_src->width, new_src->height); + + _exynosPlaneHideInternal(table); + + return TRUE; + } + + /* Source values are 16.16 fixed point */ + + uint32_t fixed_x = ((unsigned int) aligned_src.x) << 16; + uint32_t fixed_y = ((unsigned int) aligned_src.y) << 16; + uint32_t fixed_w = ((unsigned int) aligned_src.width) << 16; + uint32_t fixed_h = ((unsigned int) aligned_src.height) << 16; + + if (drmModeSetPlane + (pExynosMode->fd, table->plane_id, table->crtc_id, new_fb->id, + 0, aligned_dst.x, aligned_dst.y, aligned_dst.width, + aligned_dst.height, fixed_x, fixed_y, fixed_w, fixed_h)) { + XDBG_ERRNO(MPLN, + "drmModeSetPlane failed. plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", + table->plane_id, table->crtc_id, table->zpos, + new_fb->id, FOURCC_STR(new_fb->buffer.vbuf->id), + new_fb->buffer.vbuf->width, + new_fb->buffer.vbuf->height, aligned_src.x, + aligned_src.y, aligned_src.width, aligned_src.height, + aligned_dst.x, aligned_dst.y, aligned_dst.width, + aligned_dst.height); + + return FALSE; + } + + if (!table->visible) { + XDBG_SECURE(MPLN, + "plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", + table->plane_id, table->crtc_id, table->zpos, + new_fb->id, FOURCC_STR(new_fb->buffer.vbuf->id), + new_fb->buffer.vbuf->width, + new_fb->buffer.vbuf->height, aligned_src.x, + aligned_src.y, aligned_src.width, + aligned_src.height, aligned_dst.x, aligned_dst.y, + aligned_dst.width, aligned_dst.height); + table->visible = TRUE; + } + } + else { + EXYNOSPlaneAccess *access; + xRectangle fb_src = { 0, }; + tbm_bo src_bo; + int old_w = 0, old_h = 0; + + if (!table->access) { + table->access = calloc(1, sizeof(EXYNOSPlaneAccess)); + XDBG_RETURN_VAL_IF_FAIL(table->access != NULL, FALSE); + } + else { + old_w = table->access->width; + old_h = table->access->height; + } + + access = table->access; + + if (pCrtcPriv->bScale) { + float h_ratio = 0.0, v_ratio = 0.0; + xRectangle crop; + + h_ratio = (float) pCrtcPriv->kmode.hdisplay / pCrtcPriv->sw; + v_ratio = (float) pCrtcPriv->kmode.vdisplay / pCrtcPriv->sh; + + fb_src.x = new_src->x; + fb_src.y = new_src->y; + fb_src.width = new_src->width; + fb_src.height = new_src->height; + + CLEAR(crop); + crop.x = pCrtcPriv->sx; + crop.y = pCrtcPriv->sy; + crop.width = pCrtcPriv->sw; + crop.height = pCrtcPriv->sh; + + crop.x -= new_dst->x; + crop.y -= new_dst->y; + crop.x += new_src->x; + crop.y += new_src->y; + exynosUtilRectIntersect(&fb_src, &fb_src, &crop); + + access->dst = *new_dst; + + access->dst.x = new_dst->x; + access->dst.y = new_dst->y; + access->dst.width = new_dst->width; + access->dst.height = new_dst->height; + + CLEAR(crop); + crop.x = pCrtcPriv->sx; + crop.y = pCrtcPriv->sy; + crop.width = pCrtcPriv->sw; + crop.height = pCrtcPriv->sh; + exynosUtilRectIntersect(&access->dst, &access->dst, &crop); + + access->dst.x -= pCrtcPriv->sx; + access->dst.y -= pCrtcPriv->sy; + + access->dst.x *= h_ratio; + access->dst.y *= v_ratio; + access->dst.width *= h_ratio; + access->dst.height *= v_ratio; + + access->width = pCrtcPriv->kmode.hdisplay; + access->height = pCrtcPriv->kmode.vdisplay; + + access->src.x = 0; + access->src.y = 0; + access->src.width = access->dst.width; + access->src.height = access->dst.height; + } + else { + fb_src.x = new_src->x; + fb_src.y = new_src->y; + fb_src.width = new_src->width; + fb_src.height = new_src->height; + + /* hw restriction: 8 bytes */ + new_dst->width &= ~1; + + access->dst.x = new_dst->x; + access->dst.y = new_dst->y; + access->dst.width = new_dst->width; + access->dst.height = new_dst->height; + + access->width = access->dst.width; + access->height = access->dst.height; + + access->src.x = 0; + access->src.y = 0; + access->src.width = access->dst.width; + access->src.height = access->dst.height; + } + + XDBG_DEBUG(MPLN, + "access : accessibility_status(%d) scale(%d) bo(%p) fb(%d) (%d,%d %dx%d) (%dx%d) (%d,%d %dx%d) (%d,%d %dx%d).\n", + pCrtcPriv->accessibility_status, pCrtcPriv->bScale, + access->bo, access->fb_id, fb_src.x, fb_src.y, + fb_src.width, fb_src.height, access->width, + access->height, access->src.x, access->src.y, + access->src.width, access->src.height, access->dst.x, + access->dst.y, access->dst.width, access->dst.height); + + if (!fb_src.width || !fb_src.height || + !access->width || !access->height || + !access->dst.width || !access->dst.height) { + _exynosPlaneHideInternal(table); + + return TRUE; + } + + if (access->bo) { + if (old_w != access->width || old_h != access->height) { + if (table->access->fb_id) { + drmModeRmFB(pExynosMode->fd, table->access->fb_id); + table->access->fb_id = 0; + } + + tbm_bo_unref(table->access->bo); + table->access->bo = NULL; + } + } + + if (!access->bo) { + access->bo = tbm_bo_alloc(pExynos->tbm_bufmgr, + access->width * access->height * 4, + TBM_BO_NONCACHABLE); + XDBG_RETURN_VAL_IF_FAIL(access->bo != NULL, FALSE); + + bo_handle = tbm_bo_get_handle(access->bo, TBM_DEVICE_DEFAULT); + if (drmModeAddFB(pExynosMode->fd, access->width, access->height, + table->pPlanePriv->pScrn->depth, + table->pPlanePriv->pScrn->bitsPerPixel, + access->width * 4, + bo_handle.u32, &access->fb_id)) { + XDBG_ERRNO(MPLN, "drmModeAddFB failed. plane(%d)\n", + table->plane_id); + return FALSE; + } + + XDBG_RETURN_VAL_IF_FAIL(access->fb_id > 0, FALSE); + } + + if (new_fb->type == PLANE_FB_TYPE_DEFAULT) + src_bo = + tbm_bo_import(pExynos->tbm_bufmgr, + new_fb->buffer.vbuf->keys[0]); + else + src_bo = new_fb->buffer.bo; + XDBG_RETURN_VAL_IF_FAIL(src_bo != NULL, FALSE); + + _exynosPlaneExecAccessibility(src_bo, new_fb->width, new_fb->height, + &fb_src, access->bo, access->width, + access->height, &access->src, + pCrtcPriv->accessibility_status); + tbm_bo_unref(src_bo); + xRectangle aligned_src; + xRectangle aligned_dst; + + if (!_check_hw_restriction(table->pPlanePriv->pScrn, table->crtc_id, + access->width, access->height, + &access->src, &access->dst, + &aligned_src, &aligned_dst)) { + XDBG_TRACE(MPLN, + "access : out of range: plane(%d) crtc(%d) pos(%d) crtc(x%d,y%d w%d-h%d)\n", + table->plane_id, table->crtc_id, new_zpos, + access->dst.x, access->dst.y, access->dst.width, + access->dst.height); + XDBG_TRACE(MPLN, "access : src(x%d,y%d w%d-h%d)\n", + access->src.x, access->src.y, access->src.width, + access->src.height); + + _exynosPlaneHideInternal(table); + + return TRUE; + } + + /* Source values are 16.16 fixed point */ + uint32_t fixed_x = ((unsigned int) aligned_src.x) << 16; + uint32_t fixed_y = ((unsigned int) aligned_src.y) << 16; + uint32_t fixed_w = ((unsigned int) aligned_src.width) << 16; + uint32_t fixed_h = ((unsigned int) aligned_src.height) << 16; + + XDBG_DEBUG(MPLN, + "Access plane: fixed:(x%d,y%d w%d-h%d), dst:(x%d,y%d w%d-h%d)\n", + aligned_src.x, aligned_src.y, aligned_src.width, + aligned_src.height, aligned_dst.x, aligned_dst.y, + aligned_dst.width, aligned_dst.height); + + if (drmModeSetPlane + (pExynosMode->fd, table->plane_id, table->crtc_id, + access->fb_id, 0, aligned_dst.x, aligned_dst.y, + aligned_dst.width, aligned_dst.height, fixed_x, fixed_y, + fixed_w, fixed_h)) { + XDBG_ERRNO(MPLN, "drmModeSetPlane failed. \n"); + + return FALSE; + } + if (!table->visible) { + XDBG_SECURE(MPLN, + "plane(%d) crtc(%d) pos(%d) on: access_fb(%d,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", + table->plane_id, table->crtc_id, table->zpos, + access->fb_id, access->width, access->height, + aligned_src.x, aligned_src.y, aligned_src.width, + aligned_src.height, aligned_dst.x, aligned_dst.y, + aligned_dst.width, aligned_dst.height); + table->visible = TRUE; + } + } + + memcpy(&table->src, new_src, sizeof(xRectangle)); + memcpy(&table->dst, new_dst, sizeof(xRectangle)); + } + + return TRUE; +} + +static Bool +_exynosPlaneHideInternal(EXYNOSPlaneTable * table) +{ + EXYNOSPtr pExynos; + EXYNOSModePtr pExynosMode; + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + + if (!table->visible) + return TRUE; + + XDBG_RETURN_VAL_IF_FAIL(table->crtc_id > 0, FALSE); + + pExynos = EXYNOSPTR(table->pPlanePriv->pScrn); + pExynosMode = table->pPlanePriv->pExynosMode; + + if (table->onoff) { + if (drmModeSetPlane(pExynosMode->fd, + table->plane_id, + table->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) { + XDBG_ERRNO(MPLN, + "drmModeSetPlane failed. plane(%d) crtc(%d) zpos(%d) fb(%d)\n", + table->plane_id, table->crtc_id, table->zpos, + table->cur_fb->id); + + return FALSE; + } + } + + if (table->visible) { + XDBG_SECURE(MPLN, + "plane(%d) crtc(%d) zpos(%d) off. lcd(%s) onoff(%d)\n", + table->plane_id, table->crtc_id, table->zpos, + (pExynos->isLcdOff) ? "off" : "on", table->onoff); + table->visible = FALSE; + } + + XDBG_TRACE(MPLN, + "plane(%d) fb(%d) removed from crtc(%d) zpos(%d). LCD(%s) ONOFF(%s).\n", + table->plane_id, table->cur_fb->id, table->crtc_id, table->zpos, + (pExynos->isLcdOff) ? "OFF" : "ON", + (table->onoff) ? "ON" : "OFF"); + + return TRUE; + +} + +void +exynosPlaneInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num) +{ + EXYNOSPlanePrivPtr pPlanePriv; + + XDBG_RETURN_IF_FAIL(pScrn != NULL); + XDBG_RETURN_IF_FAIL(pExynosMode != NULL); + XDBG_RETURN_IF_FAIL(pExynosMode->plane_res != NULL); + XDBG_RETURN_IF_FAIL(pExynosMode->plane_res->count_planes > 0); + + if (!_exynosPlaneTableEnsure(pScrn, pExynosMode->plane_res->count_planes)) + return; + + pPlanePriv = calloc(sizeof(EXYNOSPlanePrivRec), 1); + XDBG_RETURN_IF_FAIL(pPlanePriv != NULL); + + pPlanePriv->mode_plane = drmModeGetPlane(pExynosMode->fd, + pExynosMode->plane_res-> + planes[num]); + if (!pPlanePriv->mode_plane) { + XDBG_ERRNO(MPLN, "drmModeGetPlane failed. plane(%d)\n", + pExynosMode->plane_res->planes[num]); + + free(pPlanePriv); + return; + } + + pPlanePriv->pScrn = pScrn; + pPlanePriv->pExynosMode = pExynosMode; + pPlanePriv->plane_id = pPlanePriv->mode_plane->plane_id; + + plane_table[num].plane_id = pPlanePriv->plane_id; + plane_table[num].pPlanePriv = pPlanePriv; + xorg_list_init(&plane_table[num].fbs); + + xorg_list_add(&pPlanePriv->link, &pExynosMode->planes); +} + +void +exynosPlaneDeinit(ScrnInfoPtr pScrn, EXYNOSPlanePrivPtr pPlanePriv) +{ + int i; + + XDBG_RETURN_IF_FAIL(pScrn != NULL); + XDBG_RETURN_IF_FAIL(pPlanePriv != NULL); + + exynosPlaneFreeId(pPlanePriv->plane_id); + drmModeFreePlane(pPlanePriv->mode_plane); + xorg_list_del(&pPlanePriv->link); + + for (i = 0; i < plane_table_size; i++) + if (plane_table[i].plane_id == pPlanePriv->plane_id) { + plane_table[i].plane_id = -1; + break; + } + + free(pPlanePriv); + + if (plane_table) { + for (i = 0; i < plane_table_size; i++) + if (plane_table[i].plane_id != -1) + return; + + free(plane_table); + plane_table = NULL; + plane_table_size = 0; + XDBG_TRACE(MPLN, "plane_table destroyed. %d\n", plane_table_size); + } +} + +void +exynosPlaneShowAll(int crtc_id) +{ + int i; + + XDBG_TRACE(MPLN, "crtc(%d) \n", crtc_id); + + for (i = 0; i < plane_table_size; i++) { + EXYNOSPlaneTable *table = &plane_table[i]; + + if (!table || !table->in_use || !table->visible || !table->onoff) + continue; + + if (table->crtc_id != crtc_id) + continue; + if (!table->cur_fb) + continue; + if (!_exynosPlaneShowInternal(table, table->cur_fb, table->cur_fb, + &table->src, &table->dst, table->zpos, + TRUE)) { + XDBG_WARNING(MPLN, "_exynosPlaneShowInternal failed. \n"); + } + + XDBG_TRACE(MPLN, "plane(%d) crtc(%d) zpos(%d) on.\n", + table->plane_id, table->crtc_id, table->zpos); + } +} + +intptr_t +exynosPlaneGetID(void) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFindEmpty(); + + if (!table) { + XDBG_ERROR(MPLN, "No avaliable plane ID. %d\n", -1); + return -1; + } + + table->in_use = TRUE; + table->onoff = TRUE; + + XDBG_TRACE(MPLN, "plane(%d). \n", table->plane_id); + + return table->plane_id; +} + +void +exynosPlaneFreeId(intptr_t plane_id) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + EXYNOSPlaneFb *fb = NULL, *fb_next = NULL; + + XDBG_RETURN_IF_FAIL(table != NULL); + + exynosPlaneHide(table->plane_id); + + table->visible = FALSE; + table->crtc_id = 0; + + table->zpos = 0; + memset(&table->src, 0x00, sizeof(xRectangle)); + memset(&table->dst, 0x00, sizeof(xRectangle)); + + table->cur_fb = NULL; + xorg_list_for_each_entry_safe(fb, fb_next, &table->fbs, link) { + _exynosPlaneTableFreeBuffer(table, fb); + } + + if (table->access) { + if (table->access->fb_id) { + EXYNOSModePtr pExynosMode = table->pPlanePriv->pExynosMode; + + if (pExynosMode) + drmModeRmFB(pExynosMode->fd, table->access->fb_id); + } + + if (table->access->bo) + tbm_bo_unref(table->access->bo); + + free(table->access); + table->access = NULL; + } + + table->in_use = FALSE; + table->onoff = TRUE; + + XDBG_TRACE(MPLN, "plane(%d).\n", table->plane_id); +} + +void +exynosPlaneFlushFBId(intptr_t plane_id) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + EXYNOSPlaneFb *fb = NULL, *fb_next = NULL; + + XDBG_RETURN_IF_FAIL(table != NULL); + table->cur_fb = NULL; + xorg_list_for_each_entry_safe(fb, fb_next, &table->fbs, link) { + _exynosPlaneTableFreeBuffer(table, fb); + } +/* Commented, because fails +* Now FBs for accessibility removes in*/ + if (table->access) { + /* if (table->access->fb_id) + { + EXYNOSModePtr pExynosMode = table->pPlanePriv->pExynosMode; + if (pExynosMode) + drmModeRmFB (pExynosMode->fd, table->access->fb_id); + } + */ + if (table->access->bo) + tbm_bo_unref(table->access->bo); + } + + XDBG_TRACE(MPLN, "flush plane(%d).\n", table->plane_id); +} + +Bool +exynosPlaneTrun(intptr_t plane_id, Bool onoff, Bool user) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + +// EXYNOSPtr pExynos; + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + +// pExynos = EXYNOSPTR (table->pPlanePriv->pScrn); + +// if (pExynos->isLcdOff) +// return TRUE; + + onoff = (onoff > 0) ? TRUE : FALSE; + + if (table->onoff == onoff) + return TRUE; + + if (onoff) { + table->onoff = onoff; + + if (!table->visible) { + if (!_exynosPlaneShowInternal(table, table->cur_fb, table->cur_fb, + &table->src, &table->dst, table->zpos, + TRUE)) { + XDBG_WARNING(MPLN, "_exynosPlaneShowInternal failed. \n"); + } + + XDBG_DEBUG(MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", + (user) ? "user" : "Xorg", plane_id, table->crtc_id, + table->zpos, (onoff) ? "ON" : "OFF"); + } + } + else { + if (table->visible) { + if (!_exynosPlaneHideInternal(table)) { + XDBG_WARNING(MPLN, "_exynosPlaneHideInternal failed. \n"); + } + + XDBG_DEBUG(MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", + (user) ? "user" : "Xorg", plane_id, table->crtc_id, + table->zpos, (onoff) ? "ON" : "OFF"); + } + + table->onoff = onoff; + } + + return TRUE; +} + +Bool +exynosPlaneTrunStatus(intptr_t plane_id) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + + return table->onoff; +} + +void +exynosPlaneFreezeUpdate(intptr_t plane_id, Bool enable) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + + XDBG_RETURN_IF_FAIL(table != NULL); + + table->freeze_update = enable; +} + +//Bool +//exynosPlaneRemoveBuffer (intptr_t plane_id, int fb_id) +//{ +// EXYNOSPlaneTable *table; +// EXYNOSPlaneFb *fb; +// +// XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE); +// +// table = _exynosPlaneTableFind (plane_id); +// XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); +// +// fb = _exynosPlaneTableFindBuffer (table, fb_id, NULL, NULL); +// XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE); +// +// _exynosPlaneTableFreeBuffer (table, fb); +// +// XDBG_TRACE (MPLN, "plane(%d) fb(%d). \n", plane_id, fb_id); +// +// return TRUE; +//} + +int +exynosPlaneAddBo(intptr_t plane_id, tbm_bo bo) +{ + EXYNOSPlaneTable *table; + EXYNOSPlaneFb *fb; + intptr_t fb_id = 0; + EXYNOSFbBoDataPtr bo_data = NULL; + int width, height; + + XDBG_RETURN_VAL_IF_FAIL(bo != NULL, 0); + + table = _exynosPlaneTableFind(plane_id); + XDBG_RETURN_VAL_IF_FAIL(table != NULL, 0); + + fb = _exynosPlaneTableFindBuffer(table, 0, bo, NULL); + XDBG_RETURN_VAL_IF_FAIL(fb == NULL, 0); + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void **) &bo_data); + XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, 0); + + fb_id = bo_data->fb_id; + width = bo_data->pos.x2 - bo_data->pos.x1; + height = bo_data->pos.y2 - bo_data->pos.y1; + + XDBG_RETURN_VAL_IF_FAIL(fb_id > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(width > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(height > 0, 0); + + fb = calloc(1, sizeof(EXYNOSPlaneFb)); + XDBG_RETURN_VAL_IF_FAIL(fb != NULL, 0); + + xorg_list_add(&fb->link, &table->fbs); + + fb->type = PLANE_FB_TYPE_BO; + fb->id = fb_id; + fb->width = width; + fb->height = height; + + fb->buffer.bo = tbm_bo_ref(bo); + + XDBG_TRACE(MPLN, "plane(%d) bo(%d,%dx%d)\n", plane_id, + fb_id, fb->width, fb->height); + + return fb->id; +} + +int +exynosPlaneAddBuffer(intptr_t plane_id, EXYNOSVideoBuf * vbuf) +{ + EXYNOSPlaneTable *table; + EXYNOSPlaneFb *fb; + + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(vbuf), 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->fb_id > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->width > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->height > 0, 0); + + table = _exynosPlaneTableFind(plane_id); + XDBG_RETURN_VAL_IF_FAIL(table != NULL, 0); + + fb = _exynosPlaneTableFindBuffer(table, 0, NULL, vbuf); + XDBG_RETURN_VAL_IF_FAIL(fb == NULL, 0); + + fb = calloc(1, sizeof(EXYNOSPlaneFb)); + XDBG_RETURN_VAL_IF_FAIL(fb != NULL, 0); + + xorg_list_add(&fb->link, &table->fbs); + + fb->type = PLANE_FB_TYPE_DEFAULT; + fb->id = vbuf->fb_id; + fb->width = vbuf->width; + fb->height = vbuf->height; + + fb->buffer.vbuf = vbuf; + + exynosUtilAddFreeVideoBufferFunc(vbuf, _exynosPlaneFreeVbuf, + (void *) plane_id); + + XDBG_TRACE(MPLN, "plane(%d) vbuf(%" PRIuPTR ",%d,%dx%d)\n", plane_id, + vbuf->stamp, vbuf->fb_id, vbuf->width, vbuf->height); + + return fb->id; +} + +intptr_t +exynosPlaneGetBuffer(int plane_id, tbm_bo bo, EXYNOSVideoBuf * vbuf) +{ + EXYNOSPlaneTable *table; + EXYNOSPlaneFb *fb; + + table = _exynosPlaneTableFind(plane_id); + XDBG_RETURN_VAL_IF_FAIL(table != NULL, 0); + + fb = _exynosPlaneTableFindBuffer(table, 0, bo, vbuf); + if (!fb) + return 0; + + return fb->id; +} + +void +exynosPlaneGetBufferSize(int plane_id, int fb_id, int *width, int *height) +{ + EXYNOSPlaneTable *table; + EXYNOSPlaneFb *fb; + + table = _exynosPlaneTableFind(plane_id); + XDBG_RETURN_IF_FAIL(table != NULL); + + fb = _exynosPlaneTableFindBuffer(table, fb_id, NULL, NULL); + XDBG_RETURN_IF_FAIL(fb != NULL); + + if (width) + *width = fb->width; + + if (height) + *height = fb->height; +} + +Bool +exynosPlaneAttach(int plane_id, int fb_id, EXYNOSVideoBuf * vbuf) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + EXYNOSPlaneFb *fb; + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + + fb = _exynosPlaneTableFindBuffer(table, fb_id, NULL, vbuf); + XDBG_RETURN_VAL_IF_FAIL(fb != NULL, FALSE); + + table->cur_fb = fb; + + XDBG_DEBUG(MPLN, "plane(%d) fb(%d)\n", plane_id, fb_id); + + return TRUE; +} + +Bool +exynosPlaneIsVisible(int plane_id) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + + return table->visible; +} + +Bool +exynosPlaneShow(int plane_id, int crtc_id, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, + int zpos, Bool need_update) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + EXYNOSPlaneTable *temp; + xRectangle src = { src_x, src_y, src_w, src_h }; + xRectangle dst = { dst_x, dst_y, dst_w, dst_h }; + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(table->cur_fb != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(crtc_id > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(zpos >= 0, FALSE); + + temp = _exynosPlaneTableFindPos(crtc_id, zpos); + + if (!need_update && temp && temp->plane_id != plane_id && temp->visible) { + XDBG_ERROR(MPLN, + "can't change zpos. plane(%d) is at zpos(%d) crtc(%d) \n", + temp->plane_id, temp->zpos, crtc_id); + return FALSE; + } + + if (!table->visible) + table->crtc_id = crtc_id; + else if (table->crtc_id != crtc_id) { + XDBG_ERROR(MPLN, "can't change crtc. plane(%d) is on crtc(%d) \n", + table->plane_id, table->zpos); + return FALSE; + } + + if (!_exynosPlaneShowInternal(table, table->cur_fb, table->cur_fb, + &src, &dst, zpos, need_update)) { + return FALSE; + } + + return TRUE; +} + +Bool +exynosPlaneHide(int plane_id) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + + if (!table->visible) + return TRUE; + + XDBG_TRACE(MPLN, "plane(%d) crtc(%d)\n", table->plane_id, table->crtc_id); + + _exynosPlaneHideInternal(table); + + return TRUE; +} + +Bool +exynosPlaneMove(int plane_id, int x, int y) +{ + EXYNOSPlaneTable *table = _exynosPlaneTableFind(plane_id); + xRectangle dst; + + XDBG_RETURN_VAL_IF_FAIL(table != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(table->cur_fb != NULL, FALSE); + + dst.x = x; + dst.y = y; + dst.width = table->dst.width; + dst.height = table->dst.height; + + if (table->visible && !table->freeze_update) + if (!_exynosPlaneShowInternal(table, table->cur_fb, table->cur_fb, + &table->src, &dst, table->zpos, FALSE)) { + return FALSE; + } + + XDBG_TRACE(MPLN, "plane(%d) moved to (%d,%d)\n", table->plane_id, x, y); + + return TRUE; +} + +char * +exynosPlaneDump(char *reply, int *len) +{ + Bool in_use = FALSE; + int i; + + for (i = 0; i < plane_table_size; i++) + if (plane_table[i].in_use) { + in_use = TRUE; + break; + } + + if (!in_use) + return reply; + + XDBG_REPLY("=================================================\n"); + XDBG_REPLY("plane\tcrtc\tpos\tvisible\tonoff\tfb(w,h)\tsrc\t\tdst\n"); + + for (i = 0; i < plane_table_size; i++) { + if (plane_table[i].in_use) + XDBG_REPLY("%" PRIdPTR "\t%d\t%d\t%d\t%d\t%" PRIdPTR + "(%dx%d)\t%d,%d %dx%d\t%d,%d %dx%d\n", + plane_table[i].plane_id, plane_table[i].crtc_id, + plane_table[i].zpos, plane_table[i].visible, + plane_table[i].onoff, + (plane_table[i].cur_fb) ? plane_table[i].cur_fb->id : 0, + (plane_table[i].cur_fb) ? plane_table[i].cur_fb-> + width : 0, + (plane_table[i].cur_fb) ? plane_table[i].cur_fb-> + height : 0, plane_table[i].src.x, plane_table[i].src.y, + plane_table[i].src.width, plane_table[i].src.height, + plane_table[i].dst.x, plane_table[i].dst.y, + plane_table[i].dst.width, plane_table[i].dst.height); + } + + XDBG_REPLY("=================================================\n"); + + return reply; +} + +int +exynosPlaneGetCount(void) +{ + return plane_table_size; +} diff --git a/src/crtcconfig/sec_plane.h b/src/crtcconfig/exynos_plane.h index 5ce2fd1..37c0d0e 100644 --- a/src/crtcconfig/sec_plane.h +++ b/src/crtcconfig/exynos_plane.h @@ -31,7 +31,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef __SEC_PLANE_H__ #define __SEC_PLANE_H__ -#include "sec_display.h" +#include "exynos_display.h" #define PLANE_POS_0 0 #define PLANE_POS_1 1 @@ -39,46 +39,48 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PLANE_POS_3 3 #define PLANE_POS_4 4 -typedef struct _SECPlanePriv -{ +typedef struct _EXYNOSPlanePriv { ScrnInfoPtr pScrn; - SECModePtr pSecMode; + EXYNOSModePtr pExynosMode; drmModePlanePtr mode_plane; int plane_id; struct xorg_list link; -} SECPlanePrivRec, *SECPlanePrivPtr; +} EXYNOSPlanePrivRec, *EXYNOSPlanePrivPtr; -void secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num); -void secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv); +void exynosPlaneInit(ScrnInfoPtr pScrn, EXYNOSModePtr pExynosMode, int num); +void exynosPlaneDeinit(ScrnInfoPtr pScrn, EXYNOSPlanePrivPtr pPlanePriv); -void secPlaneShowAll (int crtc_id); -int secPlaneGetID (void); -void secPlaneFreeId (int plane_id); -Bool secPlaneTrun (int plane_id, Bool onoff, Bool user); -Bool secPlaneTrunStatus (int plane_id); -void secPlaneFreezeUpdate (int plane_id, Bool enable); +void exynosPlaneShowAll(int crtc_id); +intptr_t exynosPlaneGetID(void); +void exynosPlaneFreeId(intptr_t plane_id); +Bool exynosPlaneTrun(intptr_t plane_id, Bool onoff, Bool user); +Bool exynosPlaneTrunStatus(intptr_t plane_id); +void exynosPlaneFreezeUpdate(intptr_t plane_id, Bool enable); -Bool secPlaneRemoveBuffer (int plane_id, int fb_id); -int secPlaneAddBo (int plane_id, tbm_bo bo); -int secPlaneAddBuffer (int plane_id, SECVideoBuf *vbuf); +//Bool exynosPlaneRemoveBuffer (intptr_t plane_id, int fb_id); +int exynosPlaneAddBo(intptr_t plane_id, tbm_bo bo); +int exynosPlaneAddBuffer(intptr_t plane_id, EXYNOSVideoBuf * vbuf); -int secPlaneGetBuffer (int plane_id, tbm_bo bo, SECVideoBuf *vbuf); -void secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height); +intptr_t exynosPlaneGetBuffer(int plane_id, tbm_bo bo, EXYNOSVideoBuf * vbuf); +void exynosPlaneGetBufferSize(int plane_id, int fb_id, int *width, int *height); -Bool secPlaneAttach (int plane_id, int fb_id); +Bool exynosPlaneAttach(int plane_id, int fb_id, EXYNOSVideoBuf * vbuf); -Bool secPlaneIsVisible (int plane_id); -Bool secPlaneHide (int plane_id); -Bool secPlaneShow (int plane_id, int crtc_id, +Bool exynosPlaneIsVisible(int plane_id); +Bool exynosPlaneHide(int plane_id); +Bool exynosPlaneShow(int plane_id, int crtc_id, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int zpos, Bool need_update); -Bool secPlaneMove (int plane_id, int x, int y); +Bool exynosPlaneMove(int plane_id, int x, int y); +void exynosPlaneFlushFBId(intptr_t plane_id); + +int exynosPlaneGetCount(void); /* for debug */ -char* secPlaneDump (char *reply, int *len); +char *exynosPlaneDump(char *reply, int *len); -#endif /* __SEC_PLANE_H__ */ +#endif /* __SEC_PLANE_H__ */ diff --git a/src/crtcconfig/exynos_prop.c b/src/crtcconfig/exynos_prop.c new file mode 100644 index 0000000..2e379b0 --- /dev/null +++ b/src/crtcconfig/exynos_prop.c @@ -0,0 +1,734 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <stdint.h> +#include <string.h> + +#include "exynos.h" +#include "exynos_display.h" +#include "exynos_output.h" +#include "exynos_crtc.h" +#include "exynos_prop.h" +#include "exynos_util.h" +#include <exynos/exynos_drm.h> +#include <sys/ioctl.h> + +#define STR_XRR_DISPLAY_MODE_PROPERTY "XRR_PROPERTY_DISPLAY_MODE" +#define STR_XRR_LVDS_FUNCTION "XRR_PROPERTY_LVDS_FUNCTION" +#define STR_XRR_FB_VISIBLE_PROPERTY "XRR_PROPERTY_FB_VISIBLE" +#define STR_XRR_VIDEO_OFFSET_PROPERTY "XRR_PROPERTY_VIDEO_OFFSET" +#define STR_XRR_PROPERTY_SCREEN_ROTATE "XRR_PROPERTY_SCREEN_ROTATE" + +#define PROP_VERIFY_RR_MODE(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRModeType, serverClient, a);\ + if (rc != Success) {\ + serverClient->errorValue = id;\ + return 0;\ + }\ + } + +#define FLAG_BITS (RR_HSyncPositive | \ + RR_HSyncNegative | \ + RR_VSyncPositive | \ + RR_VSyncNegative | \ + RR_Interlace | \ + RR_DoubleScan | \ + RR_CSync | \ + RR_CSyncPositive | \ + RR_CSyncNegative | \ + RR_HSkewPresent | \ + RR_BCast | \ + RR_PixelMultiplex | \ + RR_DoubleClock | \ + RR_ClockDivideBy2) + +static Bool g_display_mode_prop_init = FALSE; +static Bool g_lvds_func_prop_init = FALSE; +static Bool g_fb_visible_prop_init = FALSE; +static Bool g_video_offset_prop_init = FALSE; +static Bool g_screen_rotate_prop_init = FALSE; + +static Atom xrr_property_display_mode_atom; +static Atom xrr_property_lvds_func_atom; +static Atom xrr_property_fb_visible_atom; +static Atom xrr_property_video_offset_atom; +static Atom xrr_property_screen_rotate_atom; + +typedef enum { + XRR_OUTPUT_DISPLAY_MODE_NULL, + XRR_OUTPUT_DISPLAY_MODE_WB_CLONE, + XRR_OUTPUT_DISPLAY_MODE_VIDEO_ONLY, +} XRROutputPropDisplayMode; + +typedef enum { + XRR_OUTPUT_LVDS_FUNC_NULL, +#ifdef LEGACY_INTERFACE + XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL, +#endif + XRR_OUTPUT_LVDS_FUNC_HIBERNATION, + XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY, +} XRROutputPropLvdsFunc; + +/* + * Convert a RandR mode to a DisplayMode + */ +static void +_RRModeConvertToDisplayMode(ScrnInfoPtr scrn, + RRModePtr randr_mode, DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = randr_mode->mode.dotClock / 1000; + + mode->HDisplay = randr_mode->mode.width; + mode->HSyncStart = randr_mode->mode.hSyncStart; + mode->HSyncEnd = randr_mode->mode.hSyncEnd; + mode->HTotal = randr_mode->mode.hTotal; + mode->HSkew = randr_mode->mode.hSkew; + + mode->VDisplay = randr_mode->mode.height; + mode->VSyncStart = randr_mode->mode.vSyncStart; + mode->VSyncEnd = randr_mode->mode.vSyncEnd; + mode->VTotal = randr_mode->mode.vTotal; + mode->VScan = 0; + + mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; + + xf86SetModeCrtc(mode, scrn->adjustFlags); +} + +static int +_exynosPropUnsetCrtc(xf86OutputPtr pOutput) +{ + if (!pOutput->crtc) + return 1; + + ScrnInfoPtr pScrn = pOutput->scrn; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + + pExynosMode->unset_connector_type = + pOutputPriv->mode_output->connector_type; + RRGetInfo(pScrn->pScreen, TRUE); + pExynosMode->unset_connector_type = 0; + RRGetInfo(pScrn->pScreen, TRUE); + + return 1; +} + +static int +_exynosPropSetWbClone(xf86OutputPtr pOutput, int mode_xid) +{ + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + EXYNOSModePtr pExynosMode = pOutputPriv->pExynosMode; + RRModePtr pRRMode; + DisplayModeRec mode; + + /* find kmode and set the external default mode */ + PROP_VERIFY_RR_MODE(mode_xid, pRRMode, DixSetAttrAccess); + _RRModeConvertToDisplayMode(pOutput->scrn, pRRMode, &mode); + exynosDisplayModeToKmode(pOutput->scrn, &pExynosMode->ext_connector_mode, + &mode); + + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB) { + exynosDisplaySetDispConnMode(pOutput->scrn, DISPLAY_CONN_MODE_HDMI); + _exynosPropUnsetCrtc(pOutput); + } + else if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) { + exynosDisplaySetDispConnMode(pOutput->scrn, DISPLAY_CONN_MODE_VIRTUAL); + _exynosPropUnsetCrtc(pOutput); + } + else { + XDBG_WARNING(MDISP, + "(WB_CLONE) Not suuport for this connecotor type\n"); + return 0; + } + + if (!exynosDisplaySetDispSetMode(pOutput->scrn, DISPLAY_SET_MODE_CLONE)) { + return 0; + } + + return 1; +} + +static void +_exynosPropUnSetWbClone(xf86OutputPtr pOutput) +{ + exynosDisplaySetDispSetMode(pOutput->scrn, DISPLAY_SET_MODE_OFF); + exynosDisplaySetDispConnMode(pOutput->scrn, DISPLAY_CONN_MODE_NONE); +} + +Bool +exynosPropSetDisplayMode(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + XDBG_RETURN_VAL_IF_FAIL(value, FALSE); + XDBG_TRACE(MPROP, "%s\n", __FUNCTION__); + + XRROutputPropDisplayMode disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL; + EXYNOSOutputPrivPtr pOutputPriv; + + if (g_display_mode_prop_init == FALSE) { + xrr_property_display_mode_atom = + MakeAtom(STR_XRR_DISPLAY_MODE_PROPERTY, + strlen(STR_XRR_DISPLAY_MODE_PROPERTY), TRUE); + g_display_mode_prop_init = TRUE; + } + + if (xrr_property_display_mode_atom != property) { + //ErrorF ("[Display_mode]: Unrecognized property name.\n"); + return FALSE; + } + + if (!value->data || value->size == 0) { + //ErrorF ("[Display_mode]: Unrecognized property value.\n"); + return TRUE; + } + + XDBG_DEBUG(MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, + *(int *) value->data, value->size); + + disp_mode = *(int *) value->data; + + if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL) + return TRUE; + + XDBG_DEBUG(MDISP, "output_name=%s, disp_mode=%d\n", pOutput->name, + disp_mode); + + pOutputPriv = pOutput->driver_private; + + int mode_xid; + + switch (disp_mode) { + case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE: + mode_xid = *((int *) value->data + 1); + XDBG_INFO(MDISP, "[DISPLAY_MODE]: Set WriteBack Clone\n"); + _exynosPropSetWbClone(pOutput, mode_xid); + pOutputPriv->disp_mode = disp_mode; + break; + default: + break; + } + + return TRUE; +} + +void +exynosPropUnSetDisplayMode(xf86OutputPtr pOutput) +{ + XRROutputPropDisplayMode disp_mode; + EXYNOSOutputPrivPtr pOutputPriv; + + pOutputPriv = pOutput->driver_private; + disp_mode = pOutputPriv->disp_mode; + + if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL) + return; + + /* check the private and unset the diplaymode */ + switch (disp_mode) { + case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE: + XDBG_INFO(MDISP, "[DISPLAY_MODE]: UnSet WriteBack Clone\n"); + _exynosPropUnSetWbClone(pOutput); + break; + default: + break; + } + + pOutputPriv->disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL; +} + +#ifdef LEGACY_INTERFACE +static char fake_edid_info[] = { + /* fill the edid information */ +}; + +static void +_exynosPropSetVirtual(xf86OutputPtr pOutput, int sc_conn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pOutput->scrn); + int fd = pExynos->drm_fd; + + struct drm_exynos_vidi_connection vidi; + + if (sc_conn == 1) { + vidi.connection = 1; + vidi.extensions = 1; + uniType temp = {.ptr = fake_edid_info }; + vidi.edid = temp.ptr; + } + else if (sc_conn == 2) { + vidi.connection = 0; + } + else { + XDBG_WARNING(MDISP, "Warning : wrong virtual connection command\n"); + return; + } + + ioctl(fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &vidi); +} +#endif + +Bool +exynosPropSetLvdsFunc(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + XDBG_TRACE(MPROP, "%s\n", __FUNCTION__); + XDBG_RETURN_VAL_IF_FAIL(value, FALSE); + + XRROutputPropLvdsFunc lvds_func = XRR_OUTPUT_LVDS_FUNC_NULL; + + if (g_lvds_func_prop_init == FALSE) { + xrr_property_lvds_func_atom = + MakeAtom(STR_XRR_LVDS_FUNCTION, strlen(STR_XRR_LVDS_FUNCTION), + TRUE); + g_lvds_func_prop_init = TRUE; + } + + if (xrr_property_lvds_func_atom != property) { + return FALSE; + } + + if (!value->data || value->size == 0) { + //ErrorF ("[Display_mode]: Unrecognized property value.\n"); + return TRUE; + } + + XDBG_DEBUG(MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, + *(int *) value->data, value->size); + + lvds_func = *(int *) value->data; + + if (lvds_func == XRR_OUTPUT_LVDS_FUNC_NULL) + return TRUE; + + XDBG_DEBUG(MDISP, "output_name=%s, lvds_func=%d\n", pOutput->name, + lvds_func); + +#ifdef LEGACY_INTERFACE + int sc_conn; +#endif + switch (lvds_func) { +#ifdef LEGACY_INTERFACE + case XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL: + sc_conn = *((int *) value->data + 1); + XDBG_INFO(MDISP, "[LVDS_FUNC]: set virtual output (%d)\n", sc_conn); + _exynosPropSetVirtual(pOutput, sc_conn); + break; +#endif + case XRR_OUTPUT_LVDS_FUNC_HIBERNATION: + XDBG_INFO(MDISP, "[LVDS_FUNC]: set hibernationn\n"); + break; + case XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY: + XDBG_INFO(MDISP, "[LVDS_FUNC]: set accessibility\n"); + break; + default: + break; + } + + return TRUE; +} + +void +exynosPropUnSetLvdsFunc(xf86OutputPtr pOutput) +{ + +} + +static void +_exynosPropReturnProperty(RRPropertyValuePtr value, const char *f, ...) +{ + int len; + va_list args; + char buf[1024]; + + if (value->data) { + free(value->data); + value->data = NULL; + } + va_start(args, f); + len = vsnprintf(buf, sizeof(buf), f, args) + 1; + va_end(args); + + value->data = calloc(1, len); + value->format = 8; + value->size = len; + + if (value->data) + strncpy(value->data, buf, len - 1); +} + +Bool +exynosPropFbVisible(char *cmd, Bool always, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + int output = 0; + int pos = 0; + Bool onoff = FALSE; + char str[128]; + char *p; + EXYNOSLayer *layer; + EXYNOSLayerPos lpos; + + XDBG_RETURN_VAL_IF_FAIL(cmd != NULL, FALSE); + + snprintf(str, sizeof(str), "%s", cmd); + + p = strtok(str, ":"); + XDBG_RETURN_VAL_IF_FAIL(p != NULL, FALSE); + output = atoi(p); + + p = strtok(NULL, ":"); + XDBG_RETURN_VAL_IF_FAIL(p != NULL, FALSE); + pos = atoi(p); + + if (output == LAYER_OUTPUT_LCD) + lpos = pos - 3; + else + lpos = pos - 1; + + p = strtok(NULL, ":"); + if (!p) { + _exynosPropReturnProperty(value, "%d", 0); + + if (lpos != 0) { + layer = exynosLayerFind((EXYNOSLayerOutput) output, lpos); + if (layer) + _exynosPropReturnProperty(value, "%d", + exynosLayerTurnStatus(layer)); + } + else { + xf86CrtcConfigPtr pCrtcConfig; + int i; + + pCrtcConfig = XF86_CRTC_CONFIG_PTR(scrn); + if (!pCrtcConfig) + return FALSE; + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if ((output == LAYER_OUTPUT_LCD && + (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_LVDS || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_Unknown)) || + (output == LAYER_OUTPUT_EXT && + (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIB || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL))) { + if (pOutput->crtc) { + EXYNOSCrtcPrivPtr pCrtcPriv = + pOutput->crtc->driver_private; + _exynosPropReturnProperty(value, "%d", + pCrtcPriv->onoff); + } + break; + } + } + } + + return TRUE; + } + onoff = atoi(p); + + if (lpos != 0) { + if (!always) + if (output == LAYER_OUTPUT_LCD && lpos == LAYER_UPPER) { + xf86CrtcPtr pCrtc = xf86CompatCrtc(scrn); + + XDBG_RETURN_VAL_IF_FAIL((pCrtc != NULL), FALSE); + EXYNOSCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; + + exynosCrtcOverlayNeedOff(pCrtc, !onoff); + + if (pCrtcPriv->cursor_show && !onoff) { + XDBG_TRACE(MCRS, "can't turn upper off.\n"); + return FALSE; + } + } + + layer = exynosLayerFind((EXYNOSLayerOutput) output, lpos); + if (!layer) + return FALSE; + + if (onoff) + exynosLayerTurn(layer, TRUE, TRUE); + else + exynosLayerTurn(layer, FALSE, TRUE); + } + else { + xf86CrtcConfigPtr pCrtcConfig; + int i; + + pCrtcConfig = XF86_CRTC_CONFIG_PTR(scrn); + if (!pCrtcConfig) + return FALSE; + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if ((output == LAYER_OUTPUT_LCD && + (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_LVDS || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_Unknown)) || (output == LAYER_OUTPUT_EXT && + (pOutputPriv->mode_output-> + connector_type == + DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output-> + connector_type == + DRM_MODE_CONNECTOR_HDMIB || + pOutputPriv->mode_output-> + connector_type == + DRM_MODE_CONNECTOR_VIRTUAL))) + { + EXYNOSCrtcPrivPtr pCrtcPriv; + + if (!pOutput->crtc) + break; + + pCrtcPriv = pOutput->crtc->driver_private; + if (pCrtcPriv->bAccessibility) { + _exynosPropReturnProperty(value, + "[Xorg] crtc(%d) accessibility ON. \n", + exynosCrtcID(pCrtcPriv)); + return TRUE; + } + + if (pOutput->crtc && + !exynosCrtcTurn(pOutput->crtc, onoff, always, TRUE)) { + _exynosPropReturnProperty(value, + "[Xorg] crtc(%d) now %s%s\n", + exynosCrtcID(pCrtcPriv), + (pCrtcPriv->onoff) ? "ON" : "OFF", + (pCrtcPriv-> + onoff_always) ? "(always)." : + "."); + return TRUE; + } + break; + } + } + } + + _exynosPropReturnProperty(value, "[Xorg] output(%d), zpos(%d) layer %s%s\n", + output, pos, (onoff) ? "ON" : "OFF", + (always) ? "(always)." : "."); + + return TRUE; +} + +Bool +exynosPropVideoOffset(char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + int x, y; + char str[128]; + char *p; + EXYNOSLayer *layer; + + snprintf(str, sizeof(str), "%s", cmd); + + p = strtok(str, ","); + XDBG_RETURN_VAL_IF_FAIL(p != NULL, FALSE); + x = atoi(p); + + p = strtok(NULL, ","); + XDBG_RETURN_VAL_IF_FAIL(p != NULL, FALSE); + y = atoi(p); + +#if 0 + PropertyPtr rotate_prop; + int rotate = 0; + + rotate_prop = + exynosUtilGetWindowProperty(scrn->pScreen->root, + "_E_ILLUME_ROTATE_ROOT_ANGLE"); + if (rotate_prop) + rotate = *(int *) rotate_prop->data; +#endif + + pExynos->pVideoPriv->video_offset_x = x; + pExynos->pVideoPriv->video_offset_y = y; + + layer = exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_LOWER1); + if (layer) + exynosLayerSetOffset(layer, x, y); + + layer = exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_LOWER2); + if (layer) + exynosLayerSetOffset(layer, x, y); + + _exynosPropReturnProperty(value, "[Xorg] video_offset : %d,%d.\n", + pExynos->pVideoPriv->video_offset_x, + pExynos->pVideoPriv->video_offset_y); + + return TRUE; +} + +Bool +exynosPropSetFbVisible(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + if (g_fb_visible_prop_init == FALSE) { + xrr_property_fb_visible_atom = MakeAtom(STR_XRR_FB_VISIBLE_PROPERTY, + strlen + (STR_XRR_FB_VISIBLE_PROPERTY), + TRUE); + g_fb_visible_prop_init = TRUE; + } + + if (xrr_property_fb_visible_atom != property) + return FALSE; + + if (!value || !value->data || value->size == 0) + return TRUE; + + if (value->format != 8) + return TRUE; + + XDBG_TRACE(MPROP, "%s \n", (char *) value->data); + + exynosPropFbVisible(value->data, FALSE, value, pOutput->scrn); + + return TRUE; +} + +Bool +exynosPropSetVideoOffset(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + if (g_video_offset_prop_init == FALSE) { + xrr_property_video_offset_atom = MakeAtom(STR_XRR_VIDEO_OFFSET_PROPERTY, + strlen + (STR_XRR_VIDEO_OFFSET_PROPERTY), + TRUE); + g_video_offset_prop_init = TRUE; + } + + if (xrr_property_video_offset_atom != property) + return FALSE; + + if (!value || !value->data || value->size == 0) + return TRUE; + + if (value->format != 8) + return TRUE; + + XDBG_TRACE(MPROP, "%s \n", (char *) value->data); + + exynosPropVideoOffset(value->data, value, pOutput->scrn); + + return TRUE; +} + +Bool +exynosPropScreenRotate(char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn) +{ + xf86CrtcPtr crtc = xf86CompatCrtc(scrn); + int degree; + + if (!crtc) + return TRUE; + + if (!strcmp(cmd, "normal")) + degree = 0; + else if (!strcmp(cmd, "right")) + degree = 90; + else if (!strcmp(cmd, "inverted")) + degree = 180; + else if (!strcmp(cmd, "left")) + degree = 270; + else if (!strcmp(cmd, "0")) + degree = 0; + else if (!strcmp(cmd, "1")) + degree = 270; + else if (!strcmp(cmd, "2")) + degree = 180; + else if (!strcmp(cmd, "3")) + degree = 90; + else { + _exynosPropReturnProperty(value, "[Xorg] unknown value: %s\n", cmd); + return TRUE; + } + + if (exynosCrtcScreenRotate(crtc, degree)) + _exynosPropReturnProperty(value, "[Xorg] screen rotated %d.\n", degree); + else { + _exynosPropReturnProperty(value, "[Xorg] Fail screen rotate %d.\n", + degree); + return FALSE; + } + + return TRUE; +} + +Bool +exynosPropSetScreenRotate(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value) +{ + if (g_screen_rotate_prop_init == FALSE) { + xrr_property_screen_rotate_atom = + MakeAtom(STR_XRR_PROPERTY_SCREEN_ROTATE, + strlen(STR_XRR_PROPERTY_SCREEN_ROTATE), TRUE); + g_screen_rotate_prop_init = TRUE; + } + + if (xrr_property_screen_rotate_atom != property) + return FALSE; + + if (!value || !value->data || value->size == 0) + return TRUE; + + if (value->format != 8) + return TRUE; + + XDBG_TRACE(MPROP, "%s \n", (char *) value->data); + + exynosPropScreenRotate(value->data, value, pOutput->scrn); + + return TRUE; +} diff --git a/src/crtcconfig/sec_prop.h b/src/crtcconfig/exynos_prop.h index 79a2135..4e56dad 100644 --- a/src/crtcconfig/sec_prop.h +++ b/src/crtcconfig/exynos_prop.h @@ -31,20 +31,26 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef __SEC_PROP_H__ #define __SEC_PROP_H__ -Bool secPropSetLvdsFunc (xf86OutputPtr output, Atom property, RRPropertyValuePtr value); -void secPropUnSetLvdsFunc (xf86OutputPtr pOutput); - -Bool secPropSetDisplayMode (xf86OutputPtr output, Atom property, RRPropertyValuePtr value); -void secPropUnSetDisplayMode (xf86OutputPtr pOutput); - -Bool secPropSetFbVisible (xf86OutputPtr output, Atom property, RRPropertyValuePtr value); -Bool secPropSetVideoOffset (xf86OutputPtr output, Atom property, RRPropertyValuePtr value); -Bool secPropSetScreenRotate (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value); - -Bool secPropFbVisible (char *cmd, Bool always, RRPropertyValuePtr value, ScrnInfoPtr scrn); -Bool secPropVideoOffset (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn); -Bool secPropScreenRotate (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn); - - -#endif /* __SEC_PROP_H__ */ - +Bool exynosPropSetLvdsFunc(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value); +void exynosPropUnSetLvdsFunc(xf86OutputPtr pOutput); + +Bool exynosPropSetDisplayMode(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value); +void exynosPropUnSetDisplayMode(xf86OutputPtr pOutput); + +Bool exynosPropSetFbVisible(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value); +Bool exynosPropSetVideoOffset(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value); +Bool exynosPropSetScreenRotate(xf86OutputPtr pOutput, Atom property, + RRPropertyValuePtr value); + +Bool exynosPropFbVisible(char *cmd, Bool always, RRPropertyValuePtr value, + ScrnInfoPtr scrn); +Bool exynosPropVideoOffset(char *cmd, RRPropertyValuePtr value, + ScrnInfoPtr scrn); +Bool exynosPropScreenRotate(char *cmd, RRPropertyValuePtr value, + ScrnInfoPtr scrn); + +#endif /* __SEC_PROP_H__ */ diff --git a/src/crtcconfig/exynos_xberc.c b/src/crtcconfig/exynos_xberc.c new file mode 100755 index 0000000..4e9cdc5 --- /dev/null +++ b/src/crtcconfig/exynos_xberc.c @@ -0,0 +1,1264 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <stdint.h> +#include <string.h> +#include <strings.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <poll.h> +#include <dirent.h> + +#include <xorgVersion.h> +#include <tbm_bufmgr.h> +#include <xf86Crtc.h> +#include <xf86DDC.h> +#include <xf86cmap.h> +#include <xf86Priv.h> +#include <list.h> +#include <X11/Xatom.h> +#include <X11/extensions/dpmsconst.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_xberc.h" +#include "exynos_output.h" +#include "exynos_crtc.h" +#include "exynos_layer.h" +#include "exynos_wb.h" +#include "exynos_plane.h" +#include "exynos_prop.h" +#include "exynos_drmmode_dump.h" + +#define XRRPROPERTY_ATOM "X_RR_PROPERTY_REMOTE_CONTROLLER" +#define XBERC_BUF_SIZE 8192 + +static Atom rr_property_atom; + +static void _exynosXbercSetReturnProperty(RRPropertyValuePtr value, + const char *f, ...); + +static Bool +EXYNOSXbercSetTvoutMode(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + const char *mode_string[] = { "Off", "Clone", "UiClone", "Extension" }; + EXYNOSDisplaySetMode mode; + + XDBG_DEBUG(MSEC, "%s value : %d\n", __FUNCTION__, + *(unsigned int *) value->data); + + if (argc < 2) { + _exynosXbercSetReturnProperty(value, "Error : too few arguments\n"); + return TRUE; + } + + if (argc == 2) { + _exynosXbercSetReturnProperty(value, "Current Tv Out mode is %d (%s)\n", + pExynosMode->set_mode, + mode_string[pExynosMode->set_mode]); + return TRUE; + } + + mode = (EXYNOSDisplaySetMode) atoi(argv[2]); + + if (mode < DISPLAY_SET_MODE_OFF) { + _exynosXbercSetReturnProperty(value, + "Error : value(%d) is out of range.\n", + mode); + return TRUE; + } + + if (mode == pExynosMode->set_mode) { + _exynosXbercSetReturnProperty(value, "[Xorg] already tvout : %s.\n", + mode_string[mode]); + return TRUE; + } + + if (pExynosMode->conn_mode != DISPLAY_CONN_MODE_HDMI && + pExynosMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) { + _exynosXbercSetReturnProperty(value, "Error : not connected.\n"); + return TRUE; + } + + exynosDisplaySetDispSetMode(scrn, mode); + + _exynosXbercSetReturnProperty(value, "[Xorg] tvout : %s.\n", + mode_string[mode]); + + return TRUE; +} + +static Bool +EXYNOSXbercSetConnectMode(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + const char *mode_string[] = { "Off", "HDMI", "Virtual" }; + EXYNOSDisplayConnMode mode; + + XDBG_DEBUG(MSEC, "%s value : %d\n", __FUNCTION__, + *(unsigned int *) value->data); + + if (argc < 2) { + _exynosXbercSetReturnProperty(value, "Error : too few arguments\n"); + return TRUE; + } + + if (argc == 2) { + _exynosXbercSetReturnProperty(value, + "Current connect mode is %d (%s)\n", + pExynosMode->conn_mode, + mode_string[pExynosMode->conn_mode]); + return TRUE; + } + + mode = (EXYNOSDisplayConnMode) atoi(argv[2]); + + if (mode < DISPLAY_CONN_MODE_NONE || mode >= DISPLAY_CONN_MODE_MAX) { + _exynosXbercSetReturnProperty(value, + "Error : value(%d) is out of range.\n", + mode); + return TRUE; + } + + if (mode == pExynosMode->conn_mode) { + _exynosXbercSetReturnProperty(value, "[Xorg] already connect : %s.\n", + mode_string[mode]); + return TRUE; + } + + exynosDisplaySetDispConnMode(scrn, mode); + + _exynosXbercSetReturnProperty(value, "[Xorg] connect : %s.\n", + mode_string[mode]); + + return TRUE; +} + +static Bool +EXYNOSXbercAsyncSwap(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + ScreenPtr pScreen = scrn->pScreen; + int bEnable; + int status = -1; + + if (argc != 3) { + status = exynosExaScreenAsyncSwap(pScreen, -1); + if (status < 0) { + _exynosXbercSetReturnProperty(value, "%s", + "faili to set async swap\n"); + return TRUE; + } + + _exynosXbercSetReturnProperty(value, "Async swap : %d\n", status); + return TRUE; + } + + bEnable = atoi(argv[2]); + + status = exynosExaScreenAsyncSwap(pScreen, bEnable); + if (status < 0) { + _exynosXbercSetReturnProperty(value, "%s", "faili to set async swap\n"); + return TRUE; + } + + if (status) + _exynosXbercSetReturnProperty(value, "%s", "Set async swap.\n"); + else + _exynosXbercSetReturnProperty(value, "%s", "Unset async swap.\n"); + + return TRUE; +} + +static long +_parse_long(char *s) +{ + char *fmt = "%lu"; + long retval = 0L; + int thesign = 1; + + if (s && s[0]) { + char temp[12]; + + snprintf(temp, sizeof(temp), "%s", s); + s = temp; + + if (s[0] == '-') + s++, thesign = -1; + if (s[0] == '0') + s++, fmt = "%lo"; + if (s[0] == 'x' || s[0] == 'X') + s++, fmt = "%lx"; + (void) sscanf(s, fmt, &retval); + } + return (thesign * retval); +} + +static Bool +EXYNOSXbercDump(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + int dump_mode; + Bool flush = TRUE; + char *c; + int buf_cnt = 30; + + if (argc < 3) + goto print_dump; + + pExynos->dump_xid = 0; + dump_mode = 0; + + if (pExynos->dump_str) + free(pExynos->dump_str); + pExynos->dump_str = strdup(argv[2]); + + c = strtok(argv[2], ","); + if (!c) { + _exynosXbercSetReturnProperty(value, "[Xorg] fail: read option"); + return TRUE; + } + + do { + if (!strcmp(c, "off")) { + dump_mode = 0; + break; + } + else if (!strcmp(c, "clear")) { + dump_mode = 0; + flush = FALSE; + break; + } + else if (!strcmp(c, "drawable")) { + dump_mode = XBERC_DUMP_MODE_DRAWABLE; + pExynos->dump_xid = _parse_long(argv[3]); + } + else if (!strcmp(c, "fb")) + dump_mode |= XBERC_DUMP_MODE_FB; + else if (!strcmp(c, "hwc")) + dump_mode |= XBERC_DUMP_MODE_HWC; + else if (!strcmp(c, "dri3")) + dump_mode |= XBERC_DUMP_MODE_DRI3; + else if (!strcmp(c, "present")) + dump_mode |= XBERC_DUMP_MODE_PRESENT; + else if (!strcmp(c, "all")) + dump_mode |= (XBERC_DUMP_MODE_DRAWABLE | XBERC_DUMP_MODE_FB | XBERC_DUMP_MODE_DRI3 | XBERC_DUMP_MODE_PRESENT | XBERC_DUMP_MODE_HWC); + else if (!strcmp(c, "ia")) + dump_mode |= XBERC_DUMP_MODE_IA; + else if (!strcmp(c, "ca")) + dump_mode |= XBERC_DUMP_MODE_CA; + else if (!strcmp(c, "ea")) + dump_mode |= XBERC_DUMP_MODE_EA; + else { + _exynosXbercSetReturnProperty(value, + "[Xorg] fail: unknown option('%s')\n", + c); + return TRUE; + } + } while ((c = strtok(NULL, ","))); + + snprintf(pExynos->dump_type, sizeof(pExynos->dump_type), DUMP_TYPE_PNG); + if (argc > 3) { + int i; + + for (i = 3; i < argc; i++) { + c = argv[i]; + if (!strcmp(c, "-count")) + buf_cnt = MIN((argv[i + 1]) ? atoi(argv[i + 1]) : 30, 100); + else if (!strcmp(c, "-type")) { + if (!strcmp(argv[i + 1], DUMP_TYPE_PNG) + || !strcmp(argv[i + 1], DUMP_TYPE_BMP) + || !strcmp(argv[i + 1], DUMP_TYPE_RAW)) { + snprintf(pExynos->dump_type, sizeof(pExynos->dump_type), + "%s", argv[i + 1]); + } + } + } + } + + if (dump_mode != 0) { + char *dir = DUMP_DIR; + DIR *dp; + int ret = -1; + + if (!(dp = opendir(dir))) { + ret = mkdir(dir, 0755); + if (ret < 0) { + _exynosXbercSetReturnProperty(value, + "[Xorg] fail: mkdir '%s'\n", dir); + return FALSE; + } + } + else + closedir(dp); + } + + if (dump_mode != pExynos->dump_mode) { + pExynos->dump_mode = dump_mode; + + if (dump_mode == 0) { + if (flush) + exynosUtilFlushDump(pExynos->dump_info); + exynosUtilFinishDump(pExynos->dump_info); + pExynos->dump_info = NULL; + pExynos->flip_cnt = 0; + goto print_dump; + } + else { + if (pExynos->dump_info) { + exynosUtilFlushDump(pExynos->dump_info); + exynosUtilFinishDump(pExynos->dump_info); + pExynos->dump_info = NULL; + pExynos->flip_cnt = 0; + } + + pExynos->dump_info = exynosUtilPrepareDump(scrn, + pExynos-> + pExynosMode->main_lcd_mode. + hdisplay * + pExynos-> + pExynosMode->main_lcd_mode. + vdisplay * 4, buf_cnt); + if (pExynos->dump_info) { + if (pExynos->dump_mode & ~XBERC_DUMP_MODE_DRAWABLE) + _exynosXbercSetReturnProperty(value, + "[Xorg] Dump buffer: %s(cnt:%d)\n", + pExynos->dump_str, buf_cnt); + else + _exynosXbercSetReturnProperty(value, + "[Xorg] Dump buffer: %s(xid:0x%x,cnt:%d)\n", + pExynos->dump_str, + pExynos->dump_xid, buf_cnt); + } + else + _exynosXbercSetReturnProperty(value, + "[Xorg] Dump buffer: %s(fail)\n", + pExynos->dump_str); + } + } + else + goto print_dump; + + return TRUE; + print_dump: + if (pExynos->dump_mode & XBERC_DUMP_MODE_DRAWABLE) + _exynosXbercSetReturnProperty(value, "[Xorg] Dump buffer: %s(0x%x)\n", + pExynos->dump_str, pExynos->dump_xid); + else + _exynosXbercSetReturnProperty(value, "[Xorg] Dump buffer: %s\n", + pExynos->dump_str); + + return TRUE; +} + +static Bool +EXYNOSXbercCursorEnable(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool bEnable; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "Enable cursor : %d\n", + pExynos->enableCursor); + return TRUE; + } + + bEnable = atoi(argv[2]); + + if (bEnable != pExynos->enableCursor) { + pExynos->enableCursor = bEnable; + if (exynosCrtcCursorEnable(scrn, bEnable)) { + _exynosXbercSetReturnProperty(value, "[Xorg] cursor %s.\n", + bEnable ? "enable" : "disable"); + } + else { + _exynosXbercSetReturnProperty(value, "[Xorg] Fail cursor %s.\n", + bEnable ? "enable" : "disable"); + } + } + else { + _exynosXbercSetReturnProperty(value, "[Xorg] already cursor %s.\n", + bEnable ? "enabled" : "disabled"); + } + + return TRUE; +} + +static Bool +EXYNOSXbercCursorRotate(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + xf86CrtcPtr crtc = xf86CompatCrtc(scrn); + EXYNOSCrtcPrivPtr fimd_crtc; + int rotate, RR_rotate; + + if (!crtc) + return TRUE; + + fimd_crtc = crtc->driver_private; + + if (argc != 3) { + rotate = exynosUtilRotateToDegree(fimd_crtc->user_rotate); + _exynosXbercSetReturnProperty(value, + "Current cursor rotate value : %d\n", + rotate); + return TRUE; + } + + rotate = atoi(argv[2]); + RR_rotate = exynosUtilDegreeToRotate(rotate); + if (!RR_rotate) { + _exynosXbercSetReturnProperty(value, + "[Xorg] Not support rotate(0, 90, 180, 270 only)\n"); + return TRUE; + } + + if (exynosCrtcCursorRotate(crtc, RR_rotate)) { + _exynosXbercSetReturnProperty(value, "[Xorg] cursor rotated %d.\n", + rotate); + } + else { + _exynosXbercSetReturnProperty(value, "[Xorg] Fail cursor rotate %d.\n", + rotate); + } + + return TRUE; +} + +static Bool +EXYNOSXbercVideoPunch(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool video_punch; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "video_punch : %d\n", + pExynos->pVideoPriv->video_punch); + return TRUE; + } + + video_punch = atoi(argv[2]); + + if (pExynos->pVideoPriv->video_punch != video_punch) { + pExynos->pVideoPriv->video_punch = video_punch; + _exynosXbercSetReturnProperty(value, "[Xorg] video_punch %s.\n", + video_punch ? "enabled" : "disabled"); + } + else + _exynosXbercSetReturnProperty(value, "[Xorg] already punch %s.\n", + video_punch ? "enabled" : "disabled"); + + return TRUE; +} + +static Bool +EXYNOSXbercVideoOffset(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "video_offset : %d,%d.\n", + pExynos->pVideoPriv->video_offset_x, + pExynos->pVideoPriv->video_offset_y); + return TRUE; + } + + if (!exynosPropVideoOffset(argv[2], value, scrn)) { + _exynosXbercSetReturnProperty(value, "ex) xberc video_offset 0,100.\n"); + return TRUE; + } + + return TRUE; +} + +static Bool +EXYNOSXbercVideoFps(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool video_fps; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "video_fps : %d\n", + pExynos->pVideoPriv->video_fps); + return TRUE; + } + + video_fps = atoi(argv[2]); + + if (pExynos->pVideoPriv->video_fps != video_fps) { + pExynos->pVideoPriv->video_fps = video_fps; + _exynosXbercSetReturnProperty(value, "[Xorg] video_fps %s.\n", + video_fps ? "enabled" : "disabled"); + } + else + _exynosXbercSetReturnProperty(value, "[Xorg] already video_fps %s.\n", + video_fps ? "enabled" : "disabled"); + + return TRUE; +} + +static Bool +EXYNOSXbercVideoSync(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool video_sync; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "video_sync : %d\n", + pExynos->pVideoPriv->video_sync); + return TRUE; + } + + video_sync = atoi(argv[2]); + + if (pExynos->pVideoPriv->video_sync != video_sync) { + pExynos->pVideoPriv->video_sync = video_sync; + _exynosXbercSetReturnProperty(value, "[Xorg] video_sync %s.\n", + video_sync ? "enabled" : "disabled"); + } + else + _exynosXbercSetReturnProperty(value, "[Xorg] already video_sync %s.\n", + video_sync ? "enabled" : "disabled"); + + return TRUE; +} + +static Bool +EXYNOSXbercVideoNoRetbuf(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "[Xorg] %s wait retbuf\n", + (pExynos->pVideoPriv-> + no_retbuf) ? "No" : ""); + return TRUE; + } + + pExynos->pVideoPriv->no_retbuf = atoi(argv[2]); + + _exynosXbercSetReturnProperty(value, "[Xorg] %s wait retbuf\n", + (pExynos->pVideoPriv->no_retbuf) ? "No" : ""); + + return TRUE; +} + +static Bool +EXYNOSXbercVideoOutput(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + const char *output_string[] = { "None", "default", "video", "ext_only" }; + int video_output; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "video_output : %d\n", + output_string[pExynos->pVideoPriv-> + video_output]); + return TRUE; + } + + video_output = atoi(argv[2]); + + if (video_output < OUTPUT_MODE_DEFAULT || + video_output > OUTPUT_MODE_EXT_ONLY) { + _exynosXbercSetReturnProperty(value, + "Error : value(%d) is out of range.\n", + video_output); + return TRUE; + } + + video_output += 1; + + if (pExynos->pVideoPriv->video_output != video_output) { + pExynos->pVideoPriv->video_output = video_output; + _exynosXbercSetReturnProperty(value, "[Xorg] video_output : %s.\n", + output_string[video_output]); + } + else + _exynosXbercSetReturnProperty(value, + "[Xorg] already video_output : %s.\n", + output_string[video_output]); + + return TRUE; +} + +static Bool +EXYNOSXbercWbFps(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool wb_fps; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "wb_fps : %d\n", pExynos->wb_fps); + return TRUE; + } + + wb_fps = atoi(argv[2]); + + if (pExynos->wb_fps != wb_fps) { + pExynos->wb_fps = wb_fps; + _exynosXbercSetReturnProperty(value, "[Xorg] wb_fps %s.\n", + wb_fps ? "enabled" : "disabled"); + } + else + _exynosXbercSetReturnProperty(value, "[Xorg] already wb_fps %s.\n", + wb_fps ? "enabled" : "disabled"); + + return TRUE; +} + +static Bool +EXYNOSXbercWbHz(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + Bool wb_hz; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, "wb_hz : %d\n", pExynos->wb_hz); + return TRUE; + } + + wb_hz = atoi(argv[2]); + + if (pExynos->wb_hz != wb_hz) { + pExynos->wb_hz = wb_hz; + _exynosXbercSetReturnProperty(value, "[Xorg] wb_hz %d.\n", wb_hz); + } + else + _exynosXbercSetReturnProperty(value, "[Xorg] already wb_hz %d.\n", + wb_hz); + + return TRUE; +} + +static Bool +EXYNOSXbercXvPerf(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + char *c; + + if (argc < 3) { + _exynosXbercSetReturnProperty(value, "[Xorg] xvperf: %s\n", + (pExynos->xvperf) ? pExynos-> + xvperf : "off"); + return TRUE; + } + + if (pExynos->xvperf) + free(pExynos->xvperf); + pExynos->xvperf = strdup(argv[2]); + + c = strtok(argv[2], ","); + if (!c) { + _exynosXbercSetReturnProperty(value, "[Xorg] fail: read option\n"); + return TRUE; + } + + do { + if (!strcmp(c, "off")) + pExynos->xvperf_mode = 0; + else if (!strcmp(c, "ia")) + pExynos->xvperf_mode |= XBERC_XVPERF_MODE_IA; + else if (!strcmp(c, "ca")) + pExynos->xvperf_mode |= XBERC_XVPERF_MODE_CA; + else if (!strcmp(c, "cvt")) + pExynos->xvperf_mode |= XBERC_XVPERF_MODE_CVT; + else if (!strcmp(c, "wb")) + pExynos->xvperf_mode |= XBERC_XVPERF_MODE_WB; + else if (!strcmp(c, "access")) + pExynos->xvperf_mode |= XBERC_XVPERF_MODE_ACCESS; + else { + _exynosXbercSetReturnProperty(value, + "[Xorg] fail: unknown option('%s')\n", + c); + return TRUE; + } + } while ((c = strtok(NULL, ","))); + + _exynosXbercSetReturnProperty(value, "[Xorg] xvperf: %s\n", + (pExynos->xvperf) ? pExynos->xvperf : "off"); + + return TRUE; +} + +static Bool +EXYNOSXbercSwap(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + if (argc != 2) { + _exynosXbercSetReturnProperty(value, "Error : too few arguments\n"); + return TRUE; + } + + exynosVideoSwapLayers(scrn->pScreen); + + _exynosXbercSetReturnProperty(value, "%s", "Video layers swapped.\n"); + + return TRUE; +} + +static Bool +EXYNOSXbercDrmmodeDump(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + char reply[XBERC_BUF_SIZE] = { 0, }; + int len = sizeof(reply); + + if (argc != 2) { + _exynosXbercSetReturnProperty(value, "Error : too few arguments\n"); + return TRUE; + } + + exynos_drmmode_dump(pExynos->drm_fd, reply, &len); + _exynosXbercSetReturnProperty(value, "%s", reply); + + return TRUE; +} + +static Bool +EXYNOSXbercAccessibility(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + Bool found = FALSE; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86OutputPtr pOutput = NULL; + xf86CrtcPtr pCrtc = NULL; + EXYNOSCrtcPrivPtr pCrtcPriv = NULL; + int output_w = 0, output_h = 0; + + char *opt; + char *mode; + int i; + + int accessibility_status; + int bScale; + _X_UNUSED Bool bChange = FALSE; + + char seps[] = "x+-"; + char *tr; + int geo[10], g = 0; + + for (i = 0; i < xf86_config->num_output; i++) { + pOutput = xf86_config->output[i]; + if (!pOutput->crtc->enabled) + continue; + + /* modify the physical size of monitor */ + if (!strcmp(pOutput->name, "LVDS1")) { + found = TRUE; + break; + } + } + + if (!found) { + _exynosXbercSetReturnProperty(value, "Error : cannot found LVDS1\n"); + return TRUE; + } + + pCrtc = pOutput->crtc; + pCrtcPriv = pCrtc->driver_private; + + output_w = pCrtc->mode.HDisplay; + output_h = pCrtc->mode.VDisplay; + + for (i = 0; i < argc; i++) { + opt = argv[i]; + if (*opt != '-') + continue; + + if (!strcmp(opt, "-n")) { + accessibility_status = atoi(argv[++i]); + if (pCrtcPriv->accessibility_status != accessibility_status) { + pCrtcPriv->accessibility_status = accessibility_status; + bChange = TRUE; + } + } + else if (!strcmp(opt, "-scale")) { + bScale = atoi(argv[++i]); + + pCrtcPriv->bScale = bScale; + bChange = TRUE; + //ErrorF("[XORG] Set Scale = %d\n", bScale); + + if (bScale) { + int x, y, w, h; + + mode = argv[++i]; + tr = strtok(mode, seps); + while (tr != NULL) { + geo[g++] = atoi(tr); + tr = strtok(NULL, seps); + } + + if (g < 4) { + _exynosXbercSetReturnProperty(value, + "[Xberc] Invalid geometry(%s)\n", + mode); + continue; + } + + w = geo[0]; + h = geo[1]; + x = geo[2]; + y = geo[3]; + + /*Check invalidate region */ + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (x + w > output_w) + w = output_w - x; + if (y + h > output_h) + h = output_h - y; + + if (pCrtcPriv->rotate == RR_Rotate_90) { + pCrtcPriv->sx = y; + pCrtcPriv->sy = output_w - (x + w); + pCrtcPriv->sw = h; + pCrtcPriv->sh = w; + } + else if (pCrtcPriv->rotate == RR_Rotate_270) { + pCrtcPriv->sx = output_h - (y + h); + pCrtcPriv->sy = x; + pCrtcPriv->sw = h; + pCrtcPriv->sh = w; + } + else if (pCrtcPriv->rotate == RR_Rotate_180) { + pCrtcPriv->sx = output_w - (x + w); + pCrtcPriv->sy = output_h - (y + h); + pCrtcPriv->sw = w; + pCrtcPriv->sh = h; + } + else { + pCrtcPriv->sx = x; + pCrtcPriv->sy = y; + pCrtcPriv->sw = w; + pCrtcPriv->sh = h; + } + } + } + } + + exynosCrtcEnableAccessibility(pCrtc); + + return TRUE; +} + +static Bool +EXYNOSXbercEnableFb(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + Bool always = FALSE; + + if (argc == 2) { + char ret_buf[XBERC_BUF_SIZE] = { 0, }; + char temp[1024] = { 0, }; + xf86CrtcConfigPtr pCrtcConfig; + int i, len, remain = XBERC_BUF_SIZE; + char *buf = ret_buf; + + pCrtcConfig = XF86_CRTC_CONFIG_PTR(scrn); + if (!pCrtcConfig) + goto fail_enable_fb; + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + + if (pOutput->crtc) { + EXYNOSCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; + + snprintf(temp, sizeof(temp), "crtc(%d) : %s%s\n", + pCrtcPriv->mode_crtc->crtc_id, + (pCrtcPriv->onoff) ? "ON" : "OFF", + (pCrtcPriv->onoff_always) ? "(always)." : "."); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + } + } + + exynosPlaneDump(buf, &remain); + + _exynosXbercSetReturnProperty(value, "%s", ret_buf); + + return TRUE; + } + + if (argc > 4) + goto fail_enable_fb; + + if (!strcmp("always", argv[3])) + always = TRUE; + + if (!exynosPropFbVisible(argv[2], always, value, scrn)) + goto fail_enable_fb; + + return TRUE; + + fail_enable_fb: + _exynosXbercSetReturnProperty(value, + "ex) xberc fb [output]:[zpos]:[onoff] {always}.\n"); + + return TRUE; +} + +static Bool +EXYNOSXbercScreenRotate(int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn) +{ + xf86CrtcPtr crtc = xf86CompatCrtc(scrn); + EXYNOSCrtcPrivPtr fimd_crtc; + + if (!crtc) + return TRUE; + + fimd_crtc = crtc->driver_private; + + if (argc != 3) { + _exynosXbercSetReturnProperty(value, + "Current screen rotate value : %d\n", + fimd_crtc->screen_rotate_degree); + return TRUE; + } + + exynosPropScreenRotate(argv[2], value, scrn); + + return TRUE; +} + +static struct { + const char *Cmd; + const char *Description; + const char *Options; + + const char *(*DynamicUsage) (int); + const char *DetailedUsage; + + Bool (*set_property) (int argc, char **argv, RRPropertyValuePtr value, + ScrnInfoPtr scrn); + Bool (*get_property) (RRPropertyValuePtr value); +} xberc_property_proc[] = { + { + "tvout", "to set Tv Out Mode", "[0-4]", + NULL, "[Off:0 / Clone:1 / UiClone:2 / Extension:3]", + EXYNOSXbercSetTvoutMode, NULL,}, { + "connect", "to set connect mode", "[0-2]", + NULL, "[Off:0 / HDMI:1 / Virtual:2]", + EXYNOSXbercSetConnectMode, NULL,}, { + "async_swap", "not block by vsync", "[0 or 1]", + NULL, "[0/1]", EXYNOSXbercAsyncSwap, NULL}, { + "dump", "to dump buffers, default dump-format is png", + "[off,clear,drawable,fb,all]", NULL, + "[off,clear,drawable,fb,all] -count [n] -type [raw|bmp|png]", + EXYNOSXbercDump, NULL}, { + "cursor_enable", "to enable/disable cursor", "[0 or 1]", NULL, + "[Enable:1 / Disable:0]", EXYNOSXbercCursorEnable, NULL}, { + "cursor_rotate", "to set cursor rotate degree", "[0,90,180,270]", NULL, + "[0,90,180,270]", EXYNOSXbercCursorRotate, NULL}, { + "video_punch", "to punch screen when XV put image on screen", + "[0 or 1]", NULL, "[0/1]", EXYNOSXbercVideoPunch, NULL}, { + "video_offset", "to add x,y to the position video", "[x,y]", NULL, + "[x,y]", EXYNOSXbercVideoOffset, NULL}, { + "video_fps", "to print fps of video", "[0 or 1]", NULL, "[0/1]", + EXYNOSXbercVideoFps, NULL}, { + "video_sync", "to sync video", "[0 or 1]", NULL, "[0/1]", + EXYNOSXbercVideoSync, NULL}, { + "video_output", "to set output", "[0,1,2]", NULL, + "[default:0 / video:1 / ext_only:2]", EXYNOSXbercVideoOutput, NULL}, + { + "video_no_retbuf", "no wait until buffer returned", "[0,1]", NULL, + "[disable:0 / enable:1]", EXYNOSXbercVideoNoRetbuf, NULL}, { + "wb_fps", "to print fps of writeback", "[0 or 1]", NULL, "[0/1]", + EXYNOSXbercWbFps, NULL}, { + "wb_hz", "to set hz of writeback", "[0, 12, 15, 20, 30, 60]", NULL, + "[0, 12, 15, 20, 30, 60]", EXYNOSXbercWbHz, NULL}, { + "xv_perf", "to print xv elapsed time", "[off,ia,ca,cvt,wb]", NULL, + "[off,ia,ca,cvt,wb]", EXYNOSXbercXvPerf, NULL}, { + "swap", "to swap video layers", "", NULL, "", EXYNOSXbercSwap, NULL}, { + "drmmode_dump", "to print drmmode resources", "", + NULL, "", EXYNOSXbercDrmmodeDump, NULL}, { + "accessibility", "to set accessibility", + "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]", NULL, + "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]", + EXYNOSXbercAccessibility, NULL}, { + "fb", "to turn framebuffer on/off", "[0~1]:[0~4]:[0~1] {always}", NULL, + "[output : 0(lcd)~1(ext)]:[zpos : 0 ~ 4]:[onoff : 0(on)~1(off)] {always}", + EXYNOSXbercEnableFb, NULL}, { +"screen_rotate", "to set screen orientation", + "[normal,inverted,left,right,0,1,2,3]", NULL, + "[normal,inverted,left,right,0,1,2,3]", + EXYNOSXbercScreenRotate, NULL},}; + +static int +_exynosXbercPrintUsage(char *buf, int size, const char *exec) +{ + char *begin = buf; + char temp[1024]; + int i, len, remain = size; + + int option_cnt = + sizeof(xberc_property_proc) / sizeof(xberc_property_proc[0]); + + snprintf(temp, sizeof(temp), "Usage : %s [cmd] [options]\n", exec); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + + snprintf(temp, sizeof(temp), " ex)\n"); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + + for (i = 0; i < option_cnt; i++) { + snprintf(temp, sizeof(temp), " %s %s %s\n", exec, + xberc_property_proc[i].Cmd, xberc_property_proc[i].Options); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + } + + snprintf(temp, sizeof(temp), " options :\n"); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + + for (i = 0; i < option_cnt; i++) { + if (xberc_property_proc[i].Cmd && xberc_property_proc[i].Description) + snprintf(temp, sizeof(temp), " %s (%s)\n", + xberc_property_proc[i].Cmd, + xberc_property_proc[i].Description); + else + snprintf(temp, sizeof(temp), " Cmd(%p) or Descriptiont(%p).\n", + xberc_property_proc[i].Cmd, + xberc_property_proc[i].Description); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + + if (xberc_property_proc[i].DynamicUsage) { + snprintf(temp, sizeof(temp), " [MODULE:%s]\n", + xberc_property_proc[i].DynamicUsage(MODE_NAME_ONLY)); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + } + + if (xberc_property_proc[i].DetailedUsage) + snprintf(temp, sizeof(temp), " %s\n", + xberc_property_proc[i].DetailedUsage); + else + snprintf(temp, sizeof(temp), " DetailedUsage(%p).\n", + xberc_property_proc[i].DetailedUsage); + len = MIN(remain, strlen(temp)); + strncpy(buf, temp, len); + buf += len; + remain -= len; + + if (remain <= 0) + return (buf - begin); + } + + return (buf - begin); +} + +static unsigned int +_exynosXbercInit() +{ + XDBG_DEBUG(MSEC, "%s()\n", __FUNCTION__); + + static Bool g_property_init = FALSE; + static unsigned int nProperty = + sizeof(xberc_property_proc) / sizeof(xberc_property_proc[0]); + + if (g_property_init == FALSE) { + rr_property_atom = + MakeAtom(XRRPROPERTY_ATOM, strlen(XRRPROPERTY_ATOM), TRUE); + g_property_init = TRUE; + } + + return nProperty; +} + +static int +_exynosXbercParseArg(int *argc, char **argv, RRPropertyValuePtr value) +{ + int i; + char *data; + + if (argc == NULL || value == NULL || argv == NULL || value->data == NULL) + return FALSE; + + data = value->data; + + if (value->format != 8) + return FALSE; + + if (value->size < 3 || data[value->size - 2] != '\0' || + data[value->size - 1] != '\0') + return FALSE; + + for (i = 0; *data; i++) { + argv[i] = data; + data += strlen(data) + 1; + if (data - (char *) value->data > value->size) + return FALSE; + } + argv[i] = data; + *argc = i; + + return TRUE; +} + +static void +_exynosXbercSetReturnProperty(RRPropertyValuePtr value, const char *f, ...) +{ + int len; + va_list args; + char buf[XBERC_BUF_SIZE]; + + if (value->data) { + free(value->data); + value->data = NULL; + } + va_start(args, f); + len = vsnprintf(buf, sizeof(buf), f, args) + 1; + va_end(args); + + value->data = calloc(1, len); + value->format = 8; + value->size = len; + + if (value->data) + strncpy(value->data, buf, len - 1); +} + +int +exynosXbercSetProperty(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + XDBG_TRACE(MXBRC, "%s\n", __FUNCTION__); + + unsigned int nProperty = _exynosXbercInit(); + unsigned int p; + + int argc; + char *argv[1024]; + char buf[XBERC_BUF_SIZE] = { 0, }; + + if (rr_property_atom != property) { + _exynosXbercSetReturnProperty(value, + "[Xberc]: Unrecognized property name.\n"); + return FALSE; + } + + if (_exynosXbercParseArg(&argc, argv, value) == FALSE || argc < 1) { + _exynosXbercSetReturnProperty(value, "[Xberc]: Parse error.\n"); + return TRUE; + } + + if (argc < 2) { + _exynosXbercPrintUsage(buf, sizeof(buf), argv[0]); + _exynosXbercSetReturnProperty(value, buf); + + return TRUE; + } + + for (p = 0; p < nProperty; p++) { + if (!strcmp(argv[1], xberc_property_proc[p].Cmd) || + (argv[1][0] == '-' && + !strcmp(1 + argv[1], xberc_property_proc[p].Cmd))) { + xberc_property_proc[p].set_property(argc, argv, value, + output->scrn); + return TRUE; + } + } + + _exynosXbercPrintUsage(buf, sizeof(buf), argv[0]); + _exynosXbercSetReturnProperty(value, buf); + + return TRUE; +} diff --git a/src/crtcconfig/sec_xberc.h b/src/crtcconfig/exynos_xberc.h index bf9beaa..b8a9b01 100644 --- a/src/crtcconfig/sec_xberc.h +++ b/src/crtcconfig/exynos_xberc.h @@ -35,9 +35,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XBERC_DUMP_MODE_DRAWABLE 0x1 #define XBERC_DUMP_MODE_FB 0x2 +#define XBERC_DUMP_MODE_PRESENT 0x4 +#define XBERC_DUMP_MODE_DRI3 0x8 #define XBERC_DUMP_MODE_IA 0x10 #define XBERC_DUMP_MODE_CA 0x20 #define XBERC_DUMP_MODE_EA 0x40 +#define XBERC_DUMP_MODE_HWC 0x80 #define XBERC_XVPERF_MODE_IA 0x1 #define XBERC_XVPERF_MODE_CA 0x2 @@ -45,7 +48,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XBERC_XVPERF_MODE_WB 0x20 #define XBERC_XVPERF_MODE_ACCESS 0x40 -int secXbercSetProperty (xf86OutputPtr output, Atom property, RRPropertyValuePtr value); - -#endif /* __SEC_XBERC_H__ */ +int exynosXbercSetProperty(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value); +#endif /* __SEC_XBERC_H__ */ diff --git a/src/crtcconfig/sec_crtc.c b/src/crtcconfig/sec_crtc.c deleted file mode 100755 index a69cc7b..0000000 --- a/src/crtcconfig/sec_crtc.c +++ /dev/null @@ -1,2768 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011-2012 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <stdint.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <poll.h> - -#include <xace.h> -#include <xacestr.h> -#include <xorgVersion.h> -#include <tbm_bufmgr.h> -#include <xf86Crtc.h> -#include <xf86DDC.h> -#include <xf86cmap.h> -#include <xf86Xinput.h> -#include <exevents.h> -#include <list.h> -#include <X11/Xatom.h> -#include <X11/extensions/dpmsconst.h> -#include <exynos_drm.h> -#include "sec.h" -#include "sec_util.h" -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_plane.h" -#include "sec_layer.h" -#include "sec_accel.h" -#include "sec_drm_ipp.h" -#include "fimg2d.h" - -static void _cursorRegisterBlockHandler (xf86CrtcPtr pCrtc); -static void _cursorUnregisterBlockHandler (xf86CrtcPtr pCrtc); -static void _cursorShow (xf86CrtcPtr pCrtc); -static void _cursorMove (xf86CrtcPtr pCrtc, int x, int y); -static void _cursorDrawCursor (xf86CrtcPtr pCrtc); - -static Atom atom_rotate_root_angle; -static Atom atom_relative_device_exist; - -static int -_overlayGetXMoveOffset (xf86CrtcPtr pCrtc, int x) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - int offset = 0; - - if (pCrtcPriv->pipe != 0) - return 0; - - offset = x + SEC_CURSOR_W - pSecMode->main_lcd_mode.hdisplay; - - return (offset > 0) ? offset : 0; -} - -static Bool -_overlayEnsureBuffer (xf86CrtcPtr pCrtc, Bool move_layer) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (move_layer) - { - if (!pCrtcPriv->ovl_vbuf_cursor) - { - pCrtcPriv->ovl_vbuf_cursor = secUtilAllocVideoBuffer (pCrtc->scrn, FOURCC_RGB32, - SEC_CURSOR_W, SEC_CURSOR_H, - FALSE, TRUE, FALSE); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_vbuf_cursor != NULL, FALSE); - XDBG_TRACE (MCRS, "[%p] ovl_vbuf_cursor(%p) %dx%d created. \n", pCrtc, - pCrtcPriv->ovl_vbuf_cursor, SEC_CURSOR_W, SEC_CURSOR_H); - } - } - else - { - if (!pCrtcPriv->ovl_vbuf_pixmap) - { - pCrtcPriv->ovl_vbuf_pixmap = secUtilAllocVideoBuffer (pCrtc->scrn, FOURCC_RGB32, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay, - FALSE, TRUE, FALSE); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_vbuf_pixmap != NULL, FALSE); - XDBG_TRACE (MCRS, "[%p] ovl_vbuf_pixmap(%p) %dx%d created. \n", pCrtc, pCrtcPriv->ovl_vbuf_pixmap, - pSecMode->main_lcd_mode.hdisplay, pSecMode->main_lcd_mode.vdisplay); - } - } - - return TRUE; -} - -static Bool -_overlayEnsureLayer (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - int connector_type; - SECLayerOutput output = LAYER_OUTPUT_LCD; - SECLayer *layer; - - if (pCrtcPriv->ovl_layer) - return TRUE; - - connector_type = secCrtcGetConnectType (pCrtc); - - if (connector_type == DRM_MODE_CONNECTOR_LVDS || - connector_type == DRM_MODE_CONNECTOR_Unknown) - { - output = LAYER_OUTPUT_LCD; - } - else if (connector_type == DRM_MODE_CONNECTOR_HDMIA || - connector_type == DRM_MODE_CONNECTOR_HDMIB || - connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - output = LAYER_OUTPUT_EXT; - } - else - { - XDBG_NEVER_GET_HERE (MDISP); - return FALSE; - } - - layer = secLayerFind (output, LAYER_UPPER); - XDBG_RETURN_VAL_IF_FAIL (layer == NULL, FALSE); - - pCrtcPriv->ovl_layer = secLayerCreate (pCrtc->scrn, output, LAYER_UPPER); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_layer != NULL, FALSE); - - XDBG_TRACE (MCRS, "[%p] ovl_layer(%p) created. \n", pCrtc, pCrtcPriv->ovl_layer); - - return TRUE; -} - -static Bool -_overlaySelectBuffer (xf86CrtcPtr pCrtc, Bool move_layer) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - - if (!_overlayEnsureLayer (pCrtc)) - return FALSE; - - if (!_overlayEnsureBuffer (pCrtc, move_layer)) - return FALSE; - - if (move_layer) - { - if (secLayerGetBuffer (pCrtcPriv->ovl_layer) == pCrtcPriv->ovl_vbuf_cursor) - return TRUE; - - secLayerFreezeUpdate (pCrtcPriv->ovl_layer, TRUE); - _cursorDrawCursor (pCrtc); - secLayerSetBuffer (pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_cursor); - secLayerFreezeUpdate (pCrtcPriv->ovl_layer, FALSE); - - int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x); - _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y); - - XDBG_TRACE (MCRS, "[%p] Set ovl_vbuf_cursor. \n", pCrtc); - } - else - { - xRectangle rect = {0,}; - - if (secLayerGetBuffer (pCrtcPriv->ovl_layer) == pCrtcPriv->ovl_vbuf_pixmap) - return TRUE; - - rect.width = pSecMode->main_lcd_mode.hdisplay; - rect.height = pSecMode->main_lcd_mode.vdisplay; - secLayerFreezeUpdate (pCrtcPriv->ovl_layer, TRUE); - secLayerSetBuffer (pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_pixmap); - secLayerFreezeUpdate (pCrtcPriv->ovl_layer, FALSE); - - secLayerSetRect (pCrtcPriv->ovl_layer, &rect, &rect); - - XDBG_TRACE (MCRS, "[%p] Set ovl_vbuf_pixmap. \n", pCrtc); - } - - return TRUE; -} - -static Bool -_cursorEnsureCursorImage(xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECPtr pSec = SECPTR (pCrtc->scrn); - - int x, y, cursor_x, cursor_y; - int win_x, win_y; - int rotate; - int tx = 0, ty = 0; - double c, s; - pixman_transform_t t; - - x = pCrtcPriv->cursor_pos_x; - y = pCrtcPriv->cursor_pos_y; - - //Determine cursor image transform - rotate = secUtilRotateAdd (pSec->rotate, pCrtcPriv->user_rotate); - - //Transform cursor position and screen size - switch (pSec->rotate) - { - case RR_Rotate_0: - default: - cursor_x = x; - cursor_y = y; - break; - case RR_Rotate_90: - cursor_x = y; - cursor_y = pCrtc->scrn->virtualX-1 - x; - break; - case RR_Rotate_180: - cursor_x = pCrtc->scrn->virtualX-1 - x; - cursor_y = pCrtc->scrn->virtualY-1 - y; - break; - case RR_Rotate_270: - cursor_x = pCrtc->scrn->virtualY-1 - y; - cursor_y = x; - break; - } - - switch (rotate) - { - case RR_Rotate_0: - default: - c = 1.0; - s = 0.0; - win_x = cursor_x; - win_y = cursor_y; - break; - case RR_Rotate_90: - c = 0.0; - s = 1.0; - tx = SEC_CURSOR_W; - ty = 0; - - win_x = cursor_x; - win_y = cursor_y - SEC_CURSOR_W; - break; - case RR_Rotate_180: - c = -1.0; - s = 0.0; - tx = SEC_CURSOR_W; - ty = SEC_CURSOR_H; - - win_x = cursor_x - SEC_CURSOR_W; - win_y = cursor_y - SEC_CURSOR_H; - break; - case RR_Rotate_270: - c = 0.0; - s = -1.0; - tx = 0; - ty = SEC_CURSOR_H; - - win_x = cursor_x - SEC_CURSOR_H; - win_y = cursor_y; - break; - } - - pCrtcPriv->cursor_win_x = win_x; - pCrtcPriv->cursor_win_y = win_y; - - if(pCrtcPriv->cursor_image == NULL) - { - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->backup_image != NULL, FALSE); - - XDBG_DEBUG (MCRS, "[%p] (%d + %d) => %d \n", pCrtc, - pSec->rotate, pCrtcPriv->user_rotate, rotate); - - if(rotate == RR_Rotate_0) - { - pCrtcPriv->cursor_image = pCrtcPriv->backup_image; - pixman_image_ref(pCrtcPriv->cursor_image); - } - else - { - //Clear cursor image - pCrtcPriv->cursor_image = pixman_image_create_bits (PIXMAN_a8r8g8b8 - , SEC_CURSOR_W, SEC_CURSOR_H - , NULL - , 0); - - //Copy Cursor image - pixman_transform_init_rotate (&t, pixman_double_to_fixed (c), pixman_double_to_fixed (s)); - pixman_transform_translate (&t, NULL, pixman_int_to_fixed (tx), pixman_int_to_fixed (ty)); - pixman_image_set_transform (pCrtcPriv->backup_image, &t); - pixman_image_composite (PIXMAN_OP_SRC - , pCrtcPriv->backup_image - , NULL - , pCrtcPriv->cursor_image - , 0, 0, 0, 0, 0, 0, SEC_CURSOR_W, SEC_CURSOR_H); - pixman_transform_init_rotate (&t, pixman_double_to_fixed (1.0), pixman_double_to_fixed (0.0)); - pixman_image_set_transform (pCrtcPriv->backup_image, &t); - } - } - - return TRUE; -} - -static Bool -_cursorEnsureCanvas (xf86CrtcPtr pCrtc, SECVideoBuf *vbuf, int width, int height) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - tbm_bo_handle bo_handle; - - if (pCrtcPriv->ovl_canvas) - return TRUE; - - if (!_overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer)) - return FALSE; - - XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE); - - bo_handle = tbm_bo_get_handle (vbuf->bo[0], TBM_DEVICE_CPU); - XDBG_RETURN_VAL_IF_FAIL (bo_handle.ptr != NULL, FALSE); - - pCrtcPriv->ovl_canvas = pixman_image_create_bits (PIXMAN_a8r8g8b8, - width, height, - (uint32_t *)bo_handle.ptr, - width * 4); - - XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) %dx%d created.\n", pCrtc, - pCrtcPriv->ovl_canvas, width, height); - - return TRUE; -} - -static Bool -_cursorEnsureSavedImage (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (pCrtcPriv->saved_image) - return TRUE; - - pCrtcPriv->saved_image = pixman_image_create_bits (PIXMAN_a8r8g8b8, - SEC_CURSOR_W, SEC_CURSOR_H, - NULL, - 0); - XDBG_TRACE (MCRS, "[%p] saved_image(%p) %dx%d created.\n", pCrtc, - pCrtcPriv->saved_image, SEC_CURSOR_W, SEC_CURSOR_H); - - return TRUE; -} - -static void -_cursorSaveImage (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - - XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE); - - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay); - - _cursorEnsureSavedImage (pCrtc); - - pixman_image_composite (PIXMAN_OP_SRC, - pCrtcPriv->ovl_canvas, - NULL, - pCrtcPriv->saved_image, - pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y, - 0, 0, - 0, 0, - SEC_CURSOR_W, SEC_CURSOR_H); - - pCrtcPriv->saved_box.x1 = pCrtcPriv->cursor_win_x; - pCrtcPriv->saved_box.y1 = pCrtcPriv->cursor_win_y; - pCrtcPriv->saved_box.x2 = pCrtcPriv->cursor_win_x+SEC_CURSOR_W; - pCrtcPriv->saved_box.y2 = pCrtcPriv->cursor_win_y+SEC_CURSOR_H; - - XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) saved. \n", pCrtc, - pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y, - SEC_CURSOR_W, SEC_CURSOR_H); -} - -static void -_cursorRestoreImage (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (!pCrtcPriv->saved_image || !pCrtcPriv->ovl_canvas) - return; - - pixman_image_composite (PIXMAN_OP_SRC, - pCrtcPriv->saved_image, - NULL, - pCrtcPriv->ovl_canvas, - 0, 0, 0, 0, - pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1, - SEC_CURSOR_W, SEC_CURSOR_H); - - if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerUpdate (pCrtcPriv->ovl_layer); - - XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) restored. \n", pCrtc, - pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1, - SEC_CURSOR_W, SEC_CURSOR_H); -} - -static void -_cursorDrawCursor (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - int x, y; - - XDBG_RETURN_IF_FAIL (pCrtcPriv->ovl_canvas != NULL); - XDBG_RETURN_IF_FAIL (pCrtcPriv->cursor_image != NULL); - - if (pCrtcPriv->move_layer) - { - /* clear */ - pixman_color_t color = {0,}; - pixman_rectangle16_t rect = {0, 0, SEC_CURSOR_W, SEC_CURSOR_H}; - pixman_image_fill_rectangles (PIXMAN_OP_CLEAR, pCrtcPriv->ovl_canvas, - &color, 1, &rect); - - x = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x); - y = 0; - } - else - { - x = pCrtcPriv->cursor_win_x; - y = pCrtcPriv->cursor_win_y; - } - - pixman_image_composite (PIXMAN_OP_OVER, - pCrtcPriv->cursor_image, - NULL, - pCrtcPriv->ovl_canvas, - 0, 0, 0, 0, x, y, - SEC_CURSOR_W, SEC_CURSOR_H); - - XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) drawn. \n", pCrtc, - x, y, SEC_CURSOR_W, SEC_CURSOR_H); - - secUtilCacheFlush (pCrtc->scrn); - - if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerUpdate (pCrtcPriv->ovl_layer); -} - -static void -_cursorReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - xf86CrtcPtr pCrtc = (xf86CrtcPtr)closure; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECPtr pSec = SECPTR (pCrtc->scrn); - - if (pCrtcPriv->move_layer) - return; - - if(!pSec->enableCursor || !pCrtcPriv->cursor_show) - return; - - if (RegionContainsRect (pRegion, &pCrtcPriv->saved_box) != rgnOUT) - { - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); - pCrtcPriv->need_cursor_update = TRUE; - _cursorRestoreImage(pCrtc); - _cursorRegisterBlockHandler (pCrtc); - } -} - -static void -_cursorDamageDestroy(DamagePtr pDamage, void *closure) -{ - xf86CrtcPtr pCrtc = (xf86CrtcPtr)closure; - SECPtr pSec = SECPTR (pCrtc->scrn); - - if (!pSec->ovl_damage) - return; - - pSec->ovl_damage = NULL; -} - -static void -_cursorBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) -{ - xf86CrtcPtr pCrtc = (xf86CrtcPtr)data; - SECPtr pSec = SECPTR (pCrtc->scrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE); - - if(pSec->ovl_drawable) - { - if(pSec->ovl_damage == NULL) - { - pSec->ovl_damage = DamageCreate((DamageReportFunc)_cursorReportDamage, - (DamageDestroyFunc)_cursorDamageDestroy, - DamageReportRawRegion, - TRUE, pCrtc->scrn->pScreen, pCrtc); - XDBG_RETURN_IF_FAIL (pSec->ovl_damage); - DamageRegister(pSec->ovl_drawable, pSec->ovl_damage); - } - } - else - { - if(pSec->ovl_damage) - { - DamageDestroy(pSec->ovl_damage); - pSec->ovl_damage = NULL; - } - } - - XDBG_DEBUG (MCRS, "[%p] enable(%d) cursor_show(%d) need_update(%d) show(%d) \n", pCrtc, - pSec->enableCursor, pCrtcPriv->cursor_show, - pCrtcPriv->need_cursor_update, pCrtcPriv->cursor_show); - - if(pSec->enableCursor && pCrtcPriv->need_cursor_update) - { - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - - _cursorEnsureCursorImage (pCrtc); - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay); - - _cursorSaveImage (pCrtc); - - /*Draw Cursor*/ - if(pCrtcPriv->cursor_show) - _cursorDrawCursor (pCrtc); - - _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer); - _cursorMove (pCrtc, pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y); - - pCrtcPriv->need_cursor_update = FALSE; - } - - if (!secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerShow (pCrtcPriv->ovl_layer); - - if(!pSec->enableCursor || !pCrtcPriv->cursor_show || !pCrtcPriv->need_cursor_update) - _cursorUnregisterBlockHandler (pCrtc); -} - -static Bool -_cursorSetPointerDeviceRotate (DeviceIntPtr dev, int rotate) -{ -#define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion" /* BOOL, 2 values [x, y], 1 inverts axis */ -#define EVDEV_PROP_SWAP_AXES "Evdev Axes Swap" /* BOOL */ - - int swap = 0; - char inv[2]; - - static Atom swap_axes=0; - static Atom invert_axes=0; - int rc; - - if (!dev) return FALSE; - - XDBG_TRACE (MCRS, "device %s (valuator:%p)\n", - dev->name, dev->valuator); - - if (!swap_axes) - swap_axes = MakeAtom (EVDEV_PROP_SWAP_AXES, strlen (EVDEV_PROP_SWAP_AXES), TRUE); - - if (!invert_axes) - invert_axes = MakeAtom (EVDEV_PROP_INVERT_AXES, strlen (EVDEV_PROP_INVERT_AXES), TRUE); - - switch (rotate) - { - case RR_Rotate_0: - swap = 0; - inv[0] = 0; - inv[1] = 0; - break; - case RR_Rotate_90: - swap = 1; - inv[0] = 0; - inv[1] = 1; - break; - case RR_Rotate_180: - swap = 0; - inv[0] = 1; - inv[1] = 1; - break; - case RR_Rotate_270: - swap = 1; - inv[0] = 1; - inv[1] = 0; - break; - default: - XDBG_ERROR (MCRS, "Error.. cursor_rotate:%d\n", rotate); - return FALSE; - } - - XDBG_TRACE (MCRS, "%s change(swap:%d, inv:%d,%d rotate:%d)\n", dev->name, swap, inv[0], inv[1], rotate); - rc = XIChangeDeviceProperty (dev, swap_axes, XA_INTEGER, 8, - PropModeReplace, 1, &swap, TRUE); - if (rc != Success) - { - XDBG_ERROR (MCRS, "Fail change swap(%s , swap:%d)\n", dev->name, swap); - } - - rc = XIChangeDeviceProperty (dev, invert_axes, XA_INTEGER, 8, - PropModeReplace, 2, - inv, TRUE); - if (rc != Success) - { - XDBG_ERROR (MCRS, "Fail change invert(%s , invert:%d,%d)\n", dev->name, inv[0], inv[1]); - } - - return TRUE; -} - -static Bool -_cursorFindRelativeDevice (xf86CrtcPtr pCrtc) -{ - InputInfoPtr localDevices; - DeviceIntPtr dev; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); - - localDevices = xf86FirstLocalDevice(); - while (localDevices) - { - dev= localDevices->dev; - _cursorSetPointerDeviceRotate (dev, pCrtcPriv->user_rotate); - localDevices = localDevices->next; - } - - return TRUE; -} - -static void -_cursorRotateHook (CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - ScrnInfoPtr pScrn = (ScrnInfoPtr) unused; - xf86CrtcPtr pCrtc = xf86CompatCrtc (pScrn); - XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata; - PropertyPtr pProp = *rec->ppProp; - Atom name = pProp->propertyName; - - XDBG_RETURN_IF_FAIL (pCrtc != NULL); - - /* Don't care about the new content check */ - if (rec->pWin != pScrn->pScreen->root) //Check Rootwindow - return; - - if (name == atom_rotate_root_angle - && (rec->access_mode & DixWriteAccess)) - { - int rotate_degree = *(int*)pProp->data; - - XDBG_TRACE (MCRS, "[%p] Change root angle(%d)\n", pCrtc, rotate_degree); - secCrtcCursorRotate (pCrtc, secUtilDegreeToRotate (rotate_degree)); - } - - if (name == atom_relative_device_exist - && (rec->access_mode & DixWriteAccess)) - { - int exist = *(int*)pProp->data; - if (exist) - { - _cursorFindRelativeDevice (pCrtc); - XDBG_TRACE (MCRS, "[%p] Change device exist(%d)\n", pCrtc, exist); - } - } - - return; -} - -static void -_cursorRegisterBlockHandler (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE); - - if (pCrtcPriv->registered_block_handler) - return; - - XDBG_DEBUG (MCRS, "[%p] \n", pCrtc); - - RegisterBlockAndWakeupHandlers (_cursorBlockHandler, - (WakeupHandlerProcPtr)NoopDDA, pCrtc); - - pCrtcPriv->registered_block_handler = TRUE; -} - -static void -_cursorUnregisterBlockHandler (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (!pCrtcPriv->registered_block_handler) - return; - - XDBG_DEBUG (MCRS, "[%p] \n", pCrtc); - - RemoveBlockAndWakeupHandlers (_cursorBlockHandler, - (WakeupHandlerProcPtr)NoopDDA, pCrtc); - - pCrtcPriv->registered_block_handler = FALSE; -} - -static void -_cursorMove (xf86CrtcPtr pCrtc, int x, int y) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (!pCrtcPriv->move_layer) - return; - - if (pCrtcPriv->ovl_layer) - { - xRectangle src = {0,}; - xRectangle dst = {0,}; - - src.width = SEC_CURSOR_W; - src.height = SEC_CURSOR_H; - - dst.x = x; - dst.y = y; - dst.width = SEC_CURSOR_W; - dst.height = SEC_CURSOR_H; - - XDBG_DEBUG (MCRS, "[%p] to (%d,%d)\n", pCrtc, x, y); - - secLayerSetRect (pCrtcPriv->ovl_layer, &src, &dst); - } -} - -static void -_cursorInit (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); - - //Damage Create - if (!pCrtcPriv->move_layer) - _cursorRegisterBlockHandler (pCrtc); -} - -static int -_cursorDestroy (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); - - if(pCrtcPriv->saved_image) - { - pixman_image_unref(pCrtcPriv->saved_image); - pCrtcPriv->saved_image = NULL; - } - - if(pCrtcPriv->cursor_image) - { - pixman_image_unref(pCrtcPriv->cursor_image); - pCrtcPriv->cursor_image = NULL; - } - - if(pCrtcPriv->ovl_canvas) - { - XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_canvas); - pixman_image_unref(pCrtcPriv->ovl_canvas); - pCrtcPriv->ovl_canvas = NULL; - pCrtcPriv->need_draw_cursor = TRUE; - } - - if (pCrtcPriv->ovl_layer) - { - XDBG_TRACE (MCRS, "[%p] ovl_layer(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_layer); - secLayerUnref (pCrtcPriv->ovl_layer); - pCrtcPriv->ovl_layer = NULL; - } - - return TRUE; -} - -static void -_cursorShow (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECPtr pSec = SECPTR (pCrtc->scrn); - - if(!pSec->enableCursor) - return; - - if (pCrtcPriv->ovl_layer && !secLayerTurnStatus (pCrtcPriv->ovl_layer)) - secLayerTurn (pCrtcPriv->ovl_layer, TRUE, FALSE); - - XDBG_TRACE (MCRS, "[%p] user_rotate(%d)\n", pCrtc, pCrtcPriv->user_rotate); - - if (pCrtcPriv->move_layer) - { - _overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer); - _overlayEnsureLayer (pCrtc); - - _cursorEnsureCursorImage (pCrtc); - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor, - SEC_CURSOR_W, SEC_CURSOR_H); - _cursorDrawCursor (pCrtc); - - _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer); - - int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x); - _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y); - - if (!secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerShow (pCrtcPriv->ovl_layer); - } - else - { - pCrtcPriv->need_cursor_update = TRUE; - _cursorRestoreImage(pCrtc); - _cursorRegisterBlockHandler (pCrtc); - } -} - -static void -_cursorHide (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); - - if (pCrtcPriv->move_layer) - { - if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerHide (pCrtcPriv->ovl_layer); - } - else - { - _cursorRestoreImage (pCrtc); - - if (pCrtcPriv->need_off && !pCrtcPriv->cursor_show) - { - if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerHide (pCrtcPriv->ovl_layer); - return; - } - } - - if (pCrtcPriv->ovl_layer && secLayerTurnStatus (pCrtcPriv->ovl_layer)) - { - Bool turnoff = FALSE; - - if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off) - turnoff = TRUE; - if (!pCrtcPriv->ref_overlay) - turnoff = TRUE; - - if (turnoff) - _cursorDestroy (pCrtc); - } - - pCrtcPriv->cursor_old_offset = 0; - pCrtcPriv->need_cursor_update = TRUE; -} - -static Bool -_cursorEnable (xf86CrtcPtr pCrtc, Bool enable) -{ - ScrnInfoPtr pScrn = pCrtc->scrn; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (!pCrtcPriv->cursor_show) - return FALSE; - - XDBG_TRACE (MCRS, "[%p] enable(%d) \n", pCrtc, enable); - - if (enable) - { - _cursorShow (pCrtc); - - if (pCrtc == xf86CompatCrtc (pScrn)) - { - PropertyPtr rotate_prop; - - /* Set Current Root Rotation */ - rotate_prop = secUtilGetWindowProperty (pScrn->pScreen->root, - "_E_ILLUME_ROTATE_ROOT_ANGLE"); - if (rotate_prop) - { - int rotate = secUtilDegreeToRotate (*(int*)rotate_prop->data); - pCrtcPriv->user_rotate = rotate; - - //Send swap property to relative input device - _cursorFindRelativeDevice (pCrtc); - } - } - - /* Hook for window rotate */ - atom_rotate_root_angle = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE" - , strlen ("_E_ILLUME_ROTATE_ROOT_ANGLE"), FALSE); - atom_relative_device_exist = MakeAtom ("X Mouse Exist" - , strlen ("X Mouse Exist"), TRUE); - - if (atom_rotate_root_angle != None) - { - if (!XaceRegisterCallback (XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn)) - XDBG_ERROR (MCRS, "[%p] Fail XaceRegisterCallback:XACE_PROPERTY_ACCESS\n", pCrtc); - - XDBG_TRACE (MCRS, "[%p] Hook property : _E_ILLUME_ROTATE_ROOT_ANGLE\n", pCrtc); - } - else - XDBG_TRACE (MCRS, "[%p] Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n", pCrtc); - } - else - { - XaceDeleteCallback (XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn); - - _cursorHide (pCrtc); - } - - pCrtcPriv->cursor_old_offset = 0; - - return TRUE; -} - -static Bool -_cursorRotate (xf86CrtcPtr pCrtc, int rotate) -{ - SECPtr pSec = SECPTR (pCrtc->scrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (pCrtcPriv->user_rotate == rotate) - return TRUE; - - if (!pCrtcPriv->cursor_show) - return TRUE; - - XDBG_TRACE (MCRS, "[%p] rotate(%d) \n", pCrtc, rotate); - - pCrtcPriv->user_rotate = rotate; - - if (pSec->enableCursor && pCrtcPriv->cursor_show) - { - //Send swap property to relative input device - _cursorFindRelativeDevice (pCrtc); - - if(pCrtcPriv->cursor_image) - { - pixman_image_unref(pCrtcPriv->cursor_image); - pCrtcPriv->cursor_image = NULL; - } - - if (pCrtcPriv->move_layer) - { - _overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer); - _overlayEnsureLayer (pCrtc); - - _cursorEnsureCursorImage (pCrtc); - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor, - SEC_CURSOR_W, SEC_CURSOR_H); - _cursorDrawCursor (pCrtc); - - int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x); - _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y); - } - else - { - pCrtcPriv->need_cursor_update = TRUE; - _cursorRestoreImage(pCrtc); - _cursorRegisterBlockHandler (pCrtc); - } - } - - pCrtcPriv->cursor_old_offset = 0; - - return TRUE; -} - -static Bool -_cursorChangeStatus (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECPtr pSec = SECPTR (pCrtc->scrn); - int new_value; - - if (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off) - new_value = FALSE; - else - new_value = TRUE; - - XDBG_TRACE (MCRS, "[%p] ref(%d) off(%d) value(%d=>%d) cursor(%d,%d) \n", pCrtc, - pCrtcPriv->ref_overlay, pCrtcPriv->need_off, pCrtcPriv->move_layer, - new_value, pCrtcPriv->cursor_show, pSec->enableCursor); - - /* layer off if needed */ - if (!pSec->enableCursor && pCrtcPriv->ovl_layer && secLayerTurnStatus (pCrtcPriv->ovl_layer)) - { - Bool turnoff = FALSE; - - if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off) - turnoff = TRUE; - if (!pCrtcPriv->ref_overlay) - turnoff = TRUE; - - if (turnoff) - { - _cursorDestroy (pCrtc); - return TRUE; - } - } - - /* layer on if needed */ - if (pCrtcPriv->ovl_layer && !secLayerTurnStatus (pCrtcPriv->ovl_layer)) - if (pSec->enableCursor || (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off)) - secLayerTurn (pCrtcPriv->ovl_layer, TRUE, FALSE); - - if (pCrtcPriv->move_layer == new_value) - return TRUE; - - pCrtcPriv->move_layer = new_value; - - if(pCrtcPriv->ovl_canvas) - { - XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_canvas); - pixman_image_unref(pCrtcPriv->ovl_canvas); - pCrtcPriv->ovl_canvas = NULL; - pCrtcPriv->need_draw_cursor = TRUE; - } - - if (pCrtcPriv->cursor_show) - _cursorShow (pCrtc); - - if (new_value && pCrtcPriv->ovl_vbuf_pixmap) - { - SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode; - pixman_image_t *old = pCrtcPriv->ovl_canvas; - - pCrtcPriv->ovl_canvas = NULL; - - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap, - pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay); - - _cursorRestoreImage (pCrtc); - - if(pCrtcPriv->ovl_canvas) - pixman_image_unref(pCrtcPriv->ovl_canvas); - - pCrtcPriv->ovl_canvas = old; - } - - if (!pCrtcPriv->ovl_layer) - _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer); - - if (pCrtcPriv->ovl_layer) - if (!secLayerIsVisible (pCrtcPriv->ovl_layer)) - secLayerShow (pCrtcPriv->ovl_layer); - - return TRUE; -} - -static void -_flipPixmapInit (xf86CrtcPtr pCrtc) -{ - ScrnInfoPtr pScrn = pCrtc->scrn; - SECPtr pSec = SECPTR (pScrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - int flip_backbufs = pSec->flip_bufs - 1; - int i; - - pCrtcPriv->flip_backpixs.lub = -1; - pCrtcPriv->flip_backpixs.num = flip_backbufs; - - pCrtcPriv->flip_backpixs.pix_free = calloc (flip_backbufs, sizeof(void*)); - XDBG_RETURN_IF_FAIL (pCrtcPriv->flip_backpixs.pix_free != NULL); - for (i = 0; i < flip_backbufs; i++) - pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; - pCrtcPriv->flip_backpixs.flip_pixmaps = calloc (flip_backbufs, sizeof(void*)); - pCrtcPriv->flip_backpixs.flip_draws = calloc (flip_backbufs, sizeof(void*)); -} - -static void -_flipPixmapDeinit (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - ScreenPtr pScreen = pCrtc->scrn->pScreen; - int i; - - for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) - { - pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; - if (pCrtcPriv->flip_backpixs.flip_pixmaps[i]) - { -#if USE_XDBG - if (pCrtcPriv->flip_backpixs.flip_draws[i]) - xDbgLogPListDrawRemoveRefPixmap (pCrtcPriv->flip_backpixs.flip_draws[i], - pCrtcPriv->flip_backpixs.flip_pixmaps[i]); -#endif - - (*pScreen->DestroyPixmap) (pCrtcPriv->flip_backpixs.flip_pixmaps[i]); - pCrtcPriv->flip_backpixs.flip_pixmaps[i] = NULL; - pCrtcPriv->flip_backpixs.flip_draws[i] = NULL; - } - } - pCrtcPriv->flip_backpixs.lub = -1; -} - -static xf86CrtcPtr -_secCrtcGetFromPipe (ScrnInfoPtr pScrn, int pipe) -{ - xf86CrtcConfigPtr pXf86CrtcConfig; - pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - int i; - - for (i = 0; i < pXf86CrtcConfig->num_output; i++) - { - pCrtc = pXf86CrtcConfig->crtc[i]; - pCrtcPriv = pCrtc->driver_private; - if (pCrtcPriv->pipe == pipe) - { - return pCrtc; - } - } - - return NULL; -} - - -static void -SECCrtcDpms(xf86CrtcPtr pCrtc, int pMode) -{ - -} - -static Bool -SECCrtcSetModeMajor(xf86CrtcPtr pCrtc, DisplayModePtr pMode, - Rotation rotation, int x, int y) -{ - ScrnInfoPtr pScrn = pCrtc->scrn; - SECPtr pSec = SECPTR (pScrn); - SECFbPtr pFb = pSec->pFb; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = pCrtcPriv->pSecMode; - tbm_bo bo = NULL, old_bo = NULL; - tbm_bo bo_accessibility[2] = {0,}, old_bo_accessibility[2] = {0,}; - int saved_x, saved_y; - Rotation saved_rotation; - DisplayModeRec saved_mode; - Bool ret = FALSE; - - XDBG_DEBUG(MDISP, - "SetModeMajor pMode:%d cur(%dx%d+%d+%d),rot:%d new(%dx%d+%d+%d),refresh(%f)rot:%d\n", - secCrtcID(pCrtcPriv), - pCrtc->mode.HDisplay, pCrtc->mode.VDisplay,pCrtc->x, pCrtc->y, - pCrtc->rotation, - pMode->HDisplay,pMode->VDisplay,x,y,pMode->VRefresh, - rotation); - - memcpy (&saved_mode, &pCrtc->mode, sizeof(DisplayModeRec)); - saved_x = pCrtc->x; - saved_y = pCrtc->y; - saved_rotation = pCrtc->rotation; - - memcpy (&pCrtc->mode, pMode, sizeof(DisplayModeRec)); - pCrtc->x = x; - pCrtc->y = y; - pCrtc->rotation = rotation; - - if (pSec->fake_root) - secDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); - else - secDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode); - - /* accessibility */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - XDBG_GOTO_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, fail); - XDBG_GOTO_IF_FAIL (pCrtcPriv->accessibility_back_bo != NULL, fail); - - old_bo_accessibility[0] = pCrtcPriv->accessibility_front_bo; - old_bo_accessibility[1] = pCrtcPriv->accessibility_back_bo; - - bo_accessibility[0] = secRenderBoCreate (pScrn, pMode->HDisplay, pMode->VDisplay); - bo_accessibility[1] = secRenderBoCreate (pScrn, pMode->HDisplay, pMode->VDisplay); - - pCrtcPriv->accessibility_front_bo = bo_accessibility[0]; - pCrtcPriv->accessibility_back_bo = bo_accessibility[1]; - } - - /* find bo which covers the requested mode of crtc */ - old_bo = pCrtcPriv->front_bo; - bo = secFbGetBo(pFb, x, y, pMode->HDisplay, pMode->VDisplay, FALSE); - XDBG_GOTO_IF_FAIL (bo != NULL, fail); - pCrtcPriv->front_bo = bo; - - ret = secCrtcApply(pCrtc); - XDBG_GOTO_IF_FAIL (ret == TRUE, fail); - - /* set the default external mode */ - secDisplayModeToKmode (pCrtc->scrn, &pSecMode->ext_connector_mode, pMode); - - /* accessibility */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - if (ret) - { - if (old_bo_accessibility[0]) - secRenderBoUnref (old_bo_accessibility[0]); - if (old_bo_accessibility[1]) - secRenderBoUnref (old_bo_accessibility[1]); - } - } - - return ret; -fail: - XDBG_ERROR(MDISP, "Fail crtc apply(crtc_id:%d, rotate:%d, %dx%d+%d+%d\n", - secCrtcID(pCrtcPriv), rotation, x, y, pCrtc->mode.HDisplay, pCrtc->mode.VDisplay); - - pCrtcPriv->front_bo = old_bo; - - /* accessibility */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - if (bo_accessibility[0]) - secRenderBoUnref (bo_accessibility[0]); - if (bo_accessibility[1]) - secRenderBoUnref (bo_accessibility[1]); - - pCrtcPriv->accessibility_front_bo = old_bo_accessibility[0]; - pCrtcPriv->accessibility_back_bo = old_bo_accessibility[1]; - } - - if (pSec->fake_root) - secDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode); - else - secDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode); - - memcpy (&pCrtc->mode, &saved_mode, sizeof(DisplayModeRec)); - pCrtc->x = saved_x; - pCrtc->y = saved_y; - pCrtc->rotation = saved_rotation; - - return ret; -} - -static void -SECCrtcSetCursorColors(xf86CrtcPtr pCrtc, int bg, int fg) -{ - XDBG_TRACE (MCRS, "[%p] \n", pCrtc); -} - -static void -SECCrtcSetCursorPosition (xf86CrtcPtr pCrtc, int x, int y) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECPtr pSec = SECPTR (pCrtc->scrn); - - pCrtcPriv->cursor_pos_x = x; - pCrtcPriv->cursor_pos_y = y; - - XDBG_DEBUG (MCRS, "[%p] (%d,%d) \n", pCrtc, x, y); - - if (!pSec->enableCursor) - return; - - if (!pCrtcPriv->cursor_show) - return; - - if (pCrtcPriv->move_layer) - { - _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor, - SEC_CURSOR_W, SEC_CURSOR_H); - _cursorEnsureCursorImage (pCrtc); - - int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x); - if (pCrtcPriv->cursor_old_offset != offset) - { - _cursorDrawCursor (pCrtc); - pCrtcPriv->cursor_old_offset = offset; - } - - _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y); - } - else - { - /* Draw cursor in block handler */ - pCrtcPriv->need_cursor_update = TRUE; - _cursorRestoreImage(pCrtc); - _cursorRegisterBlockHandler (pCrtc); - } -} - -static void -SECCrtcShowCursor (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show); - - if(pCrtcPriv->cursor_show) - return; - - pCrtcPriv->cursor_show = TRUE; - - _cursorShow (pCrtc); -} - -static void -SECCrtcHideCursor (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_TRACE (MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show); - - if(!pCrtcPriv->cursor_show) - return; - - pCrtcPriv->cursor_show = FALSE; - - _cursorHide (pCrtc); -} - -static void -SECCrtcLoadCursorArgb(xf86CrtcPtr pCrtc, CARD32 *image) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - if (image == NULL) - return; - - XDBG_TRACE (MCRS, "[%p] image(%p) \n", pCrtc, image); - - if (pCrtcPriv->backup_image) - pixman_image_unref (pCrtcPriv->backup_image); - - pCrtcPriv->backup_image = pixman_image_create_bits (PIXMAN_a8r8g8b8 - , SEC_CURSOR_W, SEC_CURSOR_H - , NULL - , 0); - - XDBG_RETURN_IF_FAIL (pCrtcPriv->backup_image != NULL); - - memcpy (pixman_image_get_data(pCrtcPriv->backup_image), image, SEC_CURSOR_W * SEC_CURSOR_H * 4); - - if(pCrtcPriv->cursor_image) - { - pixman_image_unref(pCrtcPriv->cursor_image); - pCrtcPriv->cursor_image = NULL; - } - - pCrtcPriv->need_cursor_update = TRUE; -} - - -static void * -SECCrtcShadowAllocate(xf86CrtcPtr pCrtc, int width, int height) -{ -#if 0 - ScrnInfoPtr scrn = pCrtc->scrn; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = pCrtcPriv->pSecMode; - unsigned long rotate_pitch; - uint32_t tiling; - int ret; - - pCrtcPriv->rotate_bo = intel_allocate_framebuffer (scrn, - width, height, - pSecMode->cpp, - &rotate_pitch, - &tiling); - - if (!pCrtcPriv->rotate_bo) - { - xf86DrvMsg (pCrtc->scrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow memory for rotated CRTC\n"); - return NULL; - } - - ret = drmModeAddFB (pSecMode->fd, width, height, pCrtc->scrn->depth, - pCrtc->scrn->bitsPerPixel, rotate_pitch, - pCrtcPriv->rotate_bo->handle, - &pCrtcPriv->rotate_fb_id); - if (ret < 0) - { - ErrorF ("failed to add rotate fb\n"); - drm_intel_bo_unreference (pCrtcPriv->rotate_bo); - return NULL; - } - - pCrtcPriv->rotate_pitch = rotate_pitch; - return pCrtcPriv->rotate_bo; -#else - return NULL; -#endif -} - -static PixmapPtr -SECCrtcShadowCreate(xf86CrtcPtr pCrtc, void *data, int width, int height) -{ -#if 0 - ScrnInfoPtr pScrn = pCrtc->scrn; - SECPtr pSEC = SECPtr (pScrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - PixmapPtr rotate_pixmap; - - if (!data) - { - data = SECCrtcShadowAllocate (pCrtc, width, height); - if (!data) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - return NULL; - } - } - if (pCrtcPriv->rotate_bo == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - return NULL; - } - - rotate_pixmap = GetScratchPixmapHeader (pScrn->pScreen, - width, height, - pScrn->depth, - pScrn->bitsPerPixel, - pCrtcPriv->rotate_pitch, - NULL); - - if (rotate_pixmap == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - return NULL; - } - -// intel_set_pixmap_bo(rotate_pixmap, pCrtcPriv->rotate_bo); - - pSEC->shadow_present = TRUE; - - return rotate_pixmap; -#else - return NULL; -#endif -} - -static void -SECCrtcShadowDestroy(xf86CrtcPtr pCrtc, PixmapPtr rotate_pixmap, void *data) -{ -#if 0 - ScrnInfoPtr pScrn = pCrtc->scrn; - SECPtr pSEC = SECPtr (pScrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = pCrtcPriv->mode; - - if (rotate_pixmap) - { - intel_set_pixmap_bo (rotate_pixmap, NULL); - FreeScratchPixmapHeader (rotate_pixmap); - } - - if (data) - { - /* Be sure to sync acceleration before the memory gets - * unbound. */ - drmModeRmFB (pSecMode->fd, pCrtcPriv ->rotate_fb_id); - pCrtcPriv ->rotate_fb_id = 0; - - tbm_bo_unreference (pCrtcPriv ->rotate_bo); - pCrtcPriv ->rotate_bo = NULL; - } - - pSEC->shadow_present = pSEC->use_shadow; -#else - return; -#endif -} - -static void -SECCrtcGammaSet(xf86CrtcPtr pCrtc, - CARD16 *red, CARD16 *green, CARD16 *blue, int size) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = pCrtcPriv->pSecMode; - - drmModeCrtcSetGamma(pSecMode->fd, secCrtcID(pCrtcPriv), - size, red, green, blue); -} - -static void -SECCrtcDestroy(xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - DRI2FrameEventPtr event_ref=NULL, event_next=NULL; - xorg_list_for_each_entry_safe (event_ref, event_next, &pCrtcPriv->pending_flips, crtc_pending_link) - { - free (event_ref); - } - - _flipPixmapDeinit (pCrtc); - - _cursorDestroy (pCrtc); - _cursorUnregisterBlockHandler (pCrtc); - -#if 1 - if (pCrtcPriv->pFpsDebug) - { - xDbgLogFpsDebugDestroy (pCrtcPriv->pFpsDebug); - pCrtcPriv->pFpsDebug = NULL; - } -#endif - - if (pCrtcPriv->accessibility_front_bo) - { - secRenderBoUnref (pCrtcPriv->accessibility_front_bo); - pCrtcPriv->accessibility_front_bo = NULL; - } - - if (pCrtcPriv->accessibility_back_bo) - { - secRenderBoUnref (pCrtcPriv->accessibility_back_bo); - pCrtcPriv->accessibility_back_bo = NULL; - } - - if (pCrtcPriv->backup_image) - { - pixman_image_unref(pCrtcPriv->backup_image); - pCrtcPriv->backup_image = NULL; - } - - if (pCrtcPriv->ovl_vbuf_cursor) - { - secUtilVideoBufferUnref (pCrtcPriv->ovl_vbuf_cursor); - pCrtcPriv->ovl_vbuf_cursor = NULL; - } - - if (pCrtcPriv->ovl_vbuf_pixmap) - { - secUtilVideoBufferUnref (pCrtcPriv->ovl_vbuf_pixmap); - pCrtcPriv->ovl_vbuf_pixmap = NULL; - } - - if (pCrtcPriv->ovl_layer) - { - secLayerUnref (pCrtcPriv->ovl_layer); - pCrtcPriv->ovl_layer = NULL; - } - - if (pCrtcPriv->mode_crtc) - drmModeFreeCrtc (pCrtcPriv->mode_crtc); - - if (pCrtcPriv->front_bo) - { - pCrtcPriv->front_bo = NULL; - } - - if (pCrtcPriv->back_bo) - { - secRenderBoUnref(pCrtcPriv->back_bo); - pCrtcPriv->back_bo = NULL; - } - - if( pCrtcPriv->flip_backpixs.pix_free != NULL ) - { - free(pCrtcPriv->flip_backpixs.pix_free); - pCrtcPriv->flip_backpixs.pix_free = NULL; - } - - if( pCrtcPriv->flip_backpixs.flip_pixmaps != NULL ) - { - free(pCrtcPriv->flip_backpixs.flip_pixmaps); - pCrtcPriv->flip_backpixs.flip_pixmaps = NULL; - } - - if( pCrtcPriv->flip_backpixs.flip_draws != NULL ) - { - free(pCrtcPriv->flip_backpixs.flip_draws); - pCrtcPriv->flip_backpixs.flip_draws = NULL; - } - - xorg_list_del (&pCrtcPriv->link); - free (pCrtcPriv); - - pCrtc->driver_private = NULL; -} - -static const xf86CrtcFuncsRec sec_crtc_funcs = -{ - .dpms = SECCrtcDpms, - .set_mode_major = SECCrtcSetModeMajor, - .set_cursor_colors = SECCrtcSetCursorColors, - .set_cursor_position = SECCrtcSetCursorPosition, - .show_cursor = SECCrtcShowCursor, - .hide_cursor = SECCrtcHideCursor, - .load_cursor_argb = SECCrtcLoadCursorArgb, - .shadow_create = SECCrtcShadowCreate, - .shadow_allocate = SECCrtcShadowAllocate, - .shadow_destroy = SECCrtcShadowDestroy, - .gamma_set = SECCrtcGammaSet, - .destroy = SECCrtcDestroy, -}; - -void -secCrtcInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num) -{ - xf86CrtcPtr pCrtc; - SECCrtcPrivPtr pCrtcPriv; - SECPtr pSec = SECPTR (pScrn); - -// secLogSetLevel("CRTC", 0); - - pCrtcPriv = calloc (sizeof (SECCrtcPrivRec), 1); - if (pCrtcPriv == NULL) - return; - - pCrtc = xf86CrtcCreate (pScrn, &sec_crtc_funcs); - if (pCrtc == NULL) - { - free (pCrtcPriv); - return; - } - - pCrtcPriv->idx = num; - pCrtcPriv->mode_crtc = drmModeGetCrtc (pSecMode->fd, - pSecMode->mode_res->crtcs[num]); - pCrtcPriv->move_layer = TRUE; - pCrtcPriv->user_rotate = RR_Rotate_0; - - pCrtcPriv->pSecMode = pSecMode; - pCrtc->driver_private = pCrtcPriv; - - pCrtcPriv->pipe = num; - pCrtcPriv->onoff = TRUE; - - xorg_list_init (&pCrtcPriv->pending_flips); - - pCrtcPriv->pCrtc = pCrtc; - -#if 1 - pCrtcPriv->pFpsDebug = xDbgLogFpsDebugCreate (); - if (pCrtcPriv->pFpsDebug == NULL) - { - free (pCrtcPriv); - return; - } -#endif - - if (pSec->enableCursor) - _cursorInit (pCrtc); - - _flipPixmapInit (pCrtc); - - xorg_list_add(&(pCrtcPriv->link), &(pSecMode->crtcs)); -} - -/* check the crtc is on */ -Bool -secCrtcOn(xf86CrtcPtr pCrtc) -{ - ScrnInfoPtr pScrn = pCrtc->scrn; - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - int i; - - if (!pCrtc->enabled) - return FALSE; - - /* Kernel manage CRTC status based out output config */ - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - if (pOutput->crtc == pCrtc && - secOutputDpmsStatus(pOutput) == DPMSModeOn) - return TRUE; - } - - return TRUE; -} - -Bool -secCrtcApply(xf86CrtcPtr pCrtc) -{ - ScrnInfoPtr pScrn = pCrtc->scrn; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - SECModePtr pSecMode = pCrtcPriv->pSecMode; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR (pCrtc->scrn); - uint32_t *output_ids; - int output_count = 0; - int fb_id, x, y; - int i; - Bool ret = FALSE; - SECFbBoDataPtr bo_data; - tbm_bo bo; - - output_ids = calloc (sizeof (uint32_t), xf86_config->num_output); - if (!output_ids) - return FALSE; - - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr pOutput = xf86_config->output[i]; - SECOutputPrivPtr pOutputPriv; - if (pOutput->crtc != pCrtc) - continue; - - pOutputPriv = pOutput->driver_private; - - /* modify the physical size of monitor */ - if (!strcmp(pOutput->name, "LVDS1")) - { - pOutput->mm_width = pOutputPriv->mode_output->mmWidth; - pOutput->mm_height = pOutputPriv->mode_output->mmHeight; - pOutput->conf_monitor->mon_width = pOutputPriv->mode_output->mmWidth; - pOutput->conf_monitor->mon_height = pOutputPriv->mode_output->mmHeight; - } - - output_ids[output_count] = pOutputPriv->mode_output->connector_id; - output_count++; - } - - if (!xf86CrtcRotate (pCrtc)) - goto done; - - pCrtc->funcs->gamma_set (pCrtc, pCrtc->gamma_red, pCrtc->gamma_green, - pCrtc->gamma_blue, pCrtc->gamma_size); - - /* accessilitity */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - tbm_bo temp; - bo = pCrtcPriv->accessibility_back_bo; - temp = pCrtcPriv->accessibility_front_bo; - pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo; - pCrtcPriv->accessibility_back_bo = temp; - } - else - { - bo = pCrtcPriv->front_bo; - } - - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - x = pCrtc->x-bo_data->pos.x1; - y = pCrtc->y-bo_data->pos.y1; - fb_id = bo_data->fb_id; - - if (pCrtcPriv->rotate_fb_id) - { - fb_id = pCrtcPriv->rotate_fb_id; - x = 0; - y = 0; - } - - XDBG_INFO (MDISP, "fb_id,%d name,%s width,%d height,%d, vrefresh,%d, accessibility,%d\n", - fb_id, pCrtcPriv->kmode.name, pCrtcPriv->kmode.hdisplay, - pCrtcPriv->kmode.vdisplay, pCrtcPriv->kmode.vrefresh, pCrtcPriv->bAccessibility); - - /* turn off the crtc if the same crtc is set already by another display mode - * before the set crtcs - */ - secDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_OFF); - - if (!pCrtcPriv->onoff) - secCrtcTurn (pCrtc, TRUE, FALSE, FALSE); - - /* for cache control */ - tbm_bo_map (bo, TBM_DEVICE_2D, TBM_OPTION_READ); - tbm_bo_unmap (bo); - - ret = drmModeSetCrtc(pSecMode->fd, secCrtcID(pCrtcPriv), - fb_id, x, y, output_ids, output_count, - &pCrtcPriv->kmode); - if (ret) - { - XDBG_INFO (MDISP, "failed to set mode: %s\n", strerror (-ret)); - ret = FALSE; - } - else - { - ret = TRUE; - - /* Force DPMS to On for all outputs, which the kernel will have done - * with the mode set. Also, restore the backlight level - */ - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr pOutput = xf86_config->output[i]; - SECOutputPrivPtr pOutputPriv; - - if (pOutput->crtc != pCrtc) - continue; - - pOutputPriv = pOutput->driver_private; - - /* TODO :: soolim :: check this out */ - secOutputDpmsSet(pOutput, DPMSModeOn); - pOutputPriv->dpms_mode = DPMSModeOn; - - /* update mode_encoder */ - drmModeFreeEncoder (pOutputPriv->mode_encoder); - pOutputPriv->mode_encoder = - drmModeGetEncoder (pSecMode->fd, pOutputPriv->mode_output->encoders[0]); - - /* set display connector and display set mode */ - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB) - { - secDisplaySetDispConnMode (pScrn, DISPLAY_CONN_MODE_HDMI); - /* TODO : find the display mode */ - secDisplaySetDispSetMode (pScrn, DISPLAY_SET_MODE_EXT); - - /* should be shown again when crtc on. */ - secLayerShowAll (pScrn, LAYER_OUTPUT_EXT); - } - else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - secDisplaySetDispConnMode (pScrn, DISPLAY_CONN_MODE_VIRTUAL); - /* TODO : find the display mode */ - secDisplaySetDispSetMode (pScrn, DISPLAY_SET_MODE_EXT); - - /* should be shown again when crtc on. */ - secLayerShowAll (pScrn, LAYER_OUTPUT_EXT); - } - else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS) - { - /* should be shown again when crtc on. */ - secLayerShowAll (pScrn, LAYER_OUTPUT_LCD); - } - else - XDBG_NEVER_GET_HERE (MDISP); - } - } - - secOutputDrmUpdate (pScrn); - - if (pScrn->pScreen) - xf86_reload_cursors (pScrn->pScreen); - -done: - free (output_ids); - return ret; -} - -Bool -secCrtcOverlayNeedOff (xf86CrtcPtr pCrtc, Bool need_off) -{ - SECCrtcPrivPtr pCrtcPriv; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE); - - pCrtcPriv->need_off = need_off; - - XDBG_TRACE (MCRS, "[%p] need_off(%d) \n", pCrtc, need_off); - - _cursorChangeStatus (pCrtc); - - return TRUE; -} - -Bool -secCrtcOverlayRef (xf86CrtcPtr pCrtc, Bool refer) -{ - SECCrtcPrivPtr pCrtcPriv; - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE); - - pCrtcPriv->ref_overlay = refer; - - XDBG_TRACE (MCRS, "[%p] refer(%d) \n", pCrtc, refer); - - _cursorChangeStatus (pCrtc); - - return TRUE; -} - -Bool -secCrtcCursorEnable (ScrnInfoPtr pScrn, Bool enable) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - SECCrtcPrivPtr pCur = NULL, pNext = NULL; - - xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->crtcs, link) - { - xf86CrtcPtr pCrtc = pCur->pCrtc; - int connector_type = secCrtcGetConnectType (pCrtc); - if (connector_type != DRM_MODE_CONNECTOR_Unknown) - _cursorEnable (pCrtc, enable); - } - - return TRUE; -} - -Bool -secCrtcCursorRotate (xf86CrtcPtr pCrtc, int rotate) -{ - return _cursorRotate (pCrtc, rotate); -} - -xf86CrtcPtr -secCrtcGetAtGeometry (ScrnInfoPtr pScrn, int x, int y, int width, int height) -{ - BoxRec box; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL); - - box.x1 = x; - box.y1 = y; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - - return secModeCoveringCrtc (pScrn, &box, NULL, NULL); -} - -int -secCrtcGetConnectType (xf86CrtcPtr pCrtc) -{ - xf86CrtcConfigPtr pCrtcConfig; - int i; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, DRM_MODE_CONNECTOR_Unknown); - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn); - XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, DRM_MODE_CONNECTOR_Unknown); - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - - if (pOutput->crtc == pCrtc) - return pOutputPriv->mode_output->connector_type; - } - - return DRM_MODE_CONNECTOR_Unknown; -} - -Bool -secCrtcIsFlipping (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - pCrtcPriv = pCrtc->driver_private; - - /* if isFlipping is true, return true */ - if (pCrtcPriv->is_flipping) - return TRUE; - - /* if there is pending_flips in the list, return true */ - if (!xorg_list_is_empty (&pCrtcPriv->pending_flips)) - return TRUE; - - return FALSE; -} - - -DRI2FrameEventPtr -secCrtcGetPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) -{ - SECCrtcPrivPtr pCrtcPriv; - DRI2FrameEventPtr item=NULL, tmp=NULL; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL); - pCrtcPriv = pCrtc->driver_private; - - if (xorg_list_is_empty (&pCrtcPriv->pending_flips)) - return NULL; - - xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link) - { - if (item == pEvent) - return item; - } - - return NULL; -} - - - -DRI2FrameEventPtr -secCrtcGetFirstPendingFlip (xf86CrtcPtr pCrtc) -{ - DRI2FrameEventPtr pEvent = NULL; - SECCrtcPrivPtr pCrtcPriv; - DRI2FrameEventPtr item=NULL, tmp=NULL; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL); - pCrtcPriv = pCrtc->driver_private; - - if (xorg_list_is_empty (&pCrtcPriv->pending_flips)) - return NULL; - - xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link) - { - /* get the last item in the circular list ( last item is at last_item.next==head)*/ - if (item->crtc_pending_link.next == &pCrtcPriv->pending_flips) - { - pEvent = item; - break; - } - } - - return pEvent; -} - -void -secCrtcAddPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) -{ - SECCrtcPrivPtr pCrtcPriv; - - XDBG_RETURN_IF_FAIL (pCrtc != NULL); - - pCrtcPriv = pCrtc->driver_private; - - xorg_list_add(&(pEvent->crtc_pending_link), &(pCrtcPriv->pending_flips)); -} - -void -secCrtcRemovePendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent) -{ - SECCrtcPrivPtr pCrtcPriv; - DRI2FrameEventPtr item=NULL, tmp=NULL; - - XDBG_RETURN_IF_FAIL (pCrtc != NULL); - - pCrtcPriv = pCrtc->driver_private; - - if (xorg_list_is_empty (&pCrtcPriv->pending_flips)) - return; - - xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link) - { - if (item == pEvent) - { - xorg_list_del(&item->crtc_pending_link); - } - } -} - -static Bool -_secCrtcExecAccessibilityScaleNegative (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo) -{ - XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); - - SECPtr pSec = SECPTR(pCrtc->scrn); - - if (pSec->isLcdOff) - { - XDBG_INFO (MDISP, "Accessibility execute : LCD IS OFF\n"); - return TRUE; - } - - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - XDBG_RETURN_VAL_IF_FAIL(src_bo != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL(dst_bo != NULL, FALSE); - - SECFbBoDataPtr src_bo_data; - SECFbBoDataPtr dst_bo_data; - G2dColorKeyMode mode; - G2dImage *srcImg = NULL, *dstImg = NULL; - unsigned int src_bo_w, src_bo_h, src_bo_stride; - unsigned int dst_bo_w, dst_bo_h, dst_bo_stride; - int src_x, src_y; - unsigned int src_w, src_h; - int negative = 0; - tbm_bo_handle src_bo_handle; - tbm_bo_handle dst_bo_handle; - - tbm_bo_get_user_data (src_bo, TBM_BO_DATA_FB, (void * *)&src_bo_data); - XDBG_RETURN_VAL_IF_FAIL(src_bo_data != NULL, FALSE); - - tbm_bo_get_user_data (dst_bo, TBM_BO_DATA_FB, (void * *)&dst_bo_data); - XDBG_RETURN_VAL_IF_FAIL(dst_bo_data != NULL, FALSE); - - src_bo_w = src_bo_data->pos.x2 - src_bo_data->pos.x1; - src_bo_h = src_bo_data->pos.y2 - src_bo_data->pos.y1; - src_bo_stride = src_bo_w * 4; - - dst_bo_w = dst_bo_data->pos.x2 - dst_bo_data->pos.x1; - dst_bo_h = dst_bo_data->pos.y2 - dst_bo_data->pos.y1; - dst_bo_stride = dst_bo_w * 4; - - mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; - src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); - - srcImg = g2d_image_create_bo (mode, src_bo_w, src_bo_h, src_bo_handle.u32, src_bo_stride); - dstImg = g2d_image_create_bo (mode, dst_bo_w, dst_bo_h, dst_bo_handle.u32, dst_bo_stride); - if (!srcImg || !dstImg) - { - XDBG_ERROR (MDISP, "Accessibility : Fail to create g2d_image\n"); - tbm_bo_unmap(src_bo); - tbm_bo_unmap(dst_bo); - - if (srcImg) - g2d_image_free (srcImg); - - if (dstImg) - g2d_image_free (dstImg); - - return FALSE; - } - - if (pCrtcPriv->accessibility_status == ACCESSIBILITY_MODE_NEGATIVE) - { - negative = 1; - } - - if (pCrtcPriv->bScale) - { - src_x = pCrtcPriv->sx; - src_y = pCrtcPriv->sy; - src_w = pCrtcPriv->sw; - src_h = pCrtcPriv->sh; - } - else - { - src_x = 0; - src_y = 0; - src_w = src_bo_w; - src_h = src_bo_h; - } - - util_g2d_copy_with_scale(srcImg, dstImg, - src_x, src_y, src_w, src_h, - 0, 0, dst_bo_w, dst_bo_h, - negative); - g2d_exec (); - - tbm_bo_unmap(src_bo); - tbm_bo_unmap(dst_bo); - - g2d_image_free (srcImg); - g2d_image_free (dstImg); - - return TRUE; -} - -static Bool -_secCrtcExecRotate (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo) -{ - SECPtr pSec; - SECCrtcPrivPtr pCrtcPriv; - struct drm_exynos_ipp_queue_buf buf; - - XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->screen_rotate_prop_id > 0, FALSE); - - pSec = SECPTR(pCrtc->scrn); - if (pSec->isLcdOff) - { - XDBG_INFO (MDISP, "screen rotate execute : LCD IS OFF\n"); - return TRUE; - } - - CLEAR (buf); - buf.ops_id = EXYNOS_DRM_OPS_SRC; - buf.buf_type = IPP_BUF_ENQUEUE; - buf.prop_id = pCrtcPriv->screen_rotate_prop_id; - buf.handle[0] = (__u32)tbm_bo_get_handle (src_bo, TBM_DEVICE_DEFAULT).u32; - - if (!secDrmIppQueueBuf (pCrtc->scrn, &buf)) - return FALSE; - - CLEAR (buf); - buf.ops_id = EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_ENQUEUE; - buf.prop_id = pCrtcPriv->screen_rotate_prop_id; - buf.handle[0] = (__u32)tbm_bo_get_handle (dst_bo, TBM_DEVICE_DEFAULT).u32; - - if (!secDrmIppQueueBuf (pCrtc->scrn, &buf)) - return FALSE; - - if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_STOP) - { - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; - ctrl.ctrl = IPP_CTRL_PLAY; - secDrmIppCmdCtrl (pCrtc->scrn, &ctrl); - pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PLAY; - - XDBG_INFO (MDISP, "screen rotate ipp(id:%d) play\n", - pCrtcPriv->screen_rotate_prop_id); - } - else if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_PAUSE) - { - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; - ctrl.ctrl = IPP_CTRL_RESUME; - secDrmIppCmdCtrl (pCrtc->scrn, &ctrl); - pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_RESUME; - - XDBG_INFO (MDISP, "screen rotate ipp(id:%d) resume\n", - pCrtcPriv->screen_rotate_prop_id); - } - - return TRUE; -} - -Bool -secCrtcExecAccessibility (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - Bool ret = FALSE; - CARD32 elapsed = 0; - SECPtr pSec = SECPTR(pCrtc->scrn); - - tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_ACCESS) - elapsed = GetTimeInMillis (); - - if (pCrtcPriv->screen_rotate_degree > 0) - ret = _secCrtcExecRotate (pCrtc, src_bo, dst_bo); - else if (pCrtcPriv->bAccessibility) - ret = _secCrtcExecAccessibilityScaleNegative (pCrtc, src_bo, dst_bo); - else - XDBG_NEVER_GET_HERE (MDISP); - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_ACCESS) - ErrorF ("Access exec: %3ld ms \n", GetTimeInMillis()-elapsed); - - tbm_bo_unmap(src_bo); - tbm_bo_unmap(dst_bo); - - return ret; -} - -Bool -secCrtcEnableAccessibility (xf86CrtcPtr pCrtc) -{ - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - ScrnInfoPtr pScrn = pCrtc->scrn; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - /* accessibility and screen rotate can't be enable at the same time */ - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->screen_rotate_degree == 0, FALSE); - - int bAccessibility = (pCrtcPriv->accessibility_status | pCrtcPriv->bScale); - int width = pCrtc->mode.HDisplay; - int height = pCrtc->mode.VDisplay; - - SECLayer *pLayer = NULL; - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn); - xf86OutputPtr pOutput = NULL; - int i; - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pTemp = pCrtcConfig->output[i]; - if (pTemp->crtc == pCrtc) - { - pOutput = pTemp; - break; - } - } - XDBG_RETURN_VAL_IF_FAIL (pOutput != NULL, FALSE); - - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - SECLayerOutput output = LAYER_OUTPUT_LCD; - - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown) - { - output = LAYER_OUTPUT_LCD; - } - else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - output = LAYER_OUTPUT_EXT; - } - else - XDBG_NEVER_GET_HERE (MACCE); - - - if (bAccessibility) - { - if (!pCrtcPriv->accessibility_front_bo) - { - pCrtcPriv->accessibility_front_bo = secRenderBoCreate (pScrn, width, height); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, FALSE); - } - - pCrtcPriv->bAccessibility = TRUE; - - /* do accessibility */ - if (!secCrtcExecAccessibility (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_front_bo)) - { - XDBG_ERROR (MDISP, "Accessibility : Fail to execute accessibility\n"); - secRenderBoUnref(pCrtcPriv->accessibility_front_bo); - pCrtcPriv->accessibility_front_bo = NULL; - pCrtcPriv->bAccessibility = FALSE; - return FALSE; - } - - XDBG_INFO (MDISP, "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n", - pCrtcPriv->accessibility_status, - pCrtcPriv->bScale, pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh); - - /* layer update */ - pLayer = secLayerFind (output, LAYER_UPPER); - if (pLayer && secLayerIsVisible (pLayer)) - secLayerUpdate (pLayer); - - /* set crtc when accessibility buffer destroy, or drmvlank is error */ - if (!secCrtcApply (pCrtc)) - { - - XDBG_ERROR (MDISP, "Accessibility : Fail to set crtc\n"); - secRenderBoUnref(pCrtcPriv->accessibility_front_bo); - pCrtcPriv->accessibility_front_bo = NULL; - pCrtcPriv->bAccessibility = FALSE; - return FALSE; - } - - } - else - { - pCrtcPriv->bAccessibility = FALSE; - - XDBG_INFO (MDISP, "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n", - pCrtcPriv->accessibility_status, - pCrtcPriv->bScale, pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh); - - if (!secCrtcApply (pCrtc)) - { - XDBG_ERROR (MDISP, "Accessibility : Fail to set crtc\n"); - pCrtcPriv->bAccessibility = TRUE; - return FALSE; - } - - /* layer update */ - pLayer = secLayerFind (output, LAYER_UPPER); - if (pLayer && secLayerIsVisible (pLayer)) - secLayerUpdate (pLayer); - } - - return TRUE; -} - -Bool -secCrtcEnableScreenRotate (xf86CrtcPtr pCrtc, Bool enable) -{ -#ifdef _F_WEARABLE_FEATURE_ - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - ScrnInfoPtr pScrn = pCrtc->scrn; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - int width = pCrtc->mode.HDisplay; - int height = pCrtc->mode.VDisplay; - int degree = pCrtcPriv->screen_rotate_degree; - - /* accessibility and screen rotate can't be enable at the same time */ - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->bAccessibility == FALSE, FALSE); - - if (enable) - { - struct drm_exynos_ipp_property property; - int prop_id; - - if (!pCrtcPriv->accessibility_front_bo) - { - pCrtcPriv->accessibility_front_bo = secRenderBoCreate (pScrn, width, height); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, FALSE); - - pCrtcPriv->accessibility_back_bo = secRenderBoCreate (pScrn, width, height); - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_back_bo != NULL, FALSE); - } - - prop_id = pCrtcPriv->screen_rotate_prop_id; - if (prop_id != 0) - { - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; - ctrl.ctrl = IPP_CTRL_PAUSE; - secDrmIppCmdCtrl (pScrn, &ctrl); - pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PAUSE; - XDBG_INFO (MDISP, "screen rotate ipp(id:%d) pause\n", - pCrtcPriv->screen_rotate_prop_id); - } - else - pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP; - - CLEAR (property); - property.config[0].ops_id = EXYNOS_DRM_OPS_SRC; - property.config[0].fmt = DRM_FORMAT_ARGB8888; - property.config[0].sz.hsize = (__u32)width; - property.config[0].sz.vsize = (__u32)height; - property.config[0].pos.x = 0; - property.config[0].pos.y = 0; - property.config[0].pos.w = (__u32)width; - property.config[0].pos.h = (__u32)height; - property.config[1].ops_id = EXYNOS_DRM_OPS_DST; - if (degree % 360 == 90) - property.config[1].degree = EXYNOS_DRM_DEGREE_90; - else if (degree % 360 == 180) - property.config[1].degree = EXYNOS_DRM_DEGREE_180; - else if (degree % 360 == 270) - property.config[1].degree = EXYNOS_DRM_DEGREE_270; - else - property.config[1].degree = EXYNOS_DRM_DEGREE_0; - property.config[1].fmt = DRM_FORMAT_ARGB8888; - property.config[1].sz.hsize = width; - property.config[1].sz.vsize = height; - property.config[1].pos.x = (__u32)0; - property.config[1].pos.y = (__u32)0; - property.config[1].pos.w = (__u32)width; - property.config[1].pos.h = (__u32)height; - - property.cmd = IPP_CMD_M2M; - property.type = IPP_SYNC_WORK; - property.prop_id = prop_id; - - prop_id = secDrmIppSetProperty (pScrn, &property); - XDBG_RETURN_VAL_IF_FAIL (prop_id != 0, FALSE); - pCrtcPriv->screen_rotate_prop_id = prop_id; - - XDBG_INFO (MDISP, "screen rotate ipp(id:%d) start\n", prop_id); - } - else - { - if (pCrtcPriv->screen_rotate_prop_id > 0) - { - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id; - ctrl.ctrl = IPP_CTRL_STOP; - secDrmIppCmdCtrl (pScrn, &ctrl); - pCrtcPriv->screen_rotate_prop_id = 0; - pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP; - XDBG_INFO (MDISP, "screen rotate ipp(id:%d) stop\n", - pCrtcPriv->screen_rotate_prop_id); - } - } -#endif - return TRUE; -} - -Bool -secCrtcScreenRotate (xf86CrtcPtr pCrtc, int degree) -{ -#ifdef _F_WEARABLE_FEATURE_ - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - ScrnInfoPtr pScrn = pCrtc->scrn; - SECPtr pSec = SECPTR(pCrtc->scrn); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - CARD32 elapsed[3] = {0,}; - - if (pCrtcPriv->screen_rotate_degree == degree) - return TRUE; - - /* accessibility and screen rotate can't be enable at the same time */ - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->bAccessibility == FALSE, FALSE); - - pCrtcPriv->screen_rotate_degree = degree; - - if (pSec->isLcdOff) - { - XDBG_INFO (MDISP, "screen rotate(degree:%d)\n", degree); - secVideoScreenRotate (pScrn, degree); - return TRUE; - } - - elapsed[0] = GetTimeInMillis (); - - if (degree > 0) - { - secCrtcEnableScreenRotate (pCrtc, TRUE); - - /* do accessibility */ - if (!secCrtcExecAccessibility (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_back_bo)) - { - secRenderBoUnref(pCrtcPriv->accessibility_front_bo); - pCrtcPriv->accessibility_front_bo = NULL; - secRenderBoUnref(pCrtcPriv->accessibility_back_bo); - pCrtcPriv->accessibility_back_bo = NULL; - return FALSE; - } - } - else - secCrtcEnableScreenRotate (pCrtc, FALSE); - - elapsed[1] = GetTimeInMillis (); - - secCrtcApply (pCrtc); - - elapsed[2] = GetTimeInMillis (); - - secVideoScreenRotate (pScrn, degree); - - XDBG_INFO (MDISP, "screen rotate done(degree:%d, dur:%ld~%ld~%ld ms)\n", - degree, elapsed[1]-elapsed[0],elapsed[2]-elapsed[1], - GetTimeInMillis()-elapsed[2]); -#endif - return TRUE; -} - -Bool -secCrtcTurn (xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user) -{ - SECModePtr pSecMode = SECPTR (pCrtc->scrn)->pSecMode; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - int crtc_id = secCrtcID(pCrtcPriv); - int mode; - - mode = (onoff > 0) ? 0 : 1; - - if (pCrtcPriv->onoff == onoff) - { - pCrtcPriv->onoff_always = always; - XDBG_ERROR (MDISP, "Crtc(%d) UI layer is '%s'%s\n", - crtc_id, (onoff)?"ON":"OFF", (always)?"(always).":"."); - return TRUE; - } - - if (pCrtcPriv->onoff_always) - if (!always) - { - XDBG_ERROR (MDISP, "Crtc(%d) UI layer can't be '%s'.\n", crtc_id, (onoff)?"ON":"OFF"); - return FALSE; - } - - /* 0 : normal, 1 : blank, 2 : defer */ - if (!secUtilSetDrmProperty (pSecMode, crtc_id, - DRM_MODE_OBJECT_CRTC, "mode", mode)) - { - XDBG_ERROR (MDISP, "SetDrmProperty failed. crtc(%d) onoff(%d) \n", crtc_id, onoff); - return FALSE; - } - - pCrtcPriv->onoff = onoff; - pCrtcPriv->onoff_always = always; - - XDBG_INFO (MDISP, "%s >> crtc(%d) UI layer '%s'%s\n", (user)?"user":"Xorg", - crtc_id, (onoff)?"ON":"OFF", (always)?"(always).":"."); - - return TRUE; -} - -Bool -secCrtcCheckOn (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - return pCrtcPriv->onoff; -} - -/* return true if there is no flip pixmap available */ -Bool -secCrtcFullFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe) -{ - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - int i; - - pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe); - XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - - /* there is a free flip pixmap, return false */ - for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) - { - if (pCrtcPriv->flip_backpixs.pix_free[i]) - { - return FALSE; - } - } - - XDBG_WARNING (MFLIP, "no free flip pixmap\n"); - - return TRUE; -} - -#define GET_NEXT_IDX(idx, max) (((idx+1) % (max))) -PixmapPtr -secCrtcGetFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, DrawablePtr pDraw, unsigned int usage_hint) -{ - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - PixmapPtr pPixmap = NULL; - ScreenPtr pScreen = pScrn->pScreen; - int i; - int check_release = 0; - - pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe); - XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - - /* check if there is free flip pixmaps */ - if (secCrtcFullFreeFlipPixmap(pScrn, crtc_pipe)) - { - /* case : flip pixmap is never release - if flip_count is 0 where there is no uncompleted pageflipping, - release the flip_pixmap which occupied by a drawable. */ - if (pCrtcPriv->flip_count == 0) - { - secCrtcRelAllFlipPixmap (pScrn, crtc_pipe); - check_release = 1; - XDBG_WARNING (MFLIP, "@@ release the drawable pre-occuiped the flip_pixmap\n"); - } - - /* return null, if there is no flip_backpixmap which can release */ - if (!check_release) - return NULL; - } - - /* return flip pixmap */ - for (i = GET_NEXT_IDX(pCrtcPriv->flip_backpixs.lub, pCrtcPriv->flip_backpixs.num) - ; i < pCrtcPriv->flip_backpixs.num - ; i = GET_NEXT_IDX(i, pCrtcPriv->flip_backpixs.num)) - { - if (pCrtcPriv->flip_backpixs.pix_free[i]) - { - if (pCrtcPriv->flip_backpixs.flip_pixmaps[i]) - { - pPixmap = pCrtcPriv->flip_backpixs.flip_pixmaps[i]; - XDBG_DEBUG (MFLIP, "the index(%d, %d) of the flip pixmap in pipe(%d) is set\n", - i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe); - } - else - { - pPixmap = (*pScreen->CreatePixmap) (pScreen, - pDraw->width, - pDraw->height, - pDraw->depth, - usage_hint); - XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL); - pCrtcPriv->flip_backpixs.flip_pixmaps[i] = pPixmap; - - XDBG_DEBUG (MFLIP, - "the index(%d, %d) of the flip pixmap in pipe(%d) is created\n", - i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe); - } - -#if USE_XDBG - if (pCrtcPriv->flip_backpixs.flip_draws[i] && - (pCrtcPriv->flip_backpixs.flip_draws[i] != pDraw)) - { - xDbgLogPListDrawRemoveRefPixmap (pCrtcPriv->flip_backpixs.flip_draws[i], - pCrtcPriv->flip_backpixs.flip_pixmaps[i]); - } -#endif - - pCrtcPriv->flip_backpixs.pix_free[i] = FALSE; - pCrtcPriv->flip_backpixs.flip_draws[i] = pDraw; - pCrtcPriv->flip_backpixs.lub = i; - -#if USE_XDBG - xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap); -#endif - break; - } - } - - return pPixmap; -} - -void -secCrtcRelFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, PixmapPtr pPixmap) -{ - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - int i; - - pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe); - XDBG_RETURN_IF_FAIL(pCrtc != NULL); - - pCrtcPriv = pCrtc->driver_private; - - /* release flip pixmap */ - for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) - { - if (pPixmap == pCrtcPriv->flip_backpixs.flip_pixmaps[i]) - { - pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; - /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL;*/ - - XDBG_DEBUG (MFLIP, "the index(%d, %d) of the flip pixmap in pipe(%d) is unset\n", - i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe); - break; - } - } -} - -void -secCrtcRelAllFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe) -{ - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - int i; - - pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe); - XDBG_RETURN_IF_FAIL(pCrtc != NULL); - - pCrtcPriv = pCrtc->driver_private; - - /* release flip pixmap */ - for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++) - { - pCrtcPriv->flip_backpixs.pix_free[i] = TRUE; - /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL;*/ - - XDBG_DEBUG (MFLIP, - "the index(%d) of the flip draw in pipe(%d) is unset\n", - i, crtc_pipe); - } -} - -void -secCrtcRemoveFlipPixmap (xf86CrtcPtr pCrtc) -{ - _flipPixmapDeinit (pCrtc); -} - -void -secCrtcCountFps(xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = NULL; - int conn_type; - - if (!pCrtc->enabled) - return; - - pCrtcPriv = pCrtc->driver_private; - conn_type = secCrtcGetConnectType (pCrtc); - - xDbgLogFpsDebugCount (pCrtcPriv->pFpsDebug, conn_type); -} diff --git a/src/crtcconfig/sec_crtc.h b/src/crtcconfig/sec_crtc.h deleted file mode 100755 index 64d4a44..0000000 --- a/src/crtcconfig/sec_crtc.h +++ /dev/null @@ -1,170 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 __SEC_CRTC_H__ -#define __SEC_CRTC_H__ - -#include "sec_display.h" -#include "sec_layer.h" -#include "sec_util.h" - -typedef enum -{ - ACCESSIBILITY_MODE_NONE, - ACCESSIBILITY_MODE_NEGATIVE, -}ACCESSIBILITY_STATUS; - -typedef struct _secCrtcPriv -{ - SECModePtr pSecMode; - drmModeModeInfo kmode; - drmModeCrtcPtr mode_crtc; - int pipe; - - int idx; - tbm_bo front_bo; - tbm_bo back_bo; - - /* for pageflip */ - unsigned int fe_frame; - unsigned int fe_tv_sec; - unsigned int fe_tv_usec; - DRI2FrameEventPtr flip_info; /* pending flips : flipping must garauntee to do it sequentially */ - struct xorg_list pending_flips; - Bool is_flipping; /* check flipping */ - Bool is_fb_blit_flipping; - int flip_count; /* check flipping completed (check pairs of request_flip and complete_flip */ - struct { - int num; /* number of flip back pixmaps */ - int lub; /* Last used backbuffer */ - Bool *pix_free; /* flags for a flip pixmap to be free */ - DrawablePtr *flip_draws; - PixmapPtr *flip_pixmaps; /* back flip pixmaps in a crtc */ - } flip_backpixs; - -#if 1 - /* for fps debug */ - FpsDebugPtr pFpsDebug; -#endif - - /* overlay(cursor) */ - Bool need_off; - Bool ref_overlay; - Bool move_layer; - Bool cursor_show; - Bool need_draw_cursor; - SECLayer *ovl_layer; - SECVideoBuf *ovl_vbuf_cursor; - SECVideoBuf *ovl_vbuf_pixmap; - Bool need_cursor_update; - Bool registered_block_handler; - int user_rotate; - int cursor_old_offset; - int cursor_pos_x; - int cursor_pos_y; - int cursor_win_x; - int cursor_win_y; - BoxRec saved_box; - pixman_image_t *ovl_canvas; - pixman_image_t *saved_image; - pixman_image_t *cursor_image; - pixman_image_t *backup_image; - - tbm_bo rotate_bo; - uint32_t rotate_pitch; - uint32_t rotate_fb_id; - - /* crtc rotate by display conf */ - Rotation rotate; - - /* Accessibility */ - tbm_bo accessibility_front_bo; - tbm_bo accessibility_back_bo; - Bool bAccessibility; - ACCESSIBILITY_STATUS accessibility_status; - Bool bScale; - int sx, sy, sw, sh; - - /* screen rotate */ - int screen_rotate_degree; - int screen_rotate_prop_id; - int screen_rotate_ipp_status; - - Bool onoff; - Bool onoff_always; - - xf86CrtcPtr pCrtc; - struct xorg_list link; -} SECCrtcPrivRec, *SECCrtcPrivPtr; - -void secCrtcInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num); -Bool secCrtcOn (xf86CrtcPtr pCrtc); -Bool secCrtcApply (xf86CrtcPtr pCrtc); - -Bool secCrtcOverlayNeedOff (xf86CrtcPtr pCrtc, Bool need_off); -Bool secCrtcOverlayRef (xf86CrtcPtr pCrtc, Bool refer); -Bool secCrtcCursorEnable (ScrnInfoPtr pScrn, Bool enable); -Bool secCrtcCursorRotate (xf86CrtcPtr pCrtc, int rotate); - -Bool secCrtcScreenRotate (xf86CrtcPtr pCrtc, int degree); -Bool secCrtcEnableScreenRotate (xf86CrtcPtr pCrtc, Bool enable); - -xf86CrtcPtr secCrtcGetAtGeometry (ScrnInfoPtr pScrn, int x, int y, int width, int height); -int secCrtcGetConnectType (xf86CrtcPtr pCrtc); - -Bool secCrtcIsFlipping (xf86CrtcPtr pCrtc); -void secCrtcAddPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent); -void secCrtcRemovePendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent); -DRI2FrameEventPtr secCrtcGetPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent); -DRI2FrameEventPtr secCrtcGetFirstPendingFlip (xf86CrtcPtr pCrtc); - -Bool secCrtcEnableAccessibility (xf86CrtcPtr pCrtc); -Bool secCrtcExecAccessibility (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo); - -Bool secCrtcTurn (xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user); -Bool secCrtcCheckOn (xf86CrtcPtr pCrtc); - -Bool secCrtcFullFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe); -PixmapPtr secCrtcGetFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, DrawablePtr pDraw, unsigned int usage_hint); -void secCrtcRelFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, PixmapPtr pPixmap); -void secCrtcRelAllFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe); -void secCrtcRemoveFlipPixmap (xf86CrtcPtr pCrtc); - -void secCrtcCountFps(xf86CrtcPtr pCrtc); - -static inline int -secCrtcID(SECCrtcPrivPtr pCrtcPriv) -{ - return pCrtcPriv->mode_crtc->crtc_id; -} - - -#endif /* __SEC_CRTC_H__ */ - diff --git a/src/crtcconfig/sec_display.c b/src/crtcconfig/sec_display.c deleted file mode 100755 index 051903e..0000000 --- a/src/crtcconfig/sec_display.c +++ /dev/null @@ -1,1681 +0,0 @@ -/* - * Copyright © 2007 Red Hat, Inc. - * - * 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, sublicense, - * 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 NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS 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. - * - * Authors: - * Dave Airlie <airlied@redhat.com> - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdint.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <poll.h> -#include <dirent.h> - -#include <X11/extensions/dpmsconst.h> -#include <xorgVersion.h> -#include <X11/Xatom.h> -#include <xf86Crtc.h> -#include <xf86DDC.h> -#include <xf86cmap.h> -#include <sec.h> - -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_plane.h" -#include "sec_display.h" -#include "sec_video_fourcc.h" -#include "sec_wb.h" -#include "sec_converter.h" -#include "sec_util.h" -#include "sec_xberc.h" - -#include <exynos_drm.h> - -static Bool SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height); -static void SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event); -static void SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); -static void SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); -static void SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); - -static const xf86CrtcConfigFuncsRec sec_xf86crtc_config_funcs = -{ - SECCrtcConfigResize -}; - -static void -_secDisplaySetDrmEventCtx(SECModePtr pSecMode) -{ - pSecMode->event_context.vblank_handler = SECModeVblankHandler; - pSecMode->event_context.page_flip_handler = SECModePageFlipHandler; - pSecMode->event_context.g2d_handler = SECModeG2dHandler; - pSecMode->event_context.ipp_handler = SECModeIppHandler; -} - -static int -_secSetMainMode (ScrnInfoPtr pScrn, SECModePtr pSecMode) -{ - xf86CrtcConfigPtr pXf86CrtcConfig; - pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - int i; - - for (i = 0; i < pXf86CrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pXf86CrtcConfig->output[i]; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown) - { - memcpy (&pSecMode->main_lcd_mode, pOutputPriv->mode_output->modes, sizeof(drmModeModeInfo)); - return 1; - } - } - - return -1; -} - -static void -_secDisplayRemoveFlipPixmaps (ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - int c; - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; - int conn_type = secCrtcGetConnectType (pCrtc); - if (conn_type == DRM_MODE_CONNECTOR_Unknown) - secCrtcRemoveFlipPixmap (pCrtc); - } -} - -static void -_saveFrameBuffer (ScrnInfoPtr pScrn, tbm_bo bo, int w, int h) -{ - SECPtr pSec = SECPTR(pScrn); - char file[128]; - SECFbBoDataPtr bo_data; - - if (!pSec->dump_info) - return; - - tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data); - XDBG_RETURN_IF_FAIL(bo_data != NULL); - - snprintf (file, sizeof(file), "%03d_fb_%d.bmp", pSec->flip_cnt, bo_data->fb_id); - secUtilDoDumpBmps (pSec->dump_info, bo, w, h, NULL, file); - pSec->flip_cnt++; -} - -static int -secHandleEvent (int fd, secDrmEventContextPtr evctx) -{ -#define MAX_BUF_SIZE 1024 - - char buffer[MAX_BUF_SIZE]; - unsigned int len, i; - struct drm_event *e; - - /* The DRM read semantics guarantees that we always get only - * complete events. */ - len = read (fd, buffer, sizeof buffer); - if (len == 0) - { - XDBG_WARNING (MDISP, "warning: the size of the drm_event is 0.\n"); - return 0; - } - if (len < sizeof *e) - { - XDBG_WARNING (MDISP, "warning: the size of the drm_event is less than drm_event structure.\n"); - return -1; - } - if (len > MAX_BUF_SIZE - sizeof (struct drm_exynos_ipp_event)) - { - XDBG_WARNING (MDISP, "warning: the size of the drm_event can be over the maximum size.\n"); - return -1; - } - - i = 0; - while (i < len) - { - e = (struct drm_event *) &buffer[i]; - switch (e->type) - { - case DRM_EVENT_VBLANK: - { - struct drm_event_vblank *vblank; - - if (evctx->vblank_handler == NULL) - break; - - vblank = (struct drm_event_vblank *) e; - evctx->vblank_handler (fd, - vblank->sequence, - vblank->tv_sec, - vblank->tv_usec, - (void *)((unsigned long)vblank->user_data)); - } - break; - case DRM_EVENT_FLIP_COMPLETE: - { - struct drm_event_vblank *vblank; - - if (evctx->page_flip_handler == NULL) - break; - - vblank = (struct drm_event_vblank *) e; - evctx->page_flip_handler (fd, - vblank->sequence, - vblank->tv_sec, - vblank->tv_usec, - (void *)((unsigned long)vblank->user_data)); - } - break; - case DRM_EXYNOS_G2D_EVENT: - { - struct drm_exynos_g2d_event *g2d; - - if (evctx->g2d_handler == NULL) - break; - - g2d = (struct drm_exynos_g2d_event *) e; - evctx->g2d_handler (fd, - g2d->cmdlist_no, - g2d->tv_sec, - g2d->tv_usec, - (void *)((unsigned long)g2d->user_data)); - } - break; - case DRM_EXYNOS_IPP_EVENT: - { - struct drm_exynos_ipp_event *ipp; - - if (evctx->ipp_handler == NULL) - break; - - ipp = (struct drm_exynos_ipp_event *) e; - evctx->ipp_handler (fd, - ipp->prop_id, - ipp->buf_id, - ipp->tv_sec, - ipp->tv_usec, - (void *)((unsigned long)ipp->user_data)); - } - break; - default: - break; - } - i += e->length; - } - - return 0; -} - -static Bool -SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height) -{ - ScreenPtr pScreen = pScrn->pScreen; - SECPtr pSec = SECPTR (pScrn); - - XDBG_DEBUG(MDISP, "Resize cur(%dx%d) new(%d,%d)\n", - pScrn->virtualX, - pScrn->virtualY, - width, height); - - if (pScrn->virtualX == width && - pScrn->virtualY == height) - { - return TRUE; - } - - secFbResize(pSec->pFb, width, height); - - /* set the new size of pScrn */ - pScrn->virtualX = width; - pScrn->virtualY = height; - secExaScreenSetScrnPixmap (pScreen); - - secOutputDrmUpdate (pScrn); - - _secDisplayRemoveFlipPixmaps (pScrn); - - return TRUE; -} - -static void -SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event) -{ - SECVBlankInfoPtr pVblankInfo = event; - SECVBlankInfoType vblank_type; - void *data; - - XDBG_RETURN_IF_FAIL (pVblankInfo != NULL); - - vblank_type = pVblankInfo->type; - data = pVblankInfo->data; - -#if DBG_DRM_EVENT - xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank); -#endif - - if (vblank_type == VBLANK_INFO_SWAP) - { - XDBG_TRACE (MDISP, "vblank handler (%p, %ld, %ld)\n", - pVblankInfo, pVblankInfo->time, GetTimeInMillis () - pVblankInfo->time); - secDri2FrameEventHandler (frame, tv_sec, tv_usec, data); - } - else if (vblank_type == VBLANK_INFO_PLANE) - secLayerVBlankEventHandler (frame, tv_sec, tv_usec, data); - else - XDBG_ERROR (MDISP, "unknown the vblank type\n"); - - free (pVblankInfo); - pVblankInfo = NULL; -} - -static void -SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - SECPageFlipPtr flip = event_data; - xf86CrtcPtr pCrtc; - SECCrtcPrivPtr pCrtcPriv; - - if (!flip) - { - XDBG_ERROR (MDISP, "flip is null\n"); - return; - } - - XDBG_TRACE (MDISP, "pageflip handler (%p, %ld, %ld)\n", - flip, flip->time, GetTimeInMillis () - flip->time); - - #if DBG_DRM_EVENT - if( flip->xdbg_log_pageflip != NULL ) - xDbgLogDrmEventRemovePageflip (flip->xdbg_log_pageflip); - #endif - - pCrtc = flip->pCrtc; - pCrtcPriv = pCrtc->driver_private; - pCrtcPriv->is_flipping = FALSE; - pCrtcPriv->is_fb_blit_flipping = FALSE; - pCrtcPriv->flip_count--; /* check flipping completed */ - - /* Is this the event whose info shall be delivered to higher level? */ - /* Yes: Cache msc, ust for later delivery. */ - pCrtcPriv->fe_frame = frame; - pCrtcPriv->fe_tv_sec = tv_sec; - pCrtcPriv->fe_tv_usec = tv_usec; - - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - if (pCrtcPriv->accessibility_front_bo && pCrtcPriv->accessibility_back_bo) - { - tbm_bo temp; - temp = pCrtcPriv->accessibility_front_bo; - pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo; - pCrtcPriv->accessibility_back_bo = temp; - } - - /* accessibility */ - if (flip->accessibility_back_bo) - { - secRenderBoUnref(flip->accessibility_back_bo); - flip->accessibility_back_bo = NULL; - } - - /* if accessibility is diabled, remove the accessibility_bo - when the pageflip is occurred once after the accessibility is disabled */ - if (!pCrtcPriv->bAccessibility && pCrtcPriv->screen_rotate_degree == 0) - { - if (pCrtcPriv->accessibility_front_bo) - { - secRenderBoUnref (pCrtcPriv->accessibility_front_bo); - pCrtcPriv->accessibility_front_bo = NULL; - } - if (pCrtcPriv->accessibility_back_bo) - { - secRenderBoUnref (pCrtcPriv->accessibility_back_bo); - pCrtcPriv->accessibility_back_bo = NULL; - } - } - - /* Release back framebuffer */ - if (flip->back_bo) - { - secRenderBoUnref(flip->back_bo); - flip->back_bo = NULL; - } - - if (pCrtcPriv->flip_info == NULL) - { - /** - * If pCrtcPriv->flip_info is failed and secCrtcGetFirstPendingFlip (pCrtc) has data, - * ModePageFlipHandler is triggered by secDisplayUpdateRequest(). - Maybe FB_BLIT or FB is updated by CPU. - * In this case we should call _secDri2ProcessPending(). - */ - DRI2FrameEventPtr pending_flip; - pending_flip = secCrtcGetFirstPendingFlip (pCrtc); - if( pending_flip != NULL ) - { - XDBG_DEBUG (MDISP, "FB_BLIT or FB is updated by CPU. But there's secCrtcGetFirstPendingFlip(). So trigger it manually\n"); - flip->dispatch_me = TRUE; - pCrtcPriv->flip_info = pending_flip; - } - else - goto fail; - } - - XDBG_DEBUG(MDISP, "ModePageFlipHandler ctrc_id:%d dispatch_me:%d, frame:%d, flip_count=%d is_pending=%p\n", - secCrtcID(pCrtcPriv), flip->dispatch_me, frame, pCrtcPriv->flip_count, secCrtcGetFirstPendingFlip (pCrtc)); - - /* Last crtc completed flip? */ - if (flip->dispatch_me) - { - secCrtcCountFps(pCrtc); - - /* Deliver cached msc, ust from reference crtc to flip event handler */ - secDri2FlipEventHandler (pCrtcPriv->fe_frame, pCrtcPriv->fe_tv_sec, - pCrtcPriv->fe_tv_usec, pCrtcPriv->flip_info, flip->flip_failed); - } - - free (flip); - return; -fail: - if (flip->accessibility_back_bo) - { - secRenderBoUnref(flip->accessibility_back_bo); - flip->accessibility_back_bo = NULL; - } - - if (flip->back_bo) - { - secRenderBoUnref(flip->back_bo); - flip->back_bo = NULL; - } - - free (flip); -} - -static void -SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ -} - -static void -SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx, - unsigned int tv_sec, unsigned int tv_usec, void *event_data) -{ - XDBG_DEBUG (MDRM, "wb_prop_id(%d) prop_id(%d), buf_idx(%d, %d) \n", - secWbGetPropID(), prop_id, buf_idx[0], buf_idx[1]); - - if (secWbGetPropID () == prop_id) - secWbHandleIppEvent (fd, buf_idx, event_data); - else - secCvtHandleIppEvent (fd, buf_idx, event_data, FALSE); -} - -static void -SECModeWakeupHanlder(pointer data, int err, pointer p) -{ - SECModePtr pSecMode; - fd_set *read_mask; - - if (data == NULL || err < 0) - return; - - pSecMode = data; - read_mask = p; - if (FD_ISSET (pSecMode->fd, read_mask)) - secHandleEvent (pSecMode->fd, &pSecMode->event_context); -} - -Bool -secModePreInit (ScrnInfoPtr pScrn, int drm_fd) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode; - unsigned int i; - int cpp; - -// secLogSetLevel(MDISP, 0); - - pSecMode = calloc (1, sizeof *pSecMode); - if (!pSecMode) - return FALSE; - - pSecMode->fd = drm_fd; - xorg_list_init (&pSecMode->crtcs); - xorg_list_init (&pSecMode->outputs); - xorg_list_init (&pSecMode->planes); - - xf86CrtcConfigInit (pScrn, &sec_xf86crtc_config_funcs); - - cpp = pScrn->bitsPerPixel /8; - - pSecMode->cpp = cpp; - pSecMode->mode_res = drmModeGetResources (pSecMode->fd); - if (!pSecMode->mode_res) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "failed to get resources: %s\n", strerror (errno)); - free (pSecMode); - return FALSE; - } - - pSecMode->plane_res = drmModeGetPlaneResources (pSecMode->fd); - if (!pSecMode->plane_res) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "failed to get plane resources: %s\n", strerror (errno)); - drmModeFreeResources (pSecMode->mode_res); - free (pSecMode); - return FALSE; - } - - xf86CrtcSetSizeRange (pScrn, 320, 200, pSecMode->mode_res->max_width, - pSecMode->mode_res->max_height); - - for (i = 0; i < pSecMode->mode_res->count_crtcs; i++) - secCrtcInit (pScrn, pSecMode, i); - - for (i = 0; i < pSecMode->mode_res->count_connectors; i++) - secOutputInit (pScrn, pSecMode, i); - - for (i = 0; i < pSecMode->plane_res->count_planes; i++) - secPlaneInit (pScrn, pSecMode, i); - - _secSetMainMode (pScrn, pSecMode); - - xf86InitialConfiguration (pScrn, TRUE); - - /* soolim:: - * we assume that kernel always support the pageflipping - * and the drm vblank - */ - /* set the drm event context */ - _secDisplaySetDrmEventCtx(pSecMode); - - pSec->pSecMode = pSecMode; - - /* virtaul x and virtual y of the screen is ones from main lcd mode */ - pScrn->virtualX = pSecMode->main_lcd_mode.hdisplay; - pScrn->virtualY = pSecMode->main_lcd_mode.vdisplay; - -#if DBG_DRM_EVENT - xDbgLogDrmEventInit(); -#endif - - return TRUE; -} - -void -secModeInit (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - /* We need to re-register the mode->fd for the synchronisation - * feedback on every server generation, so perform the - * registration within ScreenInit and not PreInit. - */ - //pSecMode->flip_count = 0; - AddGeneralSocket(pSecMode->fd); - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - SECModeWakeupHanlder, pSecMode); - -} - -void -secModeDeinit (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = (SECModePtr) pSec->pSecMode; - xf86CrtcPtr pCrtc = NULL; - xf86OutputPtr pOutput = NULL; - - secDisplayDeinitDispMode (pScrn); - - SECCrtcPrivPtr crtc_ref = NULL, crtc_next = NULL; - xorg_list_for_each_entry_safe (crtc_ref, crtc_next, &pSecMode->crtcs, link) - { - pCrtc = crtc_ref->pCrtc; - xf86CrtcDestroy (pCrtc); - } - - SECOutputPrivPtr output_ref = NULL, output_next = NULL; - xorg_list_for_each_entry_safe (output_ref, output_next, &pSecMode->outputs, link) - { - pOutput = output_ref->pOutput; - xf86OutputDestroy (pOutput); - } - - SECPlanePrivPtr plane_ref = NULL, plane_next = NULL; - xorg_list_for_each_entry_safe (plane_ref, plane_next, &pSecMode->planes, link) - { - secPlaneDeinit (pScrn, plane_ref); - } - - if (pSecMode->mode_res) - drmModeFreeResources (pSecMode->mode_res); - - if (pSecMode->plane_res) - drmModeFreePlaneResources (pSecMode->plane_res); - - /* mode->rotate_fb_id should have been destroyed already */ - - free (pSecMode); - pSec->pSecMode = NULL; -} - -/* - * Return the crtc covering 'box'. If two crtcs cover a portion of - * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc - * with greater coverage - */ -xf86CrtcPtr -secModeCoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc) -{ - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - xf86CrtcPtr pCrtc, pBestCrtc; - int coverage, best_coverage; - int c; - BoxRec crtc_box, cover_box; - - XDBG_RETURN_VAL_IF_FAIL (pBox != NULL, NULL); - - pBestCrtc = NULL; - best_coverage = 0; - - if (pBoxCrtc) - { - pBoxCrtc->x1 = 0; - pBoxCrtc->y1 = 0; - pBoxCrtc->x2 = 0; - pBoxCrtc->y2 = 0; - } - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - pCrtc = pCrtcConfig->crtc[c]; - - /* If the CRTC is off, treat it as not covering */ - if(!secCrtcOn(pCrtc)) - continue; - - crtc_box.x1 = pCrtc->x; - crtc_box.x2 = pCrtc->x + xf86ModeWidth (&pCrtc->mode, pCrtc->rotation); - crtc_box.y1 = pCrtc->y; - crtc_box.y2 = pCrtc->y + xf86ModeHeight (&pCrtc->mode, pCrtc->rotation); - - secUtilBoxIntersect(&cover_box, &crtc_box, pBox); - coverage = secUtilBoxArea(&cover_box); - - if (coverage && pCrtc == pDesiredCrtc) - { - if (pBoxCrtc) - *pBoxCrtc = crtc_box; - return pCrtc; - } - - if (coverage > best_coverage) - { - if (pBoxCrtc) - *pBoxCrtc = crtc_box; - pBestCrtc = pCrtc; - best_coverage = coverage; - } - } - - return pBestCrtc; -} - -int secModeGetCrtcPipe (xf86CrtcPtr pCrtc) -{ - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - return pCrtcPriv->pipe; -} - -Bool -secModePageFlip (ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void* flip_info, int pipe, tbm_bo back_bo) -{ - SECPageFlipPtr pPageFlip = NULL; - SECFbBoDataPtr bo_data; - SECCrtcPrivPtr pCrtcPriv; - SECModePtr pSecMode; - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - xf86CrtcPtr pCurCrtc; - SECPtr pSec = SECPTR(pScrn); - int ret; - int fb_id = 0; - DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) flip_info; - - BoxRec b1; - int retBox, found=0; - int i; - - tbm_bo_get_user_data (back_bo, TBM_BO_DATA_FB, (void * *)&bo_data); - XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE); - - for (i = 0; i < pCrtcConfig->num_crtc; i++) - { - pCurCrtc = pCrtcConfig->crtc[i]; - if (!pCurCrtc->enabled) - continue; - pCrtcPriv = pCurCrtc->driver_private; - pSecMode = pCrtcPriv->pSecMode; - - b1.x1 = pCurCrtc->x; - b1.y1 = pCurCrtc->y; - b1.x2 = pCurCrtc->x + pCurCrtc->mode.HDisplay; - b1.y2 = pCurCrtc->y + pCurCrtc->mode.VDisplay; - - retBox = secUtilBoxInBox(&bo_data->pos, &b1); - if(retBox == rgnSAME || retBox == rgnIN) - { - pPageFlip = calloc (1, sizeof (SECPageFlipRec)); - if (pPageFlip == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n"); - return FALSE; - } - - /* Only the reference crtc will finally deliver its page flip - * completion event. All other crtc's events will be discarded. - */ - pPageFlip->dispatch_me = 0; - pPageFlip->pCrtc = pCurCrtc; - pPageFlip->clone = TRUE; - pPageFlip->back_bo = secRenderBoRef (back_bo); - pPageFlip->data = flip_info; - pPageFlip->flip_failed = FALSE; - - /* accessilitity */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo; - SECFbBoDataPtr accessibility_bo_data; - - tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data); - XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail); - - fb_id = accessibility_bo_data->fb_id; - - /*Buffer is already changed by bo_swap*/ - if (!secCrtcExecAccessibility (pCurCrtc, back_bo, accessibility_bo)) - goto fail; - - pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo); - } - else - { - fb_id = bo_data->fb_id; - - tbm_bo_map(pPageFlip->back_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - tbm_bo_unmap(pPageFlip->back_bo); - } - - pCrtcPriv->is_flipping = TRUE; - - if (!pCrtcPriv->onoff && !pCrtcPriv->onoff_always) - secCrtcTurn (pCrtcPriv->pCrtc, TRUE, FALSE, FALSE); - -#if DBG_DRM_EVENT - pPageFlip->xdbg_log_pageflip = xDbgLogDrmEventAddPageflip (pipe, pEvent->client_idx, pEvent->drawable_id); -#endif - - XDBG_DEBUG (MSEC, "dump_mode(%x)\n", pSec->dump_mode); - - if (pSec->dump_mode & XBERC_DUMP_MODE_FB) - _saveFrameBuffer (pScrn, back_bo, - bo_data->pos.x2 - bo_data->pos.x1, - bo_data->pos.y2 - bo_data->pos.y1); - - pPageFlip->time = GetTimeInMillis (); - - /*Set DirtyFB*/ - if(pSec->use_partial_update && pEvent->pRegion) - { - int nBox; - BoxPtr pBox; - RegionRec new_region; - RegionPtr pRegion = pEvent->pRegion; - - for (nBox = RegionNumRects(pRegion), - pBox = RegionRects(pRegion); nBox--; pBox++) - { - XDBG_DEBUG (MDISP, "dirtfb region(%d): (%d,%d %dx%d)\n", nBox, - pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1); - } - - if (pCrtcPriv->screen_rotate_degree > 0) - { - RegionCopy (&new_region, pEvent->pRegion); - secUtilRotateRegion (pCrtc->mode.HDisplay, pCrtc->mode.VDisplay, - &new_region, pCrtcPriv->screen_rotate_degree); - pRegion = &new_region; - - for (nBox = RegionNumRects(pRegion), - pBox = RegionRects(pRegion); nBox--; pBox++) - { - XDBG_DEBUG (MDISP, "(R)dirtfb region(%d): (%d,%d %dx%d)\n", nBox, - pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1); - } - } - - drmModeDirtyFB (pSec->drm_fd, fb_id, - (drmModeClipPtr)RegionRects (pRegion), - (uint32_t)RegionNumRects (pRegion)); - } - - - /* DRM Page Flip */ - ret = drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id, - DRM_MODE_PAGE_FLIP_EVENT, pPageFlip); - if (ret) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", strerror (errno)); - goto fail; - } - - XDBG_TRACE (MDISP, "pageflip do (%p, %ld)\n", pPageFlip, pPageFlip->time); - - pCrtcPriv->flip_count++; /* check flipping completed */ - pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info; - - found++; - XDBG_DEBUG(MDISP, "ModePageFlip crtc_id:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d\n", - secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, - tbm_bo_export (back_bo), pCrtcPriv->bAccessibility); - } - } - - if(found==0) - { - XDBG_WARNING(MDISP, "Cannot find CRTC in (%d,%d)-(%d,%d)\n", - bo_data->pos.x1, bo_data->pos.y1, bo_data->pos.x2, bo_data->pos.y2); - return FALSE; - } - - /* Set dispatch_me to last pageflip */ - pPageFlip->dispatch_me = 1; - - return TRUE; - -fail: - pCrtcPriv->flip_count++; /* check flipping completed */ - pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info; - pPageFlip->dispatch_me = 1; - pPageFlip->flip_failed = TRUE; - - SECModePageFlipHandler(pSecMode->fd, 0, 0, 0, pPageFlip); - - XDBG_ERROR(MDISP, "drmModePageFlip error(crtc:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d)\n", - secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, tbm_bo_export (back_bo), pCrtcPriv->bAccessibility); - - return FALSE; -} - -/* load palette per a crtc */ -void -secModeLoadPalette (ScrnInfoPtr pScrn, int numColors, int* indices, - LOCO* colors, VisualPtr pVisual) -{ - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - int i, j, index; - int p; - uint16_t lut_r[256], lut_g[256], lut_b[256]; - - for (p = 0; p < pCrtcConfig->num_crtc; p++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[p]; - - switch (pScrn->depth) - { - case 16: - for (i = 0; i < numColors; i++) - { - index = indices[i]; - if (index <= 31) - { - for (j = 0; j < 8; j++) - { - lut_r[index * 8 + j] = colors[index].red << 8; - lut_b[index * 8 + j] = colors[index].blue << 8; - } - } - for (j = 0; j < 4; j++) - { - lut_g[index * 4 + j] = colors[index].green << 8; - } - } - break; - default: - for (i = 0; i < numColors; i++) - { - index = indices[i]; - lut_r[index] = colors[index].red << 8; - lut_g[index] = colors[index].green << 8; - lut_b[index] = colors[index].blue << 8; - - } - break; - } - - /* make the change through RandR */ - RRCrtcGammaSet (pCrtc->randr_crtc, lut_r, lut_g, lut_b); - } -} - -void -secDisplaySwapModeFromKmode(ScrnInfoPtr pScrn, - drmModeModeInfoPtr kmode, - DisplayModePtr pMode) -{ - char fake_name[32] = "fake_mode"; - - memset (pMode, 0, sizeof (DisplayModeRec)); - pMode->status = MODE_OK; - - pMode->Clock = kmode->clock; - - pMode->HDisplay = kmode->vdisplay; - pMode->HSyncStart = kmode->vsync_start; - pMode->HSyncEnd = kmode->vsync_end; - pMode->HTotal = kmode->vtotal; - pMode->HSkew = kmode->vscan; - - pMode->VDisplay = kmode->hdisplay; - pMode->VSyncStart = kmode->hsync_start; - pMode->VSyncEnd = kmode->hsync_end; - pMode->VTotal = kmode->htotal; - pMode->VScan = kmode->hskew; - - pMode->Flags = kmode->flags; //& FLAG_BITS; - pMode->name = strdup (fake_name); - - if (kmode->type & DRM_MODE_TYPE_DRIVER) - pMode->type = M_T_DRIVER; - if (kmode->type & DRM_MODE_TYPE_PREFERRED) - pMode->type |= M_T_PREFERRED; - - xf86SetModeCrtc (pMode, pScrn->adjustFlags); -} - - - - -void -secDisplayModeFromKmode(ScrnInfoPtr pScrn, - drmModeModeInfoPtr kmode, - DisplayModePtr pMode) -{ - memset (pMode, 0, sizeof (DisplayModeRec)); - pMode->status = MODE_OK; - - pMode->Clock = kmode->clock; - - pMode->HDisplay = kmode->hdisplay; - pMode->HSyncStart = kmode->hsync_start; - pMode->HSyncEnd = kmode->hsync_end; - pMode->HTotal = kmode->htotal; - pMode->HSkew = kmode->hskew; - - pMode->VDisplay = kmode->vdisplay; - pMode->VSyncStart = kmode->vsync_start; - pMode->VSyncEnd = kmode->vsync_end; - pMode->VTotal = kmode->vtotal; - pMode->VScan = kmode->vscan; - - pMode->Flags = kmode->flags; //& FLAG_BITS; - pMode->name = strdup (kmode->name); - pMode->VRefresh = kmode->vrefresh; - - if (kmode->type & DRM_MODE_TYPE_DRIVER) - pMode->type = M_T_DRIVER; - if (kmode->type & DRM_MODE_TYPE_PREFERRED) - pMode->type |= M_T_PREFERRED; - - xf86SetModeCrtc (pMode, pScrn->adjustFlags); -} - - -void -secDisplaySwapModeToKmode(ScrnInfoPtr pScrn, - drmModeModeInfoPtr kmode, - DisplayModePtr pMode) -{ - memset (kmode, 0, sizeof (*kmode)); - - kmode->clock = pMode->Clock; - kmode->hdisplay = pMode->VDisplay; - kmode->hsync_start = pMode->VSyncStart; - kmode->hsync_end = pMode->VSyncEnd; - kmode->htotal = pMode->VTotal; - kmode->hskew = pMode->VScan; - - kmode->vdisplay = pMode->HDisplay; - kmode->vsync_start = pMode->HSyncStart; - kmode->vsync_end = pMode->HSyncEnd; - kmode->vtotal = pMode->HTotal; - kmode->vscan = pMode->HSkew; - kmode->vrefresh = xf86ModeVRefresh (pMode); - - kmode->flags = pMode->Flags; //& FLAG_BITS; - if (pMode->name) - strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN); - kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; -} - - -void -secDisplayModeToKmode(ScrnInfoPtr pScrn, - drmModeModeInfoPtr kmode, - DisplayModePtr pMode) -{ - memset (kmode, 0, sizeof (*kmode)); - - kmode->clock = pMode->Clock; - kmode->hdisplay = pMode->HDisplay; - kmode->hsync_start = pMode->HSyncStart; - kmode->hsync_end = pMode->HSyncEnd; - kmode->htotal = pMode->HTotal; - kmode->hskew = pMode->HSkew; - - kmode->vdisplay = pMode->VDisplay; - kmode->vsync_start = pMode->VSyncStart; - kmode->vsync_end = pMode->VSyncEnd; - kmode->vtotal = pMode->VTotal; - kmode->vscan = pMode->VScan; - kmode->vrefresh = xf86ModeVRefresh (pMode); - - kmode->flags = pMode->Flags; //& FLAG_BITS; - if (pMode->name) - strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN); - - kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; -} - - -static uint32_t crtc_id; -static tbm_bo hdmi_bo; - -static Bool connect_crtc; - -static int -_secDisplayGetAvailableCrtcID (ScrnInfoPtr pScrn) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - int i; - int crtc_id = 0; - - for (i = 0; i < pSecMode->mode_res->count_crtcs; i++) - { - drmModeCrtcPtr kcrtc = NULL; - kcrtc = drmModeGetCrtc (pSecMode->fd, pSecMode->mode_res->crtcs[i]); - if (!kcrtc) - { - XDBG_ERROR (MSEC, "fail to get kcrtc. \n"); - return 0; - } - - if (kcrtc->buffer_id > 0) - { - drmModeFreeCrtc (kcrtc); - continue; - } - - crtc_id = kcrtc->crtc_id; - drmModeFreeCrtc (kcrtc); - - return crtc_id; - } - - return 0; -} - -static void -_secDisplayWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data) -{ - ScrnInfoPtr pScrn = (ScrnInfoPtr)user_data; - SECPtr pSec; - - if (!pScrn) - return; - - pSec = SECPTR (pScrn); - - pSec->wb_clone = NULL; -} - -Bool -secDisplayInitDispMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - Bool ret = FALSE; - uint32_t *output_ids = NULL; - int output_cnt = 1; - uint32_t fb_id; - drmModeModeInfoPtr pKmode = NULL; - drmModeCrtcPtr kcrtc = NULL; - SECFbBoDataPtr bo_data = NULL; - SECOutputPrivPtr pOutputPriv=NULL, pNext=NULL; - int connector_type = -1; - int width, height; - - if (connect_crtc) - return TRUE; - - /* get output ids */ - output_ids = calloc (output_cnt, sizeof (uint32_t)); - XDBG_RETURN_VAL_IF_FAIL (output_ids != NULL, FALSE); - - xorg_list_for_each_entry_safe (pOutputPriv, pNext, &pSecMode->outputs, link) - { - if (conn_mode == DISPLAY_CONN_MODE_HDMI) - { - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB) - { - output_ids[0] = pOutputPriv->mode_output->connector_id; - pKmode = &pSecMode->ext_connector_mode; - connector_type = pOutputPriv->mode_output->connector_type; - break; - } - } - else if (conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - output_ids[0] = pOutputPriv->mode_output->connector_id; - pKmode = &pSecMode->ext_connector_mode; - connector_type = pOutputPriv->mode_output->connector_type; - break; - } - - } - else - { - XDBG_NEVER_GET_HERE (MTVO); - goto fail_to_init; - } - } - XDBG_GOTO_IF_FAIL (output_ids[0] > 0, fail_to_init); - XDBG_GOTO_IF_FAIL (pKmode != NULL, fail_to_init); - - width = pKmode->hdisplay; - height = pKmode->vdisplay; - - pOutputPriv = secOutputGetPrivateForConnType (pScrn, connector_type); - if (pOutputPriv && pOutputPriv->mode_encoder) - XDBG_GOTO_IF_FAIL (pOutputPriv->mode_encoder->crtc_id == 0, fail_to_init); - - crtc_id = _secDisplayGetAvailableCrtcID (pScrn); - XDBG_GOTO_IF_FAIL (crtc_id > 0, fail_to_init); - - /* get crtc_id */ - kcrtc = drmModeGetCrtc (pSecMode->fd, crtc_id); - XDBG_GOTO_IF_FAIL (kcrtc != NULL, fail_to_init); - - if (kcrtc->buffer_id > 0) - { - XDBG_ERROR (MTVO, "crtc(%d) already has buffer(%d) \n", - crtc_id, kcrtc->buffer_id); - goto fail_to_init; - } - - /* get fb_id */ - hdmi_bo = secRenderBoCreate (pScrn, width, height); - XDBG_GOTO_IF_FAIL (hdmi_bo != NULL, fail_to_init); - - tbm_bo_get_user_data(hdmi_bo, TBM_BO_DATA_FB, (void * *)&bo_data); - XDBG_GOTO_IF_FAIL (bo_data != NULL, fail_to_init); - - fb_id = bo_data->fb_id; - - /* set crtc */ - if (drmModeSetCrtc (pSecMode->fd, crtc_id, fb_id, 0, 0, output_ids, output_cnt, pKmode)) - { - XDBG_ERRNO (MTVO, "drmModeSetCrtc failed. \n"); - goto fail_to_init; - } - else - { - ret = TRUE; - } - - secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 1); - - secOutputDrmUpdate (pScrn); - - XDBG_INFO (MDISP, "** ModeSet : (%dx%d) %dHz !!\n", pKmode->hdisplay, pKmode->vdisplay, pKmode->vrefresh); - - connect_crtc = TRUE; - -fail_to_init: - free (output_ids); - if (kcrtc) - drmModeFreeCrtc (kcrtc); - - return ret; -} - -void -secDisplayDeinitDispMode (ScrnInfoPtr pScrn) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - - if (!connect_crtc) - return; - - XDBG_INFO (MDISP, "** ModeUnset. !!\n"); - - secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 0); - - if (hdmi_bo) - { - secRenderBoUnref (hdmi_bo); - hdmi_bo = NULL; - } - - secOutputDrmUpdate (pScrn); - - crtc_id = 0; - connect_crtc = FALSE; -} - -Bool -secDisplaySetDispSetMode (ScrnInfoPtr pScrn, SECDisplaySetMode set_mode) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - if (pSecMode->set_mode == set_mode) - { - XDBG_INFO (MDISP, "set_mode(%d) is already set\n", set_mode); - return TRUE; - } - - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_NONE) - { - XDBG_WARNING (MDISP, "set_mode(%d) is failed : output is not connected yet\n", set_mode); - return FALSE; - } - - switch (set_mode) - { - case DISPLAY_SET_MODE_OFF: - if (secWbIsOpened ()) - { - SECWb *wb = secWbGet (); - secWbClose (wb); - } - secDisplayDeinitDispMode (pScrn); - break; - case DISPLAY_SET_MODE_CLONE: - /* In case of DISPLAY_CONN_MODE_VIRTUAL, we will open writeback - * on GetStill. - */ - if (pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) - { - int wb_hz; - - if (pSec->wb_clone) - { - XDBG_ERROR (MWB, "Fail : wb_clone(%p) already exists.\n", pSec->wb_clone); - break; - } - - if (secWbIsOpened ()) - { - XDBG_ERROR (MWB, "Fail : wb(%p) already opened.\n", secWbGet ()); - break; - } - - wb_hz = (pSec->wb_hz > 0)? pSec->wb_hz : pSecMode->ext_connector_mode.vrefresh; - - XDBG_TRACE (MWB, "wb_hz(%d) vrefresh(%d)\n", pSec->wb_hz, pSecMode->ext_connector_mode.vrefresh); - - pSec->wb_clone = secWbOpen (pScrn, FOURCC_SN12, 0, 0, (pSec->scanout)?TRUE:FALSE, wb_hz, TRUE); - if (pSec->wb_clone) - { - secWbAddNotifyFunc (pSec->wb_clone, WB_NOTI_CLOSED, - _secDisplayWbCloseFunc, pScrn); - secWbSetRotate (pSec->wb_clone, pSecMode->rotate); - secWbSetTvout (pSec->wb_clone, TRUE); - if (!secWbStart (pSec->wb_clone)) - { - secWbClose (pSec->wb_clone); - return FALSE; - } - } - } - break; - case DISPLAY_SET_MODE_EXT: - if (secWbIsOpened ()) - { - SECWb *wb = secWbGet (); - secWbClose (wb); - } - secDisplayDeinitDispMode (pScrn); - break; - default: - break; - } - - pSecMode->set_mode = set_mode; - - return TRUE; -} - -SECDisplaySetMode -secDisplayGetDispSetMode (ScrnInfoPtr pScrn) -{ - SECDisplaySetMode set_mode; - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - set_mode = pSecMode->set_mode; - - return set_mode; -} - -Bool -secDisplaySetDispRotate (ScrnInfoPtr pScrn, int rotate) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - if (pSecMode->rotate == rotate) - return TRUE; - - pSecMode->rotate = rotate; - - if (pSec->wb_clone) - secWbSetRotate (pSec->wb_clone, rotate); - - return TRUE; -} - -int -secDisplayGetDispRotate (ScrnInfoPtr pScrn) -{ - int rotate; - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - rotate = pSecMode->rotate; - - return rotate; -} - -Bool -secDisplaySetDispConnMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - if (pSecMode->conn_mode == conn_mode) - { - XDBG_DEBUG (MDISP, "conn_mode(%d) is already set\n", conn_mode); - return TRUE; - } - - switch (conn_mode) - { - case DISPLAY_CONN_MODE_NONE: - break; - case DISPLAY_CONN_MODE_HDMI: - break; - case DISPLAY_CONN_MODE_VIRTUAL: - break; - default: - break; - } - - pSecMode->conn_mode = conn_mode; - - return TRUE; -} - -SECDisplayConnMode -secDisplayGetDispConnMode (ScrnInfoPtr pScrn) -{ - SECDisplayConnMode conn_mode; - - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - conn_mode = pSecMode->conn_mode; - - return conn_mode; -} - -Bool -secDisplayGetCurMSC (ScrnInfoPtr pScrn, int pipe, CARD64 *ust, CARD64 *msc) -{ - drmVBlank vbl; - int ret; - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = pSec->pSecMode; - - /* if lcd is off, return true with msc = 0 */ - if (pSec->isLcdOff) - { - *ust = 0; - *msc = 0; - return TRUE; - } - - - /* if pipe is -1, return the current msc of the main crtc */ - if (pipe == -1) - pipe = 0; - - vbl.request.type = DRM_VBLANK_RELATIVE; - - if (pipe > 0) - { - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI; - else - vbl.request.type |= DRM_VBLANK_SECONDARY; - } - - vbl.request.sequence = 0; - ret = drmWaitVBlank (pSec->drm_fd, &vbl); - if (ret) - { - *ust = 0; - *msc = 0; - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "first get vblank counter failed: %s\n", - strerror (errno)); - return FALSE; - } - - *ust = ((CARD64) vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; - *msc = vbl.reply.sequence; - - return TRUE; -} - -Bool -secDisplayVBlank (ScrnInfoPtr pScrn, int pipe, CARD64 *target_msc, int flip, - SECVBlankInfoType type, void *vblank_info) -{ - drmVBlank vbl; - int ret; - SECPtr pSec = SECPTR (pScrn); - SECVBlankInfoPtr pVblankInfo = NULL; - SECModePtr pSecMode = pSec->pSecMode; - - pVblankInfo = calloc (1, sizeof (SECVBlankInfoRec)); - if (pVblankInfo == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "vblank_info alloc failed\n"); - return FALSE; - } - - pVblankInfo->type = type; - pVblankInfo->data = vblank_info; - pVblankInfo->time = GetTimeInMillis (); - - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - - if (pipe > 0) - { - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI; - else - vbl.request.type |= DRM_VBLANK_SECONDARY; - } - - /* If non-pageflipping, but blitting/exchanging, we need to use - * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later - * on. - */ - if (flip == 0) - { - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL && pipe > 0) - ; /* do not set the DRM_VBLANK_NEXTMISS */ - else - vbl.request.type |= DRM_VBLANK_NEXTONMISS; - } - - vbl.request.sequence = *target_msc; - vbl.request.signal = (unsigned long) pVblankInfo; - -#if DBG_DRM_EVENT - DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) vblank_info; - if (type == VBLANK_INFO_SWAP) - pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, pEvent->client_idx, pEvent->drawable_id, type); - else - pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, 0, 0, type); -#endif - ret = drmWaitVBlank (pSec->drm_fd, &vbl); - if (ret) - { -#if DBG_DRM_EVENT - xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank); -#endif - if (pVblankInfo) - { - free(pVblankInfo); - pVblankInfo = NULL; - } - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "divisor 0 get vblank counter failed: %s\n", - strerror (errno)); - return FALSE; - } - - XDBG_TRACE (MDISP, "vblank do (%p, %ld)\n", pVblankInfo, pVblankInfo->time); - - /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ - *target_msc = vbl.reply.sequence + flip; - - return TRUE; -} - -int -secDisplayDrawablePipe (DrawablePtr pDraw) -{ - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - BoxRec box, crtc_box; - xf86CrtcPtr pCrtc; - int pipe = -1; - - box.x1 = pDraw->x; - box.y1 = pDraw->y; - box.x2 = box.x1 + pDraw->width; - box.y2 = box.y1 + pDraw->height; - - pCrtc = secModeCoveringCrtc (pScrn, &box, NULL, &crtc_box); - - if (pCrtc != NULL && !pCrtc->rotatedData) - pipe = secModeGetCrtcPipe (pCrtc); - - return pipe; -} - -int -secDisplayCrtcPipe (ScrnInfoPtr pScrn, int crtc_id) -{ - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn); - int c; - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - if (pCrtcPriv->mode_crtc->crtc_id == crtc_id) - return pCrtcPriv->pipe; - } - - XDBG_ERROR (MDISP, "%s(%d): crtc(%d) not found.\n", __func__, __LINE__, crtc_id); - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - XDBG_ERROR (MDISP, "%s(%d) : crtc(%d) != crtc(%d)\n", __func__, __LINE__, - pCrtcPriv->mode_crtc->crtc_id, crtc_id); - } - - return 0; -} - -Bool secDisplayUpdateRequest(ScrnInfoPtr pScrn) -{ - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE); - - SECPtr pSec = SECPTR(pScrn); - xf86CrtcPtr pCrtc = xf86CompatCrtc (pScrn); - SECCrtcPrivPtr pCrtcPriv; - tbm_bo bo; - Bool ret = FALSE; - SECPageFlipPtr pPageFlip = NULL; - - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE); - - pCrtcPriv = pCrtc->driver_private; - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE); - - bo = pCrtcPriv->front_bo; - - if( pCrtcPriv->is_fb_blit_flipping || pCrtcPriv->is_flipping || secCrtcGetFirstPendingFlip (pCrtc) ) - { - XDBG_DEBUG (MDISP, "drmModePageFlip is already requested!\n"); - } - else - { - // Without buffer swap, we need to request drmModePageFlip(). - if( bo != NULL ) - { - SECFbBoDataPtr bo_data; - int fb_id = 0; - - tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data); - XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE); - - fb_id = bo_data->fb_id; - - pPageFlip = calloc (1, sizeof (SECPageFlipRec)); - if (pPageFlip == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n"); - return FALSE; - } - - /* Only the reference crtc will finally deliver its page flip - * completion event. All other crtc's events will be discarded. - */ - pPageFlip->dispatch_me = 0; - pPageFlip->pCrtc = pCrtc; - pPageFlip->clone = TRUE; - pPageFlip->back_bo = secRenderBoRef (bo); - pPageFlip->data = NULL; - pPageFlip->flip_failed = FALSE; - pPageFlip->xdbg_log_pageflip = NULL; - pPageFlip->time = GetTimeInMillis (); - - /* accessilitity */ - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo; - SECFbBoDataPtr accessibility_bo_data; - - tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data); - XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail); - - fb_id = accessibility_bo_data->fb_id; - - /*Buffer is already changed by bo_swap*/ - if (!secCrtcExecAccessibility (pCrtc, bo, accessibility_bo)) - goto fail; - - pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo); - } - - /* - * DRM Page Flip - * If pPageFlip->dispatch_me is NULL, then in SECModePageFlipHandler, nothing to happen. - * That means only LCD buffer is updated. - * Frame buffer is not swapped. Because these request is only for FB_BLIT case! - */ - if (drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id, - DRM_MODE_PAGE_FLIP_EVENT, pPageFlip)) - { - XDBG_ERRNO (MDISP, "Page flip failed: %s\n", strerror (errno)); - goto fail; - } - - pCrtcPriv->flip_info = NULL; - pCrtcPriv->flip_count++; - pCrtcPriv->is_fb_blit_flipping = TRUE; - } - else - { - XDBG_DEBUG (MDISP, "pCrtcPriv->front_bo is NULL!\n"); - } - } - - ret = TRUE; - - return ret; - -fail : - - if( pPageFlip != NULL ) - { - if (pPageFlip->accessibility_back_bo) - { - secRenderBoUnref(pPageFlip->accessibility_back_bo); - pPageFlip->accessibility_back_bo = NULL; - } - - if (pPageFlip->back_bo) - { - secRenderBoUnref(pPageFlip->back_bo); - pPageFlip->back_bo = NULL; - } - - free(pPageFlip); - } - - return ret; -} - diff --git a/src/crtcconfig/sec_display.h b/src/crtcconfig/sec_display.h deleted file mode 100755 index e45cc05..0000000 --- a/src/crtcconfig/sec_display.h +++ /dev/null @@ -1,183 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 __SEC_DISPLAY_H__ -#define __SEC_DISPLAY_H__ - -#include <xf86drmMode.h> -#include <xf86Crtc.h> -#include <tbm_bufmgr.h> -#include <list.h> - -#define DBG_DRM_EVENT 1 - -typedef enum -{ - DISPLAY_SET_MODE_OFF, - DISPLAY_SET_MODE_CLONE, - DISPLAY_SET_MODE_EXT, -} SECDisplaySetMode; - -typedef enum -{ - DISPLAY_CONN_MODE_NONE, - DISPLAY_CONN_MODE_HDMI, - DISPLAY_CONN_MODE_VIRTUAL, - DISPLAY_CONN_MODE_MAX, -} SECDisplayConnMode; - -typedef enum -{ - VBLNAK_INFO_NONE, - VBLANK_INFO_SWAP, - VBLANK_INFO_PLANE, - VBLANK_INFO_MAX -} SECVBlankInfoType; - -typedef struct _secDrmEventContext { - void (*vblank_handler) (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); - - void (*page_flip_handler) (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); - - void (*g2d_handler) (int fd, - unsigned int cmdlist_no, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); - - void (*ipp_handler) (int fd, - unsigned int prop_id, - unsigned int *buf_idx, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); -} secDrmEventContext, *secDrmEventContextPtr; - -typedef struct _secDrmMode -{ - int type; - int fd; - drmModeResPtr mode_res; - drmModePlaneResPtr plane_res; - int cpp; - drmModeModeInfo main_lcd_mode; - drmModeModeInfo ext_connector_mode; - - secDrmEventContext event_context; - - struct xorg_list outputs; - struct xorg_list crtcs; - struct xorg_list planes; - - SECDisplaySetMode set_mode; - SECDisplayConnMode conn_mode; - int rotate; - - int unset_connector_type; -} SECModeRec, *SECModePtr; - -typedef struct _secPageFlip -{ - xf86CrtcPtr pCrtc; - Bool dispatch_me; - Bool clone; - Bool flip_failed; - - tbm_bo back_bo; - tbm_bo accessibility_back_bo; - - void *data; - CARD32 time; - -#if DBG_DRM_EVENT - void *xdbg_log_pageflip; -#endif -} SECPageFlipRec, *SECPageFlipPtr; - -typedef struct _secVBlankInfo -{ - SECVBlankInfoType type; - void *data; /* request data pointer */ - CARD32 time; - -#if DBG_DRM_EVENT - void *xdbg_log_vblank; -#endif -} SECVBlankInfoRec, *SECVBlankInfoPtr; - -typedef struct _secProperty -{ - drmModePropertyPtr mode_prop; - uint64_t value; - int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ - Atom *atoms; -} SECPropertyRec, *SECPropertyPtr; - -Bool secModePreInit (ScrnInfoPtr pScrn, int drm_fd); -void secModeInit (ScrnInfoPtr pScrn); -void secModeDeinit (ScrnInfoPtr pScrn); -xf86CrtcPtr secModeCoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc); -int secModeGetCrtcPipe (xf86CrtcPtr pCrtc); -Bool secModePageFlip (ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void* flip_info, int pipe, tbm_bo back_bo); -void secModeLoadPalette (ScrnInfoPtr pScrn, int numColors, int* indices, LOCO* colors, VisualPtr pVisual); - -void secDisplaySwapModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode); -void secDisplayModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode); -void secDisplaySwapModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode); -void secDisplayModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode); - -Bool secDisplaySetDispSetMode (ScrnInfoPtr pScrn, SECDisplaySetMode disp_mode); -SECDisplaySetMode secDisplayGetDispSetMode (ScrnInfoPtr pScrn); -Bool secDisplaySetDispRotate (ScrnInfoPtr pScrn, int disp_rotate); -int secDisplayGetDispRotate (ScrnInfoPtr pScrn); -Bool secDisplaySetDispConnMode (ScrnInfoPtr pScrn, SECDisplayConnMode disp_conn); -SECDisplayConnMode secDisplayGetDispConnMode (ScrnInfoPtr pScrn); - -Bool secDisplayInitDispMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode); -void secDisplayDeinitDispMode (ScrnInfoPtr pScrn); - -Bool secDisplayGetCurMSC (ScrnInfoPtr pScrn, int pipe, CARD64 *ust, CARD64 *msc); -Bool secDisplayVBlank (ScrnInfoPtr pScrn, int pipe, CARD64 *target_msc, int flip, SECVBlankInfoType type, void *vblank_info); -int secDisplayDrawablePipe (DrawablePtr pDraw); - -int secDisplayCrtcPipe (ScrnInfoPtr pScrn, int crtc_id); - -Bool secDisplayUpdateRequest(ScrnInfoPtr pScrn); - -#endif /* __SEC_DISPLAY_H__ */ - diff --git a/src/crtcconfig/sec_layer.c b/src/crtcconfig/sec_layer.c deleted file mode 100755 index d91f950..0000000 --- a/src/crtcconfig/sec_layer.c +++ /dev/null @@ -1,1146 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <stdlib.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_plane.h" -#include "sec_layer.h" -#include "sec_video_fourcc.h" -#include "sec_video_tvout.h" -#include "sec_video_virtual.h" - -#include <exynos_drm.h> - -//#define DEBUG_REFCNT - -#ifdef DEBUG_REFCNT -#define SEC_LAYER_PRINT_REFCNT(b) \ - XDBG_TRACE(MLYR, "layer(%p) ref_cnt(%d) \n", b, b->ref_cnt) -#else -#define SEC_LAYER_PRINT_REFCNT(b) -#endif - -typedef struct _NotifyFuncData -{ - NotifyFunc func; - void *user_data; - - struct xorg_list link; -} NotifyFuncData; - -struct _SECLayer -{ - ScrnInfoPtr pScrn; - - SECLayerOutput output; - SECLayerPos lpos; - - int plane_id; - int crtc_id; - - /* for buffer */ - int fb_id; - - int offset_x; - int offset_y; - - xRectangle *src; - xRectangle *dst; - - SECVideoBuf *vbuf; - Bool visible; - - /* vblank */ - Bool enable_vblank; - Bool wait_vblank; - SECVideoBuf *wait_vbuf; - SECVideoBuf *pending_vbuf; - SECVideoBuf *showing_vbuf; - - struct xorg_list noti_data; - struct xorg_list link; - - Bool onoff; - int ref_cnt; - Bool freeze_update; - - /* count */ - unsigned int put_counts; - OsTimerPtr timer; -}; - -static Bool crtc_layers_init; -static struct xorg_list crtc_layers; -static Bool wait_vblank[LAYER_OUTPUT_MAX]; - -#define LAYER_VBLANK_FLAG 0xFFFF - -static CARD32 -_countPrint (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECLayer *layer = (SECLayer*)arg; - - if (layer->timer) - { - TimerFree (layer->timer); - layer->timer = NULL; - } - - XDBG_DEBUG (MEXA, "crtc(%d) pos(%d) : %d fps. \n", - layer->crtc_id, layer->lpos, layer->put_counts); - - layer->put_counts = 0; - - return 0; -} - -static void -_countFps (SECLayer *layer) -{ - layer->put_counts++; - - if (layer->timer) - return; - - layer->timer = TimerSet (NULL, 0, 1000, _countPrint, layer); -} - -static void -_secLayerInitList (void) -{ - if (!crtc_layers_init) - { - xorg_list_init (&crtc_layers); - crtc_layers_init = TRUE; - } -} - -static void -_secLayerNotify (SECLayer *layer, int type, void *type_data) -{ - NotifyFuncData *data = NULL, *data_next = NULL; - - xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link) - { - if (data->func) - data->func (layer, type, type_data, data->user_data); - } -} - -static int -_GetCrtcIdForOutput (ScrnInfoPtr pScrn, SECLayerOutput output) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - SECOutputPrivPtr pOutputPriv = NULL; - int crtc_id = 0; - - switch (output) - { - case LAYER_OUTPUT_LCD: - pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_LVDS); - if (!pOutputPriv) - pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_Unknown); - if (pOutputPriv && pOutputPriv->mode_encoder) - crtc_id = pOutputPriv->mode_encoder->crtc_id; - break; - case LAYER_OUTPUT_EXT: - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI) - { - pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIA); - if (!pOutputPriv) - pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIB); - if (pOutputPriv && pOutputPriv->mode_encoder) - crtc_id = pOutputPriv->mode_encoder->crtc_id; - } - else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_VIRTUAL); - if (pOutputPriv && pOutputPriv->mode_encoder) - crtc_id = pOutputPriv->mode_encoder->crtc_id; - } - break; - default: - break; - } - - XDBG_DEBUG (MLYR, "crtc(%d) for output(%d) \n", crtc_id, output); - - if (crtc_id == 0) - XDBG_ERROR (MLYR, "no crtc for output(%d) \n", output); - - return crtc_id; -} - -static int -_GetCrtcID (SECLayer *layer) -{ - if (layer->crtc_id > 0) - return layer->crtc_id; - - layer->crtc_id = _GetCrtcIdForOutput (layer->pScrn, layer->output); - - XDBG_RETURN_VAL_IF_FAIL (layer->crtc_id > 0, 0); - - return layer->crtc_id; -} - -static int -_secLayerGetPlanePos (SECLayer *layer, SECLayerPos lpos) -{ - if (layer->output == LAYER_OUTPUT_LCD) - { - XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (1)\n", lpos, PLANE_POS_3 + lpos); - return PLANE_POS_3 + lpos; - } - else if (layer->output == LAYER_OUTPUT_EXT) - { - if (lpos == -1) - { - XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (2)\n", lpos, PLANE_POS_2); - return PLANE_POS_2; - } - else - { - XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (3)\n", lpos, PLANE_POS_0 + lpos); - return PLANE_POS_0 + lpos; - } - } - else - { - XDBG_NEVER_GET_HERE (MLYR); - } - - return -1; -} - -static void -_secLayerDestroy (SECLayer *layer) -{ - NotifyFuncData *data = NULL, *data_next = NULL; - - XDBG_RETURN_IF_FAIL (layer != NULL); - - xorg_list_del (&layer->link); - - if (layer->src) - free (layer->src); - if (layer->dst) - free (layer->dst); - - if (layer->wait_vbuf) - secUtilVideoBufferUnref (layer->wait_vbuf); - if (layer->pending_vbuf) - secUtilVideoBufferUnref (layer->pending_vbuf); - if (layer->showing_vbuf) - secUtilVideoBufferUnref (layer->showing_vbuf); - if (layer->vbuf) - { - secUtilVideoBufferUnref (layer->vbuf); - layer->vbuf = NULL; - } - - XDBG_TRACE (MLYR, "layer(%p) destroyed. \n", layer); - SEC_LAYER_PRINT_REFCNT (layer); - - _secLayerNotify (layer, LAYER_DESTROYED, NULL); - - xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link) - { - xorg_list_del (&data->link); - free (data); - } - - if (layer->plane_id > 0) - secPlaneFreeId (layer->plane_id); - - free (layer); -} - -static void -_secLayerWatchVblank (SECLayer *layer) -{ - CARD64 ust, msc, target_msc; - int pipe, flip = 1; - SECPtr pSec = SECPTR (layer->pScrn); - - /* if lcd is off, do not request vblank information */ - if (pSec->isLcdOff) - return; - - pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer)); - - layer->wait_vblank = TRUE; - - if (wait_vblank[pipe]) - return; - - wait_vblank[pipe] = TRUE; - - if (!secDisplayGetCurMSC (layer->pScrn, pipe, &ust, &msc)) - XDBG_WARNING (MLYR, "fail to get current_msc.\n"); - - target_msc = msc + 1; - - XDBG_TRACE (MLYR, "layer(%p) wait vblank : cur(%lld) target(%lld). \n", - layer, msc, target_msc); - - if (!secDisplayVBlank (layer->pScrn, pipe, &target_msc, flip, VBLANK_INFO_PLANE, (void*)pipe)) - XDBG_WARNING (MLYR, "fail to Vblank.\n"); -} - -static Bool -_secLayerShowInternal (SECLayer *layer, Bool need_update) -{ - int crtc_id, plane_pos; - - XDBG_RETURN_VAL_IF_FAIL (layer->fb_id > 0, FALSE); - - crtc_id = _GetCrtcID (layer); - plane_pos = _secLayerGetPlanePos (layer, layer->lpos); - - if (!secPlaneShow (layer->plane_id, crtc_id, - layer->src->x, layer->src->y, - layer->src->width, layer->src->height, - layer->offset_x + layer->dst->x, - layer->offset_y + layer->dst->y, - layer->dst->width, layer->dst->height, - plane_pos, need_update)) - return FALSE; - - return TRUE; -} - -static void -_secLayerGetBufferID (SECLayer *layer, SECVideoBuf *vbuf) -{ - SECModePtr pSecMode; - unsigned int drmfmt; - unsigned int handles[4] = {0,}; - unsigned int pitches[4] = {0,}; - unsigned int offsets[4] = {0,}; - int i; - - if (vbuf->fb_id > 0) - return; - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - drmfmt = secUtilGetDrmFormat (vbuf->id); - - for (i = 0 ; i < PLANAR_CNT; i++) - { - handles[i] = (unsigned int)vbuf->handles[i]; - pitches[i] = (unsigned int)vbuf->pitches[i]; - offsets[i] = (unsigned int)vbuf->offsets[i]; - } - - if (drmModeAddFB2 (pSecMode->fd, vbuf->width, vbuf->height, drmfmt, - handles, pitches, offsets, &vbuf->fb_id, 0)) - { - XDBG_ERRNO (MLYR, "drmModeAddFB2 failed. handles(%d %d %d) pitches(%d %d %d) offsets(%d %d %d) '%c%c%c%c'\n", - handles[0], handles[1], handles[2], - pitches[0], pitches[1], pitches[2], - offsets[0], offsets[1], offsets[2], - FOURCC_STR (drmfmt)); - } - - XDBG_DEBUG (MVBUF, "layer(%p) vbuf(%ld) fb_id(%d) added. \n", layer, vbuf->stamp, vbuf->fb_id); -} - -Bool -secLayerSupport (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos, unsigned int id) -{ - SECModePtr pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, FALSE); - - pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - - if (output == LAYER_OUTPUT_EXT && lpos == LAYER_LOWER1) - { - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI) - { - if (id == FOURCC_SN12 || id == FOURCC_ST12) - return TRUE; - else - return FALSE; - } - else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - if (id == FOURCC_SN12 || id == FOURCC_RGB32) - return TRUE; - else - return FALSE; - } - } - - return (id == FOURCC_RGB32 || id == FOURCC_SR32) ? TRUE : FALSE; -} - -SECLayer* -secLayerFind (SECLayerOutput output, SECLayerPos lpos) -{ - SECLayer *layer = NULL, *layer_next = NULL; - - XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL); - - _secLayerInitList (); - - xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link) - { - if (layer->output == output && layer->lpos == lpos) - return layer; - } - - return NULL; -} - -void -secLayerDestroyAll (void) -{ - SECLayer *layer = NULL, *layer_next = NULL; - - _secLayerInitList (); - - xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link) - { - _secLayerDestroy (layer); - } -} - -void -secLayerShowAll (ScrnInfoPtr pScrn, SECLayerOutput output) -{ - int crtc_id = _GetCrtcIdForOutput (pScrn, output); - - secPlaneShowAll (crtc_id); -} - -SECLayer* -secLayerCreate (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos) -{ - SECLayer* layer; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL); - XDBG_RETURN_VAL_IF_FAIL (lpos != LAYER_DEFAULT, NULL); - - layer = secLayerFind (output, lpos); - if (layer) - { - XDBG_ERROR (MLYR, "layer(%p) already is at output(%d) lpos(%d). \n", - layer, output, lpos); - - return NULL; - } - - layer = calloc (sizeof (SECLayer), 1); - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL); - - layer->pScrn = pScrn; - layer->output = output; - layer->lpos = lpos; - - layer->plane_id = secPlaneGetID (); - if (layer->plane_id < 0) - { - free (layer); - return NULL; - } - - layer->ref_cnt = 1; - - xorg_list_init (&layer->noti_data); - - _secLayerInitList (); - - xorg_list_add(&layer->link, &crtc_layers); - - XDBG_TRACE (MLYR, "layer(%p) output(%d) lpos(%d) created. \n", layer, output, lpos); - SEC_LAYER_PRINT_REFCNT (layer); - - return layer; -} - -SECLayer* -secLayerRef (SECLayer* layer) -{ - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL); - - layer->ref_cnt++; - - SEC_LAYER_PRINT_REFCNT (layer); - - return layer; -} - -void -secLayerUnref (SECLayer* layer) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - layer->ref_cnt--; - - SEC_LAYER_PRINT_REFCNT (layer); - - if (layer->ref_cnt == 0) - { - secLayerHide (layer); - _secLayerDestroy (layer); - } -} - -void -secLayerAddNotifyFunc (SECLayer* layer, NotifyFunc func, void *user_data) -{ - NotifyFuncData *data = NULL, *data_next = NULL; - - XDBG_RETURN_IF_FAIL (layer != NULL); - XDBG_RETURN_IF_FAIL (func != NULL); - - xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link) - { - if (data->func == func && data->user_data == user_data) - return; - } - - data = calloc (sizeof (NotifyFuncData), 1); - XDBG_RETURN_IF_FAIL (data != NULL); - - data->func = func; - data->user_data = user_data; - - xorg_list_add (&data->link, &layer->noti_data); -} - -void -secLayerRemoveNotifyFunc (SECLayer* layer, NotifyFunc func) -{ - NotifyFuncData *data = NULL, *data_next = NULL; - - XDBG_RETURN_IF_FAIL (layer != NULL); - XDBG_RETURN_IF_FAIL (func != NULL); - - xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link) - { - if (data->func == func) - { - xorg_list_del (&data->link); - free (data); - } - } -} - -Bool -secLayerIsVisible (SECLayer *layer) -{ - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - - return layer->visible; -} - -void -secLayerShow (SECLayer *layer) -{ - SECModePtr pSecMode; - - XDBG_RETURN_IF_FAIL (layer != NULL); - XDBG_RETURN_IF_FAIL (layer->fb_id > 0); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (layer->visible) - return; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - layer->visible = TRUE; - XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer); - return; - } - - if (!_secLayerShowInternal (layer, FALSE)) - return; - - if (layer->enable_vblank) - _secLayerWatchVblank (layer); - - layer->visible = TRUE; - - XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer); - - _secLayerNotify (layer, LAYER_SHOWN, (void*)layer->fb_id); -} - -void -secLayerHide (SECLayer *layer) -{ - SECModePtr pSecMode; - - XDBG_RETURN_IF_FAIL (layer != NULL); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (!layer->visible || layer->ref_cnt > 1) - return; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - layer->visible = FALSE; - XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer); - return; - } - - if (!secPlaneHide (layer->plane_id)) - return; - - if (layer->wait_vbuf && VBUF_IS_VALID (layer->wait_vbuf)) - { - layer->wait_vbuf->showing = FALSE; - XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer, - (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV", - layer->wait_vbuf->stamp, VBUF_IS_CONVERTING (layer->wait_vbuf), - layer->wait_vbuf->showing); - secUtilVideoBufferUnref (layer->wait_vbuf); - } - - if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf)) - { - layer->pending_vbuf->showing = FALSE; - secUtilVideoBufferUnref (layer->pending_vbuf); - } - - if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf)) - { - layer->showing_vbuf->showing = FALSE; - XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer, - (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV", - layer->showing_vbuf->stamp, VBUF_IS_CONVERTING (layer->showing_vbuf), - layer->showing_vbuf->showing); - secUtilVideoBufferUnref (layer->showing_vbuf); - } - - layer->showing_vbuf = NULL; - layer->pending_vbuf = NULL; - layer->wait_vbuf = NULL; - layer->wait_vblank = FALSE; - layer->visible = FALSE; - layer->crtc_id = 0; - - XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer); - - _secLayerNotify (layer, LAYER_HIDDEN, (void*)layer->fb_id); -} - -void -secLayerFreezeUpdate (SECLayer *layer, Bool enable) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - layer->freeze_update = enable; - - XDBG_TRACE (MLYR, "layer(%p) freeze %d. \n", layer, enable); - - if (layer->plane_id > 0) - secPlaneFreezeUpdate (layer->plane_id, enable); -} - -void -secLayerUpdate (SECLayer *layer) -{ - SECModePtr pSecMode; - - XDBG_RETURN_IF_FAIL (layer != NULL); - XDBG_RETURN_IF_FAIL (layer->fb_id > 0); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (!layer->visible) - return; - - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (layer->pScrn); - SECCrtcPrivPtr pCrtcPriv = NULL; - int c; - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; - SECCrtcPrivPtr pTemp = pCrtc->driver_private; - if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == layer->crtc_id) - { - pCrtcPriv = pTemp; - break; - } - } - - if (!pCrtcPriv || !pCrtcPriv->bAccessibility) - return; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - return; - - if (!_secLayerShowInternal (layer, TRUE)) - return; -} - -void -secLayerTurn (SECLayer *layer, Bool onoff, Bool user) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - secPlaneTrun (layer->plane_id, onoff, user); -} - -Bool -secLayerTurnStatus (SECLayer *layer) -{ - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - - return secPlaneTrunStatus (layer->plane_id); -} - -void -secLayerEnableVBlank (SECLayer *layer, Bool enable) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - layer->enable_vblank = (enable) ? TRUE : FALSE; -} - -Bool -secLayerSetOffset (SECLayer *layer, int x, int y) -{ - SECModePtr pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (layer->offset_x == x && layer->offset_y == y) - return TRUE; - - /* display controller restriction. x+width=2's mutiple */ - XDBG_TRACE (MLYR, "layer(%p) offset(%d,%d => %d,%d).\n", - layer, x, y, x & (~0x1), y); - layer->offset_x = x & (~0x1); - layer->offset_y = y; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - return TRUE; - - if (secLayerIsVisible (layer) && !layer->freeze_update) - { - int crtc_id = _GetCrtcID (layer); - int plane_pos = _secLayerGetPlanePos (layer, layer->lpos); - - if (!secPlaneShow (layer->plane_id, crtc_id, - layer->src->x, layer->src->y, - layer->src->width, layer->src->height, - layer->offset_x + layer->dst->x, - layer->offset_y + layer->dst->y, - layer->dst->width, layer->dst->height, - plane_pos, FALSE)) - return FALSE; - } - - return TRUE; -} - -void -secLayerGetOffset (SECLayer *layer, int *x, int *y) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - if (x) - *x = layer->offset_x; - if (y) - *y = layer->offset_y; -} - -Bool -secLayerSetPos (SECLayer *layer, SECLayerPos lpos) -{ - SECModePtr pSecMode; - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_NONE && lpos < LAYER_MAX, FALSE); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - layer->lpos = lpos; - return TRUE; - } - - - if (layer->lpos == lpos) - return TRUE; - - if (secLayerFind (layer->output, lpos)) - return FALSE; - - if (secLayerIsVisible (layer) && !layer->freeze_update) - { - if (lpos == LAYER_NONE) - { - if (!secPlaneHide (layer->plane_id)) - return FALSE; - - layer->visible = FALSE; - layer->crtc_id = 0; - } - else - { - int crtc_id = _GetCrtcID (layer); - int plane_pos = _secLayerGetPlanePos (layer, lpos); - - if (!secPlaneShow (layer->plane_id, crtc_id, - layer->src->x, layer->src->y, - layer->src->width, layer->src->height, - layer->offset_x + layer->dst->x, - layer->offset_y + layer->dst->y, - layer->dst->width, layer->dst->height, - plane_pos, FALSE)) - return FALSE; - } - } - - XDBG_TRACE (MLYR, "layer(%p) lpos(%d). \n", layer, lpos); - - layer->lpos = lpos; - - return TRUE; -} - -Bool -secLayerSwapPos (SECLayer *layer1, SECLayer *layer2) -{ - SECLayer *lower, *upper; - SECLayerPos upper_lpos, lower_lpos; - - XDBG_RETURN_VAL_IF_FAIL (layer1 != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (layer2 != NULL, FALSE); - - XDBG_TRACE (MLYR, "layer1(%p) layer2(%p). \n", layer1, layer2); - - lower = (layer2->lpos < layer1->lpos) ? layer2 : layer1; - upper = (layer2->lpos < layer1->lpos) ? layer1 : layer2; - - upper_lpos = upper->lpos; - lower_lpos = lower->lpos; - - secLayerSetPos (upper, LAYER_NONE); - secLayerSetPos (lower, upper_lpos); - secLayerSetPos (upper, lower_lpos); - - return TRUE; -} - -SECLayerPos -secLayerGetPos (SECLayer *layer) -{ - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0); - - return layer->lpos; -} - -Bool -secLayerSetRect (SECLayer *layer, xRectangle *src, xRectangle *dst) -{ - SECModePtr pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE); - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (!layer->src) - layer->src = calloc (sizeof (xRectangle), 1); - - XDBG_RETURN_VAL_IF_FAIL (layer->src != NULL, FALSE); - - if (!layer->dst) - layer->dst = calloc (sizeof (xRectangle), 1); - - XDBG_RETURN_VAL_IF_FAIL (layer->dst != NULL, FALSE); - - if (!memcmp (layer->src, src, sizeof (xRectangle)) && - !memcmp (layer->dst, dst, sizeof (xRectangle))) - return TRUE; - - *layer->src = *src; - *layer->dst = *dst; - - XDBG_TRACE (MLYR, "layer(%p) src(%d,%d %dx%d) dst(%d,%d %dx%d). \n", - layer, src->x, src->y, src->width, src->height, - dst->x, dst->y, dst->width, dst->height); - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - return TRUE; - - if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf)) - { - layer->pending_vbuf->showing = FALSE; - secUtilVideoBufferUnref (layer->pending_vbuf); - layer->pending_vbuf = NULL; - } - - if (secLayerIsVisible (layer) && !layer->freeze_update) - { - int plane_pos = _secLayerGetPlanePos (layer, layer->lpos); - - if (!secPlaneShow (layer->plane_id, _GetCrtcID (layer), - src->x, src->y, src->width, src->height, - layer->offset_x + dst->x, - layer->offset_y + dst->y, - dst->width, dst->height, - plane_pos, FALSE)) - return FALSE; - } - - return TRUE; -} - -void -secLayerGetRect (SECLayer *layer, xRectangle *src, xRectangle *dst) -{ - XDBG_RETURN_IF_FAIL (layer != NULL); - - if (src && layer->src) - *src = *layer->src; - - if (dst && layer->dst) - *dst = *layer->dst; -} - -int -secLayerSetBuffer (SECLayer *layer, SECVideoBuf *vbuf) -{ - SECModePtr pSecMode; - unsigned int fb_id; - - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0); - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0); - - if (!secLayerSupport (layer->pScrn, layer->output, layer->lpos, vbuf->id)) - { - XDBG_ERROR (MLYR, "fail : layer(%p) output(%d) lpos(%d) vbuf(%c%c%c%c)\n", - layer, layer->output, layer->lpos, FOURCC_STR (vbuf->id)); - return 0; - } - - pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode; - - if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - XDBG_RETURN_VAL_IF_FAIL (layer->enable_vblank == FALSE, 0); - - XDBG_TRACE (MLYR, "layer(%p) vbuf('%c%c%c%c', %dx%d, %d,%d %dx%d)\n", - layer, FOURCC_STR(vbuf->id), vbuf->width, vbuf->height, - vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height); - - if (layer->vbuf) - secUtilVideoBufferUnref (layer->vbuf); - - layer->vbuf = secUtilVideoBufferRef (vbuf); - layer->fb_id = 1; - - _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf); - - return layer->fb_id; - } - - if (layer->wait_vbuf && layer->pending_vbuf) - { - XDBG_TRACE (MLYR, "pending_vbuf(%ld) exists.\n", layer->pending_vbuf->stamp); - return 0; - } - - _secLayerGetBufferID (layer, vbuf); - XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0); - - if (layer->wait_vbuf && !layer->pending_vbuf) - { - layer->pending_vbuf = secUtilVideoBufferRef (vbuf); - XDBG_RETURN_VAL_IF_FAIL(layer->pending_vbuf, 0) - layer->pending_vbuf->showing = TRUE; - XDBG_TRACE (MLYR, "pending vbuf(%ld).\n", layer->pending_vbuf->stamp); - return vbuf->fb_id; - } - - fb_id = secPlaneGetBuffer (layer->plane_id, NULL, vbuf); - if (fb_id == 0) - { - fb_id = secPlaneAddBuffer (layer->plane_id, vbuf); - XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0); - - layer->fb_id = vbuf->fb_id; - } - - if (vbuf->fb_id != fb_id) - XDBG_WARNING (MLYR, "fb_id (%d != %d) \n", vbuf->fb_id, fb_id); - - layer->fb_id = fb_id; - if (!secPlaneAttach (layer->plane_id, fb_id)) - return 0; - - if (secLayerIsVisible (layer) && !layer->freeze_update) - if (!_secLayerShowInternal (layer, TRUE)) - return 0; - - if (layer->enable_vblank) - { - XDBG_RETURN_VAL_IF_FAIL (layer->wait_vbuf == NULL, 0); - - layer->wait_vbuf = secUtilVideoBufferRef (vbuf); - XDBG_RETURN_VAL_IF_FAIL ((layer->wait_vbuf != NULL), 0); - layer->wait_vbuf->showing = TRUE; - XDBG_DEBUG (MVBUF, "layer(%p) --> %s (%ld,%d,%d) \n", layer, - (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV", - layer->wait_vbuf->stamp, - VBUF_IS_CONVERTING (layer->wait_vbuf), - layer->wait_vbuf->showing); - - if (secLayerIsVisible (layer)) - { - XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) attached. \n", layer, fb_id); - _secLayerWatchVblank (layer); - } - } - - if (layer->vbuf) - secUtilVideoBufferUnref (layer->vbuf); - layer->vbuf = secUtilVideoBufferRef (vbuf); - - _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf); - - return fb_id; -} - -SECVideoBuf* -secLayerGetBuffer (SECLayer *layer) -{ - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL); - - if (layer->showing_vbuf && layer->dst && layer->visible) - return layer->showing_vbuf; - else if (layer->vbuf) - return layer->vbuf; - - return NULL; -} - -void -secLayerVBlankEventHandler (unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - SECLayer *layer = NULL, *layer_next = NULL; - int pipe = (int)event_data; - - XDBG_RETURN_IF_FAIL (pipe < LAYER_OUTPUT_MAX); - - _secLayerInitList (); - - wait_vblank[pipe] = FALSE; - - XDBG_DEBUG (MLYR, "frame(%d), tv_sec(%d), tv_usec(%d) \n", frame, tv_sec, tv_usec); - - xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link) - { - int crtc_pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer)); - - if (!layer->enable_vblank || !layer->wait_vblank) - continue; - - if (crtc_pipe != pipe) - continue; - - layer->wait_vblank = FALSE; - - if (VBUF_IS_VALID (layer->wait_vbuf)) - { - if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf)) - { - layer->showing_vbuf->showing = FALSE; - secUtilVideoBufferUnref (layer->showing_vbuf); - } - - layer->showing_vbuf = layer->wait_vbuf; - layer->wait_vbuf = NULL; - - if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf)) - { - int fb_id; - - layer->wait_vbuf = layer->pending_vbuf; - layer->pending_vbuf = NULL; - - fb_id = secPlaneGetBuffer (layer->plane_id, NULL, layer->wait_vbuf); - if (fb_id == 0) - { - fb_id = secPlaneAddBuffer (layer->plane_id, layer->wait_vbuf); - XDBG_RETURN_IF_FAIL (fb_id > 0); - - layer->fb_id = layer->wait_vbuf->fb_id; - } - - if (!secPlaneAttach (layer->plane_id, layer->wait_vbuf->fb_id)) - continue; - - if (secLayerIsVisible (layer) && !layer->freeze_update) - _secLayerShowInternal (layer, TRUE); - - _secLayerWatchVblank (layer); - } - - SECPtr pSec = SECPTR (layer->pScrn); - if (pSec->pVideoPriv->video_fps) - _countFps (layer); - - XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) now showing frame(%d) (%ld,%ld,%ld) => crtc(%d) pos(%d). \n", - layer, layer->fb_id, frame, - VSTMAP(layer->pending_vbuf), VSTMAP(layer->wait_vbuf), VSTMAP(layer->showing_vbuf), - _GetCrtcID (layer), layer->lpos); - - _secLayerNotify (layer, LAYER_VBLANK, (void*)layer->showing_vbuf); - } - } -} diff --git a/src/crtcconfig/sec_layer.h b/src/crtcconfig/sec_layer.h deleted file mode 100644 index e3f0685..0000000 --- a/src/crtcconfig/sec_layer.h +++ /dev/null @@ -1,105 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 __SEC_LAYER_H__ -#define __SEC_LAYER_H__ - -#include "sec_video_types.h" -#include "sec_video_fourcc.h" - -typedef enum -{ - LAYER_OUTPUT_LCD, - LAYER_OUTPUT_EXT, - LAYER_OUTPUT_MAX -} SECLayerOutput; - -typedef enum -{ - LAYER_NONE = -3, - LAYER_LOWER2 = -2, - LAYER_LOWER1 = -1, - LAYER_DEFAULT = 0, - LAYER_UPPER = +1, - LAYER_MAX = +2, -} SECLayerPos; - -#define LAYER_DESTROYED 1 -#define LAYER_SHOWN 2 -#define LAYER_HIDDEN 3 -/* To manage buffer */ -#define LAYER_BUF_CHANGED 4 /* type_data: SECLayerBufInfo */ -#define LAYER_VBLANK 5 /* type_data: SECLayerBufInfo */ - -typedef struct _SECLayer SECLayer; - -typedef void (*NotifyFunc) (SECLayer *layer, int type, void *type_data, void *user_data); - -Bool secLayerSupport (ScrnInfoPtr pScrn, SECLayerOutput output, - SECLayerPos lpos, unsigned int id); - -SECLayer* secLayerFind (SECLayerOutput output, SECLayerPos lpos); -void secLayerDestroyAll (void); -void secLayerShowAll (ScrnInfoPtr pScrn, SECLayerOutput output); - -void secLayerAddNotifyFunc (SECLayer *layer, NotifyFunc func, void *user_data); -void secLayerRemoveNotifyFunc (SECLayer *layer, NotifyFunc func); - -SECLayer* secLayerCreate (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos); -SECLayer* secLayerRef (SECLayer *layer); -void secLayerUnref (SECLayer *layer); - -Bool secLayerIsVisible (SECLayer *layer); -void secLayerShow (SECLayer *layer); -void secLayerHide (SECLayer *layer); -void secLayerFreezeUpdate (SECLayer *layer, Bool enable); -void secLayerUpdate (SECLayer *layer); -void secLayerTurn (SECLayer *layer, Bool onoff, Bool user); -Bool secLayerTurnStatus (SECLayer *layer); - -void secLayerEnableVBlank (SECLayer *layer, Bool enable); - -Bool secLayerSetOffset (SECLayer *layer, int x, int y); -void secLayerGetOffset (SECLayer *layer, int *x, int *y); - -Bool secLayerSetPos (SECLayer *layer, SECLayerPos lpos); -SECLayerPos secLayerGetPos (SECLayer *layer); -Bool secLayerSwapPos (SECLayer *layer1, SECLayer *layer2); - -Bool secLayerSetRect (SECLayer *layer, xRectangle *src, xRectangle *dst); -void secLayerGetRect (SECLayer *layer, xRectangle *src, xRectangle *dst); - -int secLayerSetBuffer (SECLayer *layer, SECVideoBuf *vbuf); -SECVideoBuf* secLayerGetBuffer (SECLayer *layer); - -void secLayerVBlankEventHandler (unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); - -#endif /* __SEC_LAYER_H__ */ diff --git a/src/crtcconfig/sec_output.c b/src/crtcconfig/sec_output.c deleted file mode 100755 index 448c5c8..0000000 --- a/src/crtcconfig/sec_output.c +++ /dev/null @@ -1,881 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <stdint.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <poll.h> - -#include <xorgVersion.h> -#include <tbm_bufmgr.h> -#include <xf86Crtc.h> -#include <xf86DDC.h> -#include <xf86cmap.h> -#include <list.h> -#include <X11/Xatom.h> -#include <X11/extensions/dpmsconst.h> -#include <sec.h> - -#include "sec_util.h" -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_prop.h" -#include "sec_xberc.h" -#include "sec_layer.h" -#include "sec_wb.h" -#include "sec_video_virtual.h" - -static const int subpixel_conv_table[7] = -{ - 0, - SubPixelUnknown, - SubPixelHorizontalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalRGB, - SubPixelVerticalBGR, - SubPixelNone -}; - -static const char *output_names[] = -{ - "None", - "VGA", - "DVI", - "DVI", - "DVI", - "Composite", - "TV", - "LVDS", - "CTV", - "DIN", - "DP", - "HDMI", - "HDMI", - "TV", - "eDP", - "Virtual", -}; - -static CARD32 -_secOutputResumeWbTimeout (OsTimerPtr timer, CARD32 now, pointer arg) -{ - XDBG_RETURN_VAL_IF_FAIL(arg, 0); - - xf86OutputPtr pOutput = (xf86OutputPtr)arg; - SECPtr pSec = SECPTR (pOutput->scrn); - - pSec = SECPTR (pOutput->scrn); - - if (pSec->resume_timer) - { - TimerFree (pSec->resume_timer); - pSec->resume_timer = NULL; - } - - secDisplaySetDispSetMode (pOutput->scrn, pSec->set_mode); - pSec->set_mode = DISPLAY_SET_MODE_OFF; - - return 0; -} - -static void -_secOutputAttachEdid(xf86OutputPtr pOutput) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - drmModeConnectorPtr koutput = pOutputPriv->mode_output; - SECModePtr pSecMode = pOutputPriv->pSecMode; - drmModePropertyBlobPtr edid_blob = NULL; - xf86MonPtr mon = NULL; - int i; - - /* look for an EDID property */ - for (i = 0; i < koutput->count_props; i++) - { - drmModePropertyPtr props; - - props = drmModeGetProperty (pSecMode->fd, koutput->props[i]); - if (!props) - continue; - - if (!(props->flags & DRM_MODE_PROP_BLOB)) - { - drmModeFreeProperty (props); - continue; - } - - if (!strcmp (props->name, "EDID")) - { - drmModeFreePropertyBlob (edid_blob); - edid_blob = - drmModeGetPropertyBlob (pSecMode->fd, - koutput->prop_values[i]); - } - drmModeFreeProperty (props); - } - - if (edid_blob) - { - mon = xf86InterpretEDID (pOutput->scrn->scrnIndex, - edid_blob->data); - - if (mon && edid_blob->length > 128) - mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; - } - - xf86OutputSetEDID (pOutput, mon); - - if (edid_blob) - drmModeFreePropertyBlob (edid_blob); -} - -static Bool -_secOutputPropertyIgnore(drmModePropertyPtr prop) -{ - if (!prop) - return TRUE; - - /* ignore blob prop */ - if (prop->flags & DRM_MODE_PROP_BLOB) - return TRUE; - - /* ignore standard property */ - if (!strcmp (prop->name, "EDID") || - !strcmp (prop->name, "DPMS")) - return TRUE; - - return FALSE; -} - -static xf86OutputStatus -SECOutputDetect(xf86OutputPtr output) -{ - /* go to the hw and retrieve a new output struct */ - SECOutputPrivPtr pOutputPriv = output->driver_private; - SECModePtr pSecMode = pOutputPriv->pSecMode; - xf86OutputStatus status; -// char *conn_str[] = {"connected", "disconnected", "unknow"}; - - /* update output */ - drmModeFreeConnector (pOutputPriv->mode_output); - pOutputPriv->mode_output = - drmModeGetConnector (pSecMode->fd, pOutputPriv->output_id); - XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_output != NULL, XF86OutputStatusUnknown); - - /* update encoder */ - drmModeFreeEncoder (pOutputPriv->mode_encoder); - pOutputPriv->mode_encoder = - drmModeGetEncoder (pSecMode->fd, pOutputPriv->mode_output->encoders[0]); - XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_encoder != NULL, XF86OutputStatusUnknown); - - if (pSecMode->unset_connector_type == pOutputPriv->mode_output->connector_type) - { - return XF86OutputStatusDisconnected; - } -#if 0 - XDBG_INFO (MSEC, "detect : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n", - pOutputPriv->output_id, pOutputPriv->mode_output->connector_type, - conn_str[pOutputPriv->mode_output->connection-1], - pOutputPriv->mode_encoder->encoder_id, pOutputPriv->mode_encoder->crtc_id); -#endif - switch (pOutputPriv->mode_output->connection) - { - case DRM_MODE_CONNECTED: - status = XF86OutputStatusConnected; - break; - case DRM_MODE_DISCONNECTED: - status = XF86OutputStatusDisconnected; - /* unset write-back clone */ - secPropUnSetDisplayMode (output); - break; - default: - case DRM_MODE_UNKNOWNCONNECTION: - status = XF86OutputStatusUnknown; - break; - } - return status; -} - -static Bool -SECOutputModeValid(xf86OutputPtr pOutput, DisplayModePtr pModes) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - drmModeConnectorPtr koutput = pOutputPriv->mode_output; - int i; - - /* driver want to remain available modes which is same as mode - supported from drmmode */ - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS) - { - for (i = 0; i < koutput->count_modes; i++) - { - if (pModes->HDisplay == koutput->modes[i].hdisplay && - pModes->VDisplay == koutput->modes[i].vdisplay) - return MODE_OK; - } - return MODE_ERROR; - } - - return MODE_OK; -} - -static DisplayModePtr -SECOutputGetModes(xf86OutputPtr pOutput) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - drmModeConnectorPtr koutput = pOutputPriv->mode_output; - DisplayModePtr Modes = NULL; - int i; - SECPtr pSec = SECPTR (pOutput->scrn); - DisplayModePtr Mode; - - /* LVDS1 (main LCD) does not provide edid data */ - if (pOutputPriv->mode_output->connector_type != DRM_MODE_CONNECTOR_LVDS) - _secOutputAttachEdid(pOutput); - - /* modes should already be available */ - for (i = 0; i < koutput->count_modes; i++) - { - Mode = calloc (1, sizeof (DisplayModeRec)); - if (Mode) - { - /* generate the fake modes when screen rotation is set */ - if(pSec->fake_root) - secDisplaySwapModeFromKmode(pOutput->scrn, &koutput->modes[i], Mode); - else - secDisplayModeFromKmode(pOutput->scrn, &koutput->modes[i], Mode); - Modes = xf86ModesAdd(Modes, Mode); - } - } - - return Modes; -} - -static void -SECOutputDestory(xf86OutputPtr pOutput) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - SECPtr pSec = SECPTR (pOutput->scrn); - int i; - - if (pSec->resume_timer) - { - TimerFree (pSec->resume_timer); - pSec->resume_timer = NULL; - } - pSec->set_mode = DISPLAY_SET_MODE_OFF; - - for (i = 0; i < pOutputPriv->num_props; i++) - { - drmModeFreeProperty (pOutputPriv->props[i].mode_prop); - free (pOutputPriv->props[i].atoms); - } - free (pOutputPriv->props); - - drmModeFreeEncoder (pOutputPriv->mode_encoder); - drmModeFreeConnector (pOutputPriv->mode_output); - xorg_list_del (&pOutputPriv->link); - free (pOutputPriv); - - pOutput->driver_private = NULL; -} - -static void -SECOutputDpms(xf86OutputPtr pOutput, int dpms) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - drmModeConnectorPtr koutput = pOutputPriv->mode_output; - SECModePtr pSecMode = pOutputPriv->pSecMode; - SECPtr pSec = SECPTR (pOutput->scrn); - int old_dpms = pOutputPriv->dpms_mode; - int i; - - if (!strcmp(pOutput->name, "HDMI1") || - !strcmp(pOutput->name, "Virtual1")) - return; - - if (dpms == DPMSModeSuspend) - return; - - for (i = 0; i < koutput->count_props; i++) - { - drmModePropertyPtr props; - - props = drmModeGetProperty (pSecMode->fd, koutput->props[i]); - if (!props) - continue; - - if ((old_dpms == DPMSModeStandby && dpms == DPMSModeOn) || - (old_dpms == DPMSModeOn && dpms == DPMSModeStandby)) - { - if (!strcmp (props->name, "panel")) - { - int value = (dpms == DPMSModeStandby)? 1 : 0; - drmModeConnectorSetProperty(pSecMode->fd, - pOutputPriv->output_id, - props->prop_id, - value); - pOutputPriv->dpms_mode = dpms; - drmModeFreeProperty (props); - XDBG_INFO (MDPMS, "panel '%s'\n", (value)?"OFF":"ON"); - return; - } - } - else if (!strcmp (props->name, "DPMS")) - { - int _tmp_dpms = dpms; - switch (dpms) - { - case DPMSModeStandby: - case DPMSModeOn: - if (pOutputPriv->isLcdOff == FALSE) - { - drmModeFreeProperty (props); - return; - } - /* lcd on */ - XDBG_INFO (MDPMS, "\t Reqeust DPMS ON (%s)\n", pOutput->name); - _tmp_dpms = DPMSModeOn; - pOutputPriv->isLcdOff = FALSE; - - if (!strcmp(pOutput->name, "LVDS1")) - { - pSec->isLcdOff = FALSE; - - /* if wb need to be started, start wb after timeout. */ - if (pSec->set_mode == DISPLAY_SET_MODE_CLONE) - { - pSec->resume_timer = TimerSet (pSec->resume_timer, - 0, 30, - _secOutputResumeWbTimeout, - pOutput); - } - - secVideoDpms (pOutput->scrn, TRUE); - secVirtualVideoDpms (pOutput->scrn, TRUE); - } - - /* accessibility */ - SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; - if (pCrtcPriv->screen_rotate_degree > 0) - secCrtcEnableScreenRotate (pOutput->crtc, TRUE); - else - secCrtcEnableScreenRotate (pOutput->crtc, FALSE); - if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0) - { - tbm_bo src_bo = pCrtcPriv->front_bo; - tbm_bo dst_bo = pCrtcPriv->accessibility_back_bo; - if (!secCrtcExecAccessibility (pOutput->crtc, src_bo, dst_bo)) - { - XDBG_ERROR(MDPMS, "Fail execute accessibility(output name, %s)\n", - pOutput->name); - } - } - - /* set current fb to crtc */ - if(!secCrtcApply(pOutput->crtc)) - { - XDBG_ERROR(MDPMS, "Fail crtc apply(output name, %s)\n", - pOutput->name); - } - break; - case DPMSModeOff: - if (pOutputPriv->isLcdOff == TRUE) - { - drmModeFreeProperty (props); - return; - } - /* lcd off */ - XDBG_INFO (MDPMS, "\t Reqeust DPMS OFF (%s)\n", pOutput->name); - _tmp_dpms = DPMSModeOff; - pOutputPriv->isLcdOff = TRUE; - - secCrtcEnableScreenRotate (pOutput->crtc, FALSE); - - if (!strcmp(pOutput->name, "LVDS1")) - { - secVideoDpms (pOutput->scrn, FALSE); - secVirtualVideoDpms (pOutput->scrn, FALSE); - - pSec->isLcdOff = TRUE; - - if (pSec->resume_timer) - { - TimerFree (pSec->resume_timer); - drmModeFreeProperty (props); - pSec->resume_timer = NULL; - return; - } - - /* keep previous pSecMode's set_mode. */ - pSec->set_mode = secDisplayGetDispSetMode (pOutput->scrn); - - if (pSec->set_mode == DISPLAY_SET_MODE_CLONE) - { - /* stop wb if wb is working. */ - secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_OFF); - } - } - break; - default: - drmModeFreeProperty (props); - return; - } - - drmModeConnectorSetProperty(pSecMode->fd, - pOutputPriv->output_id, - props->prop_id, - _tmp_dpms); - - XDBG_INFO (MDPMS, "\t Success DPMS request (%s)\n", pOutput->name); - - pOutputPriv->dpms_mode = _tmp_dpms; - drmModeFreeProperty (props); - return; - } - - drmModeFreeProperty (props); - } -} - -static void -SECOutputCreateReaources(xf86OutputPtr pOutput) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - drmModeConnectorPtr mode_output = pOutputPriv->mode_output; - SECModePtr pSecMode = pOutputPriv->pSecMode; - int i, j, err; - - pOutputPriv->props = calloc (mode_output->count_props, sizeof (SECPropertyRec)); - if (!pOutputPriv->props) - return; - - pOutputPriv->num_props = 0; - for (i = j = 0; i < mode_output->count_props; i++) - { - drmModePropertyPtr drmmode_prop; - - drmmode_prop = drmModeGetProperty(pSecMode->fd, - mode_output->props[i]); - if (_secOutputPropertyIgnore(drmmode_prop)) - { - drmModeFreeProperty (drmmode_prop); - continue; - } - - pOutputPriv->props[j].mode_prop = drmmode_prop; - pOutputPriv->props[j].value = mode_output->prop_values[i]; - j++; - } - pOutputPriv->num_props = j; - - for (i = 0; i < pOutputPriv->num_props; i++) - { - SECPropertyPtr p = &pOutputPriv->props[i]; - drmModePropertyPtr drmmode_prop = p->mode_prop; - - if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) - { - INT32 range[2]; - - p->num_atoms = 1; - p->atoms = calloc (p->num_atoms, sizeof (Atom)); - if (!p->atoms) - continue; - - p->atoms[0] = MakeAtom (drmmode_prop->name, strlen (drmmode_prop->name), TRUE); - range[0] = drmmode_prop->values[0]; - range[1] = drmmode_prop->values[1]; - err = RRConfigureOutputProperty (pOutput->randr_output, p->atoms[0], - FALSE, TRUE, - drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, - 2, range); - if (err != 0) - { - xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - err = RRChangeOutputProperty (pOutput->randr_output, p->atoms[0], - XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE); - if (err != 0) - { - xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - } - else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) - { - p->num_atoms = drmmode_prop->count_enums + 1; - p->atoms = calloc (p->num_atoms, sizeof (Atom)); - if (!p->atoms) - continue; - - p->atoms[0] = MakeAtom (drmmode_prop->name, strlen (drmmode_prop->name), TRUE); - for (j = 1; j <= drmmode_prop->count_enums; j++) - { - struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; - p->atoms[j] = MakeAtom (e->name, strlen (e->name), TRUE); - } - - err = RRConfigureOutputProperty (pOutput->randr_output, p->atoms[0], - FALSE, FALSE, - drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, - p->num_atoms - 1, (INT32*)&p->atoms[1]); - if (err != 0) - { - xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - - for (j = 0; j < drmmode_prop->count_enums; j++) - if (drmmode_prop->enums[j].value == p->value) - break; - /* there's always a matching value */ - err = RRChangeOutputProperty (pOutput->randr_output, p->atoms[0], - XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); - if (err != 0) - { - xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - } - - if (p->atoms) - free (p->atoms); - } -} - -static Bool -SECOutputSetProperty(xf86OutputPtr output, Atom property, - RRPropertyValuePtr value) -{ - SECOutputPrivPtr pOutputPriv = output->driver_private; - SECModePtr pSecMode = pOutputPriv->pSecMode; - int i; - - //SECOutputDpms(output, DPMSModeStandby); - - for (i = 0; i < pOutputPriv->num_props; i++) - { - SECPropertyPtr p = &pOutputPriv->props[i]; - - if (p->atoms[0] != property) - continue; - - if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) - { - uint32_t val; - - if (value->type != XA_INTEGER || value->format != 32 || - value->size != 1) - return FALSE; - val = *(uint32_t*)value->data; - - drmModeConnectorSetProperty (pSecMode->fd, pOutputPriv->output_id, - p->mode_prop->prop_id, (uint64_t) val); - return TRUE; - } - else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) - { - Atom atom; - const char *name; - int j; - - if (value->type != XA_ATOM || value->format != 32 || value->size != 1) - return FALSE; - memcpy (&atom, value->data, 4); - name = NameForAtom (atom); - XDBG_RETURN_VAL_IF_FAIL ((name != NULL), FALSE); - - /* search for matching name string, then set its value down */ - for (j = 0; j < p->mode_prop->count_enums; j++) - { - if (!strcmp (p->mode_prop->enums[j].name, name)) - { - drmModeConnectorSetProperty (pSecMode->fd, pOutputPriv->output_id, - p->mode_prop->prop_id, p->mode_prop->enums[j].value); - return TRUE; - } - } - return FALSE; - } - } - - /* We didn't recognise this property, just report success in order - * to allow the set to continue, otherwise we break setting of - * common properties like EDID. - */ - /* set the hidden properties : features for sec debugging*/ - /* TODO : xberc can works on only LVDS????? */ - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS) - { - if (secPropSetLvdsFunc (output, property, value)) - return TRUE; - - if (secPropSetFbVisible (output, property, value)) - return TRUE; - - if (secPropSetVideoOffset (output, property, value)) - return TRUE; - - if (secPropSetScreenRotate (output, property, value)) - return TRUE; - - if (secXbercSetProperty (output, property, value)) - return TRUE; - } - /* set the hidden properties : features for driver specific funtions */ - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - /* set the property for the display mode */ - if (secPropSetDisplayMode(output, property, value)) - return TRUE; - } - - return TRUE; -} - -static Bool -SECOutputGetProperty(xf86OutputPtr pOutput, Atom property) -{ - return FALSE; -} - -static const xf86OutputFuncsRec sec_output_funcs = -{ - .create_resources = SECOutputCreateReaources, -#ifdef RANDR_12_INTERFACE - .set_property = SECOutputSetProperty, - .get_property = SECOutputGetProperty, -#endif - .dpms = SECOutputDpms, -#if 0 - .save = drmmode_crt_save, - .restore = drmmode_crt_restore, - .mode_fixup = drmmode_crt_mode_fixup, - .prepare = sec_output_prepare, - .mode_set = drmmode_crt_mode_set, - .commit = sec_output_commit, -#endif - .detect = SECOutputDetect, - .mode_valid = SECOutputModeValid, - - .get_modes = SECOutputGetModes, - .destroy = SECOutputDestory -}; - -Bool -secOutputDrmUpdate (ScrnInfoPtr pScrn) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - Bool ret = TRUE; - int i; - - for (i = 0; i < pSecMode->mode_res->count_connectors; i++) - { - SECOutputPrivPtr pCur = NULL, pNext = NULL, pOutputPriv = NULL; - drmModeConnectorPtr koutput; - drmModeEncoderPtr kencoder; - char *conn_str[] = {"connected", "disconnected", "unknow"}; - - xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->outputs, link) - { - if (pCur->output_id == pSecMode->mode_res->connectors[i]) - { - pOutputPriv = pCur; - break; - } - } - - if (!pOutputPriv) - { - ret = FALSE; - break; - } - - koutput = drmModeGetConnector (pSecMode->fd, - pSecMode->mode_res->connectors[i]); - if (!koutput) - { - ret = FALSE; - break; - } - - kencoder = drmModeGetEncoder (pSecMode->fd, koutput->encoders[0]); - if (!kencoder) - { - drmModeFreeConnector (koutput); - ret = FALSE; - break; - } - - if (pOutputPriv->mode_output) - { - drmModeFreeConnector (pOutputPriv->mode_output); - pOutputPriv->mode_output = NULL; - } - pOutputPriv->mode_output = koutput; - - if (pOutputPriv->mode_encoder) - { - drmModeFreeEncoder (pOutputPriv->mode_encoder); - pOutputPriv->mode_encoder = NULL; - } - pOutputPriv->mode_encoder = kencoder; - - XDBG_INFO (MSEC, "drm update : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n", - pSecMode->mode_res->connectors[i], koutput->connector_type, - conn_str[pOutputPriv->mode_output->connection-1], - kencoder->encoder_id, kencoder->crtc_id); -#if 0 - /* Does these need to update? */ - pOutput->mm_width = koutput->mmWidth; - pOutput->mm_height = koutput->mmHeight; - - pOutput->possible_crtcs = kencoder->possible_crtcs; - pOutput->possible_clones = kencoder->possible_clones; -#endif - } - - if (!ret) - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "drm(output) update error. (%s)\n", strerror (errno)); - - return ret; -} - -void -secOutputInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num) -{ - xf86OutputPtr pOutput; - drmModeConnectorPtr koutput; - drmModeEncoderPtr kencoder; - SECOutputPrivPtr pOutputPriv; - const char *output_name; - char name[32]; - - koutput = drmModeGetConnector (pSecMode->fd, - pSecMode->mode_res->connectors[num]); - if (!koutput) - return; - - kencoder = drmModeGetEncoder (pSecMode->fd, koutput->encoders[0]); - if (!kencoder) - { - drmModeFreeConnector (koutput); - return; - } - - if (koutput->connector_type < ARRAY_SIZE (output_names)) - output_name = output_names[koutput->connector_type]; - else - output_name = "UNKNOWN"; - snprintf (name, 32, "%s%d", output_name, koutput->connector_type_id); - - pOutput = xf86OutputCreate (pScrn, &sec_output_funcs, name); - if (!pOutput) - { - drmModeFreeEncoder (kencoder); - drmModeFreeConnector (koutput); - return; - } - - pOutputPriv = calloc (sizeof (SECOutputPrivRec), 1); - if (!pOutputPriv) - { - xf86OutputDestroy (pOutput); - drmModeFreeConnector (koutput); - drmModeFreeEncoder (kencoder); - return; - } - - pOutputPriv->output_id = pSecMode->mode_res->connectors[num]; - pOutputPriv->mode_output = koutput; - pOutputPriv->mode_encoder = kencoder; - pOutputPriv->pSecMode = pSecMode; - - pOutput->mm_width = koutput->mmWidth; - pOutput->mm_height = koutput->mmHeight; - - pOutput->subpixel_order = subpixel_conv_table[koutput->subpixel]; - pOutput->driver_private = pOutputPriv; - - pOutput->possible_crtcs = kencoder->possible_crtcs; - pOutput->possible_clones = kencoder->possible_clones; - pOutput->interlaceAllowed = TRUE; - - pOutputPriv->pOutput = pOutput; - /* TODO : soolim : management crtc privates */ - xorg_list_add(&pOutputPriv->link, &pSecMode->outputs); -} - -int -secOutputDpmsStatus(xf86OutputPtr pOutput) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - return pOutputPriv->dpms_mode; -} - -void -secOutputDpmsSet(xf86OutputPtr pOutput, int mode) -{ - SECOutputDpms(pOutput, mode); -} - -SECOutputPrivPtr -secOutputGetPrivateForConnType (ScrnInfoPtr pScrn, int connect_type) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - int i; - - for (i = 0; i < pSecMode->mode_res->count_connectors; i++) - { - SECOutputPrivPtr pCur = NULL, pNext = NULL; - - xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->outputs, link) - { - drmModeConnectorPtr koutput = pCur->mode_output; - - if (koutput && koutput->connector_type == connect_type) - return pCur; - } - } - - XDBG_ERROR (MSEC, "no output for connect_type(%d) \n", connect_type); - - return NULL; -} diff --git a/src/crtcconfig/sec_plane.c b/src/crtcconfig/sec_plane.c deleted file mode 100644 index 41384a6..0000000 --- a/src/crtcconfig/sec_plane.c +++ /dev/null @@ -1,1334 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <sys/ioctl.h> -#include <stdint.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <poll.h> - -#include <xorgVersion.h> -#include <tbm_bufmgr.h> -#include <xf86Crtc.h> -#include <xf86DDC.h> -#include <xf86cmap.h> -#include <list.h> -#include <X11/Xatom.h> -#include <X11/extensions/dpmsconst.h> -#include <sec.h> -#include <exynos_drm.h> - -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_util.h" -#include "sec_video_fourcc.h" -#include "sec_plane.h" -#include "fimg2d.h" - -/* HW restriction */ -#define MIN_WIDTH 32 - -enum -{ - PLANE_FB_TYPE_NONE, - PLANE_FB_TYPE_DEFAULT, - PLANE_FB_TYPE_BO, - PLANE_FB_TYPE_MAX -}; - -typedef struct _SECPlaneAccess -{ - unsigned int fb_id; - - tbm_bo bo; - - int width; - int height; - - xRectangle src; - xRectangle dst; -} SECPlaneAccess; - -/* This is structure to manage a added buffer. */ -typedef struct _SECPlaneFb -{ - unsigned int id; - - int type; - union - { - /* for framebuffer */ - tbm_bo bo; - SECVideoBuf *vbuf; - } buffer; - - int width; - int height; - - Bool buffer_gone; - - struct xorg_list link; -} SECPlaneFb; - -typedef struct _SECPlaneTable -{ - SECPlanePrivPtr pPlanePriv; - int plane_id; - - /* buffers which this plane has */ - struct xorg_list fbs; - SECPlaneFb *cur_fb; - - /* visibilitiy information */ - Bool visible; - int crtc_id; - int zpos; - xRectangle src; - xRectangle dst; - int conn_type; - - Bool onoff; - Bool in_use; - Bool freeze_update; - - /* accessibility */ - SECPlaneAccess *access; -} SECPlaneTable; - -/* table of planes which system has entirely */ -static SECPlaneTable *plane_table; -static int plane_table_size; - -static SECPlaneTable* _secPlaneTableFind (int plane_id); -static SECPlaneFb* _secPlaneTableFindBuffer (SECPlaneTable *table, int fb_id, - tbm_bo bo, SECVideoBuf *vbuf); -static Bool _secPlaneHideInternal (SECPlaneTable *table); - -static void -_secPlaneFreeVbuf (SECVideoBuf *vbuf, void *data) -{ - int plane_id = (int)data; - SECPlaneTable *table; - SECPlaneFb *fb; - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_IF_FAIL (table != NULL); - - fb = _secPlaneTableFindBuffer (table, vbuf->fb_id, NULL, NULL); - XDBG_RETURN_IF_FAIL (fb != NULL); - - fb->buffer_gone = TRUE; - secPlaneRemoveBuffer (plane_id, vbuf->fb_id); -} - -static SECPlaneTable* -_secPlaneTableFindPos (int crtc_id, int zpos) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, NULL); - - for (i = 0; i < plane_table_size; i++) - if (plane_table[i].crtc_id == crtc_id && plane_table[i].zpos == zpos) - return &plane_table[i]; - - return NULL; -} - -static SECPlaneTable* -_secPlaneTableFind (int plane_id) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (plane_id > 0, NULL); - - for (i = 0; i < plane_table_size; i++) - if (plane_table[i].plane_id == plane_id) - return &plane_table[i]; - - XDBG_TRACE (MPLN, "plane(%d) not found. \n", plane_id); - - return NULL; -} - -static SECPlaneTable* -_secPlaneTableFindEmpty (void) -{ - int i; - - for (i = 0; i < plane_table_size; i++) - if (!plane_table[i].in_use) - return &plane_table[i]; - - return NULL; -} - -static SECPlaneFb* -_secPlaneTableFindBuffer (SECPlaneTable *table, - int fb_id, - tbm_bo bo, - SECVideoBuf *vbuf) -{ - SECPlaneFb *fb = NULL, *fb_next = NULL; - - xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link) - { - if (fb_id > 0) - { - if (fb->id == fb_id) - return fb; - } - else if (bo) - { - if (fb->type == PLANE_FB_TYPE_BO && fb->buffer.bo == bo) - return fb; - } - else if (vbuf) - { - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL); - - if (fb->type == PLANE_FB_TYPE_DEFAULT) - if (fb->buffer.vbuf == vbuf && fb->buffer.vbuf->stamp == vbuf->stamp) - return fb; - } - } - - return NULL; -} - -static void -_secPlaneTableFreeBuffer (SECPlaneTable *table, SECPlaneFb *fb) -{ - if (table->cur_fb == fb) - return; - - if (fb->type == PLANE_FB_TYPE_BO) - { - if (fb->buffer.bo) - tbm_bo_unref (fb->buffer.bo); - } - else - { - if (!fb->buffer_gone && fb->buffer.vbuf) - secUtilRemoveFreeVideoBufferFunc (fb->buffer.vbuf, _secPlaneFreeVbuf, - (void*)table->plane_id); - } - - xorg_list_del (&fb->link); - - free (fb); -} - -static Bool -_secPlaneTableEnsure (ScrnInfoPtr pScrn, int count_planes) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (count_planes > 0, FALSE); - - if (plane_table) - { - if (plane_table_size != count_planes) - XDBG_WARNING (MPLN, "%d != %d, need to re-create! \n", - plane_table_size, count_planes); - return TRUE; - } - - plane_table = calloc (sizeof (SECPlaneTable), count_planes); - XDBG_RETURN_VAL_IF_FAIL (plane_table != NULL, FALSE); - - plane_table_size = count_planes; - - for (i = 0; i < plane_table_size; i++) - { - SECPlaneTable *table = &plane_table[i]; - table->plane_id = -1; - table->onoff = TRUE; - } - - return TRUE; -} - -static void -_secPlaneExecAccessibility (tbm_bo src_bo, int sw, int sh, xRectangle *sr, - tbm_bo dst_bo, int dw, int dh, xRectangle *dr, - Bool bNegative) -{ - G2dImage *srcImg = NULL, *dstImg = NULL; - tbm_bo_handle src_bo_handle = {0,}; - tbm_bo_handle dst_bo_handle = {0,}; - G2dColorKeyMode mode; - - mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; - src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (src_bo_handle.s32 > 0, access_done); - - dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); - XDBG_GOTO_IF_FAIL (dst_bo_handle.s32 > 0, access_done); - - srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sw * 4); - XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done); - - dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dw * 4); - XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done); - - util_g2d_copy_with_scale (srcImg, dstImg, - (int)sr->x, (int)sr->y, sr->width, sr->height, - (int)dr->x, (int)dr->y, dr->width, dr->height, - (int)bNegative); - g2d_exec (); - -access_done: - if (src_bo_handle.s32) - tbm_bo_unmap (src_bo); - if (dst_bo_handle.s32) - tbm_bo_unmap (dst_bo); - if (srcImg) - g2d_image_free (srcImg); - if (dstImg) - g2d_image_free (dstImg); -} - -static Bool -_check_hw_restriction (ScrnInfoPtr pScrn, int crtc_id, int buf_w, - int src_x, int src_w, int dst_x, int dst_w, - int *new_src_x, int *new_src_w, - int *new_dst_x, int *new_dst_w) -{ - SECOutputPrivPtr pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_LVDS); - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - int max = pSecMode->main_lcd_mode.hdisplay; - int start, end, diff; - Bool virtual_screen; - - XDBG_RETURN_VAL_IF_FAIL (pOutputPriv != NULL, FALSE); - - if (pOutputPriv->mode_encoder->crtc_id != crtc_id) - return TRUE; - - if (buf_w < MIN_WIDTH || buf_w % 2) - { - XDBG_TRACE (MPLN, "hide: buf_w(%d) not 2's multiple or less than %d\n", - buf_w, MIN_WIDTH); - return FALSE; - } - - if (src_x > dst_x || ((dst_x - src_x) + buf_w) > max) - virtual_screen = TRUE; - else - virtual_screen = FALSE; - - start = (dst_x < 0) ? 0 : dst_x; - end = ((dst_x + dst_w) > max) ? max : (dst_x + dst_w); - - /* check window minimun width */ - if ((end - start) < MIN_WIDTH) - { - XDBG_TRACE (MPLN, "hide: %d than min size: buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n", - end-start, buf_w, src_x, src_w, dst_x, dst_w, - virtual_screen, start, end); - return FALSE; - } - - XDBG_DEBUG (MPLN, "buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n", - buf_w, src_x, src_w, dst_x, dst_w, virtual_screen, start, end); - - if (!virtual_screen) - { - /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */ - if ((end - start) % 2) - end--; - } - else - { - /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */ - if (end % 2) - end--; - } - - *new_dst_x = start; - *new_dst_w = end - start; - *new_src_w = *new_dst_w; - diff = start - dst_x; - *new_src_x += diff; - - XDBG_RETURN_VAL_IF_FAIL (*new_src_w > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (*new_dst_w > 0, FALSE); - - if (src_x != *new_src_x || src_w != *new_src_w || - dst_x != *new_dst_x || dst_w != *new_dst_w) - XDBG_TRACE (MPLN, " => buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n", - buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start, end); - - return TRUE; -} - -static Bool -_secPlaneShowInternal (SECPlaneTable *table, - SECPlaneFb *old_fb, SECPlaneFb *new_fb, - xRectangle *new_src, xRectangle *new_dst, int new_zpos, - Bool need_set_plane) -{ - SECPtr pSec; - SECModePtr pSecMode; - xRectangle old_src = table->src; - xRectangle old_dst = table->dst; - int old_zpos = table->zpos; - Bool change_zpos = FALSE; - tbm_bo_handle bo_handle; - - pSec = SECPTR (table->pPlanePriv->pScrn); - pSecMode = table->pPlanePriv->pSecMode; - - if (pSec->isLcdOff) - { - XDBG_TRACE (MPLN, "lcd off, can't show : plane(%d) crtc(%d) pos(%d). \n", - table->plane_id, table->crtc_id, new_zpos); - return FALSE; - } - - if (!table->onoff) - { - XDBG_TRACE (MPLN, "plane off, can't show : plane(%d) crtc(%d) pos(%d). \n", - table->plane_id, table->crtc_id, new_zpos); - return FALSE; - } - - /* should set zpos before doing drmModeSetPlane */ - if (new_zpos != old_zpos) - { - if (!secUtilSetDrmProperty (pSecMode, table->plane_id, DRM_MODE_OBJECT_PLANE, - "zpos", new_zpos)) - return FALSE; - - table->zpos = new_zpos; - change_zpos = TRUE; - - XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) zpos(%d)\n", - table->plane_id, table->crtc_id, table->zpos); - } - - if (!table->visible || need_set_plane || - change_zpos || - (!old_fb || (old_fb != new_fb)) || - (memcmp (&old_src, new_src, sizeof (xRectangle))) || - (memcmp (&old_dst, new_dst, sizeof (xRectangle)))) - { - xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (table->pPlanePriv->pScrn); - SECCrtcPrivPtr pCrtcPriv = NULL; - int c; - - for (c = 0; c < pCrtcConfig->num_crtc; c++) - { - xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c]; - SECCrtcPrivPtr pTemp = pCrtc->driver_private; - if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == table->crtc_id) - { - pCrtcPriv = pTemp; - break; - } - } - - XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE); - - XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) fb(%d) (%d,%d %dx%d) => (%d,%d %dx%d) [%d,%d,%c%c%c%c]\n", - table->plane_id, table->crtc_id, new_fb->id, - new_src->x, new_src->y, new_src->width, new_src->height, - new_dst->x, new_dst->y, new_dst->width, new_dst->height, - pCrtcPriv->bAccessibility, new_fb->type, - FOURCC_STR (new_fb->buffer.vbuf->id)); - - if (!pCrtcPriv->bAccessibility || - (new_fb->type == PLANE_FB_TYPE_DEFAULT && new_fb->buffer.vbuf->id != FOURCC_RGB32)) - { - int aligned_src_x = new_src->x; - int aligned_src_w = new_src->width; - int aligned_dst_x = new_dst->x; - int aligned_dst_w = new_dst->width; - - if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id, - table->cur_fb->width, - new_src->x, new_src->width, - new_dst->x, new_dst->width, - &aligned_src_x, &aligned_src_w, - &aligned_dst_x, &aligned_dst_w)) - { - XDBG_TRACE (MPLN, "out of range: plane(%d) crtc(%d) pos(%d) crtc(%d,%d %dx%d). \n", - table->plane_id, table->crtc_id, new_zpos, - aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height); - - _secPlaneHideInternal (table); - - return TRUE; - } - - /* Source values are 16.16 fixed point */ - uint32_t fixed_x = ((unsigned int)aligned_src_x) << 16; - uint32_t fixed_y = ((unsigned int)new_src->y) << 16; - uint32_t fixed_w = ((unsigned int)aligned_src_w) << 16; - uint32_t fixed_h = ((unsigned int)new_src->height) << 16; - - if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id, - new_fb->id, 0, - aligned_dst_x, new_dst->y, - aligned_dst_w, new_dst->height, - fixed_x, fixed_y, - fixed_w, fixed_h)) - { - XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", - table->plane_id, table->crtc_id, table->zpos, - new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id), - new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height, - aligned_src_x, new_src->y, aligned_src_w, new_src->height, - aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height); - - return FALSE; - } - - if (!table->visible) - { - XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", - table->plane_id, table->crtc_id, table->zpos, - new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id), - new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height, - aligned_src_x, new_src->y, aligned_src_w, new_src->height, - aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height); - table->visible = TRUE; - } - } - else - { - SECPlaneAccess *access; - xRectangle fb_src = {0,}; - tbm_bo src_bo; - int old_w = 0, old_h = 0; - - if (!table->access) - { - table->access = calloc (1, sizeof (SECPlaneAccess)); - XDBG_RETURN_VAL_IF_FAIL (table->access != NULL, FALSE); - } - else - { - old_w = table->access->width; - old_h = table->access->height; - } - - access = table->access; - - if (pCrtcPriv->bScale) - { - float h_ratio = 0.0, v_ratio = 0.0; - xRectangle crop; - - h_ratio = (float)pCrtcPriv->kmode.hdisplay / pCrtcPriv->sw; - v_ratio = (float)pCrtcPriv->kmode.vdisplay / pCrtcPriv->sh; - - fb_src.x = new_src->x; - fb_src.y = new_src->y; - fb_src.width = new_src->width; - fb_src.height = new_src->height; - - CLEAR (crop); - crop.x = pCrtcPriv->sx; - crop.y = pCrtcPriv->sy; - crop.width = pCrtcPriv->sw; - crop.height = pCrtcPriv->sh; - - crop.x -= new_dst->x; - crop.y -= new_dst->y; - crop.x += new_src->x; - crop.y += new_src->y; - secUtilRectIntersect (&fb_src, &fb_src, &crop); - - access->dst = *new_dst; - - access->dst.x = new_dst->x; - access->dst.y = new_dst->y; - access->dst.width = new_dst->width; - access->dst.height = new_dst->height; - - CLEAR (crop); - crop.x = pCrtcPriv->sx; - crop.y = pCrtcPriv->sy; - crop.width = pCrtcPriv->sw; - crop.height = pCrtcPriv->sh; - secUtilRectIntersect (&access->dst, &access->dst, &crop); - - access->dst.x -= pCrtcPriv->sx; - access->dst.y -= pCrtcPriv->sy; - - access->dst.x *= h_ratio; - access->dst.y *= v_ratio; - access->dst.width *= h_ratio; - access->dst.height *= v_ratio; - - access->width = pCrtcPriv->kmode.hdisplay; - access->height = pCrtcPriv->kmode.vdisplay; - - access->src.x = 0; - access->src.y = 0; - access->src.width = access->dst.width; - access->src.height = access->dst.height; - } - else - { - fb_src.x = new_src->x; - fb_src.y = new_src->y; - fb_src.width = new_src->width; - fb_src.height = new_src->height; - - /* hw restriction: 8 bytes */ - new_dst->width &= ~1; - - access->dst.x = new_dst->x; - access->dst.y = new_dst->y; - access->dst.width = new_dst->width; - access->dst.height = new_dst->height; - - access->width = access->dst.width; - access->height = access->dst.height; - - access->src.x = 0; - access->src.y = 0; - access->src.width = access->dst.width; - access->src.height = access->dst.height; - } - - XDBG_DEBUG (MPLN, "access : accessibility_status(%d) scale(%d) bo(%p) fb(%d) (%d,%d %dx%d) (%dx%d) (%d,%d %dx%d) (%d,%d %dx%d).\n", - pCrtcPriv->accessibility_status, pCrtcPriv->bScale, - access->bo, access->fb_id, - fb_src.x, fb_src.y, fb_src.width, fb_src.height, - access->width, access->height, - access->src.x, access->src.y, access->src.width, access->src.height, - access->dst.x, access->dst.y, access->dst.width, access->dst.height); - - if (!fb_src.width || !fb_src.height || - !access->width || !access->height || - !access->dst.width || !access->dst.height) - { - _secPlaneHideInternal (table); - - return TRUE; - } - - if (access->bo) - { - if (old_w != access->width || old_h != access->height) - { - if (table->access->fb_id) - { - drmModeRmFB (pSecMode->fd, table->access->fb_id); - table->access->fb_id = 0; - } - - tbm_bo_unref (table->access->bo); - table->access->bo = NULL; - } - } - - if (!access->bo) - { - access->bo = tbm_bo_alloc (pSec->tbm_bufmgr, - access->width * access->height * 4, - TBM_BO_NONCACHABLE); - XDBG_RETURN_VAL_IF_FAIL (access->bo != NULL, FALSE); - - bo_handle = tbm_bo_get_handle (access->bo, TBM_DEVICE_DEFAULT); - if (drmModeAddFB (pSecMode->fd, access->width, access->height, - table->pPlanePriv->pScrn->depth, - table->pPlanePriv->pScrn->bitsPerPixel, - access->width * 4, - bo_handle.u32, - &access->fb_id)) - { - XDBG_ERRNO (MPLN, "drmModeAddFB failed. plane(%d)\n", table->plane_id); - return FALSE; - } - - XDBG_RETURN_VAL_IF_FAIL (access->fb_id > 0, FALSE); - } - - if (new_fb->type == PLANE_FB_TYPE_DEFAULT) - src_bo = new_fb->buffer.vbuf->bo[0]; - else - src_bo = new_fb->buffer.bo; - XDBG_RETURN_VAL_IF_FAIL (src_bo != NULL, FALSE); - - _secPlaneExecAccessibility (src_bo, new_fb->width, new_fb->height, &fb_src, - access->bo, access->width, access->height, &access->src, - pCrtcPriv->accessibility_status); - - int aligned_src_x = access->src.x; - int aligned_src_w = access->src.width; - int aligned_dst_x = access->dst.x; - int aligned_dst_w = access->dst.width; - - if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id, - access->width, - access->src.x, access->src.width, - access->dst.x, access->dst.width, - &aligned_src_x, &aligned_src_w, - &aligned_dst_x, &aligned_dst_w)) - { - XDBG_TRACE (MPLN, "out of range: plane(%d) crtc(%d) pos(%d) crtc(%d,%d %dx%d). \n", - table->plane_id, table->crtc_id, new_zpos, - aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height); - - _secPlaneHideInternal (table); - - return TRUE; - } - - /* Source values are 16.16 fixed point */ - uint32_t fixed_x = ((unsigned int)aligned_src_x) << 16; - uint32_t fixed_y = ((unsigned int)access->src.y) << 16; - uint32_t fixed_w = ((unsigned int)aligned_src_w) << 16; - uint32_t fixed_h = ((unsigned int)access->src.height) << 16; - - if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id, - access->fb_id, 0, - aligned_dst_x, access->dst.y, - aligned_dst_w, access->dst.height, - fixed_x, fixed_y, - fixed_w, fixed_h)) - { - XDBG_ERRNO (MPLN, "drmModeSetPlane failed. \n"); - - return FALSE; - } - - if (!table->visible) - { - XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: access_fb(%d,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n", - table->plane_id, table->crtc_id, table->zpos, - access->fb_id, access->width, access->height, - aligned_src_x, access->src.y, aligned_src_w, access->src.height, - aligned_dst_x, access->dst.y, aligned_dst_w, access->dst.height); - - table->visible = TRUE; - } - } - - memcpy (&table->src, new_src, sizeof (xRectangle)); - memcpy (&table->dst, new_dst, sizeof (xRectangle)); - } - - return TRUE; -} - -static Bool -_secPlaneHideInternal (SECPlaneTable *table) -{ - SECPtr pSec; - SECModePtr pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - if (!table->visible) - return TRUE; - - XDBG_RETURN_VAL_IF_FAIL (table->crtc_id > 0, FALSE); - - pSec = SECPTR (table->pPlanePriv->pScrn); - pSecMode = table->pPlanePriv->pSecMode; - - if (!pSec->isLcdOff && table->onoff) - { - if (drmModeSetPlane (pSecMode->fd, - table->plane_id, - table->crtc_id, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0)) - { - XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) zpos(%d) fb(%d)\n", - table->plane_id, table->crtc_id, table->zpos, table->cur_fb->id); - - return FALSE; - } - } - - if (table->visible) - { - XDBG_SECURE (MPLN, "plane(%d) crtc(%d) zpos(%d) off. lcd(%s) onoff(%d)\n", - table->plane_id, table->crtc_id, table->zpos, - (pSec->isLcdOff)?"off":"on", table->onoff); - table->visible = FALSE; - } - - XDBG_TRACE (MPLN, "plane(%d) fb(%d) removed from crtc(%d) zpos(%d). LCD(%s) ONOFF(%s).\n", - table->plane_id, table->cur_fb->id, table->crtc_id, table->zpos, - (pSec->isLcdOff)?"OFF":"ON", (table->onoff)?"ON":"OFF"); - - return TRUE; - -} - -void -secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num) -{ - SECPlanePrivPtr pPlanePriv; - - XDBG_RETURN_IF_FAIL (pScrn != NULL); - XDBG_RETURN_IF_FAIL (pSecMode != NULL); - XDBG_RETURN_IF_FAIL (pSecMode->plane_res != NULL); - XDBG_RETURN_IF_FAIL (pSecMode->plane_res->count_planes > 0); - - if (!_secPlaneTableEnsure (pScrn, pSecMode->plane_res->count_planes)) - return; - - pPlanePriv = calloc (sizeof (SECPlanePrivRec), 1); - XDBG_RETURN_IF_FAIL (pPlanePriv != NULL); - - pPlanePriv->mode_plane = drmModeGetPlane (pSecMode->fd, - pSecMode->plane_res->planes[num]); - if (!pPlanePriv->mode_plane) - { - XDBG_ERRNO (MPLN, "drmModeGetPlane failed. plane(%d)\n", - pSecMode->plane_res->planes[num]); - - free (pPlanePriv); - return; - } - - pPlanePriv->pScrn = pScrn; - pPlanePriv->pSecMode = pSecMode; - pPlanePriv->plane_id = pPlanePriv->mode_plane->plane_id; - - plane_table[num].plane_id = pPlanePriv->plane_id; - plane_table[num].pPlanePriv = pPlanePriv; - xorg_list_init (&plane_table[num].fbs); - - xorg_list_add(&pPlanePriv->link, &pSecMode->planes); -} - -void -secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv) -{ - int i; - - XDBG_RETURN_IF_FAIL (pScrn != NULL); - XDBG_RETURN_IF_FAIL (pPlanePriv != NULL); - - secPlaneFreeId (pPlanePriv->plane_id); - drmModeFreePlane (pPlanePriv->mode_plane); - xorg_list_del (&pPlanePriv->link); - - for (i = 0; i < plane_table_size; i++) - if (plane_table[i].plane_id == pPlanePriv->plane_id) - { - plane_table[i].plane_id = -1; - break; - } - - free (pPlanePriv); - - if (plane_table) - { - for (i = 0; i < plane_table_size; i++) - if (plane_table[i].plane_id != -1) - return; - - free (plane_table); - plane_table = NULL; - plane_table_size = 0; - XDBG_TRACE (MPLN, "plane_table destroyed. %d\n", plane_table_size); - } -} - -void -secPlaneShowAll (int crtc_id) -{ - int i; - - XDBG_TRACE (MPLN, "crtc(%d) \n", crtc_id); - - for (i = 0; i < plane_table_size; i++) - { - SECPlaneTable *table = &plane_table[i]; - - if (!table || !table->in_use || !table->visible || !table->onoff) - continue; - - if (table->crtc_id != crtc_id) - continue; - - if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb, - &table->src, &table->dst, table->zpos, TRUE)) - - { - XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n"); - } - - XDBG_TRACE (MPLN, "plane(%d) crtc(%d) zpos(%d) on.\n", - table->plane_id, table->crtc_id, table->zpos); - } -} - -int -secPlaneGetID (void) -{ - SECPlaneTable *table = _secPlaneTableFindEmpty (); - - if (!table) - { - XDBG_ERROR (MPLN, "No avaliable plane ID. %d\n", -1); - return -1; - } - - table->in_use = TRUE; - table->onoff = TRUE; - - XDBG_TRACE (MPLN, "plane(%d). \n", table->plane_id); - - return table->plane_id; -} - -void -secPlaneFreeId (int plane_id) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - SECPlaneFb *fb = NULL, *fb_next = NULL; - - XDBG_RETURN_IF_FAIL (table != NULL); - - secPlaneHide (table->plane_id); - - table->visible = FALSE; - table->crtc_id = 0; - - table->zpos = 0; - memset (&table->src, 0x00, sizeof (xRectangle)); - memset (&table->dst, 0x00, sizeof (xRectangle)); - - table->cur_fb = NULL; - xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link) - { - _secPlaneTableFreeBuffer (table, fb); - } - - if (table->access) - { - if (table->access->fb_id) - { - SECModePtr pSecMode = table->pPlanePriv->pSecMode; - if (pSecMode) - drmModeRmFB (pSecMode->fd, table->access->fb_id); - } - - if (table->access->bo) - tbm_bo_unref (table->access->bo); - - free (table->access); - table->access = NULL; - } - - table->in_use = FALSE; - table->onoff = TRUE; - - XDBG_TRACE (MPLN, "plane(%d).\n", table->plane_id); -} - -Bool -secPlaneTrun (int plane_id, Bool onoff, Bool user) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - SECPtr pSec; - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - pSec = SECPTR (table->pPlanePriv->pScrn); - - if (pSec->isLcdOff) - return TRUE; - - onoff = (onoff > 0) ? TRUE : FALSE; - - if (table->onoff == onoff) - return TRUE; - - if (onoff) - { - table->onoff = onoff; - - if (!table->visible) - { - if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb, - &table->src, &table->dst, table->zpos, TRUE)) - - { - XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n"); - } - - XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg", - plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF"); - } - } - else - { - if (table->visible) - { - if (!_secPlaneHideInternal (table)) - - { - XDBG_WARNING (MPLN, "_secPlaneHideInternal failed. \n"); - } - - XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg", - plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF"); - } - - table->onoff = onoff; - } - - return TRUE; -} - -Bool -secPlaneTrunStatus (int plane_id) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - return table->onoff; -} - -void -secPlaneFreezeUpdate (int plane_id, Bool enable) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - - XDBG_RETURN_IF_FAIL (table != NULL); - - table->freeze_update = enable; -} - -Bool -secPlaneRemoveBuffer (int plane_id, int fb_id) -{ - SECPlaneTable *table; - SECPlaneFb *fb; - - XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE); - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE); - - _secPlaneTableFreeBuffer (table, fb); - - XDBG_TRACE (MPLN, "plane(%d) fb(%d). \n", plane_id, fb_id); - - return TRUE; -} - -int -secPlaneAddBo (int plane_id, tbm_bo bo) -{ - SECPlaneTable *table; - SECPlaneFb *fb; - int fb_id = 0; - SECFbBoDataPtr bo_data = NULL; - int width, height; - - XDBG_RETURN_VAL_IF_FAIL (bo != NULL, 0); - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0); - - fb = _secPlaneTableFindBuffer (table, 0, bo, NULL); - XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0); - - tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void**)&bo_data); - XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, 0); - - fb_id = bo_data->fb_id; - width = bo_data->pos.x2 - bo_data->pos.x1; - height = bo_data->pos.y2 - bo_data->pos.y1; - - XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (width > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (height > 0, 0); - - fb = calloc (1, sizeof (SECPlaneFb)); - XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0); - - xorg_list_add(&fb->link, &table->fbs); - - fb->type = PLANE_FB_TYPE_BO; - fb->id = fb_id; - fb->width = width; - fb->height = height; - - fb->buffer.bo = tbm_bo_ref (bo); - - XDBG_TRACE (MPLN, "plane(%d) bo(%d,%dx%d)\n", plane_id, - fb_id, fb->width, fb->height); - - return fb->id; -} - -int -secPlaneAddBuffer (int plane_id, SECVideoBuf *vbuf) -{ - SECPlaneTable *table; - SECPlaneFb *fb; - - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0); - XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (vbuf->width > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (vbuf->height > 0, 0); - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0); - - fb = _secPlaneTableFindBuffer (table, 0, NULL, vbuf); - XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0); - - fb = calloc (1, sizeof (SECPlaneFb)); - XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0); - - xorg_list_add(&fb->link, &table->fbs); - - fb->type = PLANE_FB_TYPE_DEFAULT; - fb->id = vbuf->fb_id; - fb->width = vbuf->width; - fb->height = vbuf->height; - - fb->buffer.vbuf = vbuf; - - secUtilAddFreeVideoBufferFunc (vbuf, _secPlaneFreeVbuf, (void*)plane_id); - - XDBG_TRACE (MPLN, "plane(%d) vbuf(%ld,%d,%dx%d)\n", plane_id, - vbuf->stamp, vbuf->fb_id, vbuf->width, vbuf->height); - - return fb->id; -} - -int -secPlaneGetBuffer (int plane_id, tbm_bo bo, SECVideoBuf *vbuf) -{ - SECPlaneTable *table; - SECPlaneFb *fb; - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0); - - fb = _secPlaneTableFindBuffer (table, 0, bo, vbuf); - if (!fb) - return 0; - - return fb->id; -} - -void -secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height) -{ - SECPlaneTable *table; - SECPlaneFb *fb; - - table = _secPlaneTableFind (plane_id); - XDBG_RETURN_IF_FAIL (table != NULL); - - fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL); - XDBG_RETURN_IF_FAIL (fb != NULL); - - if (width) - *width = fb->width; - - if (height) - *height = fb->height; -} - -Bool -secPlaneAttach (int plane_id, int fb_id) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - SECPlaneFb *fb; - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE); - - fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE); - - table->cur_fb = fb; - - XDBG_DEBUG (MPLN, "plane(%d) fb(%d)\n", plane_id, fb_id); - - return TRUE; -} - -Bool -secPlaneIsVisible (int plane_id) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - return table->visible; -} - -Bool -secPlaneShow (int plane_id, int crtc_id, - int src_x, int src_y, int src_w, int src_h, - int dst_x, int dst_y, int dst_w, int dst_h, - int zpos, Bool need_update) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - SECPlaneTable *temp; - xRectangle src = {src_x, src_y, src_w, src_h}; - xRectangle dst = {dst_x, dst_y, dst_w, dst_h}; - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (zpos >= 0, FALSE); - - temp = _secPlaneTableFindPos (crtc_id, zpos); - - if (temp && temp->plane_id != plane_id) - { - XDBG_ERROR (MPLN, "can't change zpos. plane(%d) is at zpos(%d) crtc(%d) \n", - temp->plane_id, temp->zpos, crtc_id); - return FALSE; - } - - if (!table->visible) - table->crtc_id = crtc_id; - else if (table->crtc_id != crtc_id) - { - XDBG_ERROR (MPLN, "can't change crtc. plane(%d) is on crtc(%d) \n", - table->plane_id, table->zpos); - return FALSE; - } - - if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb, - &src, &dst, zpos, need_update)) - { - return FALSE; - } - - return TRUE; -} - -Bool -secPlaneHide (int plane_id) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - - if (!table->visible) - return TRUE; - - XDBG_TRACE (MPLN, "plane(%d) crtc(%d)\n", table->plane_id, table->crtc_id); - - _secPlaneHideInternal (table); - - return TRUE; -} - -Bool -secPlaneMove (int plane_id, int x, int y) -{ - SECPlaneTable *table = _secPlaneTableFind (plane_id); - xRectangle dst; - - XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE); - - dst.x = x; - dst.y = y; - dst.width = table->dst.width; - dst.height = table->dst.height; - - if (table->visible && !table->freeze_update) - if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb, - &table->src, &dst, table->zpos, FALSE)) - { - return FALSE; - } - - XDBG_TRACE (MPLN, "plane(%d) moved to (%d,%d)\n", table->plane_id, x, y); - - return TRUE; -} - -char* -secPlaneDump (char *reply, int *len) -{ - Bool in_use = FALSE; - int i; - - for (i = 0; i < plane_table_size; i++) - if (plane_table[i].in_use) - { - in_use = TRUE; - break; - } - - if (!in_use) - return reply; - - XDBG_REPLY ("=================================================\n"); - XDBG_REPLY ("plane\tcrtc\tpos\tvisible\tonoff\tfb(w,h)\tsrc\t\tdst\n"); - - for (i = 0; i < plane_table_size; i++) - { - if (plane_table[i].in_use) - XDBG_REPLY ("%d\t%d\t%d\t%d\t%d\t%d(%dx%d)\t%d,%d %dx%d\t%d,%d %dx%d\n", - plane_table[i].plane_id, - plane_table[i].crtc_id, plane_table[i].zpos, - plane_table[i].visible, - plane_table[i].onoff, - (plane_table[i].cur_fb)?plane_table[i].cur_fb->id:0, - (plane_table[i].cur_fb)?plane_table[i].cur_fb->width:0, - (plane_table[i].cur_fb)?plane_table[i].cur_fb->height:0, - plane_table[i].src.x, plane_table[i].src.y, - plane_table[i].src.width, plane_table[i].src.height, - plane_table[i].dst.x, plane_table[i].dst.y, - plane_table[i].dst.width, plane_table[i].dst.height); - } - - XDBG_REPLY ("=================================================\n"); - - return reply; -} diff --git a/src/crtcconfig/sec_prop.c b/src/crtcconfig/sec_prop.c deleted file mode 100755 index 9cf1904..0000000 --- a/src/crtcconfig/sec_prop.c +++ /dev/null @@ -1,713 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <stdint.h> -#include <string.h> - -#include "sec.h" -#include "sec_display.h" -#include "sec_output.h" -#include "sec_crtc.h" -#include "sec_prop.h" -#include "sec_util.h" -#include <exynos_drm.h> -#include <sys/ioctl.h> - -#define STR_XRR_DISPLAY_MODE_PROPERTY "XRR_PROPERTY_DISPLAY_MODE" -#define STR_XRR_LVDS_FUNCTION "XRR_PROPERTY_LVDS_FUNCTION" -#define STR_XRR_FB_VISIBLE_PROPERTY "XRR_PROPERTY_FB_VISIBLE" -#define STR_XRR_VIDEO_OFFSET_PROPERTY "XRR_PROPERTY_VIDEO_OFFSET" -#define STR_XRR_PROPERTY_SCREEN_ROTATE "XRR_PROPERTY_SCREEN_ROTATE" - -#define PROP_VERIFY_RR_MODE(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RRModeType, serverClient, a);\ - if (rc != Success) {\ - serverClient->errorValue = id;\ - return 0;\ - }\ - } - - -#define FLAG_BITS (RR_HSyncPositive | \ - RR_HSyncNegative | \ - RR_VSyncPositive | \ - RR_VSyncNegative | \ - RR_Interlace | \ - RR_DoubleScan | \ - RR_CSync | \ - RR_CSyncPositive | \ - RR_CSyncNegative | \ - RR_HSkewPresent | \ - RR_BCast | \ - RR_PixelMultiplex | \ - RR_DoubleClock | \ - RR_ClockDivideBy2) - -static Bool g_display_mode_prop_init = FALSE; -static Bool g_lvds_func_prop_init = FALSE; -static Bool g_fb_visible_prop_init = FALSE; -static Bool g_video_offset_prop_init = FALSE; -static Bool g_screen_rotate_prop_init = FALSE; - -static Atom xrr_property_display_mode_atom; -static Atom xrr_property_lvds_func_atom; -static Atom xrr_property_fb_visible_atom; -static Atom xrr_property_video_offset_atom; -static Atom xrr_property_screen_rotate_atom; - -typedef enum -{ - XRR_OUTPUT_DISPLAY_MODE_NULL, - XRR_OUTPUT_DISPLAY_MODE_WB_CLONE, - XRR_OUTPUT_DISPLAY_MODE_VIDEO_ONLY, -} XRROutputPropDisplayMode; - -typedef enum -{ - XRR_OUTPUT_LVDS_FUNC_NULL, - XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL, - XRR_OUTPUT_LVDS_FUNC_HIBERNATION, - XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY, -} XRROutputPropLvdsFunc; - -/* - * Convert a RandR mode to a DisplayMode - */ -static void -_RRModeConvertToDisplayMode (ScrnInfoPtr scrn, - RRModePtr randr_mode, - DisplayModePtr mode) -{ - memset(mode, 0, sizeof(DisplayModeRec)); - mode->status = MODE_OK; - - mode->Clock = randr_mode->mode.dotClock / 1000; - - mode->HDisplay = randr_mode->mode.width; - mode->HSyncStart = randr_mode->mode.hSyncStart; - mode->HSyncEnd = randr_mode->mode.hSyncEnd; - mode->HTotal = randr_mode->mode.hTotal; - mode->HSkew = randr_mode->mode.hSkew; - - mode->VDisplay = randr_mode->mode.height; - mode->VSyncStart = randr_mode->mode.vSyncStart; - mode->VSyncEnd = randr_mode->mode.vSyncEnd; - mode->VTotal = randr_mode->mode.vTotal; - mode->VScan = 0; - - mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; - - xf86SetModeCrtc (mode, scrn->adjustFlags); -} - - -static int -_secPropUnsetCrtc (xf86OutputPtr pOutput) -{ - if (!pOutput->crtc) - return 1; - - ScrnInfoPtr pScrn = pOutput->scrn; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - SECModePtr pSecMode = pOutputPriv->pSecMode; - - pSecMode->unset_connector_type = pOutputPriv->mode_output->connector_type; - RRGetInfo (pScrn->pScreen, TRUE); - pSecMode->unset_connector_type = 0; - RRGetInfo (pScrn->pScreen, TRUE); - - return 1; -} - -static int -_secPropSetWbClone (xf86OutputPtr pOutput, int mode_xid) -{ - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - SECModePtr pSecMode = pOutputPriv->pSecMode; - RRModePtr pRRMode; - DisplayModeRec mode; - - /* find kmode and set the external default mode */ - PROP_VERIFY_RR_MODE (mode_xid, pRRMode, DixSetAttrAccess); - _RRModeConvertToDisplayMode (pOutput->scrn, pRRMode, &mode); - secDisplayModeToKmode (pOutput->scrn, &pSecMode->ext_connector_mode, &mode); - - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB) - { - secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_HDMI); - _secPropUnsetCrtc (pOutput); - } - else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_VIRTUAL); - _secPropUnsetCrtc (pOutput); - } - else - { - XDBG_WARNING (MDISP, "(WB_CLONE) Not suuport for this connecotor type\n"); - return 0; - } - - if(!secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_CLONE)) - { - return 0; - } - - return 1; -} - -static void -_secPropUnSetWbClone (xf86OutputPtr pOutput) -{ - secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_OFF); - secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_NONE); -} - -Bool -secPropSetDisplayMode (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) -{ - XDBG_RETURN_VAL_IF_FAIL(value, FALSE); - XDBG_TRACE (MPROP, "%s\n", __FUNCTION__); - - XRROutputPropDisplayMode disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL; - SECOutputPrivPtr pOutputPriv; - - if (g_display_mode_prop_init == FALSE) - { - xrr_property_display_mode_atom = MakeAtom (STR_XRR_DISPLAY_MODE_PROPERTY, strlen (STR_XRR_DISPLAY_MODE_PROPERTY), TRUE); - g_display_mode_prop_init = TRUE; - } - - if (xrr_property_display_mode_atom != property) - { - //ErrorF ("[Display_mode]: Unrecognized property name.\n"); - return FALSE; - } - - if (!value->data || value->size == 0) - { - //ErrorF ("[Display_mode]: Unrecognized property value.\n"); - return TRUE; - } - - XDBG_DEBUG (MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, *(int *)value->data, value->size); - - disp_mode = *(int *)value->data; - - if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL) - return TRUE; - - XDBG_DEBUG (MDISP, "output_name=%s, disp_mode=%d\n", pOutput->name, disp_mode); - - pOutputPriv = pOutput->driver_private; - - int mode_xid; - switch (disp_mode) - { - case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE: - mode_xid = *((int *)value->data+1); - XDBG_INFO (MDISP, "[DISPLAY_MODE]: Set WriteBack Clone\n"); - _secPropSetWbClone (pOutput, mode_xid); - pOutputPriv->disp_mode = disp_mode; - break; - default: - break; - } - - return TRUE; -} - -void -secPropUnSetDisplayMode (xf86OutputPtr pOutput) -{ - XRROutputPropDisplayMode disp_mode; - SECOutputPrivPtr pOutputPriv; - - pOutputPriv = pOutput->driver_private; - disp_mode = pOutputPriv->disp_mode; - - if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL) - return; - - /* check the private and unset the diplaymode */ - switch (disp_mode) - { - case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE: - XDBG_INFO (MDISP, "[DISPLAY_MODE]: UnSet WriteBack Clone\n"); - _secPropUnSetWbClone (pOutput); - break; - default: - break; - } - - pOutputPriv->disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL; -} - -static const char fake_edid_info[] = { - /* fill the edid information */ -}; - -static void -_secPropSetVirtual (xf86OutputPtr pOutput, int sc_conn) -{ - SECPtr pSec = SECPTR (pOutput->scrn); - int fd = pSec->drm_fd; - - struct drm_exynos_vidi_connection vidi; - - if (sc_conn == 1) - { - vidi.connection = 1; - vidi.extensions = 1; - vidi.edid = (uint64_t *)fake_edid_info; - } - else if (sc_conn == 2) - { - vidi.connection = 0; - } - else - { - XDBG_WARNING (MDISP, "Warning : wrong virtual connection command\n"); - return; - } - - ioctl (fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &vidi); -} - -Bool -secPropSetLvdsFunc (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) -{ - XDBG_TRACE (MPROP, "%s\n", __FUNCTION__); - XDBG_RETURN_VAL_IF_FAIL(value, FALSE); - - XRROutputPropLvdsFunc lvds_func = XRR_OUTPUT_LVDS_FUNC_NULL; - - if (g_lvds_func_prop_init == FALSE) - { - xrr_property_lvds_func_atom = MakeAtom (STR_XRR_LVDS_FUNCTION, strlen (STR_XRR_LVDS_FUNCTION), TRUE); - g_lvds_func_prop_init = TRUE; - } - - if (xrr_property_lvds_func_atom != property) - { - return FALSE; - } - - if (!value->data || value->size == 0) - { - //ErrorF ("[Display_mode]: Unrecognized property value.\n"); - return TRUE; - } - - XDBG_DEBUG (MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, *(int *)value->data, value->size); - - lvds_func = *(int *)value->data; - - if (lvds_func == XRR_OUTPUT_LVDS_FUNC_NULL) - return TRUE; - - XDBG_DEBUG (MDISP, "output_name=%s, lvds_func=%d\n", pOutput->name, lvds_func); - - int sc_conn; - switch (lvds_func) - { - case XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL: - sc_conn = *((int *)value->data+1); - XDBG_INFO (MDISP, "[LVDS_FUNC]: set virtual output (%d)\n", sc_conn); - _secPropSetVirtual (pOutput, sc_conn); - break; - case XRR_OUTPUT_LVDS_FUNC_HIBERNATION: - XDBG_INFO (MDISP, "[LVDS_FUNC]: set hibernationn\n"); - break; - case XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY: - XDBG_INFO (MDISP, "[LVDS_FUNC]: set accessibility\n"); - break; - default: - break; - } - - return TRUE; -} - -void -secPropUnSetLvdsFunc (xf86OutputPtr pOutput) -{ - -} - -static void -_secPropReturnProperty (RRPropertyValuePtr value, const char * f, ...) -{ - int len; - va_list args; - char buf[1024]; - - if (value->data) - { - free (value->data); - value->data = NULL; - } - va_start (args, f); - len = vsnprintf (buf, sizeof(buf), f, args) + 1; - va_end (args); - - value->data = calloc (1, len); - value->format = 8; - value->size = len; - - if (value->data) - strncpy (value->data, buf, len-1); -} - -Bool secPropFbVisible (char *cmd, Bool always, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - int output = 0; - int pos = 0; - Bool onoff = FALSE; - char str[128]; - char *p; - SECLayer *layer; - SECLayerPos lpos; - - XDBG_RETURN_VAL_IF_FAIL (cmd != NULL, FALSE); - - snprintf (str, sizeof(str), "%s", cmd); - - p = strtok (str, ":"); - XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE); - output = atoi (p); - - p = strtok (NULL, ":"); - XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE); - pos = atoi (p); - - if (output == LAYER_OUTPUT_LCD) - lpos = pos - 3; - else - lpos = pos - 1; - - p = strtok (NULL, ":"); - if (!p) - { - _secPropReturnProperty (value, "%d", 0); - - if (lpos != 0) - { - layer = secLayerFind ((SECLayerOutput)output, lpos); - if (layer) - _secPropReturnProperty (value, "%d", secLayerTurnStatus (layer)); - } - else - { - xf86CrtcConfigPtr pCrtcConfig; - int i; - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn); - if (!pCrtcConfig) - return FALSE; - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - - if ((output == LAYER_OUTPUT_LCD && - (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)) || - (output == LAYER_OUTPUT_EXT && - (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL))) - { - if (pOutput->crtc) - { - SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; - _secPropReturnProperty (value, "%d", pCrtcPriv->onoff); - } - break; - } - } - } - - return TRUE; - } - onoff = atoi (p); - - if (lpos != 0) - { - if (!always) - if (output == LAYER_OUTPUT_LCD && lpos == LAYER_UPPER) - { - xf86CrtcPtr pCrtc = xf86CompatCrtc (scrn); - XDBG_RETURN_VAL_IF_FAIL ((pCrtc != NULL), FALSE); - SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private; - - secCrtcOverlayNeedOff (pCrtc, !onoff); - - if (pCrtcPriv->cursor_show && !onoff) - { - XDBG_TRACE (MCRS, "can't turn upper off.\n"); - return FALSE; - } - } - - layer = secLayerFind ((SECLayerOutput)output, lpos); - if (!layer) - return FALSE; - - if (onoff) - secLayerTurn (layer, TRUE, TRUE); - else - secLayerTurn (layer, FALSE, TRUE); - } - else - { - xf86CrtcConfigPtr pCrtcConfig; - int i; - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn); - if (!pCrtcConfig) - return FALSE; - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - - if ((output == LAYER_OUTPUT_LCD && - (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)) || - (output == LAYER_OUTPUT_EXT && - (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL))) - { - SECCrtcPrivPtr pCrtcPriv; - - if (!pOutput->crtc) - break; - - pCrtcPriv = pOutput->crtc->driver_private; - if (pCrtcPriv->bAccessibility) - { - _secPropReturnProperty (value, "[Xorg] crtc(%d) accessibility ON. \n", - secCrtcID(pCrtcPriv)); - return TRUE; - } - - if (pOutput->crtc && !secCrtcTurn (pOutput->crtc, onoff, always, TRUE)) - { - _secPropReturnProperty (value, "[Xorg] crtc(%d) now %s%s\n", - secCrtcID(pCrtcPriv), - (pCrtcPriv->onoff)?"ON":"OFF", - (pCrtcPriv->onoff_always)?"(always).":"."); - return TRUE; - } - break; - } - } - } - - _secPropReturnProperty (value, "[Xorg] output(%d), zpos(%d) layer %s%s\n", - output, pos, (onoff)?"ON":"OFF", (always)?"(always).":"."); - - return TRUE; -} - -Bool secPropVideoOffset (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - int x, y; - char str[128]; - char *p; - SECLayer *layer; - - snprintf (str, sizeof(str), "%s", cmd); - - p = strtok (str, ","); - XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE); - x = atoi (p); - - p = strtok (NULL, ","); - XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE); - y = atoi (p); - -#if 0 - PropertyPtr rotate_prop; - int rotate = 0; - rotate_prop = secUtilGetWindowProperty (scrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE"); - if (rotate_prop) - rotate = *(int*)rotate_prop->data; -#endif - - pSec->pVideoPriv->video_offset_x = x; - pSec->pVideoPriv->video_offset_y = y; - - layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_LOWER1); - if (layer) - secLayerSetOffset (layer, x, y); - - layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_LOWER2); - if (layer) - secLayerSetOffset (layer, x, y); - - _secPropReturnProperty (value, "[Xorg] video_offset : %d,%d.\n", - pSec->pVideoPriv->video_offset_x, - pSec->pVideoPriv->video_offset_y); - - return TRUE; -} - -Bool -secPropSetFbVisible (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) -{ - if (g_fb_visible_prop_init == FALSE) - { - xrr_property_fb_visible_atom = MakeAtom (STR_XRR_FB_VISIBLE_PROPERTY, - strlen (STR_XRR_FB_VISIBLE_PROPERTY), TRUE); - g_fb_visible_prop_init = TRUE; - } - - if (xrr_property_fb_visible_atom != property) - return FALSE; - - if (!value || !value->data || value->size == 0) - return TRUE; - - if (value->format != 8) - return TRUE; - - XDBG_TRACE (MPROP, "%s \n", value->data); - - secPropFbVisible (value->data, FALSE, value, pOutput->scrn); - - return TRUE; -} - -Bool -secPropSetVideoOffset (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) -{ - if (g_video_offset_prop_init == FALSE) - { - xrr_property_video_offset_atom = MakeAtom (STR_XRR_VIDEO_OFFSET_PROPERTY, - strlen (STR_XRR_VIDEO_OFFSET_PROPERTY), TRUE); - g_video_offset_prop_init = TRUE; - } - - if (xrr_property_video_offset_atom != property) - return FALSE; - - if (!value || !value->data || value->size == 0) - return TRUE; - - if (value->format != 8) - return TRUE; - - XDBG_TRACE (MPROP, "%s \n", value->data); - - secPropVideoOffset (value->data, value, pOutput->scrn); - - return TRUE; -} - -Bool secPropScreenRotate (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - xf86CrtcPtr crtc = xf86CompatCrtc (scrn); - int degree; - - if (!crtc) - return TRUE; - - if (!strcmp (cmd, "normal")) - degree = 0; - else if (!strcmp (cmd, "right")) - degree = 90; - else if (!strcmp (cmd, "inverted")) - degree = 180; - else if (!strcmp (cmd, "left")) - degree = 270; - else if (!strcmp (cmd, "0")) - degree = 0; - else if (!strcmp (cmd, "1")) - degree = 270; - else if (!strcmp (cmd, "2")) - degree = 180; - else if (!strcmp (cmd, "3")) - degree = 90; - else - { - _secPropReturnProperty (value, "[Xorg] unknown value: %s\n", cmd); - return TRUE; - } - - if (secCrtcScreenRotate (crtc, degree)) - _secPropReturnProperty (value, "[Xorg] screen rotated %d.\n", degree); - else - { - _secPropReturnProperty (value, "[Xorg] Fail screen rotate %d.\n", degree); - return FALSE; - } - - return TRUE; -} - -Bool -secPropSetScreenRotate (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) -{ - if (g_screen_rotate_prop_init == FALSE) - { - xrr_property_screen_rotate_atom = MakeAtom (STR_XRR_PROPERTY_SCREEN_ROTATE, - strlen (STR_XRR_PROPERTY_SCREEN_ROTATE), TRUE); - g_screen_rotate_prop_init = TRUE; - } - - if (xrr_property_screen_rotate_atom != property) - return FALSE; - - if (!value || !value->data || value->size == 0) - return TRUE; - - if (value->format != 8) - return TRUE; - - XDBG_TRACE (MPROP, "%s \n", value->data); - - secPropScreenRotate (value->data, value, pOutput->scrn); - - return TRUE; -} - diff --git a/src/crtcconfig/sec_xberc.c b/src/crtcconfig/sec_xberc.c deleted file mode 100755 index 3b0936f..0000000 --- a/src/crtcconfig/sec_xberc.c +++ /dev/null @@ -1,1276 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <stdint.h> -#include <string.h> -#include <strings.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <poll.h> -#include <dirent.h> - -#include <xorgVersion.h> -#include <tbm_bufmgr.h> -#include <xf86Crtc.h> -#include <xf86DDC.h> -#include <xf86cmap.h> -#include <xf86Priv.h> -#include <list.h> -#include <X11/Xatom.h> -#include <X11/extensions/dpmsconst.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_xberc.h" -#include "sec_output.h" -#include "sec_crtc.h" -#include "sec_layer.h" -#include "sec_wb.h" -#include "sec_plane.h" -#include "sec_prop.h" -#include "sec_drmmode_dump.h" - -#define XRRPROPERTY_ATOM "X_RR_PROPERTY_REMOTE_CONTROLLER" -#define XBERC_BUF_SIZE 8192 - -static Atom rr_property_atom; - -static void _secXbercSetReturnProperty (RRPropertyValuePtr value, const char * f, ...); - -static Bool SECXbercSetTvoutMode (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - SECModePtr pSecMode = pSec->pSecMode; - const char * mode_string[] = {"Off", "Clone", "UiClone", "Extension"}; - SECDisplaySetMode mode; - - XDBG_DEBUG (MSEC, "%s value : %d\n", __FUNCTION__, *(unsigned int*)value->data); - - if (argc < 2) - { - _secXbercSetReturnProperty (value, "Error : too few arguments\n"); - return TRUE; - } - - if (argc == 2) - { - _secXbercSetReturnProperty (value, "Current Tv Out mode is %d (%s)\n", - pSecMode->set_mode, mode_string[pSecMode->set_mode]); - return TRUE; - } - - mode = (SECDisplaySetMode)atoi (argv[2]); - - if (mode < DISPLAY_SET_MODE_OFF) - { - _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", mode); - return TRUE; - } - - if (mode == pSecMode->set_mode) - { - _secXbercSetReturnProperty (value, "[Xorg] already tvout : %s.\n", mode_string[mode]); - return TRUE; - } - - if (pSecMode->conn_mode != DISPLAY_CONN_MODE_HDMI && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) - { - _secXbercSetReturnProperty (value, "Error : not connected.\n"); - return TRUE; - } - - secDisplaySetDispSetMode (scrn, mode); - - _secXbercSetReturnProperty (value, "[Xorg] tvout : %s.\n", mode_string[mode]); - - return TRUE; -} - -static Bool SECXbercSetConnectMode (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - SECModePtr pSecMode = pSec->pSecMode; - const char * mode_string[] = {"Off", "HDMI", "Virtual"}; - SECDisplayConnMode mode; - - XDBG_DEBUG (MSEC, "%s value : %d\n", __FUNCTION__, *(unsigned int*)value->data); - - if (argc < 2) - { - _secXbercSetReturnProperty (value, "Error : too few arguments\n"); - return TRUE; - } - - if (argc == 2) - { - _secXbercSetReturnProperty (value, "Current connect mode is %d (%s)\n", - pSecMode->conn_mode, mode_string[pSecMode->conn_mode]); - return TRUE; - } - - mode = (SECDisplayConnMode)atoi (argv[2]); - - if (mode < DISPLAY_CONN_MODE_NONE || mode >= DISPLAY_CONN_MODE_MAX) - { - _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", mode); - return TRUE; - } - - if (mode == pSecMode->conn_mode) - { - _secXbercSetReturnProperty (value, "[Xorg] already connect : %s.\n", mode_string[mode]); - return TRUE; - } - - secDisplaySetDispConnMode (scrn, mode); - - _secXbercSetReturnProperty (value, "[Xorg] connect : %s.\n", mode_string[mode]); - - return TRUE; -} - -static Bool SECXbercAsyncSwap (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - ScreenPtr pScreen = scrn->pScreen; - int bEnable; - int status = -1; - - if (argc !=3 ) - { - status = secExaScreenAsyncSwap (pScreen, -1); - if (status < 0) - { - _secXbercSetReturnProperty (value, "%s", "faili to set async swap\n"); - return TRUE; - } - - _secXbercSetReturnProperty (value, "Async swap : %d\n", status); - return TRUE; - } - - bEnable = atoi (argv[2]); - - status = secExaScreenAsyncSwap (pScreen, bEnable); - if (status < 0) - { - _secXbercSetReturnProperty (value, "%s", "faili to set async swap\n"); - return TRUE; - } - - if (status) - _secXbercSetReturnProperty (value, "%s", "Set async swap.\n"); - else - _secXbercSetReturnProperty (value, "%s", "Unset async swap.\n"); - - return TRUE; -} - -static long -_parse_long (char *s) -{ - char *fmt = "%lu"; - long retval = 0L; - int thesign = 1; - - if (s && s[0]) - { - char temp[12]; - snprintf (temp, sizeof (temp), "%s", s); - s = temp; - - if (s[0] == '-') - s++, thesign = -1; - if (s[0] == '0') - s++, fmt = "%lo"; - if (s[0] == 'x' || s[0] == 'X') - s++, fmt = "%lx"; - (void) sscanf (s, fmt, &retval); - } - return (thesign * retval); -} - -static Bool SECXbercDump (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - int dump_mode; - Bool flush = TRUE; - char *c; - int buf_cnt = 30; - - if (argc < 3) - goto print_dump; - - pSec->dump_xid = 0; - dump_mode = 0; - - if (pSec->dump_str) - free (pSec->dump_str); - pSec->dump_str = strdup (argv[2]); - - c = strtok (argv[2], ","); - if (!c) - { - _secXbercSetReturnProperty (value, "[Xorg] fail: read option"); - return TRUE; - } - - do - { - if (!strcmp (c, "off")) - { - dump_mode = 0; - break; - } - else if (!strcmp (c, "clear")) - { - dump_mode = 0; - flush = FALSE; - break; - } - else if (!strcmp (c, "drawable")) - { - dump_mode = XBERC_DUMP_MODE_DRAWABLE; - pSec->dump_xid = _parse_long (argv[3]); - } - else if (!strcmp (c, "fb")) - dump_mode |= XBERC_DUMP_MODE_FB; - else if (!strcmp (c, "all")) - dump_mode |= (XBERC_DUMP_MODE_DRAWABLE|XBERC_DUMP_MODE_FB); - else if (!strcmp (c, "ia")) - dump_mode |= XBERC_DUMP_MODE_IA; - else if (!strcmp (c, "ca")) - dump_mode |= XBERC_DUMP_MODE_CA; - else if (!strcmp (c, "ea")) - dump_mode |= XBERC_DUMP_MODE_EA; - else - { - _secXbercSetReturnProperty (value, "[Xorg] fail: unknown option('%s')\n", c); - return TRUE; - } - } while ((c = strtok (NULL, ","))); - - snprintf (pSec->dump_type, sizeof (pSec->dump_type), "bmp"); - if (argc > 3) - { - int i; - for (i = 3; i < argc; i++) - { - c = argv[i]; - if (!strcmp (c, "-count")) - buf_cnt = MIN((argv[i+1])?atoi(argv[i+1]):30,100); - else if (!strcmp (c, "-type")) - { - if (!strcmp (argv[i+1], "bmp") || !strcmp (argv[i+1], "raw")) - snprintf (pSec->dump_type, sizeof (pSec->dump_type), "%s", argv[i+1]); - } - } - } - - if (dump_mode != 0) - { - char *dir = DUMP_DIR; - DIR *dp; - int ret = -1; - - if (!(dp = opendir (dir))) - { - ret = mkdir (dir, 0755); - if (ret < 0) - { - _secXbercSetReturnProperty (value, "[Xorg] fail: mkdir '%s'\n", dir); - return FALSE; - } - } - else - closedir (dp); - } - - if (dump_mode != pSec->dump_mode) - { - pSec->dump_mode = dump_mode; - - if (dump_mode == 0) - { - if (flush) - secUtilFlushDump (pSec->dump_info); - secUtilFinishDump (pSec->dump_info); - pSec->dump_info = NULL; - pSec->flip_cnt = 0; - goto print_dump; - } - else - { - if (pSec->dump_info) - { - secUtilFlushDump (pSec->dump_info); - secUtilFinishDump (pSec->dump_info); - pSec->dump_info = NULL; - pSec->flip_cnt = 0; - } - - pSec->dump_info = secUtilPrepareDump (scrn, - pSec->pSecMode->main_lcd_mode.hdisplay * pSec->pSecMode->main_lcd_mode.vdisplay * 4, - buf_cnt); - if (pSec->dump_info) - { - if (pSec->dump_mode & ~XBERC_DUMP_MODE_DRAWABLE) - _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(cnt:%d)\n", - pSec->dump_str, buf_cnt); - else - _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(xid:0x%x,cnt:%d)\n", - pSec->dump_str, pSec->dump_xid, buf_cnt); - } - else - _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(fail)\n", pSec->dump_str); - } - } - else - goto print_dump; - - return TRUE; -print_dump: - if (pSec->dump_mode & XBERC_DUMP_MODE_DRAWABLE) - _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(0x%x)\n", pSec->dump_str, pSec->dump_xid); - else - _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s\n", pSec->dump_str); - - return TRUE; -} - -static Bool SECXbercCursorEnable (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool bEnable; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "Enable cursor : %d\n", pSec->enableCursor); - return TRUE; - } - - bEnable = atoi (argv[2]); - - if (bEnable!=pSec->enableCursor) - { - pSec->enableCursor = bEnable; - if (secCrtcCursorEnable (scrn, bEnable)) - { - _secXbercSetReturnProperty (value, "[Xorg] cursor %s.\n", bEnable?"enable":"disable"); - } - else - { - _secXbercSetReturnProperty (value, "[Xorg] Fail cursor %s.\n", bEnable?"enable":"disable"); - } - } - else - { - _secXbercSetReturnProperty (value, "[Xorg] already cursor %s.\n", bEnable?"enabled":"disabled"); - } - - return TRUE; -} - -static Bool SECXbercCursorRotate (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - xf86CrtcPtr crtc = xf86CompatCrtc (scrn); - SECCrtcPrivPtr fimd_crtc; - int rotate, RR_rotate; - - if (!crtc) - return TRUE; - - fimd_crtc = crtc->driver_private; - - if (argc != 3) - { - rotate = secUtilRotateToDegree (fimd_crtc->user_rotate); - _secXbercSetReturnProperty (value, "Current cursor rotate value : %d\n", rotate); - return TRUE; - } - - rotate = atoi (argv[2]); - RR_rotate = secUtilDegreeToRotate (rotate); - if (!RR_rotate) - { - _secXbercSetReturnProperty (value, "[Xorg] Not support rotate(0, 90, 180, 270 only)\n"); - return TRUE; - } - - if (secCrtcCursorRotate (crtc, RR_rotate)) - { - _secXbercSetReturnProperty (value, "[Xorg] cursor rotated %d.\n", rotate); - } - else - { - _secXbercSetReturnProperty (value, "[Xorg] Fail cursor rotate %d.\n", rotate); - } - - return TRUE; -} - -static Bool SECXbercVideoPunch (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool video_punch; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "video_punch : %d\n", pSec->pVideoPriv->video_punch); - return TRUE; - } - - video_punch = atoi (argv[2]); - - if (pSec->pVideoPriv->video_punch != video_punch) - { - pSec->pVideoPriv->video_punch = video_punch; - _secXbercSetReturnProperty (value, "[Xorg] video_punch %s.\n", video_punch?"enabled":"disabled"); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already punch %s.\n", video_punch?"enabled":"disabled"); - - return TRUE; -} - -static Bool SECXbercVideoOffset (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "video_offset : %d,%d.\n", - pSec->pVideoPriv->video_offset_x, - pSec->pVideoPriv->video_offset_y); - return TRUE; - } - - if (!secPropVideoOffset (argv[2], value, scrn)) - { - _secXbercSetReturnProperty (value, "ex) xberc video_offset 0,100.\n"); - return TRUE; - } - - return TRUE; -} - -static Bool SECXbercVideoFps (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool video_fps; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "video_fps : %d\n", pSec->pVideoPriv->video_fps); - return TRUE; - } - - video_fps = atoi (argv[2]); - - if (pSec->pVideoPriv->video_fps != video_fps) - { - pSec->pVideoPriv->video_fps = video_fps; - _secXbercSetReturnProperty (value, "[Xorg] video_fps %s.\n", video_fps?"enabled":"disabled"); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already video_fps %s.\n", video_fps?"enabled":"disabled"); - - return TRUE; -} - -static Bool SECXbercVideoSync (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool video_sync; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "video_sync : %d\n", pSec->pVideoPriv->video_sync); - return TRUE; - } - - video_sync = atoi (argv[2]); - - if (pSec->pVideoPriv->video_sync != video_sync) - { - pSec->pVideoPriv->video_sync = video_sync; - _secXbercSetReturnProperty (value, "[Xorg] video_sync %s.\n", video_sync?"enabled":"disabled"); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already video_sync %s.\n", video_sync?"enabled":"disabled"); - - return TRUE; -} - -static Bool SECXbercVideoNoRetbuf (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "[Xorg] %s wait retbuf\n", (pSec->pVideoPriv->no_retbuf)?"No":""); - return TRUE; - } - - pSec->pVideoPriv->no_retbuf = atoi (argv[2]); - - _secXbercSetReturnProperty (value, "[Xorg] %s wait retbuf\n", (pSec->pVideoPriv->no_retbuf)?"No":""); - - return TRUE; -} - -static Bool SECXbercVideoOutput (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - const char * output_string[] = {"None", "default", "video", "ext_only"}; - int video_output; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "video_output : %d\n", output_string[pSec->pVideoPriv->video_output]); - return TRUE; - } - - video_output = atoi (argv[2]); - - if (video_output < OUTPUT_MODE_DEFAULT || video_output > OUTPUT_MODE_EXT_ONLY) - { - _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", video_output); - return TRUE; - } - - video_output += 1; - - if (pSec->pVideoPriv->video_output != video_output) - { - pSec->pVideoPriv->video_output = video_output; - _secXbercSetReturnProperty (value, "[Xorg] video_output : %s.\n", output_string[video_output]); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already video_output : %s.\n", output_string[video_output]); - - return TRUE; -} - -static Bool SECXbercWbFps (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool wb_fps; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "wb_fps : %d\n", pSec->wb_fps); - return TRUE; - } - - wb_fps = atoi (argv[2]); - - if (pSec->wb_fps != wb_fps) - { - pSec->wb_fps = wb_fps; - _secXbercSetReturnProperty (value, "[Xorg] wb_fps %s.\n", wb_fps?"enabled":"disabled"); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already wb_fps %s.\n", wb_fps?"enabled":"disabled"); - - return TRUE; -} - -static Bool SECXbercWbHz (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - - Bool wb_hz; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "wb_hz : %d\n", pSec->wb_hz); - return TRUE; - } - - wb_hz = atoi (argv[2]); - - if (pSec->wb_hz != wb_hz) - { - pSec->wb_hz = wb_hz; - _secXbercSetReturnProperty (value, "[Xorg] wb_hz %d.\n", wb_hz); - } - else - _secXbercSetReturnProperty (value, "[Xorg] already wb_hz %d.\n", wb_hz); - - return TRUE; -} - -static Bool SECXbercXvPerf (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - char *c; - - if (argc < 3) - { - _secXbercSetReturnProperty (value, "[Xorg] xvperf: %s\n", - (pSec->xvperf)?pSec->xvperf:"off"); - return TRUE; - } - - if (pSec->xvperf) - free (pSec->xvperf); - pSec->xvperf = strdup (argv[2]); - - c = strtok (argv[2], ","); - if (!c) - { - _secXbercSetReturnProperty (value, "[Xorg] fail: read option\n"); - return TRUE; - } - - do - { - if (!strcmp (c, "off")) - pSec->xvperf_mode = 0; - else if (!strcmp (c, "ia")) - pSec->xvperf_mode |= XBERC_XVPERF_MODE_IA; - else if (!strcmp (c, "ca")) - pSec->xvperf_mode |= XBERC_XVPERF_MODE_CA; - else if (!strcmp (c, "cvt")) - pSec->xvperf_mode |= XBERC_XVPERF_MODE_CVT; - else if (!strcmp (c, "wb")) - pSec->xvperf_mode |= XBERC_XVPERF_MODE_WB; - else if (!strcmp (c, "access")) - pSec->xvperf_mode |= XBERC_XVPERF_MODE_ACCESS; - else - { - _secXbercSetReturnProperty (value, "[Xorg] fail: unknown option('%s')\n", c); - return TRUE; - } - } while ((c = strtok (NULL, ","))); - - _secXbercSetReturnProperty (value, "[Xorg] xvperf: %s\n", - (pSec->xvperf)?pSec->xvperf:"off"); - - return TRUE; -} - -static Bool SECXbercSwap (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - if (argc != 2) - { - _secXbercSetReturnProperty (value, "Error : too few arguments\n"); - return TRUE; - } - - secVideoSwapLayers (scrn->pScreen); - - _secXbercSetReturnProperty (value, "%s", "Video layers swapped.\n"); - - return TRUE; -} - -static Bool SECXbercDrmmodeDump (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - SECPtr pSec = SECPTR (scrn); - char reply[XBERC_BUF_SIZE] = {0,}; - int len = sizeof (reply); - - if (argc != 2) - { - _secXbercSetReturnProperty (value, "Error : too few arguments\n"); - return TRUE; - } - - sec_drmmode_dump (pSec->drm_fd, reply, &len); - _secXbercSetReturnProperty (value, "%s", reply); - - return TRUE; -} - -static Bool SECXbercAccessibility (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - Bool found = FALSE; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR (scrn); - xf86OutputPtr pOutput = NULL; - xf86CrtcPtr pCrtc = NULL; - SECCrtcPrivPtr pCrtcPriv = NULL; - int output_w = 0, output_h = 0; - - char *opt; - char *mode; - int i; - - int accessibility_status; - int bScale; - _X_UNUSED Bool bChange = FALSE; - - char seps[]="x+-"; - char *tr; - int geo[10], g=0; - - for (i = 0; i < xf86_config->num_output; i++) - { - pOutput = xf86_config->output[i]; - if (!pOutput->crtc->enabled) - continue; - - /* modify the physical size of monitor */ - if (!strcmp(pOutput->name, "LVDS1")) - { - found = TRUE; - break; - } - } - - if (!found) - { - _secXbercSetReturnProperty (value, "Error : cannot found LVDS1\n"); - return TRUE; - } - - pCrtc = pOutput->crtc; - pCrtcPriv = pCrtc->driver_private; - - output_w = pCrtc->mode.HDisplay; - output_h = pCrtc->mode.VDisplay; - - for(i=0; i<argc; i++) - { - opt = argv[i]; - if(*opt != '-') continue; - - if(!strcmp(opt, "-n") ) - { - accessibility_status = atoi(argv[++i]); - if(pCrtcPriv->accessibility_status != accessibility_status) - { - pCrtcPriv->accessibility_status = accessibility_status; - bChange = TRUE; - } - } - else if(!strcmp(opt, "-scale")) - { - bScale = atoi(argv[++i]); - - pCrtcPriv->bScale = bScale; - bChange = TRUE; - //ErrorF("[XORG] Set Scale = %d\n", bScale); - - if(bScale) - { - int x,y,w,h; - - mode = argv[++i]; - tr = strtok(mode, seps); - while(tr != NULL) - { - geo[g++] = atoi(tr); - tr=strtok(NULL, seps); - } - - if(g < 4) - { - _secXbercSetReturnProperty (value, "[Xberc] Invalid geometry(%s)\n", mode); - continue; - } - - w = geo[0]; - h = geo[1]; - x = geo[2]; - y = geo[3]; - - /*Check invalidate region */ - if(x<0) x=0; - if(y<0) y=0; - if(x+w > output_w) w = output_w-x; - if(y+h > output_h) h = output_h-y; - - if(pCrtcPriv->rotate == RR_Rotate_90) - { - pCrtcPriv->sx = y; - pCrtcPriv->sy = output_w - (x+w); - pCrtcPriv->sw = h; - pCrtcPriv->sh = w; - } - else if(pCrtcPriv->rotate == RR_Rotate_270) - { - pCrtcPriv->sx = output_h - (y+h); - pCrtcPriv->sy = x; - pCrtcPriv->sw = h; - pCrtcPriv->sh = w; - } - else if(pCrtcPriv->rotate == RR_Rotate_180) - { - pCrtcPriv->sx = output_w - (x+w); - pCrtcPriv->sy = output_h - (y+h); - pCrtcPriv->sw = w; - pCrtcPriv->sh = h; - } - else - { - pCrtcPriv->sx = x; - pCrtcPriv->sy = y; - pCrtcPriv->sw = w; - pCrtcPriv->sh = h; - } - } - } - } - - secCrtcEnableAccessibility (pCrtc); - - return TRUE; -} - -static Bool SECXbercEnableFb (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - Bool always = FALSE; - - if (argc == 2) - { - char ret_buf[XBERC_BUF_SIZE] = {0,}; - char temp[1024] = {0,}; - xf86CrtcConfigPtr pCrtcConfig; - int i, len, remain = XBERC_BUF_SIZE; - char *buf = ret_buf; - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn); - if (!pCrtcConfig) - goto fail_enable_fb; - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - if (pOutput->crtc) - { - SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; - snprintf (temp, sizeof (temp), "crtc(%d) : %s%s\n", - pCrtcPriv->mode_crtc->crtc_id, - (pCrtcPriv->onoff)?"ON":"OFF", - (pCrtcPriv->onoff_always)?"(always).":"."); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - } - } - - secPlaneDump (buf, &remain); - - _secXbercSetReturnProperty (value, "%s", ret_buf); - - return TRUE; - } - - if (argc > 4) - goto fail_enable_fb; - - if (!strcmp ("always", argv[3])) - always = TRUE; - - if (!secPropFbVisible (argv[2], always, value, scrn)) - goto fail_enable_fb; - - return TRUE; - -fail_enable_fb: - _secXbercSetReturnProperty (value, "ex) xberc fb [output]:[zpos]:[onoff] {always}.\n"); - - return TRUE; -} - -static Bool SECXbercScreenRotate (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn) -{ - xf86CrtcPtr crtc = xf86CompatCrtc (scrn); - SECCrtcPrivPtr fimd_crtc; - - if (!crtc) - return TRUE; - - fimd_crtc = crtc->driver_private; - - if (argc != 3) - { - _secXbercSetReturnProperty (value, "Current screen rotate value : %d\n", fimd_crtc->screen_rotate_degree); - return TRUE; - } - - secPropScreenRotate (argv[2], value, scrn); - - return TRUE; -} - -static struct -{ - const char * Cmd; - const char * Description; - const char * Options; - - const char *(*DynamicUsage) (int); - const char * DetailedUsage; - - Bool (*set_property) (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn); - Bool (*get_property) (RRPropertyValuePtr value); -} xberc_property_proc[] = -{ - { - "tvout", "to set Tv Out Mode", "[0-4]", - NULL, "[Off:0 / Clone:1 / UiClone:2 / Extension:3]", - SECXbercSetTvoutMode, NULL, - }, - - { - "connect", "to set connect mode", "[0-2]", - NULL, "[Off:0 / HDMI:1 / Virtual:2]", - SECXbercSetConnectMode, NULL, - }, - - { - "async_swap", "not block by vsync", "[0 or 1]", - NULL, "[0/1]", - SECXbercAsyncSwap, NULL - }, - - { - "dump", "to dump buffers", "[off,clear,drawable,fb,all]", - NULL, "[off,clear,drawable,fb,all] -count [n] -type [raw|bmp]", - SECXbercDump, NULL - }, - - { - "cursor_enable", "to enable/disable cursor", "[0 or 1]", - NULL, "[Enable:1 / Disable:0]", - SECXbercCursorEnable, NULL - }, - - { - "cursor_rotate", "to set cursor rotate degree", "[0,90,180,270]", - NULL, "[0,90,180,270]", - SECXbercCursorRotate, NULL - }, - - { - "video_punch", "to punch screen when XV put image on screen", "[0 or 1]", - NULL, "[0/1]", - SECXbercVideoPunch, NULL - }, - - { - "video_offset", "to add x,y to the position video", "[x,y]", - NULL, "[x,y]", - SECXbercVideoOffset, NULL - }, - - { - "video_fps", "to print fps of video", "[0 or 1]", - NULL, "[0/1]", - SECXbercVideoFps, NULL - }, - - { - "video_sync", "to sync video", "[0 or 1]", - NULL, "[0/1]", - SECXbercVideoSync, NULL - }, - - { - "video_output", "to set output", "[0,1,2]", - NULL, "[default:0 / video:1 / ext_only:2]", - SECXbercVideoOutput, NULL - }, - - { - "video_no_retbuf", "no wait until buffer returned", "[0,1]", - NULL, "[disable:0 / enable:1]", - SECXbercVideoNoRetbuf, NULL - }, - - { - "wb_fps", "to print fps of writeback", "[0 or 1]", - NULL, "[0/1]", - SECXbercWbFps, NULL - }, - - { - "wb_hz", "to set hz of writeback", "[0, 12, 15, 20, 30, 60]", - NULL, "[0, 12, 15, 20, 30, 60]", - SECXbercWbHz, NULL - }, - - { - "xv_perf", "to print xv elapsed time", "[off,ia,ca,cvt,wb]", - NULL, "[off,ia,ca,cvt,wb]", - SECXbercXvPerf, NULL - }, - - { - "swap", "to swap video layers", "", - NULL, "", - SECXbercSwap, NULL - }, - - { - "drmmode_dump", "to print drmmode resources", "", - NULL, "", - SECXbercDrmmodeDump, NULL - }, - - { - "accessibility", "to set accessibility", "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]", - NULL, "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]", - SECXbercAccessibility, NULL - }, - - { - "fb", "to turn framebuffer on/off", "[0~1]:[0~4]:[0~1] {always}", - NULL, "[output : 0(lcd)~1(ext)]:[zpos : 0 ~ 4]:[onoff : 0(on)~1(off)] {always}", - SECXbercEnableFb, NULL - }, - - { - "screen_rotate", "to set screen orientation", "[normal,inverted,left,right,0,1,2,3]", - NULL, "[normal,inverted,left,right,0,1,2,3]", - SECXbercScreenRotate, NULL - }, -}; - -static int _secXbercPrintUsage (char *buf, int size, const char * exec) -{ - char * begin = buf; - char temp[1024]; - int i, len, remain = size; - - int option_cnt = sizeof (xberc_property_proc) / sizeof (xberc_property_proc[0]); - - snprintf (temp, sizeof (temp), "Usage : %s [cmd] [options]\n", exec); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - - snprintf (temp, sizeof (temp), " ex)\n"); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - - for (i=0; i<option_cnt; i++) - { - snprintf (temp, sizeof (temp), " %s %s %s\n", exec, xberc_property_proc[i].Cmd, xberc_property_proc[i].Options); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - } - - snprintf (temp, sizeof (temp), " options :\n"); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - - for (i=0; i<option_cnt; i++) - { - if (xberc_property_proc[i].Cmd && xberc_property_proc[i].Description) - snprintf (temp, sizeof (temp), " %s (%s)\n", xberc_property_proc[i].Cmd, xberc_property_proc[i].Description); - else - snprintf (temp, sizeof (temp), " Cmd(%p) or Descriptiont(%p).\n", xberc_property_proc[i].Cmd, xberc_property_proc[i].Description); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - - if (xberc_property_proc[i].DynamicUsage) - { - snprintf (temp, sizeof (temp), " [MODULE:%s]\n", xberc_property_proc[i].DynamicUsage (MODE_NAME_ONLY)); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - } - - if (xberc_property_proc[i].DetailedUsage) - snprintf (temp, sizeof (temp), " %s\n", xberc_property_proc[i].DetailedUsage); - else - snprintf (temp, sizeof (temp), " DetailedUsage(%p).\n", xberc_property_proc[i].DetailedUsage); - len = MIN (remain, strlen (temp)); - strncpy (buf, temp, len); - buf += len; - remain -= len; - - if (remain <= 0) - return (buf - begin); - } - - return (buf - begin); -} - -static unsigned int _secXbercInit() -{ - XDBG_DEBUG (MSEC, "%s()\n", __FUNCTION__); - - static Bool g_property_init = FALSE; - static unsigned int nProperty = sizeof (xberc_property_proc) / sizeof (xberc_property_proc[0]); - - if (g_property_init == FALSE) - { - rr_property_atom = MakeAtom (XRRPROPERTY_ATOM, strlen (XRRPROPERTY_ATOM), TRUE); - g_property_init = TRUE; - } - - return nProperty; -} - -static int _secXbercParseArg (int * argc, char ** argv, RRPropertyValuePtr value) -{ - int i; - char * data; - - if (argc == NULL || value == NULL || argv == NULL || value->data == NULL) - return FALSE; - - data = value->data; - - if (value->format != 8) - return FALSE; - - if (value->size < 3 || data[value->size - 2] != '\0' || data[value->size - 1] != '\0') - return FALSE; - - for (i=0; *data; i++) - { - argv[i] = data; - data += strlen (data) + 1; - if (data - (char*)value->data > value->size) - return FALSE; - } - argv[i] = data; - *argc = i; - - return TRUE; -} - -static void _secXbercSetReturnProperty (RRPropertyValuePtr value, const char * f, ...) -{ - int len; - va_list args; - char buf[XBERC_BUF_SIZE]; - - if (value->data) - { - free (value->data); - value->data = NULL; - } - va_start (args, f); - len = vsnprintf (buf, sizeof(buf), f, args) + 1; - va_end (args); - - value->data = calloc (1, len); - value->format = 8; - value->size = len; - - if (value->data) - strncpy (value->data, buf, len-1); -} - -int -secXbercSetProperty (xf86OutputPtr output, Atom property, RRPropertyValuePtr value) -{ - XDBG_TRACE (MXBRC, "%s\n", __FUNCTION__); - - unsigned int nProperty = _secXbercInit(); - unsigned int p; - - int argc; - char * argv[1024]; - char buf[XBERC_BUF_SIZE] = {0,}; - - if (rr_property_atom != property) - { - _secXbercSetReturnProperty (value, "[Xberc]: Unrecognized property name.\n"); - return TRUE; - } - - if (_secXbercParseArg (&argc, argv, value) == FALSE || argc < 1) - { - _secXbercSetReturnProperty (value, "[Xberc]: Parse error.\n"); - return TRUE; - } - - if (argc < 2) - { - _secXbercPrintUsage (buf, sizeof (buf), argv[0]); - _secXbercSetReturnProperty (value, buf); - - return TRUE; - } - - for (p=0; p<nProperty; p++) - { - if (!strcmp (argv[1], xberc_property_proc[p].Cmd) || - (argv[1][0] == '-' && !strcmp (1 + argv[1], xberc_property_proc[p].Cmd))) - { - xberc_property_proc[p].set_property (argc, argv, value, output->scrn); - return TRUE; - } - } - - _secXbercPrintUsage (buf, sizeof (buf), argv[0]); - _secXbercSetReturnProperty (value, buf); - - return TRUE; -} diff --git a/src/debug/exynos_drmmode_dump.c b/src/debug/exynos_drmmode_dump.c new file mode 100644 index 0000000..66c227a --- /dev/null +++ b/src/debug/exynos_drmmode_dump.c @@ -0,0 +1,400 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/poll.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/poll.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <time.h> +#include <signal.h> + +#include "libdrm/drm.h" +#include "xf86drm.h" +#include "xf86drmMode.h" +#include <exynos/exynos_drm.h> +#include "exynos_display.h" +#include "exynos_util.h" + +typedef struct _DRMModeTest { + int tc_num; + int drm_fd; + + drmModeRes *resources; + drmModePlaneRes *plane_resources; + drmModeEncoder *encoders[3]; + drmModeConnector *connectors[3]; + drmModeCrtc *crtcs[3]; + drmModeFB *fbs[10]; + drmModePlane *planes[10]; + +} DRMModeTest; + +struct type_name { + int type; + char *name; +}; + +#define dump_resource(res, reply, len) if (res) reply = dump_##res(reply, len) + +static DRMModeTest test; + +struct type_name encoder_type_names[] = { + {DRM_MODE_ENCODER_NONE, "none"}, + {DRM_MODE_ENCODER_DAC, "DAC"}, + {DRM_MODE_ENCODER_TMDS, "TMDS"}, + {DRM_MODE_ENCODER_LVDS, "LVDS"}, + {DRM_MODE_ENCODER_TVDAC, "TVDAC"}, +}; + +struct type_name connector_status_names[] = { + {DRM_MODE_CONNECTED, "connected"}, + {DRM_MODE_DISCONNECTED, "disconnected"}, + {DRM_MODE_UNKNOWNCONNECTION, "unknown"}, +}; + +struct type_name connector_type_names[] = { + {DRM_MODE_CONNECTOR_Unknown, "unknown"}, + {DRM_MODE_CONNECTOR_VGA, "VGA"}, + {DRM_MODE_CONNECTOR_DVII, "DVI-I"}, + {DRM_MODE_CONNECTOR_DVID, "DVI-D"}, + {DRM_MODE_CONNECTOR_DVIA, "DVI-A"}, + {DRM_MODE_CONNECTOR_Composite, "composite"}, + {DRM_MODE_CONNECTOR_SVIDEO, "s-video"}, + {DRM_MODE_CONNECTOR_LVDS, "LVDS"}, + {DRM_MODE_CONNECTOR_Component, "component"}, + {DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN"}, + {DRM_MODE_CONNECTOR_DisplayPort, "displayport"}, + {DRM_MODE_CONNECTOR_HDMIA, "HDMI-A"}, + {DRM_MODE_CONNECTOR_HDMIB, "HDMI-B"}, + {DRM_MODE_CONNECTOR_TV, "TV"}, + {DRM_MODE_CONNECTOR_eDP, "embedded displayport"}, +}; + +extern char *exynosPlaneDump(char *reply, int *len); +extern char *exynosUtilDumpVideoBuffer(char *reply, int *len); + +static char * +encoder_type_str(int type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(encoder_type_names); i++) { + if (encoder_type_names[i].type == type) + return encoder_type_names[i].name; + } + return "(invalid)"; +} + +static char * +connector_status_str(int type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(connector_status_names); i++) { + if (connector_status_names[i].type == type) + return connector_status_names[i].name; + } + return "(invalid)"; +} + +static char * +connector_type_str(int type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(connector_type_names); i++) { + if (connector_type_names[i].type == type) + return connector_type_names[i].name; + } + return "(invalid)"; +} + +static char * +dump_encoders(char *reply, int *len) +{ + drmModeEncoder *encoder; + drmModeRes *resources = test.resources; + int i; + + XDBG_REPLY("Encoders:\n"); + XDBG_REPLY("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n"); + for (i = 0; i < resources->count_encoders; i++) { + encoder = test.encoders[i];; + + if (!encoder) { + XDBG_REPLY("could not get encoder %i\n", i); + continue; + } + XDBG_REPLY("%d\t%d\t%s\t0x%08x\t0x%08x\n", + encoder->encoder_id, + encoder->crtc_id, + encoder_type_str(encoder->encoder_type), + encoder->possible_crtcs, encoder->possible_clones); + } + + XDBG_REPLY("\n"); + + return reply; +} + +static char * +dump_mode(drmModeModeInfo * mode, char *reply, int *len) +{ + XDBG_REPLY(" %s %d %d %d %d %d %d %d %d %d\n", + mode->name, + mode->vrefresh, + mode->hdisplay, + mode->hsync_start, + mode->hsync_end, + mode->htotal, + mode->vdisplay, + mode->vsync_start, mode->vsync_end, mode->vtotal); + + return reply; +} + +static char * +dump_props(drmModeConnector * connector, char *reply, int *len) +{ + drmModePropertyPtr props; + int i; + + for (i = 0; i < connector->count_props; i++) { + props = drmModeGetProperty(test.drm_fd, connector->props[i]); + if (props == NULL) + continue; + XDBG_REPLY("\t%s, flags %d\n", props->name, props->flags); + drmModeFreeProperty(props); + } + + return reply; +} + +static char * +dump_connectors(char *reply, int *len) +{ + drmModeConnector *connector; + drmModeRes *resources = test.resources; + int i, j; + + XDBG_REPLY("Connectors:\n"); + XDBG_REPLY("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n"); + for (i = 0; i < resources->count_connectors; i++) { + connector = test.connectors[i]; + + if (!connector) { + XDBG_REPLY("could not get connector %i\n", i); + continue; + } + + XDBG_REPLY("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t", + connector->connector_id, + connector->encoder_id, + connector_status_str(connector->connection), + connector_type_str(connector->connector_type), + connector->mmWidth, connector->mmHeight, + connector->count_modes); + + for (j = 0; j < connector->count_encoders; j++) + XDBG_REPLY("%s%d", j > 0 ? ", " : "", connector->encoders[j]); + XDBG_REPLY("\n"); + + if (!connector->count_modes) + continue; + + XDBG_REPLY(" modes:\n"); + XDBG_REPLY(" name refresh (Hz) hdisp hss hse htot vdisp " + "vss vse vtot)\n"); + for (j = 0; j < connector->count_modes; j++) + reply = dump_mode(&connector->modes[j], reply, len); + + XDBG_REPLY(" props:\n"); + reply = dump_props(connector, reply, len); + } + XDBG_REPLY("\n"); + + return reply; +} + +static char * +dump_crtcs(char *reply, int *len) +{ + drmModeCrtc *crtc; + drmModeRes *resources = test.resources; + int i; + + XDBG_REPLY("CRTCs:\n"); + XDBG_REPLY("id\tfb\tpos\tsize\n"); + for (i = 0; i < resources->count_crtcs; i++) { + crtc = test.crtcs[i]; + + if (!crtc) { + XDBG_REPLY("could not get crtc %i\n", i); + continue; + } + XDBG_REPLY("%d\t%d\t(%d,%d)\t(%dx%d)\n", + crtc->crtc_id, + crtc->buffer_id, + crtc->x, crtc->y, crtc->width, crtc->height); + reply = dump_mode(&crtc->mode, reply, len); + } + XDBG_REPLY("\n"); + + return reply; +} + +static char * +dump_framebuffers(char *reply, int *len) +{ + drmModeFB *fb; + drmModeRes *resources = test.resources; + int i; + + XDBG_REPLY("Frame buffers:\n"); + XDBG_REPLY("id\tsize\tpitch\n"); + for (i = 0; i < resources->count_fbs; i++) { + fb = test.fbs[i]; + + if (!fb) { + XDBG_REPLY("could not get fb %i\n", i); + continue; + } + XDBG_REPLY("%u\t(%ux%u)\t%u\n", + fb->fb_id, fb->width, fb->height, fb->pitch); + } + XDBG_REPLY("\n"); + + return reply; +} + +static char * +get_resources_all(char *reply, int *len) +{ + int i; + + /* get drm mode resources */ + test.resources = drmModeGetResources(test.drm_fd); + if (!test.resources) { + XDBG_REPLY("drmModeGetResources failed: %s\n", strerror(errno)); + return reply; + } + + /* get drm mode encoder */ + for (i = 0; i < test.resources->count_encoders; i++) { + test.encoders[i] = + drmModeGetEncoder(test.drm_fd, test.resources->encoders[i]); + if (!test.encoders[i]) { + XDBG_REPLY("fail to get encoder %i; %s\n", + test.resources->encoders[i], strerror(errno)); + continue; + } + } + + /* get drm mode connector */ + for (i = 0; i < test.resources->count_connectors; i++) { + test.connectors[i] = + drmModeGetConnector(test.drm_fd, test.resources->connectors[i]); + if (!test.connectors[i]) { + XDBG_REPLY("fail to get connector %i; %s\n", + test.resources->connectors[i], strerror(errno)); + continue; + } + } + + /* get drm mode crtc */ + for (i = 0; i < test.resources->count_crtcs; i++) { + test.crtcs[i] = drmModeGetCrtc(test.drm_fd, test.resources->crtcs[i]); + if (!test.crtcs[i]) { + XDBG_REPLY("fail to get crtc %i; %s\n", + test.resources->crtcs[i], strerror(errno)); + continue; + } + } + + /* drm mode fb */ + for (i = 0; i < test.resources->count_fbs; i++) { + test.fbs[i] = drmModeGetFB(test.drm_fd, test.resources->fbs[i]); + if (!test.fbs[i]) { + XDBG_REPLY("fail to get fb %i; %s\n", + test.resources->fbs[i], strerror(errno)); + continue; + } + } + + return reply; +} + +static void +free_resources_all() +{ + int i; + + if (test.resources) { + /* free drm mode fbs */ + for (i = 0; i < test.resources->count_fbs; i++) + if (test.fbs[i]) { + drmModeFreeFB(test.fbs[i]); + test.fbs[i] = NULL; + } + + /* free drm mode crtcs */ + for (i = 0; i < test.resources->count_crtcs; i++) + if (test.crtcs[i]) { + drmModeFreeCrtc(test.crtcs[i]); + test.crtcs[i] = NULL; + } + + /* free drm mode connectors */ + for (i = 0; i < test.resources->count_connectors; i++) + if (test.connectors[i]) { + drmModeFreeConnector(test.connectors[i]); + test.connectors[i] = NULL; + } + + /* free drm mode encoders */ + for (i = 0; i < test.resources->count_encoders; i++) + if (test.encoders[i]) { + drmModeFreeEncoder(test.encoders[i]); + test.encoders[i] = NULL; + } + + /* free drm mode resources */ + drmModeFreeResources(test.resources); + test.resources = NULL; + } +} + +void +exynos_drmmode_dump(int drm_fd, char *reply, int *len) +{ + int encoders, connectors, crtcs, modes, framebuffers; + + encoders = connectors = crtcs = modes = framebuffers = 1; + + test.drm_fd = drm_fd; + + get_resources_all(reply, len); + dump_resource(encoders, reply, len); + dump_resource(connectors, reply, len); + dump_resource(crtcs, reply, len); + dump_resource(framebuffers, reply, len); + + reply = exynosPlaneDump(reply, len); + reply = exynosUtilDumpVideoBuffer(reply, len); + + free_resources_all(); + +} diff --git a/src/debug/sec_drmmode_dump.h b/src/debug/exynos_drmmode_dump.h index b1493a9..9c9871a 100644 --- a/src/debug/sec_drmmode_dump.h +++ b/src/debug/exynos_drmmode_dump.h @@ -31,6 +31,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef __SEC_DRMMODE_DUMP_H_ #define __SEC_DRMMODE_DUMP_H_ -void sec_drmmode_dump (int drm_fd, char *reply, int *len); +void exynos_drmmode_dump(int drm_fd, char *reply, int *len); #endif diff --git a/src/debug/sec_drmmode_dump.c b/src/debug/sec_drmmode_dump.c deleted file mode 100644 index f53ebd8..0000000 --- a/src/debug/sec_drmmode_dump.c +++ /dev/null @@ -1,422 +0,0 @@ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <sys/poll.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/poll.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <time.h> -#include <signal.h> - -#include "libdrm/drm.h" -#include "xf86drm.h" -#include "xf86drmMode.h" -#include "exynos_drm.h" -#include "sec_display.h" -#include "sec_util.h" - -typedef struct _DRMModeTest -{ - int tc_num; - int drm_fd; - - drmModeRes *resources; - drmModePlaneRes *plane_resources; - drmModeEncoder *encoders[3]; - drmModeConnector *connectors[3]; - drmModeCrtc *crtcs[3]; - drmModeFB *fbs[10]; - drmModePlane *planes[10]; - -} DRMModeTest; - -struct type_name -{ - int type; - char *name; -}; - -#define dump_resource(res, reply, len) if (res) reply = dump_##res(reply, len) - -static DRMModeTest test; - -struct type_name encoder_type_names[] = -{ - { DRM_MODE_ENCODER_NONE, "none" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, -}; - -struct type_name connector_status_names[] = -{ - { DRM_MODE_CONNECTED, "connected" }, - { DRM_MODE_DISCONNECTED, "disconnected" }, - { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, -}; - -struct type_name connector_type_names[] = -{ - { DRM_MODE_CONNECTOR_Unknown, "unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "displayport" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, - { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "embedded displayport" }, -}; - -extern char* secPlaneDump (char *reply, int *len); -extern char* secUtilDumpVideoBuffer (char *reply, int *len); - -static char * encoder_type_str (int type) -{ - int i; - for (i = 0; i < ARRAY_SIZE(encoder_type_names); i++) - { - if (encoder_type_names[i].type == type) - return encoder_type_names[i].name; - } - return "(invalid)"; -} - - -static char * connector_status_str (int type) -{ - int i; - for (i = 0; i < ARRAY_SIZE(connector_status_names); i++) - { - if (connector_status_names[i].type == type) - return connector_status_names[i].name; - } - return "(invalid)"; -} - -static char * connector_type_str (int type) -{ - int i; - for (i = 0; i < ARRAY_SIZE(connector_type_names); i++) - { - if (connector_type_names[i].type == type) - return connector_type_names[i].name; - } - return "(invalid)"; -} - -static char* dump_encoders(char *reply, int *len) -{ - drmModeEncoder *encoder; - drmModeRes *resources = test.resources; - int i; - - XDBG_REPLY ("Encoders:\n"); - XDBG_REPLY ("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n"); - for (i = 0; i < resources->count_encoders; i++) - { - encoder = test.encoders[i];; - - if (!encoder) - { - XDBG_REPLY ("could not get encoder %i\n", i); - continue; - } - XDBG_REPLY ("%d\t%d\t%s\t0x%08x\t0x%08x\n", - encoder->encoder_id, - encoder->crtc_id, - encoder_type_str(encoder->encoder_type), - encoder->possible_crtcs, - encoder->possible_clones); - } - - XDBG_REPLY ("\n"); - - return reply; -} - -static char* dump_mode(drmModeModeInfo *mode, char *reply, int *len) -{ - XDBG_REPLY (" %s %d %d %d %d %d %d %d %d %d\n", - mode->name, - mode->vrefresh, - mode->hdisplay, - mode->hsync_start, - mode->hsync_end, - mode->htotal, - mode->vdisplay, - mode->vsync_start, - mode->vsync_end, - mode->vtotal); - - return reply; -} - -static char* -dump_props(drmModeConnector *connector, char *reply, int *len) -{ - drmModePropertyPtr props; - int i; - - for (i = 0; i < connector->count_props; i++) - { - props = drmModeGetProperty(test.drm_fd, connector->props[i]); - if (props == NULL) - continue; - XDBG_REPLY ("\t%s, flags %d\n", props->name, props->flags); - drmModeFreeProperty(props); - } - - return reply; -} - -static char* dump_connectors(char *reply, int *len) -{ - drmModeConnector *connector; - drmModeRes *resources = test.resources; - int i, j; - - XDBG_REPLY ("Connectors:\n"); - XDBG_REPLY ("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n"); - for (i = 0; i < resources->count_connectors; i++) - { - connector = test.connectors[i]; - - if (!connector) - { - XDBG_REPLY ("could not get connector %i\n", i); - continue; - } - - XDBG_REPLY ("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t", - connector->connector_id, - connector->encoder_id, - connector_status_str(connector->connection), - connector_type_str(connector->connector_type), - connector->mmWidth, connector->mmHeight, - connector->count_modes); - - for (j = 0; j < connector->count_encoders; j++) - XDBG_REPLY ("%s%d", j > 0 ? ", " : "", connector->encoders[j]); - XDBG_REPLY ("\n"); - - if (!connector->count_modes) - continue; - - XDBG_REPLY (" modes:\n"); - XDBG_REPLY (" name refresh (Hz) hdisp hss hse htot vdisp " - "vss vse vtot)\n"); - for (j = 0; j < connector->count_modes; j++) - reply = dump_mode(&connector->modes[j], reply, len); - - XDBG_REPLY (" props:\n"); - reply = dump_props(connector, reply, len); - } - XDBG_REPLY ("\n"); - - return reply; -} - -static char* dump_crtcs(char *reply, int *len) -{ - drmModeCrtc *crtc; - drmModeRes *resources = test.resources; - int i; - - XDBG_REPLY ("CRTCs:\n"); - XDBG_REPLY ("id\tfb\tpos\tsize\n"); - for (i = 0; i < resources->count_crtcs; i++) - { - crtc = test.crtcs[i]; - - if (!crtc) - { - XDBG_REPLY ("could not get crtc %i\n", i); - continue; - } - XDBG_REPLY ("%d\t%d\t(%d,%d)\t(%dx%d)\n", - crtc->crtc_id, - crtc->buffer_id, - crtc->x, crtc->y, - crtc->width, crtc->height); - reply = dump_mode(&crtc->mode, reply, len); - } - XDBG_REPLY ("\n"); - - return reply; -} - -static char* dump_framebuffers(char *reply, int *len) -{ - drmModeFB *fb; - drmModeRes *resources = test.resources; - int i; - - XDBG_REPLY ("Frame buffers:\n"); - XDBG_REPLY ("id\tsize\tpitch\n"); - for (i = 0; i < resources->count_fbs; i++) - { - fb = test.fbs[i]; - - if (!fb) - { - XDBG_REPLY ("could not get fb %i\n", i); - continue; - } - XDBG_REPLY ("%u\t(%ux%u)\t%u\n", - fb->fb_id, - fb->width, fb->height, - fb->pitch); - } - XDBG_REPLY ("\n"); - - return reply; -} - -static char* get_resources_all (char *reply, int *len) -{ - int i; - - /* get drm mode resources */ - test.resources = drmModeGetResources (test.drm_fd); - if (!test.resources) - { - XDBG_REPLY ("drmModeGetResources failed: %s\n", strerror(errno)); - return reply; - } - - /* get drm mode encoder */ - for (i = 0; i < test.resources->count_encoders; i++) - { - test.encoders[i] = drmModeGetEncoder (test.drm_fd, test.resources->encoders[i]); - if (!test.encoders[i]) - { - XDBG_REPLY ("fail to get encoder %i; %s\n", - test.resources->encoders[i], strerror(errno)); - continue; - } - } - - /* get drm mode connector */ - for (i = 0; i < test.resources->count_connectors; i++) - { - test.connectors[i] = drmModeGetConnector (test.drm_fd, test.resources->connectors[i]); - if (!test.connectors[i]) - { - XDBG_REPLY ("fail to get connector %i; %s\n", - test.resources->connectors[i], strerror(errno)); - continue; - } - } - - /* get drm mode crtc */ - for (i = 0; i < test.resources->count_crtcs; i++) - { - test.crtcs[i] = drmModeGetCrtc (test.drm_fd, test.resources->crtcs[i]); - if (!test.crtcs[i]) - { - XDBG_REPLY ("fail to get crtc %i; %s\n", - test.resources->crtcs[i], strerror(errno)); - continue; - } - } - - /* drm mode fb */ - for (i = 0; i < test.resources->count_fbs; i++) - { - test.fbs[i] = drmModeGetFB (test.drm_fd, test.resources->fbs[i]); - if (!test.fbs[i]) - { - XDBG_REPLY ("fail to get fb %i; %s\n", - test.resources->fbs[i], strerror(errno)); - continue; - } - } - - return reply; -} - -static void free_resources_all () -{ - int i; - - if (test.resources) - { - /* free drm mode fbs */ - for (i = 0; i < test.resources->count_fbs; i++) - if (test.fbs[i]) - { - drmModeFreeFB (test.fbs[i]); - test.fbs[i] = NULL; - } - - /* free drm mode crtcs */ - for (i = 0; i < test.resources->count_crtcs; i++) - if (test.crtcs[i]) - { - drmModeFreeCrtc (test.crtcs[i]); - test.crtcs[i] = NULL; - } - - /* free drm mode connectors */ - for (i = 0; i < test.resources->count_connectors; i++) - if (test.connectors[i]) - { - drmModeFreeConnector (test.connectors[i]); - test.connectors[i] = NULL; - } - - /* free drm mode encoders */ - for (i = 0; i < test.resources->count_encoders; i++) - if (test.encoders[i]) - { - drmModeFreeEncoder (test.encoders[i]); - test.encoders[i] = NULL; - } - - /* free drm mode resources */ - drmModeFreeResources (test.resources); - test.resources = NULL; - } -} - -void sec_drmmode_dump (int drm_fd, char *reply, int *len) -{ - int encoders, connectors, crtcs, modes, framebuffers; - - encoders = connectors = crtcs = modes = framebuffers = 1; - - test.drm_fd = drm_fd; - - get_resources_all (reply, len); - dump_resource(encoders, reply, len); - dump_resource(connectors, reply, len); - dump_resource(crtcs, reply, len); - dump_resource(framebuffers, reply, len); - - reply = secPlaneDump (reply, len); - reply = secUtilDumpVideoBuffer (reply, len); - - free_resources_all (); - -} diff --git a/src/exynos.c b/src/exynos.c new file mode 100755 index 0000000..608a843 --- /dev/null +++ b/src/exynos.c @@ -0,0 +1,1933 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 <xorg-server.h> +#include <sys/stat.h> +#include <fcntl.h> + +/* all driver need this */ +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "fb.h" +#include "mipointer.h" +#include "micmap.h" +#include "colormapst.h" +#include "xf86cmap.h" +#include "xf86xv.h" +#include "xf86Crtc.h" +#include "exynos.h" +#include "exynos_display.h" +#include "exynos_plane.h" +#include "exynos_accel.h" +#include "exynos_xberc.h" +#include "exynos_util.h" +#include "exynos_wb.h" +#include "exynos_crtc.h" +#include <tbm_bufmgr.h> +#include "fimg2d.h" +#include "exynos_output.h" +#include "exynos_layer_manager.h" + +#define OPTION_FLIP_BUFFERS 0 +#define EXYNOS_DRM_NAME "exynos" + +/* prototypes */ +static const OptionInfoRec *EXYNOSAvailableOptions(int chipid, int busid); +static void EXYNOSIdentify(int flags); +static Bool EXYNOSProbe(DriverPtr pDrv, int flags); +static Bool EXYNOSPreInit(ScrnInfoPtr pScrn, int flags); +static Bool EXYNOSScreenInit(ScreenPtr pScreen, int argc, char **argv); +static Bool EXYNOSSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +static void EXYNOSAdjustFrame(ScrnInfoPtr pScrn, int x, int y); +static Bool EXYNOSEnterVT(ScrnInfoPtr pScrn); +static void EXYNOSLeaveVT(ScrnInfoPtr pScrn); +static ModeStatus EXYNOSValidMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, + Bool verbose, int flags); +static Bool EXYNOSCloseScreen(ScreenPtr pScreen); +static Bool EXYNOSCreateScreenResources(ScreenPtr pScreen); + +#if HAVE_UDEV +static void EXYNOSUdevEventsHandler(int fd, void *closure); +#endif + +/* This DriverRec must be defined in the driver for Xserver to load this driver */ +_X_EXPORT DriverRec EXYNOS = { + EXYNOS_VERSION, + EXYNOS_DRIVER_NAME, + EXYNOSIdentify, + EXYNOSProbe, + EXYNOSAvailableOptions, + NULL, + 0, + NULL, +}; + +/* Supported "chipsets" */ +static SymTabRec EXYNOSChipsets[] = { + {0, "exynos"}, + {-1, NULL} +}; + +/* Supported options */ +typedef enum { + OPTION_DRI2, + OPTION_EXA, + OPTION_SWEXA, + OPTION_ROTATE, + OPTION_SNAPSHOT, + OPTION_WB, +#if OPTION_FLIP_BUFFERS + OPTION_FLIPBUFS, +#endif + OPTION_CACHABLE, + OPTION_SCANOUT, + OPTION_ACCEL2D, + OPTION_PRESENT, + OPTION_DRI3, + OPTION_PARTIAL_UPDATE, + OPTION_HWC, + OPTION_HWA, + OPTION_SET_PLANE, + OPTION_PAGE_FLIP +} EXYNOSOpts; + +static const OptionInfoRec EXYNOSOptions[] = { + {OPTION_DRI2, "dri2", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_EXA, "exa", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SWEXA, "sw_exa", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_ROTATE, "rotate", OPTV_STRING, {0}, FALSE}, + {OPTION_SNAPSHOT, "snapshot", OPTV_STRING, {0}, FALSE}, + {OPTION_WB, "wb", OPTV_BOOLEAN, {0}, FALSE}, +#if OPTION_FLIP_BUFFERS + {OPTION_FLIPBUFS, "flip_bufs", OPTV_INTEGER, {0}, 3}, +#endif + {OPTION_CACHABLE, "cachable", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SCANOUT, "scanout", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_ACCEL2D, "accel_2d", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_PRESENT, "present", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DRI3, "dri3", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_PARTIAL_UPDATE, "partial_update", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_HWC, "hwc", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_HWA, "hwa", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SET_PLANE, "set_plane", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_PAGE_FLIP, "flip", OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, OPTV_NONE, {0}, FALSE} +}; + +/* -------------------------------------------------------------------- */ +#ifdef XFree86LOADER + +MODULESETUPPROTO(EXYNOSSetup); + +static XF86ModuleVersionInfo EXYNOSVersRec = { + "exynos", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, + PACKAGE_VERSION_MINOR, + PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + NULL, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData exynosModuleData = + { &EXYNOSVersRec, EXYNOSSetup, NULL }; + +pointer +EXYNOSSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&EXYNOS, module, HaveDriverFuncs); + return (pointer) 1; + } + else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ +/* -------------------------------------------------------------------- */ + +static int +_exynosOpenDRM(void) +{ + int fd = -1; + + fd = drmOpen(EXYNOS_DRM_NAME, NULL); +#ifdef HAVE_UDEV + if (fd < 0) { + struct udev *udev; + struct udev_enumerate *e; + struct udev_list_entry *entry; + struct udev_device *device, *drm_device, *device_parent; + const char *filename; + + xf86Msg(X_WARNING, "[DRM] Cannot open drm device.. search by udev\n"); + udev = udev_new(); + if (!udev) { + xf86Msg(X_ERROR, "[DRM] fail to initialize udev context\n"); + goto close_l; + } + /* Will try to find sys path /exynos-drm/drm/card0 */ + 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)) { + device = udev_device_new_from_syspath(udev_enumerate_get_udev(e), + udev_list_entry_get_name + (entry)); + device_parent = udev_device_get_parent(device); + /* Not need unref device_parent. device_parent and device have same refcnt */ + if (device_parent) { + if (strcmp(udev_device_get_sysname(device_parent), "exynos-drm") + == 0) { + drm_device = device; + xf86Msg(X_INFO, "Found drm device: '%s' (%s)\n", + udev_device_get_syspath(drm_device), + udev_device_get_sysname(device_parent)); + break; + } + } + udev_device_unref(device); + } + + if (drm_device == NULL) { + xf86Msg(X_ERROR, "[DRM] fail to find drm device\n"); + udev_enumerate_unref(e); + udev_unref(udev); + goto close_l; + } + + filename = udev_device_get_devnode(drm_device); + + fd = open(filename, O_RDWR | O_CLOEXEC); + if (fd < 0) { + xf86Msg(X_ERROR, "[DRM] Cannot open drm device(%s)\n", filename); + } + udev_device_unref(drm_device); + udev_enumerate_unref(e); + udev_unref(udev); + } +#endif + close_l: + return fd; +} + +static void +_exynosCloseDRM(int fd) +{ + if (fd < 0) + return; + if (drmClose(fd) < 0) { + xf86Msg(X_ERROR, "[DRM] Cannot close drm device fd=%d\n", fd); + } +} + +/* + * Probing the device with the device node, this probing depend on the specific hw. + * This function just verify whether the display hw is avaliable or not. + */ +static Bool +_exynosHwProbe(struct pci_device *pPci, char *device, char **namep) +{ + int fd = -1; + + fd = _exynosOpenDRM(); + if (fd < 0) { + return FALSE; + } + + _exynosCloseDRM(fd); + return TRUE; +} + +static tbm_bufmgr +_exynosInitBufmgr(int drm_fd, void *arg) +{ + tbm_bufmgr bufmgr = NULL; + + /* get buffer manager */ + setenv("BUFMGR_LOCK_TYPE", "once", 1); + setenv("BUFMGR_MAP_CACHE", "true", 1); + bufmgr = tbm_bufmgr_init(drm_fd); + + if (bufmgr == NULL) + return NULL; + + return bufmgr; +} + +static void +_exynosDeInitBufmgr(tbm_bufmgr bufmgr) +{ + if (bufmgr) + tbm_bufmgr_deinit(bufmgr); +} + +/* open drm */ +static Bool +_openDrmMaster(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int ret; + + /* open drm */ + pExynos->drm_fd = _exynosOpenDRM(); + if (pExynos->drm_fd < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[DRM] Cannot open drm device\n"); + goto fail_to_open_drm_master; + } + + pExynos->drm_device_name = drmGetDeviceNameFromFd(pExynos->drm_fd); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "[DRM] Succeed get drm device name:%s\n", + pExynos->drm_device_name); + + /* enable drm vblank */ + ret = drmCtlInstHandler(pExynos->drm_fd, 217); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[DRM] Fail to enable drm VBlank(%d)\n", ret); + goto fail_to_open_drm_master; + } + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "[DRM] Enable drm VBlank(%d)\n", ret); + + /* initialize drm bufmgr */ + pExynos->tbm_bufmgr = _exynosInitBufmgr(pExynos->drm_fd, NULL); + if (pExynos->tbm_bufmgr == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[DRM] Error : bufmgr initialization failed\n"); + goto fail_to_open_drm_master; + } + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "[DRM] Enable buffer manager\n"); + + return TRUE; + + fail_to_open_drm_master: + + if (pExynos->tbm_bufmgr) { + _exynosDeInitBufmgr(pExynos->tbm_bufmgr); + pExynos->tbm_bufmgr = NULL; + } + + if (pExynos->drm_device_name) { + free(pExynos->drm_device_name); + pExynos->drm_device_name = NULL; + } + + if (pExynos->drm_fd >= 0) { + _exynosCloseDRM(pExynos->drm_fd); + pExynos->drm_fd = -1; + } + + return FALSE; +} + +/* close drm */ +static void +_closeDrmMaster(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (pExynos->tbm_bufmgr) { + _exynosDeInitBufmgr(pExynos->tbm_bufmgr); + pExynos->tbm_bufmgr = NULL; + } + + if (pExynos->drm_device_name) { + free(pExynos->drm_device_name); + pExynos->drm_device_name = NULL; + } + + if (pExynos->drm_fd >= 0) { + _exynosCloseDRM(pExynos->drm_fd); + pExynos->drm_fd = -1; + } +} + +/* + * Initialize the device Probing the device with the device node, + * this probing depend on the specific hw. + * This function just verify whether the display hw is avaliable or not. + */ +static Bool +_exynosHwInit(ScrnInfoPtr pScrn, struct pci_device *pPci, char *device) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + /* init drm master */ + if (_openDrmMaster(pScrn) == TRUE) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRM BLANK is enabled\n"); + else + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRM BLANK is disabled\n"); + + if (g2d_init(pExynos->drm_fd)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "G2D is enabled\n"); + pExynos->is_accel_2d = TRUE; + } + else + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "G2D is disabled\n"); +#ifdef NO_CRTC_MODE + /*** Temporary disable G2D acceleration for using PIXMAN ***/ + pExynos->is_accel_2d = FALSE; +#endif + return TRUE; +} + +/* SigHook */ +OsSigWrapperPtr old_sig_wrapper; +int +_exynosOsSigWrapper(int sig) +{ + XDBG_KLOG(MSEC, "Catch SIG: %d\n", sig); + + return old_sig_wrapper(sig); /*Contiue */ +} + +/* + * DeInitialize the hw + */ +static void +_exynosHwDeinit(ScrnInfoPtr pScrn) +{ + g2d_fini(); + + /* deinit drm master */ + _closeDrmMaster(pScrn); + + return; +} + +static Bool +_allocScrnPrivRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = calloc(sizeof(EXYNOSRec), 1); + if (!pScrn->driverPrivate) + return FALSE; + + return TRUE; +} + +static void +_freeScrnPrivRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +/* + * Check the driver option. + * Set the option flags to the driver private + */ +static void +_checkDriverOptions(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + const char *s; + int flip_bufs = 3; + + /* exa */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_EXA, TRUE)) + pExynos->is_exa = TRUE; + + /* sw exa */ + if (pExynos->is_exa) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_SWEXA, TRUE)) + pExynos->is_sw_exa = TRUE; + } + + /* dri2 */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_DRI2, FALSE)) { + pExynos->is_dri2 = TRUE; + + /* number of the flip buffers */ +#if OPTION_FLIP_BUFFERS + if (xf86GetOptValInteger(pExynos->Options, OPTION_FLIPBUFS, &flip_bufs)) + pExynos->flip_bufs = flip_bufs; + else +#endif + { + /* default is 3 */ + flip_bufs = 3; + pExynos->flip_bufs = flip_bufs; + } + } + +#ifdef HAVE_DRI3_PRESENT_H + /* present */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_PRESENT, FALSE)) { + pExynos->is_present = TRUE; + } + + /* dri3 */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_DRI3, FALSE)) { + pExynos->is_dri3 = TRUE; + } +#endif + + /* rotate */ + pExynos->rotate = RR_Rotate_0; + if ((s = xf86GetOptValString(pExynos->Options, OPTION_ROTATE))) { + if (!xf86NameCmp(s, "CW")) { + pExynos->rotate = RR_Rotate_90; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "rotating screen clockwise\n"); + } + else if (!xf86NameCmp(s, "CCW")) { + pExynos->rotate = RR_Rotate_270; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "rotating screen counter-clockwise\n"); + } + else if (!xf86NameCmp(s, "UD")) { + pExynos->rotate = RR_Rotate_180; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "rotating screen upside-down\n"); + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not valid option", + s); + } + } + + /* wb */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_WB, FALSE)) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_WB, TRUE)) + pExynos->is_wb_clone = TRUE; + } + + /* cachable */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_CACHABLE, FALSE)) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_CACHABLE, TRUE)) { + pExynos->cachable = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use cachable buffer.\n"); + } + } + + /* scanout */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_SCANOUT, FALSE)) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_SCANOUT, TRUE)) { + pExynos->scanout = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use scanout buffer.\n"); + } + } + + /* hw_2d */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_ACCEL2D, FALSE)) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_ACCEL2D, TRUE)) { + pExynos->is_accel_2d = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use 2d accelerator.\n"); + } + } + + /* use_partial_update */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_PARTIAL_UPDATE, FALSE)) { + if (xf86ReturnOptValBool(pExynos->Options, OPTION_PARTIAL_UPDATE, TRUE)) { + pExynos->use_partial_update = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use partial update.\n"); + } + } + + /* page_flip */ + pExynos->use_flip = TRUE; + if (!xf86ReturnOptValBool(pExynos->Options, OPTION_PAGE_FLIP, TRUE)) { + pExynos->use_flip = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Page flip DISABLE\n"); + } + + /* HWC default */ + pExynos->use_hwc = FALSE; + /* default value without HWC */ + pExynos->use_setplane = FALSE; +#ifdef HAVE_HWC_H + if (xf86ReturnOptValBool(pExynos->Options, OPTION_HWC, FALSE)) { + pExynos->use_hwc = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use HWC extension.\n"); + /* default value with HWC */ + pExynos->use_setplane = TRUE; + } +#endif + +#ifdef HAVE_HWA_H + if (xf86ReturnOptValBool(pExynos->Options, OPTION_HWA, FALSE)) { + pExynos->use_hwa = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Use HWA extension.\n"); + } +#endif + + /* set_plane */ + if (xf86ReturnOptValBool(pExynos->Options, OPTION_SET_PLANE, FALSE)) { + pExynos->use_setplane = TRUE; + } + + if (pExynos->use_flip) { + if (pExynos->use_setplane) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Page flip using plane\n"); + else + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Page flip using crtc (drmModePegeFlip())\n"); + } + +} + +#if HAVE_UDEV +static void +_exynosUdevInit(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + struct udev *u; + struct udev_monitor *mon; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "hotplug detection\n"); + + u = udev_new(); + if (!u) + return; + + mon = udev_monitor_new_from_netlink(u, "udev"); + if (!mon) { + udev_unref(u); + return; + } + + if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") + > 0 || udev_monitor_enable_receiving(mon) < 0) { + udev_monitor_unref(mon); + udev_unref(u); + return; + } + + pExynos->uevent_handler = + xf86AddGeneralHandler(udev_monitor_get_fd(mon), EXYNOSUdevEventsHandler, + pScrn); + if (!pExynos->uevent_handler) { + udev_monitor_unref(mon); + udev_unref(u); + return; + } + + pExynos->uevent_monitor = mon; +} + +static void +_exynosUdevDeinit(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (pExynos->uevent_handler) { + struct udev *u = udev_monitor_get_udev(pExynos->uevent_monitor); + + udev_monitor_unref(pExynos->uevent_monitor); + udev_unref(u); + pExynos->uevent_handler = NULL; + pExynos->uevent_monitor = NULL; + } + +} + +static Bool +EXYNOSSaveScreen(ScreenPtr pScreen, int mode) +{ + /* dummpy save screen */ + return TRUE; +} + +static void +EXYNOSUdevEventsHandler(int fd, void *closure) +{ + ScrnInfoPtr pScrn = closure; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + struct udev_device *dev; + const char *hotplug; + struct stat s; + dev_t udev_devnum; + int ret; + + dev = udev_monitor_receive_device(pExynos->uevent_monitor); + if (!dev) + return; + + udev_devnum = udev_device_get_devnum(dev); + + ret = fstat(pExynos->drm_fd, &s); + if (ret == -1) + return; + + /* + * Check to make sure this event is directed at our + * device (by comparing dev_t values), then make + * sure it's a hotplug event (HOTPLUG=1) + */ + hotplug = udev_device_get_property_value(dev, "HOTPLUG"); + + if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 && + hotplug && atoi(hotplug) == 1) { + XDBG_INFO(MSEC, "EXYNOS-UDEV: HotPlug\n"); + exynosOutputDrmUpdate(pScrn); + RRGetInfo(xf86ScrnToScreen(pScrn), TRUE); +#ifdef NO_CRTC_MODE +// exynosDisplayChangeMode(pScrn); +#endif + } + + udev_device_unref(dev); +} +#endif /* UDEV_HAVE */ + +static const OptionInfoRec * +EXYNOSAvailableOptions(int chipid, int busid) +{ + return EXYNOSOptions; +} + +static void +EXYNOSIdentify(int flags) +{ + xf86PrintChipsets(EXYNOS_NAME, "driver for Exynos Chipsets", + EXYNOSChipsets); +} + +/* The purpose of this function is to identify all instances of hardware supported + * by the driver. The probe must find the active device exynostions that match the driver + * by calling xf86MatchDevice(). + */ +static Bool +EXYNOSProbe(DriverPtr pDrv, int flags) +{ + int i; + ScrnInfoPtr pScrn; + GDevPtr *ppDevSections = NULL; + int numDevSections; + int entity; + Bool foundScreen = FALSE; + + /* check the drm mode setting */ + if (!_exynosHwProbe(NULL, NULL, NULL)) { + return FALSE; + } + + numDevSections = xf86MatchDevice(EXYNOS_DRIVER_NAME, &ppDevSections); + + if ((flags & PROBE_DETECT) && (numDevSections <= 0)) { + numDevSections = 1; + } + + for (i = 0; i < numDevSections; i++) { + + if (flags & PROBE_DETECT) { + xf86AddBusDeviceToConfigure(EXYNOS_DRIVER_NAME, BUS_NONE, NULL, i); + foundScreen = TRUE; + continue; + } + + pScrn = xf86AllocateScreen(pDrv, flags); + + if (ppDevSections) { + entity = xf86ClaimNoSlot(pDrv, 0, ppDevSections[i], TRUE); + xf86AddEntityToScreen(pScrn, entity); + } + + if (pScrn) { + foundScreen = TRUE; + + pScrn->driverVersion = EXYNOS_VERSION; + pScrn->driverName = EXYNOS_DRIVER_NAME; + pScrn->name = EXYNOS_NAME; + pScrn->Probe = EXYNOSProbe; + pScrn->PreInit = EXYNOSPreInit; + pScrn->ScreenInit = EXYNOSScreenInit; + pScrn->SwitchMode = EXYNOSSwitchMode; + pScrn->AdjustFrame = EXYNOSAdjustFrame; + pScrn->EnterVT = EXYNOSEnterVT; + pScrn->LeaveVT = EXYNOSLeaveVT; + pScrn->ValidMode = EXYNOSValidMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "using drm mode setting device\n"); + } + } + if (ppDevSections) { + free(ppDevSections); + } + + return foundScreen; +} + +/* + * This is called before ScreenInit to probe the screen configuration. + * The main tasks to do in this funtion are probing, module loading, option handling, + * card mapping, and mode setting setup. + */ +static Bool +EXYNOSPreInit(ScrnInfoPtr pScrn, int flags) +{ + EXYNOSPtr pExynos; + Gamma defualt_gamma = { 0.0, 0.0, 0.0 }; + rgb default_weight = { 0, 0, 0 }; + int flag24; + + if (flags & PROBE_DETECT) + return FALSE; + + /* allocate private */ + if (!_allocScrnPrivRec(pScrn)) + return FALSE; + pExynos = EXYNOSPTR(pScrn); + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + pExynos->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + + /* initialize the hardware specifics */ + if (!_exynosHwInit(pScrn, NULL, NULL)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to initialize hardware\n"); + goto bail1; + } + + pScrn->displayWidth = 640; /*default width */ + pScrn->monitor = pScrn->confScreen->monitor; + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + + /* set the depth and the bpp to pScrn */ + flag24 = Support24bppFb | Support32bppFb; + if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flag24)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to find the depth\n"); + goto bail1; + } + xf86PrintDepthBpp(pScrn); /* just print out the depth and the bpp */ + + /* color weight */ + if (!xf86SetWeight(pScrn, default_weight, default_weight)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "fail to set the color weight of RGB\n"); + goto bail1; + } + + /* visual init, make a TrueColor, -1 */ + if (!xf86SetDefaultVisual(pScrn, -1)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "fail to initialize the default visual\n"); + goto bail1; + } + + /* Collect all the option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* + * Process the options based on the information EXYNOSOptions. + * The results are written to pExynos->Options. If all the options + * processing is done within this fuction a local variable "options" + * can be used instead of pExynos->Options + */ + if (!(pExynos->Options = malloc(sizeof(EXYNOSOptions)))) + goto bail1; + memcpy(pExynos->Options, EXYNOSOptions, sizeof(EXYNOSOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pExynos->pEnt->device->options, + pExynos->Options); + + /* Check with the driver options */ + _checkDriverOptions(pScrn); + + /* use a fake root pixmap when rotation angle is 90 or 270 */ + pExynos->fake_root = + ((pExynos->rotate & (RR_Rotate_90 | RR_Rotate_270)) != 0); + + /* drm mode init:: Set the Crtc, the default Output, and the current Mode */ + if (!exynosModePreInit(pScrn, pExynos->drm_fd)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "fail to initialize drm mode setting\n"); + goto bail1; + } + + /* set gamma */ + if (!xf86SetGamma(pScrn, defualt_gamma)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to set the gamma\n"); + goto bail1; + } +#ifdef NO_CRTC_MODE + if (pScrn->modes == NULL) { + pScrn->modes = xf86ModesAdd(pScrn->modes, + xf86CVTMode(pScrn->virtualX, + pScrn->virtualY, 60, 0, 0)); + } +#endif + pScrn->currentMode = pScrn->modes; + + pScrn->displayWidth = pScrn->virtualX; + xf86PrintModes(pScrn); /* just print the current mode */ + + /* set dpi */ + xf86SetDpi(pScrn, 0, 0); + + /* Load modules */ + if (!xf86LoadSubModule(pScrn, "fb")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to load fb module\n"); + goto bail1; + } + + if (!xf86LoadSubModule(pScrn, "exa")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to load exa module\n"); + goto bail1; + } + + if (!xf86LoadSubModule(pScrn, "dri2")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to load dri2 module\n"); + goto bail1; + } + + old_sig_wrapper = OsRegisterSigWrapper(_exynosOsSigWrapper); + return TRUE; + + bail1: + _freeScrnPrivRec(pScrn); + _exynosHwDeinit(pScrn); + return FALSE; +} + +static Bool +EXYNOSScreenInit(ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + VisualPtr visual; + int init_picture = 0; + EXYNOSFbPtr pFb = NULL; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Infomation of Visual is \n\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" + "\tmask: %x,%x,%x, offset: %d,%d,%d\n", + pScrn->bitsPerPixel, + pScrn->depth, + xf86GetVisualName(pScrn->defaultVisual), + (unsigned int) pScrn->mask.red, + (unsigned int) pScrn->mask.green, + (unsigned int) pScrn->mask.blue, + (int) pScrn->offset.red, + (int) pScrn->offset.green, (int) pScrn->offset.blue); +#ifdef LAYER_MANAGER + /* Init Layer manager */ + if (!exynosLayerMngInit(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Fail to initialize layer manager\n"); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[LYRM] Initialized layer manager\n"); +#endif + /* initialize the framebuffer */ + /* soolim :: think rotations */ + + pFb = exynosFbAllocate(pScrn, pScrn->virtualX, pScrn->virtualY); + if (!pFb) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "cannot allocate framebuffer\n"); + return FALSE; + } + pExynos->pFb = pFb; + + /* mi layer */ + miClearVisualTypes(); + if (!miSetVisualTypes + (pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "visual type setup failed for %d bits per pixel [1]\n", + pScrn->bitsPerPixel); + return FALSE; + } + + if (!miSetPixmapDepths()) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "pixmap depth setup failed\n"); + return FALSE; + } + + switch (pScrn->bitsPerPixel) { + case 16: + case 24: + case 32: + if (!fbScreenInit(pScreen, (void *) ROOT_FB_ADDR, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->virtualX, /*Pixel width for framebuffer */ + pScrn->bitsPerPixel)) + return FALSE; + + init_picture = 1; + + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "internal error: invalid number of bits per pixel (%d) encountered\n", + pScrn->bitsPerPixel); + break; + } + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* must be after RGB ordering fixed */ + if (init_picture && !fbPictureInit(pScreen, NULL, 0)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Render extension initialisation failed\n"); + } + + /* init the exa */ + if (pExynos->is_exa) { + if (!exynosExaInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EXA initialization failed\n"); + } + else { + /* init the dri2 */ + if (pExynos->is_dri2) { + if (!exynosDri2Init(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRI2 initialization failed\n"); + } + } + +#ifdef HAVE_DRI3_PRESENT_H + if (pExynos->is_present) { + if (!exynosPresentScreenInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Present initialization failed\n"); + } + } + + /* init the dri3 */ + if (pExynos->is_dri3) { + if (!exynosDri3ScreenInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRI3 initialization failed\n"); + } + } +#endif + } + } + +#ifdef HAVE_HWC_H + if (pExynos->use_hwc) { + if (!exynosHwcInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HWC initialization failed\n"); + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HWC initialization succeed\n"); + } + } +#endif + +#ifdef HAVE_HWA_H + if (pExynos->use_hwa) { + if (!exynosHwaInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HWA initialization failed\n"); + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HWA initialization succeed\n"); + } + } +#endif + + /* XVideo Initiailization here */ + if (!exynosVideoInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "XVideo extention initialization failed\n"); + + xf86SetBlackWhitePixels(pScreen); + xf86SetBackingStore(pScreen); + + /* use dummy hw_cursro instead of sw_cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); +#if 1 + if (!xf86_cursors_init(pScreen, EXYNOS_CURSOR_W, EXYNOS_CURSOR_H, + (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_ARGB))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + } +#endif + /* crtc init */ + if (!xf86CrtcScreenInit(pScreen)) + return FALSE; + + /* set the desire mode : set the mode to xf86crtc here */ + xf86SetDesiredModes(pScrn); + + /* colormap */ + if (!miCreateDefColormap(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "internal error: miCreateDefColormap failed \n"); + return FALSE; + } + + if (!xf86HandleColormaps(pScreen, 256, 8, exynosModeLoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR)) + return FALSE; + + /* dpms */ + xf86DPMSInit(pScreen, xf86DPMSSet, 0); + + /* screen saver */ + pScreen->SaveScreen = EXYNOSSaveScreen; + + exynosModeInit(pScrn); + + /* Wrap the current CloseScreen function */ + pExynos->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = EXYNOSCloseScreen; + + /* Wrap the current CloseScreen function */ + pExynos->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = EXYNOSCreateScreenResources; + +#if HAVE_UDEV + _exynosUdevInit(pScrn); +#endif + +#if 0 + /* Init Hooks for memory flush */ + exynosMemoryInstallHooks(); +#endif + +#if USE_XDBG + xDbgLogPListInit(pScreen); +#endif +#if 0 + xDbgLogSetLevel(MDRI2, 0); + xDbgLogSetLevel(MEXA, 0); + xDbgLogSetLevel(MLYRM, 0); +#endif +#ifdef NO_CRTC_MODE + pExynos->isCrtcOn = exynosCrtcCheckInUseAll(pScrn); +#endif + XDBG_KLOG(MSEC, "Init Screen\n"); + return TRUE; +} + +static Bool +EXYNOSSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + return xf86SetSingleMode(pScrn, pMode, RR_Rotate_0); +} + +static void +EXYNOSAdjustFrame(ScrnInfoPtr pScrn, int x, int y) +{ +} + +static Bool +EXYNOSEnterVT(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + xf86OutputPtr pOutput; + EXYNOSCrtcPrivPtr pCrtcPriv; + xf86CrtcConfigPtr pXf86CrtcConfig; + int ret; + int i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EnterVT::Hardware state at EnterVT:\n"); + + if (pExynos->drm_fd > 0) { + ret = drmSetMaster(pExynos->drm_fd); + if (ret) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EnterVT::failed to set drm_fd %d as master.\n", + pExynos->drm_fd); + } + + pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + for (i = 0; i < pXf86CrtcConfig->num_output; i++) { + pOutput = pXf86CrtcConfig->output[i]; + if (!strcmp(pOutput->name, "LVDS1") || !strcmp(pOutput->name, "HDMI1")) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EnterVT::Find %s Output:\n", + pOutput->name); + + pCrtcPriv = pOutput->crtc->driver_private; + + if (pCrtcPriv->bAccessibility || + pCrtcPriv->screen_rotate_degree > 0) { + tbm_bo src_bo = pCrtcPriv->front_bo; + tbm_bo dst_bo = pCrtcPriv->accessibility_back_bo; + + if (!exynosCrtcExecAccessibility(pOutput->crtc, src_bo, dst_bo)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EnterVT::Fail execute accessibility(output name, %s)\n", + pOutput->name); + } + } + + /* set current fb to crtc */ + if (!exynosCrtcApply(pOutput->crtc)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EnterVT::Fail crtc apply(output name, %s)\n", + pOutput->name); + } + return TRUE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EnterVT::failed to find Output.\n"); + + return TRUE; +} + +static void +EXYNOSLeaveVT(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int ret; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "LeaveVT::Hardware state at LeaveVT:\n"); + + if (pExynos->drm_fd > 0) { + ret = drmDropMaster(pExynos->drm_fd); + if (ret) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "LeaveVT::drmDropMaster failed for drmFD %d: %s\n", + pExynos->drm_fd, strerror(errno)); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "LeaveVT::drmFD dropped master.\n"); + } +} + +static ModeStatus +EXYNOSValidMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool verbose, + int flags) +{ + return MODE_OK; +} + +/** + * Adjust the screen pixmap for the current location of the front buffer. + * This is done at EnterVT when buffers are bound as long as the resources + * have already been created, but the first EnterVT happens before + * CreateScreenResources. + */ +static Bool +EXYNOSCreateScreenResources(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + pScreen->CreateScreenResources = pExynos->CreateScreenResources; + if (!(*pScreen->CreateScreenResources) (pScreen)) + return FALSE; + + /* + * [TODO]::::: + * create screen resources + * set the bo to the screen pixamp private here + * or create the shadow pixmap for the screen pixamp here + * or set the fake rotated screen infomation here. + */ + + return TRUE; +} + +static Bool +EXYNOSCloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + exynosWbDestroy(); + +#if HAVE_UDEV + _exynosUdevDeinit(pScrn); +#endif + + exynosHwcDeinit(pScreen); +#ifdef LAYER_MANAGER + exynosLayerMngDeInit(pScrn); +#endif + exynosVideoFini(pScreen); + exynosExaDeinit(pScreen); + exynosModeDeinit(pScrn); + if (pExynos->pFb) { + exynosFbFree(pExynos->pFb); + pExynos->pFb = NULL; + } + + _exynosHwDeinit(pScrn); + + pScrn->vtSema = FALSE; + + pScreen->CreateScreenResources = pExynos->CreateScreenResources; + pScreen->CloseScreen = pExynos->CloseScreen; + + XDBG_KLOG(MSEC, "Close Screen\n"); + return (*pScreen->CloseScreen) (pScreen); +} + +#define CONV_POINT_TO_KEY(x, y, key) key = (unsigned long)((((unsigned short)(x&0xFFFF)) << 16) | ((unsigned short)(y&0xFFFF ))) +#define CONT_KEY_TO_POINT(key, x, y) x = (unsigned short)((key&0xFFFF0000)>>16); y=(unsigned short)(key&0xFFFF) + +typedef struct { + tbm_bo bo; + struct xorg_list link; +} SecFbBoItem, *SecFbBoItemPtr; + +static void +_exynosFbFreeBoData(void *data) +{ + XDBG_RETURN_IF_FAIL(data != NULL); + + ScrnInfoPtr pScrn; + EXYNOSPtr pExynos; + EXYNOSFbBoDataPtr bo_data = (EXYNOSFbBoDataPtr) data; + + pScrn = bo_data->pScrn; + pExynos = EXYNOSPTR(pScrn); + + XDBG_DEBUG(MFB, "FreeRender bo_data gem:%d, fb_id:%d, %dx%d+%d+%d\n", + bo_data->gem_handle, bo_data->fb_id, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1, bo_data->pos.x1, + bo_data->pos.y1); + + if (bo_data->fb_id) { + drmModeRmFB(pExynos->drm_fd, bo_data->fb_id); + bo_data->fb_id = 0; + } + + if (bo_data->pPixmap) { + pScrn->pScreen->DestroyPixmap(bo_data->pPixmap); + bo_data->pPixmap = NULL; + } + + free(bo_data); + bo_data = NULL; +} + +static tbm_bo +_exynosFbCreateBo2(EXYNOSFbPtr pFb, int x, int y, int width, int height, + tbm_bo prev_bo, Bool clear) +{ + XDBG_RETURN_VAL_IF_FAIL((pFb != NULL), NULL); + XDBG_RETURN_VAL_IF_FAIL((width > 0), NULL); + XDBG_RETURN_VAL_IF_FAIL((height > 0), NULL); + + EXYNOSPtr pExynos = EXYNOSPTR(pFb->pScrn); + + tbm_bo bo = NULL; + tbm_bo_handle bo_handle2; + EXYNOSFbBoDataPtr bo_data = NULL; + unsigned int pitch; + unsigned int fb_id = 0; + int ret; + int flag; + + pitch = width * 4; + + if (!pExynos->cachable) + flag = TBM_BO_WC; + else + flag = TBM_BO_DEFAULT; + + if (prev_bo != NULL) { + XDBG_RETURN_VAL_IF_FAIL(tbm_bo_size(prev_bo) >= (pitch * height), NULL); + + tbm_bo_delete_user_data(prev_bo, TBM_BO_DATA_FB); + + /* TODO: check flags */ + + bo = prev_bo; + } + else { + bo = tbm_bo_alloc(pExynos->tbm_bufmgr, pitch * height, flag); + XDBG_GOTO_IF_FAIL(bo != NULL, fail); + } + + if (clear) { + tbm_bo_handle bo_handle1; + + /* memset 0x0 */ + bo_handle1 = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + XDBG_RETURN_VAL_IF_FAIL(bo_handle1.ptr != NULL, NULL); + + memset(bo_handle1.ptr, 0x0, pitch * height); + tbm_bo_unmap(bo); + } + + bo_handle2 = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT); + + /* Create drm fb */ + ret = + drmModeAddFB(pExynos->drm_fd, width, height, pFb->pScrn->bitsPerPixel, + pFb->pScrn->bitsPerPixel, pitch, bo_handle2.u32, &fb_id); + XDBG_GOTO_IF_ERRNO(ret == Success, fail, -ret); + + if (x == -1) + x = 0; + if (y == -1) + y = 0; + + /* Set bo user data */ + bo_data = calloc(1, sizeof(EXYNOSFbBoDataRec)); + XDBG_GOTO_IF_FAIL(bo_data != NULL, fail); + bo_data->pFb = pFb; + bo_data->gem_handle = bo_handle2.u32; + bo_data->pitch = pitch; + bo_data->fb_id = fb_id; + bo_data->pos.x1 = x; + bo_data->pos.y1 = y; + bo_data->pos.x2 = x + width; + bo_data->pos.y2 = y + height; + bo_data->size = tbm_bo_size(bo); + bo_data->pScrn = pFb->pScrn; + XDBG_GOTO_IF_FAIL(tbm_bo_add_user_data + (bo, TBM_BO_DATA_FB, _exynosFbFreeBoData), fail); + XDBG_GOTO_IF_FAIL(tbm_bo_set_user_data + (bo, TBM_BO_DATA_FB, (void *) bo_data), fail); + + XDBG_DEBUG(MFB, "CreateRender bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n", + tbm_bo_export(bo), bo_data->gem_handle, bo_data->fb_id, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1, bo_data->pos.x1, + bo_data->pos.y1); + + return bo; + fail: + if (bo) { + exynosRenderBoUnref(bo); + } + + if (fb_id) { + drmModeRmFB(pExynos->drm_fd, fb_id); + } + + if (bo_data) { + free(bo_data); + bo_data = NULL; + } + + return NULL; +} + +static tbm_bo +_exynosFbCreateBo(EXYNOSFbPtr pFb, int x, int y, int width, int height) +{ + return _exynosFbCreateBo2(pFb, x, y, width, height, NULL, TRUE); +} + +static tbm_bo +_exynosFbRefBo(tbm_bo bo) +{ + return tbm_bo_ref(bo); +} + +static int +_exynosFbUnrefBo(tbm_bo bo) +{ + tbm_bo_unref(bo); + bo = NULL; + + return TRUE; +} + +EXYNOSFbPtr +exynosFbAllocate(ScrnInfoPtr pScrn, int width, int height) +{ + //exynosLogSetLevel(MFB, 0); + + XDBG_RETURN_VAL_IF_FAIL((pScrn != NULL), NULL); + XDBG_RETURN_VAL_IF_FAIL((width > 0), NULL); + XDBG_RETURN_VAL_IF_FAIL((height > 0), NULL); + + EXYNOSFbPtr pFb = calloc(1, sizeof(EXYNOSFbRec)); + + XDBG_GOTO_IF_FAIL((pFb != NULL), fail); + + pFb->pScrn = pScrn; + pFb->num_bo = 0; + pFb->width = width; + pFb->height = height; + + xorg_list_init(&pFb->list_bo); + + /* Create default buffer */ + pFb->default_bo = _exynosFbCreateBo(pFb, 0, 0, width, height); + + XDBG_TRACE(MFB, "Allocate %dx%d\n", width, height); + + return pFb; + + fail: + + return NULL; +} + +void +exynosFbFree(EXYNOSFbPtr pFb) +{ + XDBG_RETURN_IF_FAIL(pFb != NULL); + + XDBG_TRACE(MFB, "Free %dx%d, num:%d\n", pFb->width, pFb->height, + pFb->num_bo); + + if (!xorg_list_is_empty(&pFb->list_bo)) { + SecFbBoItemPtr item = NULL, tmp = NULL; + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + xorg_list_del(&item->link); + _exynosFbUnrefBo(item->bo); + free(item); + item = NULL; + } + } + + if (pFb->default_bo) { + exynosRenderBoUnref(pFb->default_bo); + pFb->default_bo = NULL; + } + + free(pFb); + pFb = NULL; +} + +tbm_bo +exynosFbGetBo(EXYNOSFbPtr pFb, int x, int y, int width, int height, + Bool onlyIfExists) +{ + EXYNOSFbBoDataPtr bo_data = NULL; + tbm_bo bo = NULL; + _X_UNUSED unsigned long key; + BoxRec box; + BoxPtr b1, b2; + int ret = rgnOUT; + + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + b2 = &box; + + if (!xorg_list_is_empty(&pFb->list_bo)) { + SecFbBoItemPtr item = NULL, tmp = NULL; + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + bo = item->bo; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + b1 = &bo_data->pos; + + ret = exynosUtilBoxInBox(b1, b2); + + if (ret == rgnIN || ret == rgnSAME) { + return bo; + } +#if 0 + else if (ret == rgnPART) { + if (!onlyIfExists) + continue; + + int r2 = exynosUtilBoxInBox(b2, b1); + + if (r2 == rgnIN) { + xorg_list_del(&item->link); + _exynosFbUnrefBo(bo); + free(item); + item = NULL; + pFb->num_bo--; + ret = rgnOUT; + break; + } + } +#endif + else if (ret == rgnOUT || ret == rgnPART) { + continue; + } + else { + return NULL; + } + } + } + + if ((ret == rgnOUT || ret == rgnPART) && !onlyIfExists) { + SecFbBoItemPtr item; + + CONV_POINT_TO_KEY(x, y, key); + + item = calloc(1, sizeof(SecFbBoItem)); + XDBG_RETURN_VAL_IF_FAIL(item != NULL, NULL); + if (width == pFb->width && height == pFb->height && x == 0 && y == 0) { + bo = _exynosFbRefBo(pFb->default_bo); + } + else { + bo = _exynosFbCreateBo(pFb, x, y, width, height); + if (!bo) { + free(item); + item = NULL; + return NULL; + } + } + + item->bo = bo; + xorg_list_add(&item->link, &pFb->list_bo); + pFb->num_bo++; + + XDBG_TRACE(MFB, "GetBO num:%d bo:%p name:%d, %dx%d+%d+%d\n", + pFb->num_bo, bo, tbm_bo_export(bo), width, height, x, y); + return bo; + } + + return NULL; +} + +tbm_bo +exynosFbSwapBo(EXYNOSFbPtr pFb, tbm_bo back_bo) +{ + EXYNOSFbBoDataPtr back_bo_data = NULL; + EXYNOSFbBoDataPtr bo_data = NULL; + EXYNOSFbBoDataRec tmp_bo_data; + tbm_bo bo; + BoxPtr b1, b2; + SecFbBoItemPtr item = NULL, tmp = NULL; + + XDBG_RETURN_VAL_IF_FAIL(pFb != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(FALSE == xorg_list_is_empty(&pFb->list_bo), NULL); + XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data + (back_bo, TBM_BO_DATA_FB, (void * *) &back_bo_data), + NULL); + XDBG_RETURN_VAL_IF_FAIL(back_bo_data, NULL); + + b2 = &back_bo_data->pos; + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + bo = item->bo; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + b1 = &bo_data->pos; + if (rgnSAME == exynosUtilBoxInBox(b1, b2)) { + XDBG_DEBUG(MFB, "SwapBO(Back:%d, Front:%d)\n", + tbm_bo_export(back_bo), tbm_bo_export(bo)); + + if (tbm_bo_swap(bo, back_bo)) { + memcpy(&tmp_bo_data, bo_data, sizeof(EXYNOSFbBoDataRec)); + memcpy(bo_data, back_bo_data, sizeof(EXYNOSFbBoDataRec)); + memcpy(back_bo_data, &tmp_bo_data, sizeof(EXYNOSFbBoDataRec)); + } + else + return NULL; + + return bo; + } + } + + return NULL; +} + +void +exynosFbResize(EXYNOSFbPtr pFb, int width, int height) +{ + XDBG_RETURN_IF_FAIL(pFb != NULL); + + EXYNOSFbBoDataPtr bo_data = NULL; + tbm_bo bo, old_bo; + int ret; + BoxRec box; + BoxPtr b1, b2; + + if (pFb->width == width && pFb->height == height) + return; + + old_bo = pFb->default_bo; + + pFb->width = width; + pFb->height = height; + XDBG_TRACE(MFB, "Resize %dx%d, num:%d\n", pFb->width, pFb->height, + pFb->num_bo); + + box.x1 = 0; + box.y1 = 0; + box.x2 = width; + box.y2 = height; + b1 = &box; + + if (!xorg_list_is_empty(&pFb->list_bo)) { + SecFbBoItemPtr item = NULL, tmp = NULL; + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + bo = item->bo; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + b2 = &bo_data->pos; + ret = exynosUtilBoxInBox(b1, b2); + + if (ret == rgnIN || ret == rgnSAME) + continue; + + /* Remove bo */ + XDBG_DEBUG(MFB, + "\t unref bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n", + tbm_bo_export(bo), bo_data->gem_handle, bo_data->fb_id, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1, bo_data->pos.x1, + bo_data->pos.y1); + + xorg_list_del(&item->link); + exynosRenderBoUnref(bo); + pFb->num_bo--; + free(item); + item = NULL; + } + } + + pFb->default_bo = _exynosFbCreateBo(pFb, 0, 0, width, height); + if (old_bo) + exynosRenderBoUnref(old_bo); +} + +int +exynosFbFindBo(EXYNOSFbPtr pFb, int x, int y, int width, int height, + int *num_bo, tbm_bo ** bos) +{ + EXYNOSFbBoDataPtr bo_data = NULL; + int num = 0; + tbm_bo *l = NULL; + tbm_bo bo; + int ret = rgnOUT; + BoxRec box; + BoxPtr b1, b2; + SecFbBoItemPtr item = NULL, tmp = NULL; + + if (xorg_list_is_empty(&pFb->list_bo)) { + return rgnOUT; + } + + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + b2 = &box; + + l = calloc(pFb->num_bo, sizeof(tbm_bo)); + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + bo = item->bo; + + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + if (bo_data == NULL) { + free(l); + return rgnOUT; + } + + b1 = &bo_data->pos; + ret = exynosUtilBoxInBox(b1, b2); + XDBG_DEBUG(MFB, "[%d/%d] ret:%d bo(%d,%d,%d,%d) fb(%d,%d,%d,%d)\n", + num + 1, pFb->num_bo, ret, + b1->x1, b1->y1, b1->x2, b1->y2, + b2->x1, b2->y1, b2->x2, b2->y2); + + if (ret == rgnSAME || ret == rgnIN) { + l[num++] = bo; + break; + } + else if (ret == rgnPART) { +// l[num++] = bo; + continue; + } + else { + continue; + } + } + + if (num_bo) + *num_bo = num; + if (bos) { + *bos = l; + } + else { + free(l); + } + + return ret; +} + +tbm_bo +exynosFbFindBoByPoint(EXYNOSFbPtr pFb, int x, int y) +{ + EXYNOSFbBoDataPtr bo_data = NULL; + tbm_bo bo; + SecFbBoItemPtr item = NULL, tmp = NULL; + + if (xorg_list_is_empty(&pFb->list_bo)) { + return NULL; + } + + xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) { + bo = item->bo; + tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *) &bo_data); + if ((x >= bo_data->pos.x1) && + (x < bo_data->pos.x2) && + (y >= bo_data->pos.y1) && (y < bo_data->pos.y2)) { + return bo; + } + } + + return NULL; +} + +PixmapPtr +exynosRenderBoGetPixmap(EXYNOSFbPtr pFb, tbm_bo bo) +{ + ScreenPtr pScreen = pFb->pScrn->pScreen; + PixmapPtr pPixmap; + EXYNOSFbBoDataPtr bo_data; + int ret; + + XDBG_RETURN_VAL_IF_FAIL(bo != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data + (bo, TBM_BO_DATA_FB, (void **) &bo_data), NULL); + + if (bo_data->pPixmap == NULL) { + pPixmap = pScreen->CreatePixmap(pFb->pScrn->pScreen, 0, 0, + pFb->pScrn->depth, + CREATE_PIXMAP_USAGE_SUB_FB); + XDBG_GOTO_IF_FAIL(pPixmap != NULL, fail); + + ret = pScreen->ModifyPixmapHeader(pPixmap, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1, + pFb->pScrn->depth, + pFb->pScrn->bitsPerPixel, + bo_data->pitch, (void *) bo); + XDBG_GOTO_IF_FAIL(ret != FALSE, fail); + bo_data->pPixmap = pPixmap; + XDBG_DEBUG(MFB, "CreateRenderPixmap:%p\n", pPixmap); + } + + return bo_data->pPixmap; + + fail: + XDBG_ERROR(MFB, "ERR: CreateRenderPixmap\n"); + if (pPixmap) { + pScreen->DestroyPixmap(pPixmap); + } + return NULL; +} + +tbm_bo +exynosRenderBoCreate(ScrnInfoPtr pScrn, int width, int height) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + return _exynosFbCreateBo(pExynos->pFb, -1, -1, width, height); +} + +int +exynosSwapToRenderBo(ScrnInfoPtr pScrn, int width, int height, tbm_bo carr_bo, + Bool clear) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + tbm_bo tbo = + _exynosFbCreateBo2(pExynos->pFb, -1, -1, width, height, carr_bo, clear); + + return tbo ? 1 : 0; +} + +tbm_bo +exynosRenderBoRef(tbm_bo bo) +{ + return _exynosFbRefBo(bo); +} + +void +exynosRenderBoUnref(tbm_bo bo) +{ + _exynosFbUnrefBo(bo); +} + +void +exynosRenderBoSetPos(tbm_bo bo, int x, int y) +{ + EXYNOSFbBoDataPtr bo_data; + int width, height; + + XDBG_RETURN_IF_FAIL(bo != NULL); + XDBG_RETURN_IF_FAIL(x >= 0); + XDBG_RETURN_IF_FAIL(y >= 0); + XDBG_RETURN_IF_FAIL(tbm_bo_get_user_data + (bo, TBM_BO_DATA_FB, (void **) &bo_data)); + + width = bo_data->pos.x2 - bo_data->pos.x1; + height = bo_data->pos.y2 - bo_data->pos.y1; + + bo_data->pos.x1 = x; + bo_data->pos.y1 = y; + bo_data->pos.x2 = x + width; + bo_data->pos.y2 = y + height; +} diff --git a/src/exynos.h b/src/exynos.h new file mode 100755 index 0000000..ba99420 --- /dev/null +++ b/src/exynos.h @@ -0,0 +1,304 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 EXYNOS_H +#define EXYNOS_H + +#ifdef TEMP_D +#define XV 1 +#define LAYER_MANAGER 1 +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include "xorg-server.h" +#include "xf86.h" +#include "xf86xv.h" +#include "xf86_OSproc.h" +#include "xf86drm.h" +#include "X11/Xatom.h" +#include "exynos.h" +#include "tbm_bufmgr.h" +#include "exynos_display.h" +#include "exynos_accel.h" +#include "exynos_video.h" +#include "exynos_wb.h" +#include "exynos_util.h" +#include "exynos_hwc.h" +#include "exynos_hwa.h" +#if HAVE_UDEV +#include <libudev.h> +#endif + +#ifdef ENABLE_TTRACE +#include <ttrace.h> +#ifdef TTRACE_VIDEO_BEGIN +#undef TTRACE_VIDEO_BEGIN +#endif +#ifdef TTRACE_VIDEO_END +#undef TTRACE_VIDEO_END +#endif +#ifdef TTRACE_GRAPHICS_BEGIN +#undef TTRACE_GRAPHICS_BEGIN +#endif +#ifdef TTRACE_GRAPHICS_END +#undef TTRACE_GRAPHICS_END +#endif +#define TTRACE_VIDEO_BEGIN(NAME) traceBegin(TTRACE_TAG_VIDEO, NAME) +#define TTRACE_VIDEO_END() traceEnd(TTRACE_TAG_VIDEO) + +#define TTRACE_GRAPHICS_BEGIN(NAME) traceBegin(TTRACE_TAG_GRAPHICS, NAME) +#define TTRACE_GRAPHICS_END() traceEnd(TTRACE_TAG_GRAPHICS) +#else +#ifdef TTRACE_VIDEO_BEGIN +#undef TTRACE_VIDEO_BEGIN +#endif +#ifdef TTRACE_VIDEO_END +#undef TTRACE_VIDEO_END +#endif +#ifdef TTRACE_GRAPHICS_BEGIN( +#undef TTRACE_GRAPHICS_BEGIN +#endif +#ifdef TTRACE_GRAPHICS_END +#undef TTRACE_GRAPHICS_END +#endif +#define TTRACE_VIDEO_BEGIN(NAME) +#define TTRACE_VIDEO_END() + +#define TTRACE_GRAPHICS_BEGIN(NAME) +#define TTRACE_GRAPHICS_END() +#endif + +#define USE_XDBG 0 + +#define DUMP_TYPE_PNG "png" +#define DUMP_TYPE_BMP "bmp" +#define DUMP_TYPE_RAW "raw" + +/* drm bo data type */ +typedef enum { + TBM_BO_DATA_FB = 1, +} TBM_BO_DATA; + +/* framebuffer infomation */ +typedef struct { + ScrnInfoPtr pScrn; + + int width; + int height; + + int num_bo; + struct xorg_list list_bo; + void *tbl_bo; /* bo hash table: key=(x,y)position */ + + tbm_bo default_bo; +} EXYNOSFbRec, *EXYNOSFbPtr; + +/* framebuffer bo data */ +typedef struct { + EXYNOSFbPtr pFb; + BoxRec pos; + uint32_t gem_handle; + intptr_t fb_id; + int pitch; + int size; + PixmapPtr pPixmap; + ScrnInfoPtr pScrn; +} EXYNOSFbBoDataRec, *EXYNOSFbBoDataPtr; + +/* exynos screen private information */ +typedef struct { + EntityInfoPtr pEnt; + Bool fake_root; /* screen rotation status */ + + /* driver options */ + OptionInfoPtr Options; + Bool is_exa; + Bool is_dri2; + Bool is_present; + Bool is_dri3; + Bool is_sw_exa; + Bool is_accel_2d; + Bool is_wb_clone; + Bool is_tfb; /* triple flip buffer */ + Bool cachable; /* if use cachable buffer */ + Bool scanout; /* if use scanout buffer */ + int flip_bufs; /* number of the flip buffers */ + Rotation rotate; + Bool use_partial_update; + Bool is_fb_touched; /* whether framebuffer is touched or not */ + + Bool use_hwc; + Bool use_setplane; + Bool use_flip; + Bool use_hwa; + + /* drm */ + int drm_fd; + char *drm_device_name; + tbm_bufmgr tbm_bufmgr; + + /* main fb information */ + EXYNOSFbPtr pFb; + + /* mode setting info private */ + EXYNOSModePtr pExynosMode; + + /* exa private */ + EXYNOSExaPrivPtr pExaPriv; + + /* video private */ + EXYNOSVideoPrivPtr pVideoPriv; + + /* HWC Compositor */ + Bool hwc_active; + Bool hwc_use_def_layer; + EXYNOSHwcPtr pHwc; +#ifdef LAYER_MANAGER + /* Layer Manager */ + void *pLYRM; +#endif + Bool isLcdOff; /* lvds connector on/off status */ +#ifdef NO_CRTC_MODE + Bool isCrtcOn; /* Global crtc status */ +#endif + /* screen wrapper functions */ + CloseScreenProcPtr CloseScreen; + CreateScreenResourcesProcPtr CreateScreenResources; + +#if HAVE_UDEV + struct udev_monitor *uevent_monitor; + InputHandlerProc uevent_handler; +#endif + + /* DRI2 */ + Atom atom_use_dri2; + Bool useAsyncSwap; + DrawablePtr flipDrawable; + + /* pending flip handler cause of lcd off */ + Bool pending_flip_handler; + unsigned int frame; + unsigned int tv_sec; + unsigned int tv_usec; + void *event_data; + + /* overlay drawable */ + DamagePtr ovl_damage; + DrawablePtr ovl_drawable; + + EXYNOSDisplaySetMode set_mode; + OsTimerPtr resume_timer; + + EXYNOSWb *wb_clone; + Bool wb_fps; + int wb_hz; + + /* Cursor */ + Bool enableCursor; + + /* dump */ + int dump_mode; + long dump_xid; + void *dump_info; + char *dump_str; + char dump_type[16]; + int xvperf_mode; + char *xvperf; + + int scale; + int cpu; + int flip_cnt; + + /* mem debug + Normal pixmap + CREATE_PIXMAP_USAGE_BACKING_PIXMAP + CREATE_PIXMAP_USAGE_OVERLAY + CREATE_PIXMAP_USAGE_XVIDEO + CREATE_PIXMAP_USAGE_DRI2_FILP_BACK + CREATE_PIXMAP_USAGE_FB + CREATE_PIXMAP_USAGE_SUB_FB + CREATE_PIXMAP_USAGE_DRI2_BACK + CREATE_PIXMAP_USAGE_DRI3_BACK + */ + int pix_normal; + int pix_backing_pixmap; + int pix_overlay; + int pix_dri2_flip_back; + int pix_fb; + int pix_sub_fb; + int pix_dri2_back; + int pix_dri3_back; + + /* HWA */ + int XVHIDE; + +} EXYNOSRec, *EXYNOSPtr; + +/* get a private screen of ScrnInfo */ +#define EXYNOSPTR(p) ((EXYNOSPtr)((p)->driverPrivate)) + +/* the version of the driver */ +#define EXYNOS_VERSION 1000 + +/* the name used to prefix messages */ +#define EXYNOS_NAME "exynos" + +/* the driver name used in display.conf file. exynos_drv.so */ +#define EXYNOS_DRIVER_NAME "exynos" + +#define ROOT_FB_ADDR (~0UL) + +#define EXYNOS_CURSOR_W 128 +#define EXYNOS_CURSOR_H 128 + +/* exynos framebuffer */ +EXYNOSFbPtr exynosFbAllocate(ScrnInfoPtr pScrn, int width, int height); +void exynosFbFree(EXYNOSFbPtr pFb); +void exynosFbResize(EXYNOSFbPtr pFb, int width, int height); +tbm_bo exynosFbGetBo(EXYNOSFbPtr pFb, int x, int y, int width, int height, + Bool onlyIfExists); +int exynosFbFindBo(EXYNOSFbPtr pFb, int x, int y, int width, int height, + int *num_bo, tbm_bo ** bos); +tbm_bo exynosFbFindBoByPoint(EXYNOSFbPtr pFb, int x, int y); +tbm_bo exynosFbSwapBo(EXYNOSFbPtr pFb, tbm_bo back_bo); + +tbm_bo exynosRenderBoCreate(ScrnInfoPtr pScrn, int width, int height); +int exynosSwapToRenderBo(ScrnInfoPtr pScrn, int width, int height, + tbm_bo carr_bo, Bool clear); +tbm_bo exynosRenderBoRef(tbm_bo bo); +void exynosRenderBoUnref(tbm_bo bo); +void exynosRenderBoSetPos(tbm_bo bo, int x, int y); +PixmapPtr exynosRenderBoGetPixmap(EXYNOSFbPtr pFb, tbm_bo bo); + +#endif /* EXYNOS_H */ diff --git a/src/g2d/fimg2d.c b/src/g2d/fimg2d.c index a68347b..b1e4567 100644 --- a/src/g2d/fimg2d.c +++ b/src/g2d/fimg2d.c @@ -1,3 +1,4 @@ +#include <xorg-server.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -5,17 +6,18 @@ #include <sys/ioctl.h> #include <sys/mman.h> +#include <xorg-server.h> #include "xf86drm.h" #include "xf86drmMode.h" -#include "exynos_drm.h" +#include <exynos/exynos_drm.h> #include "fimg2d.h" -#include "sec_util.h" +#include "exynos_util.h" #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE -#define FALSE 1 +#define FALSE 0 #endif #define G2D_MAX_CMD 64 @@ -34,9 +36,9 @@ typedef struct _G2D_CONTEXT { unsigned int cmd_gem_nr; unsigned int cmdlist_nr; -}G2dContext; +} G2dContext; -G2dContext* gCtx=NULL; +G2dContext *gCtx = NULL; static void _g2d_clear(void) @@ -46,19 +48,21 @@ _g2d_clear(void) } int -g2d_init (int fd) +g2d_init(int fd) { +#ifdef LEGACY_INTERFACE int ret; struct drm_exynos_g2d_get_ver ver; - if(gCtx) return FALSE; + if (gCtx) + return FALSE; - gCtx = calloc(1, sizeof(*gCtx)); - gCtx->drm_fd = fd; + gCtx = calloc(1, sizeof(*gCtx)); + gCtx->drm_fd = fd; ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_GET_VER, &ver); if (ret < 0) { - XDBG_ERROR (MG2D, "failed to get version: %s\n", strerror(-ret)); + XDBG_ERROR(MG2D, "failed to get version: %s\n", strerror(-ret)); free(gCtx); gCtx = NULL; @@ -68,32 +72,38 @@ g2d_init (int fd) gCtx->major = ver.major; gCtx->minor = ver.minor; - XDBG_INFO (MG2D, "[G2D] version(%d.%d) init....OK\n", gCtx->major, gCtx->minor); + XDBG_INFO(MG2D, "[G2D] version(%d.%d) init....OK\n", gCtx->major, + gCtx->minor); return TRUE; +#else + XDBG_ERROR(MG2D, "need to check g2d functionality\n"); + gCtx = NULL; + return FALSE; +#endif } void -g2d_fini (void) +g2d_fini(void) { +#ifdef LEGACY_INTERFACE free(gCtx); gCtx = NULL; +#endif } int -g2d_add_cmd (unsigned int cmd, unsigned int value) +g2d_add_cmd(unsigned int cmd, unsigned int value) { - switch(cmd) /* Check GEM Command */ - { + switch (cmd) { /* Check GEM Command */ case SRC_BASE_ADDR_REG: case SRC_PLANE2_BASE_ADDR_REG: case DST_BASE_ADDR_REG: case DST_PLANE2_BASE_ADDR_REG: case PAT_BASE_ADDR_REG: case MASK_BASE_ADDR_REG: - if(gCtx->cmd_gem_nr >= G2D_MAX_GEM_CMD) - { - XDBG_ERROR (MG2D, "Overflow cmd_gem size:%d\n", gCtx->cmd_gem_nr); + if (gCtx->cmd_gem_nr >= G2D_MAX_GEM_CMD) { + XDBG_ERROR(MG2D, "Overflow cmd_gem size:%d\n", gCtx->cmd_gem_nr); return FALSE; } @@ -102,9 +112,8 @@ g2d_add_cmd (unsigned int cmd, unsigned int value) gCtx->cmd_gem_nr++; break; default: - if(gCtx->cmd_nr >= G2D_MAX_CMD) - { - XDBG_ERROR (MG2D, "Overflow cmd size:%d\n", gCtx->cmd_nr); + if (gCtx->cmd_nr >= G2D_MAX_CMD) { + XDBG_ERROR(MG2D, "Overflow cmd size:%d\n", gCtx->cmd_nr); return FALSE; } @@ -118,30 +127,29 @@ g2d_add_cmd (unsigned int cmd, unsigned int value) } void -g2d_reset (unsigned int clear_reg) +g2d_reset(unsigned int clear_reg) { gCtx->cmd_nr = 0; gCtx->cmd_gem_nr = 0; - if(clear_reg) - { + if (clear_reg) { g2d_add_cmd(SOFT_RESET_REG, 0x01); } } int -g2d_exec (void) +g2d_exec(void) { struct drm_exynos_g2d_exec exec; int ret; - if(gCtx->cmdlist_nr == 0) + if (gCtx->cmdlist_nr == 0) return TRUE; exec.async = 0; ret = ioctl(gCtx->drm_fd, DRM_IOCTL_EXYNOS_G2D_EXEC, &exec); if (ret < 0) { - XDBG_ERROR (MG2D, "failed to execute(%d): %s\n", ret, strerror(-ret)); + XDBG_ERROR(MG2D, "failed to execute(%d): %s\n", ret, strerror(-ret)); return FALSE; } @@ -150,24 +158,24 @@ g2d_exec (void) } int -g2d_flush (void) +g2d_flush(void) { +#ifdef LEGACY_INTERFACE int ret; struct drm_exynos_g2d_set_cmdlist cmdlist; if (gCtx->cmd_nr == 0 && gCtx->cmd_gem_nr == 0) return TRUE; - if(gCtx->cmdlist_nr >= G2D_MAX_CMD_LIST) - { - XDBG_WARNING (MG2D, "Overflow cmdlist:%d\n", gCtx->cmdlist_nr); + if (gCtx->cmdlist_nr >= G2D_MAX_CMD_LIST) { + XDBG_WARNING(MG2D, "Overflow cmdlist:%d\n", gCtx->cmdlist_nr); g2d_exec(); } memset(&cmdlist, 0, sizeof(struct drm_exynos_g2d_set_cmdlist)); - cmdlist.cmd = (unsigned long)&gCtx->cmd[0]; - cmdlist.cmd_gem = (unsigned long)&gCtx->cmd_gem[0]; + cmdlist.cmd = (unsigned long) &gCtx->cmd[0]; + cmdlist.cmd_gem = (unsigned long) &gCtx->cmd_gem[0]; cmdlist.cmd_nr = gCtx->cmd_nr; cmdlist.cmd_gem_nr = gCtx->cmd_gem_nr; cmdlist.event_type = G2D_EVENT_NOT; @@ -178,23 +186,26 @@ g2d_flush (void) ret = ioctl(gCtx->drm_fd, DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST, &cmdlist); if (ret < 0) { - XDBG_ERROR (MG2D, "numFlush:%d, failed to set cmdlist(%d): %s\n", gCtx->cmdlist_nr, ret, strerror(-ret)); + XDBG_ERROR(MG2D, "numFlush:%d, failed to set cmdlist(%d): %s\n", + gCtx->cmdlist_nr, ret, strerror(-ret)); return FALSE; } gCtx->cmdlist_nr++; return TRUE; +#else + return FALSE; +#endif } -G2dImage* +G2dImage * g2d_image_new(void) { - G2dImage* img; + G2dImage *img; img = calloc(1, sizeof(G2dImage)); - if(img == NULL) - { - XDBG_ERROR (MG2D, "Cannot create solid image\n"); + if (img == NULL) { + XDBG_ERROR(MG2D, "Cannot create solid image\n"); return NULL; } @@ -206,20 +217,19 @@ g2d_image_new(void) return img; } -G2dImage* -g2d_image_create_solid (unsigned int color) +G2dImage * +g2d_image_create_solid(unsigned int color) { - G2dImage* img; + G2dImage *img; img = g2d_image_new(); - if(img == NULL) - { - XDBG_ERROR (MG2D, "Cannot create solid image\n"); + if (img == NULL) { + XDBG_ERROR(MG2D, "Cannot create solid image\n"); return NULL; } img->select_mode = G2D_SELECT_MODE_FGCOLOR; - img->color_mode = G2D_COLOR_FMT_ARGB8888|G2D_ORDER_AXRGB; + img->color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; img->data.color = color; img->width = -1; img->height = -1; @@ -227,16 +237,15 @@ g2d_image_create_solid (unsigned int color) return img; } -G2dImage* -g2d_image_create_bo (G2dColorMode format, unsigned int width, unsigned int height, - unsigned int bo, unsigned int stride) +G2dImage * +g2d_image_create_bo(G2dColorMode format, unsigned int width, + unsigned int height, unsigned int bo, unsigned int stride) { - G2dImage* img; + G2dImage *img; img = g2d_image_new(); - if(img == NULL) - { - XDBG_ERROR (MG2D, "Cannot alloc bo\n"); + if (img == NULL) { + XDBG_ERROR(MG2D, "Cannot alloc bo\n"); return NULL; } @@ -245,44 +254,42 @@ g2d_image_create_bo (G2dColorMode format, unsigned int width, unsigned int heigh img->width = width; img->height = height; - if(bo) - { + if (bo) { img->data.bo[0] = bo; img->stride = stride; } - else - { + else { unsigned int stride; struct drm_exynos_gem_create arg; - switch(format&G2D_COLOR_FMT_MASK) - { + switch (format & G2D_COLOR_FMT_MASK) { case G2D_COLOR_FMT_XRGB8888: case G2D_COLOR_FMT_ARGB8888: - stride = width*4; + stride = width * 4; break; case G2D_COLOR_FMT_A1: - stride = (width+7) / 8; + stride = (width + 7) / 8; break; case G2D_COLOR_FMT_A4: - stride = (width*4+7) /8; + stride = (width * 4 + 7) / 8; break; case G2D_COLOR_FMT_A8: case G2D_COLOR_FMT_L8: stride = width; break; default: - XDBG_ERROR (MG2D, "Unsurpported format(%d)\n", format); + XDBG_ERROR(MG2D, "Unsurpported format(%d)\n", format); free(img); return NULL; } /* Allocation gem buffer */ arg.flags = EXYNOS_BO_CACHABLE; - arg.size = stride*height; - if(drmCommandWriteRead(gCtx->drm_fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg))) - { - XDBG_ERROR (MG2D, "Cannot create bo image(flag:%x, size:%d)\n", arg.flags, (unsigned int)arg.size); + arg.size = stride * height; + if (drmCommandWriteRead + (gCtx->drm_fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg))) { + XDBG_ERROR(MG2D, "Cannot create bo image(flag:%x, size:%d)\n", + arg.flags, (unsigned int) arg.size); free(img); return NULL; } @@ -294,14 +301,15 @@ g2d_image_create_bo (G2dColorMode format, unsigned int width, unsigned int heigh memset(&arg_map, 0, sizeof(arg_map)); arg_map.handle = arg.handle; arg_map.size = arg.size; - if(drmCommandWriteRead(gCtx->drm_fd, DRM_EXYNOS_GEM_MMAP, &arg_map, sizeof(arg_map))) - { - XDBG_ERROR (MG2D, "Cannot map offset bo image\n"); + if (drmCommandWriteRead + (gCtx->drm_fd, DRM_EXYNOS_GEM_MMAP, &arg_map, + sizeof(arg_map))) { + XDBG_ERROR(MG2D, "Cannot map offset bo image\n"); free(img); return NULL; } - img->mapped_ptr[0] = (void*)(unsigned long)arg_map.mapped; + img->mapped_ptr[0] = (void *) (unsigned long) arg_map.mapped; } img->stride = stride; @@ -312,31 +320,28 @@ g2d_image_create_bo (G2dColorMode format, unsigned int width, unsigned int heigh return img; } -G2dImage* -g2d_image_create_bo2 (G2dColorMode format, - unsigned int width, unsigned int height, - unsigned int bo1, unsigned int bo2, unsigned int stride) +G2dImage * +g2d_image_create_bo2(G2dColorMode format, + unsigned int width, unsigned int height, + unsigned int bo1, unsigned int bo2, unsigned int stride) { - G2dImage* img; + G2dImage *img; - if (bo1 == 0) - { - XDBG_ERROR (MG2D, "[G2D] first bo is NULL. \n"); + if (bo1 == 0) { + XDBG_ERROR(MG2D, "[G2D] first bo is NULL. \n"); return NULL; } if (format & G2D_YCbCr_2PLANE) - if (bo2 == 0) - { - XDBG_ERROR (MG2D, "[G2D] second bo is NULL. \n"); + if (bo2 == 0) { + XDBG_ERROR(MG2D, "[G2D] exynosond bo is NULL. \n"); return NULL; } img = g2d_image_new(); - if(img == NULL) - { - XDBG_ERROR (MG2D, "Cannot alloc bo\n"); + if (img == NULL) { + XDBG_ERROR(MG2D, "Cannot alloc bo\n"); return NULL; } @@ -352,16 +357,16 @@ g2d_image_create_bo2 (G2dColorMode format, return img; } -G2dImage* -g2d_image_create_data (G2dColorMode format, unsigned int width, unsigned int height, - void* data, unsigned int stride) +G2dImage * +g2d_image_create_data(G2dColorMode format, unsigned int width, + unsigned int height, void *data, unsigned int stride) { - G2dImage* img; +#ifdef LEGACY_INTERFACE + G2dImage *img; img = g2d_image_new(); - if(img == NULL) - { - XDBG_ERROR (MG2D, "Cannot alloc bo\n"); + if (img == NULL) { + XDBG_ERROR(MG2D, "Cannot alloc bo\n"); return NULL; } @@ -370,62 +375,59 @@ g2d_image_create_data (G2dColorMode format, unsigned int width, unsigned int hei img->width = width; img->height = height; - if(data) - { + if (data) { struct drm_exynos_gem_userptr userptr; memset(&userptr, 0, sizeof(struct drm_exynos_gem_userptr)); - userptr.userptr = (uint64_t)((uint32_t)data); - userptr.size = stride*height; + userptr.userptr = (uint64_t) ((uint32_t) data); + userptr.size = stride * height; img->mapped_ptr[0] = data; img->stride = stride; - if(drmCommandWriteRead(gCtx->drm_fd, - DRM_EXYNOS_GEM_USERPTR, - &userptr, sizeof(userptr))) - { - XDBG_ERROR (MG2D, "Cannot create userptr(ptr:%p, size:%d)\n", (void*)((uint32_t)userptr.userptr), (uint32_t)userptr.size); + if (drmCommandWriteRead(gCtx->drm_fd, + DRM_EXYNOS_GEM_USERPTR, + &userptr, sizeof(userptr))) { + XDBG_ERROR(MG2D, "Cannot create userptr(ptr:%p, size:%d)\n", + (void *) ((uint32_t) userptr.userptr), + (uint32_t) userptr.size); free(img); return NULL; } img->data.bo[0] = userptr.handle; img->need_free = 1; } - else - { + else { unsigned int stride; struct drm_exynos_gem_create arg; - switch(format&G2D_COLOR_FMT_MASK) - { + switch (format & G2D_COLOR_FMT_MASK) { case G2D_COLOR_FMT_XRGB8888: case G2D_COLOR_FMT_ARGB8888: - stride = width*4; + stride = width * 4; break; case G2D_COLOR_FMT_A1: - stride = (width+7) / 8; + stride = (width + 7) / 8; break; case G2D_COLOR_FMT_A4: - stride = (width*4+7) /8; + stride = (width * 4 + 7) / 8; break; case G2D_COLOR_FMT_A8: case G2D_COLOR_FMT_L8: stride = width; break; default: - XDBG_ERROR (MG2D, "Unsurpported format(%d)\n", format); + XDBG_ERROR(MG2D, "Unsurpported format(%d)\n", format); free(img); return NULL; } /* Allocation gem buffer */ - arg.flags = EXYNOS_BO_NONCONTIG|EXYNOS_BO_CACHABLE; - arg.size = stride*height; - if(drmCommandWriteRead(gCtx->drm_fd, - DRM_EXYNOS_GEM_CREATE, - &arg, sizeof(arg))) - { - XDBG_ERROR (MG2D, "Cannot create bo image(flag:%x, size:%d)\n", arg.flags, (unsigned int)arg.size); + arg.flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE; + arg.size = stride * height; + if (drmCommandWriteRead(gCtx->drm_fd, + DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg))) { + XDBG_ERROR(MG2D, "Cannot create bo image(flag:%x, size:%d)\n", + arg.flags, (unsigned int) arg.size); free(img); return NULL; } @@ -437,16 +439,15 @@ g2d_image_create_data (G2dColorMode format, unsigned int width, unsigned int hei memset(&arg_map, 0, sizeof(arg_map)); arg_map.handle = arg.handle; arg_map.size = arg.size; - if(drmCommandWriteRead(gCtx->drm_fd, - DRM_EXYNOS_GEM_MMAP, - &arg_map, sizeof(arg_map))) - { - XDBG_ERROR (MG2D, "Cannot map offset bo image\n"); + if (drmCommandWriteRead(gCtx->drm_fd, + DRM_EXYNOS_GEM_MMAP, + &arg_map, sizeof(arg_map))) { + XDBG_ERROR(MG2D, "Cannot map offset bo image\n"); free(img); return NULL; } - img->mapped_ptr[0] = (void*)(unsigned long)arg_map.mapped; + img->mapped_ptr[0] = (void *) (unsigned long) arg_map.mapped; } img->stride = stride; @@ -455,21 +456,23 @@ g2d_image_create_data (G2dColorMode format, unsigned int width, unsigned int hei } return img; +#else + return NULL; +#endif } void -g2d_image_free (G2dImage* img) +g2d_image_free(G2dImage * img) { - if(img->need_free) - { + if (img->need_free) { struct drm_gem_close arg; /* Free gem buffer */ memset(&arg, 0, sizeof(arg)); arg.handle = img->data.bo[0]; - if(drmIoctl(gCtx->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: %d\n",__FUNCTION__, __LINE__, errno); + if (drmIoctl(gCtx->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: %d\n", __FUNCTION__, __LINE__, + errno); } } @@ -477,23 +480,23 @@ g2d_image_free (G2dImage* img) } int -g2d_set_src(G2dImage* img) +g2d_set_src(G2dImage * img) { - if(img == NULL) return FALSE; + if (img == NULL) + return FALSE; g2d_add_cmd(SRC_SELECT_REG, img->select_mode); g2d_add_cmd(SRC_COLOR_MODE_REG, img->color_mode); - switch(img->select_mode) - { + switch (img->select_mode) { case G2D_SELECT_MODE_NORMAL: g2d_add_cmd(SRC_BASE_ADDR_REG, img->data.bo[0]); - if (img->color_mode & G2D_YCbCr_2PLANE) - { + if (img->color_mode & G2D_YCbCr_2PLANE) { if (img->data.bo[1] > 0) g2d_add_cmd(SRC_PLANE2_BASE_ADDR_REG, img->data.bo[1]); else - XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + XDBG_ERROR(MG2D, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(SRC_STRIDE_REG, img->stride); break; @@ -504,7 +507,7 @@ g2d_set_src(G2dImage* img) g2d_add_cmd(BG_COLOR_REG, img->data.color); break; default: - XDBG_ERROR (MG2D, "Error: set src\n"); + XDBG_ERROR(MG2D, "Error: set src\n"); _g2d_clear(); return FALSE; } @@ -513,19 +516,20 @@ g2d_set_src(G2dImage* img) } int -g2d_set_mask(G2dImage* img) +g2d_set_mask(G2dImage * img) { G2dMaskModeVal mode; - if(img == NULL) return FALSE; - if(img->select_mode != G2D_SELECT_MODE_NORMAL) return FALSE; + if (img == NULL) + return FALSE; + if (img->select_mode != G2D_SELECT_MODE_NORMAL) + return FALSE; g2d_add_cmd(MASK_BASE_ADDR_REG, img->data.bo[0]); g2d_add_cmd(MASK_STRIDE_REG, img->stride); mode.val = 0; - switch(img->color_mode & G2D_COLOR_FMT_MASK) - { + switch (img->color_mode & G2D_COLOR_FMT_MASK) { case G2D_COLOR_FMT_A1: mode.data.maskMode = G2D_MASK_MODE_1BPP; break; @@ -537,19 +541,19 @@ g2d_set_mask(G2dImage* img) break; case G2D_COLOR_FMT_ARGB8888: mode.data.maskMode = G2D_MASK_MODE_32BPP; - mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4; + mode.data.maskOrder = (img->color_mode & G2D_ORDER_MASK) >> 4; break; case G2D_COLOR_FMT_RGB565: mode.data.maskMode = G2D_MASK_MODE_16BPP_565; - mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4; + mode.data.maskOrder = (img->color_mode & G2D_ORDER_MASK) >> 4; break; case G2D_COLOR_FMT_ARGB1555: mode.data.maskMode = G2D_MASK_MODE_16BPP_1555; - mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4; + mode.data.maskOrder = (img->color_mode & G2D_ORDER_MASK) >> 4; break; case G2D_COLOR_FMT_ARGB4444: mode.data.maskMode = G2D_MASK_MODE_16BPP_4444; - mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4; + mode.data.maskOrder = (img->color_mode & G2D_ORDER_MASK) >> 4; break; default: break; @@ -560,15 +564,15 @@ g2d_set_mask(G2dImage* img) } int -g2d_set_dst(G2dImage* img) +g2d_set_dst(G2dImage * img) { - if(img == NULL) return FALSE; + if (img == NULL) + return FALSE; g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR); g2d_add_cmd(DST_COLOR_MODE_REG, img->color_mode); - switch(img->select_mode) - { + switch (img->select_mode) { case G2D_SELECT_MODE_NORMAL: g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, img->stride); @@ -580,7 +584,7 @@ g2d_set_dst(G2dImage* img) g2d_add_cmd(BG_COLOR_REG, img->data.color); break; default: - XDBG_ERROR (MG2D, "Error: set src\n"); + XDBG_ERROR(MG2D, "Error: set src\n"); _g2d_clear(); return FALSE; } @@ -592,6 +596,7 @@ unsigned int g2d_get_blend_op(G2dOp op) { G2dBlendFunctionVal val; + #define set_bf(sc, si, scsa, scda, dc, di, dcsa, dcda) \ val.data.srcCoeff = sc; \ val.data.invSrcColorCoeff = si; \ @@ -603,29 +608,24 @@ g2d_get_blend_op(G2dOp op) val.data.dstCoeffDstA = dcda val.val = 0; - switch (op) - { + switch (op) { case G2D_OP_CLEAR: case G2D_OP_DISJOINT_CLEAR: case G2D_OP_CONJOINT_CLEAR: - set_bf (G2D_COEFF_MODE_ZERO, 0,0,0, - G2D_COEFF_MODE_ZERO, 0,0,0); + set_bf(G2D_COEFF_MODE_ZERO, 0, 0, 0, G2D_COEFF_MODE_ZERO, 0, 0, 0); break; case G2D_OP_SRC: case G2D_OP_DISJOINT_SRC: case G2D_OP_CONJOINT_SRC: - set_bf (G2D_COEFF_MODE_ONE, 0,0,0, - G2D_COEFF_MODE_ZERO, 0,0,0); + set_bf(G2D_COEFF_MODE_ONE, 0, 0, 0, G2D_COEFF_MODE_ZERO, 0, 0, 0); break; case G2D_OP_DST: case G2D_OP_DISJOINT_DST: case G2D_OP_CONJOINT_DST: - set_bf (G2D_COEFF_MODE_ZERO, 0,0,0, - G2D_COEFF_MODE_ONE, 0,0,0); + set_bf(G2D_COEFF_MODE_ZERO, 0, 0, 0, G2D_COEFF_MODE_ONE, 0, 0, 0); break; case G2D_OP_OVER: - set_bf (G2D_COEFF_MODE_ONE, 0,0,0, - G2D_COEFF_MODE_SRC_ALPHA, 1,0,0); + set_bf(G2D_COEFF_MODE_ONE, 0, 0, 0, G2D_COEFF_MODE_SRC_ALPHA, 1, 0, 0); break; case G2D_OP_OVER_REVERSE: case G2D_OP_IN: @@ -638,9 +638,8 @@ g2d_get_blend_op(G2dOp op) case G2D_OP_ADD: case G2D_OP_NONE: default: - XDBG_ERROR (MG2D, "[FIMG2D] Not support op:%d\n", op); - set_bf (G2D_COEFF_MODE_ONE, 0,0,0, - G2D_COEFF_MODE_ZERO, 0,0,0); + XDBG_ERROR(MG2D, "[FIMG2D] Not support op:%d\n", op); + set_bf(G2D_COEFF_MODE_ONE, 0, 0, 0, G2D_COEFF_MODE_ZERO, 0, 0, 0); break; } #undef set_bf @@ -652,19 +651,18 @@ void g2d_dump(void) { int i; - XDBG_DEBUG (MG2D, "==================\n"); - XDBG_DEBUG (MG2D, " G2D REG DUMP \n"); - XDBG_DEBUG (MG2D, "==================\n"); - - for(i=0; i<gCtx->cmd_gem_nr; i++) - { - XDBG_DEBUG (MG2D, "[GEM] 0x%08x 0x%08x\n", - gCtx->cmd_gem[i].offset, gCtx->cmd_gem[i].data); + + XDBG_DEBUG(MG2D, "==================\n"); + XDBG_DEBUG(MG2D, " G2D REG DUMP \n"); + XDBG_DEBUG(MG2D, "==================\n"); + + for (i = 0; i < gCtx->cmd_gem_nr; i++) { + XDBG_DEBUG(MG2D, "[GEM] 0x%08x 0x%08x\n", + gCtx->cmd_gem[i].offset, gCtx->cmd_gem[i].data); } - for(i=0; i<gCtx->cmd_nr; i++) - { - XDBG_DEBUG (MG2D, "[CMD] 0x%08x 0x%08x\n", - gCtx->cmd[i].offset, gCtx->cmd[i].data); + for (i = 0; i < gCtx->cmd_nr; i++) { + XDBG_DEBUG(MG2D, "[CMD] 0x%08x 0x%08x\n", + gCtx->cmd[i].offset, gCtx->cmd[i].data); } } diff --git a/src/g2d/fimg2d.h b/src/g2d/fimg2d.h index ada1c2f..b7423cd 100755 --- a/src/g2d/fimg2d.h +++ b/src/g2d/fimg2d.h @@ -6,138 +6,137 @@ typedef unsigned int G2dFixed; typedef enum { - G2D_INT_MODE_LEVEL, - G2D_INT_MODE_EDGE, + G2D_INT_MODE_LEVEL, + G2D_INT_MODE_EDGE, - G2D_INT_MODE_MAX = G2D_INT_MODE_EDGE + G2D_INT_MODE_MAX = G2D_INT_MODE_EDGE } G2dIntMode; typedef enum { - G2D_TRANSPARENT_MODE_OPAQUE, - G2D_TRANSPARENT_MODE_TRANSPARENT, - G2D_TRANSPARENT_MODE_BLUESCREEN, - G2D_TRANSPARENT_MODE_MAX + G2D_TRANSPARENT_MODE_OPAQUE, + G2D_TRANSPARENT_MODE_TRANSPARENT, + G2D_TRANSPARENT_MODE_BLUESCREEN, + G2D_TRANSPARENT_MODE_MAX } G2dTransparentMode; typedef enum { - G2D_COLORKEY_MODE_DISABLE = 0, - G2D_COLORKEY_MODE_SRC_RGBA = (1<<0), - G2D_COLORKEY_MODE_DST_RGBA = (1<<1), - G2D_COLORKEY_MODE_SRC_YCbCr = (1<<2), /* VER4.1 */ - G2D_COLORKEY_MODE_DST_YCbCr = (1<<3), /* VER4.1 */ - - G2D_COLORKEY_MODE_MASK = 15, + G2D_COLORKEY_MODE_DISABLE = 0, + G2D_COLORKEY_MODE_SRC_RGBA = (1 << 0), + G2D_COLORKEY_MODE_DST_RGBA = (1 << 1), + G2D_COLORKEY_MODE_SRC_YCbCr = (1 << 2), /* VER4.1 */ + G2D_COLORKEY_MODE_DST_YCbCr = (1 << 3), /* VER4.1 */ + + G2D_COLORKEY_MODE_MASK = 15, } G2dColorKeyMode; typedef enum { - G2D_ALPHA_BLEND_MODE_DISABLE, - G2D_ALPHA_BLEND_MODE_ENABLE, - G2D_ALPHA_BLEND_MODE_FADING, /* VER3.0 */ - G2D_ALPHA_BLEND_MODE_MAX + G2D_ALPHA_BLEND_MODE_DISABLE, + G2D_ALPHA_BLEND_MODE_ENABLE, + G2D_ALPHA_BLEND_MODE_FADING, /* VER3.0 */ + G2D_ALPHA_BLEND_MODE_MAX } G2dAlphaBlendMode; typedef enum { - G2D_SRC_NONPREBLAND_MODE_DISABLE, /* VER3.0 */ - G2D_SRC_NONPREBLAND_MODE_CONSTANT, /* VER3.0 */ - G2D_SRC_NONPREBLAND_MODE_PERPIXEL, /* VER3.0 */ - G2D_SRC_NONPREBLAND_MODE_MAX, /* VER3.0 */ + G2D_SRC_NONPREBLAND_MODE_DISABLE, /* VER3.0 */ + G2D_SRC_NONPREBLAND_MODE_CONSTANT, /* VER3.0 */ + G2D_SRC_NONPREBLAND_MODE_PERPIXEL, /* VER3.0 */ + G2D_SRC_NONPREBLAND_MODE_MAX, /* VER3.0 */ } G2dSrcNonPreBlendMode; typedef enum { - G2D_SELECT_SRC_FOR_ALPHA_BLEND, /* VER4.1 */ - G2D_SELECT_ROP_FOR_ALPHA_BLEND, /* VER4.1 */ + G2D_SELECT_SRC_FOR_ALPHA_BLEND, /* VER4.1 */ + G2D_SELECT_ROP_FOR_ALPHA_BLEND, /* VER4.1 */ } G2dSelectAlphaSource; - -typedef enum { /* VER4.1 */ - G2D_COEFF_MODE_ONE, - G2D_COEFF_MODE_ZERO, - G2D_COEFF_MODE_SRC_ALPHA, - G2D_COEFF_MODE_SRC_COLOR, - G2D_COEFF_MODE_DST_ALPHA, - G2D_COEFF_MODE_DST_COLOR, - G2D_COEFF_MODE_GB_ALPHA, /* Global Alpha : Set by ALPHA_REG(0x618) */ - G2D_COEFF_MODE_GB_COLOR, /* Global Alpha : Set by ALPHA_REG(0x618) */ - G2D_COEFF_MODE_DISJOINT_S, /* (1-SRC alpha)/DST Alpha */ - G2D_COEFF_MODE_DISJOINT_D, /* (1-DST alpha)/SRC Alpha */ - G2D_COEFF_MODE_CONJOINT_S, /* SRC alpha/DST alpha */ - G2D_COEFF_MODE_CONJOINT_D, /* DST alpha/SRC alpha */ - G2D_COEFF_MODE_MASK -}G2dCoeffMode; +typedef enum { /* VER4.1 */ + G2D_COEFF_MODE_ONE, + G2D_COEFF_MODE_ZERO, + G2D_COEFF_MODE_SRC_ALPHA, + G2D_COEFF_MODE_SRC_COLOR, + G2D_COEFF_MODE_DST_ALPHA, + G2D_COEFF_MODE_DST_COLOR, + G2D_COEFF_MODE_GB_ALPHA, /* Global Alpha : Set by ALPHA_REG(0x618) */ + G2D_COEFF_MODE_GB_COLOR, /* Global Alpha : Set by ALPHA_REG(0x618) */ + G2D_COEFF_MODE_DISJOINT_S, /* (1-SRC alpha)/DST Alpha */ + G2D_COEFF_MODE_DISJOINT_D, /* (1-DST alpha)/SRC Alpha */ + G2D_COEFF_MODE_CONJOINT_S, /* SRC alpha/DST alpha */ + G2D_COEFF_MODE_CONJOINT_D, /* DST alpha/SRC alpha */ + G2D_COEFF_MODE_MASK +} G2dCoeffMode; typedef enum { - G2D_ACOEFF_MODE_A, /*alpha*/ - G2D_ACOEFF_MODE_APGA, /*alpha + global alpha*/ - G2D_ACOEFF_MODE_AMGA, /*alpha * global alpha*/ + G2D_ACOEFF_MODE_A, /*alpha */ + G2D_ACOEFF_MODE_APGA, /*alpha + global alpha */ + G2D_ACOEFF_MODE_AMGA, /*alpha * global alpha */ G2D_ACOEFF_MODE_MASK -}G2dACoeffMode; +} G2dACoeffMode; typedef enum { - G2D_SELECT_MODE_NORMAL = (0 << 0), - G2D_SELECT_MODE_FGCOLOR = (1 << 0), - G2D_SELECT_MODE_BGCOLOR = (2 << 0), - G2D_SELECT_MODE_MAX = (3 << 0), + G2D_SELECT_MODE_NORMAL = (0 << 0), + G2D_SELECT_MODE_FGCOLOR = (1 << 0), + G2D_SELECT_MODE_BGCOLOR = (2 << 0), + G2D_SELECT_MODE_MAX = (3 << 0), } G2dSelectMode; typedef enum { - /* COLOR FORMAT */ - G2D_COLOR_FMT_XRGB8888, - G2D_COLOR_FMT_ARGB8888, - G2D_COLOR_FMT_RGB565, - G2D_COLOR_FMT_XRGB1555, - G2D_COLOR_FMT_ARGB1555, - G2D_COLOR_FMT_XRGB4444, - G2D_COLOR_FMT_ARGB4444, - G2D_COLOR_FMT_PRGB888, - G2D_COLOR_FMT_YCbCr444, - G2D_COLOR_FMT_YCbCr422, - G2D_COLOR_FMT_YCbCr420=10, - G2D_COLOR_FMT_A8, /* alpha 8bit */ - G2D_COLOR_FMT_L8, /* Luminance 8bit: gray color */ - G2D_COLOR_FMT_A1, /* alpha 1bit */ - G2D_COLOR_FMT_A4, /* alpha 4bit */ - G2D_COLOR_FMT_MASK = (15 << 0), /* VER4.1 */ - - /* COLOR ORDER */ - G2D_ORDER_AXRGB = (0 << 4), /* VER4.1 */ - G2D_ORDER_RGBAX = (1 << 4), /* VER4.1 */ - G2D_ORDER_AXBGR = (2 << 4), /* VER4.1 */ - G2D_ORDER_BGRAX = (3 << 4), /* VER4.1 */ - G2D_ORDER_MASK = (3 << 4), /* VER4.1 */ - - /* Number of YCbCr plane */ - G2D_YCbCr_1PLANE = (0 << 8), /* VER4.1 */ - G2D_YCbCr_2PLANE = (1 << 8), /* VER4.1 */ - G2D_YCbCr_PLANE_MASK = (3 << 8), /* VER4.1 */ - - /* Order in YCbCr */ - G2D_YCbCr_ORDER_CrY1CbY0 = (0 << 12), /* VER4.1 */ - G2D_YCbCr_ORDER_CbY1CrY0 = (1 << 12), /* VER4.1 */ - G2D_YCbCr_ORDER_Y1CrY0Cb = (2 << 12), /* VER4.1 */ - G2D_YCbCr_ORDER_Y1CbY0Cr = (3 << 12), /* VER4.1 */ - G2D_YCbCr_ORDER_CrCb = G2D_YCbCr_ORDER_CrY1CbY0, /* VER4.1, for 2 plane */ - G2D_YCbCr_ORDER_CbCr = G2D_YCbCr_ORDER_CbY1CrY0, /* VER4.1, for 2 plane */ - G2D_YCbCr_ORDER_MASK = (3 < 12), /* VER4.1 */ - - /* CSC */ - G2D_CSC_601 = (0 << 16), /* VER4.1 */ - G2D_CSC_709 = (1 << 16), /* VER4.1 */ - G2D_CSC_MASK = (1 << 16), /* VER4.1 */ - - /* Valid value range of YCbCr */ - G2D_YCbCr_RANGE_NARROW = (0 << 17), /* VER4.1 */ - G2D_YCbCr_RANGE_WIDE = (1 << 17), /* VER4.1 */ - G2D_YCbCr_RANGE_MASK= (1 << 17), /* VER4.1 */ - - G2D_COLOR_MODE_MASK = 0xFFFFFFFF -}G2dColorMode; + /* COLOR FORMAT */ + G2D_COLOR_FMT_XRGB8888, + G2D_COLOR_FMT_ARGB8888, + G2D_COLOR_FMT_RGB565, + G2D_COLOR_FMT_XRGB1555, + G2D_COLOR_FMT_ARGB1555, + G2D_COLOR_FMT_XRGB4444, + G2D_COLOR_FMT_ARGB4444, + G2D_COLOR_FMT_PRGB888, + G2D_COLOR_FMT_YCbCr444, + G2D_COLOR_FMT_YCbCr422, + G2D_COLOR_FMT_YCbCr420 = 10, + G2D_COLOR_FMT_A8, /* alpha 8bit */ + G2D_COLOR_FMT_L8, /* Luminance 8bit: gray color */ + G2D_COLOR_FMT_A1, /* alpha 1bit */ + G2D_COLOR_FMT_A4, /* alpha 4bit */ + G2D_COLOR_FMT_MASK = (15 << 0), /* VER4.1 */ + + /* COLOR ORDER */ + G2D_ORDER_AXRGB = (0 << 4), /* VER4.1 */ + G2D_ORDER_RGBAX = (1 << 4), /* VER4.1 */ + G2D_ORDER_AXBGR = (2 << 4), /* VER4.1 */ + G2D_ORDER_BGRAX = (3 << 4), /* VER4.1 */ + G2D_ORDER_MASK = (3 << 4), /* VER4.1 */ + + /* Number of YCbCr plane */ + G2D_YCbCr_1PLANE = (0 << 8), /* VER4.1 */ + G2D_YCbCr_2PLANE = (1 << 8), /* VER4.1 */ + G2D_YCbCr_PLANE_MASK = (3 << 8), /* VER4.1 */ + + /* Order in YCbCr */ + G2D_YCbCr_ORDER_CrY1CbY0 = (0 << 12), /* VER4.1 */ + G2D_YCbCr_ORDER_CbY1CrY0 = (1 << 12), /* VER4.1 */ + G2D_YCbCr_ORDER_Y1CrY0Cb = (2 << 12), /* VER4.1 */ + G2D_YCbCr_ORDER_Y1CbY0Cr = (3 << 12), /* VER4.1 */ + G2D_YCbCr_ORDER_CrCb = G2D_YCbCr_ORDER_CrY1CbY0, /* VER4.1, for 2 plane */ + G2D_YCbCr_ORDER_CbCr = G2D_YCbCr_ORDER_CbY1CrY0, /* VER4.1, for 2 plane */ + G2D_YCbCr_ORDER_MASK = (3 < 12), /* VER4.1 */ + + /* CSC */ + G2D_CSC_601 = (0 << 16), /* VER4.1 */ + G2D_CSC_709 = (1 << 16), /* VER4.1 */ + G2D_CSC_MASK = (1 << 16), /* VER4.1 */ + + /* Valid value range of YCbCr */ + G2D_YCbCr_RANGE_NARROW = (0 << 17), /* VER4.1 */ + G2D_YCbCr_RANGE_WIDE = (1 << 17), /* VER4.1 */ + G2D_YCbCr_RANGE_MASK = (1 << 17), /* VER4.1 */ + + G2D_COLOR_MODE_MASK = 0xFFFFFFFF +} G2dColorMode; typedef enum { - G2D_SCALE_MODE_NONE = 0, - G2D_SCALE_MODE_NEAREST, - G2D_SCALE_MODE_BILINEAR, + G2D_SCALE_MODE_NONE = 0, + G2D_SCALE_MODE_NEAREST, + G2D_SCALE_MODE_BILINEAR, - G2D_SCALE_MODE_MAX + G2D_SCALE_MODE_MAX } G2dScaleMode; typedef enum { @@ -161,21 +160,21 @@ typedef enum { G2D_MASK_ORDER_RGBAX, G2D_MASK_ORDER_AXBGR, G2D_MASK_ORDER_BGRAX, - + G2D_MASK_ORDER_MAX } G2dMaskOrder; typedef enum { - G2D_MASK_MODE_1BPP = 0, - G2D_MASK_MODE_4BPP, - G2D_MASK_MODE_8BPP, - G2D_MASK_MODE_16BPP_565, - G2D_MASK_MODE_16BPP_1555, - G2D_MASK_MODE_16BPP_4444, - G2D_MASK_MODE_32BPP, - G2D_MASK_MODE_4BPP_FOR_WINCE, /* ([31:24]bit field of 32bit is used as mask) */ - - G2D_MASK_MODE_MAX + G2D_MASK_MODE_1BPP = 0, + G2D_MASK_MODE_4BPP, + G2D_MASK_MODE_8BPP, + G2D_MASK_MODE_16BPP_565, + G2D_MASK_MODE_16BPP_1555, + G2D_MASK_MODE_16BPP_4444, + G2D_MASK_MODE_32BPP, + G2D_MASK_MODE_4BPP_FOR_WINCE, /* ([31:24]bit field of 32bit is used as mask) */ + + G2D_MASK_MODE_MAX } G2dMaskMode; /* @@ -187,238 +186,238 @@ Here are some examples on how to use the ROP3 value to perform the operations: 5) Final Data = Source OR Pattern. ROP Value = "0xCC" | "0xF0" = "0xFC". */ typedef enum G2D_ROP3_TYPE { - G2D_ROP3_DST = 0xAA, - G2D_ROP3_SRC = 0xCC, - G2D_ROP3_3RD = 0xF0, + G2D_ROP3_DST = 0xAA, + G2D_ROP3_SRC = 0xCC, + G2D_ROP3_3RD = 0xF0, - G2D_ROP3_MASK = 0xFF + G2D_ROP3_MASK = 0xFF } G2dROP3Type; typedef enum G2D_ALU { - /*Common alu for x base*/ - G2Dclear = 0x0, /* 0 */ - G2Dand = 0x1, /* src AND dst */ - G2DandReverse = 0x2, /* src AND NOT dst */ - G2Dcopy = 0x3, /* src */ - G2DandInverted = 0x4, /* NOT src AND dst */ - G2Dnoop = 0x5, /* dst */ - G2Dxor = 0x6, /* src XOR dst */ - G2Dor = 0x7, /* src OR dst */ - G2Dnor = 0x8, /* NOT src AND NOT dst */ - G2Dequiv = 0x9, /* NOT src XOR dst */ - G2Dinvert = 0xa, /* NOT dst */ - G2DorReverse = 0xb, /* src OR NOT dst */ - G2DcopyInverted = 0xc, /* NOT src */ - G2DorInverted = 0xd, /* NOT src OR dst */ - G2Dnand = 0xe, /* NOT src OR NOT dst */ - G2Dset = 0xf, /* 1 */ - - /*Special alu*/ - G2Dnegative = 0x20, /*NOT src XOR 0x00FFFFFF*/ -}G2dAlu; + /*Common alu for x base */ + G2Dclear = 0x0, /* 0 */ + G2Dand = 0x1, /* src AND dst */ + G2DandReverse = 0x2, /* src AND NOT dst */ + G2Dcopy = 0x3, /* src */ + G2DandInverted = 0x4, /* NOT src AND dst */ + G2Dnoop = 0x5, /* dst */ + G2Dxor = 0x6, /* src XOR dst */ + G2Dor = 0x7, /* src OR dst */ + G2Dnor = 0x8, /* NOT src AND NOT dst */ + G2Dequiv = 0x9, /* NOT src XOR dst */ + G2Dinvert = 0xa, /* NOT dst */ + G2DorReverse = 0xb, /* src OR NOT dst */ + G2DcopyInverted = 0xc, /* NOT src */ + G2DorInverted = 0xd, /* NOT src OR dst */ + G2Dnand = 0xe, /* NOT src OR NOT dst */ + G2Dset = 0xf, /* 1 */ + + /*Special alu */ + G2Dnegative = 0x20, /*NOT src XOR 0x00FFFFFF */ +} G2dAlu; typedef union _G2D_BITBLT_CMD_VAL { - unsigned int val; - struct { - /* [0:3] */ - unsigned int maskROP4En:1; - unsigned int maskingEn:1; - G2dSelectAlphaSource ROP4AlphaEn:1; - unsigned int ditherEn:1; - /* [4:7] */ - unsigned int resolved1:4; - /* [8:11] */ - unsigned int cwEn:4; - /* [12:15] */ - G2dTransparentMode transparentMode:4; - /* [16:19] */ - G2dColorKeyMode colorKeyMode:4; - /* [20:23] */ - G2dAlphaBlendMode alphaBlendMode:4; - /* [24:27] */ - unsigned int srcPreMultiply:1; - unsigned int patPreMultiply:1; - unsigned int dstPreMultiply:1; - unsigned int dstDepreMultiply:1; - /* [28:31] */ - unsigned int fastSolidColorFillEn:1; - unsigned int reserved:3; - }data; + unsigned int val; + struct { + /* [0:3] */ + unsigned int maskROP4En:1; + unsigned int maskingEn:1; + G2dSelectAlphaSource ROP4AlphaEn:1; + unsigned int ditherEn:1; + /* [4:7] */ + unsigned int resolved1:4; + /* [8:11] */ + unsigned int cwEn:4; + /* [12:15] */ + G2dTransparentMode transparentMode:4; + /* [16:19] */ + G2dColorKeyMode colorKeyMode:4; + /* [20:23] */ + G2dAlphaBlendMode alphaBlendMode:4; + /* [24:27] */ + unsigned int srcPreMultiply:1; + unsigned int patPreMultiply:1; + unsigned int dstPreMultiply:1; + unsigned int dstDepreMultiply:1; + /* [28:31] */ + unsigned int fastSolidColorFillEn:1; + unsigned int reserved:3; + } data; } G2dBitBltCmdVal; typedef union _G2D_BLEND_FUNCTION_VAL { - unsigned int val; - struct { - /* [0:15] */ - G2dCoeffMode srcCoeff:4; - G2dACoeffMode srcCoeffSrcA:2; - G2dACoeffMode srcCoeffDstA:2; - G2dCoeffMode dstCoeff:4; - G2dACoeffMode dstCoeffSrcA:2; - G2dACoeffMode dstCoeffDstA:2; - /* [16:19] */ - unsigned int invSrcColorCoeff:1; - unsigned int resoled1:1; - unsigned int invDstColorCoeff:1; - unsigned int resoled2:1; - /* [20:23] */ - unsigned int lightenEn:1; - unsigned int darkenEn:1; - unsigned int winCESrcOverEn:2; - /* [24:31] */ - unsigned int reserved:8; - }data; + unsigned int val; + struct { + /* [0:15] */ + G2dCoeffMode srcCoeff:4; + G2dACoeffMode srcCoeffSrcA:2; + G2dACoeffMode srcCoeffDstA:2; + G2dCoeffMode dstCoeff:4; + G2dACoeffMode dstCoeffSrcA:2; + G2dACoeffMode dstCoeffDstA:2; + /* [16:19] */ + unsigned int invSrcColorCoeff:1; + unsigned int resoled1:1; + unsigned int invDstColorCoeff:1; + unsigned int resoled2:1; + /* [20:23] */ + unsigned int lightenEn:1; + unsigned int darkenEn:1; + unsigned int winCESrcOverEn:2; + /* [24:31] */ + unsigned int reserved:8; + } data; } G2dBlendFunctionVal; typedef union _G2D_ROUND_MODE_VAL { - unsigned int val; - struct { - /* - Round Mode in Blending - 2'b00 : - Result = ((A + 1) * B) >>8; - 2'b01 : - Result = ((A+ (A>>7)) * B) >>8; - 2'b10 : - Result_tmp = A * B + 0x80; - Result = (Result_tmp + (Result_tmp>>8))>>8; - 2'b11 : - Result_A = A * B; (16 bpp) - Result_B = C * D; (16 bpp) - Result_tmp = Result_A + Result_B + 0x80; - Result = (Result_tmp + (Result_tmp>>8))>>8; - */ - unsigned int blend:4; - /* - Round Mode in Alpha Premultiply - 2'b00 : - Result = (A * B) >>8; - 2'b01 : - Result = ((A + 1) * B) >>8; - 2'b10 : - Result = ((A+ (A>>7)) * B) >>8; - 2'b11 : - Result_tmp = A * B + 0x80; - Result = (Result_tmp + (Result_tmp>>8))>>8; - */ - unsigned int alphaPremultiply:4; - /* - Round Mode in Alpha Depremultiply - 2'b00 : - Result = ((A + 1) * B) >>8; - 2'b01 : - Result = ((A+ (A>>7)) * B) >>8; - 2'b10 : - Result_tmp = A * B + 0x80; - Result = (Result_tmp + (Result_tmp>>8))>>8; - 2'b11 : Reserved - */ - unsigned int alphaDepremultiply:4; - - unsigned int reserved:20; - }data; + unsigned int val; + struct { + /* + Round Mode in Blending + 2'b00 : + Result = ((A + 1) * B) >>8; + 2'b01 : + Result = ((A+ (A>>7)) * B) >>8; + 2'b10 : + Result_tmp = A * B + 0x80; + Result = (Result_tmp + (Result_tmp>>8))>>8; + 2'b11 : + Result_A = A * B; (16 bpp) + Result_B = C * D; (16 bpp) + Result_tmp = Result_A + Result_B + 0x80; + Result = (Result_tmp + (Result_tmp>>8))>>8; + */ + unsigned int blend:4; + /* + Round Mode in Alpha Premultiply + 2'b00 : + Result = (A * B) >>8; + 2'b01 : + Result = ((A + 1) * B) >>8; + 2'b10 : + Result = ((A+ (A>>7)) * B) >>8; + 2'b11 : + Result_tmp = A * B + 0x80; + Result = (Result_tmp + (Result_tmp>>8))>>8; + */ + unsigned int alphaPremultiply:4; + /* + Round Mode in Alpha Depremultiply + 2'b00 : + Result = ((A + 1) * B) >>8; + 2'b01 : + Result = ((A+ (A>>7)) * B) >>8; + 2'b10 : + Result_tmp = A * B + 0x80; + Result = (Result_tmp + (Result_tmp>>8))>>8; + 2'b11 : Reserved + */ + unsigned int alphaDepremultiply:4; + + unsigned int reserved:20; + } data; } G2dRoundModeVal; typedef union _G2D_ROTATE_VAL { - unsigned int val; - struct { - /* - 0 : No rotation - 1 : 90 degree rotation - */ - unsigned int srcRotate:4; - unsigned int patRotate:4; - unsigned int maskRotate:4; - - unsigned int reserved:20; - }data; + unsigned int val; + struct { + /* + 0 : No rotation + 1 : 90 degree rotation + */ + unsigned int srcRotate:4; + unsigned int patRotate:4; + unsigned int maskRotate:4; + + unsigned int reserved:20; + } data; } G2dRotateVal; typedef union _G2D_SRC_MASK_DIR_VAL { - unsigned int val; - struct { - unsigned int dirSrcX:1; - unsigned int dirSrcY:1; - unsigned int reserved1:2; - - unsigned int dirMaskX:1; - unsigned int dirMaskY:1; - unsigned int reserved2:2; - - unsigned int reserved:24; - }data; + unsigned int val; + struct { + unsigned int dirSrcX:1; + unsigned int dirSrcY:1; + unsigned int reserved1:2; + + unsigned int dirMaskX:1; + unsigned int dirMaskY:1; + unsigned int reserved2:2; + + unsigned int reserved:24; + } data; } G2dSrcMaskDirVal; typedef union _G2D_DST_PAT_DIR_VAL { - unsigned int val; - struct { - unsigned int dirDstX:1; - unsigned int dirDstY:1; - unsigned int reserved1:2; - - unsigned int dirPatX:1; - unsigned int dirPatY:1; - unsigned int reserved2:2; - - unsigned int reserved:24; - }data; + unsigned int val; + struct { + unsigned int dirDstX:1; + unsigned int dirDstY:1; + unsigned int reserved1:2; + + unsigned int dirPatX:1; + unsigned int dirPatY:1; + unsigned int reserved2:2; + + unsigned int reserved:24; + } data; } G2dDstPatDirVal; typedef union G2D_POINT_VAL { - unsigned int val; - struct { - /* - X Coordinate of Source Image - Range: 0 ~ 8000 (Requirement: SrcLeftX < SrcRightX) - In YCbCr 422 and YCbCr 420 format, this value should be even number. - */ - unsigned int x:16; - /* - Y Coordinate of Source Image - Range: 0 ~ 8000 (Requirement: SrcTopY < SrcBottomY) - In YCbCr 420 format, this value should be even number. - */ - unsigned int y:16; - }data; + unsigned int val; + struct { + /* + X Coordinate of Source Image + Range: 0 ~ 8000 (Requirement: SrcLeftX < SrcRightX) + In YCbCr 422 and YCbCr 420 format, this value should be even number. + */ + unsigned int x:16; + /* + Y Coordinate of Source Image + Range: 0 ~ 8000 (Requirement: SrcTopY < SrcBottomY) + In YCbCr 420 format, this value should be even number. + */ + unsigned int y:16; + } data; } G2dPointVal; typedef union G2D_BOX_SIZE_VAL { - unsigned int val; - struct { - /* - Width of box. Range: 1 ~ 8000. - */ - unsigned int width:16; - /* - Height of box. Range: 1 ~ 8000. - */ - unsigned int height:16; - }data; + unsigned int val; + struct { + /* + Width of box. Range: 1 ~ 8000. + */ + unsigned int width:16; + /* + Height of box. Range: 1 ~ 8000. + */ + unsigned int height:16; + } data; } G2dBoxSizeVal; typedef union _G2D_SELECT_3RD_VAL { - unsigned int val; - struct{ - G2dSelectMode unmasked:4; - G2dSelectMode masked:4; + unsigned int val; + struct { + G2dSelectMode unmasked:4; + G2dSelectMode masked:4; - unsigned int reserved:24; - }data; + unsigned int reserved:24; + } data; } G2dSelect3rdVal; typedef union _G2D_ROP4_VAL { - unsigned int val; - struct{ - G2dROP3Type unmaskedROP3:8; - G2dROP3Type maskedROP3:8; + unsigned int val; + struct { + G2dROP3Type unmaskedROP3:8; + G2dROP3Type maskedROP3:8; - unsigned int reserved:16; - }data; + unsigned int reserved:16; + } data; } G2dROP4Val; typedef union _G2D_MASK_MODE_VAL { unsigned int val; - struct{ + struct { /* [0:7] */ G2dMaskMode maskMode:4; G2dMaskOrder maskOrder:4; @@ -426,152 +425,153 @@ typedef union _G2D_MASK_MODE_VAL { G2dMaskOpType maskOp:4; /* [12:31] */ unsigned int reserved:20; - }data; + } data; } G2dMaskModeVal; typedef union _G2D_GLOBAL_ARGB_VAL { - unsigned int val; - struct{ - unsigned int alpha:8; - unsigned int color:24; - }data; + unsigned int val; + struct { + unsigned int alpha:8; + unsigned int color:24; + } data; } G2dGlovalARGBVal; typedef union _G2D_COLORKEY_CTL_VAL { - unsigned int val; - struct{ - /* - 0: Stencil Test Off for each RGBA value - 1: Stencil Test On for each RGBA value - */ - unsigned int stencilOnB:4; - unsigned int stencilOnG:4; - unsigned int stencilOnR:4; - unsigned int stencilOnA:4; - unsigned int stencilInv:4; - - unsigned int reserved:12; - }data; + unsigned int val; + struct { + /* + 0: Stencil Test Off for each RGBA value + 1: Stencil Test On for each RGBA value + */ + unsigned int stencilOnB:4; + unsigned int stencilOnG:4; + unsigned int stencilOnR:4; + unsigned int stencilOnA:4; + unsigned int stencilInv:4; + + unsigned int reserved:12; + } data; } G2dColorkeyCtlVal; typedef union _G2D_COLORKEY_DR_MIN_VAL { - unsigned int val; - struct{ - /* - The color format of source colorkey decision reference register is generally the same as the source color format. - If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format. - But if the source color is selected as the foreground color or the background color, - the source colorkey operation is not activated because the colorkeying for the foreground color - and the background color set by user is meaningless. - */ - unsigned int drMinB:8; - unsigned int drMinG:8; - unsigned int drMinR:8; - unsigned int drMinA:8; - }data; + unsigned int val; + struct { + /* + The color format of source colorkey decision reference register is generally the same as the source color format. + If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format. + But if the source color is selected as the foreground color or the background color, + the source colorkey operation is not activated because the colorkeying for the foreground color + and the background color set by user is meaningless. + */ + unsigned int drMinB:8; + unsigned int drMinG:8; + unsigned int drMinR:8; + unsigned int drMinA:8; + } data; } G2dColorkeyDrMinVal; typedef union _G2D_COLORKEY_DR_MAX_VAL { - unsigned int val; - struct{ - /* - The color format of source colorkey decision reference register is generally the same as the source color format. - If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format. - But if the source color is selected as the foreground color or the background color, - the source colorkey operation is not activated because the colorkeying for the foreground color and - the background color set by user is meaningless. - */ - unsigned int drMaxB:8; - unsigned int drMaxG:8; - unsigned int drMaxR:8; - unsigned int drMaxA:8; - }data; + unsigned int val; + struct { + /* + The color format of source colorkey decision reference register is generally the same as the source color format. + If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format. + But if the source color is selected as the foreground color or the background color, + the source colorkey operation is not activated because the colorkeying for the foreground color and + the background color set by user is meaningless. + */ + unsigned int drMaxB:8; + unsigned int drMaxG:8; + unsigned int drMaxR:8; + unsigned int drMaxA:8; + } data; } G2dColorkeyDrMaxVal; typedef union _G2D_COLORKEY_YCBCR_CTL_VAL { - unsigned int val; - struct{ - unsigned int stencilOnCr:4; - unsigned int stencilOnCb:4; - unsigned int stencilOnY:4; - unsigned int stencilInv:4; - - unsigned int reserved:16; - }data; + unsigned int val; + struct { + unsigned int stencilOnCr:4; + unsigned int stencilOnCb:4; + unsigned int stencilOnY:4; + unsigned int stencilInv:4; + + unsigned int reserved:16; + } data; } G2dColorkeyYCbCrCtlVal; typedef union _G2D_COLORKEY_YCBCR_DR_MIN_VAL { - unsigned int val; - struct{ - unsigned int drMinCr:8; - unsigned int drMinCb:8; - unsigned int drMinY:8; - - unsigned int reserved:8; - }data; + unsigned int val; + struct { + unsigned int drMinCr:8; + unsigned int drMinCb:8; + unsigned int drMinY:8; + + unsigned int reserved:8; + } data; } G2dColorkeyYCbCrDrMinVal; typedef union _G2D_COLORKEY_YCBCR_DR_MAX_VAL { - unsigned int val; - struct{ - unsigned int drMaxCr:8; - unsigned int drMaxCb:8; - unsigned int drMaxY:8; - - unsigned int reserved:8; - }data; + unsigned int val; + struct { + unsigned int drMaxCr:8; + unsigned int drMaxCb:8; + unsigned int drMaxY:8; + + unsigned int reserved:8; + } data; } G2dColorkeyYCbCrDrMaxVal; typedef enum { - G2D_OP_CLEAR = 0x00, - G2D_OP_SRC = 0x01, - G2D_OP_DST = 0x02, - G2D_OP_OVER = 0x03, - G2D_OP_OVER_REVERSE = 0x04, - G2D_OP_IN = 0x05, - G2D_OP_IN_REVERSE = 0x06, - G2D_OP_OUT = 0x07, - G2D_OP_OUT_REVERSE = 0x08, - G2D_OP_ATOP = 0x09, - G2D_OP_ATOP_REVERSE = 0x0a, - G2D_OP_XOR = 0x0b, - G2D_OP_ADD = 0x0c, - G2D_OP_SATURATE = 0x0d, - - G2D_OP_DISJOINT_CLEAR = 0x10, - G2D_OP_DISJOINT_SRC = 0x11, - G2D_OP_DISJOINT_DST = 0x12, - G2D_OP_DISJOINT_OVER = 0x13, - G2D_OP_DISJOINT_OVER_REVERSE = 0x14, - G2D_OP_DISJOINT_IN = 0x15, - G2D_OP_DISJOINT_IN_REVERSE = 0x16, - G2D_OP_DISJOINT_OUT = 0x17, - G2D_OP_DISJOINT_OUT_REVERSE = 0x18, - G2D_OP_DISJOINT_ATOP = 0x19, - G2D_OP_DISJOINT_ATOP_REVERSE = 0x1a, - G2D_OP_DISJOINT_XOR = 0x1b, - - G2D_OP_CONJOINT_CLEAR = 0x20, - G2D_OP_CONJOINT_SRC = 0x21, - G2D_OP_CONJOINT_DST = 0x22, - G2D_OP_CONJOINT_OVER = 0x23, - G2D_OP_CONJOINT_OVER_REVERSE = 0x24, - G2D_OP_CONJOINT_IN = 0x25, - G2D_OP_CONJOINT_IN_REVERSE = 0x26, - G2D_OP_CONJOINT_OUT = 0x27, - G2D_OP_CONJOINT_OUT_REVERSE = 0x28, - G2D_OP_CONJOINT_ATOP = 0x29, - G2D_OP_CONJOINT_ATOP_REVERSE = 0x2a, - G2D_OP_CONJOINT_XOR = 0x2b, - - G2D_N_OPERATORS, - G2D_OP_NONE = G2D_N_OPERATORS -}G2dOp; + G2D_OP_CLEAR = 0x00, + G2D_OP_SRC = 0x01, + G2D_OP_DST = 0x02, + G2D_OP_OVER = 0x03, + G2D_OP_OVER_REVERSE = 0x04, + G2D_OP_IN = 0x05, + G2D_OP_IN_REVERSE = 0x06, + G2D_OP_OUT = 0x07, + G2D_OP_OUT_REVERSE = 0x08, + G2D_OP_ATOP = 0x09, + G2D_OP_ATOP_REVERSE = 0x0a, + G2D_OP_XOR = 0x0b, + G2D_OP_ADD = 0x0c, + G2D_OP_SATURATE = 0x0d, + + G2D_OP_DISJOINT_CLEAR = 0x10, + G2D_OP_DISJOINT_SRC = 0x11, + G2D_OP_DISJOINT_DST = 0x12, + G2D_OP_DISJOINT_OVER = 0x13, + G2D_OP_DISJOINT_OVER_REVERSE = 0x14, + G2D_OP_DISJOINT_IN = 0x15, + G2D_OP_DISJOINT_IN_REVERSE = 0x16, + G2D_OP_DISJOINT_OUT = 0x17, + G2D_OP_DISJOINT_OUT_REVERSE = 0x18, + G2D_OP_DISJOINT_ATOP = 0x19, + G2D_OP_DISJOINT_ATOP_REVERSE = 0x1a, + G2D_OP_DISJOINT_XOR = 0x1b, + + G2D_OP_CONJOINT_CLEAR = 0x20, + G2D_OP_CONJOINT_SRC = 0x21, + G2D_OP_CONJOINT_DST = 0x22, + G2D_OP_CONJOINT_OVER = 0x23, + G2D_OP_CONJOINT_OVER_REVERSE = 0x24, + G2D_OP_CONJOINT_IN = 0x25, + G2D_OP_CONJOINT_IN_REVERSE = 0x26, + G2D_OP_CONJOINT_OUT = 0x27, + G2D_OP_CONJOINT_OUT_REVERSE = 0x28, + G2D_OP_CONJOINT_ATOP = 0x29, + G2D_OP_CONJOINT_ATOP_REVERSE = 0x2a, + G2D_OP_CONJOINT_XOR = 0x2b, + + G2D_N_OPERATORS, + G2D_OP_NONE = G2D_N_OPERATORS +} G2dOp; + #define G2D_OP_DEFAULT G2D_OP_NONE #define G2D_PLANE_MAX 2 -typedef struct _G2D_IMAGE G2dImage; +typedef struct _G2D_IMAGE G2dImage; struct _G2D_IMAGE { G2dSelectMode select_mode; G2dColorMode color_mode; @@ -585,16 +585,16 @@ struct _G2D_IMAGE { unsigned char xDir; unsigned char yDir; unsigned char componentAlpha; - + unsigned int width; unsigned int height; unsigned int stride; unsigned int need_free; - union{ - unsigned int color; - unsigned int bo[G2D_PLANE_MAX]; - }data; + union { + unsigned int color; + unsigned int bo[G2D_PLANE_MAX]; + } data; void *mapped_ptr[G2D_PLANE_MAX]; }; @@ -610,61 +610,61 @@ struct _G2D_IMAGE { int g2d_init(int fd); void g2d_fini(void); int g2d_add_cmd(unsigned int cmd, unsigned int value); -void g2d_reset (unsigned int clear_reg); +void g2d_reset(unsigned int clear_reg); int g2d_exec(void); int g2d_flush(void); void g2d_dump(void); -G2dImage* g2d_image_create_solid(unsigned int color); -G2dImage* g2d_image_create_bo(G2dColorMode format, - unsigned int width, unsigned int height, - unsigned int bo, unsigned int stride); -G2dImage* g2d_image_create_bo2 (G2dColorMode format, - unsigned int width, unsigned int height, - unsigned int bo1, unsigned int bo2, unsigned int stride); -G2dImage* g2d_image_create_data (G2dColorMode format, - unsigned int width, unsigned int height, - void* data, unsigned int stride); - -void g2d_image_free (G2dImage* img); - -int g2d_set_src(G2dImage* img); -int g2d_set_dst(G2dImage* img); -int g2d_set_mask(G2dImage* img); +G2dImage *g2d_image_create_solid(unsigned int color); +G2dImage *g2d_image_create_bo(G2dColorMode format, + unsigned int width, unsigned int height, + unsigned int bo, unsigned int stride); +G2dImage *g2d_image_create_bo2(G2dColorMode format, + unsigned int width, unsigned int height, + unsigned int bo1, unsigned int bo2, + unsigned int stride); +G2dImage *g2d_image_create_data(G2dColorMode format, unsigned int width, + unsigned int height, void *data, + unsigned int stride); + +void g2d_image_free(G2dImage * img); + +int g2d_set_src(G2dImage * img); +int g2d_set_dst(G2dImage * img); +int g2d_set_mask(G2dImage * img); unsigned int g2d_get_blend_op(G2dOp op); /* UTIL Functions */ -void util_g2d_fill(G2dImage* img, - int x, int y, unsigned int w, unsigned int h, - unsigned int color); -void util_g2d_fill_alu(G2dImage* img, - int x, int y, unsigned int w, unsigned int h, - unsigned int color, G2dAlu alu); -void util_g2d_copy(G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height); -void util_g2d_copy_alu(G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height, - G2dAlu alu); -void util_g2d_copy_with_scale(G2dImage* src, G2dImage* dst, - int src_x, int src_y, unsigned int src_w, unsigned int src_h, - int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h, - int negative); -void util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height); -void util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst, - int src_x, int src_y, unsigned int src_w, unsigned int src_h, - int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h, - int negative); -void util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst, - int src_x, int src_y, - int mask_x, int mask_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height); - -#endif /* _FIMG2D3X_H_ */ +void util_g2d_fill(G2dImage * img, + int x, int y, unsigned int w, unsigned int h, + unsigned int color); +void util_g2d_fill_alu(G2dImage * img, + int x, int y, unsigned int w, unsigned int h, + unsigned int color, G2dAlu alu); +void util_g2d_copy(G2dImage * src, G2dImage * dst, + int src_x, int src_y, + int dst_x, int dst_y, + unsigned int width, unsigned int height); +void util_g2d_copy_alu(G2dImage * src, G2dImage * dst, + int src_x, int src_y, + int dst_x, int dst_y, + unsigned int width, unsigned int height, G2dAlu alu); +void util_g2d_copy_with_scale(G2dImage * src, G2dImage * dst, + int src_x, int src_y, unsigned int src_w, + unsigned int src_h, int dst_x, int dst_y, + unsigned int dst_w, unsigned int dst_h, + int negative); +void util_g2d_blend(G2dOp op, G2dImage * src, G2dImage * dst, int src_x, + int src_y, int dst_x, int dst_y, unsigned int width, + unsigned int height); +void util_g2d_blend_with_scale(G2dOp op, G2dImage * src, G2dImage * dst, + int src_x, int src_y, unsigned int src_w, + unsigned int src_h, int dst_x, int dst_y, + unsigned int dst_w, unsigned int dst_h, + int negative); +void util_g2d_composite(G2dOp op, G2dImage * src, G2dImage * mask, + G2dImage * dst, int src_x, int src_y, int mask_x, + int mask_y, int dst_x, int dst_y, unsigned int width, + unsigned int height); + +#endif /* _FIMG2D3X_H_ */ diff --git a/src/g2d/fimg2d_reg.h b/src/g2d/fimg2d_reg.h index 97813c8..f112174 100755 --- a/src/g2d/fimg2d_reg.h +++ b/src/g2d/fimg2d_reg.h @@ -21,8 +21,8 @@ */ #define BITBLT_START_REG (0x0100) #define BITBLT_COMMAND_REG (0x0104) -#define BLEND_FUNCTION_REG (0x0108) /* VER4.1 */ -#define ROUND_MODE_REG (0x010C) /* VER4.1 */ +#define BLEND_FUNCTION_REG (0x0108) /* VER4.1 */ +#define ROUND_MODE_REG (0x010C) /* VER4.1 */ /* * PARAMETER SETTING REGISTER @@ -40,8 +40,8 @@ #define SRC_COLOR_MODE_REG (0x030c) #define SRC_LEFT_TOP_REG (0x0310) #define SRC_RIGHT_BOTTOM_REG (0x0314) -#define SRC_PLANE2_BASE_ADDR_REG (0x0318) /* VER4.1 */ -#define SRC_REPEAT_MODE_REG (0x031C) +#define SRC_PLANE2_BASE_ADDR_REG (0x0318) /* VER4.1 */ +#define SRC_REPEAT_MODE_REG (0x031C) #define SRC_PAD_VALUE_REG (0x0320) #define SRC_A8_RGB_EXT_REG (0x0324) #define SRC_SCALE_CTRL_REG (0x0328) @@ -55,7 +55,7 @@ #define DST_COLOR_MODE_REG (0x040C) #define DST_LEFT_TOP_REG (0x0410) #define DST_RIGHT_BOTTOM_REG (0x0414) -#define DST_PLANE2_BASE_ADDR_REG (0x0418) /* VER4.1 */ +#define DST_PLANE2_BASE_ADDR_REG (0x0418) /* VER4.1 */ #define DST_A8_RGB_EXT_REG (0x041C) /* PATTERN */ @@ -68,9 +68,9 @@ /* MASK */ #define MASK_BASE_ADDR_REG (0x0520) #define MASK_STRIDE_REG (0x0524) -#define MASK_LEFT_TOP_REG (0x0528) /* VER4.1 */ -#define MASK_RIGHT_BOTTOM_REG (0x052C) /* VER4.1 */ -#define MASK_MODE_REG (0x0530) /* VER4.1 */ +#define MASK_LEFT_TOP_REG (0x0528) /* VER4.1 */ +#define MASK_RIGHT_BOTTOM_REG (0x052C) /* VER4.1 */ +#define MASK_MODE_REG (0x0530) /* VER4.1 */ #define MASK_REPEAT_MODE_REG (0x0534) #define MASK_PAD_VALUE_REG (0x0538) #define MASK_SCALE_CTRL_REG (0x053C) @@ -96,7 +96,7 @@ #define FG_COLOR_REG (0x0700) #define BG_COLOR_REG (0x0704) #define BS_COLOR_REG (0x0708) -#define SF_COLOR_REG (0x070C) /* VER4.1 */ +#define SF_COLOR_REG (0x070C) /* VER4.1 */ /* * COLOR KEY @@ -108,13 +108,12 @@ #define DST_COLORKEY_DR_MIN_REG (0x0720) #define DST_COLORKEY_DR_MAX_REG (0x0724) /* YCbCr src Color Key */ -#define YCbCr_SRC_COLORKEY_CTRL_REG (0x0728) /* VER4.1 */ -#define YCbCr_SRC_COLORKEY_DR_MIN_REG (0x072C) /* VER4.1 */ -#define YCbCr_SRC_COLORKEY_DR_MAX_REG (0x0730) /* VER4.1 */ +#define YCbCr_SRC_COLORKEY_CTRL_REG (0x0728) /* VER4.1 */ +#define YCbCr_SRC_COLORKEY_DR_MIN_REG (0x072C) /* VER4.1 */ +#define YCbCr_SRC_COLORKEY_DR_MAX_REG (0x0730) /* VER4.1 */ /* YCbCr dst Color Key */ -#define YCbCr_DST_COLORKEY_CTRL_REG (0x0734) /* VER4.1 */ -#define YCbCr_DST_COLORKEY_DR_MIN_REG (0x0738) /* VER4.1 */ -#define YCbCr_DST_COLORKEY_DR_MAX_REG (0x073C) /* VER4.1 */ +#define YCbCr_DST_COLORKEY_CTRL_REG (0x0734) /* VER4.1 */ +#define YCbCr_DST_COLORKEY_DR_MIN_REG (0x0738) /* VER4.1 */ +#define YCbCr_DST_COLORKEY_DR_MAX_REG (0x073C) /* VER4.1 */ #endif - diff --git a/src/g2d/util_g2d.c b/src/g2d/util_g2d.c index 7c5f2d7..400de56 100644 --- a/src/g2d/util_g2d.c +++ b/src/g2d/util_g2d.c @@ -1,13 +1,17 @@ +#include <xorg-server.h> #include <stdio.h> +#include <stdio.h> + +#include <xorg-server.h> #include "xf86.h" #include "fimg2d.h" -#include "sec_util.h" +#include "exynos_util.h" static int -_util_get_clip(G2dImage* img, int x, int y, int width, int height, G2dPointVal *lt, G2dPointVal *rb) +_util_get_clip(G2dImage * img, int x, int y, int width, int height, + G2dPointVal * lt, G2dPointVal * rb) { - if(img->select_mode != G2D_SELECT_MODE_NORMAL) - { + if (img->select_mode != G2D_SELECT_MODE_NORMAL) { lt->data.x = 0; lt->data.y = 0; rb->data.x = 1; @@ -15,34 +19,28 @@ _util_get_clip(G2dImage* img, int x, int y, int width, int height, G2dPointVal * return 1; } - if(x<0) - { + if (x < 0) { width += x; - x=0; + x = 0; } - if(y<0) - { + if (y < 0) { height += y; - y=0; + y = 0; } - if(x+width > img->width) - { + if (x + width > img->width) { width = img->width - x; } - if(y+height > img->height) - { + if (y + height > img->height) { height = img->height - y; } - if(width <= 0 || height <= 0) - { - if(img->repeat_mode != G2D_REPEAT_MODE_NONE) - { - x=0; - y=0; + if (width <= 0 || height <= 0) { + if (img->repeat_mode != G2D_REPEAT_MODE_NONE) { + x = 0; + y = 0; width = img->width; height = img->height; return 1; @@ -53,18 +51,17 @@ _util_get_clip(G2dImage* img, int x, int y, int width, int height, G2dPointVal * lt->data.x = x; lt->data.y = y; - rb->data.x = x+width; - rb->data.y = y+height; + rb->data.x = x + width; + rb->data.y = y + height; return 1; } void -util_g2d_fill(G2dImage* img, - int x, int y, unsigned int w, unsigned int h, - unsigned int color) +util_g2d_fill(G2dImage * img, + int x, int y, unsigned int w, unsigned int h, unsigned int color) { - G2dBitBltCmdVal bitblt={0,}; + G2dBitBltCmdVal bitblt = { 0, }; G2dPointVal lt, rb; g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR); @@ -72,20 +69,20 @@ util_g2d_fill(G2dImage* img, g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, img->stride); - /*Set Geometry*/ - if(!_util_get_clip(img, x, y, w, h, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + /*Set Geometry */ + if (!_util_get_clip(img, x, y, w, h, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } g2d_add_cmd(DST_LEFT_TOP_REG, lt.val); g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val); - /*set Src Image*/ + /*set Src Image */ g2d_add_cmd(SF_COLOR_REG, color); - /*Set G2D Command*/ + /*Set G2D Command */ bitblt.val = 0; bitblt.data.fastSolidColorFillEn = 1; g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val); @@ -95,76 +92,75 @@ util_g2d_fill(G2dImage* img, } void -util_g2d_fill_alu(G2dImage* img, - int x, int y, unsigned int w, unsigned int h, - unsigned int color, G2dAlu alu) +util_g2d_fill_alu(G2dImage * img, + int x, int y, unsigned int w, unsigned int h, + unsigned int color, G2dAlu alu) { - G2dBitBltCmdVal bitblt={0,}; + G2dBitBltCmdVal bitblt = { 0, }; G2dROP4Val rop4; G2dPointVal lt, rb; _X_UNUSED unsigned int bg_color; unsigned int dst_mode = G2D_SELECT_MODE_BGCOLOR; G2dROP3Type rop3 = 0; - switch(alu) - { - case G2Dclear: /* 0 */ + switch (alu) { + case G2Dclear: /* 0 */ color = 0x00000000; break; - case G2Dand: /* src AND dst */ + case G2Dand: /* src AND dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC & G2D_ROP3_DST; break; - case G2DandReverse: /* src AND NOT dst */ + case G2DandReverse: /* src AND NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC & (~G2D_ROP3_DST); break; - case G2Dcopy: /* src */ + case G2Dcopy: /* src */ break; - case G2DandInverted: /* NOT src AND dst */ + case G2DandInverted: /* NOT src AND dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) & G2D_ROP3_DST; break; - case G2Dnoop: /* dst */ + case G2Dnoop: /* dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_DST; break; - case G2Dxor: /* src XOR dst */ + case G2Dxor: /* src XOR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST; break; - case G2Dor: /* src OR dst */ + case G2Dor: /* src OR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC | G2D_ROP3_DST; break; - case G2Dnor: /* NOT src AND NOT dst */ + case G2Dnor: /* NOT src AND NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) & (~G2D_ROP3_DST); break; - case G2Dequiv: /* NOT src XOR dst */ + case G2Dequiv: /* NOT src XOR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) ^ G2D_ROP3_DST; break; - case G2Dinvert: /* NOT dst */ + case G2Dinvert: /* NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = ~G2D_ROP3_DST; break; - case G2DorReverse: /* src OR NOT dst */ + case G2DorReverse: /* src OR NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; - rop3 = G2D_ROP3_SRC |( ~G2D_ROP3_DST); + rop3 = G2D_ROP3_SRC | (~G2D_ROP3_DST); break; - case G2DcopyInverted: /* NOT src */ + case G2DcopyInverted: /* NOT src */ rop3 = ~G2D_ROP3_SRC; break; - case G2DorInverted: /* NOT src OR dst */ + case G2DorInverted: /* NOT src OR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) | G2D_ROP3_DST; break; - case G2Dnand: /* NOT src OR NOT dst */ + case G2Dnand: /* NOT src OR NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) | (~G2D_ROP3_DST); break; - case G2Dset: /* 1 */ + case G2Dset: /* 1 */ color = 0xFFFFFFFF; break; case G2Dnegative: @@ -175,39 +171,38 @@ util_g2d_fill_alu(G2dImage* img, break; } - /*set Dst Image*/ + /*set Dst Image */ g2d_add_cmd(DST_SELECT_REG, dst_mode); g2d_add_cmd(DST_COLOR_MODE_REG, img->color_mode); g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, img->stride); - /*Set Geometry*/ - if(!_util_get_clip(img, x, y, w, h, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + /*Set Geometry */ + if (!_util_get_clip(img, x, y, w, h, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } g2d_add_cmd(DST_LEFT_TOP_REG, lt.val); g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val); - /*set ROP4 val*/ - if(rop3 != 0) - { - /*set Src Image*/ + /*set ROP4 val */ + if (rop3 != 0) { + /*set Src Image */ g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_FGCOLOR); - g2d_add_cmd(SRC_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); + g2d_add_cmd(SRC_COLOR_MODE_REG, + G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); g2d_add_cmd(FG_COLOR_REG, color); rop4.val = 0; rop4.data.unmaskedROP3 = rop3; g2d_add_cmd(ROP4_REG, rop4.val); } - else - { + else { g2d_add_cmd(SF_COLOR_REG, color); - /*Set G2D Command*/ + /*Set G2D Command */ bitblt.val = 0; bitblt.data.fastSolidColorFillEn = 1; g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val); @@ -218,55 +213,54 @@ util_g2d_fill_alu(G2dImage* img, } void -util_g2d_copy(G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height) +util_g2d_copy(G2dImage * src, G2dImage * dst, + int src_x, int src_y, + int dst_x, int dst_y, unsigned int width, unsigned int height) { G2dROP4Val rop4; G2dPointVal lt, rb; - /*Set dst*/ + /*Set dst */ g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode); g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); - if (dst->color_mode & G2D_YCbCr_2PLANE) - { + if (dst->color_mode & G2D_YCbCr_2PLANE) { if (dst->data.bo[1] > 0) g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]); else - XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + XDBG_ERROR(MG2D, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ + /*Set src */ g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode); g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]); - if (src->color_mode & G2D_YCbCr_2PLANE) - { + if (src->color_mode & G2D_YCbCr_2PLANE) { if (src->data.bo[1] > 0) g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, src->data.bo[1]); else - XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + XDBG_ERROR(MG2D, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(SRC_STRIDE_REG, src->stride); - if(src->repeat_mode) + if (src->repeat_mode) g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode); - /*Set cmd*/ - if(!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + /*Set cmd */ + if (!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val); g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val); - if(!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + if (!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } @@ -281,81 +275,79 @@ util_g2d_copy(G2dImage* src, G2dImage* dst, } void -util_g2d_copy_alu(G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height, - G2dAlu alu) +util_g2d_copy_alu(G2dImage * src, G2dImage * dst, + int src_x, int src_y, + int dst_x, int dst_y, + unsigned int width, unsigned int height, G2dAlu alu) { G2dROP4Val rop4; G2dPointVal lt, rb; unsigned int dst_mode = G2D_SELECT_MODE_BGCOLOR; unsigned int src_mode = G2D_SELECT_MODE_NORMAL; - G2dROP3Type rop3=0; + G2dROP3Type rop3 = 0; unsigned int fg_color = 0, bg_color = 0; - /*Select alu*/ - switch(alu) - { - case G2Dclear: /* 0 */ + /*Select alu */ + switch (alu) { + case G2Dclear: /* 0 */ src_mode = G2D_SELECT_MODE_FGCOLOR; fg_color = 0x00000000; break; - case G2Dand: /* src AND dst */ + case G2Dand: /* src AND dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC & G2D_ROP3_DST; break; - case G2DandReverse: /* src AND NOT dst */ + case G2DandReverse: /* src AND NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC & (~G2D_ROP3_DST); break; - case G2Dcopy: /* src */ + case G2Dcopy: /* src */ rop3 = G2D_ROP3_SRC; break; - case G2DandInverted: /* NOT src AND dst */ + case G2DandInverted: /* NOT src AND dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) & G2D_ROP3_DST; break; - case G2Dnoop: /* dst */ + case G2Dnoop: /* dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_DST; break; - case G2Dxor: /* src XOR dst */ + case G2Dxor: /* src XOR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST; break; - case G2Dor: /* src OR dst */ + case G2Dor: /* src OR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = G2D_ROP3_SRC | G2D_ROP3_DST; break; - case G2Dnor: /* NOT src AND NOT dst */ + case G2Dnor: /* NOT src AND NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) & (~G2D_ROP3_DST); break; - case G2Dequiv: /* NOT src XOR dst */ + case G2Dequiv: /* NOT src XOR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) ^ G2D_ROP3_DST; break; - case G2Dinvert: /* NOT dst */ + case G2Dinvert: /* NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = ~G2D_ROP3_DST; break; - case G2DorReverse: /* src OR NOT dst */ + case G2DorReverse: /* src OR NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; - rop3 = G2D_ROP3_SRC |( ~G2D_ROP3_DST); + rop3 = G2D_ROP3_SRC | (~G2D_ROP3_DST); break; - case G2DcopyInverted: /* NOT src */ + case G2DcopyInverted: /* NOT src */ rop3 = ~G2D_ROP3_SRC; break; - case G2DorInverted: /* NOT src OR dst */ + case G2DorInverted: /* NOT src OR dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) | G2D_ROP3_DST; break; - case G2Dnand: /* NOT src OR NOT dst */ + case G2Dnand: /* NOT src OR NOT dst */ dst_mode = G2D_SELECT_MODE_NORMAL; rop3 = (~G2D_ROP3_SRC) | (~G2D_ROP3_DST); break; - case G2Dset: /* 1 */ + case G2Dset: /* 1 */ src_mode = G2D_SELECT_MODE_FGCOLOR; fg_color = 0xFFFFFFFF; rop3 = G2D_ROP3_DST; @@ -368,51 +360,49 @@ util_g2d_copy_alu(G2dImage* src, G2dImage* dst, break; } - /*Set dst*/ - if(dst_mode != G2D_SELECT_MODE_NORMAL) - { + /*Set dst */ + if (dst_mode != G2D_SELECT_MODE_NORMAL) { g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); - g2d_add_cmd(DST_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); + g2d_add_cmd(DST_COLOR_MODE_REG, + G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); g2d_add_cmd(BG_COLOR_REG, bg_color); } - else - { + else { g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode); } g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ - if(src_mode != G2D_SELECT_MODE_NORMAL) - { + /*Set src */ + if (src_mode != G2D_SELECT_MODE_NORMAL) { g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_FGCOLOR); - g2d_add_cmd(SRC_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); + g2d_add_cmd(SRC_COLOR_MODE_REG, + G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB); g2d_add_cmd(FG_COLOR_REG, fg_color); } - else - { + else { g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode); g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]); g2d_add_cmd(SRC_STRIDE_REG, src->stride); - if(src->repeat_mode) + if (src->repeat_mode) g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode); } - /*Set cmd*/ - if(!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + /*Set cmd */ + if (!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val); g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val); - if(!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + if (!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } @@ -427,89 +417,84 @@ util_g2d_copy_alu(G2dImage* src, G2dImage* dst, } void -util_g2d_copy_with_scale(G2dImage* src, G2dImage* dst, - int src_x, int src_y, unsigned int src_w, unsigned int src_h, - int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h, - int negative) +util_g2d_copy_with_scale(G2dImage * src, G2dImage * dst, + int src_x, int src_y, unsigned int src_w, + unsigned int src_h, int dst_x, int dst_y, + unsigned int dst_w, unsigned int dst_h, int negative) { G2dROP4Val rop4; G2dPointVal pt; int bScale; - double scalex=1.0, scaley=1.0; + double scalex = 1.0, scaley = 1.0; - /*Set dst*/ + /*Set dst */ g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode); g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ + /*Set src */ g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode); g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]); g2d_add_cmd(SRC_STRIDE_REG, src->stride); - /*Set cmd*/ - if(src_w == dst_w && src_h == dst_h) + /*Set cmd */ + if (src_w == dst_w && src_h == dst_h) bScale = 0; - else - { + else { bScale = 1; - scalex = (double)src_w/(double)dst_w; - scaley = (double)src_h/(double)dst_h; + scalex = (double) src_w / (double) dst_w; + scaley = (double) src_h / (double) dst_h; } - if(src_x < 0) - { + if (src_x < 0) { src_w += src_x; src_x = 0; } - if(src_y < 0) - { + if (src_y < 0) { src_h += src_y; src_y = 0; } - if(src_x+src_w > src->width) src_w = src->width - src_x; - if(src_y+src_h > src->height) src_h = src->height - src_y; + if (src_x + src_w > src->width) + src_w = src->width - src_x; + if (src_y + src_h > src->height) + src_h = src->height - src_y; - if(dst_x < 0) - { + if (dst_x < 0) { dst_w += dst_x; dst_x = 0; } - if(dst_y < 0) - { + if (dst_y < 0) { dst_h += dst_y; dst_y = 0; } - if(dst_x+dst_w > dst->width) dst_w = dst->width - dst_x; - if(dst_y+dst_h > dst->height) dst_h = dst->height - dst_y; + if (dst_x + dst_w > dst->width) + dst_w = dst->width - dst_x; + if (dst_y + dst_h > dst->height) + dst_h = dst->height - dst_y; - if(src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) - { - XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n"); + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { + XDBG_ERROR(MG2D, "[G2D] error: invalid geometry\n"); g2d_reset(0); return; } - if(negative) - { + if (negative) { g2d_add_cmd(BG_COLOR_REG, 0x00FFFFFF); rop4.val = 0; - rop4.data.unmaskedROP3 = G2D_ROP3_SRC^G2D_ROP3_DST; + rop4.data.unmaskedROP3 = G2D_ROP3_SRC ^ G2D_ROP3_DST; g2d_add_cmd(ROP4_REG, rop4.val); } - else - { + else { rop4.val = 0; rop4.data.unmaskedROP3 = G2D_ROP3_SRC; g2d_add_cmd(ROP4_REG, rop4.val); } - if(bScale) - { + if (bScale) { g2d_add_cmd(SRC_SCALE_CTRL_REG, G2D_SCALE_MODE_BILINEAR); g2d_add_cmd(SRC_XSCALE_REG, G2D_DOUBLE_TO_FIXED(scalex)); g2d_add_cmd(SRC_YSCALE_REG, G2D_DOUBLE_TO_FIXED(scaley)); @@ -517,31 +502,29 @@ util_g2d_copy_with_scale(G2dImage* src, G2dImage* dst, pt.data.x = src_x; pt.data.y = src_y; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(SRC_LEFT_TOP_REG, pt.val); pt.data.x = src_x + src_w; pt.data.y = src_y + src_h; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val); - pt.data.x = dst_x; pt.data.y = dst_y; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(DST_LEFT_TOP_REG, pt.val); pt.data.x = dst_x + dst_w; pt.data.y = dst_y + dst_h; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(DST_RIGHT_BOTTOM_REG, pt.val); g2d_flush(); } void -util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height) +util_g2d_blend(G2dOp op, G2dImage * src, G2dImage * dst, + int src_x, int src_y, + int dst_x, int dst_y, unsigned int width, unsigned int height) { G2dBitBltCmdVal bitblt; G2dBlendFunctionVal blend; @@ -550,8 +533,8 @@ util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, bitblt.val = 0; blend.val = 0; - /*Set dst*/ - if(op == G2D_OP_SRC || op == G2D_OP_CLEAR) + /*Set dst */ + if (op == G2D_OP_SRC || op == G2D_OP_CLEAR) g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); else g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); @@ -559,23 +542,30 @@ util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ + /*Set src */ g2d_set_src(src); - /*Set cmd*/ - if(src_x < 0) src_x = 0; - if(src_y < 0) src_y = 0; - if(src_x+width > src->width) width = src->width - src_x; - if(src_y+height > src->height) height = src->height - src_y; + /*Set cmd */ + if (src_x < 0) + src_x = 0; + if (src_y < 0) + src_y = 0; + if (src_x + width > src->width) + width = src->width - src_x; + if (src_y + height > src->height) + height = src->height - src_y; - if(dst_x < 0) dst_x = 0; - if(dst_y < 0) dst_y = 0; - if(dst_x+width > dst->width) width = dst->width - dst_x; - if(dst_y+height > dst->height) height = dst->height - dst_y; + if (dst_x < 0) + dst_x = 0; + if (dst_y < 0) + dst_y = 0; + if (dst_x + width > dst->width) + width = dst->width - dst_x; + if (dst_y + height > dst->height) + height = dst->height - dst_y; - if(width <= 0 || height <= 0) - { - XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n"); + if (width <= 0 || height <= 0) { + XDBG_ERROR(MG2D, "[G2D] error: invalid geometry\n"); g2d_reset(0); return; } @@ -592,7 +582,6 @@ util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, pt.data.y = src_y + height; g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val); - pt.data.x = dst_x; pt.data.y = dst_y; g2d_add_cmd(DST_LEFT_TOP_REG, pt.val); @@ -604,15 +593,15 @@ util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, } void -util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst, - int src_x, int src_y, unsigned int src_w, unsigned int src_h, - int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h, - int negative) +util_g2d_blend_with_scale(G2dOp op, G2dImage * src, G2dImage * dst, + int src_x, int src_y, unsigned int src_w, + unsigned int src_h, int dst_x, int dst_y, + unsigned int dst_w, unsigned int dst_h, int negative) { G2dROP4Val rop4; G2dPointVal pt; int bScale; - double scalex=1.0, scaley=1.0; + double scalex = 1.0, scaley = 1.0; G2dRotateVal rotate; G2dSrcMaskDirVal dir; int rotate_w, rotate_h; @@ -624,109 +613,99 @@ util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst, rotate.val = 0; dir.val = 0; - if(src_x < 0) - { + if (src_x < 0) { src_w += src_x; src_x = 0; } - if(src_y < 0) - { + if (src_y < 0) { src_h += src_y; src_y = 0; } - if(src_x+src_w > src->width) + if (src_x + src_w > src->width) src_w = src->width - src_x; - if(src_y+src_h > src->height) + if (src_y + src_h > src->height) src_h = src->height - src_y; - if(dst_x < 0) - { + if (dst_x < 0) { dst_w += dst_x; dst_x = 0; } - if(dst_y < 0) - { + if (dst_y < 0) { dst_h += dst_y; dst_y = 0; } - if(dst_x+dst_w > dst->width) + if (dst_x + dst_w > dst->width) dst_w = dst->width - dst_x; - if(dst_y+dst_h > dst->height) + if (dst_y + dst_h > dst->height) dst_h = dst->height - dst_y; - if(src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) - { - XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n"); + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { + XDBG_ERROR(MG2D, "[G2D] error: invalid geometry\n"); g2d_reset(0); return; } - /*Set dst*/ - if(op == G2D_OP_SRC || op == G2D_OP_CLEAR) + /*Set dst */ + if (op == G2D_OP_SRC || op == G2D_OP_CLEAR) g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); else g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode); g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); - if (dst->color_mode & G2D_YCbCr_2PLANE) - { + if (dst->color_mode & G2D_YCbCr_2PLANE) { if (dst->data.bo[1] > 0) g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]); else - fprintf(stderr, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + fprintf(stderr, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ + /*Set src */ g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode); g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]); - if (src->color_mode & G2D_YCbCr_2PLANE) - { + if (src->color_mode & G2D_YCbCr_2PLANE) { if (src->data.bo[1] > 0) g2d_add_cmd(SRC_PLANE2_BASE_ADDR_REG, src->data.bo[1]); else - fprintf(stderr, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + fprintf(stderr, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(SRC_STRIDE_REG, src->stride); - /*Set cmd*/ - rotate_w = (src->rotate_90)?dst_h:dst_w; - rotate_h = (src->rotate_90)?dst_w:dst_h; + /*Set cmd */ + rotate_w = (src->rotate_90) ? dst_h : dst_w; + rotate_h = (src->rotate_90) ? dst_w : dst_h; - if(src_w == rotate_w && src_h == rotate_h) + if (src_w == rotate_w && src_h == rotate_h) bScale = 0; - else - { + else { bScale = 1; - scalex = (double)src_w/(double)rotate_w; - scaley = (double)src_h/(double)rotate_h; + scalex = (double) src_w / (double) rotate_w; + scaley = (double) src_h / (double) rotate_h; } - if(negative) - { + if (negative) { g2d_add_cmd(BG_COLOR_REG, 0x00FFFFFF); rop4.val = 0; - rop4.data.unmaskedROP3 = G2D_ROP3_SRC^G2D_ROP3_DST; + rop4.data.unmaskedROP3 = G2D_ROP3_SRC ^ G2D_ROP3_DST; g2d_add_cmd(ROP4_REG, rop4.val); } - else - { + else { rop4.val = 0; rop4.data.unmaskedROP3 = G2D_ROP3_SRC; g2d_add_cmd(ROP4_REG, rop4.val); } - if(bScale) - { + if (bScale) { g2d_add_cmd(SRC_SCALE_CTRL_REG, G2D_SCALE_MODE_BILINEAR); g2d_add_cmd(SRC_XSCALE_REG, G2D_DOUBLE_TO_FIXED(scalex)); g2d_add_cmd(SRC_YSCALE_REG, G2D_DOUBLE_TO_FIXED(scaley)); } - if(src->rotate_90 || src->xDir || src->yDir) - { + if (src->rotate_90 || src->xDir || src->yDir) { rotate.data.srcRotate = src->rotate_90; dir.data.dirSrcX = src->xDir; dir.data.dirSrcY = src->yDir; @@ -734,24 +713,23 @@ util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst, pt.data.x = src_x; pt.data.y = src_y; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(SRC_LEFT_TOP_REG, pt.val); pt.data.x = src_x + src_w; pt.data.y = src_y + src_h; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val); pt.data.x = dst_x; pt.data.y = dst_y; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(DST_LEFT_TOP_REG, pt.val); pt.data.x = dst_x + dst_w; pt.data.y = dst_y + dst_h; - pt.val = (pt.data.y << 16) | pt.data.x ; + pt.val = (pt.data.y << 16) | pt.data.x; g2d_add_cmd(DST_RIGHT_BOTTOM_REG, pt.val); - if(op != G2D_OP_SRC || op != G2D_OP_CLEAR) - { + if (op != G2D_OP_SRC || op != G2D_OP_CLEAR) { bitblt.data.alphaBlendMode = G2D_ALPHA_BLEND_MODE_ENABLE; blend.val = g2d_get_blend_op(op); g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val); @@ -765,11 +743,11 @@ util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst, } void -util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst, - int src_x, int src_y, - int mask_x, int mask_y, - int dst_x, int dst_y, - unsigned int width, unsigned int height) +util_g2d_composite(G2dOp op, G2dImage * src, G2dImage * mask, G2dImage * dst, + int src_x, int src_y, + int mask_x, int mask_y, + int dst_x, int dst_y, + unsigned int width, unsigned int height) { G2dBitBltCmdVal bitblt; G2dBlendFunctionVal blend; @@ -782,86 +760,78 @@ util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst, rotate.val = 0; dir.val = 0; - /*Set dst*/ - if(op == G2D_OP_SRC || op == G2D_OP_CLEAR) + /*Set dst */ + if (op == G2D_OP_SRC || op == G2D_OP_CLEAR) g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR); else g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL); g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode); g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]); - if (dst->color_mode & G2D_YCbCr_2PLANE) - { + if (dst->color_mode & G2D_YCbCr_2PLANE) { if (dst->data.bo[1] > 0) g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]); else - XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__); + XDBG_ERROR(MG2D, "[G2D] %s:%d error: exynosond bo is null.\n", + __FUNCTION__, __LINE__); } g2d_add_cmd(DST_STRIDE_REG, dst->stride); - /*Set src*/ + /*Set src */ g2d_set_src(src); - if(src->repeat_mode) - { + if (src->repeat_mode) { g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode); } - if(src->scale_mode) - { + if (src->scale_mode) { g2d_add_cmd(SRC_XSCALE_REG, src->xscale); g2d_add_cmd(SRC_YSCALE_REG, src->yscale); g2d_add_cmd(SRC_SCALE_CTRL_REG, src->scale_mode); } - if(src->rotate_90 || src->xDir || src->yDir) - { + if (src->rotate_90 || src->xDir || src->yDir) { rotate.data.srcRotate = src->rotate_90; dir.data.dirSrcX = src->xDir; dir.data.dirSrcY = src->yDir; } - /*Set Mask*/ - if(mask) - { + /*Set Mask */ + if (mask) { bitblt.data.maskingEn = 1; g2d_set_mask(mask); - if(mask->repeat_mode) - { + if (mask->repeat_mode) { g2d_add_cmd(MASK_REPEAT_MODE_REG, mask->repeat_mode); } - if(mask->scale_mode) - { + if (mask->scale_mode) { g2d_add_cmd(MASK_XSCALE_REG, mask->xscale); g2d_add_cmd(MASK_YSCALE_REG, mask->yscale); g2d_add_cmd(MASK_SCALE_CTRL_REG, mask->scale_mode); } - if(mask->rotate_90 || mask->xDir || mask->yDir) - { + if (mask->rotate_90 || mask->xDir || mask->yDir) { rotate.data.maskRotate = mask->rotate_90; dir.data.dirMaskX = mask->xDir; dir.data.dirMaskY = mask->yDir; } } - /*Set Geometry*/ - if(!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + /*Set Geometry */ + if (!_util_get_clip(src, src_x, src_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val); g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val); - if(mask) - { - if(!_util_get_clip(mask, mask_x, mask_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + if (mask) { + if (!_util_get_clip(mask, mask_x, mask_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", + __FUNCTION__, __LINE__); g2d_reset(0); return; } @@ -869,9 +839,9 @@ util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst, g2d_add_cmd(MASK_RIGHT_BOTTOM_REG, rb.val); } - if(!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) - { - XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__); + if (!_util_get_clip(dst, dst_x, dst_y, width, height, <, &rb)) { + XDBG_ERROR(MG2D, "[G2D] %s:%d error: invalid geometry\n", __FUNCTION__, + __LINE__); g2d_reset(0); return; } diff --git a/src/hwa/exynos_hwa.c b/src/hwa/exynos_hwa.c new file mode 100644 index 0000000..7cef1df --- /dev/null +++ b/src/hwa/exynos_hwa.c @@ -0,0 +1,431 @@ +/* exynos-hwa.c + * + * Copyright (c) 2009, 2013 The Linux Foundation. All rights reserved. + * + * Contact: Oleksandr Rozov<o.rozov@samsung.com> + * Contact: Roman Peresipkyn<r.peresipkyn@samsung.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_display.h" +#include <list.h> + +#include "exa.h" +#include <hwa.h> +#include <randrstr.h> +#include "exynos_hwa.h" +#include "exynos_crtc.h" +#include "exynos_layer.h" + +#include "xf86drm.h" + +typedef enum { + LVDS_LAYERS = 5, + HDMI_LAYERS = 3, + VIRTUAL_LAYERS = 3 +} HWA_OUTPUT_LAYERS; + +static xf86OutputPtr pOutputxf = NULL; + +static xf86CrtcPtr +_exynosHwaPreparePtrCrtcFromPtrScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = NULL; + + xf86OutputPtr pOutput = NULL; + xf86CrtcConfigPtr xf86_config = NULL; + + BOOL found = FALSE; + + pScrn = xf86Screens[pScreen->myNum]; + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + int i = 0; + + for (i = 0; i < xf86_config->num_output; i++) { + pOutput = xf86_config->output[i]; + if (!pOutput->crtc->enabled) + continue; + + if (!strcmp(pOutput->name, "LVDS1")) { + found = TRUE; + break; + } + } + + if (!found) + return NULL; + + return pOutput->crtc; +} + +static void * +_exynosFindOutputLayersFromID(ScreenPtr pScreen, RRCrtc rcrtc_id) +{ + int i = 0; + ScrnInfoPtr pScrn = NULL; + xf86OutputPtr pOutput = NULL; + xf86CrtcConfigPtr xf86_config = NULL; + + RRCrtcPtr pRandrCrtc = NULL; + + pScrn = xf86Screens[pScreen->myNum]; + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + for (i = 0; i < xf86_config->num_output; i++) { + pOutput = xf86_config->output[i]; + if (!pOutput->crtc) + continue; + if (!pOutput->crtc->enabled) + continue; + + pRandrCrtc = pOutput->crtc->randr_crtc; + + if (!pRandrCrtc) + continue; + if (pRandrCrtc->id == rcrtc_id) { + pOutputxf = pOutput; + return pOutput; + } + } + + return NULL; +} + +static int +SecHwaOverlayShowLayer(ScreenPtr pScreen, RRCrtc rcrtc_id, + HWA_OVERLAY_LAYER ovrlayer) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + uint16_t nlayers = 0; + EXYNOSLayerPtr curlayer = NULL; + + /* check active connector attached to crtc */ + if (!_exynosFindOutputLayersFromID(pScreen, rcrtc_id)) + return BadRequest; + + /* find layers on this crtc */ + switch (ovrlayer) { + case HWA_OVERLAY_LAYER_UI: + + if (!strcmp(pOutputxf->name, "LVDS1")) { + + curlayer = exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_LOWER1 + 1); + nlayers = LVDS_LAYERS; + break; + } + + if (!strcmp(pOutputxf->name, "HDMI1")) { + + curlayer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1 + 1); + nlayers = HDMI_LAYERS; + break; + } + + if (!strcmp(pOutputxf->name, "Virtual1")) { + + curlayer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1 + 1); + nlayers = VIRTUAL_LAYERS; + break; + } + + if (!curlayer) { + XDBG_DEBUG(MHWA, "UI layer doesn't exists!\n"); + return BadRequest; + } + + exynosLayerHide(curlayer); + XDBG_DEBUG(MHWA, "UI layer[%d] is shown now!\n layers on output= %d\n", + (int) exynosLayerGetPos(curlayer), nlayers); + break; + + case HWA_OVERLAY_LAYER_XV: + + pExynos->XVHIDE = 0; + XDBG_DEBUG(MHWA, "XV layer is shown now!\n"); + break; + + default: + break; + } + + return Success; +} + +static int +SecHwaOverlayHideLayer(ScreenPtr pScreen, RRCrtc rcrtc_id, + HWA_OVERLAY_LAYER ovrlayer) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + uint16_t nlayers = 0; + EXYNOSLayerPtr curlayer = NULL; + + /* check active connector attached to crtc */ + if (!_exynosFindOutputLayersFromID(pScreen, rcrtc_id)) + return BadRequest; + + /* find layers on this crtc */ + switch (ovrlayer) { + case HWA_OVERLAY_LAYER_UI: + + if (!strcmp(pOutputxf->name, "LVDS1")) { + + curlayer = exynosLayerFind(LAYER_OUTPUT_LCD, LAYER_LOWER1); + nlayers = LVDS_LAYERS; + break; + } + + if (!strcmp(pOutputxf->name, "HDMI1")) { + + curlayer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1); + nlayers = HDMI_LAYERS; + break; + } + + if (!curlayer) { + XDBG_DEBUG(MHWA, "UI layer doesn't exists!\n"); + return BadRequest; + } + + exynosLayerHide(curlayer); + XDBG_DEBUG(MHWA, "UI layer[%d] is hidden now!\n layers on output=%d\n", + (int) exynosLayerGetPos(curlayer), nlayers); + break; + + case HWA_OVERLAY_LAYER_XV: + pExynos->XVHIDE = 1; + XDBG_DEBUG(MHWA, "XV layer is hidden now!\n"); + break; + default: + break; + } + + return Success; +} + +static int +SecHwaCursorEnable(ScreenPtr pScreen, CARD16 *pEnable) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int bEnable = *pEnable; + + if (bEnable != pExynos->enableCursor) { + pExynos->enableCursor = bEnable; + if (exynosCrtcCursorEnable(pScrn, bEnable)) { + *pEnable = 1; + XDBG_DEBUG(MHWA, "Xorg] cursor %s.\n", + bEnable ? "enable" : "disable\n"); + + } + else { + *pEnable = 0; + XDBG_DEBUG(MHWA, "[Xorg] Fail cursor %s.\n", + bEnable ? "enable" : "disable"); + } + } + else { + *pEnable = bEnable; + XDBG_DEBUG(MHWA, "[Xorg] already cursor %s.\n", + bEnable ? "enabled" : "disabled"); + } + + return Success; +} + +static int +SecHwaCursorRotate(ScreenPtr pScreen, RRCrtc rcrtc_id, CARD16 *pdegree) +{ + int RR_rotate; + int rotate = *pdegree; + + /* rcrtc_id>=0 ? */ + if (!rcrtc_id) + return BadRequest; + + if (!_exynosFindOutputLayersFromID(pScreen, rcrtc_id)) + return BadRequest; + + RR_rotate = exynosUtilDegreeToRotate(rotate); + if (!RR_rotate) { + XDBG_DEBUG(MHWA, "[Xorg] Not support rotate(0, 90, 180, 270 only)\n"); + return BadRequest; + } + if (exynosCrtcCursorRotate(pOutputxf->crtc, RR_rotate)) { + XDBG_DEBUG(MHWA, "[Xorg] cursor rotated %d.\n", rotate); + *pdegree = rotate; + } + else { + XDBG_DEBUG(MHWA, "[Xorg] Fail cursor rotate %d.\n", rotate); + return BadRequest; + } + + return Success; +} + +static int +EXYNOSScreenInvertNegative(ScreenPtr pScreen, int accessibility_status) +{ + xf86CrtcPtr pCrtc = NULL; + + pCrtc = _exynosHwaPreparePtrCrtcFromPtrScreen(pScreen); + if (!pCrtc) + return BadAlloc; + + EXYNOSCrtcPrivPtr pCrtcPriv = (EXYNOSCrtcPrivPtr) pCrtc->driver_private; + + /* TODO process a case when option is already enabled\disabled + if( accessibility_status == pCrtcPriv->accessibility_status ) + return Success; + */ + + pCrtcPriv->accessibility_status = accessibility_status; + + exynosCrtcEnableAccessibility(pCrtc); + + return Success; +} + +static int +EXYNOSScreenScale(ScreenPtr pScreen, int scale_status, int x, int y, int w, + int h) +{ + xf86CrtcPtr pCrtc = NULL; + int output_w = 0, output_h = 0; + + pCrtc = _exynosHwaPreparePtrCrtcFromPtrScreen(pScreen); + if (!pCrtc) + return BadAlloc; + + EXYNOSCrtcPrivPtr pCrtcPriv = (EXYNOSCrtcPrivPtr) pCrtc->driver_private; + + /* TODO process a case when option is already enabled\disabled + if( scale_status == pCrtcPriv->bScale ) + return Success; + */ + + pCrtcPriv->bScale = scale_status; + + output_w = pCrtc->mode.HDisplay; + output_h = pCrtc->mode.VDisplay; + + if (pCrtcPriv->bScale) { + /*Check invalidate region */ + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (x + w > output_w) + w = output_w - x; + if (y + h > output_h) + h = output_h - y; + + if (pCrtcPriv->rotate == RR_Rotate_90) { + pCrtcPriv->sx = y; + pCrtcPriv->sy = output_w - (x + w); + pCrtcPriv->sw = h; + pCrtcPriv->sh = w; + } + else if (pCrtcPriv->rotate == RR_Rotate_270) { + pCrtcPriv->sx = output_h - (y + h); + pCrtcPriv->sy = x; + pCrtcPriv->sw = h; + pCrtcPriv->sh = w; + } + else if (pCrtcPriv->rotate == RR_Rotate_180) { + pCrtcPriv->sx = output_w - (x + w); + pCrtcPriv->sy = output_h - (y + h); + pCrtcPriv->sw = w; + pCrtcPriv->sh = h; + } + else { + pCrtcPriv->sx = x; + pCrtcPriv->sy = y; + pCrtcPriv->sw = w; + pCrtcPriv->sh = h; + } + } + + exynosCrtcEnableAccessibility(pCrtc); + + return Success; +} + +Bool +exynosHwaInit(ScreenPtr pScreen) +{ + hwa_screen_info_ptr pHwaInfo = NULL; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + pHwaInfo = calloc(1, sizeof(hwa_screen_info_rec)); + XDBG_RETURN_VAL_IF_FAIL(pHwaInfo != NULL, FALSE); + + /* hwa_screen_info_ptr is a DDX callbacks which are used by HWA Extension */ + pHwaInfo->version = HWA_SCREEN_INFO_VERSION; + pHwaInfo->cursor_enable = SecHwaCursorEnable; + pHwaInfo->cursor_rotate = SecHwaCursorRotate; + pHwaInfo->show_layer = SecHwaOverlayShowLayer; + pHwaInfo->hide_layer = SecHwaOverlayHideLayer; + pHwaInfo->screen_invert_negative = EXYNOSScreenInvertNegative; + pHwaInfo->screen_scale = EXYNOSScreenScale; + + if (LoaderSymbol("hwa_screen_init")) { + if (!hwa_screen_init(pScreen, pHwaInfo)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[HWA] hwa_screen_init failed.\n"); + goto fail_init; + } + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[HWA] hwa_screen_init not exist. XServer doesn't support HWA extension\n"); + goto fail_init; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[HWA] Enable HWA.\n"); + + return TRUE; + + fail_init: + + if (pHwaInfo) + free(pHwaInfo); + + return FALSE; +} + +void +exynosHwaDeinit(ScreenPtr pScreen) +{ + XDBG_INFO(MHWC, "Close HWA.\n"); + +} diff --git a/src/hwa/exynos_hwa.h b/src/hwa/exynos_hwa.h new file mode 100644 index 0000000..5aac6c9 --- /dev/null +++ b/src/hwa/exynos_hwa.h @@ -0,0 +1,36 @@ +/* exynos_hwa.h + * + * Copyright (c) 2009, 2013 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _EXYNOS_HWA_H_ +#define _EXYNOS_HWA_H_ + +Bool exynosHwaInit(ScreenPtr pScreen); +void exynosHwaDeinit(ScreenPtr pScreen); + +#endif diff --git a/src/hwc/exynos_hwc.c b/src/hwc/exynos_hwc.c new file mode 100755 index 0000000..9c88700 --- /dev/null +++ b/src/hwc/exynos_hwc.c @@ -0,0 +1,854 @@ +/* exynos-hwc.c + * + * Copyright (c) 2009, 2013 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_display.h" +#include <list.h> + +#include "exa.h" +#include <hwc.h> +#include "exynos_hwc.h" + +#include "xf86drm.h" + +#include "exynos_layer_manager.h" + +#define EXYNOS_HWC_MAX_LAYER 4 + +static RESTYPE layers_rtype; + +static EXYNOSLayerOutput outputlayer = LAYER_OUTPUT_LCD; //by default LCD only + +struct _exynosHwcRec { + ScreenPtr pScreen; + + /* number of layers used by x client */ + int layer_count; + /* number of available layers for x client to use */ + int max_layers; + + EXYNOSLayerMngClientID lyr_client_id; + + /* drawable id associated with this layer */ + DrawablePtr pDraw[EXYNOS_HWC_MAX_LAYER]; + int lpos[EXYNOS_HWC_MAX_LAYER]; + xRectangle src_rect[EXYNOS_HWC_MAX_LAYER]; + xRectangle dst_rect[EXYNOS_HWC_MAX_LAYER]; + struct xorg_list used_dri_list; +}; + +typedef struct { + DrawablePtr pDraw; + struct xorg_list used_dri_link; +} used_dri; + +static void +_hwcSaveDrawable(ScrnInfoPtr pScrn, DrawablePtr pDraw, int num, int index, + int type) +{ + ScreenPtr pScreen = pDraw->pScreen; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + char file[128]; + char *str_type[2] = { "none", "SetDrawable" }; + PixmapPtr pPix = NULL; + EXYNOSPixmapPriv *pExaPixPriv = NULL; + + if (!pExynos->dump_info || !(pExynos->dump_mode & XBERC_DUMP_MODE_HWC)) + return; + + XDBG_RETURN_IF_FAIL(pDraw != NULL); + + if (pDraw->type == DRAWABLE_WINDOW) + pPix = (*pScreen->GetWindowPixmap) ((WindowPtr) pDraw); + else + pPix = (PixmapPtr) pDraw; + + pExaPixPriv = exaGetPixmapDriverPrivate(pPix); + snprintf(file, sizeof(file), "[HWC]%s_%x_%p_{%d,%d}_%03d.%s", + str_type[type], + (unsigned int) pDraw->id, + (void *) pPix, index, num, pExaPixPriv->dump_cnt, + pExynos->dump_type); + + exynosUtilDoDumpPixmaps(pExynos->dump_info, pPix, file, pExynos->dump_type); + + XDBG_DEBUG(MSEC, "dump done\n"); + + pExaPixPriv->dump_cnt++; +} + +static int +_exynosOverlayRegisterEventDrawableGone(void *data, XID id) +{ + EXYNOSHwcDrawableInfo *hdi = (EXYNOSHwcDrawableInfo *) data; + + XDBG_RETURN_VAL_IF_FAIL(hdi != NULL, BadValue); + EXYNOSHwcPtr pHwc = EXYNOSPTR(hdi->pScrn)->pHwc; + + XDBG_RETURN_VAL_IF_FAIL(pHwc != NULL, BadValue); + XDBG_WARNING(MHWC, "Drawable id[%p] has been deleted\n", id); + + int i; + + for (i = 0; i < EXYNOS_HWC_MAX_LAYER; i++) { + if (pHwc->pDraw[i] != NULL) { + if (pHwc->pDraw[i]->id == id) { + exynosHwcSetDriFlag(pHwc->pDraw[i], FALSE); + exynosLayerMngRelease(pHwc->lyr_client_id, outputlayer, + pHwc->lpos[i]); + pHwc->pDraw[i] = NULL; + pHwc->lpos[i] = LAYER_NONE; + } + } + } + + free(hdi); + return Success; +} + +static Bool +_exynosOverlayRegisterEventResourceTypes(void) +{ + layers_rtype = + CreateNewResourceType(_exynosOverlayRegisterEventDrawableGone, + "EXYNOS Hwc Overlay Drawable"); + + if (!layers_rtype) + return FALSE; + + return TRUE; +} + +/* + * Add layer_rtype to drawable + * When drawable is destroyed, _exynosOverlayRegisterEventDrawableGone + * will be called and if that drawable is on overlay list. it will be destroyed.. + */ +Bool +_attachCallbackToDraw(DrawablePtr pDraw, EXYNOSLayerPtr pLayer, + ScrnInfoPtr pScrn) +{ + EXYNOSHwcDrawableInfo *resource; + + resource = malloc(sizeof(EXYNOSHwcDrawableInfo)); + if (resource == NULL) + return FALSE; + + if (!AddResource(pDraw->id, layers_rtype, resource)) { + free(resource); + return FALSE; + } + + resource->type = layers_rtype; + resource->pScrn = pScrn; + + return TRUE; +} + +/* + * The first drawable passing through EXYNOSHwcSetDrawables should be placed into top layer. + * In order that the lower layers were visible the user has to take care independently of that + * the area over the lower layer would be transparent. It to get capability + * to hide a layer without calling of EXYNOSHwcSetDrawables and to avoid a blinking. + */ +static Bool +_exynosHwcDoSetDrawables(EXYNOSHwcPtr pHwc, DrawablePtr *pDraws, + xRectangle *srcRects, xRectangle *dstRects, int count) +{ + ScreenPtr pScreen = pHwc->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int lpos[EXYNOS_HWC_MAX_LAYER] = { 0 }; + int max_lpos; + int i; + + max_lpos = + exynosLayerMngGetListOfAccessablePos(pHwc->lyr_client_id, outputlayer, + lpos); + if (max_lpos < count) { + XDBG_ERROR(MHWC, "Count of drawables:%d more of available planes:%d\n", + count, max_lpos); + return FALSE; + } + pHwc->max_layers = max_lpos; + + //set a tracking function to the new drawable + for (i = 0; i < count; i++) { + if (!exynosHwcIsDrawExist(pDraws[i])) + _attachCallbackToDraw(pDraws[i], NULL, pScrn); + } + + /* reassign count to currently available number of layers */ + for (i = 0; i < count; i++) { + if (pDraws[i] && pHwc->pDraw[i] && pDraws[i]->id != pHwc->pDraw[i]->id) { + exynosLayerMngClearQueue(pHwc->lyr_client_id, outputlayer, + pHwc->lpos[i]); + exynosHwcSetDriFlag(pHwc->pDraw[i], FALSE); + exynosHwcSetDriFlag(pDraws[i], FALSE); + } + if (exynosHwcGetDriFlag(pDraws[i])) { + XDBG_GOTO_IF_FAIL(exynosLayerMngSet + (pHwc->lyr_client_id, 0, 0, &srcRects[i], + &dstRects[i], NULL, NULL, outputlayer, + lpos[(max_lpos - 1) - i], NULL, NULL), + fail_setdrwbs); + } + else { + XDBG_GOTO_IF_FAIL(exynosLayerMngSet + (pHwc->lyr_client_id, 0, 0, &srcRects[i], + &dstRects[i], pDraws[i], NULL, outputlayer, + lpos[(max_lpos - 1) - i], NULL, NULL), + fail_setdrwbs); + } + pHwc->pDraw[i] = pDraws[i]; + pHwc->lpos[i] = lpos[(max_lpos - 1) - i]; + pHwc->src_rect[i] = srcRects[i]; + pHwc->dst_rect[i] = dstRects[i]; + } + + /* Remove old */ + for (i = count; i < EXYNOS_HWC_MAX_LAYER; i++) { + if (pHwc->pDraw[i]) { + exynosHwcSetDriFlag(pHwc->pDraw[i], FALSE); + exynosLayerMngRelease(pHwc->lyr_client_id, outputlayer, + pHwc->lpos[i]); + pHwc->lpos[i] = LAYER_NONE; + pHwc->pDraw[i] = NULL; + } + } + + /* set count of layers to the hwc */ + pHwc->layer_count = count; + + return TRUE; + + fail_setdrwbs: + XDBG_ERROR(MHWC, "HWC set drawables failed\n"); + + for (i = 0; i < count; i++) { + exynosLayerMngRelease(pHwc->lyr_client_id, outputlayer, + lpos[(max_lpos - 1) - i]); + } + + return FALSE; +} + +Bool +exynosHwcDoSetRootDrawables(EXYNOSHwcPtr pHwc, PixmapPtr pScreenPixmap) +{ + Bool ret = FALSE; + + WindowPtr root = pHwc->pScreen->root; + DrawablePtr pDrawRoot = &(root->drawable); + xRectangle srcRect, dstRect; + + dstRect.x = pDrawRoot->x; + dstRect.y = pDrawRoot->y; + dstRect.width = pDrawRoot->width; + dstRect.height = pDrawRoot->height; + srcRect = dstRect; + + ret = + _exynosHwcDoSetDrawables(pHwc, (DrawablePtr *) &pScreenPixmap, &dstRect, + &srcRect, 1); + + return ret; +} + +#ifdef USE_PIXMAN_COMPOSITE +static inline PixmapPtr +_getPixmapFromDrawable(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + PixmapPtr pPix; + + if (pDraw->type == DRAWABLE_WINDOW) + pPix = (*pScreen->GetWindowPixmap) ((WindowPtr) pDraw); + else + pPix = (PixmapPtr) pDraw; + + return pPix; +} +#endif + +PixmapPtr +exynosHwcGetScreenPixmap(ScreenPtr pScreen) +{ +#ifdef USE_PIXMAN_COMPOSITE + XDBG_DEBUG(MHWC, + "================> merge layers to pixmap of root window. \n"); + + EXYNOSPtr pExynos = EXYNOSPTR(xf86ScreenToScrn(pScreen)); + EXYNOSHwcPtr pHwc = pExynos->pHwc; + + pixman_image_t *pSrcImg = NULL; + pixman_image_t *pDstImg = NULL; + + PixmapPtr pDstPixmap = NULL; + PixmapPtr pSrcPixmap = NULL; + DrawablePtr pSrcDraw = NULL; + + EXYNOSPixmapPriv *pSrcPixmapPriv = NULL; + EXYNOSPixmapPriv *pDstPixmapPriv = NULL; + + uint32_t *pSrcBits = NULL; + uint32_t *pDstbits = NULL; + + Bool need_finish = FALSE; + + int i = 0; + int pixman_op = PIXMAN_OP_SRC; + + /* + * Step 1. Initialize dest pixmap private data. + * - It will be a root screen pixmap. + */ + pDstPixmap = (*pScreen->GetScreenPixmap) (pScreen); + XDBG_GOTO_IF_FAIL(pDstPixmap != NULL, fail_mergesrn); + pDstPixmapPriv = exaGetPixmapDriverPrivate(pDstPixmap); + XDBG_GOTO_IF_FAIL(pDstPixmapPriv != NULL, fail_mergesrn); + if (!pDstPixmapPriv->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pDstPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(pDstPixmapPriv->bo != NULL, fail_mergesrn); + } + + pDstbits = + tbm_bo_map(pDstPixmapPriv->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE).ptr; + pDstImg = + pixman_image_create_bits(PIXMAN_a8r8g8b8, pDstPixmap->drawable.width, + pDstPixmap->drawable.height, pDstbits, + pDstPixmap->devKind); + + /* + * Step 2. Recursive composite between hwc layer's pixmap and root screen pixmap + * - The result is stored in root screen pixmap (dest pixmap). + */ + for (i = 0; i < pHwc->layer_count; i++) { + if (!pHwc->pDraw[i] || pHwc->dst_rect[i].width == 0 || + pHwc->dst_rect[i].height == 0) { + continue; + } + pSrcDraw = pHwc->pDraw[i]; + XDBG_GOTO_IF_FAIL(pSrcDraw != NULL, fail_mergesrn); + pSrcPixmap = _getPixmapFromDrawable(pHwc->pDraw[i]); + XDBG_GOTO_IF_FAIL(pSrcPixmap != NULL, fail_mergesrn); + + pSrcPixmapPriv = exaGetPixmapDriverPrivate(pSrcPixmap); + if (pDstPixmap == pSrcPixmap) + continue; + XDBG_GOTO_IF_FAIL(pSrcPixmapPriv != NULL, fail_mergesrn); + XDBG_GOTO_IF_FAIL(pSrcPixmapPriv->bo != NULL, fail_mergesrn); + + pSrcBits = + tbm_bo_map(pSrcPixmapPriv->bo, TBM_DEVICE_CPU, TBM_OPTION_READ).ptr; + pSrcImg = + pixman_image_create_bits(PIXMAN_a8r8g8b8, + pSrcPixmap->drawable.width, + pSrcPixmap->drawable.height, pSrcBits, + pSrcPixmap->devKind); + XDBG_GOTO_IF_FAIL(pSrcImg != NULL, fail_mergesrn); + XDBG_GOTO_IF_FAIL(pDstImg != NULL, fail_mergesrn); + + /* + * for base layer(first layer) PIXMAN_OP_SRC should be used + */ + if (pSrcDraw->depth == 32 && i != 0) + pixman_op = PIXMAN_OP_OVER; + else + pixman_op = PIXMAN_OP_SRC; + + XDBG_DEBUG(MHWC, + "pixmap operation(%d): layer_idx=%d [%d,%d %dx%d] => [%d,%d %dx%d]\n", + pixman_op, i, 0, 0, pSrcPixmap->drawable.width, + pSrcPixmap->drawable.height, pSrcPixmap->drawable.x, + pSrcPixmap->drawable.y, pDstPixmap->drawable.width, + pDstPixmap->drawable.height); + + xRectangle destRect = { 0, }; + memcpy(&destRect, &pHwc->dst_rect[i], sizeof(xRectangle)); + + pixman_image_composite(pixman_op, pSrcImg, NULL, pDstImg, 0, 0, 0, 0, + pSrcPixmap->screen_x + destRect.x, + pSrcPixmap->screen_y + destRect.y, + pSrcPixmap->drawable.width, + pSrcPixmap->drawable.height); + if (pSrcBits != NULL) { + tbm_bo_unmap(pSrcPixmapPriv->bo); + pSrcBits = NULL; + } + } + + XDBG_DEBUG(MHWC, "pixman composite is done\n"); + + fail_mergesrn: + + if (pDstPixmap && need_finish) + exynosExaFinishAccess(pDstPixmap, EXA_PREPARE_DEST); + + if (pSrcImg) { + pixman_image_unref(pSrcImg); + pSrcImg = NULL; + } + + if (pDstbits != NULL) { + tbm_bo_unmap(pDstPixmapPriv->bo); + pDstbits = NULL; + } + + if (pDstImg) { + pixman_image_unref(pDstImg); + pDstImg = NULL; + } + + return pDstPixmap; +#else + return (*pScreen->GetScreenPixmap) (pScreen); +#endif +} + +static Bool +_exynosHwcSetValid(DrawablePtr *pDraws, xRectangle *srcRects, + xRectangle *dstRects, int count) +{ + DrawablePtr pDraw = NULL; + xRectangle srcRect, dstRect; + int i; + + XDBG_RETURN_VAL_IF_FAIL(pDraws != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(srcRects != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dstRects != NULL, FALSE); + + for (i = 0; i < count; i++) { + pDraw = pDraws[i]; + srcRect = srcRects[i]; + dstRect = dstRects[i]; + XDBG_GOTO_IF_FAIL(pDraw->x >= 0, fail); + XDBG_GOTO_IF_FAIL(pDraw->y >= 0, fail); + XDBG_GOTO_IF_FAIL(pDraw->width > 0, fail); + XDBG_GOTO_IF_FAIL(pDraw->height > 0, fail); + + XDBG_GOTO_IF_FAIL(srcRect.x >= 0, fail); + XDBG_GOTO_IF_FAIL(srcRect.y >= 0, fail); + XDBG_GOTO_IF_FAIL(srcRect.width > 0, fail); + XDBG_GOTO_IF_FAIL(srcRect.width + srcRect.x <= pDraws[i]->width, fail); + XDBG_GOTO_IF_FAIL(srcRect.height > 0, fail); + XDBG_GOTO_IF_FAIL(srcRect.height + srcRect.y <= pDraws[i]->height, + fail); + XDBG_GOTO_IF_FAIL(dstRect.x >= 0, fail); + XDBG_GOTO_IF_FAIL(dstRect.y >= 0, fail); + XDBG_GOTO_IF_FAIL(dstRect.width > 0, fail); + XDBG_GOTO_IF_FAIL(dstRect.height > 0, fail); + + XDBG_DEBUG(MHWC, + "xid=%p pDraw(x,y,w,h)=(%d,%d,%d,%d) pSrcRect(%d,%d,%d,%d) pDstRect(%d,%d,%d,%d)\n", + (void *) pDraw->id, pDraw->x, pDraw->y, pDraw->width, + pDraw->height, srcRect.x, srcRect.y, srcRect.width, + srcRect.height, dstRect.x, dstRect.y, dstRect.width, + dstRect.height); + } + + return TRUE; + fail: + XDBG_ERROR(MHWC, + "Error: Drawable is not valid. ==> xid=%p pDraw(x,y,w,h)=(%d,%d,%d,%d) pSrcRect(%d,%d,%d,%d) pDstRect(%d,%d,%d,%d)\n", + (void *) pDraw->id, pDraw->x, pDraw->y, pDraw->width, + pDraw->height, srcRect.x, srcRect.y, srcRect.width, + srcRect.height, dstRect.x, dstRect.y, dstRect.width, + dstRect.height); + + return FALSE; +} + +#ifdef USE_HWC_RESIZE_MOVE +static void +EXYNOSHwcMoveDrawable(ScreenPtr pScreen, DrawablePtr pDraw, int x, int y) +{ +} + +static void +EXYNOSHwcResizeDrawable(ScreenPtr pScreen, DrawablePtr pDraw, int x, int y, + int w, int h) +{ +} +#endif + +static int +EXYNOSHwcOpen(ScreenPtr pScreen, int *maxLayer) +{ + XDBG_DEBUG(MHWC, "enter! \n"); + + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSHwcPtr pHwc = pExynos->pHwc; + + *maxLayer = pHwc->max_layers; + return Success; +} + +int +EXYNOSHwcSetDrawables(ScreenPtr pScreen, DrawablePtr *pDraws, + xRectangle *srcRects, xRectangle *dstRects, int count) +{ + XDBG_DEBUG(MHWC, "================> Start set drawables. count:%d\n", + count); + + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSHwcPtr pHwc = pExynos->pHwc; + int i; + + if (count == 0) { + EXYNOSPTR(pScrn)->hwc_active = TRUE; +// EXYNOSPTR(pScrn)->hwc_use_def_layer = TRUE; + + PixmapPtr pScreenPixmap = NULL; + + /*merge all layers to root */ + pScreenPixmap = exynosHwcGetScreenPixmap(pScreen); + if (pScreenPixmap == NULL) { + XDBG_ERROR(MHWC, "exynosHwcMergeScreenPixmap failed.\n"); + return BadMatch; + } + + if (!exynosHwcDoSetRootDrawables(pHwc, pScreenPixmap)) { + XDBG_WARNING(MHWC, "exynosHwcDoSetRootDrawables failed.\n"); + return BadMatch; + } + return Success; + } + + if (!_exynosHwcSetValid(pDraws, srcRects, dstRects, count)) + return BadMatch; + + EXYNOSPTR(pScrn)->hwc_active = TRUE; + EXYNOSPTR(pScrn)->hwc_use_def_layer = FALSE; + + if (!_exynosHwcDoSetDrawables(pHwc, pDraws, srcRects, dstRects, count)) { + XDBG_WARNING(MHWC, "_exynosHwcDoSetDrawables failed.\n"); + return BadMatch; + } + + for (i = 0; i < count; i++) + _hwcSaveDrawable(pScrn, pDraws[i], count, i, 1); + + return Success; +} + +static void +_exynosLayerAnnexHandler(void *user_data, + EXYNOSLayerMngEventCallbackDataPtr data) +{ + EXYNOSHwcPtr pHwc = (EXYNOSHwcPtr) user_data; + int new_max_layers = + exynosLayerMngGetListOfAccessablePos(pHwc->lyr_client_id, outputlayer, + NULL); + int old_max_layers = pHwc->max_layers; + + if (pHwc->layer_count <= new_max_layers) { + _exynosHwcDoSetDrawables(pHwc, pHwc->pDraw, pHwc->src_rect, + pHwc->dst_rect, pHwc->layer_count); + } + /* send configure notify */ + if (new_max_layers != old_max_layers) { + pHwc->max_layers = new_max_layers; + hwc_send_config_notify(pHwc->pScreen, pHwc->max_layers); + XDBG_DEBUG(MHWC, "hwc_send_config_notify - pHwc->max_layers(%d)\n", + pHwc->max_layers); + } +} + +static void +_exynosLayerFreeCounterHandler(void *user_data, + EXYNOSLayerMngEventCallbackDataPtr data) +{ + EXYNOSHwcPtr pHwc = (EXYNOSHwcPtr) user_data; + int new_max_layers = + exynosLayerMngGetListOfAccessablePos(pHwc->lyr_client_id, outputlayer, + NULL); + + if (pHwc->max_layers != new_max_layers) { + pHwc->max_layers = new_max_layers; + /* send configure notify */ + hwc_send_config_notify(pHwc->pScreen, pHwc->max_layers); + XDBG_DEBUG(MHWC, "hwc_send_config_notify - pHwc->max_layers(%d)\n", + pHwc->max_layers); + } +} + +static void +_exynosUsedDri2InitList(EXYNOSHwcPtr pHwc) +{ + static Bool dri_list_init = FALSE; + + if (!dri_list_init) { + xorg_list_init(&pHwc->used_dri_list); + dri_list_init = TRUE; + } +} + +void +exynosHwcUpdate(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSHwcPtr pHwc = pExynos->pHwc; + int i; + + for (i = 0; i < EXYNOS_HWC_MAX_LAYER; i++) { + if (pHwc->pDraw[i]) { + if (exynosHwcGetDriFlag(pHwc->pDraw[i])) { + XDBG_RETURN_IF_FAIL(exynosLayerMngSet + (pHwc->lyr_client_id, 0, 0, + &pHwc->src_rect[i], &pHwc->dst_rect[i], + NULL, NULL, outputlayer, pHwc->lpos[i], + NULL, NULL)); + } + else { + XDBG_RETURN_IF_FAIL(exynosLayerMngSet + (pHwc->lyr_client_id, 0, 0, + &pHwc->src_rect[i], &pHwc->dst_rect[i], + pHwc->pDraw[i], NULL, outputlayer, + pHwc->lpos[i], NULL, NULL)); + } + } + } +} + +void +exynosHwcSetDriFlag(DrawablePtr pDraw, Bool flag) +{ + XDBG_RETURN_IF_FAIL(pDraw != NULL); + EXYNOSHwcPtr pHwc = EXYNOSPTR(xf86Screens[pDraw->pScreen->myNum])->pHwc; + + XDBG_RETURN_IF_FAIL(pHwc != NULL); + used_dri *pDraw_cur = NULL, *pDraw_next = NULL; + Bool found = FALSE; + + _exynosUsedDri2InitList(pHwc); + xorg_list_for_each_entry_safe(pDraw_cur, pDraw_next, &pHwc->used_dri_list, + used_dri_link) { + if (pDraw_cur->pDraw == pDraw) { + found = TRUE; + if (flag) { + break; + } + else { + XDBG_DEBUG(MHWC, + "Remove dri flag for Drawable:%p, XID:%" PRIXID "\n", + pDraw, pDraw->id); + xorg_list_del(&pDraw_cur->used_dri_link); + free(pDraw_cur); + } + } + } + if (!found && flag) { + used_dri *dri_data = calloc(1, sizeof(used_dri)); + + XDBG_RETURN_IF_FAIL(dri_data != NULL); + dri_data->pDraw = pDraw; + xorg_list_add(&dri_data->used_dri_link, &pHwc->used_dri_list); + XDBG_DEBUG(MHWC, "Setup dri flag for Drawable:%p, XID:%" PRIXID "\n", + pDraw, pDraw->id); + } +} + +Bool +exynosHwcGetDriFlag(DrawablePtr pDraw) +{ + XDBG_RETURN_VAL_IF_FAIL(pDraw != NULL, FALSE); + EXYNOSHwcPtr pHwc = EXYNOSPTR(xf86Screens[pDraw->pScreen->myNum])->pHwc; + + XDBG_RETURN_VAL_IF_FAIL(pHwc != NULL, FALSE); + used_dri *pDraw_cur = NULL, *pDraw_next = NULL; + Bool found = FALSE; + + _exynosUsedDri2InitList(pHwc); + xorg_list_for_each_entry_safe(pDraw_cur, pDraw_next, &pHwc->used_dri_list, + used_dri_link) { + if (pDraw_cur->pDraw == pDraw) { + found = TRUE; + break; + } + } + return found; +} + +Bool +exynosHwcIsDrawExist(DrawablePtr pDraw) +{ + EXYNOSHwcPtr pHwc = EXYNOSPTR(xf86Screens[pDraw->pScreen->myNum])->pHwc; + int j; + + for (j = 0; j < EXYNOS_HWC_MAX_LAYER; j++) { + if (pHwc->pDraw[j] && pDraw->id == pHwc->pDraw[j]->id) { + return TRUE; + } + } + return FALSE; +} + +EXYNOSLayerPos +exynosHwcGetDrawLpos(DrawablePtr pDraw) +{ + EXYNOSHwcPtr pHwc = EXYNOSPTR(xf86Screens[pDraw->pScreen->myNum])->pHwc; + int i; + + for (i = 0; i < EXYNOS_HWC_MAX_LAYER; i++) { + if (pHwc->pDraw[i] && pDraw == pHwc->pDraw[i]) { + return pHwc->lpos[i]; + } + } + return LAYER_NONE; +} + +Bool +exynosHwcInit(ScreenPtr pScreen) +{ + hwc_screen_info_ptr pHwcInfo = NULL; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSHwcPtr pHwc = NULL; + + pHwcInfo = calloc(1, sizeof(hwc_screen_info_rec)); + XDBG_RETURN_VAL_IF_FAIL(pHwcInfo != NULL, FALSE); + + memset(pHwcInfo, 0, sizeof(hwc_screen_info_rec)); + + pHwc = calloc(1, sizeof(EXYNOSHwcRec)); + XDBG_GOTO_IF_FAIL(pHwc != NULL, fail_init); + + /* set the initial values */ + pHwc->layer_count = 0; + pHwc->max_layers = EXYNOS_HWC_MAX_LAYER; + // pHwc->commit_complete = TRUE; //no such field yet + pHwc->pScreen = pScreen; + pExynos->pHwc = pHwc; + + pHwcInfo->version = HWC_SCREEN_INFO_VERSION; + pHwcInfo->maxLayer = EXYNOS_HWC_MAX_LAYER; + pHwcInfo->open = EXYNOSHwcOpen; + pHwcInfo->set_drawables = EXYNOSHwcSetDrawables; + +#ifdef USE_HWC_RESIZE_MOVE + pHwcInfo->move_drawable = EXYNOSHwcMoveDrawable; + pHwcInfo->resize_drawable = EXYNOSHwcResizeDrawable; +#else + pHwcInfo->move_drawable = NULL; + pHwcInfo->resize_drawable = NULL; +#endif + + pHwcInfo->update_drawable = NULL; + + /*find what connector is active */ + int active_connector = -1; + + active_connector = findActiveConnector(pScrn); + XDBG_GOTO_IF_FAIL(active_connector != -1, fail_init); + + if (active_connector == DRM_MODE_CONNECTOR_LVDS) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[HWC] output layers on LCD.\n"); + outputlayer = LAYER_OUTPUT_LCD; + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[HWC] output layers on external display.\n"); + outputlayer = LAYER_OUTPUT_EXT; + } + + pHwc->lyr_client_id = exynosLayerMngRegisterClient(pScrn, "HWC", 1); + if (pHwc->lyr_client_id == LYR_ERROR_ID) { + XDBG_ERROR(MHWC, "Can't register layer_id\n"); + goto fail_init; + } + exynosLayerMngAddEvent(pHwc->lyr_client_id, EVENT_LAYER_ANNEX, + _exynosLayerAnnexHandler, pHwc); + exynosLayerMngAddEvent(pHwc->lyr_client_id, EVENT_LAYER_FREE_COUNTER, + _exynosLayerFreeCounterHandler, pHwc); + + pHwc->max_layers = + exynosLayerMngGetListOfAccessablePos(pHwc->lyr_client_id, outputlayer, + NULL); + pHwcInfo->maxLayer = pHwc->max_layers; + int i; + + for (i = 0; i < EXYNOS_HWC_MAX_LAYER; i++) { + pHwc->lpos[i] = LAYER_NONE; + } + + if (LoaderSymbol("hwc_screen_init")) { + if (!hwc_screen_init(pScreen, pHwcInfo)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[HWC] hwc_screen_init failed.\n"); + goto fail_init; + } + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[HWC] hwc_screen_init not exist. XServer doesn't support HWC extension\n"); + goto fail_init; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[HWC] Enable HWC.\n"); + + if (!_exynosOverlayRegisterEventResourceTypes()) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[HWC] Failed to register EventResourceTypes. \n"); + return FALSE; + } + return TRUE; + + fail_init: + free(pHwc); + pExynos->pHwc = NULL; + if (pHwcInfo) + free(pHwcInfo); + + return FALSE; +} + +EXYNOSLayerMngClientID +exynosHwcGetLyrClientId(EXYNOSHwcPtr pHwc) +{ + return pHwc->lyr_client_id; +} + +void +exynosHwcDeinit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (pExynos->pHwc) { + exynosLayerMngUnRegisterClient(pExynos->pHwc->lyr_client_id); + free(pExynos->pHwc); + pExynos->pHwc = NULL; + } + + XDBG_INFO(MHWC, "Close HWC.\n"); +} diff --git a/src/hwc/exynos_hwc.h b/src/hwc/exynos_hwc.h new file mode 100644 index 0000000..e557048 --- /dev/null +++ b/src/hwc/exynos_hwc.h @@ -0,0 +1,66 @@ +/* exynos_hwc.h + * + * Copyright (c) 2009, 2013 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _EXYNOS_HWC_H_ +#define _EXYNOS_HWC_H_ + +#include "exynos_layer.h" +#include "exynos_layer_manager.h" + +//EXYNOSLayer *EXYNOSLayerPtr; +typedef struct _exynosHwcRec EXYNOSHwcRec, *EXYNOSHwcPtr; + +typedef struct _HwcDrawableInfo { + // XID id; /* xid in layer structuer*/ + ScrnInfoPtr pScrn; /* pScrn is layer structure ?? */ + RESTYPE type; +} EXYNOSHwcDrawableInfo; + +Bool exynosHwcIsDrawExist(DrawablePtr pDraw); +EXYNOSLayerPos exynosHwcGetDrawLpos(DrawablePtr pDraw); + +Bool exynosHwcInit(ScreenPtr pScreen); +void exynosHwcDeinit(ScreenPtr pScreen); + +/* get the screen pixmap of which is the result of composition of the overlays */ +PixmapPtr exynosHwcGetScreenPixmap(ScreenPtr pScreen); + +/* set HWC drawable of root window */ +Bool exynosHwcDoSetRootDrawables(EXYNOSHwcPtr pHwc, PixmapPtr pScreenPixmap); + +int EXYNOSHwcSetDrawables(ScreenPtr pScreen, DrawablePtr *pDraws, + xRectangle *srcRects, xRectangle *dstRects, + int count); +void exynosHwcUpdate(ScrnInfoPtr pScrn); +void exynosHwcSetDriFlag(DrawablePtr pDraw, Bool flag); +Bool exynosHwcGetDriFlag(DrawablePtr pDraw); + +EXYNOSLayerMngClientID exynosHwcGetLyrClientId(EXYNOSHwcPtr pHwc); + +#endif // _EXYNOS_HWC_H_ diff --git a/src/ipp/exynos_converter.c b/src/ipp/exynos_converter.c new file mode 100644 index 0000000..7b5786b --- /dev/null +++ b/src/ipp/exynos_converter.c @@ -0,0 +1,1091 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 <sys/ioctl.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_video_types.h" +#include "exynos_video_fourcc.h" +#include "exynos_drm_ipp.h" +#include "exynos_converter.h" + +#include <drm_fourcc.h> + +//#define INCREASE_NUM 1 +#define DEQUEUE_FORCE 1 + +#if INCREASE_NUM +#define CVT_BUF_MAX 6 +#endif + +static Bool can_pause = TRUE; + +typedef struct _EXYNOSCvtFuncData { + CvtFunc func; + void *data; + struct xorg_list link; +} EXYNOSCvtFuncData; + +typedef struct _EXYNOSCvtBuf { + EXYNOSCvtType type; + int index; + unsigned int handles[EXYNOS_DRM_PLANAR_MAX]; + CARD32 begin; + + EXYNOSVideoBuf *vbuf; + + struct xorg_list link; +} EXYNOSCvtBuf; + +struct _EXYNOSCvt { + uintptr_t stamp; + + int prop_id; + + ScrnInfoPtr pScrn; + EXYNOSCvtOp op; + EXYNOSCvtProp props[CVT_TYPE_MAX]; + + struct xorg_list func_datas; + struct xorg_list src_bufs; + struct xorg_list dst_bufs; + +#if INCREASE_NUM + int src_index; + int dst_index; +#endif + + Bool started; + Bool paused; + Bool first_event; + + struct xorg_list link; +}; + +static unsigned int formats[] = { + FOURCC_RGB565, + FOURCC_SR16, + FOURCC_RGB32, + FOURCC_SR32, + FOURCC_YV12, + FOURCC_I420, + FOURCC_S420, + FOURCC_ST12, + FOURCC_SN12, + FOURCC_NV12, + FOURCC_SN21, + FOURCC_NV21, + FOURCC_YUY2, + FOURCC_SUYV, + FOURCC_UYVY, + FOURCC_SYVY, + FOURCC_ITLV, +}; + +static struct xorg_list cvt_list; + +static void +_initList(void) +{ + static Bool inited = FALSE; + + if (inited) + return; + + xorg_list_init(&cvt_list); + + inited = TRUE; +} + +static EXYNOSCvt * +_findCvt(uintptr_t stamp) +{ + EXYNOSCvt *cur = NULL, *next = NULL; + + _initList(); + + if (cvt_list.next != NULL) { + xorg_list_for_each_entry_safe(cur, next, &cvt_list, link) { + if (cur->stamp == stamp) + return cur; + } + } + + return NULL; +} + +static enum drm_exynos_ipp_cmd +_drmCommand(EXYNOSCvtOp op) +{ + switch (op) { + case CVT_OP_OUTPUT: + return IPP_CMD_OUTPUT; + default: + return IPP_CMD_M2M; + } +} + +static enum drm_exynos_degree +_drmDegree(int degree) +{ + switch (degree % 360) { + case 90: + return EXYNOS_DRM_DEGREE_90; + case 180: + return EXYNOS_DRM_DEGREE_180; + case 270: + return EXYNOS_DRM_DEGREE_270; + default: + return EXYNOS_DRM_DEGREE_0; + } +} + +static void +_FillConfig(EXYNOSCvtType type, EXYNOSCvtProp * prop, + struct drm_exynos_ipp_config *config) +{ + config->ops_id = + (type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; + + if (prop->hflip) + config->flip |= EXYNOS_DRM_FLIP_HORIZONTAL; + if (prop->vflip) + config->flip |= EXYNOS_DRM_FLIP_VERTICAL; + + config->degree = _drmDegree(prop->degree); + config->fmt = exynosUtilGetDrmFormat(prop->id); + config->sz.hsize = (__u32) prop->width; + config->sz.vsize = (__u32) prop->height; + config->pos.x = (__u32) prop->crop.x; + config->pos.y = (__u32) prop->crop.y; + config->pos.w = (__u32) prop->crop.width; + config->pos.h = (__u32) prop->crop.height; +} + +static void +_fillProperty(EXYNOSCvt * cvt, EXYNOSCvtType type, EXYNOSVideoBuf * vbuf, + EXYNOSCvtProp * prop) +{ + prop->id = vbuf->id; + prop->width = vbuf->width; + prop->height = vbuf->height; + prop->crop = vbuf->crop; + + prop->degree = cvt->props[type].degree; + prop->vflip = cvt->props[type].vflip; + prop->hflip = cvt->props[type].hflip; + prop->exynosure = cvt->props[type].exynosure; + prop->csc_range = cvt->props[type].csc_range; +} + +static Bool +_SetVbufConverting(EXYNOSVideoBuf * vbuf, EXYNOSCvt * cvt, Bool converting) +{ + if (!converting) { + ConvertInfo *cur = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(cur, next, &vbuf->convert_info, link) { + if (cur->cvt == (void *) cvt) { + xorg_list_del(&cur->link); + free(cur); + return TRUE; + } + } + + XDBG_ERROR(MCVT, "failed: %" PRIuPTR " not found in %" PRIuPTR ".\n", + cvt->stamp, vbuf->stamp); + return FALSE; + } + else { + ConvertInfo *info = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(info, next, &vbuf->convert_info, link) { + if (info->cvt == (void *) cvt) { + XDBG_ERROR(MCVT, + "failed: %" PRIuPTR " already converting %" PRIuPTR + ".\n", cvt->stamp, vbuf->stamp); + return FALSE; + } + } + + info = calloc(1, sizeof(ConvertInfo)); + XDBG_RETURN_VAL_IF_FAIL(info != NULL, FALSE); + + info->cvt = (void *) cvt; + + xorg_list_add(&info->link, &vbuf->convert_info); + + return TRUE; + } +} + +#if 0 +static void +_printBufIndices(EXYNOSCvt * cvt, EXYNOSCvtType type, char *str) +{ + struct xorg_list *bufs; + EXYNOSCvtBuf *cur, *next; + char nums[128]; + + bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; + + snprintf(nums, 128, "bufs:"); + + list_rev_for_each_entry_safe(cur, next, bufs, link) { + snprintf(nums, 128, "%s %d", nums, cur->index); + } + + ErrorF("%s: cvt(%p) %s(%s). \n", str, cvt, + (type == CVT_TYPE_SRC) ? "SRC" : "DST", nums); +} +#endif + +static int +_exynosCvtGetEmptyIndex(EXYNOSCvt * cvt, EXYNOSCvtType type) +{ +#if INCREASE_NUM + int ret; + + if (type == CVT_TYPE_SRC) { + ret = cvt->src_index++; + if (cvt->src_index >= CVT_BUF_MAX) + cvt->src_index = 0; + } + else { + ret = cvt->dst_index++; + if (cvt->dst_index >= CVT_BUF_MAX) + cvt->dst_index = 0; + } + + return ret; +#else + struct xorg_list *bufs; + EXYNOSCvtBuf *cur = NULL, *next = NULL; + int ret = 0; + + bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; + + while (1) { + Bool found = FALSE; + + xorg_list_for_each_entry_safe(cur, next, bufs, link) { + if (ret == cur->index) { + found = TRUE; + break; + } + } + + if (!found) + break; + + ret++; + } + + return ret; +#endif +} + +static EXYNOSCvtBuf * +_exynosCvtFindBuf(EXYNOSCvt * cvt, EXYNOSCvtType type, int index) +{ + struct xorg_list *bufs; + EXYNOSCvtBuf *cur = NULL, *next = NULL; + + bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; + + xorg_list_for_each_entry_safe(cur, next, bufs, link) { + if (index == cur->index) + return cur; + } + + XDBG_ERROR(MCVT, "cvt(%p), type(%d), index(%d) not found.\n", cvt, type, + index); + + return NULL; +} + +static Bool +_exynosCvtQueue(EXYNOSCvt * cvt, EXYNOSCvtBuf * cbuf) +{ + struct drm_exynos_ipp_queue_buf buf = { 0, }; + struct xorg_list *bufs; + int i; + int index = _exynosCvtGetEmptyIndex(cvt, cbuf->type); + + buf.prop_id = cvt->prop_id; + buf.ops_id = + (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_ENQUEUE; + buf.buf_id = cbuf->index = index; + buf.user_data = (__u64) cvt->stamp; + + for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) + buf.handle[i] = (__u32) cbuf->handles[i]; + + if (!exynosDrmIppQueueBuf(cvt->pScrn, &buf)) + return FALSE; + + bufs = (cbuf->type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; + xorg_list_add(&cbuf->link, bufs); + + _SetVbufConverting(cbuf->vbuf, cvt, TRUE); + +#if 0 + if (cbuf->type == CVT_TYPE_SRC) + _printBufIndices(cvt, CVT_TYPE_SRC, "in"); +#endif + + XDBG_DEBUG(MCVT, + "cvt(%p), cbuf(%p), type(%d), index(%d) vbuf(%p) converting(%d)\n", + cvt, cbuf, cbuf->type, index, cbuf->vbuf, + VBUF_IS_CONVERTING(cbuf->vbuf)); + + return TRUE; +} + +static void +_exynosCvtDequeue(EXYNOSCvt * cvt, EXYNOSCvtBuf * cbuf) +{ + struct drm_exynos_ipp_queue_buf buf = { 0, }; + int i; + + if (!_exynosCvtFindBuf(cvt, cbuf->type, cbuf->index)) { + XDBG_WARNING(MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n", + cvt, cbuf->type, cbuf->index); + return; + } + + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(cbuf->vbuf)); + + buf.prop_id = cvt->prop_id; + buf.ops_id = + (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_DEQUEUE; + buf.buf_id = cbuf->index; + buf.user_data = (__u64) cvt->stamp; + + for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) + buf.handle[i] = (__u32) cbuf->handles[i]; + + if (!exynosDrmIppQueueBuf(cvt->pScrn, &buf)) + return; +} + +static void +_exynosCvtDequeued(EXYNOSCvt * cvt, EXYNOSCvtType type, int index) +{ + EXYNOSCvtBuf *cbuf = _exynosCvtFindBuf(cvt, type, index); + + if (!cbuf) { + XDBG_WARNING(MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n", + cvt, type, index); + return; + } + + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(cbuf->vbuf)); + + _SetVbufConverting(cbuf->vbuf, cvt, FALSE); + + XDBG_DEBUG(MCVT, "cvt(%p) type(%d) index(%d) vbuf(%p) converting(%d)\n", + cvt, type, index, cbuf->vbuf, VBUF_IS_CONVERTING(cbuf->vbuf)); + + xorg_list_del(&cbuf->link); + +#if 0 + if (cbuf->type == CVT_TYPE_SRC) + _printBufIndices(cvt, CVT_TYPE_SRC, "out"); +#endif + + exynosUtilVideoBufferUnref(cbuf->vbuf); + free(cbuf); +} + +static void +_exynosCvtDequeueAll(EXYNOSCvt * cvt) +{ + EXYNOSCvtBuf *cur = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(cur, next, &cvt->src_bufs, link) { + _exynosCvtDequeue(cvt, cur); + } + + xorg_list_for_each_entry_safe(cur, next, &cvt->dst_bufs, link) { + _exynosCvtDequeue(cvt, cur); + } +} + +static void +_exynosCvtDequeuedAll(EXYNOSCvt * cvt) +{ + EXYNOSCvtBuf *cur = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(cur, next, &cvt->src_bufs, link) { + _exynosCvtDequeued(cvt, EXYNOS_DRM_OPS_SRC, cur->index); + } + + xorg_list_for_each_entry_safe(cur, next, &cvt->dst_bufs, link) { + _exynosCvtDequeued(cvt, EXYNOS_DRM_OPS_DST, cur->index); + } +} + +static void +_exynosCvtStop(EXYNOSCvt * cvt) +{ + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + + XDBG_RETURN_IF_FAIL(cvt != NULL); + + if (!cvt->started) + return; + + _exynosCvtDequeueAll(cvt); + + ctrl.prop_id = cvt->prop_id; + ctrl.ctrl = IPP_CTRL_STOP; + + exynosDrmIppCmdCtrl(cvt->pScrn, &ctrl); + + _exynosCvtDequeuedAll(cvt); + + XDBG_TRACE(MCVT, "cvt(%p)\n", cvt); + + cvt->prop_id = -1; + + memset(cvt->props, 0, sizeof(EXYNOSCvtProp) * CVT_TYPE_MAX); + +#if INCREASE_NUM + cvt->src_index = 0; + cvt->dst_index = 0; +#endif + cvt->started = FALSE; + + return; +} + +Bool +exynosCvtSupportFormat(EXYNOSCvtOp op, int id) +{ + unsigned int *drmfmts; + int i, size, num = 0; + unsigned int drmfmt = exynosUtilGetDrmFormat(id); + + XDBG_RETURN_VAL_IF_FAIL(op >= 0 && op < CVT_OP_MAX, FALSE); + XDBG_RETURN_VAL_IF_FAIL(id > 0, FALSE); + + size = sizeof(formats) / sizeof(unsigned int); + + for (i = 0; i < size; i++) + if (formats[i] == id) + break; + + if (i == size) { + XDBG_ERROR(MCVT, "converter(op:%d) not support : '%c%c%c%c'.\n", + op, FOURCC_STR(id)); + return FALSE; + } + + drmfmts = exynosDrmIppGetFormatList(&num); + if (!drmfmts) { + XDBG_ERROR(MCVT, "no drm format list.\n"); + return FALSE; + } + + for (i = 0; i < num; i++) + if (drmfmts[i] == drmfmt) { + free(drmfmts); + return TRUE; + } + + XDBG_ERROR(MCVT, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR(id)); + + free(drmfmts); + + return FALSE; +} + +Bool +exynosCvtEnsureSize(EXYNOSCvtProp * src, EXYNOSCvtProp * dst) +{ + if (src) { + int type = exynosUtilGetColorType(src->id); + + XDBG_RETURN_VAL_IF_FAIL(src->width >= 16, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src->height >= 8, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src->crop.width >= 16, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src->crop.height >= 8, FALSE); + + if (src->width % 16) { + if (!IS_ZEROCOPY(src->id)) { + int new_width = (src->width + 16) & (~0xF); + + XDBG_DEBUG(MCVT, "src's width : %d to %d.\n", src->width, + new_width); + src->width = new_width; + } + } + + if (type == TYPE_YUV420 && src->height % 2) + XDBG_WARNING(MCVT, "src's height(%d) is not multiple of 2!!!\n", + src->height); + + if (type == TYPE_YUV420 || type == TYPE_YUV422) { + src->crop.x = src->crop.x & (~0x1); + src->crop.width = src->crop.width & (~0x1); + } + + if (type == TYPE_YUV420) + src->crop.height = src->crop.height & (~0x1); + + if (src->crop.x + src->crop.width > src->width) + src->crop.width = src->width - src->crop.x; + if (src->crop.y + src->crop.height > src->height) + src->crop.height = src->height - src->crop.y; + } + + if (dst) { + int type = exynosUtilGetColorType(dst->id); + + XDBG_RETURN_VAL_IF_FAIL(dst->width >= 16, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst->height >= 8, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst->crop.width >= 16, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst->crop.height >= 4, FALSE); + + if (dst->width % 16) { + int new_width = (dst->width + 16) & (~0xF); + + XDBG_DEBUG(MCVT, "dst's width : %d to %d.\n", dst->width, + new_width); + dst->width = new_width; + } + + dst->height = dst->height & (~0x1); + + if (type == TYPE_YUV420 && dst->height % 2) + XDBG_WARNING(MCVT, "dst's height(%d) is not multiple of 2!!!\n", + dst->height); + + if (type == TYPE_YUV420 || type == TYPE_YUV422) { + dst->crop.x = dst->crop.x & (~0x1); + dst->crop.width = dst->crop.width & (~0x1); + } + + if (type == TYPE_YUV420) + dst->crop.height = dst->crop.height & (~0x1); + + if (dst->crop.x + dst->crop.width > dst->width) + dst->crop.width = dst->width - dst->crop.x; + if (dst->crop.y + dst->crop.height > dst->height) + dst->crop.height = dst->height - dst->crop.y; + } + + return TRUE; +} + +EXYNOSCvt * +exynosCvtCreate(ScrnInfoPtr pScrn, EXYNOSCvtOp op) +{ + EXYNOSCvt *cvt; + uintptr_t stamp = (uintptr_t) GetTimeInMillis(); + + _initList(); + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(op >= 0 && op < CVT_OP_MAX, NULL); + + while (_findCvt(stamp)) + stamp++; + + cvt = calloc(1, sizeof(EXYNOSCvt)); + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, NULL); + + cvt->stamp = stamp; + + cvt->pScrn = pScrn; + cvt->op = op; + cvt->prop_id = -1; + + xorg_list_init(&cvt->func_datas); + xorg_list_init(&cvt->src_bufs); + xorg_list_init(&cvt->dst_bufs); + + XDBG_TRACE(MCVT, "op(%d), cvt(%p) stamp(%" PRIuPTR ")\n", op, cvt, stamp); + + xorg_list_add(&cvt->link, &cvt_list); + + return cvt; +} + +void +exynosCvtDestroy(EXYNOSCvt * cvt) +{ + EXYNOSCvtFuncData *cur = NULL, *next = NULL; + + if (!cvt) + return; + + _exynosCvtStop(cvt); + + xorg_list_del(&cvt->link); + + xorg_list_for_each_entry_safe(cur, next, &cvt->func_datas, link) { + xorg_list_del(&cur->link); + free(cur); + } + + XDBG_TRACE(MCVT, "cvt(%p)\n", cvt); + + free(cvt); +} + +EXYNOSCvtOp +exynosCvtGetOp(EXYNOSCvt * cvt) +{ + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, CVT_OP_M2M); + + return cvt->op; +} + +Bool +exynosCvtSetProperpty(EXYNOSCvt * cvt, EXYNOSCvtProp * src, EXYNOSCvtProp * dst) +{ + if (cvt->started && !cvt->paused) + return TRUE; + + struct drm_exynos_ipp_property property; + + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst != NULL, FALSE); + + if (!exynosCvtEnsureSize(src, dst)) + return FALSE; + + if (dst->crop.x + dst->crop.width > dst->width) { + XDBG_ERROR(MCVT, "dst(%d+%d > %d). !\n", dst->crop.x, dst->crop.width, + dst->width); + } + + if (!exynosCvtSupportFormat(cvt->op, src->id)) { + XDBG_ERROR(MCVT, "cvt(%p) src '%c%c%c%c' not supported.\n", + cvt, FOURCC_STR(src->id)); + return FALSE; + } + + if (!exynosCvtSupportFormat(cvt->op, dst->id)) { + XDBG_ERROR(MCVT, "cvt(%p) dst '%c%c%c%c' not supported.\n", + cvt, FOURCC_STR(dst->id)); + return FALSE; + } + + memcpy(&cvt->props[CVT_TYPE_SRC], src, sizeof(EXYNOSCvtProp)); + memcpy(&cvt->props[CVT_TYPE_DST], dst, sizeof(EXYNOSCvtProp)); + + CLEAR(property); + _FillConfig(CVT_TYPE_SRC, &cvt->props[CVT_TYPE_SRC], &property.config[0]); + _FillConfig(CVT_TYPE_DST, &cvt->props[CVT_TYPE_DST], &property.config[1]); + property.cmd = _drmCommand(cvt->op); +#ifdef _F_WEARABLE_FEATURE_ + property.type = IPP_EVENT_DRIVEN; +#endif + property.prop_id = cvt->prop_id; +#ifdef LEGACY_INTERFACE + property.protect = dst->exynosure; +#endif + property.range = dst->csc_range; + + XDBG_TRACE(MCVT, + "cvt(%p) src('%c%c%c%c', '%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(src->id), + FOURCC_STR(exynosUtilGetDrmFormat(src->id)), src->width, + src->height, src->crop.x, src->crop.y, src->crop.width, + src->crop.height, src->degree, src->hflip, src->vflip, + src->exynosure, src->csc_range); + + XDBG_TRACE(MCVT, + "cvt(%p) dst('%c%c%c%c', '%c%c%c%c',%dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(dst->id), + FOURCC_STR(exynosUtilGetDrmFormat(dst->id)), dst->width, + dst->height, dst->crop.x, dst->crop.y, dst->crop.width, + dst->crop.height, dst->degree, dst->hflip, dst->vflip, + dst->exynosure, dst->csc_range); + + cvt->prop_id = exynosDrmIppSetProperty(cvt->pScrn, &property); + XDBG_RETURN_VAL_IF_FAIL(cvt->prop_id >= 0, FALSE); + + return TRUE; +} + +void +exynosCvtGetProperpty(EXYNOSCvt * cvt, EXYNOSCvtProp * src, EXYNOSCvtProp * dst) +{ + XDBG_RETURN_IF_FAIL(cvt != NULL); + + if (src) + *src = cvt->props[CVT_TYPE_SRC]; + + if (dst) + *dst = cvt->props[CVT_TYPE_DST]; +} + +Bool +exynosCvtConvert(EXYNOSCvt * cvt, EXYNOSVideoBuf * src, EXYNOSVideoBuf * dst) +{ + EXYNOSCvtBuf *src_cbuf = NULL, *dst_cbuf = NULL; + EXYNOSCvtProp src_prop, dst_prop; + + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(cvt->op == CVT_OP_M2M, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(src), FALSE); + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(dst), FALSE); + + TTRACE_VIDEO_BEGIN("XORG:IPP:CONVERT"); + + _fillProperty(cvt, CVT_TYPE_SRC, src, &src_prop); + _fillProperty(cvt, CVT_TYPE_DST, dst, &dst_prop); + + if (memcmp(&cvt->props[CVT_TYPE_SRC], &src_prop, sizeof(EXYNOSCvtProp)) || + memcmp(&cvt->props[CVT_TYPE_DST], &dst_prop, sizeof(EXYNOSCvtProp))) { + XDBG_ERROR(MCVT, "cvt(%p) prop changed!\n", cvt); + XDBG_TRACE(MCVT, + "cvt(%p) src_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(cvt->props[CVT_TYPE_SRC].id), + cvt->props[CVT_TYPE_SRC].width, + cvt->props[CVT_TYPE_SRC].height, + cvt->props[CVT_TYPE_SRC].crop.x, + cvt->props[CVT_TYPE_SRC].crop.y, + cvt->props[CVT_TYPE_SRC].crop.width, + cvt->props[CVT_TYPE_SRC].crop.height, + cvt->props[CVT_TYPE_SRC].degree, + cvt->props[CVT_TYPE_SRC].hflip, + cvt->props[CVT_TYPE_SRC].vflip, + cvt->props[CVT_TYPE_SRC].exynosure, + cvt->props[CVT_TYPE_SRC].csc_range); + XDBG_TRACE(MCVT, + "cvt(%p) src_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(src_prop.id), src_prop.width, + src_prop.height, src_prop.crop.x, src_prop.crop.y, + src_prop.crop.width, src_prop.crop.height, src_prop.degree, + src_prop.hflip, src_prop.vflip, src_prop.exynosure, + src_prop.csc_range); + XDBG_TRACE(MCVT, + "cvt(%p) dst_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(cvt->props[CVT_TYPE_DST].id), + cvt->props[CVT_TYPE_DST].width, + cvt->props[CVT_TYPE_DST].height, + cvt->props[CVT_TYPE_DST].crop.x, + cvt->props[CVT_TYPE_DST].crop.y, + cvt->props[CVT_TYPE_DST].crop.width, + cvt->props[CVT_TYPE_DST].crop.height, + cvt->props[CVT_TYPE_DST].degree, + cvt->props[CVT_TYPE_DST].hflip, + cvt->props[CVT_TYPE_DST].vflip, + cvt->props[CVT_TYPE_DST].exynosure, + cvt->props[CVT_TYPE_DST].csc_range); + XDBG_TRACE(MCVT, + "cvt(%p) dst_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", + cvt, FOURCC_STR(dst_prop.id), dst_prop.width, + dst_prop.height, dst_prop.crop.x, dst_prop.crop.y, + dst_prop.crop.width, dst_prop.crop.height, dst_prop.degree, + dst_prop.hflip, dst_prop.vflip, dst_prop.exynosure, + dst_prop.csc_range); + + TTRACE_VIDEO_END(); + + return FALSE; + } + + XDBG_GOTO_IF_FAIL(cvt->prop_id >= 0, fail_to_convert); + XDBG_GOTO_IF_FAIL(src->handles[0] > 0, fail_to_convert); + XDBG_GOTO_IF_FAIL(dst->handles[0] > 0, fail_to_convert); + + src_cbuf = calloc(1, sizeof(EXYNOSCvtBuf)); + XDBG_GOTO_IF_FAIL(src_cbuf != NULL, fail_to_convert); + dst_cbuf = calloc(1, sizeof(EXYNOSCvtBuf)); + XDBG_GOTO_IF_FAIL(dst_cbuf != NULL, fail_to_convert); + + src_cbuf->type = CVT_TYPE_SRC; + src_cbuf->vbuf = exynosUtilVideoBufferRef(src); + XDBG_GOTO_IF_FAIL(src_cbuf->vbuf != NULL, fail_to_convert); + memcpy(src_cbuf->handles, src->handles, + sizeof(unsigned int) * EXYNOS_DRM_PLANAR_MAX); + + if (!_exynosCvtQueue(cvt, src_cbuf)) { + exynosUtilVideoBufferUnref(src_cbuf->vbuf); + goto fail_to_convert; + } + + XDBG_DEBUG(MCVT, "cvt(%p) srcbuf(%p) converting(%d)\n", + cvt, src, VBUF_IS_CONVERTING(src)); + + dst_cbuf->type = CVT_TYPE_DST; + dst_cbuf->vbuf = exynosUtilVideoBufferRef(dst); + memcpy(dst_cbuf->handles, dst->handles, + sizeof(unsigned int) * EXYNOS_DRM_PLANAR_MAX); + + if (!_exynosCvtQueue(cvt, dst_cbuf)) { + exynosUtilVideoBufferUnref(dst_cbuf->vbuf); + goto fail_to_convert; + } + + XDBG_DEBUG(MCVT, "cvt(%p) dstbuf(%p) converting(%d)\n", + cvt, dst, VBUF_IS_CONVERTING(dst)); + + XDBG_DEBUG(MVBUF, "==> ipp (%" PRIuPTR ",%d,%d : %" PRIuPTR ",%d,%d) \n", + src->stamp, VBUF_IS_CONVERTING(src), src->showing, + dst->stamp, VBUF_IS_CONVERTING(dst), dst->showing); + + if (!cvt->started) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + + ctrl.prop_id = cvt->prop_id; + ctrl.ctrl = IPP_CTRL_PLAY; + + if (!exynosDrmIppCmdCtrl(cvt->pScrn, &ctrl)) + goto fail_to_convert; + + XDBG_TRACE(MCVT, "cvt(%p) start.\n", cvt); + + cvt->started = TRUE; + } + else if (cvt->paused) { + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + + ctrl.prop_id = cvt->prop_id; + ctrl.ctrl = IPP_CTRL_RESUME; + + XDBG_GOTO_IF_FAIL(exynosDrmIppCmdCtrl(cvt->pScrn, &ctrl), + fail_to_convert); + + XDBG_TRACE(MCVT, "cvt(%p) resume.\n", cvt); + + cvt->paused = FALSE; + } + + dst->dirty = TRUE; + + EXYNOSPtr pExynos = EXYNOSPTR(cvt->pScrn); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_CVT) + src_cbuf->begin = GetTimeInMillis(); + + TTRACE_VIDEO_END(); + + return TRUE; + + fail_to_convert: + + if (src_cbuf) + free(src_cbuf); + if (dst_cbuf) + free(dst_cbuf); + can_pause = FALSE; + _exynosCvtStop(cvt); + + TTRACE_VIDEO_END(); + + return FALSE; +} + +Bool +exynosCvtAddCallback(EXYNOSCvt * cvt, CvtFunc func, void *data) +{ + EXYNOSCvtFuncData *func_data; + + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(func != NULL, FALSE); + + func_data = calloc(1, sizeof(EXYNOSCvtFuncData)); + XDBG_RETURN_VAL_IF_FAIL(func_data != NULL, FALSE); + + xorg_list_add(&func_data->link, &cvt->func_datas); + + func_data->func = func; + func_data->data = data; + + return TRUE; +} + +void +exynosCvtRemoveCallback(EXYNOSCvt * cvt, CvtFunc func, void *data) +{ + EXYNOSCvtFuncData *cur = NULL, *next = NULL; + + XDBG_RETURN_IF_FAIL(cvt != NULL); + XDBG_RETURN_IF_FAIL(func != NULL); + + xorg_list_for_each_entry_safe(cur, next, &cvt->func_datas, link) { + if (cur->func == func && cur->data == data) { + xorg_list_del(&cur->link); + free(cur); + } + } +} + +void +exynosCvtHandleIppEvent(int fd, unsigned int *buf_idx, void *data, Bool error) +{ + uintptr_t stamp = (uintptr_t) data; + EXYNOSCvt *cvt; + EXYNOSCvtBuf *src_cbuf, *dst_cbuf; + EXYNOSVideoBuf *src_vbuf, *dst_vbuf; + EXYNOSCvtFuncData *curr = NULL, *next = NULL; + + XDBG_RETURN_IF_FAIL(buf_idx != NULL); + + cvt = _findCvt(stamp); + if (!cvt) { + XDBG_DEBUG(MCVT, "invalid cvt's stamp (%" PRIuPTR ").\n", stamp); + return; + } + + TTRACE_VIDEO_BEGIN("XORG:IPP:CVT_IPPEVENT"); + + XDBG_DEBUG(MCVT, "cvt(%p) index(%d, %d)\n", + cvt, buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]); + +#if 0 + char temp[64]; + + snprintf(temp, 64, "%d,%d", buf_idx[EXYNOS_DRM_OPS_SRC], + buf_idx[EXYNOS_DRM_OPS_DST]); + _printBufIndices(cvt, CVT_TYPE_SRC, temp); +#endif + +#if DEQUEUE_FORCE + EXYNOSCvtBuf *cur = NULL, *prev = NULL; + + list_rev_for_each_entry_safe(cur, prev, &cvt->src_bufs, link) { + if (buf_idx[EXYNOS_DRM_OPS_SRC] != cur->index) { + unsigned int indice[EXYNOS_DRM_OPS_MAX] = + { cur->index, cur->index }; + + XDBG_WARNING(MCVT, "cvt(%p) event(%d,%d) has been skipped!! \n", + cvt, cur->index, cur->index); + + /* To make sure all events are received, _exynosCvtDequeued should be called + * for every event. If a event has been skipped, to call _exynosCvtDequeued + * forcely, we call exynosCvtHandleIppEvent recursivly. + */ + exynosCvtHandleIppEvent(0, indice, (void *) cvt->stamp, TRUE); + } + else + break; + } +#endif + + src_cbuf = + _exynosCvtFindBuf(cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]); + XDBG_GOTO_IF_FAIL(src_cbuf != NULL, handle_done); + + dst_cbuf = + _exynosCvtFindBuf(cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]); + XDBG_GOTO_IF_FAIL(dst_cbuf != NULL, handle_done); + + EXYNOSPtr pExynos = EXYNOSPTR(cvt->pScrn); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_CVT) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - src_cbuf->begin; + ErrorF("cvt(%p) ipp interval : %6" PRIXID " ms\n", cvt, sub); + } + + src_vbuf = src_cbuf->vbuf; + dst_vbuf = dst_cbuf->vbuf; + + XDBG_DEBUG(MVBUF, "<== ipp (%" PRIuPTR ",%d,%d : %" PRIuPTR ",%d,%d) \n", + src_vbuf->stamp, VBUF_IS_CONVERTING(src_vbuf), src_vbuf->showing, + dst_vbuf->stamp, VBUF_IS_CONVERTING(dst_vbuf), + dst_vbuf->showing); + + if (!cvt->first_event) { + XDBG_DEBUG(MCVT, "cvt(%p) got a IPP event. \n", cvt); + cvt->first_event = TRUE; + } + + xorg_list_for_each_entry_safe(curr, next, &cvt->func_datas, link) { + if (curr->func) + curr->func(cvt, src_vbuf, dst_vbuf, curr->data, error); + } + + _exynosCvtDequeued(cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]); + _exynosCvtDequeued(cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]); + + handle_done: + TTRACE_VIDEO_END(); +} + +Bool +exynosCvtPause(EXYNOSCvt * cvt) +{ + XDBG_RETURN_VAL_IF_FAIL(cvt != NULL, FALSE); + if (!can_pause) { + XDBG_DEBUG(MCVT, "IPP not support pause-resume mode\n"); + return FALSE; + } + if (cvt->paused) { + XDBG_WARNING(MCVT, "IPP already in pause state\n"); + return TRUE; + } + struct drm_exynos_ipp_cmd_ctrl ctrl = { 0, }; + + ctrl.prop_id = cvt->prop_id; + ctrl.ctrl = IPP_CTRL_PAUSE; + + XDBG_GOTO_IF_FAIL(exynosDrmIppCmdCtrl(cvt->pScrn, &ctrl), fail_to_pause); + + XDBG_TRACE(MCVT, "cvt(%p) pause.\n", cvt); + + cvt->paused = TRUE; + + return TRUE; + + fail_to_pause: + + XDBG_ERROR(MCVT, "cvt(%p) pause error.\n", cvt); + can_pause = FALSE; + +// _exynosCvtStop (cvt); + + return FALSE; +} + +uintptr_t +exynosCvtGetStamp(EXYNOSCvt * cvt) +{ + if (cvt == NULL) { + return 0; + } + return cvt->stamp; +} diff --git a/src/ipp/sec_converter.h b/src/ipp/exynos_converter.h index b1b147d..74d9b0e 100644 --- a/src/ipp/sec_converter.h +++ b/src/ipp/exynos_converter.h @@ -32,59 +32,62 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define __SEC_CONVERTER_H__ #include <fbdevhw.h> -#include <exynos_drm.h> +#include <exynos/exynos_drm.h> -typedef struct _SECCvt SECCvt; +typedef struct _EXYNOSCvt EXYNOSCvt; -typedef enum -{ +typedef enum { CVT_OP_M2M, CVT_OP_OUTPUT, CVT_OP_MAX, -} SECCvtOp; +} EXYNOSCvtOp; -typedef enum -{ +typedef enum { CVT_TYPE_SRC, CVT_TYPE_DST, CVT_TYPE_MAX, -} SECCvtType; +} EXYNOSCvtType; -typedef struct _SECCvtProp -{ +typedef struct _EXYNOSCvtProp { unsigned int id; - int width; - int height; - xRectangle crop; + int width; + int height; + xRectangle crop; - int degree; - Bool vflip; - Bool hflip; - Bool secure; - int csc_range; -} SECCvtProp; + int degree; + Bool vflip; + Bool hflip; + Bool exynosure; + int csc_range; +} EXYNOSCvtProp; -typedef struct _SECCvtFmt -{ +typedef struct _EXYNOSCvtFmt { unsigned int id; -} SECCvtFmt; +} EXYNOSCvtFmt; -Bool secCvtSupportFormat (SECCvtOp op, int id); -Bool secCvtEnsureSize (SECCvtProp *src, SECCvtProp *dst); +Bool exynosCvtSupportFormat(EXYNOSCvtOp op, int id); +Bool exynosCvtEnsureSize(EXYNOSCvtProp * src, EXYNOSCvtProp * dst); -SECCvt* secCvtCreate (ScrnInfoPtr pScrn, SECCvtOp op); -void secCvtDestroy (SECCvt *cvt); -SECCvtOp secCvtGetOp (SECCvt *cvt); -Bool secCvtSetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst); -void secCvtGetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst); -Bool secCvtConvert (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst); +EXYNOSCvt *exynosCvtCreate(ScrnInfoPtr pScrn, EXYNOSCvtOp op); +void exynosCvtDestroy(EXYNOSCvt * cvt); +EXYNOSCvtOp exynosCvtGetOp(EXYNOSCvt * cvt); +Bool exynosCvtSetProperpty(EXYNOSCvt * cvt, EXYNOSCvtProp * src, + EXYNOSCvtProp * dst); +void exynosCvtGetProperpty(EXYNOSCvt * cvt, EXYNOSCvtProp * src, + EXYNOSCvtProp * dst); +Bool exynosCvtConvert(EXYNOSCvt * cvt, EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst); -typedef void (*CvtFunc) (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst, void *cvt_data, Bool error); -Bool secCvtAddCallback (SECCvt *cvt, CvtFunc func, void *data); -void secCvtRemoveCallback (SECCvt *cvt, CvtFunc func, void *data); +typedef void (*CvtFunc) (EXYNOSCvt * cvt, EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst, void *cvt_data, Bool error); +Bool exynosCvtAddCallback(EXYNOSCvt * cvt, CvtFunc func, void *data); +void exynosCvtRemoveCallback(EXYNOSCvt * cvt, CvtFunc func, void *data); -void secCvtHandleIppEvent (int fd, unsigned int *buf_idx, void *data, Bool error); +void exynosCvtHandleIppEvent(int fd, unsigned int *buf_idx, void *data, + Bool error); +Bool exynosCvtPause(EXYNOSCvt * cvt); +uintptr_t exynosCvtGetStamp(EXYNOSCvt * cvt); -#endif /* __SEC_CONVERTER_H__ */ +#endif /* __SEC_CONVERTER_H__ */ diff --git a/src/ipp/exynos_drm_ipp.c b/src/ipp/exynos_drm_ipp.c new file mode 100644 index 0000000..f2524c2 --- /dev/null +++ b/src/ipp/exynos_drm_ipp.c @@ -0,0 +1,181 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 <sys/ioctl.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_video_types.h" +#include "exynos_video_fourcc.h" +#include "exynos_drm_ipp.h" + +#include <drm_fourcc.h> + +static unsigned int drmfmt_list[] = { + /* packed */ + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + + /* 2 plane */ + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV12MT, + + /* 3 plane */ + DRM_FORMAT_YVU420, + DRM_FORMAT_YUV420, + DRM_FORMAT_YUV444, +}; + +/* A drmfmt list newly allocated. should be freed. */ +unsigned int * +exynosDrmIppGetFormatList(int *num) +{ + unsigned int *drmfmts; + + XDBG_RETURN_VAL_IF_FAIL(num != NULL, NULL); + + drmfmts = malloc(sizeof(drmfmt_list)); + XDBG_RETURN_VAL_IF_FAIL(drmfmts != NULL, NULL); + + memcpy(drmfmts, drmfmt_list, sizeof(drmfmt_list)); + *num = sizeof(drmfmt_list) / sizeof(unsigned int); + + return drmfmts; +} + +int +exynosDrmIppSetProperty(ScrnInfoPtr pScrn, + struct drm_exynos_ipp_property *property) +{ + int ret = 0; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, -1); + XDBG_RETURN_VAL_IF_FAIL(property != NULL, -1); + + if (property->prop_id == (__u32) - 1) + property->prop_id = 0; + + XDBG_DEBUG(MDRM, + "src : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d) \n", + property->config[0].flip, property->config[0].degree, + FOURCC_STR(property->config[0].fmt), + property->config[0].sz.hsize, property->config[0].sz.vsize, + property->config[0].pos.x, property->config[0].pos.y, + property->config[0].pos.w, property->config[0].pos.h); + XDBG_DEBUG(MDRM, + "dst : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d) \n", + property->config[1].flip, property->config[1].degree, + FOURCC_STR(property->config[1].fmt), + property->config[1].sz.hsize, property->config[1].sz.vsize, + property->config[1].pos.x, property->config[1].pos.y, + property->config[1].pos.w, property->config[1].pos.h); + +#ifdef LEGACY_INTERFACE +#ifdef _F_WEARABLE_FEATURE_ + XDBG_DEBUG(MDRM, + "cmd(%d) type(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d) blending(%x)\n", + property->cmd, property->type, property->ipp_id, + property->prop_id, property->refresh_rate, property->protect, + property->range, property->blending); +#else + XDBG_DEBUG(MDRM, + "cmd(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d)\n", + property->cmd, property->ipp_id, property->prop_id, + property->refresh_rate, property->protect, property->range); +#endif +#else + XDBG_DEBUG(MDRM, "cmd(%d) ipp_id(%d) prop_id(%d) hz(%d) range(%d)\n", + property->cmd, property->ipp_id, property->prop_id, + property->refresh_rate, property->range); +#endif + + ret = + ioctl(EXYNOSPTR(pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_SET_PROPERTY, + property); + if (ret) { + XDBG_ERRNO(MDRM, "failed. \n"); + return -1; + } + + XDBG_TRACE(MDRM, "success. prop_id(%d) \n", property->prop_id); + + return property->prop_id; +} + +Bool +exynosDrmIppQueueBuf(ScrnInfoPtr pScrn, struct drm_exynos_ipp_queue_buf *buf) +{ + int ret = 0; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(buf != NULL, FALSE); + + XDBG_DEBUG(MDRM, + "prop_id(%d) ops_id(%d) ctrl(%d) id(%d) handles(%x %x %x). \n", + buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id, + buf->handle[0], buf->handle[1], buf->handle[2]); + + ret = ioctl(EXYNOSPTR(pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_QUEUE_BUF, buf); + if (ret) { + XDBG_ERRNO(MDRM, "failed. prop_id(%d) op(%d) buf(%d) id(%d)\n", + buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id); + return FALSE; + } + + XDBG_DEBUG(MDRM, "success. prop_id(%d) \n", buf->prop_id); + + return TRUE; +} + +Bool +exynosDrmIppCmdCtrl(ScrnInfoPtr pScrn, struct drm_exynos_ipp_cmd_ctrl *ctrl) +{ + int ret = 0; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(ctrl != NULL, FALSE); + + XDBG_TRACE(MDRM, "prop_id(%d) ctrl(%d). \n", ctrl->prop_id, ctrl->ctrl); + + ret = ioctl(EXYNOSPTR(pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_CMD_CTRL, ctrl); + if (ret) { + XDBG_ERRNO(MDRM, "failed. prop_id(%d) ctrl(%d)\n", + ctrl->prop_id, ctrl->ctrl); + return FALSE; + } + + XDBG_DEBUG(MDRM, "success. prop_id(%d) \n", ctrl->prop_id); + + return TRUE; +} diff --git a/src/ipp/sec_drm_ipp.h b/src/ipp/exynos_drm_ipp.h index e344c4f..e005786 100644 --- a/src/ipp/sec_drm_ipp.h +++ b/src/ipp/exynos_drm_ipp.h @@ -32,13 +32,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define __SEC_DRM_IPP_H__ #include <fbdevhw.h> -#include <exynos_drm.h> +#include <exynos/exynos_drm.h> /* A drmfmt list newly allocated. should be freed. */ -unsigned int* secDrmIppGetFormatList (int *num); +unsigned int *exynosDrmIppGetFormatList(int *num); -int secDrmIppSetProperty (ScrnInfoPtr pScrn, struct drm_exynos_ipp_property *property); -Bool secDrmIppQueueBuf (ScrnInfoPtr pScrn, struct drm_exynos_ipp_queue_buf *buf); -Bool secDrmIppCmdCtrl (ScrnInfoPtr pScrn, struct drm_exynos_ipp_cmd_ctrl *ctrl); +int exynosDrmIppSetProperty(ScrnInfoPtr pScrn, + struct drm_exynos_ipp_property *property); +Bool exynosDrmIppQueueBuf(ScrnInfoPtr pScrn, + struct drm_exynos_ipp_queue_buf *buf); +Bool exynosDrmIppCmdCtrl(ScrnInfoPtr pScrn, + struct drm_exynos_ipp_cmd_ctrl *ctrl); -#endif /* __SEC_DRM_IPP_H__ */ +#endif /* __SEC_DRM_IPP_H__ */ diff --git a/src/ipp/exynos_wb.c b/src/ipp/exynos_wb.c new file mode 100644 index 0000000..6af17ef --- /dev/null +++ b/src/ipp/exynos_wb.c @@ -0,0 +1,1597 @@ +/* + * xserver-xorg-video-exynos + * + * Copyright 2004 Keith Packard + * Copyright 2005 Eric Anholt + * Copyright 2006 Nokia Corporation + * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Boram Park <boram1288.park@samsung.com> + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/poll.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/time.h> + +#include <X11/Xatom.h> +#include <xace.h> +#include <xacestr.h> + +#include <exynos/exynos_drm.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_crtc.h" +#include "exynos_video_fourcc.h" +#include "exynos_video_tvout.h" +#include "exynos_wb.h" +#include "exynos_drm_ipp.h" +#include "exynos_converter.h" + +#include <drm_fourcc.h> + +#define WB_BUF_MAX 5 +#define WB_BUF_DEFAULT 3 +#define WB_BUF_MIN 2 + +enum { + PENDING_NONE, + PENDING_ROTATE, + PENDING_STOP, + PENDING_CLOSE, +}; + +enum { + STATUS_RUNNING, + STATUS_PAUSE, + STATUS_STOP, +}; + +typedef struct _EXYNOSWbNotifyFuncInfo { + EXYNOSWbNotify noti; + WbNotifyFunc func; + void *user_data; + + struct _EXYNOSWbNotifyFuncInfo *next; +} EXYNOSWbNotifyFuncInfo; + +struct _EXYNOSWb { + int prop_id; + + ScrnInfoPtr pScrn; + + unsigned int id; + + int rotate; + + int width; + int height; + xRectangle drm_dst; + xRectangle tv_dst; + + EXYNOSVideoBuf *dst_buf[WB_BUF_MAX]; + Bool queued[WB_BUF_MAX]; + int buf_num; + + int wait_show; + int now_showing; + + EXYNOSWbNotifyFuncInfo *info_list; + + /* for tvout */ + Bool tvout; + EXYNOSVideoTv *tv; + EXYNOSLayerPos lpos; + + Bool need_rotate_hook; + OsTimerPtr rotate_timer; + + /* count */ + unsigned int put_counts; + unsigned int last_counts; + OsTimerPtr timer; + + OsTimerPtr event_timer; + OsTimerPtr ipp_timer; + + Bool scanout; + int hz; + + int status; + Bool exynosure; + CARD32 prev_time; +}; + +static unsigned int formats[] = { + FOURCC_RGB32, + FOURCC_ST12, + FOURCC_SN12, +}; + +static EXYNOSWb *keep_wb; +static Atom atom_wb_rotate; + +static void _exynosWbQueue(EXYNOSWb * wb, int index); +static Bool _exynosWbRegisterRotateHook(EXYNOSWb * wb, Bool hook); +static void _exynosWbCloseDrmDstBuffer(EXYNOSWb * wb); +static void _exynosWbCloseDrm(EXYNOSWb * wb, Bool pause); + +static CARD32 +_exynosWbCountPrint(OsTimerPtr timer, CARD32 now, pointer arg) +{ + XDBG_DEBUG(MWB, "E. timer %p now %" PRIXID " arg %p\n", timer, now, arg); + EXYNOSWb *wb = (EXYNOSWb *) arg; + + ErrorF("IppEvent : %d fps. \n", wb->put_counts - wb->last_counts); + + wb->last_counts = wb->put_counts; + + wb->timer = TimerSet(wb->timer, 0, 1000, _exynosWbCountPrint, arg); + XDBG_DEBUG(MWB, "Q. wb->timer = %p. ret 0\n", wb->timer); + return 0; +} + +static void +_exynosWbCountFps(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + wb->put_counts++; + + if (wb->timer) { + XDBG_DEBUG(MWB, "Q. wb->timer == %p\n", wb->timer); + return; + } + wb->timer = TimerSet(NULL, 0, 1000, _exynosWbCountPrint, wb); + XDBG_DEBUG(MWB, "Q. wb->timer = %p\n", wb->timer); +} + +static void +_exynosWbCountStop(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (wb->timer) { + TimerFree(wb->timer); + wb->timer = NULL; + } + + wb->put_counts = 0; + wb->last_counts = 0; + XDBG_DEBUG(MWB, "Q.\n"); +} + +static unsigned int +_exynosWbSupportFormat(int id) +{ + XDBG_DEBUG(MWB, "E. id %d\n", id); + unsigned int *drmfmts; + int i, size, num = 0; + unsigned int drmfmt = exynosUtilGetDrmFormat(id); + + size = sizeof(formats) / sizeof(unsigned int); + + for (i = 0; i < size; i++) + if (formats[i] == id) + break; + + if (i == size) { + XDBG_ERROR(MWB, "wb not support : '%c%c%c%c'.\n", FOURCC_STR(id)); + XDBG_DEBUG(MWB, "Q. i(%d) == size(%d). ret 0\n", i, size); + return 0; + } + + drmfmts = exynosDrmIppGetFormatList(&num); + if (!drmfmts) { + XDBG_ERROR(MWB, "no drm format list.\n"); + XDBG_DEBUG(MWB, "Q. drmfmts(%p) == NULL. ret 0\n", drmfmts); + return 0; + } + + for (i = 0; i < num; i++) + if (drmfmts[i] == drmfmt) { + free(drmfmts); + XDBG_DEBUG(MWB, "Q. id(%d) is support. ret %d(drmfmt)\n", id, + drmfmt); + return drmfmt; + } + + XDBG_ERROR(MWB, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR(id)); + + free(drmfmts); + XDBG_DEBUG(MWB, "Q. id %d not found in support format list. ret 0\n", id); + return 0; +} + +static void +_exynosWbCallNotifyFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, void *noti_data) +{ + XDBG_DEBUG(MWB, "E. wb %p noti %d noti_data %p\n", wb, noti, noti_data); + EXYNOSWbNotifyFuncInfo *info; + + nt_list_for_each_entry(info, wb->info_list, next) { + if (info->noti == noti && info->func) + info->func(wb, noti, noti_data, info->user_data); + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +static void +_exynosWbLayerNotifyFunc(EXYNOSLayer * layer, int type, void *type_data, + void *data) +{ + XDBG_DEBUG(MWB, "E. layer %p type %d type_data %p data %p\n", layer, type, + type_data, data); + EXYNOSWb *wb = (EXYNOSWb *) data; + EXYNOSVideoBuf *vbuf = (EXYNOSVideoBuf *) type_data; + + if (type != LAYER_VBLANK) { + XDBG_DEBUG(MWB, "Q. type(%d) != LAYER_VBLANK\n", type); + return; + } + XDBG_RETURN_IF_FAIL(wb != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(vbuf)); + + if (wb->status == STATUS_PAUSE) { + XDBG_WARNING(MWB, "pause status. return.\n"); + XDBG_DEBUG(MWB, "Q. wb->status == STATUS_PAUSE\n"); + return; + } + + if (wb->wait_show >= 0 && wb->dst_buf[wb->wait_show] != vbuf) + XDBG_WARNING(MWB, "wait_show(%d,%p) != showing_vbuf(%p). \n", + wb->wait_show, wb->dst_buf[wb->wait_show], vbuf); + + if (wb->now_showing >= 0) + _exynosWbQueue(wb, wb->now_showing); + + wb->now_showing = wb->wait_show; + wb->wait_show = -1; + + XDBG_TRACE(MWB, "now_showing(%d,%p). \n", wb->now_showing, vbuf); + XDBG_DEBUG(MWB, "Q.\n"); +} + +static Bool +_exynosWbCalTvoutRect(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(wb->pScrn)->pExynosMode; + int src_w, src_h, dst_w, dst_h; + + if (!wb->tvout) { + if (wb->width == 0 || wb->height == 0) { + wb->width = pExynosMode->main_lcd_mode.hdisplay; + wb->height = pExynosMode->main_lcd_mode.vdisplay; + } + + src_w = pExynosMode->main_lcd_mode.hdisplay; + src_h = pExynosMode->main_lcd_mode.vdisplay; + dst_w = wb->width; + dst_h = wb->height; + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { + XDBG_ERROR(MWB, "Error. Receive Negative size\n"); + XDBG_DEBUG(MWB, + "Q. src_w(%d) <= 0 || src_h(%d) <= 0 || dst_w(%d) <= 0 || dst_h(%d) <= 0. ret FALSE\n", + src_w, src_h, dst_w, dst_h); + return FALSE; + } + + if (wb->rotate % 180) + SWAP(src_w, src_h); + + exynosUtilAlignRect(src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE); + } + else { + src_w = (int) pExynosMode->main_lcd_mode.hdisplay; + src_h = (int) pExynosMode->main_lcd_mode.vdisplay; + dst_w = (int) pExynosMode->ext_connector_mode.hdisplay; + dst_h = (int) pExynosMode->ext_connector_mode.vdisplay; + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) { + XDBG_ERROR(MWB, "Error. Receive Negative size\n"); + XDBG_DEBUG(MWB, + "Q. src_w(%d) <= 0 || src_h(%d) <= 0 || dst_w(%d) <= 0 || dst_h(%d) <= 0. ret FALSE\n", + src_w, src_h, dst_w, dst_h); + return FALSE; + } + + if (wb->rotate % 180) + SWAP(src_w, src_h); +#if 0 + if (wb->lpos == LAYER_UPPER) { + /* Mixer can't scale. */ + wb->width = dst_w; + wb->height = dst_h; + wb->tv_dst.width = wb->width; + wb->tv_dst.height = wb->height; + + exynosUtilAlignRect(src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE); + } + else { /* LAYER_LOWER1 */ + + /* VP can scale */ + exynosUtilAlignRect(src_w, src_h, dst_w, dst_h, &wb->tv_dst, TRUE); + + wb->width = src_w; + wb->height = src_h; + + wb->drm_dst.width = wb->width; + wb->drm_dst.height = wb->height; + } +#else + /* Mixer can't scale. */ + wb->width = dst_w; + wb->height = dst_h; + wb->tv_dst.width = wb->width; + wb->tv_dst.height = wb->height; + + exynosUtilAlignRect(src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE); +#endif + } + + XDBG_TRACE(MWB, + "tvout(%d) lpos(%d) src(%dx%d) drm_dst(%d,%d %dx%d) tv_dst(%d,%d %dx%d).\n", + wb->tvout, wb->lpos, wb->width, wb->height, wb->drm_dst.x, + wb->drm_dst.y, wb->drm_dst.width, wb->drm_dst.height, + wb->tv_dst.x, wb->tv_dst.y, wb->tv_dst.width, wb->tv_dst.height); + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; +} + +static void +_exynosWbQueue(EXYNOSWb * wb, int index) +{ + XDBG_DEBUG(MWB, "E. wb %p index %d\n", wb, index); + struct drm_exynos_ipp_queue_buf buf; + int j; + + if (index < 0) { + XDBG_DEBUG(MWB, "Q. index(%d) < 0\n", index); + return; + } + + if (wb->dst_buf[index]->showing == TRUE) { + XDBG_DEBUG(MWB, "Q. wb->dst_buf[$d]->showing == TRUE\n", index); + return; + } + CLEAR(buf); + buf.ops_id = EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_ENQUEUE; + buf.prop_id = wb->prop_id; + buf.buf_id = index; + buf.user_data = (__u64) (uintptr_t) wb; + + for (j = 0; j < PLANAR_CNT; j++) + buf.handle[j] = wb->dst_buf[index]->handles[j]; + + if (!exynosDrmIppQueueBuf(wb->pScrn, &buf)) { + XDBG_DEBUG(MWB, "Q. exynosDrmIppQueueBuf == FALSE\n"); + return; + } + + wb->queued[index] = TRUE; + wb->dst_buf[index]->dirty = TRUE; + + XDBG_TRACE(MWB, "index(%d)\n", index); + XDBG_DEBUG(MWB, "Q.\n"); +} + +static int +_exynosWbDequeued(EXYNOSWb * wb, Bool skip_put, int index) +{ + XDBG_DEBUG(MWB, "E. wb %p skip_put %s index %d\n", wb, + skip_put ? "TRUE" : "FALSE", index); + int i, remain = 0; + + if (index >= wb->buf_num) { + XDBG_ERROR(MWB, "Wrong buf index\n"); + XDBG_DEBUG(MWB, "Q. index(%d) >= wb->buf_num($d). ret -1\n", index, + wb->buf_num); + return -1; + } + XDBG_WARNING_IF_FAIL(wb->dst_buf[index]->showing == FALSE); + + XDBG_TRACE(MWB, "skip_put(%d) index(%d)\n", skip_put, index); + + if (!wb->queued[index]) + XDBG_WARNING(MWB, "buf(%d) already dequeued.\n", index); + + wb->queued[index] = FALSE; + + for (i = 0; i < wb->buf_num; i++) { + if (wb->queued[i]) + remain++; + } + + /* the count of remain buffers should be more than 2. */ + if (remain >= WB_BUF_MIN) + _exynosWbCallNotifyFunc(wb, WB_NOTI_IPP_EVENT, + (void *) wb->dst_buf[index]); + else + XDBG_TRACE(MWB, "remain buffer count: %d\n", remain); + + if (wb->tvout) { + if (!wb->tv) { + if (wb->tv_dst.width > 0 && wb->tv_dst.height > 0) + wb->tv = exynosVideoTvConnect(wb->pScrn, wb->id, wb->lpos); + + if (wb->tv && !exynosUtilEnsureExternalCrtc(wb->pScrn)) { + wb->tvout = FALSE; + exynosVideoTvDisconnect(wb->tv); + wb->tv = NULL; + } + + if (wb->tv) { + EXYNOSLayer *layer = exynosVideoTvGetLayer(wb->tv); + + exynosLayerEnableVBlank(layer, TRUE); + exynosLayerAddNotifyFunc(layer, _exynosWbLayerNotifyFunc, wb); + } + } + + if (!skip_put && wb->tv) { + wb->wait_show = index; + exynosVideoTvPutImage(wb->tv, wb->dst_buf[index], &wb->tv_dst, 0); + } + } + + if (remain == 0) + XDBG_ERROR(MWB, "*** wb's buffer empty!! *** \n"); + + XDBG_TRACE(MWB, "tv(%p) wait_show(%d) remain(%d)\n", wb->tv, + wb->wait_show, remain); + XDBG_DEBUG(MWB, "Q. ret %d(index)\n", index); + return index; +} + +static CARD32 +_exynosWbIppRetireTimeout(OsTimerPtr timer, CARD32 now, pointer arg) +{ + XDBG_DEBUG(MWB, "E. timer %p now %" PRIXID " arg %p\n", timer, now, arg); + EXYNOSWb *wb = (EXYNOSWb *) arg; + + if (wb->ipp_timer) { + TimerFree(wb->ipp_timer); + wb->ipp_timer = NULL; + } + + XDBG_ERROR(MWB, "failed : +++ WB IPP Retire Timeout!!\n"); + XDBG_DEBUG(MWB, "Q. ret 0\n"); + return 0; +} + +unsigned int +exynosWbGetPropID(void) +{ + XDBG_DEBUG(MWB, "E.\n"); + if (!keep_wb) { + XDBG_DEBUG(MWB, "Q. keep_wb == NULL. ret -1\n"); + return -1; + } + XDBG_DEBUG(MWB, "Q. ret %d(prop_id)\n", keep_wb->prop_id); + return keep_wb->prop_id; +} + +void +exynosWbHandleIppEvent(int fd, unsigned int *buf_idx, void *data) +{ + XDBG_DEBUG(MWB, "E. fd %d buf_idx %p data %p\n", fd, buf_idx, data); + EXYNOSWb *wb = (EXYNOSWb *) data; + EXYNOSPtr pExynos; + int index = buf_idx[EXYNOS_DRM_OPS_DST]; + + if (!wb) { + XDBG_ERROR(MWB, "Error. receive NULL data\n"); + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + + if (keep_wb != wb) { + XDBG_WARNING(MWB, "Useless ipp event! (%p) \n", wb); + XDBG_DEBUG(MWB, "Q. wb(%p) != keep_wb(%p)\n\n", wb, keep_wb); + return; + } + + if (wb->event_timer) { + TimerFree(wb->event_timer); + wb->event_timer = NULL; + } + + if ((wb->status == STATUS_STOP) || (wb->status == STATUS_PAUSE)) { + XDBG_ERROR(MWB, "stop or pause. ignore a event. %p, (status:%d)\n", + data, wb->status); + XDBG_DEBUG(MWB, "Q. wb->status == %s\n", + (wb->status == + STATUS_STOP) ? "STATUS_STOP" : "STATUS_PAUSE"); + return; + } + + if (wb->ipp_timer) { + TimerFree(wb->ipp_timer); + wb->ipp_timer = NULL; + } + + wb->ipp_timer = + TimerSet(wb->ipp_timer, 0, 2000, _exynosWbIppRetireTimeout, wb); + + XDBG_TRACE(MWB, "=============== wb(%p) !\n", wb); + + pExynos = EXYNOSPTR(wb->pScrn); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_WB) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - wb->prev_time; + wb->prev_time = cur; + ErrorF("wb evt interval : %6" PRIXID " ms\n", sub); + } + + if (pExynos->wb_fps) + _exynosWbCountFps(wb); + else + _exynosWbCountStop(wb); + + if (wb->rotate_timer) { + _exynosWbDequeued(wb, TRUE, index); + _exynosWbQueue(wb, index); + } + else { + if (wb->wait_show >= 0) { + _exynosWbDequeued(wb, TRUE, index); + _exynosWbQueue(wb, index); + } + else { + _exynosWbDequeued(wb, FALSE, index); + + if (wb->wait_show < 0 && !wb->dst_buf[index]->showing) + _exynosWbQueue(wb, index); + } + } + + _exynosWbCallNotifyFunc(wb, WB_NOTI_IPP_EVENT_DONE, NULL); + + XDBG_TRACE(MWB, "=============== !\n"); + XDBG_DEBUG(MWB, "Q.\n"); +} + +static Bool +_exynosWbEnsureDrmDstBuffer(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + int i; + + for (i = 0; i < wb->buf_num; i++) { + if (wb->dst_buf[i]) { + exynosUtilClearVideoBuffer(wb->dst_buf[i]); + continue; + } + + wb->dst_buf[i] = exynosUtilAllocVideoBuffer(wb->pScrn, wb->id, + wb->width, wb->height, + keep_wb->scanout, TRUE, + exynosVideoIsSecureMode + (wb->pScrn)); + XDBG_GOTO_IF_FAIL(wb->dst_buf[i] != NULL, fail_to_ensure); + } + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; + fail_to_ensure: + _exynosWbCloseDrmDstBuffer(wb); + XDBG_DEBUG(MWB, "Q. ret FALSE\n"); + return FALSE; +} + +static void +_exynosWbCloseDrmDstBuffer(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + int i; + + for (i = 0; i < wb->buf_num; i++) { + if (wb->dst_buf[i]) { + exynosUtilVideoBufferUnref(wb->dst_buf[i]); + wb->dst_buf[i] = NULL; + } + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +static void +_exynosWbClearDrmDstBuffer(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + int i; + + for (i = 0; i < wb->buf_num; i++) { + if (wb->dst_buf[i]) { + if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset) + exynosUtilClearVideoBuffer(wb->dst_buf[i]); + else + wb->dst_buf[i]->need_reset = TRUE; + } + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +static CARD32 +_exynosWbEventTimeout(OsTimerPtr timer, CARD32 now, pointer arg) +{ + XDBG_DEBUG(MWB, "E. timer %p now %" PRIXID " arg %p\n", timer, now, arg); + EXYNOSWb *wb = (EXYNOSWb *) arg; + + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret 0\n"); + return 0; + } + + if (wb->event_timer) { + TimerFree(wb->event_timer); + wb->event_timer = NULL; + } + + XDBG_ERROR(MWB, "*** ipp event not happen!! \n"); + XDBG_DEBUG(MWB, "E. ret 0\n"); + return 0; +} + +static Bool +_exynosWbOpenDrm(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + EXYNOSPtr pExynos = EXYNOSPTR(wb->pScrn); + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) pExynos->pExynosMode; + int i; + unsigned int drmfmt = 0; + struct drm_exynos_ipp_property property; + enum drm_exynos_degree degree; + struct drm_exynos_ipp_cmd_ctrl ctrl; + + if (wb->need_rotate_hook) + _exynosWbRegisterRotateHook(wb, TRUE); + + if (!_exynosWbCalTvoutRect(wb)) + goto fail_to_open; + + drmfmt = _exynosWbSupportFormat(wb->id); + XDBG_GOTO_IF_FAIL(drmfmt > 0, fail_to_open); + + if ((wb->rotate) % 360 == 90) + degree = EXYNOS_DRM_DEGREE_90; + else if ((wb->rotate) % 360 == 180) + degree = EXYNOS_DRM_DEGREE_180; + else if ((wb->rotate) % 360 == 270) + degree = EXYNOS_DRM_DEGREE_270; + else + degree = EXYNOS_DRM_DEGREE_0; + + CLEAR(property); + property.config[0].ops_id = EXYNOS_DRM_OPS_SRC; + property.config[0].fmt = DRM_FORMAT_YUV444; + property.config[0].sz.hsize = (__u32) pExynosMode->main_lcd_mode.hdisplay; + property.config[0].sz.vsize = (__u32) pExynosMode->main_lcd_mode.vdisplay; + property.config[0].pos.x = 0; + property.config[0].pos.y = 0; + property.config[0].pos.w = (__u32) pExynosMode->main_lcd_mode.hdisplay; + property.config[0].pos.h = (__u32) pExynosMode->main_lcd_mode.vdisplay; + property.config[1].ops_id = EXYNOS_DRM_OPS_DST; + property.config[1].degree = degree; + property.config[1].fmt = drmfmt; + property.config[1].sz.hsize = wb->width; + property.config[1].sz.vsize = wb->height; + property.config[1].pos.x = (__u32) wb->drm_dst.x; + property.config[1].pos.y = (__u32) wb->drm_dst.y; + property.config[1].pos.w = (__u32) wb->drm_dst.width; + property.config[1].pos.h = (__u32) wb->drm_dst.height; + property.cmd = IPP_CMD_WB; +#ifdef _F_WEARABLE_FEATURE_ + property.type = IPP_EVENT_DRIVEN; +#endif + property.prop_id = wb->prop_id; + property.refresh_rate = wb->hz; +#ifdef LEGACY_INTERFACE + property.protect = wb->exynosure; +#endif + + wb->prop_id = exynosDrmIppSetProperty(wb->pScrn, &property); + XDBG_GOTO_IF_FAIL(wb->prop_id >= 0, fail_to_open); + + XDBG_TRACE(MWB, + "prop_id(%d) drmfmt(%c%c%c%c) size(%dx%d) crop(%d,%d %dx%d) rotate(%d)\n", + wb->prop_id, FOURCC_STR(drmfmt), wb->width, wb->height, + wb->drm_dst.x, wb->drm_dst.y, wb->drm_dst.width, + wb->drm_dst.height, wb->rotate); + + if (!_exynosWbEnsureDrmDstBuffer(wb)) + goto fail_to_open; + + for (i = 0; i < wb->buf_num; i++) { + struct drm_exynos_ipp_queue_buf buf; + int j; + + if (wb->dst_buf[i]->showing) { + XDBG_TRACE(MWB, "%d. name(%d) is showing\n", i, + wb->dst_buf[i]->keys[0]); + continue; + } + + CLEAR(buf); + buf.ops_id = EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_ENQUEUE; + buf.prop_id = wb->prop_id; + buf.buf_id = i; + buf.user_data = (__u64) (uintptr_t) wb; + + XDBG_GOTO_IF_FAIL(wb->dst_buf[i] != NULL, fail_to_open); + + for (j = 0; j < PLANAR_CNT; j++) + buf.handle[j] = wb->dst_buf[i]->handles[j]; + + if (!exynosDrmIppQueueBuf(wb->pScrn, &buf)) + goto fail_to_open; + + wb->queued[i] = TRUE; + } + + CLEAR(ctrl); + ctrl.prop_id = wb->prop_id; + ctrl.ctrl = IPP_CTRL_PLAY; + if (!exynosDrmIppCmdCtrl(wb->pScrn, &ctrl)) + goto fail_to_open; + + wb->event_timer = + TimerSet(wb->event_timer, 0, 3000, _exynosWbEventTimeout, wb); + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; + + fail_to_open: + + _exynosWbCloseDrm(wb, FALSE); + + _exynosWbCloseDrmDstBuffer(wb); + XDBG_DEBUG(MWB, "Q. ret FALSE\n"); + return FALSE; +} + +static void +_exynosWbCloseDrm(EXYNOSWb * wb, Bool pause) +{ + XDBG_DEBUG(MWB, "E. wb %p pause %s\n", wb, pause ? "TRUE" : "FALSE"); + struct drm_exynos_ipp_cmd_ctrl ctrl; + int i; + + _exynosWbCountStop(wb); + + XDBG_TRACE(MWB, "now_showing(%d) \n", wb->now_showing); + + /* pause : remain displaying layer buffer */ + if (wb->tv && !pause) { + exynosVideoTvDisconnect(wb->tv); + wb->tv = NULL; + wb->wait_show = -1; + wb->now_showing = -1; + } + + for (i = 0; i < wb->buf_num; i++) { + struct drm_exynos_ipp_queue_buf buf; + int j; + + CLEAR(buf); + buf.ops_id = EXYNOS_DRM_OPS_DST; + buf.buf_type = IPP_BUF_DEQUEUE; + buf.prop_id = wb->prop_id; + buf.buf_id = i; + + if (wb->dst_buf[i]) + for (j = 0; j < EXYNOS_DRM_PLANAR_MAX; j++) + buf.handle[j] = wb->dst_buf[i]->handles[j]; + + exynosDrmIppQueueBuf(wb->pScrn, &buf); + + wb->queued[i] = FALSE; + + } + + CLEAR(ctrl); + ctrl.prop_id = wb->prop_id; + ctrl.ctrl = IPP_CTRL_STOP; + exynosDrmIppCmdCtrl(wb->pScrn, &ctrl); + + wb->prop_id = -1; + + if (wb->rotate_timer) { + TimerFree(wb->rotate_timer); + wb->rotate_timer = NULL; + } + + if (wb->event_timer) { + TimerFree(wb->event_timer); + wb->event_timer = NULL; + } + + if (wb->ipp_timer) { + TimerFree(wb->ipp_timer); + wb->ipp_timer = NULL; + } + + if (wb->need_rotate_hook) + _exynosWbRegisterRotateHook(wb, FALSE); + XDBG_DEBUG(MWB, "Q.\n"); +} + +static CARD32 +_exynosWbRotateTimeout(OsTimerPtr timer, CARD32 now, pointer arg) +{ + XDBG_DEBUG(MWB, "E. timer %p now %" PRIXID " arg %p\n", timer, now, arg); + EXYNOSWb *wb = (EXYNOSWb *) arg; + PropertyPtr rotate_prop; + + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret 0\n"); + return 0; + } + if (wb->rotate_timer) { + TimerFree(wb->rotate_timer); + wb->rotate_timer = NULL; + } + + rotate_prop = + exynosUtilGetWindowProperty(wb->pScrn->pScreen->root, + "_E_ILLUME_ROTATE_ROOT_ANGLE"); + if (rotate_prop) { + int rotate = *(int *) rotate_prop->data; + + XDBG_TRACE(MWB, "timeout : rotate(%d)\n", rotate); + + if (wb->rotate != rotate) + if (!exynosWbSetRotate(wb, rotate)) { + XDBG_DEBUG(MWB, "Q. exynosWbSetRotate == FALSE. ret 0\n"); + return 0; + } + } + + /* make sure streaming is on. */ + exynosWbStart(wb); + XDBG_DEBUG(MWB, "Q. ret 0\n"); + return 0; +} + +static void +_exynosWbRotateHook(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XDBG_DEBUG(MWB, "E. pcbl %p unused %p calldata %p\n", pcbl, unused, + calldata); + EXYNOSWb *wb = (EXYNOSWb *) unused; + ScrnInfoPtr pScrn; + + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + + XacePropertyAccessRec *rec = (XacePropertyAccessRec *) calldata; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + + pScrn = wb->pScrn; + + if (rec->pWin != pScrn->pScreen->root) //Check Rootwindow + { + XDBG_DEBUG(MWB, "Q. rec->pWin(%p) != pScrn->pScreen->root(%p)\n", + rec->pWin, pScrn->pScreen->root); + return; + } + if (name == atom_wb_rotate && (rec->access_mode & DixWriteAccess)) { + int rotate = *(int *) pProp->data; + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + + if (wb->rotate == rotate) { + XDBG_DEBUG(MWB, "Q. wb->rotate(%d) == rotate(%d)\n", + wb->rotate, rotate); + return; + } + XDBG_TRACE(MWB, "Change root angle(%d)\n", rotate); + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + exynosWbStop(wb, FALSE); + else + exynosWbStop(wb, TRUE); + + wb->rotate_timer = TimerSet(wb->rotate_timer, 0, 800, + _exynosWbRotateTimeout, wb); + } + XDBG_DEBUG(MWB, "Q.\n"); + return; +} + +static Bool +_exynosWbRegisterRotateHook(EXYNOSWb * wb, Bool hook) +{ + XDBG_DEBUG(MWB, "E. wb %p hook %s\n", wb, hook ? "TRUE" : "FALSE"); + ScrnInfoPtr pScrn = wb->pScrn; + + XDBG_TRACE(MWB, "hook(%d) \n", hook); + + if (hook) { + PropertyPtr rotate_prop; + + rotate_prop = + exynosUtilGetWindowProperty(pScrn->pScreen->root, + "_E_ILLUME_ROTATE_ROOT_ANGLE"); + if (rotate_prop) { + int rotate = *(int *) rotate_prop->data; + + exynosWbSetRotate(wb, rotate); + } + + /* Hook for window rotate */ + if (atom_wb_rotate == None) + atom_wb_rotate = MakeAtom("_E_ILLUME_ROTATE_ROOT_ANGLE", + strlen("_E_ILLUME_ROTATE_ROOT_ANGLE"), + FALSE); + + if (atom_wb_rotate != None) { + if (!XaceRegisterCallback + (XACE_PROPERTY_ACCESS, _exynosWbRotateHook, wb)) + XDBG_ERROR(MWB, "fail to XaceRegisterCallback.\n"); + } + else + XDBG_WARNING(MWB, "Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n"); + } + else + XaceDeleteCallback(XACE_PROPERTY_ACCESS, _exynosWbRotateHook, wb); + XDBG_DEBUG(MWB, "Q.\n"); + return TRUE; +} + +Bool +exynosWbIsOpened(void) +{ + XDBG_DEBUG(MWB, "E.\n"); + XDBG_DEBUG(MWB, "Q. ret = %s\n", keep_wb ? "TRUE" : "FALSE"); + return (keep_wb) ? TRUE : FALSE; +} + +Bool +exynosWbIsRunning(void) +{ + XDBG_DEBUG(MWB, "E.\n"); + if (!keep_wb) { + XDBG_DEBUG(MWB, "Q. keep_wb == NULL. ret FALSE\n"); + return FALSE; + } + XDBG_DEBUG(MWB, "Q. ret %s\n", + (keep_wb->status == STATUS_RUNNING) ? "TRUE" : "FALSE"); + return (keep_wb->status == STATUS_RUNNING) ? TRUE : FALSE; +} + +EXYNOSWb * +_exynosWbOpen(ScrnInfoPtr pScrn, unsigned int id, int width, int height, + Bool scanout, int hz, Bool need_rotate_hook, const char *func) +{ + XDBG_DEBUG(MWB, + "E. pScrn %p id %u width %d height %d scanout %s hz %d need_rotate_hook %s\n", + pScrn, id, width, height, scanout ? "TRUE" : "FALSE", hz, + need_rotate_hook ? "TRUE" : "FALSE"); + EXYNOSModePtr pExynosMode = NULL; + + if (!pScrn) { + XDBG_DEBUG(MWB, "Q. pScrn == NULL. ret NULL\n"); + return NULL; + } + + pExynosMode = EXYNOSPTR(pScrn)->pExynosMode; + + if (keep_wb) { + XDBG_ERROR(MWB, "WB already opened. \n"); + XDBG_DEBUG(MWB, "Q. keep_wb(%p) != NULL. ret NULL\n", keep_wb); + return NULL; + } + + if (_exynosWbSupportFormat(id) == 0) { + XDBG_ERROR(MWB, "'%c%c%c%c' not supported. \n", FOURCC_STR(id)); + XDBG_DEBUG(MWB, "Q. _exynosWbSupportFormat(%d) == 0. ret NULL\n", id); + return NULL; + } + + if (EXYNOSPTR(pScrn)->isLcdOff) { + XDBG_ERROR(MWB, "Can't open wb during DPMS off. \n"); + XDBG_DEBUG(MWB, "Q. isLcdOff == TRUE. ret NULL\n"); + return NULL; + } + + keep_wb = calloc(sizeof(EXYNOSWb), 1); + + if (!keep_wb) { + XDBG_DEBUG(MWB, "Q. keep_wb == NULL. ret NULL\n"); + return NULL; + } + + keep_wb->prop_id = -1; + keep_wb->pScrn = pScrn; + keep_wb->id = id; + + keep_wb->wait_show = -1; + keep_wb->now_showing = -1; + + keep_wb->width = width; + keep_wb->height = height; + keep_wb->status = STATUS_STOP; + + keep_wb->scanout = scanout; + keep_wb->hz = (hz > 0) ? hz : 60; + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_HDMI && + keep_wb->hz > pExynosMode->ext_connector_mode.vrefresh) + keep_wb->buf_num = WB_BUF_MAX; + else + keep_wb->buf_num = WB_BUF_DEFAULT; + + if (id == FOURCC_RGB32 || id == FOURCC_RGB24) + keep_wb->lpos = LAYER_DEFAULT; + else + keep_wb->lpos = LAYER_LOWER1; + + keep_wb->need_rotate_hook = need_rotate_hook; + + XDBG_SECURE(MWB, + "wb(%p) id(%c%c%c%c) size(%dx%d) scanout(%d) hz(%d) rhoot(%d) buf_num(%d): %s\n", + keep_wb, FOURCC_STR(id), keep_wb->width, keep_wb->height, + scanout, hz, need_rotate_hook, keep_wb->buf_num, func); + XDBG_DEBUG(MWB, "Q. ret %p(keep_wb)\n", keep_wb); + return keep_wb; +} + +void +_exynosWbClose(EXYNOSWb * wb, const char *func) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + EXYNOSWbNotifyFuncInfo *info, *tmp; + + if (!wb) { + XDBG_ERROR(MWB, "wb is NULL\n"); + XDBG_DEBUG(MWB, "Q.\n"); + return; + } + if (keep_wb != wb) { + XDBG_ERROR(MWB, "wb(%p) != keep_wb(%p)\n", wb, keep_wb); + XDBG_DEBUG(MWB, "Q.\n"); + return; + } + exynosWbStop(wb, TRUE); + + XDBG_SECURE(MWB, "wb(%p): %s \n", wb, func); + + _exynosWbCallNotifyFunc(wb, WB_NOTI_CLOSED, NULL); + + nt_list_for_each_entry_safe(info, tmp, wb->info_list, next) { + nt_list_del(info, wb->info_list, EXYNOSWbNotifyFuncInfo, next); + free(info); + } + + free(wb); + keep_wb = NULL; + XDBG_DEBUG(MWB, "Q.\n"); +} + +Bool +_exynosWbStart(EXYNOSWb * wb, const char *func) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + EXYNOSPtr pExynos; + + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL, ret FALSE\n"); + return FALSE; + } + pExynos = EXYNOSPTR(wb->pScrn); + if (pExynos->isLcdOff) { + XDBG_ERROR(MWB, "Can't start wb(%p) during DPMS off. \n", wb); + XDBG_DEBUG(MWB, "Q. isLcdOff == TRUE. ret FALSE\n"); + return FALSE; + } + + if (wb->status == STATUS_RUNNING) { + XDBG_DEBUG(MWB, "Q. wb->status == STATUS_RUNNING. ret TRUE\n"); + return TRUE; + } + if (!_exynosWbOpenDrm(wb)) { + XDBG_ERROR(MWB, "open fail. \n"); + XDBG_DEBUG(MWB, "Q. _exynosWbOpenDrm == FALSE. ret FALSE\n"); + return FALSE; + } + + wb->status = STATUS_RUNNING; + + _exynosWbCallNotifyFunc(wb, WB_NOTI_START, NULL); + + XDBG_TRACE(MWB, "start: %s \n", func); + + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; +} + +void +_exynosWbStop(EXYNOSWb * wb, Bool close_buf, const char *func) +{ + XDBG_DEBUG(MWB, "E. wb %p close_buf %s\n", wb, + close_buf ? "TRUE" : "FALSE"); + if (!wb) { + XDBG_ERROR(MWB, "wb is NULL\n"); + XDBG_DEBUG(MWB, "Q.\n"); + return; + } + if ((wb->status == STATUS_STOP) || (wb->status == STATUS_PAUSE)) { + if (wb->rotate_timer) { + TimerFree(wb->rotate_timer); + wb->rotate_timer = NULL; + } + XDBG_DEBUG(MWB, "Q. wb->status == %s\n", + (wb->status == + STATUS_STOP) ? "STATUS_STOP" : "STATUS_PAUSE"); + return; + } + + _exynosWbCloseDrm(wb, FALSE); + + if (close_buf) + _exynosWbCloseDrmDstBuffer(wb); + else + _exynosWbClearDrmDstBuffer(wb); + + wb->status = STATUS_STOP; + + _exynosWbCallNotifyFunc(wb, WB_NOTI_STOP, NULL); + + XDBG_TRACE(MWB, "stop: %s \n", func); + XDBG_DEBUG(MWB, "Q.\n"); +} + +void +exynosWbPause(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + + if ((wb->status == STATUS_STOP) || (wb->status == STATUS_PAUSE)) { + if (wb->rotate_timer) { + TimerFree(wb->rotate_timer); + wb->rotate_timer = NULL; + } + XDBG_DEBUG(MWB, "Q. wb->status == %s\n", + (wb->status == + STATUS_STOP) ? "STATUS_STOP" : "STATUS_PAUSE"); + return; + } + + _exynosWbCloseDrm(wb, TRUE); + + _exynosWbCloseDrmDstBuffer(wb); + + wb->status = STATUS_PAUSE; + + _exynosWbCallNotifyFunc(wb, WB_NOTI_PAUSE, NULL); + + XDBG_TRACE(MWB, "pause: %s, wb(%p)\n", __func__, wb); + XDBG_DEBUG(MWB, "Q.\n"); +} + +void +exynosWbResume(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + wb->wait_show = -1; + wb->now_showing = -1; + + if (!exynosWbStart(wb)) { + XDBG_ERROR(MWB, "wb(%p) start fail.%s\n", wb, __func__); + exynosWbClose(wb); + wb = NULL; + } + XDBG_TRACE(MWB, "start: %s, wb(%p)\n", __func__, wb); + XDBG_DEBUG(MWB, "Q.\n"); +} + +Bool +exynosWbSetBuffer(EXYNOSWb * wb, EXYNOSVideoBuf ** vbufs, int bufnum) +{ + XDBG_DEBUG(MWB, "E. wb %p vbufs %p bufnum %d\n", wb, vbufs, bufnum); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret FALSE\n"); + return FALSE; + } + if (wb->status == STATUS_RUNNING) { + XDBG_DEBUG(MWB, "Q. wb->status == STATUS_RUNNING. ret FALSE\n"); + return FALSE; + } + + if (!vbufs) { + XDBG_DEBUG(MWB, "Q. vbufs == NULL. ret FALSE\n"); + return FALSE; + } + + if (wb->buf_num > bufnum) { + XDBG_DEBUG(MWB, "Q. wb->buf_num(%d) > bufnum(%d). ret FALSE\n", + wb->buf_num, bufnum); + return FALSE; + } + if (bufnum > WB_BUF_MAX) { + XDBG_DEBUG(MWB, "Q. bufnum(%d) > WB_BUF_MAX(%d). ret FALSE\n", bufnum, + WB_BUF_MAX); + return FALSE; + } + int i; + + for (i = 0; i < WB_BUF_MAX; i++) { + if (wb->dst_buf[i]) { + XDBG_ERROR(MWB, "already has %d buffers\n", wb->buf_num); + XDBG_DEBUG(MWB, "Q. wb->dst_buf[%d] %p exist. ret FALSE\n", i, + wb->dst_buf[i]); + return FALSE; + } + } + + for (i = 0; i < bufnum; i++) { + XDBG_GOTO_IF_FAIL(wb->id == vbufs[i]->id, fail_set_buffer); + XDBG_GOTO_IF_FAIL(wb->width == vbufs[i]->width, fail_set_buffer); + XDBG_GOTO_IF_FAIL(wb->height == vbufs[i]->height, fail_set_buffer); + XDBG_GOTO_IF_FAIL(wb->scanout == vbufs[i]->scanout, fail_set_buffer); + + wb->dst_buf[i] = exynosUtilVideoBufferRef(vbufs[i]); + XDBG_GOTO_IF_FAIL(wb->dst_buf[i] != NULL, fail_set_buffer); + + if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset) + exynosUtilClearVideoBuffer(wb->dst_buf[i]); + else + wb->dst_buf[i]->need_reset = TRUE; + } + + wb->buf_num = bufnum; + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; + + fail_set_buffer: + for (i = 0; i < WB_BUF_MAX; i++) { + if (wb->dst_buf[i]) { + exynosUtilVideoBufferUnref(wb->dst_buf[i]); + wb->dst_buf[i] = NULL; + } + } + XDBG_DEBUG(MWB, "Q. ret FALSE\n"); + return FALSE; +} + +Bool +exynosWbSetRotate(EXYNOSWb * wb, int rotate) +{ + XDBG_DEBUG(MWB, "E. wb %p rotate %d\n", wb, rotate); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret FALSE\n"); + return FALSE; + } + if ((rotate % 90) != 0) { + XDBG_DEBUG(MWB, "Q. rotate(%d) % 90 != 0. ret FALSE\n", rotate); + return FALSE; + } + + if (wb->rotate == rotate) { + XDBG_DEBUG(MWB, "Q. wb->rotate(%d) == rotate(%d). ret TRUE\n", + wb->rotate, rotate); + return TRUE; + } + + XDBG_TRACE(MWB, "rotate(%d) \n", rotate); + + wb->rotate = rotate; + + if (wb->status == STATUS_RUNNING) { + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(wb->pScrn)->pExynosMode; + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + exynosWbStop(wb, FALSE); + else + exynosWbStop(wb, TRUE); + + if (!exynosWbStart(wb)) { + XDBG_DEBUG(MWB, "Q. exynosWbStart == FALSE. ret FALSE\n"); + return FALSE; + } + } + XDBG_DEBUG(MWB, "Q. ret TRUE\n"); + return TRUE; +} + +int +exynosWbGetRotate(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret -1\n"); + return -1; + } + XDBG_DEBUG(MWB, "Q. ret %d(wb->rotate)\n", wb->rotate); + return wb->rotate; +} + +void +exynosWbSetTvout(EXYNOSWb * wb, Bool enable) +{ + XDBG_DEBUG(MWB, "E. wb %p enable %s\n", wb, enable ? "TRUE" : "FALSE"); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + + enable = (enable > 0) ? TRUE : FALSE; + + XDBG_TRACE(MWB, "tvout(%d) \n", enable); + + wb->tvout = enable; + + if (wb->status == STATUS_RUNNING) { + exynosWbStop(wb, FALSE); + + if (!exynosWbStart(wb)) { + XDBG_DEBUG(MWB, "Q. exynosWbStart == FALSE\n"); + return; + } + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +Bool +exynosWbGetTvout(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret FALSE\n"); + return FALSE; + } + XDBG_DEBUG(MWB, "Q. ret %s(wb->tvout)\n", wb->tvout ? "TRUE" : "FALSE"); + return wb->tvout; +} + +void +exynosWbSetSecure(EXYNOSWb * wb, Bool exynosure) +{ + XDBG_DEBUG(MWB, "E. wb %p exynosure %s\n", wb, + exynosure ? "TRUE" : "FALSE"); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + + exynosure = (exynosure > 0) ? TRUE : FALSE; + + if (wb->exynosure == exynosure) { + XDBG_DEBUG(MWB, "Q. wb->exynosure(%s) == exynosure(%s)\n", + wb->exynosure ? "TRUE" : "FALSE", + exynosure ? "TRUE" : "FALSE"); + return; + } + XDBG_TRACE(MWB, "exynosure(%d) \n", exynosure); + + wb->exynosure = exynosure; + + if (wb->status == STATUS_RUNNING) { + exynosWbStop(wb, TRUE); + + if (!exynosWbStart(wb)) { + XDBG_DEBUG(MWB, "Q. exynosWbStart == FALSE\n"); + return; + } + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +Bool +exynosWbGetSecure(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p\n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret FALSE\n"); + return FALSE; + } + XDBG_DEBUG(MWB, "Q. ret %s(wb->exynosure)\n", + wb->exynosure ? "TRUE" : "FALSE"); + return wb->exynosure; +} + +void +exynosWbGetSize(EXYNOSWb * wb, int *width, int *height) +{ + XDBG_DEBUG(MWB, "E. wb %p width %p height %p\n", wb, width, height); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL.\n"); + return; + } + + if (width) + *width = wb->width; + + if (height) + *height = wb->height; + XDBG_DEBUG(MWB, "Q. width %d height %d\n", wb->width, wb->height); +} + +Bool +exynosWbCanDequeueBuffer(EXYNOSWb * wb) +{ + XDBG_DEBUG(MWB, "E. wb %p \n", wb); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL. ret FALSE\n"); + return FALSE; + } + int i, remain = 0; + + for (i = 0; i < wb->buf_num; i++) + if (wb->queued[i]) + remain++; + + XDBG_TRACE(MWB, "buf_num(%d) remain(%d)\n", wb->buf_num, remain); + XDBG_DEBUG(MWB, "Q. ret %s\n", (remain > WB_BUF_MIN) ? "TRUE" : "FALSE"); + return (remain > WB_BUF_MIN) ? TRUE : FALSE; +} + +void +exynosWbQueueBuffer(EXYNOSWb * wb, EXYNOSVideoBuf * vbuf) +{ + XDBG_DEBUG(MWB, "E. wb %p vbuf %p\n", wb, vbuf); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + if (!vbuf) { + XDBG_DEBUG(MWB, "Q. vbuf == NULL\n"); + return; + } + if (vbuf->showing == TRUE) { + XDBG_DEBUG(MWB, "Q. vbuf->showing == TRUE\n"); + return; + } + int i; + + if (wb->prop_id == -1) { + XDBG_DEBUG(MWB, "Q. wb->prop_id == -1\n"); + return; + } + for (i = 0; i < wb->buf_num; i++) + if (wb->dst_buf[i] == vbuf) { + XDBG_TRACE(MWB, "%d queueing.\n", i); + _exynosWbQueue(wb, i); + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +void +exynosWbAddNotifyFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, WbNotifyFunc func, + void *user_data) +{ + XDBG_DEBUG(MWB, "E. wb %p noti %d func %p user_data %p\n", wb, noti, func, + user_data); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + if (!func) { + XDBG_DEBUG(MWB, "Q. func == NULL\n"); + return; + } + EXYNOSWbNotifyFuncInfo *info; + + nt_list_for_each_entry(info, wb->info_list, next) { + if (info->func == func) { + XDBG_DEBUG(MWB, "Q. info->func(%p) == func(%p)\n", info->func, + func); + return; + } + } + + XDBG_TRACE(MWB, "noti(%d) func(%p) user_data(%p) \n", noti, func, + user_data); + + info = calloc(1, sizeof(EXYNOSWbNotifyFuncInfo)); + if (!info) { + XDBG_DEBUG(MWB, "Q. info == NULL\n"); + return; + } + + info->noti = noti; + info->func = func; + info->user_data = user_data; + + if (wb->info_list) + nt_list_append(info, wb->info_list, EXYNOSWbNotifyFuncInfo, next); + else + wb->info_list = info; + XDBG_DEBUG(MWB, "Q.\n"); +} + +void +exynosWbRemoveNotifyFunc(EXYNOSWb * wb, WbNotifyFunc func) +{ + XDBG_DEBUG(MWB, "E. wb %p func %p\n", wb, func); + if (!wb) { + XDBG_DEBUG(MWB, "Q. wb == NULL\n"); + return; + } + if (!func) { + XDBG_DEBUG(MWB, "Q. func == NULL\n"); + return; + } + + EXYNOSWbNotifyFuncInfo *info; + + nt_list_for_each_entry(info, wb->info_list, next) { + if (info->func == func) { + XDBG_DEBUG(MWB, "func(%p) \n", func); + nt_list_del(info, wb->info_list, EXYNOSWbNotifyFuncInfo, next); + { + XDBG_DEBUG(MWB, "Q. info->func(%p) == func(%p)\n", info->func, + func); + } + free(info); + return; + } + } + XDBG_DEBUG(MWB, "Q.\n"); +} + +EXYNOSWb * +exynosWbGet(void) +{ + XDBG_DEBUG(MWB, "E.\n"); + XDBG_DEBUG(MWB, "Q. ret %p(keep_wb)\n", keep_wb); + return keep_wb; +} + +void +exynosWbDestroy(void) +{ + XDBG_DEBUG(MWB, "E.\n"); + if (!keep_wb) { + XDBG_DEBUG(MWB, "Q. keep_wb == NULL\n"); + return; + } + exynosWbClose(keep_wb); + XDBG_DEBUG(MWB, "Q.\n"); +} diff --git a/src/ipp/exynos_wb.h b/src/ipp/exynos_wb.h new file mode 100644 index 0000000..21435e1 --- /dev/null +++ b/src/ipp/exynos_wb.h @@ -0,0 +1,100 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 __SEC_WB_H__ +#define __SEC_WB_H__ + +#include <sys/types.h> +#include <xf86str.h> + +#include "exynos_video_types.h" + +typedef struct _EXYNOSWb EXYNOSWb; + +typedef enum { + WB_NOTI_INIT, + WB_NOTI_START, + WB_NOTI_IPP_EVENT, + WB_NOTI_IPP_EVENT_DONE, + WB_NOTI_PAUSE, + WB_NOTI_STOP, + WB_NOTI_CLOSED, +} EXYNOSWbNotify; + +typedef void (*WbNotifyFunc) (EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data); + +/* Don't close the wb from exynosWbGet */ +EXYNOSWb *exynosWbGet(void); + +/* If width, height is 0, they will be main display size. */ +EXYNOSWb *_exynosWbOpen(ScrnInfoPtr pScrn, + unsigned int id, int width, int height, + Bool scanout, int hz, Bool need_rotate_hook, + const char *func); +void _exynosWbClose(EXYNOSWb * wb, const char *func); +Bool _exynosWbStart(EXYNOSWb * wb, const char *func); +void _exynosWbStop(EXYNOSWb * wb, Bool close_buf, const char *func); + +#define exynosWbOpen(s,i,w,h,c,z,n) _exynosWbOpen(s,i,w,h,c,z,n,__FUNCTION__) +#define exynosWbClose(w) _exynosWbClose(w,__FUNCTION__) +#define exynosWbStart(w) _exynosWbStart(w,__FUNCTION__) +#define exynosWbStop(w,c) _exynosWbStop(w,c,__FUNCTION__) + +Bool exynosWbSetBuffer(EXYNOSWb * wb, EXYNOSVideoBuf ** vbufs, int bufnum); + +Bool exynosWbSetRotate(EXYNOSWb * wb, int rotate); +int exynosWbGetRotate(EXYNOSWb * wb); + +void exynosWbSetTvout(EXYNOSWb * wb, Bool enable); +Bool exynosWbGetTvout(EXYNOSWb * wb); + +void exynosWbSetSecure(EXYNOSWb * wb, Bool exynosure); +Bool exynosWbGetSecure(EXYNOSWb * wb); + +void exynosWbGetSize(EXYNOSWb * wb, int *width, int *height); + +Bool exynosWbCanDequeueBuffer(EXYNOSWb * wb); +void exynosWbQueueBuffer(EXYNOSWb * wb, EXYNOSVideoBuf * vbuf); + +void exynosWbAddNotifyFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + WbNotifyFunc func, void *user_data); +void exynosWbRemoveNotifyFunc(EXYNOSWb * wb, WbNotifyFunc func); + +Bool exynosWbIsOpened(void); +Bool exynosWbIsRunning(void); +void exynosWbDestroy(void); + +void exynosWbPause(EXYNOSWb * wb); +void exynosWbResume(EXYNOSWb * wb); + +unsigned int exynosWbGetPropID(void); +void exynosWbHandleIppEvent(int fd, unsigned int *buf_idx, void *data); + +#endif // __SEC_WB_H__ diff --git a/src/ipp/sec_converter.c b/src/ipp/sec_converter.c deleted file mode 100644 index 8b4f9bc..0000000 --- a/src/ipp/sec_converter.c +++ /dev/null @@ -1,1021 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 <sys/ioctl.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_video_types.h" -#include "sec_video_fourcc.h" -#include "sec_drm_ipp.h" -#include "sec_converter.h" - -#include <drm_fourcc.h> - -//#define INCREASE_NUM 1 -#define DEQUEUE_FORCE 1 - -#if INCREASE_NUM -#define CVT_BUF_MAX 6 -#endif - -typedef struct _SECCvtFuncData -{ - CvtFunc func; - void *data; - struct xorg_list link; -} SECCvtFuncData; - -typedef struct _SECCvtBuf -{ - SECCvtType type; - int index; - unsigned int handles[EXYNOS_DRM_PLANAR_MAX]; - CARD32 begin; - - SECVideoBuf *vbuf; - - struct xorg_list link; -} SECCvtBuf; - -struct _SECCvt -{ - CARD32 stamp; - - int prop_id; - - ScrnInfoPtr pScrn; - SECCvtOp op; - SECCvtProp props[CVT_TYPE_MAX]; - - struct xorg_list func_datas; - struct xorg_list src_bufs; - struct xorg_list dst_bufs; - -#if INCREASE_NUM - int src_index; - int dst_index; -#endif - - Bool started; - Bool first_event; - - struct xorg_list link; -}; - -static unsigned int formats[] = -{ - FOURCC_RGB565, - FOURCC_SR16, - FOURCC_RGB32, - FOURCC_SR32, - FOURCC_YV12, - FOURCC_I420, - FOURCC_S420, - FOURCC_ST12, - FOURCC_SN12, - FOURCC_NV12, - FOURCC_SN21, - FOURCC_NV21, - FOURCC_YUY2, - FOURCC_SUYV, - FOURCC_UYVY, - FOURCC_SYVY, - FOURCC_ITLV, -}; - -static struct xorg_list cvt_list; - -static void -_initList (void) -{ - static Bool inited = FALSE; - - if (inited) - return; - - xorg_list_init (&cvt_list); - - inited = TRUE; -} - -static SECCvt* -_findCvt (CARD32 stamp) -{ - SECCvt *cur = NULL, *next = NULL; - - _initList (); - - if (cvt_list.next != NULL) - { - xorg_list_for_each_entry_safe (cur, next, &cvt_list, link) - { - if (cur->stamp == stamp) - return cur; - } - } - - return NULL; -} - -static enum drm_exynos_ipp_cmd -_drmCommand (SECCvtOp op) -{ - switch (op) - { - case CVT_OP_OUTPUT: - return IPP_CMD_OUTPUT; - default: - return IPP_CMD_M2M; - } -} - -static enum drm_exynos_degree -_drmDegree (int degree) -{ - switch (degree % 360) - { - case 90: - return EXYNOS_DRM_DEGREE_90; - case 180: - return EXYNOS_DRM_DEGREE_180; - case 270: - return EXYNOS_DRM_DEGREE_270; - default: - return EXYNOS_DRM_DEGREE_0; - } -} - -static void -_FillConfig (SECCvtType type, SECCvtProp *prop, struct drm_exynos_ipp_config *config) -{ - config->ops_id = (type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; - - if (prop->hflip) - config->flip |= EXYNOS_DRM_FLIP_HORIZONTAL; - if (prop->vflip) - config->flip |= EXYNOS_DRM_FLIP_VERTICAL; - - config->degree = _drmDegree (prop->degree); - config->fmt = secUtilGetDrmFormat (prop->id); - config->sz.hsize = (__u32)prop->width; - config->sz.vsize = (__u32)prop->height; - config->pos.x = (__u32)prop->crop.x; - config->pos.y = (__u32)prop->crop.y; - config->pos.w = (__u32)prop->crop.width; - config->pos.h = (__u32)prop->crop.height; -} - -static void -_fillProperty (SECCvt *cvt, SECCvtType type, SECVideoBuf *vbuf, SECCvtProp *prop) -{ - prop->id = vbuf->id; - prop->width = vbuf->width; - prop->height = vbuf->height; - prop->crop = vbuf->crop; - - prop->degree = cvt->props[type].degree; - prop->vflip = cvt->props[type].vflip; - prop->hflip = cvt->props[type].hflip; - prop->secure = cvt->props[type].secure; - prop->csc_range = cvt->props[type].csc_range; -} - -static Bool -_SetVbufConverting (SECVideoBuf *vbuf, SECCvt *cvt, Bool converting) -{ - if (!converting) - { - ConvertInfo *cur = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (cur, next, &vbuf->convert_info, link) - { - if (cur->cvt == (void*)cvt) - { - xorg_list_del (&cur->link); - free (cur); - return TRUE; - } - } - - XDBG_ERROR (MCVT, "failed: %ld not found in %ld.\n", cvt->stamp, vbuf->stamp); - return FALSE; - } - else - { - ConvertInfo *info = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (info, next, &vbuf->convert_info, link) - { - if (info->cvt == (void*)cvt) - { - XDBG_ERROR (MCVT, "failed: %ld already converting %ld.\n", cvt->stamp, vbuf->stamp); - return FALSE; - } - } - - info = calloc (1, sizeof (ConvertInfo)); - XDBG_RETURN_VAL_IF_FAIL (info != NULL, FALSE); - - info->cvt = (void*)cvt; - - xorg_list_add (&info->link, &vbuf->convert_info); - - return TRUE; - } -} - -#if 0 -static void -_printBufIndices (SECCvt *cvt, SECCvtType type, char *str) -{ - struct xorg_list *bufs; - SECCvtBuf *cur, *next; - char nums[128]; - - bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; - - snprintf (nums, 128, "bufs:"); - - list_rev_for_each_entry_safe (cur, next, bufs, link) - { - snprintf (nums, 128, "%s %d", nums, cur->index); - } - - ErrorF ("%s: cvt(%p) %s(%s). \n", str, cvt, - (type == CVT_TYPE_SRC)?"SRC":"DST", nums); -} -#endif - -static int -_secCvtGetEmptyIndex (SECCvt *cvt, SECCvtType type) -{ -#if INCREASE_NUM - int ret; - - if(type == CVT_TYPE_SRC) - { - ret = cvt->src_index++; - if (cvt->src_index >= CVT_BUF_MAX) - cvt->src_index = 0; - } - else - { - ret = cvt->dst_index++; - if (cvt->dst_index >= CVT_BUF_MAX) - cvt->dst_index = 0; - } - - return ret; -#else - struct xorg_list *bufs; - SECCvtBuf *cur = NULL, *next = NULL; - int ret = 0; - - bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; - - while (1) - { - Bool found = FALSE; - - xorg_list_for_each_entry_safe (cur, next, bufs, link) - { - if (ret == cur->index) - { - found = TRUE; - break; - } - } - - if (!found) - break; - - ret++; - } - - return ret; -#endif -} - -static SECCvtBuf* -_secCvtFindBuf (SECCvt *cvt, SECCvtType type, int index) -{ - struct xorg_list *bufs; - SECCvtBuf *cur = NULL, *next = NULL; - - bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; - - xorg_list_for_each_entry_safe (cur, next, bufs, link) - { - if (index == cur->index) - return cur; - } - - XDBG_ERROR (MCVT, "cvt(%p), type(%d), index(%d) not found.\n", cvt, type, index); - - return NULL; -} - -static Bool -_secCvtQueue (SECCvt *cvt, SECCvtBuf *cbuf) -{ - struct drm_exynos_ipp_queue_buf buf = {0,}; - struct xorg_list *bufs; - int i; - int index = _secCvtGetEmptyIndex (cvt, cbuf->type); - - buf.prop_id = cvt->prop_id; - buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_ENQUEUE; - buf.buf_id = cbuf->index = index; - buf.user_data = (__u64)cvt->stamp; - - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - buf.handle[i] = (__u32)cbuf->handles[i]; - - if (!secDrmIppQueueBuf (cvt->pScrn, &buf)) - return FALSE; - - bufs = (cbuf->type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs; - xorg_list_add (&cbuf->link, bufs); - - _SetVbufConverting (cbuf->vbuf, cvt, TRUE); - -#if 0 - if (cbuf->type == CVT_TYPE_SRC) - _printBufIndices (cvt, CVT_TYPE_SRC, "in"); -#endif - - XDBG_DEBUG (MCVT, "cvt(%p), cbuf(%p), type(%d), index(%d) vbuf(%p) converting(%d)\n", - cvt, cbuf, cbuf->type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf)); - - return TRUE; -} - -static void -_secCvtDequeue (SECCvt *cvt, SECCvtBuf *cbuf) -{ - struct drm_exynos_ipp_queue_buf buf = {0,}; - int i; - - if (!_secCvtFindBuf (cvt, cbuf->type, cbuf->index)) - { - XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n", - cvt, cbuf->type, cbuf->index); - return; - } - - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf)); - - buf.prop_id = cvt->prop_id; - buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_DEQUEUE; - buf.buf_id = cbuf->index; - buf.user_data = (__u64)cvt->stamp; - - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - buf.handle[i] = (__u32)cbuf->handles[i]; - - if (!secDrmIppQueueBuf (cvt->pScrn, &buf)) - return; -} - -static void -_secCvtDequeued (SECCvt *cvt, SECCvtType type, int index) -{ - SECCvtBuf *cbuf = _secCvtFindBuf (cvt, type, index); - - if (!cbuf) - { - XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n", - cvt, type, index); - return; - } - - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf)); - - _SetVbufConverting (cbuf->vbuf, cvt, FALSE); - - XDBG_DEBUG (MCVT, "cvt(%p) type(%d) index(%d) vbuf(%p) converting(%d)\n", - cvt, type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf)); - - xorg_list_del (&cbuf->link); - -#if 0 - if (cbuf->type == CVT_TYPE_SRC) - _printBufIndices (cvt, CVT_TYPE_SRC, "out"); -#endif - - secUtilVideoBufferUnref (cbuf->vbuf); - free (cbuf); -} - -static void -_secCvtDequeueAll (SECCvt *cvt) -{ - SECCvtBuf *cur = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link) - { - _secCvtDequeue (cvt, cur); - } - - xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link) - { - _secCvtDequeue (cvt, cur); - } -} - -static void -_secCvtDequeuedAll (SECCvt *cvt) -{ - SECCvtBuf *cur = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link) - { - _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, cur->index); - } - - xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link) - { - _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, cur->index); - } -} - -static void -_secCvtStop (SECCvt *cvt) -{ - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - - XDBG_RETURN_IF_FAIL (cvt != NULL); - - if (!cvt->started) - return; - - _secCvtDequeueAll (cvt); - - ctrl.prop_id = cvt->prop_id; - ctrl.ctrl = IPP_CTRL_STOP; - - secDrmIppCmdCtrl (cvt->pScrn, &ctrl); - - _secCvtDequeuedAll (cvt); - - XDBG_TRACE (MCVT, "cvt(%p)\n", cvt); - - cvt->prop_id = -1; - - memset (cvt->props, 0, sizeof (SECCvtProp) * CVT_TYPE_MAX); - -#if INCREASE_NUM - cvt->src_index = 0; - cvt->dst_index = 0; -#endif - cvt->started = FALSE; - - return; -} - -Bool -secCvtSupportFormat (SECCvtOp op, int id) -{ - unsigned int *drmfmts; - int i, size, num = 0; - unsigned int drmfmt = secUtilGetDrmFormat (id); - - XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, FALSE); - XDBG_RETURN_VAL_IF_FAIL (id > 0, FALSE); - - size = sizeof (formats) / sizeof (unsigned int); - - for (i = 0; i < size; i++) - if (formats[i] == id) - break; - - if (i == size) - { - XDBG_ERROR (MCVT, "converter(op:%d) not support : '%c%c%c%c'.\n", - op, FOURCC_STR (id)); - return FALSE; - } - - drmfmts = secDrmIppGetFormatList (&num); - if (!drmfmts) - { - XDBG_ERROR (MCVT, "no drm format list.\n"); - return FALSE; - } - - for (i = 0; i < num; i++) - if (drmfmts[i] == drmfmt) - { - free (drmfmts); - return TRUE; - } - - XDBG_ERROR (MCVT, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR (id)); - - free (drmfmts); - - return FALSE; -} - -Bool -secCvtEnsureSize (SECCvtProp *src, SECCvtProp *dst) -{ - if (src) - { - int type = secUtilGetColorType (src->id); - - XDBG_RETURN_VAL_IF_FAIL (src->width >= 16, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src->height >= 8, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src->crop.width >= 16, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src->crop.height >= 8, FALSE); - - if (src->width % 16) - { - if (!IS_ZEROCOPY (src->id)) - { - int new_width = (src->width + 16) & (~0xF); - XDBG_DEBUG (MCVT, "src's width : %d to %d.\n", src->width, new_width); - src->width = new_width; - } - } - - if (type == TYPE_YUV420 && src->height % 2) - XDBG_WARNING (MCVT, "src's height(%d) is not multiple of 2!!!\n", src->height); - - if (type == TYPE_YUV420 || type == TYPE_YUV422) - { - src->crop.x = src->crop.x & (~0x1); - src->crop.width = src->crop.width & (~0x1); - } - - if (type == TYPE_YUV420) - src->crop.height = src->crop.height & (~0x1); - - if (src->crop.x + src->crop.width > src->width) - src->crop.width = src->width - src->crop.x; - if (src->crop.y + src->crop.height > src->height) - src->crop.height = src->height - src->crop.y; - } - - if (dst) - { - int type = secUtilGetColorType (dst->id); - - XDBG_RETURN_VAL_IF_FAIL (dst->width >= 16, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst->height >= 8, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst->crop.width >= 16, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst->crop.height >= 4, FALSE); - - if (dst->width % 16) - { - int new_width = (dst->width + 16) & (~0xF); - XDBG_DEBUG (MCVT, "dst's width : %d to %d.\n", dst->width, new_width); - dst->width = new_width; - } - - dst->height = dst->height & (~0x1); - - if (type == TYPE_YUV420 && dst->height % 2) - XDBG_WARNING (MCVT, "dst's height(%d) is not multiple of 2!!!\n", dst->height); - - if (type == TYPE_YUV420 || type == TYPE_YUV422) - { - dst->crop.x = dst->crop.x & (~0x1); - dst->crop.width = dst->crop.width & (~0x1); - } - - if (type == TYPE_YUV420) - dst->crop.height = dst->crop.height & (~0x1); - - if (dst->crop.x + dst->crop.width > dst->width) - dst->crop.width = dst->width - dst->crop.x; - if (dst->crop.y + dst->crop.height > dst->height) - dst->crop.height = dst->height - dst->crop.y; - } - - return TRUE; -} - -SECCvt* -secCvtCreate (ScrnInfoPtr pScrn, SECCvtOp op) -{ - SECCvt *cvt; - CARD32 stamp = GetTimeInMillis (); - - _initList (); - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, NULL); - - while (_findCvt (stamp)) - stamp++; - - cvt = calloc (1, sizeof (SECCvt)); - XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, NULL); - - cvt->stamp = stamp; - - cvt->pScrn = pScrn; - cvt->op = op; - cvt->prop_id = -1; - - xorg_list_init (&cvt->func_datas); - xorg_list_init (&cvt->src_bufs); - xorg_list_init (&cvt->dst_bufs); - - XDBG_TRACE (MCVT, "op(%d), cvt(%p) stamp(%ld)\n", op, cvt, stamp); - - xorg_list_add (&cvt->link, &cvt_list); - - return cvt; -} - -void -secCvtDestroy (SECCvt *cvt) -{ - SECCvtFuncData *cur = NULL, *next = NULL; - - if (!cvt) - return; - - _secCvtStop (cvt); - - xorg_list_del (&cvt->link); - - xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link) - { - xorg_list_del (&cur->link); - free (cur); - } - - XDBG_TRACE (MCVT, "cvt(%p)\n", cvt); - - free (cvt); -} - -SECCvtOp -secCvtGetOp (SECCvt *cvt) -{ - XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, CVT_OP_M2M); - - return cvt->op; -} - -Bool -secCvtSetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst) -{ - if (cvt->started) - return TRUE; - - struct drm_exynos_ipp_property property; - - XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE); - - if (!secCvtEnsureSize (src, dst)) - return FALSE; - - if (dst->crop.x + dst->crop.width > dst->width) - { - XDBG_ERROR (MCVT, "dst(%d+%d > %d). !\n", dst->crop.x, dst->crop.width, dst->width); - } - - if (!secCvtSupportFormat (cvt->op, src->id)) - { - XDBG_ERROR (MCVT, "cvt(%p) src '%c%c%c%c' not supported.\n", - cvt, FOURCC_STR (src->id)); - return FALSE; - } - - if (!secCvtSupportFormat (cvt->op, dst->id)) - { - XDBG_ERROR (MCVT, "cvt(%p) dst '%c%c%c%c' not supported.\n", - cvt, FOURCC_STR (dst->id)); - return FALSE; - } - - memcpy (&cvt->props[CVT_TYPE_SRC], src, sizeof (SECCvtProp)); - memcpy (&cvt->props[CVT_TYPE_DST], dst, sizeof (SECCvtProp)); - - CLEAR (property); - _FillConfig (CVT_TYPE_SRC, &cvt->props[CVT_TYPE_SRC], &property.config[0]); - _FillConfig (CVT_TYPE_DST, &cvt->props[CVT_TYPE_DST], &property.config[1]); - property.cmd = _drmCommand (cvt->op); -#ifdef _F_WEARABLE_FEATURE_ - property.type = IPP_EVENT_DRIVEN; -#endif - property.prop_id = cvt->prop_id; - property.protect = dst->secure; - property.range = dst->csc_range; - - XDBG_TRACE (MCVT, "cvt(%p) src('%c%c%c%c', '%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(src->id), FOURCC_STR(secUtilGetDrmFormat(src->id)), - src->width, src->height, - src->crop.x, src->crop.y, src->crop.width, src->crop.height, - src->degree, src->hflip, src->vflip, - src->secure, src->csc_range); - - XDBG_TRACE (MCVT, "cvt(%p) dst('%c%c%c%c', '%c%c%c%c',%dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(dst->id), FOURCC_STR(secUtilGetDrmFormat(dst->id)), - dst->width, dst->height, - dst->crop.x, dst->crop.y, dst->crop.width, dst->crop.height, - dst->degree, dst->hflip, dst->vflip, - dst->secure, dst->csc_range); - - cvt->prop_id = secDrmIppSetProperty (cvt->pScrn, &property); - XDBG_RETURN_VAL_IF_FAIL (cvt->prop_id >= 0, FALSE); - - return TRUE; -} - -void -secCvtGetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst) -{ - XDBG_RETURN_IF_FAIL (cvt != NULL); - - if (src) - *src = cvt->props[CVT_TYPE_SRC]; - - if (dst) - *dst = cvt->props[CVT_TYPE_DST]; -} - -Bool -secCvtConvert (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst) -{ - SECCvtBuf *src_cbuf = NULL, *dst_cbuf = NULL; - SECCvtProp src_prop, dst_prop; - - XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (cvt->op == CVT_OP_M2M, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (src), FALSE); - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (dst), FALSE); - - _fillProperty (cvt, CVT_TYPE_SRC, src, &src_prop); - _fillProperty (cvt, CVT_TYPE_DST, dst, &dst_prop); - - if (memcmp (&cvt->props[CVT_TYPE_SRC], &src_prop, sizeof (SECCvtProp)) || - memcmp (&cvt->props[CVT_TYPE_DST], &dst_prop, sizeof (SECCvtProp))) - { - XDBG_ERROR (MCVT, "cvt(%p) prop changed!\n", cvt); - XDBG_TRACE (MCVT, "cvt(%p) src_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(cvt->props[CVT_TYPE_SRC].id), - cvt->props[CVT_TYPE_SRC].width, cvt->props[CVT_TYPE_SRC].height, - cvt->props[CVT_TYPE_SRC].crop.x, cvt->props[CVT_TYPE_SRC].crop.y, - cvt->props[CVT_TYPE_SRC].crop.width, cvt->props[CVT_TYPE_SRC].crop.height, - cvt->props[CVT_TYPE_SRC].degree, - cvt->props[CVT_TYPE_SRC].hflip, cvt->props[CVT_TYPE_SRC].vflip, - cvt->props[CVT_TYPE_SRC].secure, cvt->props[CVT_TYPE_SRC].csc_range); - XDBG_TRACE (MCVT, "cvt(%p) src_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(src_prop.id), src_prop.width, src_prop.height, - src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height, - src_prop.degree, src_prop.hflip, src_prop.vflip, - src_prop.secure, src_prop.csc_range); - XDBG_TRACE (MCVT, "cvt(%p) dst_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(cvt->props[CVT_TYPE_DST].id), - cvt->props[CVT_TYPE_DST].width, cvt->props[CVT_TYPE_DST].height, - cvt->props[CVT_TYPE_DST].crop.x, cvt->props[CVT_TYPE_DST].crop.y, - cvt->props[CVT_TYPE_DST].crop.width, cvt->props[CVT_TYPE_DST].crop.height, - cvt->props[CVT_TYPE_DST].degree, - cvt->props[CVT_TYPE_DST].hflip, cvt->props[CVT_TYPE_DST].vflip, - cvt->props[CVT_TYPE_DST].secure, cvt->props[CVT_TYPE_DST].csc_range); - XDBG_TRACE (MCVT, "cvt(%p) dst_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n", - cvt, FOURCC_STR(dst_prop.id), dst_prop.width, dst_prop.height, - dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height, - dst_prop.degree, dst_prop.hflip, dst_prop.vflip, - dst_prop.secure, dst_prop.csc_range); - return FALSE; - } - - XDBG_GOTO_IF_FAIL (cvt->prop_id >= 0, fail_to_convert); - XDBG_GOTO_IF_FAIL (src->handles[0] > 0, fail_to_convert); - XDBG_GOTO_IF_FAIL (dst->handles[0] > 0, fail_to_convert); - - src_cbuf = calloc (1, sizeof (SECCvtBuf)); - XDBG_GOTO_IF_FAIL (src_cbuf != NULL, fail_to_convert); - dst_cbuf = calloc (1, sizeof (SECCvtBuf)); - XDBG_GOTO_IF_FAIL (dst_cbuf != NULL, fail_to_convert); - - src_cbuf->type = CVT_TYPE_SRC; - src_cbuf->vbuf = secUtilVideoBufferRef (src); - XDBG_GOTO_IF_FAIL (src_cbuf->vbuf != NULL, fail_to_convert); - memcpy (src_cbuf->handles, src->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX); - - if (!_secCvtQueue (cvt, src_cbuf)) - { - secUtilVideoBufferUnref (src_cbuf->vbuf); - goto fail_to_convert; - } - - XDBG_DEBUG (MCVT, "cvt(%p) srcbuf(%p) converting(%d)\n", - cvt, src, VBUF_IS_CONVERTING (src)); - - dst_cbuf->type = CVT_TYPE_DST; - dst_cbuf->vbuf = secUtilVideoBufferRef (dst); - memcpy (dst_cbuf->handles, dst->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX); - - if (!_secCvtQueue (cvt, dst_cbuf)) - { - secUtilVideoBufferUnref (dst_cbuf->vbuf); - goto fail_to_convert; - } - - XDBG_DEBUG (MCVT, "cvt(%p) dstbuf(%p) converting(%d)\n", - cvt, dst, VBUF_IS_CONVERTING (dst)); - - XDBG_DEBUG (MVBUF, "==> ipp (%ld,%d,%d : %ld,%d,%d) \n", - src->stamp, VBUF_IS_CONVERTING (src), src->showing, - dst->stamp, VBUF_IS_CONVERTING (dst), dst->showing); - - if (!cvt->started) - { - struct drm_exynos_ipp_cmd_ctrl ctrl = {0,}; - - ctrl.prop_id = cvt->prop_id; - ctrl.ctrl = IPP_CTRL_PLAY; - - if (!secDrmIppCmdCtrl (cvt->pScrn, &ctrl)) - goto fail_to_convert; - - XDBG_TRACE (MCVT, "cvt(%p) start.\n", cvt); - - cvt->started = TRUE; - } - - dst->dirty = TRUE; - - SECPtr pSec = SECPTR (cvt->pScrn); - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT) - src_cbuf->begin = GetTimeInMillis (); - - return TRUE; - -fail_to_convert: - - if (src_cbuf) - free (src_cbuf); - if (dst_cbuf) - free (dst_cbuf); - - _secCvtStop (cvt); - - return FALSE; -} - -Bool -secCvtAddCallback (SECCvt *cvt, CvtFunc func, void *data) -{ - SECCvtFuncData *func_data; - - XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (func != NULL, FALSE); - - func_data = calloc (1, sizeof (SECCvtFuncData)); - XDBG_RETURN_VAL_IF_FAIL (func_data != NULL, FALSE); - - xorg_list_add (&func_data->link, &cvt->func_datas); - - func_data->func = func; - func_data->data = data; - - return TRUE; -} - -void -secCvtRemoveCallback (SECCvt *cvt, CvtFunc func, void *data) -{ - SECCvtFuncData *cur = NULL, *next = NULL; - - XDBG_RETURN_IF_FAIL (cvt != NULL); - XDBG_RETURN_IF_FAIL (func != NULL); - - xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link) - { - if (cur->func == func && cur->data == data) - { - xorg_list_del (&cur->link); - free (cur); - } - } -} - -void -secCvtHandleIppEvent (int fd, unsigned int *buf_idx, void *data, Bool error) -{ - CARD32 stamp = (CARD32)data; - SECCvt *cvt; - SECCvtBuf *src_cbuf, *dst_cbuf; - SECVideoBuf *src_vbuf, *dst_vbuf; - SECCvtFuncData *curr = NULL, *next = NULL; - - XDBG_RETURN_IF_FAIL (buf_idx != NULL); - - cvt = _findCvt (stamp); - if (!cvt) - { - XDBG_DEBUG (MCVT, "invalid cvt's stamp (%ld).\n", stamp); - return; - } - - XDBG_DEBUG (MCVT, "cvt(%p) index(%d, %d)\n", - cvt, buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]); - -#if 0 - char temp[64]; - snprintf (temp, 64, "%d,%d", buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]); - _printBufIndices (cvt, CVT_TYPE_SRC, temp); -#endif - -#if DEQUEUE_FORCE - SECCvtBuf *cur = NULL, *prev = NULL; - - list_rev_for_each_entry_safe (cur, prev, &cvt->src_bufs, link) - { - if (buf_idx[EXYNOS_DRM_OPS_SRC] != cur->index) - { - unsigned int indice[EXYNOS_DRM_OPS_MAX] = {cur->index, cur->index}; - - XDBG_WARNING (MCVT, "cvt(%p) event(%d,%d) has been skipped!! \n", - cvt, cur->index, cur->index); - - /* To make sure all events are received, _secCvtDequeued should be called - * for every event. If a event has been skipped, to call _secCvtDequeued - * forcely, we call secCvtHandleIppEvent recursivly. - */ - secCvtHandleIppEvent (0, indice, (void*)cvt->stamp, TRUE); - } - else - break; - } -#endif - - src_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]); - XDBG_RETURN_IF_FAIL (src_cbuf != NULL); - - dst_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]); - XDBG_RETURN_IF_FAIL (dst_cbuf != NULL); - - SECPtr pSec = SECPTR (cvt->pScrn); - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - src_cbuf->begin; - ErrorF ("cvt(%p) ipp interval : %6ld ms\n", cvt, sub); - } - - src_vbuf = src_cbuf->vbuf; - dst_vbuf = dst_cbuf->vbuf; - - XDBG_DEBUG (MVBUF, "<== ipp (%ld,%d,%d : %ld,%d,%d) \n", - src_vbuf->stamp, VBUF_IS_CONVERTING (src_vbuf), src_vbuf->showing, - dst_vbuf->stamp, VBUF_IS_CONVERTING (dst_vbuf), dst_vbuf->showing); - - if (!cvt->first_event) - { - XDBG_DEBUG (MCVT, "cvt(%p) got a IPP event. \n", cvt); - cvt->first_event = TRUE; - } - - xorg_list_for_each_entry_safe (curr, next, &cvt->func_datas, link) - { - if (curr->func) - curr->func (cvt, src_vbuf, dst_vbuf, curr->data, error); - } - - _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]); - _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]); -} diff --git a/src/ipp/sec_drm_ipp.c b/src/ipp/sec_drm_ipp.c deleted file mode 100644 index cb50826..0000000 --- a/src/ipp/sec_drm_ipp.c +++ /dev/null @@ -1,165 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 <sys/ioctl.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_video_types.h" -#include "sec_video_fourcc.h" -#include "sec_drm_ipp.h" - -#include <drm_fourcc.h> - -static unsigned int drmfmt_list[] = -{ - /* packed */ - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_YUYV, - DRM_FORMAT_UYVY, - - /* 2 plane */ - DRM_FORMAT_NV12, - DRM_FORMAT_NV21, - DRM_FORMAT_NV12MT, - - /* 3 plane */ - DRM_FORMAT_YVU420, - DRM_FORMAT_YUV420, - DRM_FORMAT_YUV444, -}; - -/* A drmfmt list newly allocated. should be freed. */ -unsigned int* -secDrmIppGetFormatList (int *num) -{ - unsigned int *drmfmts; - - XDBG_RETURN_VAL_IF_FAIL (num != NULL, NULL); - - drmfmts = malloc (sizeof (drmfmt_list)); - XDBG_RETURN_VAL_IF_FAIL (drmfmts != NULL, NULL); - - memcpy (drmfmts, drmfmt_list, sizeof (drmfmt_list)); - *num = sizeof (drmfmt_list) / sizeof (unsigned int); - - return drmfmts; -} - -int -secDrmIppSetProperty (ScrnInfoPtr pScrn, struct drm_exynos_ipp_property *property) -{ - int ret = 0; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, -1); - XDBG_RETURN_VAL_IF_FAIL (property != NULL, -1); - - if (property->prop_id == (__u32)-1) - property->prop_id = 0; - - XDBG_DEBUG (MDRM, "src : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d) \n", - property->config[0].flip, property->config[0].degree, FOURCC_STR (property->config[0].fmt), - property->config[0].sz.hsize, property->config[0].sz.vsize, - property->config[0].pos.x, property->config[0].pos.y, property->config[0].pos.w, property->config[0].pos.h); - XDBG_DEBUG (MDRM, "dst : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d) \n", - property->config[1].flip, property->config[1].degree, FOURCC_STR (property->config[1].fmt), - property->config[1].sz.hsize, property->config[1].sz.vsize, - property->config[1].pos.x, property->config[1].pos.y, property->config[1].pos.w, property->config[1].pos.h); - -#ifdef _F_WEARABLE_FEATURE_ - XDBG_DEBUG (MDRM, "cmd(%d) type(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d) blending(%x)\n", - property->cmd, property->type, property->ipp_id, property->prop_id, property->refresh_rate, - property->protect, property->range, property->blending); -#else - XDBG_DEBUG (MDRM, "cmd(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d)\n", - property->cmd, property->ipp_id, property->prop_id, property->refresh_rate, - property->protect, property->range); -#endif - - ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_SET_PROPERTY, property); - if (ret) - { - XDBG_ERRNO (MDRM, "failed. \n"); - return -1; - } - - XDBG_TRACE (MDRM, "success. prop_id(%d) \n", property->prop_id); - - return property->prop_id; -} - -Bool -secDrmIppQueueBuf (ScrnInfoPtr pScrn, struct drm_exynos_ipp_queue_buf *buf) -{ - int ret = 0; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (buf != NULL, FALSE); - - XDBG_DEBUG (MDRM, "prop_id(%d) ops_id(%d) ctrl(%d) id(%d) handles(%x %x %x). \n", - buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id, - buf->handle[0], buf->handle[1], buf->handle[2]); - - ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_QUEUE_BUF, buf); - if (ret) - { - XDBG_ERRNO (MDRM, "failed. prop_id(%d) op(%d) buf(%d) id(%d)\n", - buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id); - return FALSE; - } - - XDBG_DEBUG (MDRM, "success. prop_id(%d) \n", buf->prop_id); - - return TRUE; -} - -Bool -secDrmIppCmdCtrl (ScrnInfoPtr pScrn, struct drm_exynos_ipp_cmd_ctrl *ctrl) -{ - int ret = 0; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (ctrl != NULL, FALSE); - - XDBG_TRACE (MDRM, "prop_id(%d) ctrl(%d). \n", ctrl->prop_id, ctrl->ctrl); - - ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_CMD_CTRL, ctrl); - if (ret) - { - XDBG_ERRNO (MDRM, "failed. prop_id(%d) ctrl(%d)\n", - ctrl->prop_id, ctrl->ctrl); - return FALSE; - } - - XDBG_DEBUG (MDRM, "success. prop_id(%d) \n", ctrl->prop_id); - - return TRUE; -} diff --git a/src/ipp/sec_wb.c b/src/ipp/sec_wb.c deleted file mode 100644 index b1f708e..0000000 --- a/src/ipp/sec_wb.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * xserver-xorg-video-exynos - * - * Copyright 2004 Keith Packard - * Copyright 2005 Eric Anholt - * Copyright 2006 Nokia Corporation - * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - * - * Contact: Boram Park <boram1288.park@samsung.com> - * - * Permission to use, copy, modify, distribute and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the names of the authors and/or copyright holders - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. The authors and - * copyright holders make no representations about the suitability of this - * software for any purpose. It is provided "as is" without any express - * or implied warranty. - * - * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/poll.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/time.h> - -#include <X11/Xatom.h> -#include <xace.h> -#include <xacestr.h> - -#include "exynos_drm.h" - -#include "sec.h" -#include "sec_util.h" -#include "sec_crtc.h" -#include "sec_video_fourcc.h" -#include "sec_video_tvout.h" -#include "sec_wb.h" -#include "sec_drm_ipp.h" -#include "sec_converter.h" - -#include <drm_fourcc.h> - -#define WB_BUF_MAX 5 -#define WB_BUF_DEFAULT 3 -#define WB_BUF_MIN 2 - -enum -{ - PENDING_NONE, - PENDING_ROTATE, - PENDING_STOP, - PENDING_CLOSE, -}; - -enum -{ - STATUS_STARTED, - STATUS_STOPPED, -}; - -typedef struct _SECWbNotifyFuncInfo -{ - SECWbNotify noti; - WbNotifyFunc func; - void *user_data; - - struct _SECWbNotifyFuncInfo *next; -} SECWbNotifyFuncInfo; - -struct _SECWb -{ - int prop_id; - - ScrnInfoPtr pScrn; - - unsigned int id; - - int rotate; - - int width; - int height; - xRectangle drm_dst; - xRectangle tv_dst; - - SECVideoBuf *dst_buf[WB_BUF_MAX]; - Bool queued[WB_BUF_MAX]; - int buf_num; - - int wait_show; - int now_showing; - - SECWbNotifyFuncInfo *info_list; - - /* for tvout */ - Bool tvout; - SECVideoTv *tv; - SECLayerPos lpos; - - Bool need_rotate_hook; - OsTimerPtr rotate_timer; - - /* count */ - unsigned int put_counts; - unsigned int last_counts; - OsTimerPtr timer; - - OsTimerPtr event_timer; - OsTimerPtr ipp_timer; - - Bool scanout; - int hz; - - int status; - Bool secure; - CARD32 prev_time; -}; - -static unsigned int formats[] = -{ - FOURCC_RGB32, - FOURCC_ST12, - FOURCC_SN12, -}; - -static SECWb *keep_wb; -static Atom atom_wb_rotate; - -static void _secWbQueue (SECWb *wb, int index); -static Bool _secWbRegisterRotateHook (SECWb *wb, Bool hook); -static void _secWbCloseDrmDstBuffer (SECWb *wb); -static void _secWbCloseDrm (SECWb *wb); - -static CARD32 -_secWbCountPrint (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECWb *wb = (SECWb*)arg; - - ErrorF ("IppEvent : %d fps. \n", wb->put_counts - wb->last_counts); - - wb->last_counts = wb->put_counts; - - wb->timer = TimerSet (wb->timer, 0, 1000, _secWbCountPrint, arg); - - return 0; -} - -static void -_secWbCountFps (SECWb *wb) -{ - wb->put_counts++; - - if (wb->timer) - return; - - wb->timer = TimerSet (NULL, 0, 1000, _secWbCountPrint, wb); -} - -static void -_secWbCountStop (SECWb *wb) -{ - if (wb->timer) - { - TimerFree (wb->timer); - wb->timer = NULL; - } - - wb->put_counts = 0; - wb->last_counts = 0; -} - -static unsigned int -_secWbSupportFormat (int id) -{ - unsigned int *drmfmts; - int i, size, num = 0; - unsigned int drmfmt = secUtilGetDrmFormat (id); - - size = sizeof (formats) / sizeof (unsigned int); - - for (i = 0; i < size; i++) - if (formats[i] == id) - break; - - if (i == size) - { - XDBG_ERROR (MWB, "wb not support : '%c%c%c%c'.\n", FOURCC_STR (id)); - return 0; - } - - drmfmts = secDrmIppGetFormatList (&num); - if (!drmfmts) - { - XDBG_ERROR (MWB, "no drm format list.\n"); - return 0; - } - - for (i = 0; i < num; i++) - if (drmfmts[i] == drmfmt) - { - free (drmfmts); - return drmfmt; - } - - XDBG_ERROR (MWB, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR (id)); - - free (drmfmts); - - return 0; -} - -static void -_secWbCallNotifyFunc (SECWb *wb, SECWbNotify noti, void *noti_data) -{ - SECWbNotifyFuncInfo *info; - - nt_list_for_each_entry (info, wb->info_list, next) - { - if (info->noti == noti && info->func) - info->func (wb, noti, noti_data, info->user_data); - } -} - -static void -_secWbLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data) -{ - SECWb *wb = (SECWb*)data; - SECVideoBuf *vbuf = (SECVideoBuf*)type_data; - - if (type != LAYER_VBLANK) - return; - - XDBG_RETURN_IF_FAIL (wb != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf)); - - if (wb->wait_show >= 0 && wb->dst_buf[wb->wait_show] != vbuf) - XDBG_WARNING (MWB, "wait_show(%d,%p) != showing_vbuf(%p). \n", - wb->wait_show, wb->dst_buf[wb->wait_show], vbuf); - - if (wb->now_showing >= 0) - _secWbQueue (wb, wb->now_showing); - - wb->now_showing = wb->wait_show; - wb->wait_show = -1; - - XDBG_DEBUG (MWB, "now_showing(%d,%p). \n", wb->now_showing, vbuf); -} - -static Bool -_secWbCalTvoutRect (SECWb *wb) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (wb->pScrn)->pSecMode; - int src_w, src_h, dst_w, dst_h; - - if (!wb->tvout) - { - if (wb->width == 0 || wb->height == 0) - { - wb->width = pSecMode->main_lcd_mode.hdisplay; - wb->height = pSecMode->main_lcd_mode.vdisplay; - } - - src_w = pSecMode->main_lcd_mode.hdisplay; - src_h = pSecMode->main_lcd_mode.vdisplay; - dst_w = wb->width; - dst_h = wb->height; - XDBG_RETURN_VAL_IF_FAIL (src_w > 0 && src_h > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_w > 0 && dst_h > 0, FALSE); - - if (wb->rotate % 180) - SWAP (src_w, src_h); - - secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE); - } - else - { - src_w = (int)pSecMode->main_lcd_mode.hdisplay; - src_h = (int)pSecMode->main_lcd_mode.vdisplay; - dst_w = (int)pSecMode->ext_connector_mode.hdisplay; - dst_h = (int)pSecMode->ext_connector_mode.vdisplay; - XDBG_RETURN_VAL_IF_FAIL (src_w > 0 && src_h > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_w > 0 && dst_h > 0, FALSE); - - if (wb->rotate % 180) - SWAP (src_w, src_h); - - if (wb->lpos == LAYER_UPPER) - { - /* Mixer can't scale. */ - wb->width = dst_w; - wb->height = dst_h; - wb->tv_dst.width = wb->width; - wb->tv_dst.height = wb->height; - - secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE); - } - else /* LAYER_LOWER1 */ - { - /* VP can scale */ - secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->tv_dst, TRUE); - - wb->width = src_w; - wb->height = src_h; - - wb->drm_dst.width = wb->width; - wb->drm_dst.height = wb->height; - } - } - - XDBG_TRACE (MWB, "tvout(%d) lpos(%d) src(%dx%d) drm_dst(%d,%d %dx%d) tv_dst(%d,%d %dx%d).\n", - wb->tvout, wb->lpos, wb->width, wb->height, - wb->drm_dst.x, wb->drm_dst.y, wb->drm_dst.width, wb->drm_dst.height, - wb->tv_dst.x, wb->tv_dst.y, wb->tv_dst.width, wb->tv_dst.height); - - return TRUE; -} - -static void -_secWbQueue (SECWb *wb, int index) -{ - struct drm_exynos_ipp_queue_buf buf; - int j; - - if (index < 0) - return; - - XDBG_RETURN_IF_FAIL (wb->dst_buf[index]->showing == FALSE); - - CLEAR (buf); - buf.ops_id = EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_ENQUEUE; - buf.prop_id = wb->prop_id; - buf.buf_id = index; - buf.user_data = (__u64)(unsigned int)wb; - - for (j = 0; j < PLANAR_CNT; j++) - buf.handle[j] = wb->dst_buf[index]->handles[j]; - - if (!secDrmIppQueueBuf (wb->pScrn, &buf)) - return; - - wb->queued[index] = TRUE; - wb->dst_buf[index]->dirty = TRUE; - - XDBG_DEBUG (MWB, "index(%d)\n", index); -} - -static int -_secWbDequeued (SECWb *wb, Bool skip_put, int index) -{ - int i, remain = 0; - - XDBG_RETURN_VAL_IF_FAIL (index < wb->buf_num, -1); - XDBG_WARNING_IF_FAIL (wb->dst_buf[index]->showing == FALSE); - - XDBG_DEBUG (MWB, "skip_put(%d) index(%d)\n", skip_put, index); - - if (!wb->queued[index]) - XDBG_WARNING (MWB, "buf(%d) already dequeued.\n", index); - - wb->queued[index] = FALSE; - - for (i = 0; i< wb->buf_num; i++) - { - if (wb->queued[i]) - remain++; - } - - /* the count of remain buffers should be more than 2. */ - if (remain >= WB_BUF_MIN) - _secWbCallNotifyFunc (wb, WB_NOTI_IPP_EVENT, (void*)wb->dst_buf[index]); - else - XDBG_DEBUG (MWB, "remain buffer count: %d\n", remain); - - if (wb->tvout) - { - if (!wb->tv) - { - if (wb->tv_dst.width > 0 && wb->tv_dst.height > 0) - wb->tv = secVideoTvConnect (wb->pScrn, wb->id, wb->lpos); - - if (wb->tv && !secUtilEnsureExternalCrtc (wb->pScrn)) - { - wb->tvout = FALSE; - secVideoTvDisconnect (wb->tv); - wb->tv = NULL; - } - - if (wb->tv) - { - SECLayer *layer = secVideoTvGetLayer (wb->tv); - secLayerEnableVBlank (layer, TRUE); - secLayerAddNotifyFunc (layer, _secWbLayerNotifyFunc, wb); - } - } - - if (!skip_put && wb->tv) - { - wb->wait_show = index; - secVideoTvPutImage (wb->tv, wb->dst_buf[index], &wb->tv_dst, 0); - } - } - - if (remain == 0) - XDBG_ERROR (MWB, "*** wb's buffer empty!! *** \n"); - - XDBG_DEBUG (MWB, "tv(%p) wait_show(%d) remain(%d)\n", wb->tv, - wb->wait_show, remain); - - return index; -} - -static CARD32 -_secWbIppRetireTimeout (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECWb *wb = (SECWb*)arg; - - if (wb->ipp_timer) - { - TimerFree (wb->ipp_timer); - wb->ipp_timer = NULL; - } - - XDBG_ERROR (MWB, "failed : +++ WB IPP Retire Timeout!!\n"); - - return 0; -} - -unsigned int -secWbGetPropID (void) -{ - if (!keep_wb) - return -1; - - return keep_wb->prop_id; -} - -void -secWbHandleIppEvent (int fd, unsigned int *buf_idx, void *data) -{ - SECWb *wb = (SECWb*)data; - SECPtr pSec; - int index = buf_idx[EXYNOS_DRM_OPS_DST]; - - if (!wb) - { - XDBG_ERROR (MWB, "data is %p \n", data); - return; - } - - if (keep_wb != wb) - { - XDBG_WARNING (MWB, "Useless ipp event! (%p) \n", wb); - return; - } - - if (wb->event_timer) - { - TimerFree (wb->event_timer); - wb->event_timer = NULL; - } - - if (wb->status == STATUS_STOPPED) - { - XDBG_ERROR (MWB, "stopped. ignore a event.\n", data); - return; - } - - if (wb->ipp_timer) - { - TimerFree (wb->ipp_timer); - wb->ipp_timer = NULL; - } - - wb->ipp_timer = TimerSet (wb->ipp_timer, 0, 2000, _secWbIppRetireTimeout, wb); - - XDBG_DEBUG (MWB, "=============== wb(%p) !\n", wb); - - pSec = SECPTR (wb->pScrn); - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_WB) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - wb->prev_time; - wb->prev_time = cur; - ErrorF ("wb evt interval : %6ld ms\n", sub); - } - - if (pSec->wb_fps) - _secWbCountFps (wb); - else - _secWbCountStop (wb); - - if (wb->rotate_timer) - { - _secWbDequeued (wb, TRUE, index); - _secWbQueue (wb, index); - } - else - { - if (wb->wait_show >= 0) - { - _secWbDequeued (wb, TRUE, index); - _secWbQueue (wb, index); - } - else - { - _secWbDequeued (wb, FALSE, index); - - if (wb->wait_show < 0 && !wb->dst_buf[index]->showing) - _secWbQueue (wb, index); - } - } - - _secWbCallNotifyFunc (wb, WB_NOTI_IPP_EVENT_DONE, NULL); - - XDBG_DEBUG (MWB, "=============== !\n"); -} - -static Bool -_secWbEnsureDrmDstBuffer (SECWb *wb) -{ - int i; - - for (i = 0; i < wb->buf_num; i++) - { - if (wb->dst_buf[i]) - { - secUtilClearVideoBuffer (wb->dst_buf[i]); - continue; - } - - wb->dst_buf[i] = secUtilAllocVideoBuffer (wb->pScrn, wb->id, - wb->width, wb->height, - keep_wb->scanout, TRUE, - secVideoIsSecureMode (wb->pScrn)); - XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_to_ensure); - } - - return TRUE; -fail_to_ensure: - _secWbCloseDrmDstBuffer (wb); - - return FALSE; -} - -static void -_secWbCloseDrmDstBuffer (SECWb *wb) -{ - int i; - - for (i = 0; i < wb->buf_num; i++) - { - if (wb->dst_buf[i]) - { - secUtilVideoBufferUnref (wb->dst_buf[i]); - wb->dst_buf[i] = NULL; - } - } -} - -static void -_secWbClearDrmDstBuffer (SECWb *wb) -{ - int i; - - for (i = 0; i < wb->buf_num; i++) - { - if (wb->dst_buf[i]) - { - if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset) - secUtilClearVideoBuffer (wb->dst_buf[i]); - else - wb->dst_buf[i]->need_reset = TRUE; - } - } -} - -static CARD32 -_secWbEventTimeout (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECWb *wb = (SECWb*) arg; - - if (!wb) - return 0; - - if (wb->event_timer) - { - TimerFree (wb->event_timer); - wb->event_timer = NULL; - } - - XDBG_ERROR (MWB, "*** ipp event not happen!! \n"); - - return 0; -} - -static Bool -_secWbOpenDrm (SECWb *wb) -{ - SECPtr pSec = SECPTR (wb->pScrn); - SECModePtr pSecMode = (SECModePtr)pSec->pSecMode; - int i; - unsigned int drmfmt = 0; - struct drm_exynos_ipp_property property; - enum drm_exynos_degree degree; - struct drm_exynos_ipp_cmd_ctrl ctrl; - - if (wb->need_rotate_hook) - _secWbRegisterRotateHook (wb, TRUE); - - if (!_secWbCalTvoutRect (wb)) - goto fail_to_open; - - drmfmt = _secWbSupportFormat (wb->id); - XDBG_GOTO_IF_FAIL (drmfmt > 0, fail_to_open); - - if ((wb->rotate) % 360 == 90) - degree = EXYNOS_DRM_DEGREE_90; - else if ((wb->rotate) % 360 == 180) - degree = EXYNOS_DRM_DEGREE_180; - else if ((wb->rotate) % 360 == 270) - degree = EXYNOS_DRM_DEGREE_270; - else - degree = EXYNOS_DRM_DEGREE_0; - - CLEAR (property); - property.config[0].ops_id = EXYNOS_DRM_OPS_SRC; - property.config[0].fmt = DRM_FORMAT_YUV444; - property.config[0].sz.hsize = (__u32)pSecMode->main_lcd_mode.hdisplay; - property.config[0].sz.vsize = (__u32)pSecMode->main_lcd_mode.vdisplay; - property.config[0].pos.x = 0; - property.config[0].pos.y = 0; - property.config[0].pos.w = (__u32)pSecMode->main_lcd_mode.hdisplay; - property.config[0].pos.h = (__u32)pSecMode->main_lcd_mode.vdisplay; - property.config[1].ops_id = EXYNOS_DRM_OPS_DST; - property.config[1].degree = degree; - property.config[1].fmt = drmfmt; - property.config[1].sz.hsize = wb->width; - property.config[1].sz.vsize = wb->height; - property.config[1].pos.x = (__u32)wb->drm_dst.x; - property.config[1].pos.y = (__u32)wb->drm_dst.y; - property.config[1].pos.w = (__u32)wb->drm_dst.width; - property.config[1].pos.h = (__u32)wb->drm_dst.height; - property.cmd = IPP_CMD_WB; -#ifdef _F_WEARABLE_FEATURE_ - property.type = IPP_EVENT_DRIVEN; -#endif - property.prop_id = wb->prop_id; - property.refresh_rate = wb->hz; - property.protect = wb->secure; - - wb->prop_id = secDrmIppSetProperty (wb->pScrn, &property); - XDBG_GOTO_IF_FAIL (wb->prop_id >= 0, fail_to_open); - - XDBG_TRACE (MWB, "prop_id(%d) drmfmt(%c%c%c%c) size(%dx%d) crop(%d,%d %dx%d) rotate(%d)\n", - wb->prop_id, FOURCC_STR(drmfmt), wb->width, wb->height, - wb->drm_dst.x, wb->drm_dst.y, wb->drm_dst.width, wb->drm_dst.height, - wb->rotate); - - if (!_secWbEnsureDrmDstBuffer (wb)) - goto fail_to_open; - - for (i = 0; i < wb->buf_num; i++) - { - struct drm_exynos_ipp_queue_buf buf; - int j; - - if (wb->dst_buf[i]->showing) - { - XDBG_DEBUG (MWB, "%d. name(%d) is showing\n", i, wb->dst_buf[i]->keys[0]); - continue; - } - - CLEAR (buf); - buf.ops_id = EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_ENQUEUE; - buf.prop_id = wb->prop_id; - buf.buf_id = i; - buf.user_data = (__u64)(unsigned int)wb; - - XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_to_open); - - for (j = 0; j < PLANAR_CNT; j++) - buf.handle[j] = wb->dst_buf[i]->handles[j]; - - if (!secDrmIppQueueBuf (wb->pScrn, &buf)) - goto fail_to_open; - - wb->queued[i] = TRUE; - } - - CLEAR (ctrl); - ctrl.prop_id = wb->prop_id; - ctrl.ctrl = IPP_CTRL_PLAY; - if (!secDrmIppCmdCtrl (wb->pScrn, &ctrl)) - goto fail_to_open; - - wb->event_timer = TimerSet (wb->event_timer, 0, 3000, _secWbEventTimeout, wb); - - return TRUE; - -fail_to_open: - - _secWbCloseDrm (wb); - - _secWbCloseDrmDstBuffer (wb); - - return FALSE; -} - -static void -_secWbCloseDrm (SECWb *wb) -{ - struct drm_exynos_ipp_cmd_ctrl ctrl; - int i; - - _secWbCountStop (wb); - - XDBG_TRACE (MWB, "now_showing(%d) \n", wb->now_showing); - - if (wb->tv) - { - secVideoTvDisconnect (wb->tv); - wb->tv = NULL; - wb->wait_show = -1; - wb->now_showing = -1; - } - - for (i = 0; i < wb->buf_num; i++) - { - struct drm_exynos_ipp_queue_buf buf; - int j; - - CLEAR (buf); - buf.ops_id = EXYNOS_DRM_OPS_DST; - buf.buf_type = IPP_BUF_DEQUEUE; - buf.prop_id = wb->prop_id; - buf.buf_id = i; - - if (wb->dst_buf[i]) - for (j = 0; j < EXYNOS_DRM_PLANAR_MAX && j < PLANAR_CNT; j++) - buf.handle[j] = wb->dst_buf[i]->handles[j]; - - secDrmIppQueueBuf (wb->pScrn, &buf); - - wb->queued[i] = FALSE; - } - - CLEAR (ctrl); - ctrl.prop_id = wb->prop_id; - ctrl.ctrl = IPP_CTRL_STOP; - secDrmIppCmdCtrl (wb->pScrn, &ctrl); - - wb->prop_id = -1; - - if (wb->rotate_timer) - { - TimerFree (wb->rotate_timer); - wb->rotate_timer = NULL; - } - - if (wb->event_timer) - { - TimerFree (wb->event_timer); - wb->event_timer = NULL; - } - - if (wb->ipp_timer) - { - TimerFree (wb->ipp_timer); - wb->ipp_timer = NULL; - } - - if (wb->need_rotate_hook) - _secWbRegisterRotateHook (wb, FALSE); -} - -static CARD32 -_secWbRotateTimeout (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECWb *wb = (SECWb*) arg; - PropertyPtr rotate_prop; - - if (!wb) - return 0; - - if (wb->rotate_timer) - { - TimerFree (wb->rotate_timer); - wb->rotate_timer = NULL; - } - - rotate_prop = secUtilGetWindowProperty (wb->pScrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE"); - if (rotate_prop) - { - int rotate = *(int*)rotate_prop->data; - - XDBG_TRACE (MWB, "timeout : rotate(%d)\n", rotate); - - if (wb->rotate != rotate) - if (!secWbSetRotate (wb, rotate)) - return 0; - } - - /* make sure streaming is on. */ - secWbStart (wb); - - return 0; -} - -static void -_secWbRotateHook (CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - SECWb *wb = (SECWb*) unused; - ScrnInfoPtr pScrn; - - XDBG_RETURN_IF_FAIL (wb != NULL); - - XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata; - PropertyPtr pProp = *rec->ppProp; - Atom name = pProp->propertyName; - - pScrn = wb->pScrn; - - if (rec->pWin != pScrn->pScreen->root) //Check Rootwindow - return; - - if (name == atom_wb_rotate && (rec->access_mode & DixWriteAccess)) - { - int rotate = *(int*)pProp->data; - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - - if (wb->rotate == rotate) - return; - - XDBG_TRACE (MWB, "Change root angle(%d)\n", rotate); - - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - secWbStop (wb, FALSE); - else - secWbStop (wb, TRUE); - - wb->rotate_timer = TimerSet (wb->rotate_timer, 0, 800, - _secWbRotateTimeout, - wb); - } - - return; -} - -static Bool -_secWbRegisterRotateHook (SECWb *wb, Bool hook) -{ - ScrnInfoPtr pScrn = wb->pScrn; - - XDBG_TRACE (MWB, "hook(%d) \n", hook); - - if (hook) - { - PropertyPtr rotate_prop; - - rotate_prop = secUtilGetWindowProperty (pScrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE"); - if (rotate_prop) - { - int rotate = *(int*)rotate_prop->data; - secWbSetRotate (wb, rotate); - } - - /* Hook for window rotate */ - if (atom_wb_rotate == None) - atom_wb_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", - strlen ("_E_ILLUME_ROTATE_ROOT_ANGLE"), FALSE); - - if (atom_wb_rotate != None) - { - if (!XaceRegisterCallback (XACE_PROPERTY_ACCESS, _secWbRotateHook, wb)) - XDBG_ERROR (MWB, "fail to XaceRegisterCallback.\n"); - } - else - XDBG_WARNING (MWB, "Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n"); - } - else - XaceDeleteCallback (XACE_PROPERTY_ACCESS, _secWbRotateHook, wb); - - return TRUE; -} - -Bool -secWbIsOpened (void) -{ - return (keep_wb) ? TRUE : FALSE; -} - -Bool -secWbIsRunning (void) -{ - if (!keep_wb) - return FALSE; - - return (keep_wb->status == STATUS_STARTED) ? TRUE : FALSE; -} - -SECWb* -_secWbOpen (ScrnInfoPtr pScrn, unsigned int id, int width, int height, - Bool scanout, int hz, Bool need_rotate_hook, const char *func) -{ - SECModePtr pSecMode = SECPTR (pScrn)->pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL); - - if (keep_wb) - { - XDBG_ERROR (MWB, "WB already opened. \n"); - return NULL; - } - - if (_secWbSupportFormat (id) == 0) - { - XDBG_ERROR (MWB, "'%c%c%c%c' not supported. \n", FOURCC_STR (id)); - return NULL; - } - - if (SECPTR (pScrn)->isLcdOff) - { - XDBG_ERROR (MWB, "Can't open wb during DPMS off. \n"); - return NULL; - } - - if (!keep_wb) - keep_wb = calloc (sizeof (SECWb), 1); - - XDBG_RETURN_VAL_IF_FAIL (keep_wb != NULL, FALSE); - - keep_wb->prop_id = -1; - keep_wb->pScrn = pScrn; - keep_wb->id = id; - - keep_wb->wait_show = -1; - keep_wb->now_showing = -1; - - keep_wb->width = width; - keep_wb->height = height; - keep_wb->status = STATUS_STOPPED; - - keep_wb->scanout = scanout; - keep_wb->hz = (hz > 0) ? hz : 60; - - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI && - keep_wb->hz > pSecMode->ext_connector_mode.vrefresh) - keep_wb->buf_num = WB_BUF_MAX; - else - keep_wb->buf_num = WB_BUF_DEFAULT; - - if (id == FOURCC_RGB32) - keep_wb->lpos = LAYER_UPPER; - else - keep_wb->lpos = LAYER_LOWER1; - - keep_wb->need_rotate_hook = need_rotate_hook; - - XDBG_SECURE (MWB, "wb(%p) id(%c%c%c%c) size(%dx%d) scanout(%d) hz(%d) rhoot(%d) buf_num(%d): %s\n", keep_wb, - FOURCC_STR(id), keep_wb->width, keep_wb->height, scanout, hz, - need_rotate_hook, keep_wb->buf_num, func); - - return keep_wb; -} - -void -_secWbClose (SECWb *wb, const char *func) -{ - SECWbNotifyFuncInfo *info, *tmp; - - XDBG_RETURN_IF_FAIL (wb != NULL); - XDBG_RETURN_IF_FAIL (keep_wb == wb); - - secWbStop (wb, TRUE); - - XDBG_SECURE (MWB, "wb(%p): %s \n", wb, func); - - _secWbCallNotifyFunc (wb, WB_NOTI_CLOSED, NULL); - - nt_list_for_each_entry_safe (info, tmp, wb->info_list, next) - { - nt_list_del (info, wb->info_list, SECWbNotifyFuncInfo, next); - free (info); - } - - free (wb); - keep_wb = NULL; -} - -Bool -_secWbStart (SECWb *wb, const char *func) -{ - SECPtr pSec; - - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - - pSec = SECPTR (wb->pScrn); - if (pSec->isLcdOff) - { - XDBG_ERROR (MWB, "Can't start wb(%p) during DPMS off. \n", wb); - return FALSE; - } - - if (wb->status == STATUS_STARTED) - return TRUE; - - if (!_secWbOpenDrm (wb)) - { - XDBG_ERROR (MWB, "open fail. \n"); - return FALSE; - } - - wb->status = STATUS_STARTED; - - _secWbCallNotifyFunc (wb, WB_NOTI_START, NULL); - - XDBG_TRACE (MWB, "start: %s \n", func); - - return TRUE; -} - -void -_secWbStop (SECWb *wb, Bool close_buf,const char *func) -{ - XDBG_RETURN_IF_FAIL (wb != NULL); - - if (wb->status == STATUS_STOPPED) - { - if (wb->rotate_timer) - { - TimerFree (wb->rotate_timer); - wb->rotate_timer = NULL; - } - return; - } - - _secWbCloseDrm (wb); - - if (close_buf) - _secWbCloseDrmDstBuffer (wb); - else - _secWbClearDrmDstBuffer (wb); - - wb->status = STATUS_STOPPED; - - _secWbCallNotifyFunc (wb, WB_NOTI_STOP, NULL); - - XDBG_TRACE (MWB, "stop: %s \n", func); -} - -Bool -secWbSetBuffer (SECWb *wb, SECVideoBuf **vbufs, int bufnum) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (wb->status != STATUS_STARTED, FALSE); - XDBG_RETURN_VAL_IF_FAIL (vbufs != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (wb->buf_num <= bufnum, FALSE); - XDBG_RETURN_VAL_IF_FAIL (bufnum <= WB_BUF_MAX, FALSE); - - for (i = 0; i < WB_BUF_MAX; i++) - { - if (wb->dst_buf[i]) - { - XDBG_ERROR (MWB, "already has %d buffers\n", wb->buf_num); - return FALSE; - } - } - - for (i = 0; i < bufnum; i++) - { - XDBG_GOTO_IF_FAIL (wb->id == vbufs[i]->id, fail_set_buffer); - XDBG_GOTO_IF_FAIL (wb->width == vbufs[i]->width, fail_set_buffer); - XDBG_GOTO_IF_FAIL (wb->height == vbufs[i]->height, fail_set_buffer); - XDBG_GOTO_IF_FAIL (wb->scanout == vbufs[i]->scanout, fail_set_buffer); - - wb->dst_buf[i] = secUtilVideoBufferRef (vbufs[i]); - XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_set_buffer); - - if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset) - secUtilClearVideoBuffer (wb->dst_buf[i]); - else - wb->dst_buf[i]->need_reset = TRUE; - } - - wb->buf_num = bufnum; - - return TRUE; - -fail_set_buffer: - for (i = 0; i < WB_BUF_MAX; i++) - { - if (wb->dst_buf[i]) - { - secUtilVideoBufferUnref (wb->dst_buf[i]); - wb->dst_buf[i] = NULL; - } - } - - return FALSE; -} - -Bool -secWbSetRotate (SECWb *wb, int rotate) -{ - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL ((rotate % 90) == 0, FALSE); - - if (wb->rotate == rotate) - return TRUE; - - XDBG_DEBUG (MWB, "rotate(%d) \n", rotate); - - wb->rotate = rotate; - - if (wb->status == STATUS_STARTED) - { - SECModePtr pSecMode = (SECModePtr) SECPTR (wb->pScrn)->pSecMode; - - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - secWbStop (wb, FALSE); - else - secWbStop (wb, TRUE); - - if (!secWbStart (wb)) - return FALSE; - } - - return TRUE; -} - -int -secWbGetRotate (SECWb *wb) -{ - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - - return wb->rotate; -} - -void -secWbSetTvout (SECWb *wb, Bool enable) -{ - XDBG_RETURN_IF_FAIL (wb != NULL); - - enable = (enable > 0) ? TRUE : FALSE; - - XDBG_TRACE (MWB, "tvout(%d) \n", enable); - - wb->tvout = enable; - - if (wb->status == STATUS_STARTED) - { - secWbStop (wb, FALSE); - - if (!secWbStart (wb)) - return; - } -} - -Bool -secWbGetTvout (SECWb *wb) -{ - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - - return wb->tvout; -} - -void -secWbSetSecure (SECWb *wb, Bool secure) -{ - XDBG_RETURN_IF_FAIL (wb != NULL); - - secure = (secure > 0) ? TRUE : FALSE; - - if (wb->secure == secure) - return; - - XDBG_TRACE (MWB, "secure(%d) \n", secure); - - wb->secure = secure; - - if (wb->status == STATUS_STARTED) - { - secWbStop (wb, TRUE); - - if (!secWbStart (wb)) - return; - } -} - -Bool -secWbGetSecure (SECWb *wb) -{ - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - - return wb->secure; -} - -void -secWbGetSize (SECWb *wb, int *width, int *height) -{ - XDBG_RETURN_IF_FAIL (wb != NULL); - - if (width) - *width = wb->width; - - if (height) - *height = wb->height; -} - -Bool -secWbCanDequeueBuffer (SECWb *wb) -{ - int i, remain = 0; - - XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE); - - for (i = 0; i< wb->buf_num; i++) - if (wb->queued[i]) - remain++; - - XDBG_DEBUG (MWB, "buf_num(%d) remain(%d)\n", wb->buf_num, remain); - - return (remain > WB_BUF_MIN) ? TRUE : FALSE; -} - -void -secWbQueueBuffer (SECWb *wb, SECVideoBuf *vbuf) -{ - int i; - - XDBG_RETURN_IF_FAIL (wb != NULL); - XDBG_RETURN_IF_FAIL (vbuf != NULL); - XDBG_RETURN_IF_FAIL (vbuf->showing == FALSE); - - if (wb->prop_id == -1) - return; - - for (i = 0; i < wb->buf_num; i++) - if (wb->dst_buf[i] == vbuf) - { - XDBG_DEBUG (MWB, "%d queueing.\n", i); - _secWbQueue (wb, i); - } -} - -void -secWbAddNotifyFunc (SECWb *wb, SECWbNotify noti, WbNotifyFunc func, void *user_data) -{ - SECWbNotifyFuncInfo *info; - - XDBG_RETURN_IF_FAIL (wb != NULL); - - if (!func) - return; - - nt_list_for_each_entry (info, wb->info_list, next) - { - if (info->func == func) - return; - } - - XDBG_DEBUG (MWB, "noti(%d) func(%p) user_data(%p) \n", noti, func, user_data); - - info = calloc (1, sizeof (SECWbNotifyFuncInfo)); - XDBG_RETURN_IF_FAIL (info != NULL); - - info->noti = noti; - info->func = func; - info->user_data = user_data; - - if (wb->info_list) - nt_list_append (info, wb->info_list, SECWbNotifyFuncInfo, next); - else - wb->info_list = info; -} - -void -secWbRemoveNotifyFunc (SECWb *wb, WbNotifyFunc func) -{ - SECWbNotifyFuncInfo *info; - - XDBG_RETURN_IF_FAIL (wb != NULL); - - if (!func) - return; - - nt_list_for_each_entry (info, wb->info_list, next) - { - if (info->func == func) - { - XDBG_DEBUG (MWB, "func(%p) \n", func); - nt_list_del(info, wb->info_list, SECWbNotifyFuncInfo, next); - free (info); - return; - } - } -} - -SECWb* -secWbGet (void) -{ - return keep_wb; -} - -void -secWbDestroy (void) -{ - if (!keep_wb) - return; - - secWbClose (keep_wb); -} diff --git a/src/ipp/sec_wb.h b/src/ipp/sec_wb.h deleted file mode 100644 index 38b9752..0000000 --- a/src/ipp/sec_wb.h +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 __SEC_WB_H__ -#define __SEC_WB_H__ - -#include <sys/types.h> -#include <xf86str.h> - -#include "sec_video_types.h" - -typedef struct _SECWb SECWb; - -typedef enum -{ - WB_NOTI_INIT, - WB_NOTI_START, - WB_NOTI_IPP_EVENT, - WB_NOTI_IPP_EVENT_DONE, - WB_NOTI_STOP, - WB_NOTI_CLOSED, -} SECWbNotify; - -typedef void (*WbNotifyFunc) (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data); - -/* Don't close the wb from secWbGet */ -SECWb* secWbGet (void); - -/* If width, height is 0, they will be main display size. */ -SECWb* _secWbOpen (ScrnInfoPtr pScrn, - unsigned int id, int width, int height, - Bool scanout, int hz, Bool need_rotate_hook, - const char *func); -void _secWbClose (SECWb *wb, const char *func); -Bool _secWbStart (SECWb *wb, const char *func); -void _secWbStop (SECWb *wb, Bool close_buf, const char *func); - -#define secWbOpen(s,i,w,h,c,z,n) _secWbOpen(s,i,w,h,c,z,n,__FUNCTION__) -#define secWbClose(w) _secWbClose(w,__FUNCTION__) -#define secWbStart(w) _secWbStart(w,__FUNCTION__) -#define secWbStop(w,c) _secWbStop(w,c,__FUNCTION__) - -Bool secWbSetBuffer (SECWb *wb, SECVideoBuf **vbufs, int bufnum); - -Bool secWbSetRotate (SECWb *wb, int rotate); -int secWbGetRotate (SECWb *wb); - -void secWbSetTvout (SECWb *wb, Bool enable); -Bool secWbGetTvout (SECWb *wb); - -void secWbSetSecure (SECWb *wb, Bool secure); -Bool secWbGetSecure (SECWb *wb); - -void secWbGetSize (SECWb *wb, int *width, int *height); - -Bool secWbCanDequeueBuffer (SECWb *wb); -void secWbQueueBuffer (SECWb *wb, SECVideoBuf *vbuf); - -void secWbAddNotifyFunc (SECWb *wb, SECWbNotify noti, WbNotifyFunc func, void *user_data); -void secWbRemoveNotifyFunc (SECWb *wb, WbNotifyFunc func); - -Bool secWbIsOpened (void); -Bool secWbIsRunning (void); -void secWbDestroy (void); - -unsigned int secWbGetPropID (void); -void secWbHandleIppEvent (int fd, unsigned int *buf_idx, void *data); - -#endif // __SEC_WB_H__ diff --git a/src/memory/exynos_memory_flush.c b/src/memory/exynos_memory_flush.c new file mode 100644 index 0000000..d2fc529 --- /dev/null +++ b/src/memory/exynos_memory_flush.c @@ -0,0 +1,141 @@ +/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+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 "exynos.h"
+#include <malloc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <malloc.h>
+
+#include "exynos.h"
+#include "xace.h"
+#include "xacestr.h"
+
+#include <X11/extensions/dpmsconst.h>
+#include "exynos_util.h"
+#include "exynos_dpms.h"
+#include "exynos_memory_flush.h"
+
extern CallbackListPtr DPMSCallback; +
static void
+_exynosMemoryDPMS(CallbackListPtr *list, pointer closure, pointer calldata)
+{ +
SecDPMSPtr pDPMSInfo = (SecDPMSPtr) calldata; +
ScrnInfoPtr pScrn; + +
+ //int mode = pDPMSInfo->mode;
+ //int flags = pDPMSInfo->flags;
+
if (!pDPMSInfo || !(pScrn = pDPMSInfo->pScrn)) +
{ +
XDBG_ERROR(MMEM, "[X11][%s] DPMS info or screen info is invalid !\n", + __FUNCTION__); +
return; +
} +
EXYNOSPtr pExynos = EXYNOSPTR(pScrn); +
switch (DPMSPowerLevel) +
{ +
case DPMSModeOn: +
case DPMSModeSuspend: +
break; +
case DPMSModeStandby: //LCD on
+ if (pExynos->isLcdOff == FALSE) + break; +
break; +
case DPMSModeOff: //LCD off
+ if (pExynos->isLcdOff == TRUE) + break; +
+ //stack and heap memory trim
+ exynosMemoryStackTrim(); +
malloc_trim(0); +
XDBG_DEBUG(MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__); +
break; +
default: +
return; +
} +
} + +
static void
+_exynosMemoryClientStateEvent(CallbackListPtr *list, pointer closure, + pointer calldata)
+{ +
static int chance = 0; + +
NewClientInfoRec * clientinfo = (NewClientInfoRec *) calldata; +
ClientPtr pClient = clientinfo->client; + +
if (ClientStateGone == pClient->clientState) +
{ +
int flush; + +
+ //memory flush will be done for every third client gone
+ chance++; +
flush = !(chance = chance % 3); +
if (flush) +
{ +
+ //stack and heap memory trim
+ exynosMemoryStackTrim(); +
malloc_trim(0); +
XDBG_DEBUG(MMEM, "[X11][%s] Memory flush done !\n", + __FUNCTION__); +
} +
} +
} + +
Bool
+exynosMemoryInstallHooks(void)
+{ +
int ret = TRUE; + +
ret &= + AddCallback(&ClientStateCallback, _exynosMemoryClientStateEvent, NULL); +
ret &= AddCallback(&DPMSCallback, _exynosMemoryDPMS, NULL); +
if (!ret) +
{ +
XDBG_ERROR(MMEM, + "exynosMemoryInstallHooks: Failed to register one or more callbacks\n"); +
return BadAlloc; +
} +
return Success; +
} + +
Bool
+exynosMemoryUninstallHooks(void)
+{ +
DeleteCallback(&ClientStateCallback, _exynosMemoryClientStateEvent, NULL); +
DeleteCallback(&DPMSCallback, _exynosMemoryDPMS, NULL); +
return Success; +
} + +
diff --git a/src/memory/sec_memory_flush.h b/src/memory/exynos_memory_flush.h index d9c1062..c303a4e 100644 --- a/src/memory/sec_memory_flush.h +++ b/src/memory/exynos_memory_flush.h @@ -26,60 +26,57 @@ 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 SEC_MEMORY_H
-#define SEC_MEMORY_H
-
+**************************************************************************/
+
+#ifndef EXYNOS_MEMORY_H
+#define EXYNOS_MEMORY_H
+
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <X11/Xdefs.h> /* for Bool */
-
+
#define GETSP() ({ unsigned int sp; asm volatile ("mov %0,sp " : "=r"(sp)); sp;})
#define BUF_SIZE 256
#define _PAGE_SIZE (1 << 12)
#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
#define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, _PAGE_SIZE)
-
-static inline void secMemoryStackTrim (void)
-{
- unsigned int sp;
- char buf[BUF_SIZE];
- FILE* file;
- unsigned int stacktop;
- int found = 0;
-
- sp = GETSP();
-
- snprintf (buf, BUF_SIZE, "/proc/%d/maps", getpid());
- file = fopen (buf,"r");
-
- if (!file)
- return;
-
- while (fgets (buf, BUF_SIZE, file) != NULL)
- {
- if (strstr (buf, "[stack]"))
- {
- found = 1;
- break;
- }
- }
-
- fclose (file);
-
- if (found)
- {
- sscanf (buf,"%x-",&stacktop);
- if (madvise ((void*)PAGE_ALIGN (stacktop), PAGE_ALIGN (sp)-stacktop, MADV_DONTNEED) < 0)
- perror ("stack madvise fail");
- }
-}
-
-Bool secMemoryInstallHooks (void);
-Bool secMemoryUninstallHooks (void);
-
-#endif/* SEC_MEMORY_H */
+
static inline void +exynosMemoryStackTrim(void)
+{ +
unsigned int sp; +
char buf[BUF_SIZE]; + +
FILE * file; +
unsigned int stacktop; +
int found = 0; + +
sp = GETSP(); +
snprintf(buf, BUF_SIZE, "/proc/%d/maps", getpid()); +
file = fopen(buf, "r"); +
if (!file) +
return; +
while (fgets(buf, BUF_SIZE, file) != NULL) +
{ +
if (strstr(buf, "[stack]")) +
{ +
found = 1; +
break; +
} +
} +
fclose(file); +
if (found) +
{ +
sscanf(buf, "%x-", &stacktop); +
if (madvise + ((void *) PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop, + MADV_DONTNEED) < 0) +
perror("stack madvise fail"); +
} +
}
Bool exynosMemoryInstallHooks(void); +
Bool exynosMemoryUninstallHooks(void); + +
+#endif /* EXYNOS_MEMORY_H */
diff --git a/src/memory/sec_memory_flush.c b/src/memory/sec_memory_flush.c deleted file mode 100644 index ad7d631..0000000 --- a/src/memory/sec_memory_flush.c +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************
-
-xserver-xorg-video-exynos
-
-Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
-
-Contact: SooChan Lim <sc1.lim@samsung.com>
-
-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 "sec.h"
-#include <malloc.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <malloc.h>
-
-#include "sec.h"
-#include "xace.h"
-#include "xacestr.h"
-
-#include <X11/extensions/dpmsconst.h>
-#include "sec_util.h"
-#include "sec_dpms.h"
-#include "sec_memory_flush.h"
-
-extern CallbackListPtr DPMSCallback;
-
-static void
-_secMemoryDPMS (CallbackListPtr *list, pointer closure, pointer calldata)
-{
- SecDPMSPtr pDPMSInfo = (SecDPMSPtr) calldata;
- ScrnInfoPtr pScrn;
- //int mode = pDPMSInfo->mode;
- //int flags = pDPMSInfo->flags;
-
- if (!pDPMSInfo || !(pScrn = pDPMSInfo->pScrn))
- {
- XDBG_ERROR (MMEM, "[X11][%s] DPMS info or screen info is invalid !\n", __FUNCTION__);
- return;
- }
-
- SECPtr pSec = SECPTR (pScrn);
-
- switch (DPMSPowerLevel)
- {
- case DPMSModeOn:
- case DPMSModeSuspend:
- break;
-
- case DPMSModeStandby://LCD on
- if (pSec->isLcdOff == FALSE) break;
- break;
-
- case DPMSModeOff://LCD off
- if (pSec->isLcdOff == TRUE) break;
-
- //stack and heap memory trim
- secMemoryStackTrim();
- malloc_trim (0);
-
- XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);
- break;
-
- default:
- return;
- }
-}
-
-static void
-_secMemoryClientStateEvent (CallbackListPtr *list, pointer closure, pointer calldata)
-{
- static int chance = 0;
- NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata;
- ClientPtr pClient = clientinfo->client;
-
- if (ClientStateGone == pClient->clientState)
- {
- int flush;
-
- //memory flush will be done for every third client gone
- chance++;
- flush = !(chance = chance % 3);
-
- if ( flush )
- {
- //stack and heap memory trim
- secMemoryStackTrim();
- malloc_trim (0);
-
- XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);
- }
- }
-}
-
-Bool
-secMemoryInstallHooks (void)
-{
- int ret = TRUE;
- ret &= AddCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);
- ret &= AddCallback (&DPMSCallback, _secMemoryDPMS, NULL);
-
- if (!ret)
- {
- XDBG_ERROR (MMEM, "secMemoryInstallHooks: Failed to register one or more callbacks\n");
- return BadAlloc;
- }
-
- return Success;
-}
-
-
-Bool
-secMemoryUninstallHooks (void)
-{
- DeleteCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);
- DeleteCallback (&DPMSCallback, _secMemoryDPMS, NULL);
-
- return Success;
-}
diff --git a/src/neon/copy_area.c b/src/neon/copy_area.c index 9bd2c71..eaf3af2 100644 --- a/src/neon/copy_area.c +++ b/src/neon/copy_area.c @@ -1,535 +1,447 @@ -/**************************************************************************
-
-xserver-xorg-video-exynos
-
-Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
-
-Contact: SooChan Lim <sc1.lim@samsung.com>
-
-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 "neonmem.h"
-
-//#define _USE_LIBC
-//#define _X86_SSE2 // may not work on linux platform
-#define _ARM_NEON
-
-#ifdef _USE_LIBC
-#include <string.h>
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-// General C implementation of copy functions
-//////////////////////////////////////////////////////////////////////////
-static inline void memcpy32 (unsigned long *dst, unsigned long *src, int size)
-{
- while ( size > 0 )
- {
- *dst++ = *src++;
- size--;
- }
-}
-
-static inline void memcpy_forward_32 (unsigned long *dst, unsigned long *src, int size)
-{
- while ( size > 0 )
- {
- *dst++ = *src++;
- size--;
- }
-}
-
-static inline void memcpy_backward_32 (unsigned long *dst, unsigned long *src, int size)
-{
- dst = dst + size;
- src = src + size;
-
- while ( size > 0 )
- {
- *(--dst) = *(--src);
- size--;
- }
-}
-
-static inline void memcpy_forward_16 (unsigned short *dst, unsigned short *src, int size)
-{
- while ( size > 0 )
- {
- *dst++ = *src++;
- size--;
- }
-}
-
-static inline void memcpy_backward_16 (unsigned short *dst, unsigned short *src, int size)
-{
- dst = dst + size;
- src = src + size;
-
- while ( size > 0 )
- {
- *(--dst) = *(--src);
- size--;
- }
-}
-
-static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)
-{
- while ( size > 0 && ((unsigned long) dst & 3))
- {
- *(unsigned short*)dst = *(unsigned short*)src;
- dst += 2;
- src += 2;
- size -= 2;
- }
-
- while ( size >= 4 )
- {
- *(unsigned long*)dst = *(unsigned long*)src;
- dst += 4;
- src += 4;
- size -= 4;
- }
-
- while ( size > 0 )
- {
- *dst++ = *src++;
- size--;
- }
-}
-
-static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)
-{
- dst = dst + size;
- src = src + size;
-
- while ( size > 0 && ((unsigned long) dst & 3))
- {
- *(--dst) = *(--src);
- size--;
- }
-
- while ( size >= 4 )
- {
- dst -= 4;
- src -= 4;
- size -= 4;
- *(unsigned long*)dst = *(unsigned long*)src;
- }
-
- while ( size > 0 )
- {
- *(--dst) = *(--src);
- size--;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// ARM assembly implementation of copy functions
-//////////////////////////////////////////////////////////////////////////
-#ifdef _ARM_ASM
-static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)
-{
-
-}
-
-static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)
-{
-
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-// ARM NEON implementation of copy functions
-//////////////////////////////////////////////////////////////////////////
-#ifdef _ARM_NEON
-extern void memcpy_forward_32_neon (unsigned long *dst, unsigned long *src, int size);
-extern void memcpy_backward_32_neon (unsigned long *dst, unsigned long *src, int size);
-extern void memcpy_forward_16_neon (unsigned short *dst, unsigned short *src, int size);
-extern void memcpy_backward_16_neon (unsigned short *dst, unsigned short *src, int size);
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-// X86 SSE2 copy functions
-//////////////////////////////////////////////////////////////////////////
-#ifdef _X86_SSE2
-#include <emmintrin.h>
-
-static inline void memcpy_forward_sse2 (unsigned char *dst, unsigned char *src, int size)
-{
- while ( size > 0 && ((unsigned long) dst & 1))
- {
- *dst++ = *src++;
- size--;
- }
-
- while ( size > 0 && ((unsigned long) dst & 3))
- {
- *(unsigned short*)dst = *(unsigned short*)src;
- dst += 2;
- src += 2;
- size -= 2;
- }
-
- while ( size > 0 && ((unsigned long) dst & 63))
- {
- *(unsigned long*)dst = *(unsigned long*)src;
- dst += 4;
- src += 4;
- size -= 4;
- }
-
- if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )
- {
- while ( size >= 64 )
- {
- __m128 xmm0, xmm1, xmm2, xmm3;
-
- //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);
-
- xmm0 = _mm_load_ps ((float*)(src));
- xmm1 = _mm_load_ps ((float*)(src + 16));
- xmm2 = _mm_load_ps ((float*)(src + 32));
- xmm3 = _mm_load_ps ((float*)(src + 48));
-
- _mm_stream_ps ((float*)(dst), xmm0);
- _mm_stream_ps ((float*)(dst + 16), xmm1);
- _mm_stream_ps ((float*)(dst + 32), xmm2);
- _mm_stream_ps ((float*)(dst + 48), xmm3);
-
- src += 64;
- dst += 64;
- size -= 64;
- }
-
- while ( size >= 16 )
- {
- _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));
- dst += 16;
- src += 16;
- size -= 16;
- }
- }
- else
- {
- while ( size >= 64 )
- {
- __m128 xmm0, xmm1, xmm2, xmm3;
-
- //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);
-
- xmm0 = _mm_loadu_ps ((float*)(src));
- xmm1 = _mm_loadu_ps ((float*)(src + 16));
- xmm2 = _mm_loadu_ps ((float*)(src + 32));
- xmm3 = _mm_loadu_ps ((float*)(src + 48));
-
- _mm_stream_ps ((float*)(dst), xmm0);
- _mm_stream_ps ((float*)(dst + 16), xmm1);
- _mm_stream_ps ((float*)(dst + 32), xmm2);
- _mm_stream_ps ((float*)(dst + 48), xmm3);
-
- src += 64;
- dst += 64;
- size -= 64;
- }
-
- while ( size >= 16 )
- {
- _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));
- dst += 16;
- src += 16;
- size -= 16;
- }
- }
-
- while ( size >= 4 )
- {
- *(unsigned long*)dst = *(unsigned long*)src;
- dst += 4;
- src += 4;
- size -= 4;
- }
-
- while ( size > 0 )
- {
- *dst++ = *src++;
- size--;
- }
-}
-
-static inline void memcpy_backward_sse2 (unsigned char *dst, unsigned char *src, int size)
-{
- dst = dst + size;
- src = src + size;
-
- while ( size > 0 && ((unsigned long) dst & 1))
- {
- dst--;
- src--;
- size--;
- *dst = *src;
- }
-
- while ( size > 0 && ((unsigned long) dst & 3))
- {
- dst -= 2;
- src -= 2;
- size -= 2;
- *(unsigned short*)dst = *(unsigned short*)src;
- }
-
- while ( size > 0 && ((unsigned long) dst & 63))
- {
- dst -= 4;
- src -= 4;
- size -= 4;
- *(unsigned long*)dst = *(unsigned long*)src;
- }
-
- if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )
- {
- while ( size >= 64 )
- {
- __m128 xmm0, xmm1, xmm2, xmm3;
-
- src -= 64;
- dst -= 64;
- size -= 64;
-
- //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);
-
- xmm0 = _mm_load_ps ((float*)(src));
- xmm1 = _mm_load_ps ((float*)(src + 16));
- xmm2 = _mm_load_ps ((float*)(src + 32));
- xmm3 = _mm_load_ps ((float*)(src + 48));
-
- _mm_stream_ps ((float*)(dst), xmm0);
- _mm_stream_ps ((float*)(dst + 16), xmm1);
- _mm_stream_ps ((float*)(dst + 32), xmm2);
- _mm_stream_ps ((float*)(dst + 48), xmm3);
- }
-
- while ( size >= 16 )
- {
- dst -= 16;
- src -= 16;
- size -= 16;
- _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));
- }
- }
- else
- {
- while ( size >= 64 )
- {
- __m128 xmm0, xmm1, xmm2, xmm3;
-
- src -= 64;
- dst -= 64;
- size -= 64;
-
- //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);
-
- xmm0 = _mm_loadu_ps ((float*)(src));
- xmm1 = _mm_loadu_ps ((float*)(src + 16));
- xmm2 = _mm_loadu_ps ((float*)(src + 32));
- xmm3 = _mm_loadu_ps ((float*)(src + 48));
-
- _mm_stream_ps ((float*)(dst), xmm0);
- _mm_stream_ps ((float*)(dst + 16), xmm1);
- _mm_stream_ps ((float*)(dst + 32), xmm2);
- _mm_stream_ps ((float*)(dst + 48), xmm3);
- }
-
- while ( size >= 16 )
- {
- dst -= 16;
- src -= 16;
- size -= 16;
- _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));
- }
- }
-
- while ( size >= 4 )
- {
- dst -= 4;
- src -= 4;
- size -= 4;
- *(unsigned long*)dst = *(unsigned long*)src;
- }
-
- while ( size > 0 )
- {
- dst--;
- src--;
- size--;
- *dst = *src;
- }
-}
-#endif
-
-static inline void move_memory_32 (unsigned long *dst, unsigned long *src, int size)
-{
-#ifdef _USE_LIBC
- memmove (dst, src, size*4);
-#elif defined(_ARM_NEON)
- if ( dst > src && dst < src + size )
- memcpy_backward_32_neon (dst, src, size);
- else
- memcpy_forward_32_neon (dst, src, size);
-#else
- if ( dst > src && dst < src + size )
- memcpy_backward_32 (dst, src, size);
- else
- memcpy_forward_32 (dst, src, size);
-#endif
-}
-
-static inline void move_memory_16 (unsigned short *dst, unsigned short *src, int size)
-{
-#ifdef _USE_LIBC
- memmove (dst, src, size*2);
-#elif defined(_ARM_NEON)
- if ( dst > src && dst < src + size )
- memcpy_backward_16_neon (dst, src, size);
- else
- memcpy_forward_16_neon (dst, src, size);
-#else
- if ( dst > src && dst < src + size )
- memcpy_backward_16 (dst, src, size);
- else
- memcpy_forward_16 (dst, src, size);
-#endif
-}
-
-/**
- * @brief Pixel block move function within one image buffer
- *
- * @param bits buffer address of top-left corner
- * @param bpp bits per pixel, must be one of 16 and 32
- * @param stride number of bytes to go next row (can be negative)
- * @param img_width entire image width
- * @param img_height entire image height
- * @param sx top-left x position of source area
- * @param sy top-left y position of source area
- * @param dx top-left x position of destination area
- * @param dy top-left y position of destination area
- * @param w width of area to copy
- * @param h height of area to copy
- *
- * @remark This function supports overlapping in source and destination area.
- * Any source or destination area which is outside given image will be cropped.
- * Support negative stride.
- * bits must be word aligned if bpp == 32 and half-word aligned if bpp == 16.
- */
-int move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,
- int sx, int sy, int dx, int dy, int w, int h)
-{
- int bytes_per_pixel;
- unsigned char *src_row;
- unsigned char *dst_row;
-
-
- //////////////////////////////////////////////////////////////////////////
- // check validity of arguments
- //////////////////////////////////////////////////////////////////////////
- if ( !bits || img_width < 0 || img_height < 0 || w < 0 || h < 0 )
- return 0;
-
- if ( bpp == 32 )
- bytes_per_pixel = 4;
- else if ( bpp == 16 )
- bytes_per_pixel = 2;
- else // unsupported bpp
- return 0;
-
- if ( bytes_per_pixel*img_width < stride ) // invalid image
- return 0;
-
- // Wow thanks, we have nothing to do
- if ( sx == dx && sy == dy )
- return 1;
-
-
- //////////////////////////////////////////////////////////////////////////
- // Bounds check and cropping
- //////////////////////////////////////////////////////////////////////////
- while ( sx < 0 || dx < 0 )
- {
- sx++;
- dx++;
- w--;
- }
-
- while ( sy < 0 || dy < 0 )
- {
- sy++;
- dy++;
- h--;
- }
-
- while ( sx + w > img_width || dx + w > img_width )
- w--;
-
- while ( sy + h > img_height || dy + h > img_height )
- h--;
-
-
- //////////////////////////////////////////////////////////////////////////
- // Check overlap and do copy
- //////////////////////////////////////////////////////////////////////////
-
- // No remaining area to copy
- if ( w <= 0 || h <= 0 )
- return 1;
-
- src_row = (unsigned char*)bits + sy*stride + sx*bytes_per_pixel;
- dst_row = (unsigned char*)bits + dy*stride + dx*bytes_per_pixel;
-
- // Check if we need to reverse y order
- if ( dy > sy && dy < sy + h )
- {
- src_row += (h - 1) *stride;
- dst_row += (h - 1) *stride;
- stride = -stride;
- }
-
- if ( bpp == 32 )
- {
- while ( h-- )
- {
- move_memory_32 ((unsigned long*)dst_row, (unsigned long*)src_row, w);
- dst_row += stride;
- src_row += stride;
- }
- }
- else if ( bpp == 16 )
- {
- while ( h-- )
- {
- move_memory_16 ((unsigned short*)dst_row, (unsigned short*)src_row, w);
- dst_row += stride;
- src_row += stride;
- }
- }
-
- return 1;
-}
+/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim <sc1.lim@samsung.com> + +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 +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 "neonmem.h" + +/*#define _USE_LIBC */ +/*#define _X86_SSE2 // may not work on linux platform */ +#define _ARM_NEON + +#ifdef _USE_LIBC +#include <string.h> +#endif /* */ + +/*//////////////////////////////////////////////////////////////////////// +// General C implementation of copy functions +////////////////////////////////////////////////////////////////////////*/ +static inline void +memcpy32(unsigned long *dst, unsigned long *src, int size) +{ + while (size > 0) { + *dst++ = *src++; + size--; + } +} + +static inline void +memcpy_forward_32(unsigned long *dst, unsigned long *src, int size) +{ + while (size > 0) { + *dst++ = *src++; + size--; + } +} + +static inline void +memcpy_backward_32(unsigned long *dst, unsigned long *src, int size) +{ + dst = dst + size; + src = src + size; + while (size > 0) { + *(--dst) = *(--src); + size--; + } +} + +static inline void +memcpy_forward_16(unsigned short *dst, unsigned short *src, int size) +{ + while (size > 0) { + *dst++ = *src++; + size--; + } +} + +static inline void +memcpy_backward_16(unsigned short *dst, unsigned short *src, int size) +{ + dst = dst + size; + src = src + size; + while (size > 0) { + *(--dst) = *(--src); + size--; + } +} + +static inline void +memcpy_forward(unsigned char *dst, unsigned char *src, int size) +{ + while (size > 0 && ((unsigned long) dst & 3)) { + *(unsigned short *) dst = *(unsigned short *) src; + dst += 2; + src += 2; + size -= 2; + } while (size >= 4) { + *(unsigned long *) dst = *(unsigned long *) src; + dst += 4; + src += 4; + size -= 4; + } while (size > 0) { + *dst++ = *src++; + size--; + } +} + +static inline void +memcpy_backward(unsigned char *dst, unsigned char *src, int size) +{ + dst = dst + size; + src = src + size; + while (size > 0 && ((unsigned long) dst & 3)) { + *(--dst) = *(--src); + size--; + } while (size >= 4) { + dst -= 4; + src -= 4; + size -= 4; + *(unsigned long *) dst = *(unsigned long *) src; + } while (size > 0) { + *(--dst) = *(--src); + size--; + } +} + +////////////////////////////////////////////////////////////////////////// +// ARM assembly implementation of copy functions +////////////////////////////////////////////////////////////////////////// +#ifdef _ARM_ASM +static inline void +memcpy_forward(unsigned char *dst, unsigned char *src, int size) +{ +} static inline void + +memcpy_backward(unsigned char *dst, unsigned char *src, int size) +{ +} +#endif /* */ + +////////////////////////////////////////////////////////////////////////// +// ARM NEON implementation of copy functions +////////////////////////////////////////////////////////////////////////// +#ifdef _ARM_NEON +extern void memcpy_forward_32_neon(unsigned long *dst, unsigned long *src, + int size); +extern void memcpy_backward_32_neon(unsigned long *dst, unsigned long *src, + int size); +extern void memcpy_forward_16_neon(unsigned short *dst, unsigned short *src, + int size); +extern void memcpy_backward_16_neon(unsigned short *dst, unsigned short *src, + int size); + +#endif /* */ + +////////////////////////////////////////////////////////////////////////// +// X86 SSE2 copy functions +////////////////////////////////////////////////////////////////////////// +#ifdef _X86_SSE2 +#include <emmintrin.h> +static inline void +memcpy_forward_sse2(unsigned char *dst, unsigned char *src, int size) +{ + while (size > 0 && ((unsigned long) dst & 1)) { + *dst++ = *src++; + size--; + } while (size > 0 && ((unsigned long) dst & 3)) { + *(unsigned short *) dst = *(unsigned short *) src; + dst += 2; + src += 2; + size -= 2; + } while (size > 0 && ((unsigned long) dst & 63)) { + *(unsigned long *) dst = *(unsigned long *) src; + dst += 4; + src += 4; + size -= 4; + } if ((reinterpret_cast < unsigned long >(src) & 15) == 0) { + while (size >= 64) { + __m128 xmm0, xmm1, xmm2, xmm3; + + /* _mm_prefetch((const char*)(src+320), _MM_HINT_NTA); */ + xmm0 = _mm_load_ps((float *) (src)); + xmm1 = _mm_load_ps((float *) (src + 16)); + xmm2 = _mm_load_ps((float *) (src + 32)); + xmm3 = _mm_load_ps((float *) (src + 48)); + _mm_stream_ps((float *) (dst), xmm0); + _mm_stream_ps((float *) (dst + 16), xmm1); + _mm_stream_ps((float *) (dst + 32), xmm2); + _mm_stream_ps((float *) (dst + 48), xmm3); + src += 64; + dst += 64; + size -= 64; + } while (size >= 16) { + _mm_stream_ps((float *) dst, _mm_load_ps((float *) src)); + dst += 16; + src += 16; + size -= 16; + }} + else { + while (size >= 64) { + __m128 xmm0, xmm1, xmm2, xmm3; + + /* _mm_prefetch((const char*)(src+320), _MM_HINT_NTA); */ + xmm0 = _mm_loadu_ps((float *) (src)); + xmm1 = _mm_loadu_ps((float *) (src + 16)); + xmm2 = _mm_loadu_ps((float *) (src + 32)); + xmm3 = _mm_loadu_ps((float *) (src + 48)); + _mm_stream_ps((float *) (dst), xmm0); + _mm_stream_ps((float *) (dst + 16), xmm1); + _mm_stream_ps((float *) (dst + 32), xmm2); + _mm_stream_ps((float *) (dst + 48), xmm3); + src += 64; + dst += 64; + size -= 64; + } while (size >= 16) { + _mm_stream_ps((float *) dst, _mm_loadu_ps((float *) src)); + dst += 16; + src += 16; + size -= 16; + }} while (size >= 4) { + *(unsigned long *) dst = *(unsigned long *) src; + dst += 4; + src += 4; + size -= 4; + } while (size > 0) { + *dst++ = *src++; + size--; + } +} + +static inline void +memcpy_backward_sse2(unsigned char *dst, unsigned char *src, int size) +{ + dst = dst + size; + src = src + size; + while (size > 0 && ((unsigned long) dst & 1)) { + dst--; + src--; + size--; + *dst = *src; + } while (size > 0 && ((unsigned long) dst & 3)) { + dst -= 2; + src -= 2; + size -= 2; + *(unsigned short *) dst = *(unsigned short *) src; + } while (size > 0 && ((unsigned long) dst & 63)) { + dst -= 4; + src -= 4; + size -= 4; + *(unsigned long *) dst = *(unsigned long *) src; + } if ((reinterpret_cast < unsigned long >(src) & 15) == 0) { + while (size >= 64) { + __m128 xmm0, xmm1, xmm2, xmm3; + + src -= 64; + dst -= 64; + size -= 64; + /*_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);*/ + xmm0 = _mm_load_ps((float *) (src)); + xmm1 = _mm_load_ps((float *) (src + 16)); + xmm2 = _mm_load_ps((float *) (src + 32)); + xmm3 = _mm_load_ps((float *) (src + 48)); + _mm_stream_ps((float *) (dst), xmm0); + _mm_stream_ps((float *) (dst + 16), xmm1); + _mm_stream_ps((float *) (dst + 32), xmm2); + _mm_stream_ps((float *) (dst + 48), xmm3); + } while (size >= 16) { + dst -= 16; + src -= 16; + size -= 16; + _mm_stream_ps((float *) dst, _mm_load_ps((float *) src)); + }} + else { + while (size >= 64) { + __m128 xmm0, xmm1, xmm2, xmm3; + + src -= 64; + dst -= 64; + size -= 64; + /*_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);*/ + xmm0 = _mm_loadu_ps((float *) (src)); + xmm1 = _mm_loadu_ps((float *) (src + 16)); + xmm2 = _mm_loadu_ps((float *) (src + 32)); + xmm3 = _mm_loadu_ps((float *) (src + 48)); + _mm_stream_ps((float *) (dst), xmm0); + _mm_stream_ps((float *) (dst + 16), xmm1); + _mm_stream_ps((float *) (dst + 32), xmm2); + _mm_stream_ps((float *) (dst + 48), xmm3); + } while (size >= 16) { + dst -= 16; + src -= 16; + size -= 16; + _mm_stream_ps((float *) dst, _mm_loadu_ps((float *) src)); + }} while (size >= 4) { + dst -= 4; + src -= 4; + size -= 4; + *(unsigned long *) dst = *(unsigned long *) src; + } while (size > 0) { + dst--; + src--; + se--; + *dst = *src; + } +} + +#endif +static inline void +move_memory_32(unsigned long *dst, unsigned long *src, int size) +{ + +#ifdef _USE_LIBC + memmove(dst, src, size * 4); + +#elif defined(_ARM_NEON) + if (dst > src && dst < src + size) + memcpy_backward_32_neon(dst, src, size); + else + memcpy_forward_32_neon(dst, src, size); + +#else /* */ + if (dst > src && dst < src + size) + memcpy_backward_32(dst, src, size); + else + memcpy_forward_32(dst, src, size); + +#endif /* */ +} + +static inline void +move_memory_16(unsigned short *dst, unsigned short *src, int size) +{ + +#ifdef _USE_LIBC + memmove(dst, src, size * 2); + +#elif defined(_ARM_NEON) + if (dst > src && dst < src + size) + memcpy_backward_16_neon(dst, src, size); + else + memcpy_forward_16_neon(dst, src, size); + +#else /* */ + if (dst > src && dst < src + size) + memcpy_backward_16(dst, src, size); + else + memcpy_forward_16(dst, src, size); + +#endif /* */ +} + +/** + * @brief Pixel block move function within one image buffer + * + * @param bits buffer address of top-left corner + * @param bpp bits per pixel, must be one of 16 and 32 + * @param stride number of bytes to go next row (can be negative) + * @param img_width entire image width + * @param img_height entire image height + * @param sx top-left x position of source area + * @param sy top-left y position of source area + * @param dx top-left x position of destination area + * @param dy top-left y position of destination area + * @param w width of area to copy + * @param h height of area to copy + * + * @remark This function supports overlapping in source and destination area. + * Any source or destination area which is outside given image will be cropped. + * Support negative stride. + * bits must be word aligned if bpp == 32 and half-word aligned if bpp == 16. + */ +int +move_pixels(void *bits, int bpp, int stride, int img_width, int img_height, + int sx, int sy, int dx, int dy, int w, int h) +{ + int bytes_per_pixel; + unsigned char *src_row; + unsigned char *dst_row; + + /*//////////////////////////////////////////////////////////////////////// + // check validity of arguments + //////////////////////////////////////////////////////////////////////// */ + if (!bits || img_width < 0 || img_height < 0 || w < 0 || h < 0) + return 0; + if (bpp == 32) + bytes_per_pixel = 4; + else if (bpp == 16) + bytes_per_pixel = 2; + else /* unsupported bpp */ + return 0; + if (bytes_per_pixel * img_width < stride) /* invalid image */ + return 0; + /* Wow thanks, we have nothing to do */ + if (sx == dx && sy == dy) + return 1; + + /*//////////////////////////////////////////////////////////////////////// + // Bounds check and cropping + //////////////////////////////////////////////////////////////////////// */ + while (sx < 0 || dx < 0) { + sx++; + dx++; + w--; + } + while (sy < 0 || dy < 0) { + sy++; + dy++; + h--; + } + while (sx + w > img_width || dx + w > img_width) + w--; + while (sy + h > img_height || dy + h > img_height) + h--; + /*//////////////////////////////////////////////////////////////////////// + // Check overlap and do copy + //////////////////////////////////////////////////////////////////////// */ + + /* No remaining area to copy */ + if (w <= 0 || h <= 0) + return 1; + src_row = (unsigned char *) bits + sy * stride + sx * bytes_per_pixel; + dst_row = (unsigned char *) bits + dy * stride + dx * bytes_per_pixel; + /* Check if we need to reverse y order */ + if (dy > sy && dy < sy + h) { + src_row += (h - 1) * stride; + dst_row += (h - 1) * stride; + stride = -stride; + } + if (bpp == 32) { + while (h--) { + move_memory_32((unsigned long *) dst_row, (unsigned long *) src_row, + w); + dst_row += stride; + src_row += stride; + }} + else if (bpp == 16) { + while (h--) { + move_memory_16((unsigned short *) dst_row, + (unsigned short *) src_row, w); + dst_row += stride; + src_row += stride; + }} + return 1; +} diff --git a/src/neon/neonmem.h b/src/neon/neonmem.h index 626abec..2e82ed0 100644 --- a/src/neon/neonmem.h +++ b/src/neon/neonmem.h @@ -26,24 +26,22 @@ 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 _NEON_MEMCPY_HEADER_
#define _NEON_MEMCPY_HEADER_
-
+
#include <stddef.h>
-
+
#ifdef memcpy
#undef memcpy
#endif
-
+
#define memcpy memcpy_neon
+
void *
memcpy_neon(void *dst, const void *src, size_t count); +
int
move_pixels(void *bits, int bpp, int stride, int img_width, + int img_height,
int sx, int sy, int dx, int dy, int w, + int h); -void *
-memcpy_neon (void *dst, const void *src, size_t count);
-
-int
-move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,
- int sx, int sy, int dx, int dy, int w, int h);
-#endif /* _NEON_MEMCPY_HEADER_ */
-
+#endif /* _NEON_MEMCPY_HEADER_ */
+
diff --git a/src/sec.c b/src/sec.c deleted file mode 100755 index 256f029..0000000 --- a/src/sec.c +++ /dev/null @@ -1,1777 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 <sys/stat.h> -#include <fcntl.h> - -/* all driver need this */ -#include "xf86.h" -#include "xf86_OSproc.h" - -#include "fb.h" -#include "mipointer.h" -#include "mibstore.h" -#include "micmap.h" -#include "colormapst.h" -#include "xf86cmap.h" -#include "xf86xv.h" -#include "xf86Crtc.h" -#include "sec.h" -#include "sec_display.h" -#include "sec_plane.h" -#include "sec_accel.h" -#include "sec_xberc.h" -#include "sec_util.h" -#include "sec_wb.h" -#include <tbm_bufmgr.h> -#include "fimg2d.h" - -#define OPTION_FLIP_BUFFERS 0 - -/* prototypes */ -static const OptionInfoRec* SECAvailableOptions (int chipid, int busid); -static void SECIdentify (int flags); -static Bool SECProbe (DriverPtr pDrv, int flags); -static Bool SECPreInit (ScrnInfoPtr pScrn, int flags); -static Bool SECScreenInit (ScreenPtr pScreen, int argc, char **argv); -static Bool SECSwitchMode (ScrnInfoPtr pScrn, DisplayModePtr pMode); -static void SECAdjustFrame (ScrnInfoPtr pScrn, int x, int y); -static Bool SECEnterVT (ScrnInfoPtr pScrn); -static void SECLeaveVT (ScrnInfoPtr pScrn); -static ModeStatus SECValidMode (ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool verbose, int flags); -static Bool SECCloseScreen (ScreenPtr pScreen); -static Bool SECCreateScreenResources (ScreenPtr pScreen); -#if HAVE_UDEV -static void SECUdevEventsHandler (int fd, void *closure); -#endif - -/* This DriverRec must be defined in the driver for Xserver to load this driver */ -_X_EXPORT DriverRec SEC = -{ - SEC_VERSION, - SEC_DRIVER_NAME, - SECIdentify, - SECProbe, - SECAvailableOptions, - NULL, - 0, - NULL, -}; - -/* Supported "chipsets" */ -static SymTabRec SECChipsets[] = -{ - { 0, "exynos" }, - {-1, NULL } -}; - -/* Supported options */ -typedef enum -{ - OPTION_DRI2, - OPTION_EXA, - OPTION_SWEXA, - OPTION_ROTATE, - OPTION_SNAPSHOT, - OPTION_WB, -#if OPTION_FLIP_BUFFERS - OPTION_FLIPBUFS, -#endif - OPTION_CACHABLE, - OPTION_SCANOUT, - OPTION_ACCEL2D, - OPTION_PARTIAL_UPDATE, -} SECOpts; - -static const OptionInfoRec SECOptions[] = -{ - { OPTION_DRI2, "dri2", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_EXA, "exa", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_SWEXA, "sw_exa", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_ROTATE, "rotate", OPTV_STRING, {0}, FALSE }, - { OPTION_SNAPSHOT, "snapshot", OPTV_STRING, {0}, FALSE }, - { OPTION_WB, "wb", OPTV_BOOLEAN, {0}, FALSE }, -#if OPTION_FLIP_BUFFERS - { OPTION_FLIPBUFS, "flip_bufs", OPTV_INTEGER, {0}, 3 }, -#endif - { OPTION_CACHABLE, "cachable", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_SCANOUT, "scanout", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_ACCEL2D, "accel_2d", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_PARTIAL_UPDATE, "partial_update", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; - -/* -------------------------------------------------------------------- */ -#ifdef XFree86LOADER - -MODULESETUPPROTO (SECSetup); - -static XF86ModuleVersionInfo SECVersRec = -{ - "exynos", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, - PACKAGE_VERSION_MINOR, - PACKAGE_VERSION_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - NULL, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData exynosModuleData = { &SECVersRec, SECSetup, NULL }; - -pointer -SECSetup (pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = FALSE; - - if (!setupDone) - { - setupDone = TRUE; - xf86AddDriver (&SEC, module, HaveDriverFuncs); - return (pointer) 1; - } - else - { - if (errmaj) *errmaj = LDR_ONCEONLY; - return NULL; - } -} - -#endif /* XFree86LOADER */ -/* -------------------------------------------------------------------- */ - -/* TODO:::check the fimd_drm */ -static Bool -_has_drm_mode_setting() -{ - /* TODO:: check the sysfs dri2 device name */ - return TRUE; -} - -/* - * Probing the device with the device node, this probing depend on the specific hw. - * This function just verify whether the display hw is avaliable or not. - */ -static Bool -_secHwProbe (struct pci_device * pPci, char *device,char **namep) -{ - if (!_has_drm_mode_setting()) - return FALSE; - - return TRUE; -} - -static tbm_bufmgr -_secInitBufmgr (int drm_fd, void * arg) -{ - tbm_bufmgr bufmgr = NULL; - - /* get buffer manager */ - setenv("BUFMGR_LOCK_TYPE", "once", 1); - setenv("BUFMGR_MAP_CACHE", "true", 1); - bufmgr = tbm_bufmgr_init (drm_fd); - - if (bufmgr == NULL) - return NULL; - - return bufmgr; -} - -static void -_secDeInitBufmgr (tbm_bufmgr bufmgr) -{ - if (bufmgr) - tbm_bufmgr_deinit (bufmgr); -} - -/* open drm */ -static Bool -_openDrmMaster (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - int ret; - - /* open drm */ - pSec->drm_fd = drmOpen ("exynos", NULL); - if (pSec->drm_fd < 0) - { - struct udev *udev; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device, *drm_device; - const char *path, *device_seat; - const char *filename; - - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "[DRM] Cannot open drm device.. search by udev\n"); - - /* STEP 1: Find drm device */ - udev = udev_new(); - if (udev == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR,"[DRM] fail to initialize udev context\n"); - goto fail_to_open_drm_master; - } - - 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); - device_seat = udev_device_get_property_value(device, "ID_SEAT"); - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] drm info: device:%p, patch:%s, seat:%s\n", device, path, device_seat); - - if(!device_seat) - device_seat = "seat0"; - - if(strcmp(device_seat, "seat0") == 0) - { - drm_device = device; - break; - } - udev_device_unref(device); - } - - if(drm_device == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR,"[DRM] fail to find drm device\n"); - goto fail_to_open_drm_master; - } - - filename = udev_device_get_devnode(drm_device); - - pSec->drm_fd = open(filename, O_RDWR|O_CLOEXEC); - if (pSec->drm_fd < 0) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "[DRM] Cannot open drm device(%s)\n", filename); - - udev_device_unref(drm_device); - udev_enumerate_unref(e); - udev_unref(udev); - - goto fail_to_open_drm_master; - } - else - { - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed to open drm device(%s)\n", filename); - } - - udev_device_unref(drm_device); - udev_enumerate_unref(e); - udev_unref(udev); - } - else - { - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed to open drm device\n"); - } - - pSec->drm_device_name = drmGetDeviceNameFromFd (pSec->drm_fd); - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed get drm device name:%s\n", - pSec->drm_device_name); - - /* enable drm vblank */ - ret = drmCtlInstHandler (pSec->drm_fd, 217); - if (ret) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "[DRM] Fail to enable drm VBlank(%d)\n", ret); - goto fail_to_open_drm_master; - } - - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, - "[DRM] Enable drm VBlank(%d)\n", ret); - - /* initialize drm bufmgr */ - pSec->tbm_bufmgr = _secInitBufmgr (pSec->drm_fd, NULL); - if (pSec->tbm_bufmgr == NULL) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "[DRM] Error : bufmgr initialization failed\n"); - goto fail_to_open_drm_master; - } - - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG - , "[DRM] Enable buffer manager\n"); - - return TRUE; - -fail_to_open_drm_master: - - if (pSec->tbm_bufmgr) - { - _secDeInitBufmgr (pSec->tbm_bufmgr); - pSec->tbm_bufmgr = NULL; - } - - if (pSec->drm_device_name) - { - free (pSec->drm_device_name); - pSec->drm_device_name = NULL; - } - - if (pSec->drm_fd >= 0) - { - drmClose (pSec->drm_fd); - pSec->drm_fd = -1; - } - - return FALSE; -} - -/* close drm */ -static void -_closeDrmMaster (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - - if (pSec->tbm_bufmgr) - { - _secDeInitBufmgr (pSec->tbm_bufmgr); - pSec->tbm_bufmgr = NULL; - } - - if (pSec->drm_fd >= 0) - { - drmClose (pSec->drm_fd); - pSec->drm_fd = -1; - } - - if (pSec->drm_device_name) - { - free (pSec->drm_device_name); - pSec->drm_device_name = NULL; - } -} - -/* - * Initialize the device Probing the device with the device node, - * this probing depend on the specific hw. - * This function just verify whether the display hw is avaliable or not. - */ -static Bool -_secHwInit (ScrnInfoPtr pScrn, struct pci_device *pPci, char *device) -{ - SECPtr pSec = SECPTR (pScrn); - - /* init drm master */ - if (_openDrmMaster (pScrn) == TRUE) - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG - , "DRM BLANK is enabled\n"); - else - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG - , "DRM BLANK is disabled\n"); - - - if(g2d_init (pSec->drm_fd)) - { - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG - , "G2D is enabled\n"); - pSec->is_accel_2d = TRUE; - } - else - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG - , "G2D is disabled\n"); - - return TRUE; -} - -/* SigHook */ -OsSigWrapperPtr old_sig_wrapper; -int -_secOsSigWrapper (int sig) -{ - XDBG_KLOG(MSEC,"Catch SIG: %d\n", sig); - - return old_sig_wrapper(sig); /*Contiue*/ -} - -/* - * DeInitialize the hw - */ -static void -_secHwDeinit (ScrnInfoPtr pScrn) -{ - g2d_fini (); - - /* deinit drm master */ - _closeDrmMaster (pScrn); - - return; -} - -static Bool -_allocScrnPrivRec (ScrnInfoPtr pScrn) -{ - if (pScrn->driverPrivate != NULL) - return TRUE; - - pScrn->driverPrivate = calloc (sizeof (SECRec), 1); - if (!pScrn->driverPrivate) - return FALSE; - - return TRUE; -} - -static void -_freeScrnPrivRec (ScrnInfoPtr pScrn) -{ - if (pScrn->driverPrivate == NULL) - return; - free (pScrn->driverPrivate); - pScrn->driverPrivate = NULL; -} - -/* - * Check the driver option. - * Set the option flags to the driver private - */ -static void -_checkDriverOptions (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - const char *s; - int flip_bufs = 3; - - /* exa */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_EXA, FALSE)) - pSec->is_exa = TRUE; - - /* sw exa */ - if (pSec->is_exa) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_SWEXA, TRUE)) - pSec->is_sw_exa = TRUE; - } - - /* dri2 */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_DRI2, FALSE)) - { - pSec->is_dri2 = TRUE; - - /* number of the flip buffers */ -#if OPTION_FLIP_BUFFERS - if (xf86GetOptValInteger (pSec->Options, OPTION_FLIPBUFS, &flip_bufs)) - pSec->flip_bufs = flip_bufs; - else -#endif - { - /* default is 3 */ - flip_bufs = 3; - pSec->flip_bufs = flip_bufs; - } - } - - /* rotate */ - pSec->rotate = RR_Rotate_0; - if (( s= xf86GetOptValString (pSec->Options, OPTION_ROTATE))) - { - if (!xf86NameCmp (s, "CW")) - { - pSec->rotate = RR_Rotate_90; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen clockwise\n"); - } - else if (!xf86NameCmp (s, "CCW")) - { - pSec->rotate = RR_Rotate_270; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen counter-clockwise\n"); - } - else if (!xf86NameCmp (s, "UD")) - { - pSec->rotate = RR_Rotate_180; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen upside-down\n"); - } - else - { - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "\"%s\" is not valid option", s); - } - } - - /* wb */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_WB, FALSE)) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_WB, TRUE)) - pSec->is_wb_clone = TRUE; - } - - /* cachable */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_CACHABLE, FALSE)) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_CACHABLE, TRUE)) - { - pSec->cachable = TRUE; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use cachable buffer.\n"); - } - } - - /* scanout */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_SCANOUT, FALSE)) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_SCANOUT, TRUE)) - { - pSec->scanout = TRUE; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use scanout buffer.\n"); - } - } - - /* hw_2d */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_ACCEL2D, FALSE)) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_ACCEL2D, TRUE)) - { - pSec->is_accel_2d = TRUE; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use 2d accelerator.\n"); - } - } - - /* use_partial_update */ - if (xf86ReturnOptValBool (pSec->Options, OPTION_PARTIAL_UPDATE, FALSE)) - { - if (xf86ReturnOptValBool (pSec->Options, OPTION_PARTIAL_UPDATE, TRUE)) - { - pSec->use_partial_update = TRUE; - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use partial update.\n"); - } - } -} - -#if HAVE_UDEV -static void -_secUdevInit (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - struct udev *u; - struct udev_monitor *mon; - - xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "hotplug detection\n"); - - u = udev_new(); - if(!u) - return; - - mon = udev_monitor_new_from_netlink(u, "udev"); - if(!mon) - { - udev_unref(u); - return; - } - - if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 || - udev_monitor_enable_receiving(mon) < 0) - { - udev_monitor_unref(mon); - udev_unref(u); - return; - } - - pSec->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), SECUdevEventsHandler, pScrn); - if (!pSec->uevent_handler) - { - udev_monitor_unref(mon); - udev_unref(u); - return; - } - - pSec->uevent_monitor = mon; -} - -static void -_secUdevDeinit (ScrnInfoPtr pScrn) -{ - SECPtr pSec = SECPTR (pScrn); - - if (pSec->uevent_handler) - { - struct udev *u = udev_monitor_get_udev(pSec->uevent_monitor); - - udev_monitor_unref(pSec->uevent_monitor); - udev_unref(u); - pSec->uevent_handler = NULL; - pSec->uevent_monitor = NULL; - } - -} - -static Bool -SECSaveScreen (ScreenPtr pScreen, int mode) -{ - /* dummpy save screen */ - return TRUE; -} - -static void -SECUdevEventsHandler (int fd, void *closure) -{ - ScrnInfoPtr pScrn = closure; - SECPtr pSec = SECPTR (pScrn); - struct udev_device *dev; - const char *hotplug; - struct stat s; - dev_t udev_devnum; - int ret; - - dev = udev_monitor_receive_device (pSec->uevent_monitor); - if (!dev) - return; - - udev_devnum = udev_device_get_devnum(dev); - - ret = fstat (pSec->drm_fd, &s); - if (ret == -1) - return; - - /* - * Check to make sure this event is directed at our - * device (by comparing dev_t values), then make - * sure it's a hotplug event (HOTPLUG=1) - */ - hotplug = udev_device_get_property_value (dev, "HOTPLUG"); - - if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && - hotplug && atoi(hotplug) == 1) - { - XDBG_INFO(MSEC, "SEC-UDEV: HotPlug\n"); - RRGetInfo (screenInfo.screens[pScrn->scrnIndex], TRUE); - } - - udev_device_unref(dev); -} -#endif /* UDEV_HAVE */ - -static const OptionInfoRec * -SECAvailableOptions (int chipid, int busid) -{ - return SECOptions; -} - -static void -SECIdentify (int flags) -{ - xf86PrintChipsets (SEC_NAME, "driver for Exynos Chipsets", SECChipsets); -} - - -/* The purpose of this function is to identify all instances of hardware supported - * by the driver. The probe must find the active device sections that match the driver - * by calling xf86MatchDevice(). - */ -static Bool -SECProbe (DriverPtr pDrv, int flags) -{ - int i; - ScrnInfoPtr pScrn; - GDevPtr *ppDevSections; - int numDevSections; - int entity; - Bool foundScreen = FALSE; - - /* check the drm mode setting */ - if (!_secHwProbe (NULL, NULL, NULL)) - { - return FALSE; - } - - /* For now, just bail out for PROBE_DETECT. */ - if (flags & PROBE_DETECT) - return FALSE; - - if ((numDevSections = xf86MatchDevice (SEC_DRIVER_NAME, &ppDevSections)) <= 0) - { - free (ppDevSections); - return FALSE; - } - - for (i = 0; i < numDevSections; i++) - { - entity = xf86ClaimNoSlot (pDrv, 0, ppDevSections[i], TRUE); - - pScrn = xf86AllocateScreen (pDrv, flags); - xf86AddEntityToScreen (pScrn, entity); - - if (pScrn) - { - foundScreen = TRUE; - - pScrn->driverVersion = SEC_VERSION; - pScrn->driverName = SEC_DRIVER_NAME; - pScrn->name = SEC_NAME; - pScrn->Probe = SECProbe; - pScrn->PreInit = SECPreInit; - pScrn->ScreenInit = SECScreenInit; - pScrn->SwitchMode = SECSwitchMode; - pScrn->AdjustFrame = SECAdjustFrame; - pScrn->EnterVT = SECEnterVT; - pScrn->LeaveVT = SECLeaveVT; - pScrn->ValidMode = SECValidMode; - - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "using drm mode setting device\n"); - } - } - free (ppDevSections); - - return foundScreen; -} - -/* - * This is called before ScreenInit to probe the screen configuration. - * The main tasks to do in this funtion are probing, module loading, option handling, - * card mapping, and mode setting setup. - */ -static Bool -SECPreInit (ScrnInfoPtr pScrn, int flags) -{ - SECPtr pSec; - Gamma defualt_gamma = {0.0, 0.0, 0.0}; - rgb default_weight = {0, 0, 0}; - int flag24; - - if (flags & PROBE_DETECT) - return FALSE; - - /* allocate private */ - if (!_allocScrnPrivRec (pScrn)) - return FALSE; - pSec = SECPTR (pScrn); - - /* Check the number of entities, and fail if it isn't one. */ - if (pScrn->numEntities != 1) - return FALSE; - - pSec->pEnt = xf86GetEntityInfo (pScrn->entityList[0]); - - /* initialize the hardware specifics */ - if (!_secHwInit (pScrn, NULL, NULL)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "fail to initialize hardware\n"); - goto bail1; - } - - pScrn->displayWidth = 640; /*default width */ - pScrn->monitor = pScrn->confScreen->monitor; - pScrn->progClock = TRUE; - pScrn->rgbBits = 8; - - /* set the depth and the bpp to pScrn */ - flag24 = Support24bppFb | Support32bppFb; - if (!xf86SetDepthBpp (pScrn, 0, 0, 0, flag24)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "fail to find the depth\n"); - goto bail1; - } - xf86PrintDepthBpp (pScrn); /* just print out the depth and the bpp */ - - /* color weight */ - if (!xf86SetWeight (pScrn, default_weight, default_weight)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to set the color weight of RGB\n"); - goto bail1; - } - - /* visual init, make a TrueColor, -1 */ - if (!xf86SetDefaultVisual (pScrn, -1)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to initialize the default visual\n"); - goto bail1; - } - - /* Collect all the option flags (fill in pScrn->options) */ - xf86CollectOptions (pScrn, NULL); - - /* - * Process the options based on the information SECOptions. - * The results are written to pSec->Options. If all the options - * processing is done within this fuction a local variable "options" - * can be used instead of pSec->Options - */ - if (!(pSec->Options = malloc (sizeof (SECOptions)))) - goto bail1; - memcpy (pSec->Options, SECOptions, sizeof (SECOptions)); - xf86ProcessOptions (pScrn->scrnIndex, pSec->pEnt->device->options, - pSec->Options); - - /* Check with the driver options */ - _checkDriverOptions (pScrn); - - /* use a fake root pixmap when rotation angle is 90 or 270 */ - pSec->fake_root = ((pSec->rotate &(RR_Rotate_90|RR_Rotate_270)) != 0); - - /* drm mode init:: Set the Crtc, the default Output, and the current Mode */ - if (!secModePreInit (pScrn, pSec->drm_fd)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to initialize drm mode setting\n"); - goto bail1; - } - - /* set gamma */ - if (!xf86SetGamma (pScrn,defualt_gamma)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to set the gamma\n"); - goto bail1; - } - - pScrn->currentMode = pScrn->modes; - pScrn->displayWidth = pScrn->virtualX; - xf86PrintModes (pScrn); /* just print the current mode */ - - /* set dpi */ - xf86SetDpi (pScrn, 0, 0); - - /* Load modules */ - if (!xf86LoadSubModule (pScrn, "fb")) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to load fb module\n"); - goto bail1; - } - - if (!xf86LoadSubModule (pScrn, "exa")) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to load exa module\n"); - goto bail1; - } - - if (!xf86LoadSubModule (pScrn, "dri2")) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR , - "fail to load dri2 module\n"); - goto bail1; - } - - old_sig_wrapper = OsRegisterSigWrapper(_secOsSigWrapper); - return TRUE; - -bail1: - _freeScrnPrivRec (pScrn); - _secHwDeinit (pScrn); - return FALSE; -} - - - - -static Bool -SECScreenInit (ScreenPtr pScreen, int argc, char **argv) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - VisualPtr visual; - int init_picture = 0; - SECFbPtr pFb = NULL; - - xf86DrvMsg (pScrn->scrnIndex,X_INFO, - "Infomation of Visual is \n\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" - "\tmask: %x,%x,%x, offset: %d,%d,%d\n", - pScrn->bitsPerPixel, - pScrn->depth, - xf86GetVisualName (pScrn->defaultVisual), - (unsigned int) pScrn->mask.red, - (unsigned int) pScrn->mask.green, - (unsigned int) pScrn->mask.blue, - (int) pScrn->offset.red, - (int) pScrn->offset.green, - (int) pScrn->offset.blue); - - /* initialize the framebuffer */ - /* soolim :: think rotations */ - - pFb = secFbAllocate (pScrn, pScrn->virtualX, pScrn->virtualY); - if (!pFb) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "cannot allocate framebuffer\n"); - return FALSE; - } - pSec->pFb = pFb; - - /* mi layer */ - miClearVisualTypes(); - if (!miSetVisualTypes (pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "visual type setup failed for %d bits per pixel [1]\n", - pScrn->bitsPerPixel); - return FALSE; - } - - if (!miSetPixmapDepths()) - { - xf86DrvMsg (pScrn->scrnIndex,X_ERROR , - "pixmap depth setup failed\n"); - return FALSE; - } - - switch (pScrn->bitsPerPixel) - { - case 16: - case 24: - case 32: - if (! fbScreenInit (pScreen, (void*)ROOT_FB_ADDR, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->virtualX, /*Pixel width for framebuffer*/ - pScrn->bitsPerPixel)) - return FALSE; - - init_picture = 1; - - break; - default: - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "internal error: invalid number of bits per pixel (%d) encountered\n", - pScrn->bitsPerPixel); - break; - } - - if (pScrn->bitsPerPixel > 8) - { - /* Fixup RGB ordering */ - visual = pScreen->visuals + pScreen->numVisuals; - while (--visual >= pScreen->visuals) - { - if ((visual->class | DynamicClass) == DirectColor) - { - visual->offsetRed = pScrn->offset.red; - visual->offsetGreen = pScrn->offset.green; - visual->offsetBlue = pScrn->offset.blue; - visual->redMask = pScrn->mask.red; - visual->greenMask = pScrn->mask.green; - visual->blueMask = pScrn->mask.blue; - } - } - } - - /* must be after RGB ordering fixed */ - if (init_picture && !fbPictureInit (pScreen, NULL, 0)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "Render extension initialisation failed\n"); - } - - /* init the exa */ - if (pSec->is_exa) - { - if (!secExaInit (pScreen)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "EXA initialization failed\n"); - } - else - { - /* init the dri2 */ - if (pSec->is_dri2) - { - if (!secDri2Init (pScreen)) - { - xf86DrvMsg (pScrn->scrnIndex, X_WARNING, - "DRI2 initialization failed\n"); - } - } - } - } - - /* XVideo Initiailization here */ - if (!secVideoInit (pScreen)) - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, - "XVideo extention initialization failed\n"); - - xf86SetBlackWhitePixels (pScreen); - miInitializeBackingStore (pScreen); - xf86SetBackingStore (pScreen); - - /* use dummy hw_cursro instead of sw_cursor */ - miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "Initializing HW Cursor\n"); - - if (!xf86_cursors_init (pScreen, SEC_CURSOR_W, SEC_CURSOR_H, - (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | - HARDWARE_CURSOR_INVERT_MASK | - HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | - HARDWARE_CURSOR_ARGB))) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR - , "Hardware cursor initialization failed\n"); - } - - /* crtc init */ - if (!xf86CrtcScreenInit (pScreen)) - return FALSE; - - /* set the desire mode : set the mode to xf86crtc here */ - xf86SetDesiredModes (pScrn); - - /* colormap */ - if (!miCreateDefColormap (pScreen)) - { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR - , "internal error: miCreateDefColormap failed \n"); - return FALSE; - } - - if (!xf86HandleColormaps (pScreen, 256, 8, secModeLoadPalette, NULL, - CMAP_PALETTED_TRUECOLOR)) - return FALSE; - - /* dpms */ - xf86DPMSInit (pScreen, xf86DPMSSet, 0); - - /* screen saver */ - pScreen->SaveScreen = SECSaveScreen; - - secModeInit(pScrn); - - /* Wrap the current CloseScreen function */ - pSec->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = SECCloseScreen; - - /* Wrap the current CloseScreen function */ - pSec->CreateScreenResources = pScreen->CreateScreenResources; - pScreen->CreateScreenResources = SECCreateScreenResources; - -#if HAVE_UDEV - _secUdevInit(pScrn); -#endif - -#if 0 - /* Init Hooks for memory flush */ - secMemoryInstallHooks(); -#endif - -#if USE_XDBG - xDbgLogPListInit (pScreen); -#endif - - XDBG_KLOG(MSEC, "Init Screen\n"); - return TRUE; -} - -static Bool -SECSwitchMode (ScrnInfoPtr pScrn, DisplayModePtr pMode) -{ - return xf86SetSingleMode (pScrn, pMode, RR_Rotate_0); -} - -static void -SECAdjustFrame (ScrnInfoPtr pScrn, int x, int y) -{ -} - -static Bool -SECEnterVT (ScrnInfoPtr pScrn) -{ - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "EnterVT::Hardware state at EnterVT:\n"); - - return TRUE; -} - -static void -SECLeaveVT (ScrnInfoPtr pScrn) -{ - xf86DrvMsg (pScrn->scrnIndex, X_INFO - , "LeaveVT::Hardware state at LeaveVT:\n"); -} - -static ModeStatus -SECValidMode (ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool verbose, int flags) -{ - return MODE_OK; -} - - -/** - * Adjust the screen pixmap for the current location of the front buffer. - * This is done at EnterVT when buffers are bound as long as the resources - * have already been created, but the first EnterVT happens before - * CreateScreenResources. - */ -static Bool -SECCreateScreenResources (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - pScreen->CreateScreenResources = pSec->CreateScreenResources; - if (!(*pScreen->CreateScreenResources) (pScreen)) - return FALSE; - - /* - * [TODO]::::: - * create screen resources - * set the bo to the screen pixamp private here - * or create the shadow pixmap for the screen pixamp here - * or set the fake rotated screen infomation here. - */ - - return TRUE; -} - -static Bool -SECCloseScreen (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = SECPTR (pScrn); - - secWbDestroy (); - -#if HAVE_UDEV - _secUdevDeinit(pScrn); -#endif - - secVideoFini (pScreen); - secExaDeinit (pScreen); - secModeDeinit (pScrn); - - if (pSec->pFb) - { - secFbFree (pSec->pFb); - pSec->pFb = NULL; - } - - _secHwDeinit (pScrn); - - pScrn->vtSema = FALSE; - - pScreen->CreateScreenResources = pSec->CreateScreenResources; - pScreen->CloseScreen = pSec->CloseScreen; - - XDBG_KLOG(MSEC, "Close Screen\n"); - return (*pScreen->CloseScreen) (pScreen); -} - - -#define CONV_POINT_TO_KEY(x, y, key) key = (unsigned long)((((unsigned short)(x&0xFFFF)) << 16) | ((unsigned short)(y&0xFFFF ))) -#define CONT_KEY_TO_POINT(key, x, y) x = (unsigned short)((key&0xFFFF0000)>>16); y=(unsigned short)(key&0xFFFF) - -typedef struct{ - tbm_bo bo; - struct xorg_list link; -}SecFbBoItem, *SecFbBoItemPtr; - -static void -_secFbFreeBoData(void* data) -{ - XDBG_RETURN_IF_FAIL(data != NULL); - - ScrnInfoPtr pScrn; - SECPtr pSec; - SECFbBoDataPtr bo_data = (SECFbBoDataPtr)data; - - pScrn = bo_data->pScrn; - pSec = SECPTR (pScrn); - - XDBG_DEBUG (MFB, "FreeRender bo_data gem:%d, fb_id:%d, %dx%d+%d+%d\n", - bo_data->gem_handle, bo_data->fb_id, - bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1, - bo_data->pos.x1, bo_data->pos.y1); - - if (bo_data->fb_id) - { - drmModeRmFB (pSec->drm_fd, bo_data->fb_id); - bo_data->fb_id = 0; - } - - if (bo_data->pPixmap) - { - pScrn->pScreen->DestroyPixmap (bo_data->pPixmap); - bo_data->pPixmap = NULL; - } - - free (bo_data); - bo_data = NULL; -} - - -static tbm_bo -_secFbCreateBo (SECFbPtr pFb, int x, int y, int width, int height) -{ - XDBG_RETURN_VAL_IF_FAIL ((pFb != NULL), NULL); - XDBG_RETURN_VAL_IF_FAIL ((width > 0), NULL); - XDBG_RETURN_VAL_IF_FAIL ((height > 0), NULL); - - SECPtr pSec = SECPTR (pFb->pScrn); - - tbm_bo bo = NULL; - tbm_bo_handle bo_handle1, bo_handle2; - SECFbBoDataPtr bo_data=NULL; - unsigned int pitch; - unsigned int fb_id = 0; - int ret; - int flag; - - pitch = width * 4; - - if (!pSec->cachable) - flag = TBM_BO_WC; - else - flag = TBM_BO_DEFAULT; - - bo = tbm_bo_alloc (pSec->tbm_bufmgr, pitch*height, flag); - XDBG_GOTO_IF_FAIL (bo != NULL, fail); - - /* memset 0x0 */ - bo_handle1 = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); - XDBG_RETURN_VAL_IF_FAIL (bo_handle1.ptr != NULL, NULL); - - memset (bo_handle1.ptr, 0x0, pitch*height); - tbm_bo_unmap (bo); - - bo_handle2 = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT); - - /* Create drm fb */ - ret = drmModeAddFB(pSec->drm_fd - , width, height - , pFb->pScrn->bitsPerPixel - , pFb->pScrn->bitsPerPixel - , pitch - , bo_handle2.u32 - , &fb_id); - XDBG_GOTO_IF_ERRNO(ret == Success, fail, -ret); - - if(x == -1) x = 0; - if(y == -1) y = 0; - - /* Set bo user data */ - bo_data = calloc(1, sizeof(SECFbBoDataRec)); - XDBG_GOTO_IF_FAIL (bo_data != NULL, fail); - bo_data->pFb = pFb; - bo_data->gem_handle = bo_handle2.u32; - bo_data->pitch = pitch; - bo_data->fb_id = fb_id; - bo_data->pos.x1 = x; - bo_data->pos.y1 = y; - bo_data->pos.x2 = x+width; - bo_data->pos.y2 = y+height; - bo_data->size = tbm_bo_size(bo); - bo_data->pScrn = pFb->pScrn; - XDBG_GOTO_IF_FAIL(tbm_bo_add_user_data(bo, TBM_BO_DATA_FB, _secFbFreeBoData), fail); - XDBG_GOTO_IF_FAIL(tbm_bo_set_user_data(bo, TBM_BO_DATA_FB, (void *)bo_data), fail); - - XDBG_DEBUG (MFB, "CreateRender bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n", - tbm_bo_export (bo), bo_data->gem_handle, bo_data->fb_id, - bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1, - bo_data->pos.x1, bo_data->pos.y1); - - return bo; -fail: - if (bo) - { - secRenderBoUnref(bo); - } - - if (fb_id) - { - drmModeRmFB(pSec->drm_fd, fb_id); - } - - if (bo_data) - { - free (bo_data); - bo_data = NULL; - } - - return NULL; -} - -static tbm_bo -_secFbRefBo (tbm_bo bo) -{ - return tbm_bo_ref(bo); -} - -static int -_secFbUnrefBo(tbm_bo bo) -{ - tbm_bo_unref(bo); - bo = NULL; - - return TRUE; -} - -SECFbPtr -secFbAllocate (ScrnInfoPtr pScrn, int width, int height) -{ - //secLogSetLevel(MFB, 0); - - XDBG_RETURN_VAL_IF_FAIL((pScrn != NULL), NULL); - XDBG_RETURN_VAL_IF_FAIL((width > 0), NULL); - XDBG_RETURN_VAL_IF_FAIL((height > 0), NULL); - - SECFbPtr pFb = calloc (1, sizeof(SECFbRec)); - XDBG_GOTO_IF_FAIL ((pFb != NULL), fail); - - pFb->pScrn = pScrn; - pFb->num_bo = 0; - pFb->width = width; - pFb->height = height; - - xorg_list_init(&pFb->list_bo); - - /* Create default buffer */ - pFb->default_bo = _secFbCreateBo(pFb, 0, 0, width, height); - - XDBG_TRACE (MFB,"Allocate %dx%d\n", width, height); - - return pFb; - -fail: - - return NULL; -} - -void -secFbFree (SECFbPtr pFb) -{ - XDBG_RETURN_IF_FAIL(pFb != NULL); - - XDBG_TRACE (MFB,"Free %dx%d, num:%d\n", pFb->width, pFb->height, pFb->num_bo); - - if (!xorg_list_is_empty(&pFb->list_bo)) - { - SecFbBoItemPtr item = NULL, tmp = NULL; - - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - xorg_list_del(&item->link); - _secFbUnrefBo(item->bo); - free(item); - item=NULL; - } - } - - if (pFb->default_bo) - { - secRenderBoUnref(pFb->default_bo); - pFb->default_bo = NULL; - } - - free (pFb); - pFb = NULL; -} - -tbm_bo -secFbGetBo (SECFbPtr pFb, int x, int y, int width, int height, Bool onlyIfExists) -{ - SECFbBoDataPtr bo_data=NULL; - tbm_bo bo = NULL; - _X_UNUSED unsigned long key; - BoxRec box; - BoxPtr b1, b2; - int ret = rgnOUT; - - box.x1 = x; - box.y1 = y; - box.x2 = x+width; - box.y2 = y+height; - b2 = &box; - - if(!xorg_list_is_empty(&pFb->list_bo)) - { - SecFbBoItemPtr item = NULL, tmp = NULL; - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - bo = item->bo; - - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - b1 = &bo_data->pos; - - ret = secUtilBoxInBox(b1, b2); - - if(ret == rgnIN || ret == rgnSAME) - { - return bo; - } - else if(ret == rgnPART) - { - if (!onlyIfExists) continue; - - int r2 = secUtilBoxInBox(b2, b1); - if(r2 == rgnIN) - { - xorg_list_del(&item->link); - _secFbUnrefBo(bo); - free(item); - item=NULL; - pFb->num_bo--; - ret = rgnOUT; - break; - } - } - else if(ret == rgnOUT) - { - continue; - } - else - { - return NULL; - } - } - } - - if (ret == rgnOUT && !onlyIfExists) - { - SecFbBoItemPtr item; - CONV_POINT_TO_KEY(x, y, key); - - item = calloc(1, sizeof(SecFbBoItem)); - XDBG_RETURN_VAL_IF_FAIL (item != NULL, NULL); - if(width == pFb->width && - height == pFb->height && - x == 0 && - y == 0) - { - bo = _secFbRefBo(pFb->default_bo); - } - else - { - bo = _secFbCreateBo(pFb, x, y, width, height); - if (!bo) - { - free (item); - item = NULL; - return NULL; - } - } - - item->bo = bo; - xorg_list_add(&item->link, &pFb->list_bo); - pFb->num_bo++; - - XDBG_TRACE (MFB, "GetBO num:%d bo:%p name:%d, %dx%d+%d+%d\n", - pFb->num_bo, bo, tbm_bo_export (bo), width, height, x,y); - return bo; - } - - return NULL; -} - -tbm_bo -secFbSwapBo (SECFbPtr pFb, tbm_bo back_bo) -{ - SECFbBoDataPtr back_bo_data = NULL; - SECFbBoDataPtr bo_data = NULL; - SECFbBoDataRec tmp_bo_data; - tbm_bo bo; - BoxPtr b1, b2; - SecFbBoItemPtr item = NULL, tmp = NULL; - - XDBG_RETURN_VAL_IF_FAIL(pFb != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL(FALSE == xorg_list_is_empty(&pFb->list_bo), NULL); - XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data(back_bo, TBM_BO_DATA_FB, (void * *)&back_bo_data), NULL); - XDBG_RETURN_VAL_IF_FAIL(back_bo_data, NULL); - - b2 = &back_bo_data->pos; - - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - bo = item->bo; - - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - b1 = &bo_data->pos; - if(rgnSAME == secUtilBoxInBox(b1, b2)) - { - XDBG_DEBUG(MFB, "SwapBO(Back:%d, Front:%d)\n", - tbm_bo_export (back_bo), tbm_bo_export (bo)); - - if(tbm_bo_swap(bo, back_bo)) - { - memcpy(&tmp_bo_data, bo_data, sizeof(SECFbBoDataRec)); - memcpy(bo_data, back_bo_data, sizeof(SECFbBoDataRec)); - memcpy(back_bo_data, &tmp_bo_data, sizeof(SECFbBoDataRec)); - } - else - return NULL; - - return bo; - } - } - - return NULL; -} - -void -secFbResize (SECFbPtr pFb, int width, int height) -{ - XDBG_RETURN_IF_FAIL(pFb != NULL); - - SECFbBoDataPtr bo_data=NULL; - tbm_bo bo, old_bo; - int ret; - BoxRec box; - BoxPtr b1, b2; - - if (pFb->width == width && pFb->height == height) - return; - - old_bo = pFb->default_bo; - - pFb->width = width; - pFb->height = height; - XDBG_TRACE (MFB,"Resize %dx%d, num:%d\n", pFb->width, pFb->height, pFb->num_bo); - - box.x1=0; - box.y1=0; - box.x2=width; - box.y2=height; - b1 = &box; - - if (!xorg_list_is_empty (&pFb->list_bo)) - { - SecFbBoItemPtr item = NULL, tmp = NULL; - - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - bo = item->bo; - - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - b2 = &bo_data->pos; - ret = secUtilBoxInBox(b1, b2); - - if(ret == rgnIN || ret ==rgnSAME) - continue; - - /* Remove bo */ - XDBG_DEBUG (MFB, "\t unref bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n", - tbm_bo_export (bo), bo_data->gem_handle, bo_data->fb_id, - bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1, - bo_data->pos.x1, bo_data->pos.y1); - - xorg_list_del(&item->link); - secRenderBoUnref(bo); - pFb->num_bo--; - free(item); - item=NULL; - } - } - - pFb->default_bo = _secFbCreateBo(pFb, 0, 0, width, height); - if(old_bo) - secRenderBoUnref(old_bo); -} - -int -secFbFindBo (SECFbPtr pFb, int x, int y, int width, int height, int *num_bo, tbm_bo** bos) -{ - SECFbBoDataPtr bo_data=NULL; - int num=0; - tbm_bo *l=NULL; - tbm_bo bo; - int ret = rgnOUT; - BoxRec box; - BoxPtr b1, b2; - SecFbBoItemPtr item = NULL, tmp = NULL; - - if(xorg_list_is_empty(&pFb->list_bo)) - { - return rgnOUT; - } - - box.x1=x; - box.y1=y; - box.x2=x+width; - box.y2=y+height; - b2 = &box; - - l = calloc(pFb->num_bo, sizeof(tbm_bo)); - - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - bo = item->bo; - - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - if (bo_data == NULL) - { - free (l); - return rgnOUT; - } - - b1 = &bo_data->pos; - ret = secUtilBoxInBox(b1, b2); - XDBG_DEBUG(MFB, "[%d/%d] ret:%d bo(%d,%d,%d,%d) fb(%d,%d,%d,%d)\n", - num+1, pFb->num_bo, ret, - b1->x1,b1->y1,b1->x2,b1->y2, - b2->x1,b2->y1,b2->x2,b2->y2); - - if(ret == rgnSAME || ret == rgnIN) - { - l[num++] = bo; - break; - } - else if(ret == rgnPART) - { - l[num++] = bo; - } - else - { - ; - } - } - - if(num_bo) *num_bo = num; - if(bos) - { - *bos = l; - } - else - { - free(l); - } - - return ret; -} - -tbm_bo -secFbFindBoByPoint (SECFbPtr pFb, int x, int y) -{ - SECFbBoDataPtr bo_data=NULL; - tbm_bo bo; - SecFbBoItemPtr item = NULL, tmp = NULL; - - if(xorg_list_is_empty(&pFb->list_bo)) - { - return NULL; - } - - xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link) - { - bo = item->bo; - tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data); - if ((x >= bo_data->pos.x1) && - (x < bo_data->pos.x2) && - (y >= bo_data->pos.y1) && - (y < bo_data->pos.y2)) - { - return bo; - } - } - - return NULL; -} - -PixmapPtr -secRenderBoGetPixmap (SECFbPtr pFb, tbm_bo bo) -{ - ScreenPtr pScreen = pFb->pScrn->pScreen; - PixmapPtr pPixmap; - SECFbBoDataPtr bo_data; - int ret; - - XDBG_RETURN_VAL_IF_FAIL(bo != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void**)&bo_data), NULL); - - if(bo_data->pPixmap == NULL) - { - pPixmap = pScreen->CreatePixmap(pFb->pScrn->pScreen, 0,0, - pFb->pScrn->depth, - CREATE_PIXMAP_USAGE_SUB_FB); - XDBG_GOTO_IF_FAIL(pPixmap != NULL, fail); - - ret = pScreen->ModifyPixmapHeader(pPixmap, - bo_data->pos.x2 - bo_data->pos.x1, - bo_data->pos.y2 - bo_data->pos.y1, - pFb->pScrn->depth, - pFb->pScrn->bitsPerPixel, - bo_data->pitch, (void*)bo); - XDBG_GOTO_IF_FAIL(ret != FALSE, fail); - bo_data->pPixmap = pPixmap; - XDBG_DEBUG(MFB, "CreateRenderPixmap:%p\n", pPixmap); - } - - return bo_data->pPixmap; - -fail: - XDBG_ERROR(MFB, "ERR: CreateRenderPixmap\n"); - if(pPixmap) - { - pScreen->DestroyPixmap(pPixmap); - } - return NULL; -} - -tbm_bo -secRenderBoCreate (ScrnInfoPtr pScrn, int width, int height) -{ - SECPtr pSec = SECPTR (pScrn); - - return _secFbCreateBo(pSec->pFb, -1, -1, width, height); -} - -tbm_bo -secRenderBoRef (tbm_bo bo) -{ - return _secFbRefBo (bo); -} - -void -secRenderBoUnref (tbm_bo bo) -{ - _secFbUnrefBo(bo); -} - -void -secRenderBoSetPos (tbm_bo bo, int x, int y) -{ - SECFbBoDataPtr bo_data; - int width, height; - - XDBG_RETURN_IF_FAIL(bo != NULL); - XDBG_RETURN_IF_FAIL(x >= 0); - XDBG_RETURN_IF_FAIL(y >= 0); - XDBG_RETURN_IF_FAIL(tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void**)&bo_data)); - - width = bo_data->pos.x2 - bo_data->pos.x1; - height = bo_data->pos.y2 - bo_data->pos.y1; - - bo_data->pos.x1 = x; - bo_data->pos.y1 = y; - bo_data->pos.x2 = x+width; - bo_data->pos.y2 = y+height; -} diff --git a/src/sec.h b/src/sec.h deleted file mode 100755 index de04a1b..0000000 --- a/src/sec.h +++ /dev/null @@ -1,230 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: SooChan Lim <sc1.lim@samsung.com> - -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 SEC_H -#define SEC_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdint.h> -#include "xorg-server.h" -#include "xf86.h" -#include "xf86xv.h" -#include "xf86_OSproc.h" -#include "xf86drm.h" -#include "X11/Xatom.h" -#include "tbm_bufmgr.h" -#include "sec_display.h" -#include "sec_accel.h" -#include "sec_video.h" -#include "sec_wb.h" -#include "sec_util.h" -#if HAVE_UDEV -#include <libudev.h> -#endif - -#define USE_XDBG 1 - -/* drm bo data type */ -typedef enum -{ - TBM_BO_DATA_FB = 1, -} TBM_BO_DATA; - -/* framebuffer infomation */ -typedef struct -{ - ScrnInfoPtr pScrn; - - int width; - int height; - - int num_bo; - struct xorg_list list_bo; - void* tbl_bo; /* bo hash table: key=(x,y)position */ - - tbm_bo default_bo; -} SECFbRec, *SECFbPtr; - -/* framebuffer bo data */ -typedef struct -{ - SECFbPtr pFb; - BoxRec pos; - uint32_t gem_handle; - int fb_id; - int pitch; - int size; - PixmapPtr pPixmap; - ScrnInfoPtr pScrn; -} SECFbBoDataRec, *SECFbBoDataPtr; - -/* sec screen private information */ -typedef struct -{ - EntityInfoPtr pEnt; - Bool fake_root; /* screen rotation status */ - - /* driver options */ - OptionInfoPtr Options; - Bool is_exa; - Bool is_dri2; - Bool is_sw_exa; - Bool is_accel_2d; - Bool is_wb_clone; - Bool is_tfb; /* triple flip buffer */ - Bool cachable; /* if use cachable buffer */ - Bool scanout; /* if use scanout buffer */ - int flip_bufs; /* number of the flip buffers */ - Rotation rotate; - Bool use_partial_update; - Bool is_fb_touched; /* whether framebuffer is touched or not */ - - /* drm */ - int drm_fd; - char *drm_device_name; - tbm_bufmgr tbm_bufmgr; - - /* main fb information */ - SECFbPtr pFb; - - /* mode setting info private */ - SECModePtr pSecMode; - - /* exa private */ - SECExaPrivPtr pExaPriv; - - /* video private */ - SECVideoPrivPtr pVideoPriv; - - Bool isLcdOff; /* lvds connector on/off status */ - - /* screen wrapper functions */ - CloseScreenProcPtr CloseScreen; - CreateScreenResourcesProcPtr CreateScreenResources; - -#if HAVE_UDEV - struct udev_monitor *uevent_monitor; - InputHandlerProc uevent_handler; -#endif - - /* DRI2 */ - Atom atom_use_dri2; - Bool useAsyncSwap; - DrawablePtr flipDrawable; - - /* pending flip handler cause of lcd off */ - Bool pending_flip_handler; - unsigned int frame; - unsigned int tv_sec; - unsigned int tv_usec; - void *event_data; - - /* overlay drawable */ - DamagePtr ovl_damage; - DrawablePtr ovl_drawable; - - SECDisplaySetMode set_mode; - OsTimerPtr resume_timer; - - SECWb *wb_clone; - Bool wb_fps; - int wb_hz; - - /* Cursor */ - Bool enableCursor; - - /* dump */ - int dump_mode; - long dump_xid; - void *dump_info; - char *dump_str; - char dump_type[16]; - int xvperf_mode; - char *xvperf; - - int scale; - int cpu; - int flip_cnt; - - /* mem debug - Normal pixmap - CREATE_PIXMAP_USAGE_BACKING_PIXMAP - CREATE_PIXMAP_USAGE_OVERLAY - CREATE_PIXMAP_USAGE_XVIDEO - CREATE_PIXMAP_USAGE_DRI2_FILP_BACK - CREATE_PIXMAP_USAGE_FB - CREATE_PIXMAP_USAGE_SUB_FB - CREATE_PIXMAP_USAGE_DRI2_BACK - */ - int pix_normal; - int pix_backing_pixmap; - int pix_overlay; - int pix_dri2_flip_back; - int pix_fb; - int pix_sub_fb; - int pix_dri2_back; -} SECRec, *SECPtr; - -/* get a private screen of ScrnInfo */ -#define SECPTR(p) ((SECPtr)((p)->driverPrivate)) - -/* the version of the driver */ -#define SEC_VERSION 1000 - -/* the name used to prefix messages */ -#define SEC_NAME "exynos" - -/* the driver name used in display.conf file. exynos_drv.so */ -#define SEC_DRIVER_NAME "exynos" - -#define ROOT_FB_ADDR (~0UL) - -#define SEC_CURSOR_W 64 -#define SEC_CURSOR_H 64 - -/* sec framebuffer */ -SECFbPtr secFbAllocate (ScrnInfoPtr pScrn, int width, int height); -void secFbFree (SECFbPtr pFb); -void secFbResize (SECFbPtr pFb, int width, int height); -tbm_bo secFbGetBo (SECFbPtr pFb, int x, int y, int width, int height, Bool onlyIfExists); -int secFbFindBo (SECFbPtr pFb, int x, int y, int width, int height, int *num_bo, tbm_bo** bos); -tbm_bo secFbFindBoByPoint (SECFbPtr pFb, int x, int y); -tbm_bo secFbSwapBo (SECFbPtr pFb, tbm_bo back_bo); - -tbm_bo secRenderBoCreate (ScrnInfoPtr pScrn, int width, int height); -tbm_bo secRenderBoRef (tbm_bo bo); -void secRenderBoUnref (tbm_bo bo); -void secRenderBoSetPos (tbm_bo bo, int x, int y); -PixmapPtr secRenderBoGetPixmap (SECFbPtr pFb, tbm_bo bo); - -#endif /* SEC_H */ diff --git a/src/util/exynos_util.c b/src/util/exynos_util.c new file mode 100644 index 0000000..1183eaf --- /dev/null +++ b/src/util/exynos_util.c @@ -0,0 +1,2593 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <sys/ipc.h> +#include <sys/ioctl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> +#include <X11/XWDFile.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_output.h" +#include "exynos_video_fourcc.h" +#include <exynos/exynos_drm.h> +#include <list.h> + +#include <png.h> + +#include "fimg2d.h" + +#define DUMP_SCALE_RATIO 2 +#define PNG_DEPTH 8 + +int +exynosUtilDumpBmp(const char *file, const void *data, int width, int height) +{ + int i; + + struct { + unsigned char magic[2]; + } bmpfile_magic = { { + 'B', 'M'}}; + + struct { + unsigned int filesz; + unsigned short creator1; + unsigned short creator2; + unsigned int bmp_offset; + } bmpfile_header = { + 0, 0, 0, 0x36}; + + struct { + unsigned int header_sz; + unsigned int width; + unsigned int height; + unsigned short nplanes; + unsigned short bitspp; + unsigned int compress_type; + unsigned int bmp_bytesz; + unsigned int hres; + unsigned int vres; + unsigned int ncolors; + unsigned int nimpcolors; + } bmp_dib_v3_header_t = { + 0x28, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0}; + unsigned int *blocks; + + XDBG_RETURN_VAL_IF_FAIL(data != NULL, UTIL_DUMP_ERR_INTERNAL); + XDBG_RETURN_VAL_IF_FAIL(width > 0, UTIL_DUMP_ERR_INTERNAL); + XDBG_RETURN_VAL_IF_FAIL(height > 0, UTIL_DUMP_ERR_INTERNAL); + + XDBG_TRACE(MSEC, "%s : width(%d) height(%d)\n", + __FUNCTION__, width, height); + + FILE *fp = fopen(file, "w+"); + + if (fp == NULL) { + return UTIL_DUMP_ERR_OPENFILE; + } + else { + bmpfile_header.filesz = sizeof(bmpfile_magic) + sizeof(bmpfile_header) + + sizeof(bmp_dib_v3_header_t) + width * height * 3; + bmp_dib_v3_header_t.header_sz = sizeof(bmp_dib_v3_header_t); + bmp_dib_v3_header_t.width = width; + bmp_dib_v3_header_t.height = -height; + bmp_dib_v3_header_t.nplanes = 1; + bmp_dib_v3_header_t.bmp_bytesz = width * height * 3; + + fwrite(&bmpfile_magic, sizeof(bmpfile_magic), 1, fp); + fwrite(&bmpfile_header, sizeof(bmpfile_header), 1, fp); + fwrite(&bmp_dib_v3_header_t, sizeof(bmp_dib_v3_header_t), 1, fp); + + blocks = (unsigned int *) data; + for (i = 0; i < height * width; i++) + fwrite(&blocks[i], 3, 1, fp); + + fclose(fp); + } + + return UTIL_DUMP_OK; +} + +static int +exynosUtilDumpPng(const char *file, const void *data, int width, int height) +{ + XDBG_RETURN_VAL_IF_FAIL(data != NULL, UTIL_DUMP_ERR_INTERNAL); + XDBG_RETURN_VAL_IF_FAIL(width > 0, UTIL_DUMP_ERR_INTERNAL); + XDBG_RETURN_VAL_IF_FAIL(height > 0, UTIL_DUMP_ERR_INTERNAL); + + FILE *fp = fopen(file, "wb"); + int res = UTIL_DUMP_ERR_OPENFILE; + + if (fp) { + res = UTIL_DUMP_ERR_PNG; + png_structp pPngStruct = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (pPngStruct) { + png_infop pPngInfo = png_create_info_struct(pPngStruct); + + if (pPngInfo) { + png_init_io(pPngStruct, fp); + png_set_IHDR(pPngStruct, + pPngInfo, + width, + height, + PNG_DEPTH, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_set_bgr(pPngStruct); + png_write_info(pPngStruct, pPngInfo); + + const int pixel_size = 4; // RGBA + png_bytep *row_pointers = + png_malloc(pPngStruct, height * sizeof(png_byte *)); + if (!row_pointers) { + fclose(fp); + return res; + } + + unsigned int *blocks = (unsigned int *) data; + int y = 0; + int x = 0; + + for (; y < height; ++y) { + png_bytep row = png_malloc(pPngStruct, + sizeof(png_byte) * width * + pixel_size); + if (!row) { + fclose(fp); + return res; + } + row_pointers[y] = (png_bytep) row; + for (x = 0; x < width; ++x) { + unsigned int curBlock = blocks[y * width + x]; + + row[x * pixel_size] = (curBlock & 0xFF); + row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF; + row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF; + row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF; + } + } + + png_write_image(pPngStruct, row_pointers); + png_write_end(pPngStruct, pPngInfo); + + for (y = 0; y < height; y++) { + png_free(pPngStruct, row_pointers[y]); + } + png_free(pPngStruct, row_pointers); + + png_destroy_write_struct(&pPngStruct, &pPngInfo); + + res = UTIL_DUMP_OK; + } + } + fclose(fp); + } + + return res; +} + +int +exynosUtilDumpShm(int shmid, const void *data, int width, int height) +{ + char *addr; + struct shmid_ds ds; + + addr = shmat(shmid, 0, 0); + if (addr == (void *) -1) { + return UTIL_DUMP_ERR_SHMATTACH; + } + + if ((shmctl(shmid, IPC_STAT, &ds) < 0) || + (ds.shm_segsz < width * height * 4)) { + shmctl(shmid, IPC_RMID, NULL); + shmdt(addr); + + return UTIL_DUMP_ERR_SEGSIZE; + } + + memcpy(addr, data, width * height * 4); + + shmctl(shmid, IPC_RMID, NULL); + shmdt(addr); + + return UTIL_DUMP_OK; +} + +int +exynosUtilDumpRaw(const char *file, const void *data, int size) +{ +// int i; + unsigned int *blocks; + + FILE *fp = fopen(file, "w+"); + + if (fp == NULL) { + return UTIL_DUMP_ERR_OPENFILE; + } + else { + blocks = (unsigned int *) data; + fwrite(blocks, 1, size, fp); + + fclose(fp); + } + + return UTIL_DUMP_OK; +} + +int +exynosUtilDumpPixmap(const char *file, PixmapPtr pPixmap) +{ + EXYNOSPixmapPriv *privPixmap; + Bool need_finish = FALSE; + int ret; + + XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, UTIL_DUMP_ERR_INTERNAL); + XDBG_RETURN_VAL_IF_FAIL(file != NULL, UTIL_DUMP_ERR_INTERNAL); + + privPixmap = exaGetPixmapDriverPrivate(pPixmap); + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_RETURN_VAL_IF_FAIL(privPixmap->bo != NULL, UTIL_DUMP_ERR_INTERNAL); + } + + ret = + exynosUtilDumpBmp(file, + tbm_bo_get_handle(privPixmap->bo, TBM_DEVICE_CPU).ptr, + pPixmap->devKind / + (pPixmap->drawable.bitsPerPixel >> 3), + pPixmap->drawable.height); + + if (need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + return ret; +} + +enum DumpFormat { + DUMP_RAW = 0, + DUMP_BMP = 1, + DUMP_PNG +}; + +typedef struct _DumpBufInfo { + int index; + + tbm_bo bo; + int bo_size; + + char file[128]; + Bool dirty; + enum DumpFormat dump_format; + + int width; + int height; + xRectangle rect; + int size; + + struct xorg_list link; +} DumpBufInfo; + +typedef struct _DumpInfo { + ScrnInfoPtr pScrn; + + struct xorg_list *cursor; + struct xorg_list bufs; +} DumpInfo; + +static Bool +_calculateSize(int width, int height, xRectangle *crop) +{ + if (crop->x < 0) { + crop->width += (crop->x); + crop->x = 0; + } + if (crop->y < 0) { + crop->height += (crop->y); + crop->y = 0; + } + + XDBG_GOTO_IF_FAIL(width > 0 && height > 0, fail_cal); + XDBG_GOTO_IF_FAIL(crop->width > 0 && crop->height > 0, fail_cal); + XDBG_GOTO_IF_FAIL(crop->x >= 0 && crop->x < width, fail_cal); + XDBG_GOTO_IF_FAIL(crop->y >= 0 && crop->y < height, fail_cal); + + if (crop->x + crop->width > width) + crop->width = width - crop->x; + + if (crop->y + crop->height > height) + crop->height = height - crop->y; + + return TRUE; + fail_cal: + XDBG_ERROR(MSEC, "(%dx%d : %d,%d %dx%d)\n", + width, height, crop->x, crop->y, crop->width, crop->height); + + return FALSE; +} + +static void +_exynosUtilConvertBosG2D(tbm_bo src_bo, int sw, int sh, xRectangle *sr, + int sstride, tbm_bo dst_bo, int dw, int dh, + xRectangle *dr, int dstride, Bool composite, + int rotate) +{ + G2dImage *srcImg = NULL, *dstImg = NULL; + tbm_bo_handle src_bo_handle = { 0, }; + tbm_bo_handle dst_bo_handle = { 0, }; + G2dColorKeyMode mode; + G2dOp op; + + mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + src_bo_handle = tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(src_bo_handle.s32 > 0, access_done); + + dst_bo_handle = tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); + XDBG_GOTO_IF_FAIL(dst_bo_handle.s32 > 0, access_done); + + srcImg = g2d_image_create_bo(mode, sw, sh, src_bo_handle.s32, sstride); + XDBG_GOTO_IF_FAIL(srcImg != NULL, access_done); + + dstImg = g2d_image_create_bo(mode, dw, dh, dst_bo_handle.s32, dstride); + XDBG_GOTO_IF_FAIL(dstImg != NULL, access_done); + + if (!composite) + op = G2D_OP_SRC; + else + op = G2D_OP_OVER; + + if (rotate == 270) + srcImg->rotate_90 = 1; + else if (rotate == 180) { + srcImg->xDir = 1; + srcImg->yDir = 1; + } + else if (rotate == 90) { + srcImg->rotate_90 = 1; + srcImg->xDir = 1; + srcImg->yDir = 1; + } + + util_g2d_blend_with_scale(op, srcImg, dstImg, + (int) sr->x, (int) sr->y, sr->width, sr->height, + (int) dr->x, (int) dr->y, dr->width, dr->height, + FALSE); + g2d_exec(); + + access_done: + if (src_bo_handle.s32) + tbm_bo_unmap(src_bo); + if (dst_bo_handle.s32) + tbm_bo_unmap(dst_bo); + if (srcImg) + g2d_image_free(srcImg); + if (dstImg) + g2d_image_free(dstImg); +} + +static void +_exynosUtilConvertBosPIXMAN(int src_id, tbm_bo src_bo, int sw, int sh, + xRectangle *sr, int sstride, tbm_bo dst_bo, int dw, + int dh, xRectangle *dr, int dstride, Bool composite, + int rotate) +{ + tbm_bo_handle src_bo_handle = { 0, }; + tbm_bo_handle dst_bo_handle = { 0, }; + pixman_op_t op; + pixman_format_code_t src_pix_format; + + src_bo_handle = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(src_bo_handle.ptr != NULL, access_done); + + dst_bo_handle = tbm_bo_map(dst_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + XDBG_GOTO_IF_FAIL(dst_bo_handle.ptr != NULL, access_done); + + if (!composite) + op = PIXMAN_OP_SRC; + else + op = PIXMAN_OP_OVER; + + if (IS_YUV(src_id)) + src_pix_format = PIXMAN_yuy2; //PIXMAN_yv12 + else + src_pix_format = PIXMAN_a8r8g8b8; + + exynosUtilConvertImage(op, src_bo_handle.ptr, dst_bo_handle.ptr, + src_pix_format, PIXMAN_a8r8g8b8, + sw, sh, sr, dw, dh, dr, NULL, rotate, FALSE, FALSE); + + access_done: + if (src_bo_handle.ptr) + tbm_bo_unmap(src_bo); + if (dst_bo_handle.ptr) + tbm_bo_unmap(dst_bo); +} + +/* support only RGB and YUV */ +void +exynosUtilConvertBos(ScrnInfoPtr pScrn, int src_id, + tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride, + tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride, + Bool composite, int rotate) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_RETURN_IF_FAIL(pScrn != NULL); + XDBG_RETURN_IF_FAIL(src_bo != NULL); + XDBG_RETURN_IF_FAIL(dst_bo != NULL); + XDBG_RETURN_IF_FAIL(sr != NULL); + XDBG_RETURN_IF_FAIL(dr != NULL); + + pExynos = EXYNOSPTR(pScrn); + XDBG_RETURN_IF_FAIL(pExynos != NULL); + + if (!_calculateSize(sw, sh, sr)) + return; + if (!_calculateSize(dw, dh, dr)) + return; + + if (rotate < 0) + rotate += 360; + + XDBG_DEBUG(MVA, + "[%dx%d (%d,%d %dx%d) %d] => [%dx%d (%d,%d %dx%d) %d] comp(%d) rot(%d) G2D(%d)\n", + sw, sh, sr->x, sr->y, sr->width, sr->height, sstride, dw, dh, + dr->x, dr->y, dr->width, dr->height, dstride, composite, rotate, + pExynos->is_accel_2d); + + if (pExynos->is_accel_2d) + _exynosUtilConvertBosG2D(src_bo, sw, sh, sr, sstride, + dst_bo, dw, dh, dr, dstride, composite, + rotate); + else { + _exynosUtilConvertBosPIXMAN(src_id, src_bo, sw, sh, sr, sstride, + dst_bo, dw, dh, dr, dstride, + composite, rotate); + tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + tbm_bo_unmap(src_bo); + } +} + +void * +exynosUtilPrepareDump(ScrnInfoPtr pScrn, int bo_size, int buf_cnt) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + DumpInfo *dump; + int i; + + dump = calloc(1, sizeof(DumpInfo)); + XDBG_RETURN_VAL_IF_FAIL(dump != NULL, NULL); + + bo_size = bo_size / DUMP_SCALE_RATIO; + + dump->pScrn = pScrn; + + xorg_list_init(&dump->bufs); + + for (i = 0; i < buf_cnt; i++) { + tbm_bo bo = tbm_bo_alloc(pExynos->tbm_bufmgr, bo_size, TBM_BO_DEFAULT); + + XDBG_GOTO_IF_FAIL(bo != NULL, fail_prepare); + + DumpBufInfo *buf_info = calloc(1, sizeof(DumpBufInfo)); + + if (!buf_info) { + tbm_bo_unref(bo); + XDBG_WARNING_IF_FAIL(buf_info != NULL); + goto fail_prepare; + } + + buf_info->index = i; + buf_info->bo = bo; + buf_info->bo_size = bo_size; + + tbm_bo_handle handle = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + + memset(handle.ptr, 0x00, buf_info->bo_size); + tbm_bo_unmap(bo); + + xorg_list_add(&buf_info->link, &dump->bufs); + } + + dump->cursor = &dump->bufs; + + return (void *) dump; + + fail_prepare: + exynosUtilFinishDump(dump); + return NULL; +} + +void +exynosUtilDoDumpRaws(void *d, tbm_bo * bo, int *size, int bo_cnt, + const char *file) +{ + DumpInfo *dump = (DumpInfo *) d; + DumpBufInfo *next = NULL; + struct xorg_list *next_cursor; + void *src_ptr, *dst_ptr; + int i, remain_size, need_size; + + if (!dump || !bo) + return; + + CARD32 prev = GetTimeInMillis(); + + next_cursor = dump->cursor->next; + XDBG_RETURN_IF_FAIL(next_cursor != NULL); + + if (next_cursor == &dump->bufs) { + next_cursor = next_cursor->next; + XDBG_RETURN_IF_FAIL(next_cursor != NULL); + } + + next = xorg_list_entry(next_cursor, DumpBufInfo, link); + XDBG_RETURN_IF_FAIL(next != NULL); + + need_size = 0; + for (i = 0; i < bo_cnt; i++) + need_size += size[i]; + if (need_size > next->bo_size) { + EXYNOSPtr pExynos = EXYNOSPTR(dump->pScrn); + tbm_bo new_bo = + tbm_bo_alloc(pExynos->tbm_bufmgr, need_size, TBM_BO_DEFAULT); + XDBG_RETURN_IF_FAIL(new_bo != NULL); + tbm_bo_unref(next->bo); + next->bo = new_bo; + next->bo_size = need_size; + } + + dst_ptr = tbm_bo_map(next->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE).ptr; + XDBG_RETURN_IF_FAIL(dst_ptr != NULL); + + remain_size = next->bo_size; + for (i = 0; i < bo_cnt; i++) { + XDBG_GOTO_IF_FAIL(size[i] <= remain_size, end_dump_raws); + + src_ptr = tbm_bo_map(bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ).ptr; + XDBG_GOTO_IF_FAIL(src_ptr != NULL, end_dump_raws); + + memcpy(dst_ptr, src_ptr, size[i]); + dst_ptr += size[i]; + + if (i == 0) + next->size = 0; + + next->size += size[i]; + remain_size -= size[i]; + + tbm_bo_unmap(bo[i]); + } + + snprintf(next->file, sizeof(next->file), "%.3f_%s", + GetTimeInMillis() / 1000.0, file); + memset(&next->rect, 0, sizeof(xRectangle)); + next->dirty = TRUE; + next->dump_format = DUMP_RAW; + + XDBG_TRACE(MSEC, "DumpRaws: %ld(%d)\n", GetTimeInMillis() - prev, + next->index); + + dump->cursor = next_cursor; + + end_dump_raws: + tbm_bo_unmap(next->bo); + + return; +} + +void +exynosUtilDoDumpBmps(void *d, tbm_bo bo, int w, int h, xRectangle *crop, + const char *file, const char *dumpType) +{ + DumpInfo *dump = (DumpInfo *) d; + DumpBufInfo *next = NULL; + struct xorg_list *next_cursor; + int scale_w = w / DUMP_SCALE_RATIO; + int scale_h = h / DUMP_SCALE_RATIO; + xRectangle temp = { 0, }; + + if (!dump || !bo) + return; + + next_cursor = dump->cursor->next; + XDBG_RETURN_IF_FAIL(next_cursor != NULL); + + if (next_cursor == &dump->bufs) { + next_cursor = next_cursor->next; + XDBG_RETURN_IF_FAIL(next_cursor != NULL); + } + + next = xorg_list_entry(next_cursor, DumpBufInfo, link); + XDBG_RETURN_IF_FAIL(next != NULL); + + tbm_bo_handle src_handle = tbm_bo_get_handle(bo, TBM_DEVICE_CPU); + tbm_bo_handle dst_handle = tbm_bo_get_handle(next->bo, TBM_DEVICE_CPU); + + XDBG_RETURN_IF_FAIL(src_handle.ptr != NULL); + XDBG_RETURN_IF_FAIL(dst_handle.ptr != NULL); + XDBG_RETURN_IF_FAIL(scale_w * scale_h * 4 <= next->bo_size); + + CARD32 prev = GetTimeInMillis(); + + snprintf(next->file, sizeof(next->file), "%.3f_%s", + GetTimeInMillis() / 1000.0, file); + + next->dirty = TRUE; + + if (strcmp(dumpType, DUMP_TYPE_PNG) == 0) { + next->dump_format = DUMP_PNG; + } + else if (strcmp(dumpType, DUMP_TYPE_BMP) == 0) { + next->dump_format = DUMP_BMP; + } + else { + XDBG_ERROR(MSEC, "Unsupported dump-format\n"); + } + + next->size = scale_w * scale_h * 4; + + next->width = scale_w; + next->height = scale_h; + next->rect.x = 0; + next->rect.y = 0; + next->rect.width = (crop) ? (crop->width / DUMP_SCALE_RATIO) : next->width; + next->rect.height = + (crop) ? (crop->height / DUMP_SCALE_RATIO) : next->height; + + temp.width = (crop) ? crop->width : w; + temp.height = (crop) ? crop->height : h; + + exynosUtilConvertBos(dump->pScrn, 0, bo, w, h, &temp, w * 4, + next->bo, scale_w, scale_h, &next->rect, scale_w * 4, + FALSE, 0); + + XDBG_TRACE(MSEC, "DumpBmps: %ld(%d)\n", GetTimeInMillis() - prev, + next->index); + + dump->cursor = next_cursor; +} + +void +exynosUtilDoDumpPixmaps(void *d, PixmapPtr pPixmap, const char *file, + const char *dumpType) +{ + EXYNOSPixmapPriv *privPixmap; + xRectangle rect = { 0, }; + Bool need_finish = FALSE; + + XDBG_RETURN_IF_FAIL(d != NULL); + XDBG_RETURN_IF_FAIL(pPixmap != NULL); + XDBG_RETURN_IF_FAIL(file != NULL); + + privPixmap = exaGetPixmapDriverPrivate(pPixmap); + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_RETURN_IF_FAIL(privPixmap->bo != NULL); + } + + rect.width = pPixmap->drawable.width; + rect.height = pPixmap->drawable.height; + + exynosUtilDoDumpBmps(d, privPixmap->bo, + pPixmap->devKind / + (pPixmap->drawable.bitsPerPixel >> 3), + pPixmap->drawable.height, &rect, file, dumpType); + + if (need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); +} + +void +exynosUtilDoDumpVBuf(void *d, EXYNOSVideoBuf * vbuf, const char *file) +{ + XDBG_RETURN_IF_FAIL(d != NULL); + XDBG_RETURN_IF_FAIL(vbuf != NULL); + XDBG_RETURN_IF_FAIL(file != NULL); + XDBG_RETURN_IF_FAIL(vbuf->exynosure == FALSE); + + if (IS_RGB(vbuf->id)) + exynosUtilDoDumpBmps(d, vbuf->bo[0], vbuf->width, vbuf->height, + &vbuf->crop, file, DUMP_TYPE_BMP); + else if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_ST12) + exynosUtilDoDumpRaws(d, vbuf->bo, vbuf->lengths, 2, file); + else + exynosUtilDoDumpRaws(d, vbuf->bo, &vbuf->size, 1, file); +} + +void +exynosUtilFlushDump(void *d) +{ + static Bool is_dir = FALSE; + char *dir = DUMP_DIR; + DumpInfo *dump = (DumpInfo *) d; + DumpBufInfo *cur = NULL, *next = NULL; + + if (!dump) + return; + + if (!is_dir) { + DIR *dp; + + if (!(dp = opendir(dir))) { + ErrorF("failed: open'%s' (%s)\n", dir, strerror(errno)); + return; + } + else + closedir(dp); + is_dir = TRUE; + } + + xorg_list_for_each_entry_safe(cur, next, &dump->bufs, link) { + if (cur->dirty) { + if (cur->bo) { + char file[128]; + + snprintf(file, sizeof(file), "%s/%s", dir, cur->file); + + if (cur->dump_format == DUMP_RAW) { + tbm_bo_handle handle = + tbm_bo_map(cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(handle.ptr != NULL, reset_dump); + + exynosUtilDumpRaw(file, handle.ptr, cur->size); + + tbm_bo_unmap(cur->bo); + } + else { + unsigned int *p; + tbm_bo_handle handle = + tbm_bo_map(cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(handle.ptr != NULL, reset_dump); + + /* fill magenta color(#FF00FF) for background */ + p = (unsigned int *) handle.ptr; + if (p) { + int i, j; + + for (j = 0; j < cur->height; j++) + for (i = cur->rect.width; i < cur->width; i++) + p[i + j * cur->width] = 0xFFFF00FF; + } + + if (cur->dump_format == DUMP_PNG) { + exynosUtilDumpPng(file, handle.ptr, cur->width, + cur->height); + } + else if (cur->dump_format == DUMP_BMP) { + exynosUtilDumpBmp(file, handle.ptr, cur->width, + cur->height); + } + else { + XDBG_ERROR(MSEC, "Invalid dump format specified\n"); + goto reset_dump; + } + + tbm_bo_unmap(cur->bo); + } + } + + reset_dump: + { + tbm_bo_handle handle = + tbm_bo_map(cur->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + memset(handle.ptr, 0x00, cur->bo_size); + tbm_bo_unmap(cur->bo); + } + cur->width = 0; + cur->height = 0; + cur->size = 0; + memset(&cur->rect, 0, sizeof(xRectangle)); + cur->file[0] = '\0'; + cur->dirty = FALSE; + cur->dump_format = DUMP_PNG; + } + } +} + +void +exynosUtilFinishDump(void *d) +{ + DumpInfo *dump = (DumpInfo *) d; + DumpBufInfo *cur = NULL, *next = NULL; + + if (!dump) + return; + + xorg_list_for_each_entry_safe(cur, next, &dump->bufs, link) { + if (cur->bo) + tbm_bo_unref(cur->bo); + xorg_list_del(&cur->link); + free(cur); + } + free(dump); +} + +#ifndef RR_Rotate_All +#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) +#endif + +int +exynosUtilDegreeToRotate(int degree) +{ + int rotate; + + switch (degree) { + case 0: + rotate = RR_Rotate_0; + break; + case 90: + rotate = RR_Rotate_90; + break; + case 180: + rotate = RR_Rotate_180; + break; + case 270: + rotate = RR_Rotate_270; + break; + default: + rotate = 0; /* ERROR */ + break; + } + + return rotate; +} + +int +exynosUtilRotateToDegree(int rotate) +{ + int degree; + + switch (rotate & RR_Rotate_All) { + case RR_Rotate_0: + degree = 0; + break; + case RR_Rotate_90: + degree = 90; + break; + case RR_Rotate_180: + degree = 180; + break; + case RR_Rotate_270: + degree = 270; + break; + default: + degree = -1; /* ERROR */ + break; + } + + return degree; +} + +static int +_exynosUtilRotateToInt(int rot) +{ + switch (rot & RR_Rotate_All) { + case RR_Rotate_0: + return 0; + case RR_Rotate_90: + return 1; + case RR_Rotate_180: + return 2; + case RR_Rotate_270: + return 3; + } + + return 0; +} + +int +exynosUtilRotateAdd(int rot_a, int rot_b) +{ + int a = _exynosUtilRotateToInt(rot_a); + int b = _exynosUtilRotateToInt(rot_b); + + return (int) ((1 << ((a + b) % 4)) & RR_Rotate_All); +} + +void +exynosUtilCacheFlush(ScrnInfoPtr scrn) +{ +#ifdef LEGACY_INTERFACE + struct drm_exynos_gem_cache_op cache_op; + EXYNOSPtr pExynos; + int ret; + static int success = TRUE; + + XDBG_RETURN_IF_FAIL(scrn != NULL); + + if (!success) + return; + + pExynos = EXYNOSPTR(scrn); + + CLEAR(cache_op); + cache_op.flags = EXYNOS_DRM_CACHE_FSH_ALL | EXYNOS_DRM_ALL_CACHES_CORES; + cache_op.usr_addr = 0; + cache_op.size = 0; + + ret = drmCommandWriteRead(pExynos->drm_fd, DRM_EXYNOS_GEM_CACHE_OP, + &cache_op, sizeof(cache_op)); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "cache flush failed. (%s)\n", strerror(errno)); + success = FALSE; + } +#endif +} + +const PropertyPtr +exynosUtilGetWindowProperty(WindowPtr pWin, const char *prop_name) +{ + int rc; + Mask prop_mode = DixReadAccess; + Atom property; + PropertyPtr pProp; + + if (!prop_name) + return NULL; + + property = MakeAtom(prop_name, strlen(prop_name), FALSE); + if (property == None) + return NULL; + + rc = dixLookupProperty(&pProp, pWin, property, serverClient, prop_mode); + if (rc == Success && pProp->data) { + return pProp; + } + + return NULL; +} + +static void * +_copy_one_channel(int width, int height, + char *s, int s_size_w, int s_pitches, + char *d, int d_size_w, int d_pitches) +{ + uchar *src = (uchar *) s; + uchar *dst = (uchar *) d; + + if (d_size_w == width && s_size_w == width) + memcpy(dst, src, s_pitches * height); + else { + int i; + + for (i = 0; i < height; i++) { + memcpy(dst, src, s_pitches); + src += s_pitches; + dst += d_pitches; + } + } + + return dst; +} + +void * +exynosUtilCopyImage(int width, int height, + char *s, int s_size_w, int s_size_h, + int *s_pitches, int *s_offsets, int *s_lengths, + char *d, int d_size_w, int d_size_h, + int *d_pitches, int *d_offsets, int *d_lengths, + int channel, int h_sampling, int v_sampling) +{ + int i; + + for (i = 0; i < channel; i++) { + int c_width = width; + int c_height = height; + + if (i > 0) { + c_width = c_width / h_sampling; + c_height = c_height / v_sampling; + } + + _copy_one_channel(c_width, c_height, + s, s_size_w, s_pitches[i], d, d_size_w, d_pitches[i]); + + s = s + s_lengths[i]; + d = d + d_lengths[i]; + } + + return d; +} + +/* + * RR_Rotate_90: Target turns to 90. UI turns to 270. + * RR_Rotate_270: Target turns to 270. UI turns to 90. + * + * [Target] ---------- + * | | + * Top (RR_Rotate_90) | | Top (RR_Rotate_270) + * | | + * ---------- + * [UI,FIMC] ---------- + * | | + * Top (degree: 270) | | Top (degree: 90) + * | | + * ---------- + */ +void +exynosUtilRotateArea(int *width, int *height, xRectangle *rect, int degree) +{ +// int old_w, old_h; + + XDBG_RETURN_IF_FAIL(width != NULL); + XDBG_RETURN_IF_FAIL(height != NULL); + XDBG_RETURN_IF_FAIL(rect != NULL); + + if (degree == 0) + return; + + exynosUtilRotateRect(*width, *height, rect, degree); + +// old_w = *width; +// old_h = *height; + + if (degree % 180) + SWAP(*width, *height); + +// ErrorF ("%d: (%dx%d) => (%dx%d)\n", degree, old_w, old_h, *width, *height); +} + +void +exynosUtilRotateRect2(int width, int height, xRectangle *rect, int degree, + const char *func) +{ + xRectangle new_rect = { 0, }; + + XDBG_RETURN_IF_FAIL(rect != NULL); + + if (degree == 0) + return; + + degree = (degree + 360) % 360; + + switch (degree) { + case 90: + new_rect.x = height - (rect->y + rect->height); + new_rect.y = rect->x; + new_rect.width = rect->height; + new_rect.height = rect->width; + break; + case 180: + new_rect.x = width - (rect->x + rect->width); + new_rect.y = height - (rect->y + rect->height); + new_rect.width = rect->width; + new_rect.height = rect->height; + break; + case 270: + new_rect.x = rect->y; + new_rect.y = width - (rect->x + rect->width); + new_rect.width = rect->height; + new_rect.height = rect->width; + break; + } + +// ErrorF ("%d: %dx%d (%d,%d %dx%d) => (%d,%d %dx%d) %s\n", +// degree, width, height, +// rect->x, rect->y, rect->width, rect->height, +// new_rect.x, new_rect.y, new_rect.width, new_rect.height, func); + + *rect = new_rect; +} + +void +exynosUtilRotateRegion(int width, int height, RegionPtr region, int degree) +{ + RegionRec new_region; + int nbox; + BoxPtr pBox; + + if (!region) + return; + + nbox = RegionNumRects(region); + pBox = RegionRects(region); + + if (nbox == 0) + return; + + RegionInit(&new_region, NULL, 0); + + while (nbox--) { + if (pBox) { + xRectangle temp; + RegionPtr temp_region; + + temp.x = pBox->x1; + temp.y = pBox->y1; + temp.width = pBox->x2 - pBox->x1; + temp.height = pBox->y2 - pBox->y1; + exynosUtilRotateRect(width, height, &temp, degree); + temp_region = RegionFromRects(1, &temp, 0); + RegionUnion(&new_region, &new_region, temp_region); + RegionDestroy(temp_region); + } + + pBox++; + } + + RegionCopy(region, &new_region); + RegionUninit(&new_region); +} + +void +exynosUtilAlignRect(int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, + Bool hw) +{ + int fit_width; + int fit_height; + float rw, rh, max; + + if (!fit) + return; + + XDBG_RETURN_IF_FAIL(src_w > 0 && src_h > 0); + XDBG_RETURN_IF_FAIL(dst_w > 0 && dst_h > 0); + + rw = (float) src_w / dst_w; + rh = (float) src_h / dst_h; + max = MAX(rw, rh); + + fit_width = src_w / max; + fit_height = src_h / max; + + if (hw) + fit_width &= (~0x3); + + fit->x = (dst_w - fit_width) / 2; + fit->y = (dst_h - fit_height) / 2; + fit->width = fit_width; + fit->height = fit_height; +} + +void +exynosUtilScaleRect(int src_w, int src_h, int dst_w, int dst_h, + xRectangle *scale) +{ + float ratio; + xRectangle fit; + + XDBG_RETURN_IF_FAIL(scale != NULL); + XDBG_RETURN_IF_FAIL(src_w > 0 && src_h > 0); + XDBG_RETURN_IF_FAIL(dst_w > 0 && dst_h > 0); + + if ((src_w == dst_w) && (src_h == dst_h)) + return; + + exynosUtilAlignRect(src_w, src_h, dst_w, dst_h, &fit, FALSE); + + ratio = (float) fit.width / src_w; + + scale->x = scale->x * ratio + fit.x; + scale->y = scale->y * ratio + fit.y; + scale->width = scale->width * ratio; + scale->height = scale->height * ratio; +} + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1, r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* true iff (x,y) is in Box */ +#define INBOX(r, x, y) \ + ( ((r)->x2 > x) && \ + ((r)->x1 <= x) && \ + ((r)->y2 > y) && \ + ((r)->y1 <= y) ) + +/* true iff Box r1 contains Box r2 */ +#define SUBSUMES(r1, r2) \ + ( ((r1)->x1 <= (r2)->x1) && \ + ((r1)->x2 >= (r2)->x2) && \ + ((r1)->y1 <= (r2)->y1) && \ + ((r1)->y2 >= (r2)->y2) ) + +int +exynosUtilBoxInBox(BoxPtr base, BoxPtr box) +{ + XDBG_RETURN_VAL_IF_FAIL(base != NULL, -1); + XDBG_RETURN_VAL_IF_FAIL(box != NULL, -1); + + if (base->x1 == box->x1 && base->y1 == box->y1 && base->x2 == box->x2 && + base->y2 == box->y2) { + return rgnSAME; + } + else if (SUBSUMES(base, box)) { + return rgnIN; + } + else if (EXTENTCHECK(base, box)) { + return rgnPART; + } + else + return rgnOUT; + + return -1; +} + +int +exynosUtilBoxArea(BoxPtr pBox) +{ + return (int) (pBox->x2 - pBox->x1) * (int) (pBox->y2 - pBox->y1); +} + +int +exynosUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2) +{ + pDstBox->x1 = pBox1->x1 > pBox2->x1 ? pBox1->x1 : pBox2->x1; + pDstBox->x2 = pBox1->x2 < pBox2->x2 ? pBox1->x2 : pBox2->x2; + pDstBox->y1 = pBox1->y1 > pBox2->y1 ? pBox1->y1 : pBox2->y1; + pDstBox->y2 = pBox1->y2 < pBox2->y2 ? pBox1->y2 : pBox2->y2; + + if (pDstBox->x1 >= pDstBox->x2 || pDstBox->y1 >= pDstBox->y2) { + pDstBox->x1 = 0; + pDstBox->x2 = 0; + pDstBox->y1 = 0; + pDstBox->y2 = 0; + return rgnOUT; + } + + if (pDstBox->x1 == pBox2->x1 && + pDstBox->y1 == pBox2->y1 && + pDstBox->x2 == pBox2->x2 && pDstBox->y2 == pBox2->y2) + return rgnIN; + + return rgnPART; +} + +void +exynosUtilBoxMove(BoxPtr pBox, int dx, int dy) +{ + if (dx == 0 && dy == 0) + return; + + pBox->x1 += dx; + pBox->x2 += dx; + pBox->y1 += dy; + pBox->y2 += dy; +} + +Bool +exynosUtilRectIntersect(xRectanglePtr pDest, xRectanglePtr pRect1, + xRectanglePtr pRect2) +{ + int dest_x, dest_y; + int dest_x2, dest_y2; + + if (!pDest) + return FALSE; + + dest_x = MAX(pRect1->x, pRect2->x); + dest_y = MAX(pRect1->y, pRect2->y); + dest_x2 = MIN(pRect1->x + pRect1->width, pRect2->x + pRect2->width); + dest_y2 = MIN(pRect1->y + pRect1->height, pRect2->y + pRect2->height); + + if (dest_x2 > dest_x && dest_y2 > dest_y) { + pDest->x = dest_x; + pDest->y = dest_y; + pDest->width = dest_x2 - dest_x; + pDest->height = dest_y2 - dest_y; + } + else { + pDest->width = 0; + pDest->height = 0; + } + + return TRUE; +} + +void +exynosUtilSaveImage(pixman_image_t * image, char *path) +{ + void *data; + int width, height; + + XDBG_RETURN_IF_FAIL(image != NULL); + XDBG_RETURN_IF_FAIL(path != NULL); + + width = pixman_image_get_width(image); + height = pixman_image_get_height(image); + + data = pixman_image_get_data(image); + XDBG_RETURN_IF_FAIL(data != NULL); + + exynosUtilDumpBmp(path, data, width, height); +} + +Bool +exynosUtilConvertImage(pixman_op_t op, uchar * srcbuf, uchar * dstbuf, + pixman_format_code_t src_format, + pixman_format_code_t dst_format, int sw, int sh, + xRectangle *sr, int dw, int dh, xRectangle *dr, + RegionPtr dst_clip_region, int rotate, int hflip, + int vflip) +{ + pixman_image_t *src_img; + pixman_image_t *dst_img; + int src_stride, dst_stride; + int src_bpp; + int dst_bpp; + double scale_x, scale_y; + int rotate_step; + int ret = FALSE; + pixman_transform_t t; + struct pixman_f_transform ft; + + src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8; + XDBG_RETURN_VAL_IF_FAIL(src_bpp > 0, FALSE); + + dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8; + XDBG_RETURN_VAL_IF_FAIL(dst_bpp > 0, FALSE); + + src_stride = sw * src_bpp; + dst_stride = dw * dst_bpp; + + src_img = pixman_image_create_bits(src_format, sw, sh, + (uint32_t *) srcbuf, src_stride); + dst_img = pixman_image_create_bits(dst_format, dw, dh, + (uint32_t *) dstbuf, dst_stride); + + XDBG_GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT); + XDBG_GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT); + + pixman_f_transform_init_identity(&ft); + + if (hflip) { + pixman_f_transform_scale(&ft, NULL, -1, 1); + pixman_f_transform_translate(&ft, NULL, dr->width, 0); + } + + if (vflip) { + pixman_f_transform_scale(&ft, NULL, 1, -1); + pixman_f_transform_translate(&ft, NULL, 0, dr->height); + } + + rotate_step = (rotate + 360) / 90 % 4; + + if (rotate_step > 0) { + int c, s, tx = 0, ty = 0; + + switch (rotate_step) { + case 1: + /* 90 degrees */ + c = 0; + s = -1; + tx = -dr->width; + break; + case 2: + /* 180 degrees */ + c = -1; + s = 0; + tx = -dr->width; + ty = -dr->height; + break; + case 3: + /* 270 degrees */ + c = 0; + s = 1; + ty = -dr->height; + break; + default: + /* 0 degrees */ + c = 0; + s = 0; + break; + } + + pixman_f_transform_translate(&ft, NULL, tx, ty); + pixman_f_transform_rotate(&ft, NULL, c, s); + } + + if (rotate_step % 2 == 0) { + scale_x = (double) sr->width / dr->width; + scale_y = (double) sr->height / dr->height; + } + else { + scale_x = (double) sr->width / dr->height; + scale_y = (double) sr->height / dr->width; + } + + pixman_f_transform_scale(&ft, NULL, scale_x, scale_y); + pixman_f_transform_translate(&ft, NULL, sr->x, sr->y); + + pixman_transform_from_pixman_f_transform(&t, &ft); + pixman_image_set_transform(src_img, &t); + + pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, + dr->x, dr->y, dr->width, dr->height); + + ret = TRUE; + + CANT_CONVERT: + if (src_img) + pixman_image_unref(src_img); + if (dst_img) + pixman_image_unref(dst_img); + + return ret; +} + +void +exynosUtilFreeHandle(ScrnInfoPtr scrn, uint32_t handle) +{ + struct drm_gem_close close; + EXYNOSPtr pExynos; + + XDBG_RETURN_IF_FAIL(scrn != NULL); + + pExynos = EXYNOSPTR(scrn); + + CLEAR(close); + close.handle = handle; + if (drmIoctl(pExynos->drm_fd, DRM_IOCTL_GEM_CLOSE, &close)) { + XDBG_ERRNO(MSEC, "DRM_IOCTL_GEM_CLOSE failed.\n"); + } +} + +#ifdef LEGACY_INTERFACE +Bool +exynosUtilConvertPhyaddress(ScrnInfoPtr scrn, unsigned int phy_addr, int size, + unsigned int *handle) +{ + struct drm_exynos_gem_phy_imp phy_imp = { 0, }; + EXYNOSPtr pExynos; + + XDBG_RETURN_VAL_IF_FAIL(scrn != NULL, FALSE); + + if (!phy_addr || size <= 0 || !handle) + return FALSE; + + pExynos = EXYNOSPTR(scrn); + phy_imp.phy_addr = (unsigned long) phy_addr; + phy_imp.size = (unsigned long) size; + + if (pExynos->drm_fd) + if (ioctl(pExynos->drm_fd, DRM_IOCTL_EXYNOS_GEM_PHY_IMP, &phy_imp) < 0) { + XDBG_ERRNO(MSEC, "DRM_IOCTL_EXYNOS_GEM_PHY_IMP failed. %p(%d)\n", + (void *) phy_addr, size); + return FALSE; + } + + *handle = phy_imp.gem_handle; + + return TRUE; +} + +Bool +exynosUtilConvertHandle(ScrnInfoPtr scrn, unsigned int handle, + unsigned int *phy_addr, int *size) +{ + struct drm_exynos_gem_get_phy get_phy; + EXYNOSPtr pExynos; + + XDBG_RETURN_VAL_IF_FAIL(scrn != NULL, FALSE); + + if (handle == 0 || (!phy_addr && !size)) + return FALSE; + + pExynos = EXYNOSPTR(scrn); + memset(&get_phy, 0, sizeof(struct drm_exynos_gem_get_phy)); + get_phy.gem_handle = handle; + + if (pExynos->drm_fd) + if (ioctl(pExynos->drm_fd, DRM_IOCTL_EXYNOS_GEM_GET_PHY, &get_phy) < 0) { + XDBG_DEBUG(MLYR, + "DRM_IOCTL_EXYNOS_GEM_GET_PHY failed. (%d)(%s,%d)\n", + handle, strerror(errno), errno); + return FALSE; + } + + if (phy_addr) + *phy_addr = (unsigned int) get_phy.phy_addr; + + if (size) + *size = (int) ((unsigned int) get_phy.size); + + return TRUE; +} +#endif + +typedef struct _ListData { + void *key; + uniType data; + + struct xorg_list link; +} ListData; + +static ListData * +_exynosUtilListGet(void *list, void *key) +{ + ListData *data = NULL, *next = NULL; + + if (!list) + return NULL; + + xorg_list_for_each_entry_safe(data, next, (struct xorg_list *) list, link) { + if (data->key == key) + return data; + } + return NULL; +} + +void * +exynosUtilListAdd(void *list, void *key, uniType user_data) +{ + ListData *data; + int list_flag = 0; + + XDBG_RETURN_VAL_IF_FAIL(key != NULL, NULL); + + if (!list) { + list = calloc(sizeof(struct xorg_list), 1); + XDBG_GOTO_IF_FAIL(list != NULL, fail); + xorg_list_init((struct xorg_list *) list); + list_flag = 1; + } + + if (_exynosUtilListGet(list, key)) + return list; + + data = malloc(sizeof(ListData)); + XDBG_GOTO_IF_FAIL(data != NULL, fail); + + data->key = key; + data->data = user_data; + + xorg_list_add(&data->link, (struct xorg_list *) list); + + return list; + + fail: + if (list_flag && list) + free(list); + + return NULL; +} + +void * +exynosUtilListRemove(void *list, void *key) +{ + ListData *data; + + XDBG_RETURN_VAL_IF_FAIL(key != NULL, NULL); + + data = _exynosUtilListGet(list, key); + if (data) { + xorg_list_del(&data->link); + free(data); + + if (xorg_list_is_empty((struct xorg_list *) list)) { + free(list); + return NULL; + } + } + + return list; +} + +uniType +exynosUtilListGetData(void *list, void *key) +{ + ListData *data; + uniType ret = { 0 }; + XDBG_RETURN_VAL_IF_FAIL(key != NULL, ret); + + data = _exynosUtilListGet(list, key); + if (data) + ret = data->data; + + return ret; +} + +Bool +exynosUtilListIsEmpty(void *list) +{ + if (!list) + return FALSE; + + return xorg_list_is_empty((struct xorg_list *) list); +} + +void +exynosUtilListDestroyData(void *list, DestroyDataFunc func, void *func_data) +{ + ListData *cur = NULL, *next = NULL; + struct xorg_list *l; + + if (!list || !func) + return; + + l = (struct xorg_list *) list; + xorg_list_for_each_entry_safe(cur, next, l, link) { + func(func_data, cur->data); + } +} + +void +exynosUtilListDestroy(void *list) +{ + ListData *data = NULL, *next = NULL; + struct xorg_list *l; + + if (!list) + return; + + l = (struct xorg_list *) list; + xorg_list_for_each_entry_safe(data, next, l, link) { + xorg_list_del(&data->link); + free(data); + } + + free(list); +} + +Bool +exynosUtilSetDrmProperty(EXYNOSModePtr pExynosMode, unsigned int obj_id, + unsigned int obj_type, const char *prop_name, + unsigned int value) +{ + drmModeObjectPropertiesPtr props; + unsigned int i; + + XDBG_RETURN_VAL_IF_FAIL(pExynosMode != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(obj_id > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(obj_type > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(prop_name != NULL, FALSE); + + props = drmModeObjectGetProperties(pExynosMode->fd, obj_id, obj_type); + if (!props) { + XDBG_ERRNO(MPLN, "fail : drmModeObjectGetProperties.\n"); + return FALSE; + } + + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop = + drmModeGetProperty(pExynosMode->fd, props->props[i]); + int ret; + + if (!prop) { + XDBG_ERRNO(MPLN, "fail : drmModeGetProperty.\n"); + drmModeFreeObjectProperties(props); + return FALSE; + } + + if (!strcmp(prop->name, prop_name)) { + ret = + drmModeObjectSetProperty(pExynosMode->fd, obj_id, obj_type, + prop->prop_id, value); + if (ret < 0) { + XDBG_ERRNO(MPLN, "fail : drmModeObjectSetProperty.\n"); + drmModeFreeProperty(prop); + drmModeFreeObjectProperties(props); + return FALSE; + } + + drmModeFreeProperty(prop); + drmModeFreeObjectProperties(props); + + return TRUE; + } + + drmModeFreeProperty(prop); + } + + XDBG_ERROR(MPLN, "fail : drm set property.\n"); + + drmModeFreeObjectProperties(props); + + return FALSE; +} + +Bool +exynosUtilEnsureExternalCrtc(ScrnInfoPtr scrn) +{ + EXYNOSModePtr pExynosMode; + EXYNOSOutputPrivPtr pOutputPriv = NULL; + + XDBG_RETURN_VAL_IF_FAIL(scrn != NULL, FALSE); + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(scrn)->pExynosMode; + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_HDMI) { + pOutputPriv = + exynosOutputGetPrivateForConnType(scrn, DRM_MODE_CONNECTOR_HDMIA); + if (!pOutputPriv) + pOutputPriv = + exynosOutputGetPrivateForConnType(scrn, + DRM_MODE_CONNECTOR_HDMIB); + } + else + pOutputPriv = + exynosOutputGetPrivateForConnType(scrn, DRM_MODE_CONNECTOR_VIRTUAL); + + XDBG_RETURN_VAL_IF_FAIL(pOutputPriv != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pOutputPriv->mode_encoder != NULL, FALSE); + + if (pOutputPriv->mode_encoder->crtc_id > 0) + return TRUE; + + exynosDisplayDeinitDispMode(scrn); + + return exynosDisplayInitDispMode(scrn, pExynosMode->conn_mode); +} + +typedef struct _VBufFreeFuncInfo { + FreeVideoBufFunc func; + void *data; + struct xorg_list link; +} VBufFreeFuncInfo; + +static EXYNOSFormatTable format_table[] = { + {FOURCC_RGB565, DRM_FORMAT_RGB565, TYPE_RGB}, + {FOURCC_SR16, DRM_FORMAT_RGB565, TYPE_RGB}, +#ifdef LEGACY_INTERFACE + {FOURCC_RGB32, DRM_FORMAT_XRGB8888, TYPE_RGB}, + {FOURCC_SR32, DRM_FORMAT_XRGB8888, TYPE_RGB}, +#else + {FOURCC_RGB32, DRM_FORMAT_ARGB8888, TYPE_RGB}, + {FOURCC_SR32, DRM_FORMAT_ARGB8888, TYPE_RGB}, +#endif + {FOURCC_YV12, DRM_FORMAT_YVU420, TYPE_YUV420}, + {FOURCC_I420, DRM_FORMAT_YUV420, TYPE_YUV420}, + {FOURCC_S420, DRM_FORMAT_YUV420, TYPE_YUV420}, + {FOURCC_ST12, DRM_FORMAT_NV12MT, TYPE_YUV420}, + {FOURCC_SN12, DRM_FORMAT_NV12, TYPE_YUV420}, + {FOURCC_NV12, DRM_FORMAT_NV12, TYPE_YUV420}, + {FOURCC_SN21, DRM_FORMAT_NV21, TYPE_YUV420}, + {FOURCC_NV21, DRM_FORMAT_NV21, TYPE_YUV420}, + {FOURCC_YUY2, DRM_FORMAT_YUYV, TYPE_YUV422}, + {FOURCC_SUYV, DRM_FORMAT_YUYV, TYPE_YUV422}, + {FOURCC_UYVY, DRM_FORMAT_UYVY, TYPE_YUV422}, + {FOURCC_SYVY, DRM_FORMAT_UYVY, TYPE_YUV422}, + {FOURCC_ITLV, DRM_FORMAT_UYVY, TYPE_YUV422}, +}; + +static struct xorg_list vbuf_lists; + +#define VBUF_RETURN_IF_FAIL(cond) \ + {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return; }} +#define VBUF_RETURN_VAL_IF_FAIL(cond, val) \ + {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return val; }} + +static void +_exynosUtilInitVbuf(void) +{ + static Bool init = FALSE; + + if (!init) { + xorg_list_init(&vbuf_lists); + init = TRUE; + } +} + +static void +_exynosUtilYUV420BlackFrame(unsigned char *buf, int buf_size, int width, + int height) +{ + int i; + int y_len = 0; + int yuv_len = 0; + + y_len = width * height; + yuv_len = (width * height * 3) >> 1; + + if (buf_size < yuv_len) + return; + + if (width % 4) { + for (i = 0; i < y_len; i++) + buf[i] = 0x10; + + for (; i < yuv_len; i++) + buf[i] = 0x80; + } + else { + /* faster way */ + int *ibuf = NULL; + short *sbuf = NULL; + + ibuf = (int *) buf; + + for (i = 0; i < y_len / 4; i++) + ibuf[i] = 0x10101010; /* set YYYY */ + + sbuf = (short *) (&buf[y_len]); + + for (i = 0; i < (yuv_len - y_len) / 2; i++) + sbuf[i] = 0x8080; /* set UV */ + } + + return; +} + +static void +_exynosUtilYUV422BlackFrame(int id, unsigned char *buf, int buf_size, int width, + int height) +{ + /* YUYV */ + int i; + int yuv_len = 0; + int *ibuf = NULL; + + ibuf = (int *) buf; + + yuv_len = (width * height * 2); + + if (buf_size < yuv_len) + return; + + for (i = 0; i < yuv_len / 4; i++) + if (id == FOURCC_UYVY || id == FOURCC_SYVY || id == FOURCC_ITLV) + ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */ + else + ibuf[i] = 0x10801080; /* YUYV -> 0xVYUY */ + + return; +} + +static tbm_bo +_exynosUtilAllocNormalBuffer(ScrnInfoPtr scrn, int size, int flags) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + + return tbm_bo_alloc(pExynos->tbm_bufmgr, size, flags); +} + +static tbm_bo +_exynosUtilAllocSecureBuffer(ScrnInfoPtr scrn, int size, int flags) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + struct tzmem_get_region tzmem_get = { 0, }; + struct drm_prime_handle arg_handle = { 0, }; + struct drm_gem_flink arg_flink = { 0, }; + struct drm_gem_close arg_close = { 0, }; + tbm_bo bo = NULL; + int tzmem_fd; + + tzmem_fd = -1; + tzmem_get.fd = -1; + + tzmem_fd = open("/dev/tzmem", O_EXCL); + XDBG_GOTO_IF_FAIL(tzmem_fd >= 0, done_secure_buffer); + + tzmem_get.key = "fimc"; + tzmem_get.size = size; + if (ioctl(tzmem_fd, TZMEM_IOC_GET_TZMEM, &tzmem_get)) { + XDBG_ERRNO(MVBUF, "failed : create tzmem (%d)\n", size); + goto done_secure_buffer; + } + XDBG_GOTO_IF_FAIL(tzmem_get.fd >= 0, done_secure_buffer); + + arg_handle.fd = (__s32) tzmem_get.fd; + if (drmIoctl(pExynos->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg_handle)) { + XDBG_ERRNO(MVBUF, "failed : convert to gem (%d)\n", tzmem_get.fd); + goto done_secure_buffer; + } + XDBG_GOTO_IF_FAIL(arg_handle.handle > 0, done_secure_buffer); + + arg_flink.handle = arg_handle.handle; + if (drmIoctl(pExynos->drm_fd, DRM_IOCTL_GEM_FLINK, &arg_flink)) { + XDBG_ERRNO(MVBUF, "failed : flink gem (%lu)\n", + (unsigned long) arg_handle.handle); + goto done_secure_buffer; + } + XDBG_GOTO_IF_FAIL(arg_flink.name > 0, done_secure_buffer); + + bo = tbm_bo_import(pExynos->tbm_bufmgr, arg_flink.name); + XDBG_GOTO_IF_FAIL(bo != NULL, done_secure_buffer); + + done_secure_buffer: + if (arg_handle.handle > 0) { + arg_close.handle = arg_handle.handle; + if (drmIoctl(pExynos->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg_close)) + XDBG_ERRNO(MVBUF, "failed : close gem (%lu)\n", + (unsigned long) arg_handle.handle); + } + + if (tzmem_get.fd >= 0) + close(tzmem_get.fd); + + if (tzmem_fd >= 0) + close(tzmem_fd); + + return bo; +} + +/* + * # planar # + * format: YV12 Y/V/U 420 + * format: I420 Y/U/V 420 #YU12, S420 + * format: NV12 Y/UV 420 + * format: NV12M Y/UV 420 #SN12 + * format: NV12MT Y/UV 420 #ST12 + * format: NV21 Y/VU 420 + * format: Y444 YUV 444 + * # packed # + * format: YUY2 YUYV 422 #YUYV, SUYV, SUY2 + * format: YVYU YVYU 422 + * format: UYVY UYVY 422 #SYVY + */ +G2dColorMode +exynosUtilGetG2dFormat(unsigned int id) +{ + G2dColorMode g2dfmt = 0; + + switch (id) { + case FOURCC_NV12: + case FOURCC_SN12: + g2dfmt = + G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CrCb; + break; + case FOURCC_NV21: + case FOURCC_SN21: + g2dfmt = + G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CbCr; + break; + case FOURCC_SUYV: + case FOURCC_YUY2: + g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_Y1CbY0Cr; + break; + case FOURCC_SYVY: + case FOURCC_UYVY: + g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_CbY1CrY0; + break; + case FOURCC_SR16: + case FOURCC_RGB565: + g2dfmt = G2D_COLOR_FMT_RGB565 | G2D_ORDER_AXRGB; + break; + case FOURCC_SR32: + case FOURCC_RGB32: + g2dfmt = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; + break; + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_S420: + case FOURCC_ITLV: + case FOURCC_ST12: + default: + XDBG_NEVER_GET_HERE(MVA); + return 0; + } + + return g2dfmt; +} + +unsigned int +exynosUtilGetDrmFormat(unsigned int id) +{ + int i, size; + + size = sizeof(format_table) / sizeof(EXYNOSFormatTable); + + for (i = 0; i < size; i++) + if (format_table[i].id == id) + return format_table[i].drmfmt; + + return 0; +} + +EXYNOSFormatType +exynosUtilGetColorType(unsigned int id) +{ + int i, size; + + size = sizeof(format_table) / sizeof(EXYNOSFormatTable); + + for (i = 0; i < size; i++) + if (format_table[i].id == id) + return format_table[i].type; + + return TYPE_NONE; +} + +static EXYNOSVideoBuf * +_findVideoBuffer(uintptr_t stamp) +{ + EXYNOSVideoBuf *cur = NULL, *next = NULL; + + _exynosUtilInitVbuf(); + + if (!vbuf_lists.next) + return NULL; + + xorg_list_for_each_entry_safe(cur, next, &vbuf_lists, valid_link) { + if (cur->stamp == stamp) + return cur; + } + + return NULL; +} + +EXYNOSVideoBuf * +_exynosUtilAllocVideoBuffer(ScrnInfoPtr scrn, int id, int width, int height, + Bool scanout, Bool reset, Bool exynosure, + const char *func) +{ + EXYNOSPtr pExynos = EXYNOSPTR(scrn); + EXYNOSVideoBuf *vbuf = NULL; + int flags = 0; + int i; + tbm_bo_handle bo_handle; + uintptr_t stamp; + + XDBG_RETURN_VAL_IF_FAIL(scrn != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(id > 0, NULL); + XDBG_RETURN_VAL_IF_FAIL(width > 0, NULL); + XDBG_RETURN_VAL_IF_FAIL(height > 0, NULL); + + vbuf = calloc(1, sizeof(EXYNOSVideoBuf)); + XDBG_GOTO_IF_FAIL(vbuf != NULL, alloc_fail); + + vbuf->ref_cnt = 1; + + vbuf->pScrn = scrn; + vbuf->id = id; + vbuf->width = width; + vbuf->height = height; + vbuf->crop.width = width; + vbuf->crop.height = height; + + vbuf->size = exynosVideoQueryImageAttrs(scrn, id, &width, &height, + vbuf->pitches, vbuf->offsets, + vbuf->lengths); + XDBG_GOTO_IF_FAIL(vbuf->size > 0, alloc_fail); + + for (i = 0; i < PLANAR_CNT; i++) { + int alloc_size = 0; + + if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12) { + alloc_size = vbuf->lengths[i]; + vbuf->offsets[i] = 0; + } + else if (i == 0) + alloc_size = vbuf->size; + + if (alloc_size <= 0) + continue; + + /* if i > 1, do check. */ + if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12) { + XDBG_GOTO_IF_FAIL(i <= 1, alloc_fail); + } + else + XDBG_GOTO_IF_FAIL(i == 0, alloc_fail); + + if (scanout) + flags = TBM_BO_SCANOUT | TBM_BO_WC; + else if (!pExynos->cachable) + flags = TBM_BO_WC; + else + flags = TBM_BO_DEFAULT; + + if (!exynosure) + vbuf->bo[i] = _exynosUtilAllocNormalBuffer(scrn, alloc_size, flags); + else + vbuf->bo[i] = _exynosUtilAllocSecureBuffer(scrn, alloc_size, flags); + XDBG_GOTO_IF_FAIL(vbuf->bo[i] != NULL, alloc_fail); + + vbuf->keys[i] = tbm_bo_export(vbuf->bo[i]); + XDBG_GOTO_IF_FAIL(vbuf->keys[i] > 0, alloc_fail); + + bo_handle = tbm_bo_get_handle(vbuf->bo[i], TBM_DEVICE_DEFAULT); + vbuf->handles[i] = bo_handle.u32; + XDBG_GOTO_IF_FAIL(vbuf->handles[i] > 0, alloc_fail); + +#ifdef LEGACY_INTERFACE + if (scanout) + exynosUtilConvertHandle(scrn, vbuf->handles[i], &vbuf->phy_addrs[i], + NULL); +#endif + + XDBG_DEBUG(MVBUF, "handle(%d) => phy_addrs(%d) \n", vbuf->handles[i], + vbuf->phy_addrs[i]); + } + + if (reset) + exynosUtilClearVideoBuffer(vbuf); + + vbuf->exynosure = exynosure; + vbuf->dirty = TRUE; + + xorg_list_init(&vbuf->convert_info); + xorg_list_init(&vbuf->free_funcs); + + _exynosUtilInitVbuf(); + xorg_list_add(&vbuf->valid_link, &vbuf_lists); + + stamp = (uintptr_t) GetTimeInMillis(); + while (_findVideoBuffer(stamp)) + stamp++; + vbuf->stamp = stamp; + + vbuf->func = strdup(func); + vbuf->flags = flags; + vbuf->scanout = scanout; + vbuf->vblank_handler = NULL; + vbuf->vblank_user_data = NULL; + + XDBG_DEBUG(MVBUF, "%" PRIuPTR " alloc(flags:%x, scanout:%d): %s\n", + vbuf->stamp, flags, scanout, func); + + return vbuf; + + alloc_fail: + if (vbuf) { + for (i = 0; i < PLANAR_CNT && vbuf->bo[i]; i++) + tbm_bo_unref(vbuf->bo[i]); + + free(vbuf); + } + + return NULL; +} + +EXYNOSVideoBuf * +_exynosUtilCreateVideoBuffer(ScrnInfoPtr scrn, int id, int width, int height, + Bool exynosure, const char *func) +{ + EXYNOSVideoBuf *vbuf = NULL; + uintptr_t stamp; + + XDBG_RETURN_VAL_IF_FAIL(scrn != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(id > 0, NULL); + XDBG_RETURN_VAL_IF_FAIL(width > 0, NULL); + XDBG_RETURN_VAL_IF_FAIL(height > 0, NULL); + + vbuf = calloc(1, sizeof(EXYNOSVideoBuf)); + XDBG_GOTO_IF_FAIL(vbuf != NULL, alloc_fail); + + vbuf->ref_cnt = 1; + + vbuf->pScrn = scrn; + vbuf->id = id; + vbuf->width = width; + vbuf->height = height; + vbuf->crop.width = width; + vbuf->crop.height = height; + + vbuf->size = exynosVideoQueryImageAttrs(scrn, id, &width, &height, + vbuf->pitches, vbuf->offsets, + vbuf->lengths); + XDBG_GOTO_IF_FAIL(vbuf->size > 0, alloc_fail); + + vbuf->exynosure = exynosure; + + xorg_list_init(&vbuf->convert_info); + xorg_list_init(&vbuf->free_funcs); + + _exynosUtilInitVbuf(); + xorg_list_add(&vbuf->valid_link, &vbuf_lists); + + stamp = (uintptr_t) GetTimeInMillis(); + while (_findVideoBuffer(stamp)) + stamp++; + vbuf->stamp = stamp; + + vbuf->func = strdup(func); + vbuf->flags = -1; + vbuf->vblank_handler = NULL; + vbuf->vblank_user_data = NULL; + + XDBG_DEBUG(MVBUF, "%" PRIuPTR " create: %s\n", vbuf->stamp, func); + + return vbuf; + + alloc_fail: + if (vbuf) + exynosUtilFreeVideoBuffer(vbuf); + + return NULL; +} + +EXYNOSVideoBuf * +_exynosUtilVideoBufferRef(EXYNOSVideoBuf * vbuf, const char *func) +{ + if (!vbuf) + return NULL; + + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(vbuf), NULL); + + vbuf->ref_cnt++; + XDBG_DEBUG(MVBUF, "%ld ref(%d) %s\n", vbuf->stamp, vbuf->ref_cnt, func); + + return vbuf; +} + +EXYNOSVideoBuf * +exynosUtilCreateVideoBufferByDraw(DrawablePtr pDraw) +{ + EXYNOSVideoBuf *vbuf = NULL; + PixmapPtr pPixmap = NULL; + tbm_bo_handle bo_handle; + EXYNOSPixmapPriv *privPixmap; + Bool need_finish = FALSE; + + XDBG_GOTO_IF_FAIL(pDraw != NULL, fail_get); + + if (pDraw->type == DRAWABLE_WINDOW) + pPixmap = pDraw->pScreen->GetWindowPixmap((WindowPtr) pDraw); + else + pPixmap = (PixmapPtr) pDraw; + XDBG_GOTO_IF_FAIL(pPixmap != NULL, fail_get); + + privPixmap = exaGetPixmapDriverPrivate(pPixmap); + XDBG_GOTO_IF_FAIL(privPixmap != NULL, fail_get); + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(privPixmap->bo != NULL, fail_get); + } + + /* + * Xserver or DDX can create a buffer object and pitch for an any drawable + * bigger then user has requested for improvement performance or + * for something else (it depends). So a video buffer width should depend + * on a pitch of a pixmap but not width. + */ + int width = pPixmap->devKind / (pPixmap->drawable.bitsPerPixel >> 3); + + vbuf = + exynosUtilCreateVideoBuffer(exynosUtilDrawToScrn(pDraw), FOURCC_RGB32, + width, pPixmap->drawable.height, FALSE); + + XDBG_GOTO_IF_FAIL(vbuf != NULL, fail_get); + + vbuf->bo[0] = NULL; + bo_handle = tbm_bo_get_handle(privPixmap->bo, TBM_DEVICE_DEFAULT); + vbuf->handles[0] = bo_handle.u32; + vbuf->keys[0] = tbm_bo_export(privPixmap->bo); + + XDBG_DEBUG(MVBUF, + "draw:%dx%d+%d+%d; pix:%dx%d+%d+%d: vbuff->pitche:%d: pPixmap->devKind:%d\n", + pDraw->width, pDraw->height, pDraw->x, pDraw->y, + pPixmap->drawable.width, pPixmap->drawable.height, + pPixmap->drawable.x, pPixmap->drawable.y, vbuf->pitches[0], + pPixmap->devKind); + + /* + * If "bo" has "bo_user_data" we should use fb_id from it, + * otherwise fb will be created later after the exynosLayerSetVbuf() will be called. + */ + EXYNOSFbBoDataPtr bo_data = NULL; + + int ret = tbm_bo_get_user_data(privPixmap->bo, TBM_BO_DATA_FB, + (void * *) &bo_data); + + if (ret && bo_data != NULL) { + vbuf->fb_id = bo_data->fb_id; + vbuf->fb_id_external = TRUE; + } + + if (need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + XDBG_GOTO_IF_FAIL(vbuf->handles[0] > 0, fail_get); + + return vbuf; + + fail_get: + if (pPixmap && need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + if (vbuf) + exynosUtilVideoBufferUnref(vbuf); + + return NULL; +} + +void +_exynosUtilVideoBufferUnref(EXYNOSVideoBuf * vbuf, const char *func) +{ + if (!vbuf) + return; + + VBUF_RETURN_IF_FAIL(_exynosUtilIsVbufValid(vbuf, func)); + + XDBG_DEBUG(MVBUF, "%ld unref(cnt:%d): %s\n", vbuf->stamp, vbuf->ref_cnt, + func); + + vbuf->ref_cnt--; + if (vbuf->ref_cnt == 0) + _exynosUtilFreeVideoBuffer(vbuf, func); +} + +void +_exynosUtilFreeVideoBuffer(EXYNOSVideoBuf * vbuf, const char *func) +{ + VBufFreeFuncInfo *cur = NULL, *next = NULL; + int i; + + if (!vbuf) + return; + + VBUF_RETURN_IF_FAIL(_exynosUtilIsVbufValid(vbuf, func)); + VBUF_RETURN_IF_FAIL(!VBUF_IS_CONVERTING(vbuf)); + VBUF_RETURN_IF_FAIL(vbuf->showing == FALSE); + + xorg_list_for_each_entry_safe(cur, next, &vbuf->free_funcs, link) { + /* call before tmb_bo_unref and drmModeRmFB. */ + if (cur->func) + cur->func(vbuf, cur->data); + xorg_list_del(&cur->link); + free(cur); + } + + for (i = 0; i < PLANAR_CNT; i++) { + if (vbuf->bo[i]) + tbm_bo_unref(vbuf->bo[i]); + } + + if (vbuf->fb_id > 0 && !vbuf->fb_id_external) { + XDBG_DEBUG(MVBUF, "vbuf(%" PRIuPTR ") fb_id(%" PRIdPTR ") removed. \n", + vbuf->stamp, vbuf->fb_id); + drmModeRmFB(EXYNOSPTR(vbuf->pScrn)->drm_fd, vbuf->fb_id); + } + + xorg_list_del(&vbuf->valid_link); + + XDBG_DEBUG(MVBUF, "%" PRIuPTR " freed: %s\n", vbuf->stamp, func); + + vbuf->stamp = 0; + + if (vbuf->func) + free(vbuf->func); + + free(vbuf); +} + +static void +_exynosUtilClearNormalVideoBuffer(EXYNOSVideoBuf * vbuf) +{ + int i; + tbm_bo_handle bo_handle; + + if (!vbuf) + return; + + for (i = 0; i < PLANAR_CNT; i++) { + int size = 0; + + if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || + vbuf->id == FOURCC_ST12) + size = vbuf->lengths[i]; + else if (i == 0) + size = vbuf->size; + + if (size <= 0 || !vbuf->bo[i]) + continue; + + bo_handle = tbm_bo_map(vbuf->bo[i], TBM_DEVICE_CPU, TBM_OPTION_WRITE); + XDBG_RETURN_IF_FAIL(bo_handle.ptr != NULL); + + if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || + vbuf->id == FOURCC_ST12) { + if (i == 0) + memset(bo_handle.ptr, 0x10, size); + else if (i == 1) + memset(bo_handle.ptr, 0x80, size); + } + else { + int type = exynosUtilGetColorType(vbuf->id); + + if (type == TYPE_YUV420) + _exynosUtilYUV420BlackFrame(bo_handle.ptr, size, vbuf->width, + vbuf->height); + else if (type == TYPE_YUV422) + _exynosUtilYUV422BlackFrame(vbuf->id, bo_handle.ptr, size, + vbuf->width, vbuf->height); + else if (type == TYPE_RGB) + memset(bo_handle.ptr, 0, size); + else + XDBG_NEVER_GET_HERE(MSEC); + } + + tbm_bo_unmap(vbuf->bo[i]); + } + + exynosUtilCacheFlush(vbuf->pScrn); +} + +static void +_exynosUtilClearSecureVideoBuffer(EXYNOSVideoBuf * vbuf) +{ +} + +void +exynosUtilClearVideoBuffer(EXYNOSVideoBuf * vbuf) +{ + if (!vbuf) + return; + + if (!vbuf->exynosure) + _exynosUtilClearNormalVideoBuffer(vbuf); + else + _exynosUtilClearSecureVideoBuffer(vbuf); + + vbuf->dirty = FALSE; + vbuf->need_reset = FALSE; +} + +Bool +_exynosUtilIsVbufValid(EXYNOSVideoBuf * vbuf, const char *func) +{ + EXYNOSVideoBuf *cur = NULL, *next = NULL; + + _exynosUtilInitVbuf(); + + VBUF_RETURN_VAL_IF_FAIL(vbuf != NULL, FALSE); + VBUF_RETURN_VAL_IF_FAIL(vbuf->stamp != 0, FALSE); + + xorg_list_for_each_entry_safe(cur, next, &vbuf_lists, valid_link) { + if (cur->stamp == vbuf->stamp) + return TRUE; + } + + return FALSE; +} + +static VBufFreeFuncInfo * +_exynosUtilFindFreeVideoBufferFunc(EXYNOSVideoBuf * vbuf, FreeVideoBufFunc func, + void *data) +{ + VBufFreeFuncInfo *cur = NULL, *next = NULL; + + xorg_list_for_each_entry_safe(cur, next, &vbuf->free_funcs, link) { + if (cur->func == func && cur->data == data) + return cur; + } + + return NULL; +} + +void +exynosUtilAddFreeVideoBufferFunc(EXYNOSVideoBuf * vbuf, FreeVideoBufFunc func, + void *data) +{ + VBufFreeFuncInfo *info; + + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(vbuf)); + XDBG_RETURN_IF_FAIL(func != NULL); + + info = _exynosUtilFindFreeVideoBufferFunc(vbuf, func, data); + if (info) + return; + + info = calloc(1, sizeof(VBufFreeFuncInfo)); + XDBG_RETURN_IF_FAIL(info != NULL); + + info->func = func; + info->data = data; + + xorg_list_add(&info->link, &vbuf->free_funcs); +} + +void +exynosUtilRemoveFreeVideoBufferFunc(EXYNOSVideoBuf * vbuf, + FreeVideoBufFunc func, void *data) +{ + VBufFreeFuncInfo *info; + + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(vbuf)); + XDBG_RETURN_IF_FAIL(func != NULL); + + info = _exynosUtilFindFreeVideoBufferFunc(vbuf, func, data); + if (!info) + return; + + xorg_list_del(&info->link); + + free(info); +} + +char * +exynosUtilDumpVideoBuffer(char *reply, int *len) +{ + EXYNOSVideoBuf *cur = NULL, *next = NULL; + + _exynosUtilInitVbuf(); + + if (xorg_list_is_empty(&vbuf_lists)) + return reply; + + XDBG_REPLY("\nVideo buffers:\n"); + XDBG_REPLY("id\tsize\t\t\tformat\tflags\trefcnt\tsecure\tstamp\tfunc\n"); + + xorg_list_for_each_entry_safe(cur, next, &vbuf_lists, valid_link) { + XDBG_REPLY("%" PRIdPTR "\t(%dx%d,%d)\t%c%c%c%c\t%d\t%d\t%d\t%" PRIuPTR + "\t%s\n", cur->fb_id, cur->width, cur->height, cur->size, + FOURCC_STR(cur->id), cur->flags, cur->ref_cnt, + cur->exynosure, cur->stamp, cur->func); + } + + return reply; +} + +int +findActiveConnector(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr pXf86CrtcConfig; + xf86OutputPtr pOutput; + int actv_connector = -1, i; + + pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR(pScrn); + + for (i = 0; i < pXf86CrtcConfig->num_output; i++) { + if (pXf86CrtcConfig->output[i]->status == XF86OutputStatusConnected) { + pOutput = pXf86CrtcConfig->output[i]; + if (!strcmp(pOutput->name, "LVDS1")) { + actv_connector = DRM_MODE_CONNECTOR_LVDS; + break; + } + else if (!strcmp(pOutput->name, "HDMI1")) { + actv_connector = DRM_MODE_CONNECTOR_HDMIA; + } + else if (!strcmp(pOutput->name, "Virtual1")) { + actv_connector = DRM_MODE_CONNECTOR_VIRTUAL; + } + + } + } + return actv_connector; +} + +ScrnInfoPtr +exynosUtilDrawToScrn(DrawablePtr pDraw) +{ + XDBG_RETURN_VAL_IF_FAIL(pDraw, NULL); + return xf86Screens[pDraw->pScreen->myNum]; +} + +uniType +setunitype32(uint32_t data_u32) +{ + uniType temp = {.u32 = data_u32 }; + return temp; +} diff --git a/src/util/exynos_util.h b/src/util/exynos_util.h new file mode 100644 index 0000000..719e494 --- /dev/null +++ b/src/util/exynos_util.h @@ -0,0 +1,250 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 __SEC_UTIL_H__ +#define __SEC_UTIL_H__ + +#include <fbdevhw.h> +#include <pixman.h> +#include <list.h> +#include <xdbg.h> +#include "fimg2d.h" +#include "xf86.h" +#include "exynos.h" +#include "property.h" +#include "exynos_display.h" +#include "exynos_video_types.h" +#include "exynos_xberc.h" + +#define MFB XDBG_M('F','B',0,0) +#define MDISP XDBG_M('D','I','S','P') +#define MLYR XDBG_M('L','Y','R',0) +#define MPLN XDBG_M('P','L','N',0) +#define MSEC XDBG_M('S','E','C',0) +#define MEXA XDBG_M('E','X','A',0) +#define MEXAS XDBG_M('E','X','A','S') +#define MEVT XDBG_M('E','V','T',0) +#define MDRI2 XDBG_M('D','R','I','2') +#define MDRI3 XDBG_M('D','R','I','3') +#define MCRS XDBG_M('C','R','S',0) +#define MFLIP XDBG_M('F','L','I','P') +#define MDPMS XDBG_M('D','P','M','S') +#define MVDO XDBG_M('V','D','O',0) +#define MDA XDBG_M('D','A',0,0) +#define MTVO XDBG_M('T','V','O',0) +#define MWB XDBG_M('W','B',0,0) +#define MVA XDBG_M('V','A',0,0) +#define MPROP XDBG_M('P','R','O','P') +#define MXBRC XDBG_M('X','B','R','C') +#define MVBUF XDBG_M('V','B','U','F') +#define MDRM XDBG_M('D','R','M',0) +#define MACCE XDBG_M('A','C','C','E') +#define MCVT XDBG_M('C','V','T',0) +#define MEXAH XDBG_M('E','X','A','H') +#define MG2D XDBG_M('G','2','D',0) +#define MDOUT XDBG_M('D','O','T',0) +#define MCLON XDBG_M('C','L','O','N') +#define MHWC XDBG_M('H','W','C',0) +#define MLYRM XDBG_M('L','Y','R','M') +#define MHWA XDBG_M('H','W','A',0) + +#define _XID(win) ((unsigned int)(((WindowPtr)win)->drawable.id)) + +#define UTIL_DUMP_OK 0 +#define UTIL_DUMP_ERR_OPENFILE 1 +#define UTIL_DUMP_ERR_SHMATTACH 2 +#define UTIL_DUMP_ERR_SEGSIZE 3 +#define UTIL_DUMP_ERR_CONFIG 4 +#define UTIL_DUMP_ERR_INTERNAL 5 +#define UTIL_DUMP_ERR_PNG 6 + +#define rgnSAME 3 + +#define DUMP_DIR "/tmp/xdump" + +#ifdef LONG64 +#define PRIXID "u" +#else +#define PRIXID "lu" +#endif + +#define EARLY_ERROR_MSG(ARG...) do { xf86ErrorFVerb ( 0, ##ARG); } while(0) + +typedef union { + void *ptr; + uint32_t u32; + uint64_t u64; +} uniType; + +//int exynosUtilDumpBmp (const char * file, const void * data, int width, int height); +int exynosUtilDumpRaw(const char *file, const void *data, int size); +int exynosUtilDumpShm(int shmid, const void *data, int width, int height); +int exynosUtilDumpPixmap(const char *file, PixmapPtr pPixmap); + +void *exynosUtilPrepareDump(ScrnInfoPtr pScrn, int bo_size, int buf_cnt); +void exynosUtilDoDumpRaws(void *dump, tbm_bo * bo, int *size, int bo_cnt, + const char *file); + +void exynosUtilDoDumpBmps(void *d, tbm_bo bo, int w, int h, xRectangle *crop, + const char *file, const char *dumpType); + +void exynosUtilDoDumpPixmaps(void *d, PixmapPtr pPixmap, const char *file, + const char *dumpType); + +void exynosUtilDoDumpVBuf(void *d, EXYNOSVideoBuf * vbuf, const char *file); +void exynosUtilFlushDump(void *dump); +void exynosUtilFinishDump(void *dump); + +int exynosUtilDegreeToRotate(int degree); +int exynosUtilRotateToDegree(int rotate); +int exynosUtilRotateAdd(int rot_a, int rot_b); + +void exynosUtilCacheFlush(ScrnInfoPtr scrn); + +void *exynosUtilCopyImage(int width, int height, + char *s, int s_size_w, int s_size_h, + int *s_pitches, int *s_offsets, int *s_lengths, + char *d, int d_size_w, int d_size_h, + int *d_pitches, int *d_offsets, int *d_lengths, + int channel, int h_sampling, int v_sampling); + +void exynosUtilRotateArea(int *width, int *height, xRectangle *rect, + int degree); +void exynosUtilRotateRect2(int width, int height, xRectangle *rect, int degree, + const char *func); +#define exynosUtilRotateRect(w,h,r,d) exynosUtilRotateRect2(w,h,r,d,__FUNCTION__) +void exynosUtilRotateRegion(int width, int height, RegionPtr region, + int degree); + +void exynosUtilAlignRect(int src_w, int src_h, int dst_w, int dst_h, + xRectangle *fit, Bool hw); +void exynosUtilScaleRect(int src_w, int src_h, int dst_w, int dst_h, + xRectangle *scale); + +const PropertyPtr exynosUtilGetWindowProperty(WindowPtr pWin, + const char *prop_name); + +int exynosUtilBoxInBox(BoxPtr base, BoxPtr box); +int exynosUtilBoxArea(BoxPtr pBox); +int exynosUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2); +void exynosUtilBoxMove(BoxPtr pBox, int dx, int dy); + +Bool exynosUtilRectIntersect(xRectanglePtr pDest, xRectanglePtr pRect1, + xRectanglePtr pRect2); + +void exynosUtilSaveImage(pixman_image_t * image, char *path); +Bool exynosUtilConvertImage(pixman_op_t op, uchar * srcbuf, uchar * dstbuf, + pixman_format_code_t src_format, + pixman_format_code_t dst_format, int sw, int sh, + xRectangle *sr, int dw, int dh, xRectangle *dr, + RegionPtr dst_clip_region, int rotate, int hflip, + int vflip); + +void exynosUtilConvertBos(ScrnInfoPtr pScrn, int src_id, + tbm_bo src_bo, int sw, int sh, xRectangle *sr, + int sstride, tbm_bo dst_bo, int dw, int dh, + xRectangle *dr, int dstride, Bool composite, + int rotate); + +void exynosUtilFreeHandle(ScrnInfoPtr scrn, uint32_t handle); + +#ifdef LEGACY_INTERFACE +Bool exynosUtilConvertPhyaddress(ScrnInfoPtr scrn, unsigned int phy_addr, + int size, unsigned int *handle); +Bool exynosUtilConvertHandle(ScrnInfoPtr scrn, unsigned int handle, + unsigned int *phy_addr, int *size); +#endif + +typedef void (*DestroyDataFunc) (void *func_data, uniType key_data); + +void *exynosUtilListAdd(void *list, void *key, uniType user_data); +void *exynosUtilListRemove(void *list, void *key); +uniType exynosUtilListGetData(void *list, void *key); +Bool exynosUtilListIsEmpty(void *list); +void exynosUtilListDestroyData(void *list, DestroyDataFunc func, + void *func_data); +void exynosUtilListDestroy(void *list); + +Bool exynosUtilSetDrmProperty(EXYNOSModePtr pExynosMode, unsigned int obj_id, + unsigned int obj_type, const char *prop_name, + unsigned int value); + +Bool exynosUtilEnsureExternalCrtc(ScrnInfoPtr scrn); + +G2dColorMode exynosUtilGetG2dFormat(unsigned int id); +unsigned int exynosUtilGetDrmFormat(unsigned int id); +EXYNOSFormatType exynosUtilGetColorType(unsigned int id); + +EXYNOSVideoBuf *exynosUtilCreateVideoBufferByDraw(DrawablePtr pDraw); +EXYNOSVideoBuf *_exynosUtilAllocVideoBuffer(ScrnInfoPtr scrn, int id, int width, + int height, Bool scanout, + Bool reset, Bool exynosure, + const char *func); +EXYNOSVideoBuf *_exynosUtilCreateVideoBuffer(ScrnInfoPtr scrn, int id, + int width, int height, + Bool exynosure, const char *func); +EXYNOSVideoBuf *_exynosUtilVideoBufferRef(EXYNOSVideoBuf * vbuf, + const char *func); +void _exynosUtilVideoBufferUnref(EXYNOSVideoBuf * vbuf, const char *func); +void _exynosUtilFreeVideoBuffer(EXYNOSVideoBuf * vbuf, const char *func); +void exynosUtilClearVideoBuffer(EXYNOSVideoBuf * vbuf); +Bool _exynosUtilIsVbufValid(EXYNOSVideoBuf * vbuf, const char *func); + +typedef void (*FreeVideoBufFunc) (EXYNOSVideoBuf * vbuf, void *data); +void exynosUtilAddFreeVideoBufferFunc(EXYNOSVideoBuf * vbuf, + FreeVideoBufFunc func, void *data); +void exynosUtilRemoveFreeVideoBufferFunc(EXYNOSVideoBuf * vbuf, + FreeVideoBufFunc func, void *data); + +uniType setunitype32(uint32_t data_u32); + +#define exynosUtilAllocVideoBuffer(s,i,w,h,c,r,d) _exynosUtilAllocVideoBuffer(s,i,w,h,c,r,d,__FUNCTION__) +#define exynosUtilCreateVideoBuffer(s,i,w,h,d) _exynosUtilCreateVideoBuffer(s,i,w,h,d,__FUNCTION__) +#define exynosUtilVideoBufferUnref(v) _exynosUtilVideoBufferUnref(v,__FUNCTION__) +#define exynosUtilVideoBufferRef(v) _exynosUtilVideoBufferRef(v,__FUNCTION__) +#define exynosUtilFreeVideoBuffer(v) _exynosUtilFreeVideoBuffer(v,__FUNCTION__) +#define exynosUtilIsVbufValid(v) _exynosUtilIsVbufValid(v,__FUNCTION__) +#define VBUF_IS_VALID(v) exynosUtilIsVbufValid(v) +#define VSTMAP(v) ((v)?(v)->stamp:0) +#define VBUF_IS_CONVERTING(v) (!xorg_list_is_empty (&((v)->convert_info))) + +int findActiveConnector(ScrnInfoPtr pScrn); + +ScrnInfoPtr exynosUtilDrawToScrn(DrawablePtr pDraw); + +/* for debug */ +char *exynosUtilDumpVideoBuffer(char *reply, int *len); + +#define list_rev_for_each_entry_safe(pos, tmp, head, member) \ + for (pos = __container_of((head)->prev, pos, member), tmp = __container_of(pos->member.prev, pos, member);\ + &pos->member != (head);\ + pos = tmp, tmp = __container_of(pos->member.prev, tmp, member)) + +#endif /* __SEC_UTIL_H__ */ diff --git a/src/util/sec_util.c b/src/util/sec_util.c deleted file mode 100755 index 6f6f747..0000000 --- a/src/util/sec_util.c +++ /dev/null @@ -1,2351 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/shm.h> -#include <sys/ipc.h> -#include <sys/ioctl.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <dirent.h> -#include <X11/XWDFile.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_output.h" -#include "sec_video_fourcc.h" -#include <exynos_drm.h> -#include <list.h> - -#include "fimg2d.h" - -#define DUMP_SCALE_RATIO 2 - -int secUtilDumpBmp (const char * file, const void * data, int width, int height) -{ - int i; - - struct - { - unsigned char magic[2]; - } bmpfile_magic = { {'B', 'M'} }; - - struct - { - unsigned int filesz; - unsigned short creator1; - unsigned short creator2; - unsigned int bmp_offset; - } bmpfile_header = { 0, 0, 0, 0x36 }; - - struct - { - unsigned int header_sz; - unsigned int width; - unsigned int height; - unsigned short nplanes; - unsigned short bitspp; - unsigned int compress_type; - unsigned int bmp_bytesz; - unsigned int hres; - unsigned int vres; - unsigned int ncolors; - unsigned int nimpcolors; - } bmp_dib_v3_header_t = { 0x28, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0 }; - unsigned int * blocks; - - XDBG_RETURN_VAL_IF_FAIL (data != NULL, UTIL_DUMP_ERR_INTERNAL); - XDBG_RETURN_VAL_IF_FAIL (width > 0, UTIL_DUMP_ERR_INTERNAL); - XDBG_RETURN_VAL_IF_FAIL (height > 0, UTIL_DUMP_ERR_INTERNAL); - - XDBG_TRACE (MSEC, "%s : width(%d) height(%d)\n", - __FUNCTION__, width, height); - - FILE * fp = fopen (file, "w+"); - if (fp == NULL) - { - return UTIL_DUMP_ERR_OPENFILE; - } - else - { - bmpfile_header.filesz = sizeof (bmpfile_magic) + sizeof (bmpfile_header) + - sizeof (bmp_dib_v3_header_t) + width * height * 3; - bmp_dib_v3_header_t.header_sz = sizeof (bmp_dib_v3_header_t); - bmp_dib_v3_header_t.width = width; - bmp_dib_v3_header_t.height = -height; - bmp_dib_v3_header_t.nplanes = 1; - bmp_dib_v3_header_t.bmp_bytesz = width * height * 3; - - fwrite (&bmpfile_magic, sizeof (bmpfile_magic), 1, fp); - fwrite (&bmpfile_header, sizeof (bmpfile_header), 1, fp); - fwrite (&bmp_dib_v3_header_t, sizeof (bmp_dib_v3_header_t), 1, fp); - - blocks = (unsigned int*)data; - for (i=0; i<height * width; i++) - fwrite (&blocks[i], 3, 1, fp); - - fclose (fp); - } - - return UTIL_DUMP_OK; -} - -int secUtilDumpShm (int shmid, const void * data, int width, int height) -{ - char * addr; - struct shmid_ds ds; - - addr = shmat (shmid, 0, 0); - if (addr == (void*)-1) - { - return UTIL_DUMP_ERR_SHMATTACH; - } - - if ((shmctl (shmid, IPC_STAT, &ds) < 0) || (ds.shm_segsz < width*height*4)) - { - shmctl (shmid, IPC_RMID, NULL); - shmdt (addr); - - return UTIL_DUMP_ERR_SEGSIZE; - } - - memcpy (addr, data, width*height*4); - - shmctl (shmid, IPC_RMID, NULL); - shmdt (addr); - - return UTIL_DUMP_OK; -} - -int secUtilDumpRaw (const char * file, const void * data, int size) -{ -// int i; - unsigned int * blocks; - - FILE * fp = fopen (file, "w+"); - if (fp == NULL) - { - return UTIL_DUMP_ERR_OPENFILE; - } - else - { - blocks = (unsigned int*)data; - fwrite (blocks, 1, size, fp); - - fclose (fp); - } - - return UTIL_DUMP_OK; -} - -int -secUtilDumpPixmap (const char * file, PixmapPtr pPixmap) -{ - SECPixmapPriv *privPixmap; - Bool need_finish = FALSE; - int ret; - - XDBG_RETURN_VAL_IF_FAIL (pPixmap != NULL, UTIL_DUMP_ERR_INTERNAL); - XDBG_RETURN_VAL_IF_FAIL (file != NULL, UTIL_DUMP_ERR_INTERNAL); - - privPixmap = exaGetPixmapDriverPrivate (pPixmap); - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_RETURN_VAL_IF_FAIL (privPixmap->bo != NULL, UTIL_DUMP_ERR_INTERNAL); - } - - ret = secUtilDumpBmp (file, tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_CPU).ptr, - pPixmap->devKind/(pPixmap->drawable.bitsPerPixel >> 3), - pPixmap->drawable.height); - - if (need_finish) - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - return ret; -} - -typedef struct _DumpBufInfo -{ - int index; - - tbm_bo bo; - int bo_size; - - char file[128]; - Bool dirty; - Bool dump_bmp; - - int width; - int height; - xRectangle rect; - int size; - - struct xorg_list link; -} DumpBufInfo; - -typedef struct _DumpInfo -{ - ScrnInfoPtr pScrn; - - struct xorg_list *cursor; - struct xorg_list bufs; -} DumpInfo; - -static Bool -_calculateSize (int width, int height, xRectangle *crop) -{ - if (crop->x < 0) - { - crop->width += (crop->x); - crop->x = 0; - } - if (crop->y < 0) - { - crop->height += (crop->y); - crop->y = 0; - } - - XDBG_GOTO_IF_FAIL (width > 0 && height > 0, fail_cal); - XDBG_GOTO_IF_FAIL (crop->width > 0 && crop->height > 0, fail_cal); - XDBG_GOTO_IF_FAIL (crop->x >= 0 && crop->x < width, fail_cal); - XDBG_GOTO_IF_FAIL (crop->y >= 0 && crop->y < height, fail_cal); - - if (crop->x + crop->width > width) - crop->width = width - crop->x; - - if (crop->y + crop->height > height) - crop->height = height - crop->y; - - return TRUE; -fail_cal: - XDBG_ERROR (MSEC, "(%dx%d : %d,%d %dx%d)\n", - width, height, crop->x, crop->y, crop->width, crop->height); - - return FALSE; -} - -static void -_secUtilConvertBosG2D (tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride, - tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride, - Bool composite, int rotate) -{ - G2dImage *srcImg = NULL, *dstImg = NULL; - tbm_bo_handle src_bo_handle = {0,}; - tbm_bo_handle dst_bo_handle = {0,}; - G2dColorKeyMode mode; - G2dOp op; - - mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; - src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (src_bo_handle.s32 > 0, access_done); - - dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE); - XDBG_GOTO_IF_FAIL (dst_bo_handle.s32 > 0, access_done); - - srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sstride); - XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done); - - dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dstride); - XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done); - - if (!composite) - op = G2D_OP_SRC; - else - op = G2D_OP_OVER; - - if (rotate == 270) - srcImg->rotate_90 = 1; - else if (rotate == 180) - { - srcImg->xDir = 1; - srcImg->yDir = 1; - } - else if (rotate == 90) - { - srcImg->rotate_90 = 1; - srcImg->xDir = 1; - srcImg->yDir = 1; - } - - util_g2d_blend_with_scale (op, srcImg, dstImg, - (int)sr->x, (int)sr->y, sr->width, sr->height, - (int)dr->x, (int)dr->y, dr->width, dr->height, - FALSE); - g2d_exec (); - -access_done: - if (src_bo_handle.s32) - tbm_bo_unmap (src_bo); - if (dst_bo_handle.s32) - tbm_bo_unmap (dst_bo); - if (srcImg) - g2d_image_free (srcImg); - if (dstImg) - g2d_image_free (dstImg); -} - -static void -_secUtilConvertBosPIXMAN (tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride, - tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride, - Bool composite, int rotate) -{ - tbm_bo_handle src_bo_handle = {0,}; - tbm_bo_handle dst_bo_handle = {0,}; - pixman_op_t op; - - src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (src_bo_handle.ptr != NULL, access_done); - - dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); - XDBG_GOTO_IF_FAIL (dst_bo_handle.ptr != NULL, access_done); - - if (!composite) - op = PIXMAN_OP_SRC; - else - op = PIXMAN_OP_OVER; - - secUtilConvertImage (op, src_bo_handle.ptr, dst_bo_handle.ptr, - PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, - sw, sh, sr, - dw, dh, dr, - NULL, - rotate, FALSE, FALSE); - -access_done: - if (src_bo_handle.ptr) - tbm_bo_unmap (src_bo); - if (dst_bo_handle.ptr) - tbm_bo_unmap (dst_bo); -} - -/* support only RGB */ -void -secUtilConvertBos (ScrnInfoPtr pScrn, - tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride, - tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride, - Bool composite, int rotate) -{ - SECPtr pSec = SECPTR (pScrn); - - XDBG_RETURN_IF_FAIL (pScrn != NULL); - XDBG_RETURN_IF_FAIL (src_bo != NULL); - XDBG_RETURN_IF_FAIL (dst_bo != NULL); - XDBG_RETURN_IF_FAIL (sr != NULL); - XDBG_RETURN_IF_FAIL (dr != NULL); - - pSec = SECPTR (pScrn); - XDBG_RETURN_IF_FAIL (pSec != NULL); - - if (!_calculateSize (sw, sh, sr)) - return; - if (!_calculateSize (dw, dh, dr)) - return; - - if (rotate < 0) - rotate += 360; - - XDBG_DEBUG (MVA, "[%dx%d (%d,%d %dx%d) %d] => [%dx%d (%d,%d %dx%d) %d] comp(%d) rot(%d) G2D(%d)\n", - sw, sh, sr->x, sr->y, sr->width, sr->height, sstride, - dw, dh, dr->x, dr->y, dr->width, dr->height, dstride, - composite, rotate, pSec->is_accel_2d); - - if (pSec->is_accel_2d) - _secUtilConvertBosG2D (src_bo, sw, sh, sr, sstride, - dst_bo, dw, dh, dr, dstride, - composite, rotate); - else - { - _secUtilConvertBosPIXMAN (src_bo, sw, sh, sr, sstride, - dst_bo, dw, dh, dr, dstride, - composite, rotate); - tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); - tbm_bo_unmap(src_bo); - } -} - -void* -secUtilPrepareDump (ScrnInfoPtr pScrn, int bo_size, int buf_cnt) -{ - SECPtr pSec = SECPTR (pScrn); - DumpInfo *dump; - int i; - - dump = calloc (1, sizeof (DumpInfo)); - XDBG_RETURN_VAL_IF_FAIL (dump != NULL, NULL); - - bo_size = bo_size / DUMP_SCALE_RATIO; - - dump->pScrn = pScrn; - - xorg_list_init (&dump->bufs); - - for (i = 0; i < buf_cnt; i++) - { - tbm_bo bo = tbm_bo_alloc (pSec->tbm_bufmgr, bo_size, TBM_BO_DEFAULT); - XDBG_GOTO_IF_FAIL (bo != NULL, fail_prepare); - - DumpBufInfo *buf_info = calloc (1, sizeof (DumpBufInfo)); - if (!buf_info) - { - tbm_bo_unref (bo); - XDBG_WARNING_IF_FAIL (buf_info != NULL); - goto fail_prepare; - } - - buf_info->index = i; - buf_info->bo = bo; - buf_info->bo_size = bo_size; - - tbm_bo_handle handle = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); - memset (handle.ptr, 0x00, buf_info->bo_size); - tbm_bo_unmap (bo); - - xorg_list_add (&buf_info->link, &dump->bufs); - } - - dump->cursor = &dump->bufs; - - return (void*)dump; - -fail_prepare: - secUtilFinishDump (dump); - return NULL; -} - -void -secUtilDoDumpRaws (void *d, tbm_bo *bo, int *size, int bo_cnt, const char *file) -{ - DumpInfo *dump = (DumpInfo*)d; - DumpBufInfo *next = NULL; - struct xorg_list *next_cursor; - void *src_ptr, *dst_ptr; - int i, remain_size, need_size; - - if (!dump || !bo) - return; - - CARD32 prev = GetTimeInMillis (); - - next_cursor = dump->cursor->next; - XDBG_RETURN_IF_FAIL (next_cursor != NULL); - - if (next_cursor == &dump->bufs) - { - next_cursor = next_cursor->next; - XDBG_RETURN_IF_FAIL (next_cursor != NULL); - } - - next = xorg_list_entry (next_cursor, DumpBufInfo, link); - XDBG_RETURN_IF_FAIL (next != NULL); - - need_size = 0; - for (i = 0; i < bo_cnt; i++) - need_size += size[i]; - if (need_size > next->bo_size) - { - SECPtr pSec = SECPTR (dump->pScrn); - tbm_bo new_bo = tbm_bo_alloc (pSec->tbm_bufmgr, need_size, TBM_BO_DEFAULT); - XDBG_RETURN_IF_FAIL (new_bo != NULL); - tbm_bo_unref (next->bo); - next->bo = new_bo; - next->bo_size = need_size; - } - - dst_ptr = tbm_bo_map (next->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE).ptr; - XDBG_RETURN_IF_FAIL (dst_ptr != NULL); - - remain_size = next->bo_size; - for (i = 0; i < bo_cnt; i++) - { - XDBG_GOTO_IF_FAIL (size[i] <= remain_size, end_dump_raws); - - src_ptr = tbm_bo_map (bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ).ptr; - XDBG_GOTO_IF_FAIL (src_ptr != NULL, end_dump_raws); - - memcpy (dst_ptr, src_ptr, size[i]); - dst_ptr += size[i]; - - if (i == 0) - next->size = 0; - - next->size += size[i]; - remain_size -= size[i]; - - tbm_bo_unmap (bo[i]); - } - - snprintf (next->file, sizeof (next->file), "%.3f_%s", GetTimeInMillis()/1000.0, file); - memset (&next->rect, 0, sizeof (xRectangle)); - next->dirty = TRUE; - next->dump_bmp = FALSE; - - XDBG_TRACE (MSEC, "DumpRaws: %ld(%d)\n", GetTimeInMillis () - prev, next->index); - - dump->cursor = next_cursor; - -end_dump_raws: - tbm_bo_unmap (next->bo); - - return; -} - -void -secUtilDoDumpBmps (void *d, tbm_bo bo, int w, int h, xRectangle *crop, const char *file) -{ - DumpInfo *dump = (DumpInfo*)d; - DumpBufInfo *next = NULL; - struct xorg_list *next_cursor; - int scale_w = w / DUMP_SCALE_RATIO; - int scale_h = h / DUMP_SCALE_RATIO; - xRectangle temp = {0,}; - - if (!dump || !bo) - return; - - next_cursor = dump->cursor->next; - XDBG_RETURN_IF_FAIL (next_cursor != NULL); - - if (next_cursor == &dump->bufs) - { - next_cursor = next_cursor->next; - XDBG_RETURN_IF_FAIL (next_cursor != NULL); - } - - next = xorg_list_entry (next_cursor, DumpBufInfo, link); - XDBG_RETURN_IF_FAIL (next != NULL); - - tbm_bo_handle src_handle = tbm_bo_get_handle (bo, TBM_DEVICE_CPU); - tbm_bo_handle dst_handle = tbm_bo_get_handle (next->bo, TBM_DEVICE_CPU); - XDBG_RETURN_IF_FAIL (src_handle.ptr != NULL); - XDBG_RETURN_IF_FAIL (dst_handle.ptr != NULL); - XDBG_RETURN_IF_FAIL (scale_w*scale_h*4 <= next->bo_size); - - CARD32 prev = GetTimeInMillis (); - - snprintf (next->file, sizeof (next->file), "%.3f_%s", GetTimeInMillis()/1000.0, file); - - next->dirty = TRUE; - next->dump_bmp = TRUE; - next->size = scale_w*scale_h*4; - - next->width = scale_w; - next->height = scale_h; - next->rect.x = 0; - next->rect.y = 0; - next->rect.width = (crop)?(crop->width/DUMP_SCALE_RATIO):next->width; - next->rect.height = (crop)?(crop->height/DUMP_SCALE_RATIO):next->height; - - temp.width = (crop)?crop->width:w; - temp.height = (crop)?crop->height:h; - - secUtilConvertBos (dump->pScrn, bo, w, h, &temp, w*4, - next->bo, scale_w, scale_h, &next->rect, scale_w*4, - FALSE, 0); - - XDBG_TRACE (MSEC, "DumpBmps: %ld(%d)\n", GetTimeInMillis () - prev, next->index); - - dump->cursor = next_cursor; - - return; -} - -void -secUtilDoDumpPixmaps (void *d, PixmapPtr pPixmap, const char *file) -{ - SECPixmapPriv *privPixmap; - xRectangle rect = {0,}; - Bool need_finish = FALSE; - - XDBG_RETURN_IF_FAIL (d != NULL); - XDBG_RETURN_IF_FAIL (pPixmap != NULL); - XDBG_RETURN_IF_FAIL (file != NULL); - - privPixmap = exaGetPixmapDriverPrivate (pPixmap); - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_RETURN_IF_FAIL (privPixmap->bo != NULL); - } - - rect.width = pPixmap->drawable.width; - rect.height = pPixmap->drawable.height; - - secUtilDoDumpBmps (d, privPixmap->bo, - pPixmap->devKind/(pPixmap->drawable.bitsPerPixel >> 3), - pPixmap->drawable.height, &rect, file); - - if (need_finish) - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); -} - -void -secUtilDoDumpVBuf (void *d, SECVideoBuf *vbuf, const char *file) -{ - XDBG_RETURN_IF_FAIL (d != NULL); - XDBG_RETURN_IF_FAIL (vbuf != NULL); - XDBG_RETURN_IF_FAIL (file != NULL); - XDBG_RETURN_IF_FAIL (vbuf->secure == FALSE); - - if (IS_RGB (vbuf->id)) - secUtilDoDumpBmps (d, vbuf->bo[0], vbuf->width, vbuf->height, &vbuf->crop, file); - else if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_ST12) - secUtilDoDumpRaws (d, vbuf->bo, vbuf->lengths, 2, file); - else - secUtilDoDumpRaws (d, vbuf->bo, &vbuf->size, 1, file); -} - -void -secUtilFlushDump (void *d) -{ - static Bool is_dir = FALSE; - char *dir = DUMP_DIR; - DumpInfo *dump = (DumpInfo*)d; - DumpBufInfo *cur = NULL, *next = NULL; - - if (!dump) - return; - - if (!is_dir) - { - DIR *dp; - mkdir (dir, 0755); - if (!(dp = opendir (dir))) - { - ErrorF ("failed: open'%s'\n", dir); - return; - } - else - closedir (dp); - is_dir = TRUE; - } - - xorg_list_for_each_entry_safe (cur, next, &dump->bufs, link) - { - if (cur->dirty) - { - if (cur->bo) - { - char file[128]; - - snprintf (file, sizeof(file), "%s/%s", dir, cur->file); - - if (cur->dump_bmp) - { - unsigned int *p; - tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (handle.ptr != NULL, reset_dump); - - /* fill magenta color(#FF00FF) for background */ - p = (unsigned int*)handle.ptr; - if (p) - { - int i, j; - for (j = 0; j < cur->height; j++) - for (i = cur->rect.width; i < cur->width ; i++) - p[i + j * cur->width] = 0xFFFF00FF; - } - - secUtilDumpBmp (file, handle.ptr, cur->width, cur->height); - - tbm_bo_unmap (cur->bo); - } - else - { - tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (handle.ptr != NULL, reset_dump); - - secUtilDumpRaw (file, handle.ptr, cur->size); - - tbm_bo_unmap (cur->bo); - } - - XDBG_ERROR (MSEC, "%s saved\n", file); - } - -reset_dump: - { - tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); - memset (handle.ptr, 0x00, cur->bo_size); - tbm_bo_unmap (cur->bo); - } - cur->width = 0; - cur->height = 0; - cur->size = 0; - memset (&cur->rect, 0, sizeof (xRectangle)); - cur->file[0] = '\0'; - cur->dirty = FALSE; - cur->dump_bmp = FALSE; - } - } -} - -void -secUtilFinishDump (void *d) -{ - DumpInfo *dump = (DumpInfo*)d; - DumpBufInfo *cur = NULL, *next = NULL; - - if (!dump) - return; - - xorg_list_for_each_entry_safe (cur, next, &dump->bufs, link) - { - if (cur->bo) - tbm_bo_unref (cur->bo); - xorg_list_del (&cur->link); - free (cur); - } - free (dump); -} - -#ifndef RR_Rotate_All -#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) -#endif - -int secUtilDegreeToRotate (int degree) -{ - int rotate; - - switch (degree) - { - case 0: - rotate = RR_Rotate_0; - break; - case 90: - rotate = RR_Rotate_90; - break; - case 180: - rotate = RR_Rotate_180; - break; - case 270: - rotate = RR_Rotate_270; - break; - default: - rotate = 0; /* ERROR */ - break; - } - - return rotate; -} - -int secUtilRotateToDegree (int rotate) -{ - int degree; - - switch (rotate & RR_Rotate_All) - { - case RR_Rotate_0: - degree = 0; - break; - case RR_Rotate_90: - degree = 90; - break; - case RR_Rotate_180: - degree = 180; - break; - case RR_Rotate_270: - degree = 270; - break; - default: - degree = -1; /* ERROR */ - break; - } - - return degree; -} - -static int -_secUtilRotateToInt (int rot) -{ - switch (rot & RR_Rotate_All) - { - case RR_Rotate_0: - return 0; - case RR_Rotate_90: - return 1; - case RR_Rotate_180: - return 2; - case RR_Rotate_270: - return 3; - } - - return 0; -} - -int secUtilRotateAdd (int rot_a, int rot_b) -{ - int a = _secUtilRotateToInt (rot_a); - int b = _secUtilRotateToInt (rot_b); - - return (int) ((1 << ((a+b) %4)) &RR_Rotate_All); -} - -void -secUtilCacheFlush (ScrnInfoPtr scrn) -{ - struct drm_exynos_gem_cache_op cache_op; - SECPtr pSec; - int ret; - - XDBG_RETURN_IF_FAIL (scrn != NULL); - - pSec = SECPTR (scrn); - - CLEAR (cache_op); - cache_op.flags = EXYNOS_DRM_CACHE_FSH_ALL | EXYNOS_DRM_ALL_CACHES_CORES; - cache_op.usr_addr = 0; - cache_op.size = 0; - - ret = drmCommandWriteRead (pSec->drm_fd, DRM_EXYNOS_GEM_CACHE_OP, - &cache_op, sizeof(cache_op)); - if (ret) - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "cache flush failed. (%s)\n", strerror(errno)); -} - -const PropertyPtr -secUtilGetWindowProperty (WindowPtr pWin, const char* prop_name) -{ - int rc; - Mask prop_mode = DixReadAccess; - Atom property; - PropertyPtr pProp; - - if (!prop_name) - return NULL; - - property = MakeAtom (prop_name, strlen (prop_name), FALSE); - if (property == None) - return NULL; - - rc = dixLookupProperty (&pProp, pWin, property, serverClient, prop_mode); - if (rc == Success && pProp->data) - { - return pProp; - } - - return NULL; -} - -static void * -_copy_one_channel (int width, int height, - char *s, int s_size_w, int s_pitches, - char *d, int d_size_w, int d_pitches) -{ - uchar *src = (uchar*)s; - uchar *dst = (uchar*)d; - - if (d_size_w == width && s_size_w == width) - memcpy (dst, src, s_pitches * height); - else - { - int i; - - for (i = 0; i < height; i++) - { - memcpy (dst, src, s_pitches); - src += s_pitches; - dst += d_pitches; - } - } - - return dst; -} - -void* -secUtilCopyImage (int width, int height, - char *s, int s_size_w, int s_size_h, - int *s_pitches, int *s_offsets, int *s_lengths, - char *d, int d_size_w, int d_size_h, - int *d_pitches, int *d_offsets, int *d_lengths, - int channel, int h_sampling, int v_sampling) -{ - int i; - - for (i = 0; i < channel; i++) - { - int c_width = width; - int c_height = height; - - if (i > 0) - { - c_width = c_width / h_sampling; - c_height = c_height / v_sampling; - } - - _copy_one_channel (c_width, c_height, - s, s_size_w, s_pitches[i], - d, d_size_w, d_pitches[i]); - - s = s + s_lengths[i]; - d = d + d_lengths[i]; - } - - return d; -} - -/* - * RR_Rotate_90: Target turns to 90. UI turns to 270. - * RR_Rotate_270: Target turns to 270. UI turns to 90. - * - * [Target] ---------- - * | | - * Top (RR_Rotate_90) | | Top (RR_Rotate_270) - * | | - * ---------- - * [UI,FIMC] ---------- - * | | - * Top (degree: 270) | | Top (degree: 90) - * | | - * ---------- - */ -void -secUtilRotateArea (int *width, int *height, xRectangle *rect, int degree) -{ -// int old_w, old_h; - - XDBG_RETURN_IF_FAIL (width != NULL); - XDBG_RETURN_IF_FAIL (height != NULL); - XDBG_RETURN_IF_FAIL (rect != NULL); - - if (degree == 0) - return; - - secUtilRotateRect (*width, *height, rect, degree); - -// old_w = *width; -// old_h = *height; - - if (degree % 180) - SWAP (*width, *height); - -// ErrorF ("%d: (%dx%d) => (%dx%d)\n", degree, old_w, old_h, *width, *height); -} - -void -secUtilRotateRect2 (int width, int height, xRectangle *rect, int degree, const char *func) -{ - xRectangle new_rect = {0,}; - - XDBG_RETURN_IF_FAIL (rect != NULL); - - if (degree == 0) - return; - - degree = (degree + 360) % 360; - - switch (degree) - { - case 90: - new_rect.x = height - (rect->y + rect->height); - new_rect.y = rect->x; - new_rect.width = rect->height; - new_rect.height = rect->width; - break; - case 180: - new_rect.x = width - (rect->x + rect->width); - new_rect.y = height - (rect->y + rect->height); - new_rect.width = rect->width; - new_rect.height = rect->height; - break; - case 270: - new_rect.x = rect->y; - new_rect.y = width - (rect->x + rect->width); - new_rect.width = rect->height; - new_rect.height = rect->width; - break; - } - -// ErrorF ("%d: %dx%d (%d,%d %dx%d) => (%d,%d %dx%d) %s\n", -// degree, width, height, -// rect->x, rect->y, rect->width, rect->height, -// new_rect.x, new_rect.y, new_rect.width, new_rect.height, func); - - *rect = new_rect; -} - -void -secUtilRotateRegion (int width, int height, RegionPtr region, int degree) -{ - RegionRec new_region; - int nbox; - BoxPtr pBox; - - if (!region) - return; - - nbox = RegionNumRects (region); - pBox = RegionRects (region); - - if (nbox == 0) - return; - - RegionInit (&new_region, NULL, 0); - - while (nbox--) - { - if (pBox) - { - xRectangle temp; - RegionPtr temp_region; - temp.x = pBox->x1; - temp.y = pBox->y1; - temp.width = pBox->x2 - pBox->x1; - temp.height = pBox->y2 - pBox->y1; - secUtilRotateRect (width, height, &temp, degree); - temp_region = RegionFromRects (1, &temp, 0); - RegionUnion (&new_region, &new_region, temp_region); - RegionDestroy (temp_region); - } - - pBox++; - } - - RegionCopy (region, &new_region); - RegionUninit (&new_region); -} - -void -secUtilAlignRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw) -{ - int fit_width; - int fit_height; - float rw, rh, max; - - if (!fit) - return; - - XDBG_RETURN_IF_FAIL (src_w > 0 && src_h > 0); - XDBG_RETURN_IF_FAIL (dst_w > 0 && dst_h > 0); - - rw = (float)src_w / dst_w; - rh = (float)src_h / dst_h; - max = MAX (rw, rh); - - fit_width = src_w / max; - fit_height = src_h / max; - - if (hw) - fit_width &= (~0x3); - - fit->x = (dst_w - fit_width) / 2; - fit->y = (dst_h - fit_height) / 2; - fit->width = fit_width; - fit->height = fit_height; -} - -void -secUtilScaleRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *scale) -{ - float ratio; - xRectangle fit; - - XDBG_RETURN_IF_FAIL (scale != NULL); - XDBG_RETURN_IF_FAIL (src_w > 0 && src_h > 0); - XDBG_RETURN_IF_FAIL (dst_w > 0 && dst_h > 0); - - if ((src_w == dst_w) && (src_h == dst_h)) - return; - - secUtilAlignRect (src_w, src_h, dst_w, dst_h, &fit, FALSE); - - ratio = (float)fit.width / src_w; - - scale->x = scale->x * ratio + fit.x; - scale->y = scale->y * ratio + fit.y; - scale->width = scale->width * ratio; - scale->height = scale->height * ratio; -} - -/* true iff two Boxes overlap */ -#define EXTENTCHECK(r1, r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) - -/* true iff (x,y) is in Box */ -#define INBOX(r, x, y) \ - ( ((r)->x2 > x) && \ - ((r)->x1 <= x) && \ - ((r)->y2 > y) && \ - ((r)->y1 <= y) ) - -/* true iff Box r1 contains Box r2 */ -#define SUBSUMES(r1, r2) \ - ( ((r1)->x1 <= (r2)->x1) && \ - ((r1)->x2 >= (r2)->x2) && \ - ((r1)->y1 <= (r2)->y1) && \ - ((r1)->y2 >= (r2)->y2) ) - -int -secUtilBoxInBox (BoxPtr base, BoxPtr box) -{ - XDBG_RETURN_VAL_IF_FAIL(base != NULL, -1); - XDBG_RETURN_VAL_IF_FAIL(box != NULL, -1); - - if(base->x1 == box->x1 && base->y1 == box->y1 && base->x2 == box->x2 && base->y2 == box->y2) - { - return rgnSAME; - } - else if(SUBSUMES(base, box)) - { - return rgnIN; - } - else if(EXTENTCHECK(base, box)) - { - return rgnPART; - } - else - return rgnOUT; - - return -1; -} - -int -secUtilBoxArea(BoxPtr pBox) -{ - return (int) (pBox->x2 - pBox->x1) *(int) (pBox->y2 -pBox->y1); -} - -int -secUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2) -{ - pDstBox->x1 = pBox1->x1 > pBox2->x1 ? pBox1->x1 : pBox2->x1; - pDstBox->x2 = pBox1->x2 < pBox2->x2 ? pBox1->x2 : pBox2->x2; - pDstBox->y1 = pBox1->y1 > pBox2->y1 ? pBox1->y1 : pBox2->y1; - pDstBox->y2 = pBox1->y2 < pBox2->y2 ? pBox1->y2 : pBox2->y2; - - if (pDstBox->x1 >= pDstBox->x2 || pDstBox->y1 >= pDstBox->y2) - { - pDstBox->x1 = 0; - pDstBox->x2 = 0; - pDstBox->y1 = 0; - pDstBox->y2 = 0; - return rgnOUT; - } - - if (pDstBox->x1 == pBox2->x1 && - pDstBox->y1 == pBox2->y1 && - pDstBox->x2 == pBox2->x2 && - pDstBox->y2 == pBox2->y2) - return rgnIN; - - return rgnPART; -} - -void -secUtilBoxMove(BoxPtr pBox, int dx, int dy) -{ - if(dx == 0 && dy == 0) return; - - pBox->x1 += dx; - pBox->x2 += dx; - pBox->y1 += dy; - pBox->y2 += dy; -} - - -Bool -secUtilRectIntersect (xRectanglePtr pDest, xRectanglePtr pRect1, xRectanglePtr pRect2) -{ - int dest_x, dest_y; - int dest_x2, dest_y2; - - if (!pDest) - return FALSE; - - dest_x = MAX (pRect1->x, pRect2->x); - dest_y = MAX (pRect1->y, pRect2->y); - dest_x2 = MIN (pRect1->x + pRect1->width, pRect2->x + pRect2->width); - dest_y2 = MIN (pRect1->y + pRect1->height, pRect2->y + pRect2->height); - - if (dest_x2 > dest_x && dest_y2 > dest_y) - { - pDest->x = dest_x; - pDest->y = dest_y; - pDest->width = dest_x2 - dest_x; - pDest->height = dest_y2 - dest_y; - } - else - { - pDest->width = 0; - pDest->height = 0; - } - - return TRUE; -} - - -void -secUtilSaveImage (pixman_image_t *image, char *path) -{ - void *data; - int width, height; - - XDBG_RETURN_IF_FAIL (image != NULL); - XDBG_RETURN_IF_FAIL (path != NULL); - - width = pixman_image_get_width (image); - height = pixman_image_get_height (image); - - data = pixman_image_get_data (image); - XDBG_RETURN_IF_FAIL (data != NULL); - - secUtilDumpBmp (path, data, width, height); -} - -Bool -secUtilConvertImage (pixman_op_t op, uchar *srcbuf, uchar *dstbuf, - pixman_format_code_t src_format, pixman_format_code_t dst_format, - int sw, int sh, xRectangle *sr, - int dw, int dh, xRectangle *dr, - RegionPtr dst_clip_region, - int rotate, int hflip, int vflip) -{ - pixman_image_t *src_img; - pixman_image_t *dst_img; - int src_stride, dst_stride; - int src_bpp; - int dst_bpp; - double scale_x, scale_y; - int rotate_step; - int ret = FALSE; - pixman_transform_t t; - struct pixman_f_transform ft; - - src_bpp = PIXMAN_FORMAT_BPP (src_format) / 8; - XDBG_RETURN_VAL_IF_FAIL (src_bpp > 0, FALSE); - - dst_bpp = PIXMAN_FORMAT_BPP (dst_format) / 8; - XDBG_RETURN_VAL_IF_FAIL (dst_bpp > 0, FALSE); - - src_stride = sw * src_bpp; - dst_stride = dw * dst_bpp; - - src_img = pixman_image_create_bits (src_format, sw, sh, - (uint32_t*)srcbuf, src_stride); - dst_img = pixman_image_create_bits (dst_format, dw, dh, - (uint32_t*)dstbuf, dst_stride); - - XDBG_GOTO_IF_FAIL (src_img != NULL, CANT_CONVERT); - XDBG_GOTO_IF_FAIL (dst_img != NULL, CANT_CONVERT); - - pixman_f_transform_init_identity (&ft); - - if (hflip) - { - pixman_f_transform_scale (&ft, NULL, -1, 1); - pixman_f_transform_translate (&ft, NULL, dr->width, 0); - } - - if (vflip) - { - pixman_f_transform_scale (&ft, NULL, 1, -1); - pixman_f_transform_translate (&ft, NULL, 0, dr->height); - } - - rotate_step = (rotate + 360) / 90 % 4; - - if (rotate_step > 0) - { - int c, s, tx = 0, ty = 0; - switch (rotate_step) - { - case 1: - /* 90 degrees */ - c = 0; - s = -1; - tx = -dr->width; - break; - case 2: - /* 180 degrees */ - c = -1; - s = 0; - tx = -dr->width; - ty = -dr->height; - break; - case 3: - /* 270 degrees */ - c = 0; - s = 1; - ty = -dr->height; - break; - default: - /* 0 degrees */ - c = 0; - s = 0; - break; - } - - pixman_f_transform_translate (&ft, NULL, tx, ty); - pixman_f_transform_rotate (&ft, NULL, c, s); - } - - if (rotate_step % 2 == 0) - { - scale_x = (double)sr->width / dr->width; - scale_y = (double)sr->height / dr->height; - } - else - { - scale_x = (double)sr->width / dr->height; - scale_y = (double)sr->height / dr->width; - } - - pixman_f_transform_scale (&ft, NULL, scale_x, scale_y); - pixman_f_transform_translate (&ft, NULL, sr->x, sr->y); - - pixman_transform_from_pixman_f_transform (&t, &ft); - pixman_image_set_transform (src_img, &t); - - pixman_image_composite (op, src_img, NULL, dst_img, 0, 0, 0, 0, - dr->x, dr->y, dr->width, dr->height); - - ret = TRUE; - -CANT_CONVERT: - if (src_img) - pixman_image_unref (src_img); - if (dst_img) - pixman_image_unref (dst_img); - - return ret; -} - -void -secUtilFreeHandle (ScrnInfoPtr scrn, unsigned int handle) -{ - struct drm_gem_close close; - SECPtr pSec; - - XDBG_RETURN_IF_FAIL (scrn != NULL); - - pSec = SECPTR (scrn); - - CLEAR (close); - close.handle = handle; - if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_CLOSE, &close)) - { - XDBG_ERRNO (MSEC, "DRM_IOCTL_GEM_CLOSE failed.\n"); - } -} - -Bool -secUtilConvertPhyaddress (ScrnInfoPtr scrn, unsigned int phy_addr, int size, - unsigned int *handle) -{ - struct drm_exynos_gem_phy_imp phy_imp = {0,}; - SECPtr pSec; - - XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE); - - if (!phy_addr || size <= 0 || !handle) - return FALSE; - - pSec = SECPTR (scrn); - phy_imp.phy_addr = (unsigned long)phy_addr; - phy_imp.size = (unsigned long)size; - - if (pSec->drm_fd) - if (ioctl(pSec->drm_fd, DRM_IOCTL_EXYNOS_GEM_PHY_IMP, &phy_imp) < 0) - { - XDBG_ERRNO (MSEC, "DRM_IOCTL_EXYNOS_GEM_PHY_IMP failed. %p(%d)\n", - (void*)phy_addr, size); - return FALSE; - } - - *handle = phy_imp.gem_handle; - - return TRUE; -} - -Bool -secUtilConvertHandle (ScrnInfoPtr scrn, unsigned int handle, - unsigned int *phy_addr, int *size) -{ - struct drm_exynos_gem_get_phy get_phy; - SECPtr pSec; - - XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE); - - if (handle == 0 || (!phy_addr && !size)) - return FALSE; - - pSec = SECPTR (scrn); - memset (&get_phy, 0, sizeof (struct drm_exynos_gem_get_phy)); - get_phy.gem_handle = handle; - - if (pSec->drm_fd) - if (ioctl(pSec->drm_fd, DRM_IOCTL_EXYNOS_GEM_GET_PHY, &get_phy) < 0) - { - XDBG_DEBUG (MLYR, "DRM_IOCTL_EXYNOS_GEM_GET_PHY failed. (%d)(%s,%d)\n", - handle, strerror(errno), errno); - return FALSE; - } - - if (phy_addr) - *phy_addr = (unsigned int)get_phy.phy_addr; - - if (size) - *size = (int)((unsigned int)get_phy.size); - - return TRUE; -} - -typedef struct _ListData -{ - void *key; - void *data; - - struct xorg_list link; -} ListData; - -static ListData* -_secUtilListGet (void *list, void *key) -{ - ListData *data = NULL, *next = NULL; - - if (!list) - return NULL; - - xorg_list_for_each_entry_safe (data, next, (struct xorg_list*)list, link) - { - if (data->key == key) - return data; - } - return NULL; -} - -void* -secUtilListAdd (void *list, void *key, void *user_data) -{ - ListData *data; - int list_flag; - - XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL); - - if (!list) - { - list = calloc (sizeof (struct xorg_list), 1); - XDBG_RETURN_VAL_IF_FAIL (list != NULL, NULL); - xorg_list_init ((struct xorg_list*)list); - list_flag = 1; - } - - if (_secUtilListGet (list, key)) - return list; - - data = malloc (sizeof (ListData)); - XDBG_GOTO_IF_FAIL (data != NULL, fail); - data->key = key; - data->data = user_data; - - xorg_list_add (&data->link, (struct xorg_list*)list); - - return list; - -fail: - if (list_flag && list) - free (list); - - return NULL; -} - -void* -secUtilListRemove (void *list, void *key) -{ - ListData *data; - - XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL); - - data = _secUtilListGet (list, key); - if (data) - { - xorg_list_del (&data->link); - free (data); - - if (xorg_list_is_empty ((struct xorg_list*)list)) - { - free (list); - return NULL; - } - } - - return list; -} - -void* -secUtilListGetData (void *list, void *key) -{ - ListData *data; - - XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL); - - data = _secUtilListGet (list, key); - if (data) - return data->data; - - return NULL; -} - -Bool -secUtilListIsEmpty (void *list) -{ - if (!list) - return FALSE; - - return xorg_list_is_empty ((struct xorg_list*)list); -} - -void -secUtilListDestroyData (void *list, DestroyDataFunc func, void *func_data) -{ - ListData *cur = NULL, *next = NULL; - struct xorg_list *l; - - if (!list || !func) - return; - - l = (struct xorg_list*)list; - xorg_list_for_each_entry_safe (cur, next, l, link) - { - func (func_data, cur->data); - } -} - -void -secUtilListDestroy (void *list) -{ - ListData *data = NULL, *next = NULL; - struct xorg_list *l; - - if (!list) - return; - - l = (struct xorg_list*)list; - xorg_list_for_each_entry_safe (data, next, l, link) - { - xorg_list_del (&data->link); - free (data); - } - - free (list); -} - -Bool -secUtilSetDrmProperty (SECModePtr pSecMode, unsigned int obj_id, unsigned int obj_type, - const char *prop_name, unsigned int value) -{ - drmModeObjectPropertiesPtr props; - unsigned int i; - - XDBG_RETURN_VAL_IF_FAIL (pSecMode != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (obj_id > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (obj_type > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (prop_name != NULL, FALSE); - - props = drmModeObjectGetProperties (pSecMode->fd, obj_id, obj_type); - if (!props) - { - XDBG_ERRNO (MPLN, "fail : drmModeObjectGetProperties.\n"); - return FALSE; - } - - for (i = 0; i < props->count_props; i++) - { - drmModePropertyPtr prop = drmModeGetProperty (pSecMode->fd, props->props[i]); - int ret; - - if (!prop) - { - XDBG_ERRNO (MPLN, "fail : drmModeGetProperty.\n"); - drmModeFreeObjectProperties (props); - return FALSE; - } - - if (!strcmp (prop->name, prop_name)) - { - ret = drmModeObjectSetProperty (pSecMode->fd, obj_id, obj_type, prop->prop_id, value); - if (ret < 0) - { - XDBG_ERRNO (MPLN, "fail : drmModeObjectSetProperty.\n"); - drmModeFreeProperty(prop); - drmModeFreeObjectProperties (props); - return FALSE; - } - - drmModeFreeProperty(prop); - drmModeFreeObjectProperties (props); - - return TRUE; - } - - drmModeFreeProperty(prop); - } - - XDBG_ERROR (MPLN, "fail : drm set property.\n"); - - drmModeFreeObjectProperties (props); - - return FALSE; -} - -Bool -secUtilEnsureExternalCrtc (ScrnInfoPtr scrn) -{ - SECModePtr pSecMode; - SECOutputPrivPtr pOutputPriv = NULL; - - XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE); - - pSecMode = (SECModePtr) SECPTR (scrn)->pSecMode; - - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI) - { - pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_HDMIA); - if (!pOutputPriv) - pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_HDMIB); - } - else - pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_VIRTUAL); - - XDBG_RETURN_VAL_IF_FAIL (pOutputPriv != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_encoder != NULL, FALSE); - - if (pOutputPriv->mode_encoder->crtc_id > 0) - return TRUE; - - secDisplayDeinitDispMode (scrn); - - return secDisplayInitDispMode (scrn, pSecMode->conn_mode); -} - -typedef struct _VBufFreeFuncInfo -{ - FreeVideoBufFunc func; - void *data; - struct xorg_list link; -} VBufFreeFuncInfo; - -static SECFormatTable format_table[] = -{ - { FOURCC_RGB565, DRM_FORMAT_RGB565, TYPE_RGB }, - { FOURCC_SR16, DRM_FORMAT_RGB565, TYPE_RGB }, - { FOURCC_RGB32, DRM_FORMAT_XRGB8888, TYPE_RGB }, - { FOURCC_SR32, DRM_FORMAT_XRGB8888, TYPE_RGB }, - { FOURCC_YV12, DRM_FORMAT_YVU420, TYPE_YUV420 }, - { FOURCC_I420, DRM_FORMAT_YUV420, TYPE_YUV420 }, - { FOURCC_S420, DRM_FORMAT_YUV420, TYPE_YUV420 }, - { FOURCC_ST12, DRM_FORMAT_NV12MT, TYPE_YUV420 }, - { FOURCC_SN12, DRM_FORMAT_NV12, TYPE_YUV420 }, - { FOURCC_NV12, DRM_FORMAT_NV12, TYPE_YUV420 }, - { FOURCC_SN21, DRM_FORMAT_NV21, TYPE_YUV420 }, - { FOURCC_NV21, DRM_FORMAT_NV21, TYPE_YUV420 }, - { FOURCC_YUY2, DRM_FORMAT_YUYV, TYPE_YUV422 }, - { FOURCC_SUYV, DRM_FORMAT_YUYV, TYPE_YUV422 }, - { FOURCC_UYVY, DRM_FORMAT_UYVY, TYPE_YUV422 }, - { FOURCC_SYVY, DRM_FORMAT_UYVY, TYPE_YUV422 }, - { FOURCC_ITLV, DRM_FORMAT_UYVY, TYPE_YUV422 }, -}; - -static struct xorg_list vbuf_lists; - -#define VBUF_RETURN_IF_FAIL(cond) \ - {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return; }} -#define VBUF_RETURN_VAL_IF_FAIL(cond, val) \ - {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return val; }} - -static void -_secUtilInitVbuf (void) -{ - static Bool init = FALSE; - if (!init) - { - xorg_list_init (&vbuf_lists); - init = TRUE; - } -} - -static void -_secUtilYUV420BlackFrame (unsigned char *buf, int buf_size, int width, int height) -{ - int i; - int y_len = 0; - int yuv_len = 0; - - y_len = width * height; - yuv_len = (width * height * 3) >> 1; - - if (buf_size < yuv_len) - return; - - if (width % 4) - { - for (i = 0 ; i < y_len ; i++) - buf[i] = 0x10; - - for ( ; i < yuv_len ; i++) - buf[i] = 0x80; - } - else - { - /* faster way */ - int *ibuf = NULL; - short *sbuf = NULL; - ibuf = (int *)buf; - - for (i = 0 ; i < y_len / 4 ; i++) - ibuf[i] = 0x10101010; /* set YYYY */ - - sbuf = (short*)(&buf[y_len]); - - for (i = 0 ; i < (yuv_len - y_len) / 2 ; i++) - sbuf[i] = 0x8080; /* set UV */ - } - - return; -} - -static void -_secUtilYUV422BlackFrame (int id, unsigned char *buf, int buf_size, int width, int height) -{ - /* YUYV */ - int i; - int yuv_len = 0; - int *ibuf = NULL; - - ibuf = (int *)buf; - - yuv_len = (width * height * 2); - - if (buf_size < yuv_len) - return; - - for (i = 0 ; i < yuv_len / 4 ; i++) - if (id == FOURCC_UYVY || id == FOURCC_SYVY || id == FOURCC_ITLV) - ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */ - else - ibuf[i] = 0x10801080; /* YUYV -> 0xVYUY */ - - return; -} - -static tbm_bo -_secUtilAllocNormalBuffer (ScrnInfoPtr scrn, int size, int flags) -{ - SECPtr pSec = SECPTR (scrn); - - return tbm_bo_alloc (pSec->tbm_bufmgr, size, flags); -} - -static tbm_bo -_secUtilAllocSecureBuffer (ScrnInfoPtr scrn, int size, int flags) -{ - SECPtr pSec = SECPTR (scrn); - struct tzmem_get_region tzmem_get = {0,}; - struct drm_prime_handle arg_handle = {0,}; - struct drm_gem_flink arg_flink = {0,}; - struct drm_gem_close arg_close = {0,}; - tbm_bo bo = NULL; - int tzmem_fd; - - tzmem_fd = -1; - tzmem_get.fd = -1; - - tzmem_fd = open ("/dev/tzmem", O_EXCL); - XDBG_GOTO_IF_FAIL (tzmem_fd >= 0, done_secure_buffer); - - tzmem_get.key = "fimc"; - tzmem_get.size = size; - if (ioctl (tzmem_fd, TZMEM_IOC_GET_TZMEM, &tzmem_get)) - { - XDBG_ERRNO (MVBUF, "failed : create tzmem (%d)\n", size); - goto done_secure_buffer; - } - XDBG_GOTO_IF_FAIL (tzmem_get.fd >= 0, done_secure_buffer); - - arg_handle.fd = (__s32)tzmem_get.fd; - if (drmIoctl (pSec->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg_handle)) - { - XDBG_ERRNO (MVBUF, "failed : convert to gem (%d)\n", tzmem_get.fd); - goto done_secure_buffer; - } - XDBG_GOTO_IF_FAIL (arg_handle.handle > 0, done_secure_buffer); - - arg_flink.handle = arg_handle.handle; - if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_FLINK, &arg_flink)) - { - XDBG_ERRNO (MVBUF, "failed : flink gem (%ld)\n", arg_handle.handle); - goto done_secure_buffer; - } - XDBG_GOTO_IF_FAIL (arg_flink.name > 0, done_secure_buffer); - - bo = tbm_bo_import (pSec->tbm_bufmgr, arg_flink.name); - XDBG_GOTO_IF_FAIL (bo != NULL, done_secure_buffer); - -done_secure_buffer: - if (arg_handle.handle > 0) - { - arg_close.handle = arg_handle.handle; - if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg_close)) - XDBG_ERRNO (MVBUF, "failed : close gem (%ld)\n", arg_handle.handle); - } - - if (tzmem_get.fd >= 0) - close (tzmem_get.fd); - - if (tzmem_fd >= 0) - close (tzmem_fd); - - return bo; -} - -/* - * # planar # - * format: YV12 Y/V/U 420 - * format: I420 Y/U/V 420 #YU12, S420 - * format: NV12 Y/UV 420 - * format: NV12M Y/UV 420 #SN12 - * format: NV12MT Y/UV 420 #ST12 - * format: NV21 Y/VU 420 - * format: Y444 YUV 444 - * # packed # - * format: YUY2 YUYV 422 #YUYV, SUYV, SUY2 - * format: YVYU YVYU 422 - * format: UYVY UYVY 422 #SYVY - */ -G2dColorMode -secUtilGetG2dFormat (unsigned int id) -{ - G2dColorMode g2dfmt = 0; - - switch (id) - { - case FOURCC_NV12: - case FOURCC_SN12: - g2dfmt = G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CrCb; - break; - case FOURCC_NV21: - case FOURCC_SN21: - g2dfmt = G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CbCr; - break; - case FOURCC_SUYV: - case FOURCC_YUY2: - g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_Y1CbY0Cr; - break; - case FOURCC_SYVY: - case FOURCC_UYVY: - g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_CbY1CrY0; - break; - case FOURCC_SR16: - case FOURCC_RGB565: - g2dfmt = G2D_COLOR_FMT_RGB565 | G2D_ORDER_AXRGB; - break; - case FOURCC_SR32: - case FOURCC_RGB32: - g2dfmt = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; - break; - case FOURCC_YV12: - case FOURCC_I420: - case FOURCC_S420: - case FOURCC_ITLV: - case FOURCC_ST12: - default: - XDBG_NEVER_GET_HERE (MVA); - return 0; - } - - return g2dfmt; -} - -unsigned int -secUtilGetDrmFormat (unsigned int id) -{ - int i, size; - - size = sizeof (format_table) / sizeof (SECFormatTable); - - for (i = 0; i < size; i++) - if (format_table[i].id == id) - return format_table[i].drmfmt; - - return 0; -} - -SECFormatType -secUtilGetColorType (unsigned int id) -{ - int i, size; - - size = sizeof (format_table) / sizeof (SECFormatTable); - - for (i = 0; i < size; i++) - if (format_table[i].id == id) - return format_table[i].type; - - return TYPE_NONE; -} - -static SECVideoBuf* -_findVideoBuffer (CARD32 stamp) -{ - SECVideoBuf *cur = NULL, *next = NULL; - - _secUtilInitVbuf (); - - if (!vbuf_lists.next) - return NULL; - - xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link) - { - if (cur->stamp == stamp) - return cur; - } - - return NULL; -} - -SECVideoBuf* -_secUtilAllocVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height, - Bool scanout, Bool reset, Bool secure, const char *func) -{ - SECPtr pSec = SECPTR (scrn); - SECVideoBuf *vbuf = NULL; - int flags = 0; - int i; - tbm_bo_handle bo_handle; - CARD32 stamp; - - XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL); - XDBG_RETURN_VAL_IF_FAIL (width > 0, NULL); - XDBG_RETURN_VAL_IF_FAIL (height > 0, NULL); - - vbuf = calloc (1, sizeof (SECVideoBuf)); - XDBG_GOTO_IF_FAIL (vbuf != NULL, alloc_fail); - - vbuf->ref_cnt = 1; - - vbuf->pScrn = scrn; - vbuf->id = id; - vbuf->width = width; - vbuf->height = height; - vbuf->crop.width = width; - vbuf->crop.height = height; - - vbuf->size = secVideoQueryImageAttrs (scrn, id, &width, &height, - vbuf->pitches, vbuf->offsets, vbuf->lengths); - XDBG_GOTO_IF_FAIL (vbuf->size > 0, alloc_fail); - - for (i = 0; i < PLANAR_CNT; i++) - { - int alloc_size = 0; - - if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12) - alloc_size = vbuf->lengths[i]; - else if (i == 0) - alloc_size = vbuf->size; - - if (alloc_size <= 0) - continue; - - /* if i > 1, do check. */ - if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12) - { - XDBG_GOTO_IF_FAIL (i <= 1, alloc_fail); - } - else - XDBG_GOTO_IF_FAIL (i == 0, alloc_fail); - - if (scanout) - flags = TBM_BO_SCANOUT|TBM_BO_WC; - else if (!pSec->cachable) - flags = TBM_BO_WC; - else - flags = TBM_BO_DEFAULT; - - if (!secure) - vbuf->bo[i] = _secUtilAllocNormalBuffer (scrn, alloc_size, flags); - else - vbuf->bo[i] = _secUtilAllocSecureBuffer (scrn, alloc_size, flags); - XDBG_GOTO_IF_FAIL (vbuf->bo[i] != NULL, alloc_fail); - - vbuf->keys[i] = tbm_bo_export (vbuf->bo[i]); - XDBG_GOTO_IF_FAIL (vbuf->keys[i] > 0, alloc_fail); - - bo_handle = tbm_bo_get_handle (vbuf->bo[i], TBM_DEVICE_DEFAULT); - vbuf->handles[i] = bo_handle.u32; - XDBG_GOTO_IF_FAIL (vbuf->handles[i] > 0, alloc_fail); - - if (scanout) - secUtilConvertHandle (scrn, vbuf->handles[i], &vbuf->phy_addrs[i], NULL); - - XDBG_DEBUG (MVBUF, "handle(%d) => phy_addrs(%d) \n", vbuf->handles[i], vbuf->phy_addrs[i]); - } - - if (reset) - secUtilClearVideoBuffer (vbuf); - - vbuf->secure = secure; - vbuf->dirty = TRUE; - - xorg_list_init (&vbuf->convert_info); - xorg_list_init (&vbuf->free_funcs); - - _secUtilInitVbuf (); - xorg_list_add (&vbuf->valid_link, &vbuf_lists); - - stamp = GetTimeInMillis (); - while (_findVideoBuffer (stamp)) - stamp++; - vbuf->stamp = stamp; - - vbuf->func = strdup (func); - vbuf->flags = flags; - vbuf->scanout = scanout; - - XDBG_DEBUG (MVBUF, "%ld alloc(flags:%x, scanout:%d): %s\n", vbuf->stamp, flags, scanout, func); - - return vbuf; - -alloc_fail: - if (vbuf) - { - for (i = 0; i < PLANAR_CNT && vbuf->bo[i]; i++) - tbm_bo_unref (vbuf->bo[i]); - - free (vbuf); - } - - return NULL; -} - -SECVideoBuf* -_secUtilCreateVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height, Bool secure, const char *func) -{ - SECVideoBuf *vbuf = NULL; - CARD32 stamp; - - XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL); - XDBG_RETURN_VAL_IF_FAIL (width > 0, NULL); - XDBG_RETURN_VAL_IF_FAIL (height > 0, NULL); - - vbuf = calloc (1, sizeof (SECVideoBuf)); - XDBG_GOTO_IF_FAIL (vbuf != NULL, alloc_fail); - - vbuf->ref_cnt = 1; - - vbuf->pScrn = scrn; - vbuf->id = id; - vbuf->width = width; - vbuf->height = height; - vbuf->crop.width = width; - vbuf->crop.height = height; - - vbuf->size = secVideoQueryImageAttrs (scrn, id, &width, &height, - vbuf->pitches, vbuf->offsets, vbuf->lengths); - XDBG_GOTO_IF_FAIL (vbuf->size > 0, alloc_fail); - - vbuf->secure = secure; - - xorg_list_init (&vbuf->convert_info); - xorg_list_init (&vbuf->free_funcs); - - _secUtilInitVbuf (); - xorg_list_add (&vbuf->valid_link, &vbuf_lists); - - stamp = GetTimeInMillis (); - while (_findVideoBuffer (stamp)) - stamp++; - vbuf->stamp = stamp; - - vbuf->func = strdup (func); - vbuf->flags = -1; - - XDBG_DEBUG (MVBUF, "%ld create: %s\n", vbuf->stamp, func); - - return vbuf; - -alloc_fail: - if (vbuf) - secUtilFreeVideoBuffer (vbuf); - - return NULL; -} - -SECVideoBuf* -secUtilVideoBufferRef (SECVideoBuf *vbuf) -{ - if (!vbuf) - return NULL; - - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL); - - vbuf->ref_cnt++; - - return vbuf; -} - -void -_secUtilVideoBufferUnref (SECVideoBuf *vbuf, const char *func) -{ - if (!vbuf) - return; - - VBUF_RETURN_IF_FAIL (_secUtilIsVbufValid (vbuf, func)); - - vbuf->ref_cnt--; - if (vbuf->ref_cnt == 0) - _secUtilFreeVideoBuffer (vbuf, func); -} - -void -_secUtilFreeVideoBuffer (SECVideoBuf *vbuf, const char *func) -{ - VBufFreeFuncInfo *cur = NULL, *next = NULL; - int i; - - if (!vbuf) - return; - - VBUF_RETURN_IF_FAIL (_secUtilIsVbufValid (vbuf, func)); - VBUF_RETURN_IF_FAIL (!VBUF_IS_CONVERTING (vbuf)); - VBUF_RETURN_IF_FAIL (vbuf->showing == FALSE); - - xorg_list_for_each_entry_safe (cur, next, &vbuf->free_funcs, link) - { - /* call before tmb_bo_unref and drmModeRmFB. */ - if (cur->func) - cur->func (vbuf, cur->data); - xorg_list_del (&cur->link); - free (cur); - } - - for (i = 0; i < PLANAR_CNT; i++) - { - if (vbuf->bo[i]) - tbm_bo_unref (vbuf->bo[i]); - } - - if (vbuf->fb_id > 0) - { - XDBG_DEBUG (MVBUF, "vbuf(%ld) fb_id(%d) removed. \n", vbuf->stamp, vbuf->fb_id); - drmModeRmFB (SECPTR(vbuf->pScrn)->drm_fd, vbuf->fb_id); - } - - xorg_list_del (&vbuf->valid_link); - - XDBG_DEBUG (MVBUF, "%ld freed: %s\n", vbuf->stamp, func); - - vbuf->stamp = 0; - - if (vbuf->func) - free (vbuf->func); - - free (vbuf); -} - -static void -_secUtilClearNormalVideoBuffer (SECVideoBuf *vbuf) -{ - int i; - tbm_bo_handle bo_handle; - - if (!vbuf) - return; - - for (i = 0; i < PLANAR_CNT; i++) - { - int size = 0; - - if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || vbuf->id == FOURCC_ST12) - size = vbuf->lengths[i]; - else if (i == 0) - size = vbuf->size; - - if (size <= 0 || !vbuf->bo[i]) - continue; - - bo_handle = tbm_bo_map (vbuf->bo[i], TBM_DEVICE_CPU, TBM_OPTION_WRITE); - XDBG_RETURN_IF_FAIL (bo_handle.ptr != NULL); - - if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || vbuf->id == FOURCC_ST12) - { - if (i == 0) - memset (bo_handle.ptr, 0x10, size); - else if (i == 1) - memset (bo_handle.ptr, 0x80, size); - } - else - { - int type = secUtilGetColorType (vbuf->id); - - if (type == TYPE_YUV420) - _secUtilYUV420BlackFrame (bo_handle.ptr, size, vbuf->width, vbuf->height); - else if (type == TYPE_YUV422) - _secUtilYUV422BlackFrame (vbuf->id, bo_handle.ptr, size, vbuf->width, vbuf->height); - else if (type == TYPE_RGB) - memset (bo_handle.ptr, 0, size); - else - XDBG_NEVER_GET_HERE (MSEC); - } - - tbm_bo_unmap (vbuf->bo[i]); - } - - secUtilCacheFlush (vbuf->pScrn); -} - -static void -_secUtilClearSecureVideoBuffer (SECVideoBuf *vbuf) -{ -} - -void -secUtilClearVideoBuffer (SECVideoBuf *vbuf) -{ - if (!vbuf) - return; - - if (!vbuf->secure) - _secUtilClearNormalVideoBuffer (vbuf); - else - _secUtilClearSecureVideoBuffer (vbuf); - - vbuf->dirty = FALSE; - vbuf->need_reset = FALSE; -} - -Bool -_secUtilIsVbufValid (SECVideoBuf *vbuf, const char *func) -{ - SECVideoBuf *cur = NULL, *next = NULL; - - _secUtilInitVbuf (); - - VBUF_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE); - VBUF_RETURN_VAL_IF_FAIL (vbuf->stamp != 0, FALSE); - - xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link) - { - if (cur->stamp == vbuf->stamp) - return TRUE; - } - - return FALSE; -} - -static VBufFreeFuncInfo* -_secUtilFindFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data) -{ - VBufFreeFuncInfo *cur = NULL, *next = NULL; - - xorg_list_for_each_entry_safe (cur, next, &vbuf->free_funcs, link) - { - if (cur->func == func && cur->data == data) - return cur; - } - - return NULL; -} - -void -secUtilAddFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data) -{ - VBufFreeFuncInfo *info; - - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf)); - XDBG_RETURN_IF_FAIL (func != NULL); - - info = _secUtilFindFreeVideoBufferFunc (vbuf, func, data); - if (info) - return; - - info = calloc (1, sizeof (VBufFreeFuncInfo)); - XDBG_RETURN_IF_FAIL (info != NULL); - - info->func = func; - info->data = data; - - xorg_list_add (&info->link, &vbuf->free_funcs); -} - -void -secUtilRemoveFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data) -{ - VBufFreeFuncInfo *info; - - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf)); - XDBG_RETURN_IF_FAIL (func != NULL); - - info = _secUtilFindFreeVideoBufferFunc (vbuf, func, data); - if (!info) - return; - - xorg_list_del (&info->link); - - free (info); -} - -char* -secUtilDumpVideoBuffer (char *reply, int *len) -{ - SECVideoBuf *cur = NULL, *next = NULL; - - _secUtilInitVbuf (); - - if (xorg_list_is_empty (&vbuf_lists)) - return reply; - - XDBG_REPLY ("\nVideo buffers:\n"); - XDBG_REPLY ("id\tsize\t\t\tformat\tflags\trefcnt\tsecure\tstamp\tfunc\n"); - - xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link) - { - XDBG_REPLY ("%d\t(%dx%d,%d)\t%c%c%c%c\t%d\t%d\t%d\t%ld\t%s\n", - cur->fb_id, cur->width, cur->height, cur->size, - FOURCC_STR (cur->id), - cur->flags, cur->ref_cnt, cur->secure, cur->stamp, cur->func); - } - - return reply; -} - diff --git a/src/util/sec_util.h b/src/util/sec_util.h deleted file mode 100755 index 0b0cb8f..0000000 --- a/src/util/sec_util.h +++ /dev/null @@ -1,193 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 __SEC_UTIL_H__ -#define __SEC_UTIL_H__ - -#include <fbdevhw.h> -#include <pixman.h> -#include <list.h> -#include <xdbg.h> -#include "fimg2d.h" - -#include "sec.h" -#include "property.h" -#include "sec_display.h" -#include "sec_video_types.h" -#include "sec_xberc.h" - -#define MFB XDBG_M('F','B',0,0) -#define MDISP XDBG_M('D','I','S','P') -#define MLYR XDBG_M('L','Y','R',0) -#define MPLN XDBG_M('P','L','N',0) -#define MSEC XDBG_M('S','E','C',0) -#define MEXA XDBG_M('E','X','A',0) -#define MEXAS XDBG_M('E','X','A','S') -#define MEVT XDBG_M('E','V','T',0) -#define MDRI2 XDBG_M('D','R','I','2') -#define MCRS XDBG_M('C','R','S',0) -#define MFLIP XDBG_M('F','L','I','P') -#define MDPMS XDBG_M('D','P','M','S') -#define MVDO XDBG_M('V','D','O',0) -#define MDA XDBG_M('D','A',0,0) -#define MTVO XDBG_M('T','V','O',0) -#define MWB XDBG_M('W','B',0,0) -#define MVA XDBG_M('V','A',0,0) -#define MPROP XDBG_M('P','R','O','P') -#define MXBRC XDBG_M('X','B','R','C') -#define MVBUF XDBG_M('V','B','U','F') -#define MDRM XDBG_M('D','R','M',0) -#define MACCE XDBG_M('A','C','C','E') -#define MCVT XDBG_M('C','V','T',0) -#define MEXAH XDBG_M('E','X','A','H') -#define MG2D XDBG_M('G','2','D',0) - -#define _XID(win) ((unsigned int)(((WindowPtr)win)->drawable.id)) - -#define UTIL_DUMP_OK 0 -#define UTIL_DUMP_ERR_OPENFILE 1 -#define UTIL_DUMP_ERR_SHMATTACH 2 -#define UTIL_DUMP_ERR_SEGSIZE 3 -#define UTIL_DUMP_ERR_CONFIG 4 -#define UTIL_DUMP_ERR_INTERNAL 5 - -#define rgnSAME 3 - -#define DUMP_DIR "/tmp/xdump" - -int secUtilDumpBmp (const char * file, const void * data, int width, int height); -int secUtilDumpRaw (const char * file, const void * data, int size); -int secUtilDumpShm (int shmid, const void * data, int width, int height); -int secUtilDumpPixmap (const char * file, PixmapPtr pPixmap); - -void* secUtilPrepareDump (ScrnInfoPtr pScrn, int bo_size, int buf_cnt); -void secUtilDoDumpRaws (void *dump, tbm_bo *bo, int *size, int bo_cnt, const char *file); -void secUtilDoDumpBmps (void *d, tbm_bo bo, int w, int h, xRectangle *crop, const char *file); -void secUtilDoDumpPixmaps (void *d, PixmapPtr pPixmap, const char *file); -void secUtilDoDumpVBuf (void *d, SECVideoBuf *vbuf, const char *file); -void secUtilFlushDump (void *dump); -void secUtilFinishDump (void *dump); - -int secUtilDegreeToRotate (int degree); -int secUtilRotateToDegree (int rotate); -int secUtilRotateAdd (int rot_a, int rot_b); - -void secUtilCacheFlush (ScrnInfoPtr scrn); - -void* secUtilCopyImage (int width, int height, - char *s, int s_size_w, int s_size_h, - int *s_pitches, int *s_offsets, int *s_lengths, - char *d, int d_size_w, int d_size_h, - int *d_pitches, int *d_offsets, int *d_lengths, - int channel, int h_sampling, int v_sampling); - -void secUtilRotateArea (int *width, int *height, xRectangle *rect, int degree); -void secUtilRotateRect2 (int width, int height, xRectangle *rect, int degree, const char *func); -#define secUtilRotateRect(w,h,r,d) secUtilRotateRect2(w,h,r,d,__FUNCTION__) -void secUtilRotateRegion (int width, int height, RegionPtr region, int degree); - -void secUtilAlignRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw); -void secUtilScaleRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *scale); - -const PropertyPtr secUtilGetWindowProperty (WindowPtr pWin, const char* prop_name); - -int secUtilBoxInBox (BoxPtr base, BoxPtr box); -int secUtilBoxArea(BoxPtr pBox); -int secUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2); -void secUtilBoxMove(BoxPtr pBox, int dx, int dy); - -Bool secUtilRectIntersect (xRectanglePtr pDest, xRectanglePtr pRect1, xRectanglePtr pRect2); - -void secUtilSaveImage (pixman_image_t *image, char *path); -Bool secUtilConvertImage (pixman_op_t op, uchar *srcbuf, uchar *dstbuf, - pixman_format_code_t src_format, pixman_format_code_t dst_format, - int sw, int sh, xRectangle *sr, - int dw, int dh, xRectangle *dr, - RegionPtr dst_clip_region, - int rotate, int hflip, int vflip); -void secUtilConvertBos (ScrnInfoPtr pScrn, - tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride, - tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride, - Bool composite, int rotate); - -void secUtilFreeHandle (ScrnInfoPtr scrn, unsigned int handle); -Bool secUtilConvertPhyaddress (ScrnInfoPtr scrn, unsigned int phy_addr, int size, unsigned int *handle); -Bool secUtilConvertHandle (ScrnInfoPtr scrn, unsigned int handle, unsigned int *phy_addr, int *size); - -typedef void (*DestroyDataFunc) (void *func_data, void *key_data); - -void* secUtilListAdd (void *list, void *key, void *key_data); -void* secUtilListRemove (void *list, void *key); -void* secUtilListGetData (void *list, void *key); -Bool secUtilListIsEmpty (void *list); -void secUtilListDestroyData (void *list, DestroyDataFunc func, void *func_data); -void secUtilListDestroy (void *list); - -Bool secUtilSetDrmProperty (SECModePtr pSecMode, unsigned int obj_id, unsigned int obj_type, - const char *prop_name, unsigned int value); - -Bool secUtilEnsureExternalCrtc (ScrnInfoPtr scrn); - -G2dColorMode secUtilGetG2dFormat (unsigned int id); -unsigned int secUtilGetDrmFormat (unsigned int id); -SECFormatType secUtilGetColorType (unsigned int id); - -SECVideoBuf* _secUtilAllocVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height, - Bool scanout, Bool reset, Bool secure, const char *func); -SECVideoBuf* _secUtilCreateVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height, - Bool secure, const char *func); -SECVideoBuf* secUtilVideoBufferRef (SECVideoBuf *vbuf); -void _secUtilVideoBufferUnref (SECVideoBuf *vbuf, const char *func); -void _secUtilFreeVideoBuffer (SECVideoBuf *vbuf, const char *func); -void secUtilClearVideoBuffer (SECVideoBuf *vbuf); -Bool _secUtilIsVbufValid (SECVideoBuf *vbuf, const char *func); - -typedef void (*FreeVideoBufFunc) (SECVideoBuf *vbuf, void *data); -void secUtilAddFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data); -void secUtilRemoveFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data); - -#define secUtilAllocVideoBuffer(s,i,w,h,c,r,d) _secUtilAllocVideoBuffer(s,i,w,h,c,r,d,__FUNCTION__) -#define secUtilCreateVideoBuffer(s,i,w,h,d) _secUtilCreateVideoBuffer(s,i,w,h,d,__FUNCTION__) -#define secUtilVideoBufferUnref(v) _secUtilVideoBufferUnref(v,__FUNCTION__) -#define secUtilFreeVideoBuffer(v) _secUtilFreeVideoBuffer(v,__FUNCTION__) -#define secUtilIsVbufValid(v) _secUtilIsVbufValid(v,__FUNCTION__) -#define VBUF_IS_VALID(v) secUtilIsVbufValid(v) -#define VSTMAP(v) ((v)?(v)->stamp:0) -#define VBUF_IS_CONVERTING(v) (!xorg_list_is_empty (&((v)->convert_info))) - -/* for debug */ -char* secUtilDumpVideoBuffer (char *reply, int *len); - -#define list_rev_for_each_entry_safe(pos, tmp, head, member) \ - for (pos = __container_of((head)->prev, pos, member), tmp = __container_of(pos->member.prev, pos, member);\ - &pos->member != (head);\ - pos = tmp, tmp = __container_of(pos->member.prev, tmp, member)) - -#endif /* __SEC_UTIL_H__ */ diff --git a/src/xv/exynos_video.c b/src/xv/exynos_video.c new file mode 100644 index 0000000..d226f14 --- /dev/null +++ b/src/xv/exynos_video.c @@ -0,0 +1,3469 @@ +/* + * xserver-xorg-video-exynos + * + * Copyright 2004 Keith Packard + * Copyright 2005 Eric Anholt + * Copyright 2006 Nokia Corporation + * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Boram Park <boram1288.park@samsung.com> + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <pixman.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include <fourcc.h> + +#include <fb.h> +#include <fbdevhw.h> +#include <damage.h> + +#include <xf86xv.h> + +#include "exynos.h" + +#include "exynos_accel.h" +#include "exynos_display.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_video.h" +#include "exynos_prop.h" +#include "exynos_util.h" +#include "exynos_wb.h" +#include "exynos_video_virtual.h" +#include "exynos_video_display.h" +#include "exynos_video_clone.h" +#include "exynos_video_tvout.h" +#include "exynos_video_fourcc.h" +#include "exynos_converter.h" +#include "exynos_plane.h" +#include "exynos_xberc.h" +#include "xv_types.h" +#ifdef LAYER_MANAGER +#include "exynos_layer_manager.h" +#endif + +#include <exynos/exynos_drm.h> + +#define DONT_FILL_ALPHA -1 +#define EXYNOS_MAX_PORT 16 + +#define INBUF_NUM 6 +#define OUTBUF_NUM 3 +#define NUM_HW_LAYER 2 + +#define OUTPUT_LCD (1 << 0) +#define OUTPUT_EXT (1 << 1) +#define OUTPUT_FULL (1 << 8) + +#define CHANGED_NONE 0 +#define CHANGED_INPUT 1 +#define CHANGED_OUTPUT 2 +#define CHANGED_ALL 3 + +static XF86VideoEncodingRec dummy_encoding[] = { + {0, "XV_IMAGE", -1, -1, {1, 1}}, + {1, "XV_IMAGE", 4224, 4224, {1, 1}}, +}; + +static XF86ImageRec images[] = { + XVIMAGE_YUY2, + XVIMAGE_SUYV, + XVIMAGE_UYVY, + XVIMAGE_SYVY, + XVIMAGE_ITLV, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_S420, + XVIMAGE_ST12, + XVIMAGE_NV12, + XVIMAGE_SN12, + XVIMAGE_NV21, + XVIMAGE_SN21, + XVIMAGE_RGB32, + XVIMAGE_SR32, + XVIMAGE_RGB565, + XVIMAGE_SR16, +}; + +static XF86VideoFormatRec formats[] = { + {16, TrueColor}, + {24, TrueColor}, + {32, TrueColor}, +}; + +static XF86AttributeRec attributes[] = { + {0, 0, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP"}, + {0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION"}, + {0, 0, OUTPUT_MODE_EXT_ONLY, "_USER_WM_PORT_ATTRIBUTE_OUTPUT"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE"}, +}; + +typedef enum { + PAA_MIN, + PAA_ROTATION, + PAA_HFLIP, + PAA_VFLIP, + PAA_PREEMPTION, + PAA_OUTPUT, + PAA_SECURE, + PAA_CSC_RANGE, + PAA_MAX +} EXYNOSPortAttrAtom; + +static struct { + EXYNOSPortAttrAtom paa; + const char *name; + Atom atom; +} atoms[] = { + { + PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None}, { + PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None}, { + PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None}, { + PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None}, { + PAA_OUTPUT, "_USER_WM_PORT_ATTRIBUTE_OUTPUT", None}, { + PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None}, { +PAA_CSC_RANGE, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE", None},}; + +enum { + ON_NONE, + ON_FB, + ON_WINDOW, + ON_PIXMAP +}; + +__attribute__ ((unused)) +static char *drawing_type[4] = { "NONE", "FB", "WIN", "PIX" }; + +typedef struct _PutData { + unsigned int id; + int width; + int height; + xRectangle src; + xRectangle dst; + void *buf; + Bool sync; + RegionPtr clip_boxes; + void *data; + DrawablePtr pDraw; +} PutData; + +/* EXYNOS port information structure */ +typedef struct { + CARD32 prev_time; + int index; + + /* attributes */ + int rotate; + int hflip; + int vflip; + int preemption; /* 1:high, 0:default, -1:low */ + Bool exynosure; + int csc_range; + + Bool old_secure; + int old_csc_range; + int old_rotate; + int old_hflip; + int old_vflip; + + ScrnInfoPtr pScrn; + PutData d; + PutData old_d; + + /* draw inform */ + int drawing; + int hw_rotate; + + int in_width; + int in_height; + xRectangle in_crop; + EXYNOSVideoBuf *inbuf[INBUF_NUM]; + Bool inbuf_is_fb; + + /* converter */ + EXYNOSCvt *cvt; +#ifdef LAYER_MANAGER + /* Layer Manager */ + EXYNOSLayerMngClientID lyr_client_id; + EXYNOSLayerOutput output; + EXYNOSLayerPos lpos; + EXYNOSLayerPos old_lpos; +#endif +#ifndef LAYER_MANAGER + /* layer */ + EXYNOSLayer *layer; +#endif + int out_width; + int out_height; + xRectangle out_crop; + EXYNOSVideoBuf *outbuf[OUTBUF_NUM]; + int outbuf_cvting; + DrawablePtr pDamageDrawable[OUTBUF_NUM]; + + /* tvout */ + int usr_output; + int old_output; + int grab_tvout; + EXYNOSVideoTv *tv; + void *gem_list; + Bool skip_tvout; + Bool need_start_wb; + EXYNOSVideoBuf *wait_vbuf; + CARD32 tv_prev_time; + + /* count */ + unsigned int put_counts; + OsTimerPtr timer; + Bool punched; + int stream_cnt; + + struct xorg_list link; +} EXYNOSPortPriv, *EXYNOSPortPrivPtr; + +static RESTYPE event_drawable_type; + +typedef struct _EXYNOSVideoResource { + XID id; + RESTYPE type; + + EXYNOSPortPrivPtr pPort; + ScrnInfoPtr pScrn; +} EXYNOSVideoResource; + +typedef struct _EXYNOSVideoPortInfo { + ClientPtr client; + XvPortPtr pp; +} EXYNOSVideoPortInfo; + +static int (*ddPutImage) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char *, Bool, CARD16, CARD16); + +static void _exynosVideoSendReturnBufferMessage(EXYNOSPortPrivPtr pPort, + EXYNOSVideoBuf * vbuf, + unsigned int *keys); +static void EXYNOSVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit); +static void _exynosVideoCloseInBuffer(EXYNOSPortPrivPtr pPort); +static void _exynosVideoCloseOutBuffer(EXYNOSPortPrivPtr pPort, + Bool close_layer); +static void _exynosVideoCloseConverter(EXYNOSPortPrivPtr pPort); +static Bool _exynosVideoSetOutputExternalProperty(DrawablePtr pDraw, + Bool tvout); + +static int streaming_ports; +static int registered_handler; +static struct xorg_list layer_owners; + +static DevPrivateKeyRec video_port_key; + +#define VideoPortKey (&video_port_key) +#define GetPortInfo(pDraw) ((EXYNOSVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoPortKey)) + +#define NUM_IMAGES (sizeof(images) / sizeof(images[0])) +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) +#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) +#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) + +#define ENSURE_AREA(off, lng, max) (lng = ((off + lng) > max ? (max - off) : lng)) + +static CARD32 +_countPrint(OsTimerPtr timer, CARD32 now, pointer arg) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) arg; + + if (pPort->timer) { + TimerFree(pPort->timer); + pPort->timer = NULL; + } + + ErrorF("PutImage(%d) : %d fps. \n", pPort->index, pPort->put_counts); + + pPort->put_counts = 0; + + return 0; +} + +static void +_countFps(EXYNOSPortPrivPtr pPort) +{ + pPort->put_counts++; + + if (pPort->timer) + return; + + pPort->timer = TimerSet(NULL, 0, 1000, _countPrint, pPort); +} + +static EXYNOSVideoPortInfo * +_port_info(DrawablePtr pDraw) +{ + if (!pDraw) + return NULL; + + if (pDraw->type == DRAWABLE_WINDOW) + return GetPortInfo((WindowPtr) pDraw); + else + return GetPortInfo((PixmapPtr) pDraw); +} + +static PixmapPtr +_getPixmap(DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) + return pDraw->pScreen->GetWindowPixmap((WindowPtr) pDraw); + else + return (PixmapPtr) pDraw; +} + +static XF86ImagePtr +_get_image_info(int id) +{ + int i; + + for (i = 0; i < NUM_IMAGES; i++) + if (images[i].id == id) + return &images[i]; + + return NULL; +} + +static Atom +_portAtom(EXYNOSPortAttrAtom paa) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) { + if (paa == atoms[i].paa) { + if (atoms[i].atom == None) + atoms[i].atom = MakeAtom(atoms[i].name, + strlen(atoms[i].name), TRUE); + + return atoms[i].atom; + } + } + + XDBG_ERROR(MVDO, "Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static void +_DestroyData(void *port, uniType data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) port; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + uint32_t handle = data.u32; + + exynosUtilFreeHandle(pPort->pScrn, handle); +} + +static Bool +_exynosVideoGrabTvout(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + if (pPort->grab_tvout) + return TRUE; + + /* other port already grabbed */ + if (pVideo->tvout_in_use) { + XDBG_WARNING(MVDO, "*** pPort(%p) can't grab tvout. It's in use.\n", + pPort); + return FALSE; + } + + if (pPort->tv) { + XDBG_ERROR(MVDO, "*** wrong handle if you reach here. %p \n", + pPort->tv); + return FALSE; + } + + pPort->grab_tvout = TRUE; + pVideo->tvout_in_use = TRUE; + + XDBG_TRACE(MVDO, "pPort(%p) grabs tvout.\n", pPort); + + return TRUE; +} + +static void +_exynosVideoUngrabTvout(EXYNOSPortPrivPtr pPort) +{ + if (pPort->tv) { + exynosVideoTvDisconnect(pPort->tv); + pPort->tv = NULL; + } + + /* This port didn't grab tvout */ + if (!pPort->grab_tvout) + return; + + _exynosVideoSetOutputExternalProperty(pPort->d.pDraw, FALSE); + + if (pPort->need_start_wb) { + EXYNOSWb *wb = exynosWbGet(); + + if (wb) { + exynosWbSetSecure(wb, pPort->exynosure); + exynosWbStart(wb); + } + pPort->need_start_wb = FALSE; + } + + XDBG_TRACE(MVDO, "pPort(%p) ungrabs tvout.\n", pPort); + + pPort->grab_tvout = FALSE; + + if (pPort->pScrn) { + EXYNOSVideoPrivPtr pVideo; + + pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + pVideo->tvout_in_use = FALSE; + } + pPort->wait_vbuf = NULL; +} + +static int +_exynosVideoGetTvoutMode(EXYNOSPortPrivPtr pPort) +{ + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pPort->pScrn)->pExynosMode; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + EXYNOSDisplaySetMode disp_mode = exynosDisplayGetDispSetMode(pPort->pScrn); + int output = OUTPUT_LCD; + +#if 0 + if (disp_mode == DISPLAY_SET_MODE_CLONE) { + if (pPort->preemption > -1) { + if (pVideo->video_output > 0 && streaming_ports == 1) { + int video_output = pVideo->video_output - 1; + + if (video_output == OUTPUT_MODE_DEFAULT) + output = OUTPUT_LCD; + else if (video_output == OUTPUT_MODE_TVOUT) + output = OUTPUT_LCD | OUTPUT_EXT | OUTPUT_FULL; + else + output = OUTPUT_EXT | OUTPUT_FULL; + } + else if (streaming_ports == 1) { + output = pPort->usr_output; + if (!(output & OUTPUT_FULL)) + output &= ~(OUTPUT_EXT); + } + else if (streaming_ports > 1) + output = OUTPUT_LCD; + else + XDBG_NEVER_GET_HERE(MVDO); + } + else + output = OUTPUT_LCD; + } + else if (disp_mode == DISPLAY_SET_MODE_EXT) { +#else + if (disp_mode == DISPLAY_SET_MODE_EXT) { +#endif + if (pPort->drawing == ON_PIXMAP) { + xf86CrtcPtr pCrtc = exynosCrtcGetAtGeometry(pPort->pScrn, + (int) pPort->d.pDraw->x, + (int) pPort->d.pDraw->y, + (int) pPort->d.pDraw-> + width, + (int) pPort->d.pDraw-> + height); + int c = exynosCrtcGetConnectType(pCrtc); + + if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown) + output = OUTPUT_LCD; + else if (c == DRM_MODE_CONNECTOR_HDMIA || + c == DRM_MODE_CONNECTOR_HDMIB) + output = OUTPUT_EXT; + else if (c == DRM_MODE_CONNECTOR_VIRTUAL) + output = OUTPUT_EXT; + else + XDBG_NEVER_GET_HERE(MVDO); + } + else { + xf86CrtcPtr pCrtc = exynosCrtcGetAtGeometry(pPort->pScrn, + (int) pPort->d.dst.x, + (int) pPort->d.dst.y, + (int) pPort->d.dst. + width, + (int) pPort->d.dst. + height); + int c = exynosCrtcGetConnectType(pCrtc); + + if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown) + output = OUTPUT_LCD; + else if (c == DRM_MODE_CONNECTOR_HDMIA || + c == DRM_MODE_CONNECTOR_HDMIB) + output = OUTPUT_EXT; + else if (c == DRM_MODE_CONNECTOR_VIRTUAL) + output = OUTPUT_EXT; + else + XDBG_NEVER_GET_HERE(MVDO); + } + } + else { /* DISPLAY_SET_MODE_OFF */ + + output = OUTPUT_LCD; + } + + /* OUTPUT_LCD is default display. If default display is HDMI, + * we need to change OUTPUT_LCD to OUTPUT_HDMI + */ + + XDBG_DEBUG(MVDO, + "drawing(%d) disp_mode(%d) preemption(%d) streaming_ports(%d) conn_mode(%d) usr_output(%d) video_output(%d) output(%x) skip(%d)\n", + pPort->drawing, disp_mode, pPort->preemption, streaming_ports, + pExynosMode->conn_mode, pPort->usr_output, pVideo->video_output, + output, pPort->skip_tvout); + + return output; +} + +static int +_exynosVideodrawingOn(EXYNOSPortPrivPtr pPort) +{ + if (pPort->old_d.pDraw != pPort->d.pDraw) + pPort->drawing = ON_NONE; + + if (pPort->drawing != ON_NONE) + return pPort->drawing; + + if (pPort->d.pDraw->type == DRAWABLE_PIXMAP) + return ON_PIXMAP; + else if (pPort->d.pDraw->type == DRAWABLE_WINDOW) { + PropertyPtr prop = + exynosUtilGetWindowProperty((WindowPtr) pPort->d.pDraw, + "XV_ON_DRAWABLE"); + + if (prop && *(int *) prop->data > 0) + return ON_WINDOW; + } + + return ON_FB; +} + +static void +_exynosVideoGetRotation(EXYNOSPortPrivPtr pPort, int *hw_rotate) +{ + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + /* + * RR_Rotate_90: Target turns to 90. UI turns to 270. + * RR_Rotate_270: Target turns to 270. UI turns to 90. + * + * [Target] ---------- + * | | + * Top (RR_Rotate_90) | | Top (RR_Rotate_270) + * | | + * ---------- + * [UI,FIMC] ---------- + * | | + * Top (degree: 270) | | Top (degree: 90) + * | | + * ---------- + */ + + if (pPort->drawing == ON_FB) + *hw_rotate = (pPort->rotate + pVideo->screen_rotate_degree) % 360; + else + *hw_rotate = pPort->rotate % 360; +} + +static int +_exynosVideoGetKeys(EXYNOSPortPrivPtr pPort, unsigned int *keys, + unsigned int *type) +{ + XV_DATA_PTR data = (XV_DATA_PTR) pPort->d.buf; + int valid = XV_VALIDATE_DATA(data); + + if (valid == XV_HEADER_ERROR) { + XDBG_ERROR(MVDO, "XV_HEADER_ERROR\n"); + return valid; + } + else if (valid == XV_VERSION_MISMATCH) { + XDBG_ERROR(MVDO, "XV_VERSION_MISMATCH\n"); + return valid; + } + + if (keys) { + keys[0] = data->YBuf; + keys[1] = data->CbBuf; + keys[2] = data->CrBuf; + } + + if (type) + *type = data->BufType; + + return 0; +} + +static void +_exynosVideoFreeInbuf(EXYNOSVideoBuf * vbuf, void *data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + int i; + + XDBG_RETURN_IF_FAIL(pPort->drawing != ON_NONE); + + for (i = 0; i < INBUF_NUM; i++) + if (pPort->inbuf[i] == vbuf) { + _exynosVideoSendReturnBufferMessage(pPort, vbuf, NULL); + pPort->inbuf[i] = NULL; + return; + } + + XDBG_NEVER_GET_HERE(MVDO); +} + +static void +_exynosVideoFreeOutbuf(EXYNOSVideoBuf * vbuf, void *data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + int i; + + XDBG_RETURN_IF_FAIL(pPort->drawing != ON_NONE); + + for (i = 0; i < OUTBUF_NUM; i++) + if (pPort->outbuf[i] == vbuf) { + pPort->pDamageDrawable[i] = NULL; + pPort->outbuf[i] = NULL; + return; + } + + XDBG_NEVER_GET_HERE(MVDO); +} + +#ifndef LAYER_MANAGER +static EXYNOSLayer * +#else +static Bool +#endif +_exynosVideoCreateLayer(EXYNOSPortPrivPtr pPort) +{ + ScrnInfoPtr pScrn = pPort->pScrn; + +#ifndef LAYER_MANAGER + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pScrn)->pVideoPriv; + xRectangle src, dst; + EXYNOSLayer *layer; + Bool full = FALSE; +#endif + DrawablePtr pDraw = pPort->d.pDraw; + xf86CrtcConfigPtr pCrtcConfig; + xf86OutputPtr pOutput = NULL; + int i; + xf86CrtcPtr pCrtc; + + pCrtc = + exynosCrtcGetAtGeometry(pScrn, pDraw->x, pDraw->y, pDraw->width, + pDraw->height); +#ifndef LAYER_MANAGER + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, NULL); + pCrtcConfig = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + XDBG_RETURN_VAL_IF_FAIL(pCrtcConfig != NULL, NULL); +#else + XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE); + pCrtcConfig = XF86_CRTC_CONFIG_PTR(pCrtc->scrn); + XDBG_RETURN_VAL_IF_FAIL(pCrtcConfig != NULL, FALSE); +#endif + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pTemp = pCrtcConfig->output[i]; + + if (pTemp->crtc == pCrtc) { + pOutput = pTemp; + break; + } + } +#ifndef LAYER_MANAGER + XDBG_RETURN_VAL_IF_FAIL(pOutput != NULL, NULL); +#else + XDBG_RETURN_VAL_IF_FAIL(pOutput != NULL, FALSE); +#endif + + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + EXYNOSLayerOutput output = LAYER_OUTPUT_LCD; + + if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || + pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown) + { + output = LAYER_OUTPUT_LCD; + } + else if (pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIA || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_HDMIB || + pOutputPriv->mode_output->connector_type == + DRM_MODE_CONNECTOR_VIRTUAL) { + output = LAYER_OUTPUT_EXT; + } + else + XDBG_NEVER_GET_HERE(MVDO); +#ifndef LAYER_MANAGER + if (exynosLayerFind(output, LAYER_LOWER2) && + exynosLayerFind(output, LAYER_LOWER1)) + full = TRUE; + if (full) { + return NULL; + } +#else + EXYNOSLayerPos p_lpos[PLANE_MAX]; + int count_available_layer = + exynosLayerMngGetListOfAccessablePos(pPort->lyr_client_id, output, + p_lpos); + if (count_available_layer == 0) { + XDBG_ERROR(MVDO, "XV Layers is busy\n"); + return FALSE; + } +#endif + +#ifndef LAYER_MANAGER + layer = exynosLayerCreate(pScrn, output, LAYER_NONE); + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, NULL); + + src = dst = pPort->out_crop; + dst.x = pPort->d.dst.x; + dst.y = pPort->d.dst.y; + + exynosLayerSetRect(layer, &src, &dst); + exynosLayerEnableVBlank(layer, TRUE); + exynosLayerSetOffset(layer, pVideo->video_offset_x, pVideo->video_offset_y); +#else + pPort->output = output; + for (i = 0; i < count_available_layer; i++) { + if (exynosLayerMngReservation(pPort->lyr_client_id, output, p_lpos[i])) { + pPort->lpos = p_lpos[i]; + break; + } + } + if (pPort->lpos == LAYER_NONE) + return FALSE; +#endif + xorg_list_add(&pPort->link, &layer_owners); + +#ifndef LAYER_MANAGER + return layer; +#else + return TRUE; +#endif +} + +static EXYNOSVideoBuf * +_exynosVideoGetInbufZeroCopy(EXYNOSPortPrivPtr pPort, unsigned int *names, + unsigned int buf_type) +{ + EXYNOSVideoBuf *inbuf = NULL; + int i, empty; + tbm_bo_handle bo_handle; + + for (empty = 0; empty < INBUF_NUM; empty++) + if (!pPort->inbuf[empty]) + break; + + if (empty == INBUF_NUM) { + XDBG_ERROR(MVDO, "now all inbufs in use!\n"); + return NULL; + } + + /* make sure both widths are same. */ + XDBG_RETURN_VAL_IF_FAIL(pPort->d.width == pPort->in_width, NULL); + XDBG_RETURN_VAL_IF_FAIL(pPort->d.height == pPort->in_height, NULL); + + inbuf = exynosUtilCreateVideoBuffer(pPort->pScrn, pPort->d.id, + pPort->in_width, pPort->in_height, + pPort->exynosure); + XDBG_RETURN_VAL_IF_FAIL(inbuf != NULL, NULL); + + inbuf->crop = pPort->in_crop; + + for (i = 0; i < PLANAR_CNT; i++) { + if (names[i] > 0) { + inbuf->keys[i] = names[i]; + + if (buf_type == XV_BUF_TYPE_LEGACY) { +#ifdef LEGACY_INTERFACE + uniType data = + exynosUtilListGetData(pPort->gem_list, (void *) names[i]); + if (!data.ptr) { + exynosUtilConvertPhyaddress(pPort->pScrn, names[i], + inbuf->lengths[i], + &inbuf->handles[i]); + + pPort->gem_list = + exynosUtilListAdd(pPort->gem_list, (void *) names[i], + setunitype32(inbuf->handles[i])); + } + else + inbuf->handles[i] = data.u32; + + XDBG_DEBUG(MVDO, "%d, %p => %u \n", i, (void *) names[i], + inbuf->handles[i]); +#else + XDBG_ERROR(MVDO, "not support legacy type\n"); + goto fail_dma; +#endif + } + else { + XDBG_GOTO_IF_FAIL(inbuf->lengths[i] > 0, fail_dma); + XDBG_GOTO_IF_FAIL(inbuf->bo[i] == NULL, fail_dma); + + inbuf->bo[i] = + tbm_bo_import(EXYNOSPTR(pPort->pScrn)->tbm_bufmgr, + inbuf->keys[i]); + XDBG_GOTO_IF_FAIL(inbuf->bo[i] != NULL, fail_dma); + + bo_handle = tbm_bo_get_handle(inbuf->bo[i], TBM_DEVICE_DEFAULT); + inbuf->handles[i] = bo_handle.u32; + XDBG_GOTO_IF_FAIL(inbuf->handles[i] > 0, fail_dma); + + inbuf->offsets[i] = 0; + + XDBG_DEBUG(MVDO, "%d, key(%d) => bo(%p) handle(%d)\n", + i, inbuf->keys[i], inbuf->bo[i], inbuf->handles[i]); + } + } + } + + /* not increase ref_cnt to free inbuf when converting/showing is done. */ + pPort->inbuf[empty] = inbuf; + + exynosUtilAddFreeVideoBufferFunc(inbuf, _exynosVideoFreeInbuf, pPort); + + return inbuf; + + fail_dma: + if (inbuf) + exynosUtilFreeVideoBuffer(inbuf); + + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVideoGetInbufRAW(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoBuf *inbuf = NULL; + void *vir_addr = NULL; + int i; + tbm_bo_handle bo_handle; + + /* we can't access virtual pointer. */ + XDBG_RETURN_VAL_IF_FAIL(pPort->exynosure == FALSE, NULL); + + for (i = 0; i < INBUF_NUM; i++) { + if (pPort->inbuf[i]) + continue; + + pPort->inbuf[i] = exynosUtilAllocVideoBuffer(pPort->pScrn, pPort->d.id, + pPort->in_width, + pPort->in_height, FALSE, + FALSE, pPort->exynosure); + XDBG_GOTO_IF_FAIL(pPort->inbuf[i] != NULL, fail_raw_alloc); + } + + for (i = 0; i < INBUF_NUM; i++) { + XDBG_DEBUG(MVDO, "? inbuf(%d,%p) converting(%d) showing(%d)\n", i, + pPort->inbuf[i], VBUF_IS_CONVERTING(pPort->inbuf[i]), + pPort->inbuf[i]->showing); + + if (pPort->inbuf[i] && !VBUF_IS_CONVERTING(pPort->inbuf[i]) && + !pPort->inbuf[i]->showing) { + /* increase ref_cnt to keep inbuf until stream_off. */ + inbuf = exynosUtilVideoBufferRef(pPort->inbuf[i]); + break; + } + } + + if (!inbuf) { + XDBG_ERROR(MVDO, "now all inbufs in use!\n"); + return NULL; + } + + inbuf->crop = pPort->in_crop; + + bo_handle = tbm_bo_map(inbuf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE); + vir_addr = bo_handle.ptr; + XDBG_RETURN_VAL_IF_FAIL(vir_addr != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(inbuf->size > 0, NULL); + + if (pPort->d.width != pPort->in_width || + pPort->d.height != pPort->in_height) { + XF86ImagePtr image_info = _get_image_info(pPort->d.id); + + XDBG_RETURN_VAL_IF_FAIL(image_info != NULL, NULL); + int pitches[3] = { 0, }; + int offsets[3] = { 0, }; + int lengths[3] = { 0, }; + int width, height; + + width = pPort->d.width; + height = pPort->d.height; + + exynosVideoQueryImageAttrs(pPort->pScrn, pPort->d.id, + &width, &height, pitches, offsets, lengths); + + exynosUtilCopyImage(width, height, + pPort->d.buf, width, height, + pitches, offsets, lengths, + vir_addr, inbuf->width, inbuf->height, + inbuf->pitches, inbuf->offsets, inbuf->lengths, + image_info->num_planes, + image_info->horz_u_period, + image_info->vert_u_period); + } + else + memcpy(vir_addr, pPort->d.buf, inbuf->size); + + tbm_bo_unmap(inbuf->bo[0]); + exynosUtilCacheFlush(pPort->pScrn); + return inbuf; + + fail_raw_alloc: + _exynosVideoCloseInBuffer(pPort); + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVideoGetInbuf(EXYNOSPortPrivPtr pPort) +{ + unsigned int keys[PLANAR_CNT] = { 0, }; + unsigned int buf_type = 0; + EXYNOSVideoBuf *inbuf = NULL; + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + TTRACE_VIDEO_BEGIN("XORG:XV:GETINBUF"); + + if (IS_ZEROCOPY(pPort->d.id)) { + if (_exynosVideoGetKeys(pPort, keys, &buf_type)) { + TTRACE_VIDEO_END(); + return NULL; + } + + XDBG_GOTO_IF_FAIL(keys[0] > 0, inbuf_fail); + + if (pPort->d.id == FOURCC_SN12 || pPort->d.id == FOURCC_ST12) + XDBG_GOTO_IF_FAIL(keys[1] > 0, inbuf_fail); + + inbuf = _exynosVideoGetInbufZeroCopy(pPort, keys, buf_type); + + XDBG_TRACE(MVDO, "keys: %d,%d,%d. stamp(%" PRIuPTR ")\n", keys[0], + keys[1], keys[2], VSTMAP(inbuf)); + } + else + inbuf = _exynosVideoGetInbufRAW(pPort); + + XDBG_GOTO_IF_FAIL(inbuf != NULL, inbuf_fail); + + if ((pExynos->dump_mode & XBERC_DUMP_MODE_IA) && pExynos->dump_info) { + char file[128]; + static int i; + + snprintf(file, sizeof(file), "xvin_%c%c%c%c_%dx%d_p%d_%03d.%s", + FOURCC_STR(inbuf->id), + inbuf->width, inbuf->height, pPort->index, i++, + IS_RGB(inbuf->id) ? "bmp" : "yuv"); + exynosUtilDoDumpVBuf(pExynos->dump_info, inbuf, file); + } + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_IA) + inbuf->put_time = GetTimeInMillis(); + + TTRACE_VIDEO_END(); + + return inbuf; + + inbuf_fail: + TTRACE_VIDEO_END(); + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVideoGetOutbufDrawable(EXYNOSPortPrivPtr pPort) +{ + ScrnInfoPtr pScrn = pPort->pScrn; + DrawablePtr pDraw = pPort->d.pDraw; + PixmapPtr pPixmap = (PixmapPtr) _getPixmap(pDraw); + EXYNOSPixmapPriv *privPixmap = exaGetPixmapDriverPrivate(pPixmap); + Bool need_finish = FALSE; + EXYNOSVideoBuf *outbuf = NULL; + int empty; + tbm_bo_handle bo_handle; + + for (empty = 0; empty < OUTBUF_NUM; empty++) + if (!pPort->outbuf[empty]) + break; + + if (empty == OUTBUF_NUM) { + XDBG_ERROR(MVDO, "now all outbufs in use!\n"); + return NULL; + } + + if ((pDraw->width % 16) && + (pPixmap->usage_hint != CREATE_PIXMAP_USAGE_XVIDEO)) { + ScreenPtr pScreen = pScrn->pScreen; + EXYNOSFbBoDataPtr bo_data = NULL; + + pPixmap->usage_hint = CREATE_PIXMAP_USAGE_XVIDEO; + pScreen->ModifyPixmapHeader(pPixmap, + pDraw->width, pDraw->height, + pDraw->depth, + pDraw->bitsPerPixel, pPixmap->devKind, 0); + XDBG_RETURN_VAL_IF_FAIL(privPixmap->bo != NULL, NULL); + + tbm_bo_get_user_data(privPixmap->bo, TBM_BO_DATA_FB, + (void **) &bo_data); + XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL((bo_data->pos.x2 - bo_data->pos.x1) == + pPort->out_width, NULL); + XDBG_RETURN_VAL_IF_FAIL((bo_data->pos.y2 - bo_data->pos.y1) == + pPort->out_height, NULL); + } + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(privPixmap->bo != NULL, fail_drawable); + } + + outbuf = exynosUtilCreateVideoBuffer(pScrn, FOURCC_RGB32, + pPort->out_width, + pPort->out_height, pPort->exynosure); + XDBG_GOTO_IF_FAIL(outbuf != NULL, fail_drawable); + outbuf->crop = pPort->out_crop; + + XDBG_TRACE(MVDO, "outbuf(%p)(%dx%d) created. [%s]\n", + outbuf, pPort->out_width, pPort->out_height, + (pPort->drawing == ON_PIXMAP) ? "PIX" : "WIN"); + + outbuf->bo[0] = tbm_bo_ref(privPixmap->bo); + + bo_handle = tbm_bo_get_handle(outbuf->bo[0], TBM_DEVICE_DEFAULT); + outbuf->handles[0] = bo_handle.u32; + XDBG_GOTO_IF_FAIL(outbuf->handles[0] > 0, fail_drawable); + + if (need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + pPort->pDamageDrawable[empty] = pPort->d.pDraw; + +// RegionTranslate (pPort->d.clip_boxes, -pPort->d.dst.x, -pPort->d.dst.y); + + /* not increase ref_cnt to free outbuf when converting/showing is done. */ + pPort->outbuf[empty] = outbuf; + + exynosUtilAddFreeVideoBufferFunc(outbuf, _exynosVideoFreeOutbuf, pPort); + + return outbuf; + + fail_drawable: + if (outbuf) + exynosUtilFreeVideoBuffer(outbuf); + + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVideoGetOutbufFB(EXYNOSPortPrivPtr pPort) +{ + ScrnInfoPtr pScrn = pPort->pScrn; + EXYNOSVideoBuf *outbuf = NULL; + int i, next; + +#ifndef LAYER_MANAGER + if (!pPort->layer) { + pPort->layer = _exynosVideoCreateLayer(pPort); + XDBG_RETURN_VAL_IF_FAIL(pPort->layer != NULL, NULL); + } + else { + EXYNOSVideoBuf *vbuf = exynosLayerGetBuffer(pPort->layer); + + if (vbuf && + (vbuf->width == pPort->out_width && + vbuf->height == pPort->out_height)) { + xRectangle src = { 0, }, dst = { + 0,}; + + exynosLayerGetRect(pPort->layer, &src, &dst); + + /* CHECK */ + if (pPort->d.dst.x != dst.x || pPort->d.dst.y != dst.y) { + /* x,y can be changed when window is moved. */ + dst.x = pPort->d.dst.x; + dst.y = pPort->d.dst.y; + exynosLayerSetRect(pPort->layer, &src, &dst); + } + } + } +#else + if (pPort->lpos == LAYER_NONE) { + XDBG_RETURN_VAL_IF_FAIL(_exynosVideoCreateLayer(pPort), NULL); + } + else if (pPort->lpos != pPort->old_lpos) { + exynosLayerMngRelease(pPort->lyr_client_id, pPort->output, + pPort->old_lpos); + } +#endif + + for (i = 0; i < OUTBUF_NUM; i++) { + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if (pPort->outbuf[i]) + continue; + + pPort->outbuf[i] = exynosUtilAllocVideoBuffer(pScrn, FOURCC_RGB32, + pPort->out_width, + pPort->out_height, + (pExynos-> + scanout) ? TRUE : FALSE, + FALSE, pPort->exynosure); + XDBG_GOTO_IF_FAIL(pPort->outbuf[i] != NULL, fail_fb); + pPort->outbuf[i]->crop = pPort->out_crop; + + XDBG_TRACE(MVDO, "out bo(%p, %d, %dx%d) created. [FB]\n", + pPort->outbuf[i]->bo[0], pPort->outbuf[i]->handles[0], + pPort->out_width, pPort->out_height); + } + + next = ++pPort->outbuf_cvting; + if (next >= OUTBUF_NUM) + next = 0; + + for (i = 0; i < OUTBUF_NUM; i++) { + XDBG_DEBUG(MVDO, "? outbuf(%d,%p) converting(%d)\n", next, + pPort->outbuf[next], + VBUF_IS_CONVERTING(pPort->outbuf[next])); + + if (pPort->outbuf[next] && !VBUF_IS_CONVERTING(pPort->outbuf[next])) { + /* increase ref_cnt to keep outbuf until stream_off. */ + outbuf = exynosUtilVideoBufferRef(pPort->outbuf[next]); + break; + } + + next++; + if (next >= OUTBUF_NUM) + next = 0; + } + + if (!outbuf) { + XDBG_ERROR(MVDO, "now all outbufs in use!\n"); + return NULL; + } + + pPort->outbuf_cvting = next; + + return outbuf; + + fail_fb: + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, TRUE); + + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVideoGetOutbuf(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoBuf *outbuf; + + TTRACE_VIDEO_BEGIN("XORG:XV:GETOUTBUF"); + + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) + outbuf = _exynosVideoGetOutbufDrawable(pPort); + else /* ON_FB */ + outbuf = _exynosVideoGetOutbufFB(pPort); + + TTRACE_VIDEO_END(); + + return outbuf; +} + +static void +_exynosVideoCloseInBuffer(EXYNOSPortPrivPtr pPort) +{ + int i; + + if (pPort->gem_list) { + exynosUtilListDestroyData(pPort->gem_list, _DestroyData, pPort); + exynosUtilListDestroy(pPort->gem_list); + pPort->gem_list = NULL; + } + + if (!IS_ZEROCOPY(pPort->d.id)) + for (i = 0; i < INBUF_NUM; i++) { + if (pPort->inbuf[i]) { + exynosUtilVideoBufferUnref(pPort->inbuf[i]); + pPort->inbuf[i] = NULL; + } + } + + pPort->in_width = 0; + pPort->in_height = 0; + memset(&pPort->in_crop, 0, sizeof(xRectangle)); + + XDBG_DEBUG(MVDO, "done\n"); +} + +static void +_exynosVideoCloseOutBuffer(EXYNOSPortPrivPtr pPort, Bool close_layer) +{ + int i; + + /* before close outbuf, layer/cvt should be finished. */ +#ifndef LAYER_MANAGER + if (close_layer && pPort->layer) { + exynosLayerUnref(pPort->layer); + pPort->layer = NULL; + xorg_list_del(&pPort->link); + } +#else + if (close_layer && pPort->lpos != LAYER_NONE) { + xorg_list_del(&pPort->link); + exynosLayerMngRelease(pPort->lyr_client_id, pPort->output, pPort->lpos); + pPort->lpos = LAYER_NONE; + } +#endif + for (i = 0; i < OUTBUF_NUM; i++) { + if (pPort->outbuf[i]) { + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) + XDBG_NEVER_GET_HERE(MVDO); + + exynosUtilVideoBufferUnref(pPort->outbuf[i]); + pPort->outbuf[i] = NULL; + } + } + + pPort->out_width = 0; + pPort->out_height = 0; + memset(&pPort->out_crop, 0, sizeof(xRectangle)); + pPort->outbuf_cvting = -1; + + XDBG_DEBUG(MVDO, "done\n"); +} + +static void +_exynosVideoSendReturnBufferMessage(EXYNOSPortPrivPtr pPort, + EXYNOSVideoBuf * vbuf, unsigned int *keys) +{ + static Atom return_atom = None; + EXYNOSVideoPortInfo *info = _port_info(pPort->d.pDraw); + + if (return_atom == None) + return_atom = MakeAtom("XV_RETURN_BUFFER", + strlen("XV_RETURN_BUFFER"), TRUE); + + if (!info) + return; + + xEvent event; + + CLEAR(event); + event.u.u.type = ClientMessage; + event.u.u.detail = 32; + event.u.clientMessage.u.l.type = return_atom; + if (vbuf) { + event.u.clientMessage.u.l.longs0 = (INT32) vbuf->keys[0]; + event.u.clientMessage.u.l.longs1 = (INT32) vbuf->keys[1]; + event.u.clientMessage.u.l.longs2 = (INT32) vbuf->keys[2]; + + XDBG_TRACE(MVDO, "%" PRIuPTR ": %d,%d,%d out. diff(%" PRId64 ")\n", + vbuf->stamp, vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], + (int64_t) GetTimeInMillis() - (int64_t) vbuf->stamp); + } + else if (keys) { + event.u.clientMessage.u.l.longs0 = (INT32) keys[0]; + event.u.clientMessage.u.l.longs1 = (INT32) keys[1]; + event.u.clientMessage.u.l.longs2 = (INT32) keys[2]; + + XDBG_TRACE(MVDO, "%d,%d,%d out. \n", keys[0], keys[1], keys[2]); + } + else + XDBG_NEVER_GET_HERE(MVDO); + + WriteEventsToClient(info->client, 1, (xEventPtr) & event); + + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_IA) { + if (vbuf) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - vbuf->put_time; + ErrorF("vbuf(%d,%d,%d) retbuf : %6" PRIXID " ms\n", + vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], sub); + } + else if (keys) + ErrorF("vbuf(%d,%d,%d) retbuf : 0 ms\n", + keys[0], keys[1], keys[2]); + else + XDBG_NEVER_GET_HERE(MVDO); + } +} + +#ifdef LAYER_MANAGER +static void +_exynosVideoReleaseLayerCallback(void *user_data, + EXYNOSLayerMngEventCallbackDataPtr + callback_data) +{ + XDBG_RETURN_IF_FAIL(user_data != NULL); + XDBG_RETURN_IF_FAIL(callback_data != NULL); + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) user_data; + + XDBG_DEBUG(MVDO, "Release Callback\n"); +/* Video layer try move to lowes Layer */ + if (pPort->lpos == LAYER_NONE) + return; + if (callback_data->release_callback.lpos < pPort->lpos + && callback_data->release_callback.output == pPort->output) { + { + if (exynosLayerMngReservation(pPort->lyr_client_id, + callback_data->release_callback. + output, + callback_data->release_callback.lpos)) + pPort->lpos = callback_data->release_callback.lpos; + } + } +} + +/* TODO: Annex callback */ +#endif + +static void +_exynosVideoCvtCallback(EXYNOSCvt * cvt, + EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst, void *cvt_data, Bool error) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) cvt_data; + DrawablePtr pDamageDrawable = NULL; + int out_index; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + XDBG_RETURN_IF_FAIL(cvt != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(src)); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(dst)); + XDBG_DEBUG(MVDO, "++++++++++++++++++++++++ \n"); + XDBG_DEBUG(MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst); + + for (out_index = 0; out_index < OUTBUF_NUM; out_index++) + if (pPort->outbuf[out_index] == dst) + break; + XDBG_RETURN_IF_FAIL(out_index < OUTBUF_NUM); + + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) + pDamageDrawable = pPort->pDamageDrawable[out_index]; + else + pDamageDrawable = pPort->d.pDraw; + + XDBG_RETURN_IF_FAIL(pDamageDrawable != NULL); + + if (error) { + DamageDamageRegion(pDamageDrawable, pPort->d.clip_boxes); + return; + } + + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if ((pExynos->dump_mode & XBERC_DUMP_MODE_IA) && pExynos->dump_info) { + char file[128]; + static int i; + + snprintf(file, sizeof(file), "xvout_p%d_%03d.bmp", pPort->index, i++); + exynosUtilDoDumpVBuf(pExynos->dump_info, dst, file); + } + + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) { + DamageDamageRegion(pDamageDrawable, pPort->d.clip_boxes); + } +#ifndef LAYER_MANAGER + else if (pPort->layer) { + EXYNOSVideoBuf *vbuf = exynosLayerGetBuffer(pPort->layer); + Bool reset_layer = FALSE; + xRectangle src_rect, dst_rect; + + if (vbuf) + if (vbuf->width != pPort->out_width || + vbuf->height != pPort->out_height) + reset_layer = TRUE; + + exynosLayerGetRect(pPort->layer, &src_rect, &dst_rect); + if (memcmp(&src_rect, &pPort->out_crop, sizeof(xRectangle)) || + dst_rect.x != pPort->d.dst.x || + dst_rect.y != pPort->d.dst.y || + dst_rect.width != pPort->out_crop.width || + dst_rect.height != pPort->out_crop.height) + reset_layer = TRUE; + + if (reset_layer) { + exynosLayerFreezeUpdate(pPort->layer, TRUE); + + src_rect = pPort->out_crop; + dst_rect.x = pPort->d.dst.x; + dst_rect.y = pPort->d.dst.y; + dst_rect.width = pPort->out_crop.width; + dst_rect.height = pPort->out_crop.height; + + exynosLayerSetRect(pPort->layer, &src_rect, &dst_rect); + exynosLayerFreezeUpdate(pPort->layer, FALSE); + exynosLayerSetBuffer(pPort->layer, dst); + } + else + exynosLayerSetBuffer(pPort->layer, dst); + + if (!exynosLayerIsVisible(pPort->layer) && !pExynos->XVHIDE) + exynosLayerShow(pPort->layer); + else if (pExynos->XVHIDE) + exynosLayerHide(pPort->layer); + } +#else + else if (pPort->lpos != LAYER_NONE) { + xRectangle src_rect, dst_rect; + + src_rect = pPort->out_crop; + dst_rect.x = pPort->d.dst.x; + dst_rect.y = pPort->d.dst.y; + dst_rect.width = pPort->out_crop.width; + dst_rect.height = pPort->out_crop.height; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + XDBG_RETURN_IF_FAIL(pVideo != NULL); + if (pPort->lpos != pPort->old_lpos) { + exynosLayerMngSet(pPort->lyr_client_id, pVideo->video_offset_x, + pVideo->video_offset_y, &src_rect, &dst_rect, + NULL, dst, pPort->output, pPort->old_lpos, NULL, + NULL); + } + else { + exynosLayerMngSet(pPort->lyr_client_id, pVideo->video_offset_x, + pVideo->video_offset_y, &src_rect, &dst_rect, + NULL, dst, pPort->output, pPort->lpos, NULL, + NULL); + } + } +#endif + XDBG_DEBUG(MVDO, "++++++++++++++++++++++++.. \n"); +} + +static void +_exynosVideoTvoutCvtCallback(EXYNOSCvt * cvt, + EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst, void *cvt_data, Bool error) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) cvt_data; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + XDBG_RETURN_IF_FAIL(cvt != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(src)); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(dst)); + + XDBG_DEBUG(MVDO, "######################## \n"); + XDBG_DEBUG(MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst); + + if (pPort->wait_vbuf != src) + XDBG_WARNING(MVDO, "wait_vbuf(%p) != src(%p). \n", + pPort->wait_vbuf, src); + + pPort->wait_vbuf = NULL; + + XDBG_DEBUG(MVDO, "########################.. \n"); +} + +static void +_exynosVideoLayerNotifyFunc(EXYNOSLayer * layer, int type, void *type_data, + void *data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + EXYNOSVideoBuf *vbuf = (EXYNOSVideoBuf *) type_data; + + if (type != LAYER_VBLANK) + return; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(vbuf)); + + if (pPort->wait_vbuf != vbuf) + XDBG_WARNING(MVDO, "wait_vbuf(%p) != vbuf(%p). \n", + pPort->wait_vbuf, vbuf); + + XDBG_DEBUG(MVBUF, "now_showing(%p). \n", vbuf); + + pPort->wait_vbuf = NULL; +} + +static void +_exynosVideoEnsureConverter(EXYNOSPortPrivPtr pPort) +{ + if (pPort->cvt) + return; + + pPort->cvt = exynosCvtCreate(pPort->pScrn, CVT_OP_M2M); + XDBG_RETURN_IF_FAIL(pPort->cvt != NULL); + + exynosCvtAddCallback(pPort->cvt, _exynosVideoCvtCallback, pPort); +} + +static void +_exynosVideoCloseConverter(EXYNOSPortPrivPtr pPort) +{ + if (pPort->cvt) { + exynosCvtDestroy(pPort->cvt); + pPort->cvt = NULL; + } + + XDBG_TRACE(MVDO, "done. \n"); +} + +static void +_exynosVideoStreamOff(EXYNOSPortPrivPtr pPort) +{ + _exynosVideoCloseConverter(pPort); + _exynosVideoUngrabTvout(pPort); + _exynosVideoCloseInBuffer(pPort); + _exynosVideoCloseOutBuffer(pPort, TRUE); + + EXYNOSWb *wb = exynosWbGet(); + + if (wb) { + if (pPort->need_start_wb) { + exynosWbSetSecure(wb, FALSE); + exynosWbStart(wb); + pPort->need_start_wb = FALSE; + } + else + exynosWbSetSecure(wb, FALSE); + } + + if (pPort->d.clip_boxes) { + RegionDestroy(pPort->d.clip_boxes); + pPort->d.clip_boxes = NULL; + } + + memset(&pPort->old_d, 0, sizeof(PutData)); + memset(&pPort->d, 0, sizeof(PutData)); + + pPort->need_start_wb = FALSE; + pPort->skip_tvout = FALSE; + pPort->usr_output = OUTPUT_LCD | OUTPUT_EXT | OUTPUT_FULL; + pPort->outbuf_cvting = -1; + pPort->drawing = 0; + pPort->tv_prev_time = 0; + pPort->exynosure = FALSE; + pPort->csc_range = 0; + pPort->inbuf_is_fb = FALSE; + + if (pPort->stream_cnt > 0) { + pPort->stream_cnt = 0; + XDBG_SECURE(MVDO, "pPort(%d) stream off. \n", pPort->index); + + if (pPort->preemption > -1) + streaming_ports--; + + XDBG_WARNING_IF_FAIL(streaming_ports >= 0); + } +#ifdef LAYER_MANAGER + if (pPort->lyr_client_id != LYR_ERROR_ID) { + exynosLayerMngUnRegisterClient(pPort->lyr_client_id); + pPort->lyr_client_id = LYR_ERROR_ID; + pPort->lpos = LAYER_NONE; + } +#endif + XDBG_TRACE(MVDO, "done. \n"); +} + +static Bool +_exynosVideoCalculateSize(EXYNOSPortPrivPtr pPort) +{ + EXYNOSCvtProp src_prop = { 0, }, dst_prop = { + 0,}; + + src_prop.id = pPort->d.id; + src_prop.width = pPort->d.width; + src_prop.height = pPort->d.height; + src_prop.crop = pPort->d.src; + + dst_prop.id = FOURCC_RGB32; + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) { + dst_prop.width = pPort->d.pDraw->width; + dst_prop.height = pPort->d.pDraw->height; + dst_prop.crop = pPort->d.dst; + dst_prop.crop.x -= pPort->d.pDraw->x; + dst_prop.crop.y -= pPort->d.pDraw->y; + } + else { + dst_prop.width = pPort->d.dst.width; + dst_prop.height = pPort->d.dst.height; + dst_prop.crop = pPort->d.dst; + dst_prop.crop.x = 0; + dst_prop.crop.y = 0; + } + + XDBG_DEBUG(MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n", + src_prop.width, src_prop.height, + src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, + src_prop.crop.height, dst_prop.width, dst_prop.height, + dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, + dst_prop.crop.height); + + if (!exynosCvtEnsureSize(&src_prop, &dst_prop)) + return FALSE; + + XDBG_DEBUG(MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n", + src_prop.width, src_prop.height, + src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, + src_prop.crop.height, dst_prop.width, dst_prop.height, + dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, + dst_prop.crop.height); + + XDBG_RETURN_VAL_IF_FAIL(src_prop.width > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src_prop.height > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src_prop.crop.width > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src_prop.crop.height > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_prop.width > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_prop.height > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_prop.crop.width > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_prop.crop.height > 0, FALSE); + + pPort->in_width = src_prop.width; + pPort->in_height = src_prop.height; + pPort->in_crop = src_prop.crop; + + pPort->out_width = dst_prop.width; + pPort->out_height = dst_prop.height; + pPort->out_crop = dst_prop.crop; + return TRUE; +} + +static void +_exynosVideoPunchDrawable(EXYNOSPortPrivPtr pPort) +{ + PixmapPtr pPixmap = _getPixmap(pPort->d.pDraw); + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if (pPort->drawing != ON_FB || !pExynos->pVideoPriv->video_punch) + return; + + if (!pPort->punched) { + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + if (pPixmap->devPrivate.ptr) + memset(pPixmap->devPrivate.ptr, 0, + pPixmap->drawable.width * pPixmap->drawable.height * 4); + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_TRACE(MVDO, "Punched (%dx%d) %p. \n", + pPixmap->drawable.width, pPixmap->drawable.height, + pPixmap->devPrivate.ptr); + pPort->punched = TRUE; + DamageDamageRegion(pPort->d.pDraw, pPort->d.clip_boxes); + } +} + +static Bool +_exynosVideoSupportID(int id) +{ + int i; + + for (i = 0; i < NUM_IMAGES; i++) + if (images[i].id == id) + if (exynosCvtSupportFormat(CVT_OP_M2M, id)) + return TRUE; + + return FALSE; +} + +static Bool +_exynosVideoInBranch(WindowPtr p, WindowPtr w) +{ + for (; w; w = w->parent) + if (w == p) + return TRUE; + + return FALSE; +} + +/* Return the child of 'p' which includes 'w'. */ +static WindowPtr +_exynosVideoGetChild(WindowPtr p, WindowPtr w) +{ + WindowPtr c; + + for (c = w, w = w->parent; w; c = w, w = w->parent) + if (w == p) + return c; + + return NULL; +} + +/* ancestor : Return the parent of 'a' and 'b'. + * ancestor_a : Return the child of 'ancestor' which includes 'a'. + * ancestor_b : Return the child of 'ancestor' which includes 'b'. + */ +static Bool +_exynosVideoGetAncestors(WindowPtr a, WindowPtr b, + WindowPtr *ancestor, + WindowPtr *ancestor_a, WindowPtr *ancestor_b) +{ + WindowPtr child_a, child_b; + + if (!ancestor || !ancestor_a || !ancestor_b) + return FALSE; + + for (child_b = b, b = b->parent; b; child_b = b, b = b->parent) { + child_a = _exynosVideoGetChild(b, a); + if (child_a) { + *ancestor = b; + *ancestor_a = child_a; + *ancestor_b = child_b; + return TRUE; + } + } + + return FALSE; +} + +static int +_exynosVideoCompareWindow(WindowPtr pWin1, WindowPtr pWin2) +{ + WindowPtr a, a1, a2, c; + + if (!pWin1 || !pWin2) + return -2; + + if (pWin1 == pWin2) + return 0; + + if (_exynosVideoGetChild(pWin1, pWin2)) + return -1; + + if (_exynosVideoGetChild(pWin2, pWin1)) + return 1; + + if (!_exynosVideoGetAncestors(pWin1, pWin2, &a, &a1, &a2)) + return -3; + + for (c = a->firstChild; c; c = c->nextSib) { + if (c == a1) + return 1; + else if (c == a2) + return -1; + } + + return -4; +} + +static void +_exynosVideoArrangeLayerPos(EXYNOSPortPrivPtr pPort, Bool by_notify) +{ + EXYNOSPortPrivPtr pCur = NULL, pNext = NULL; + EXYNOSPortPrivPtr pAnother = NULL; + int i = 0; + + xorg_list_for_each_entry_safe(pCur, pNext, &layer_owners, link) { + if (pCur == pPort) + continue; + + i++; + + if (!pAnother) + pAnother = pCur; + else + XDBG_WARNING(MVDO, "There are 3 more V4L2 ports. (%d) \n", i); + } +#ifndef LAYER_MANAGER + if (!pAnother) { + EXYNOSLayerPos lpos = exynosLayerGetPos(pPort->layer); + + if (lpos == LAYER_NONE) + exynosLayerSetPos(pPort->layer, LAYER_LOWER2); + } + else { + EXYNOSLayerPos lpos1 = LAYER_NONE; + EXYNOSLayerPos lpos2 = LAYER_NONE; + + if (pAnother->layer) + lpos1 = exynosLayerGetPos(pAnother->layer); + if (pPort->layer) + lpos2 = exynosLayerGetPos(pPort->layer); + + if (lpos2 == LAYER_NONE) { + int comp = _exynosVideoCompareWindow((WindowPtr) pAnother->d.pDraw, + (WindowPtr) pPort->d.pDraw); + + XDBG_TRACE(MVDO, "0x%08x : 0x%08x => %d \n", + _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp); + + if (comp == 1) { + if (lpos1 != LAYER_LOWER1) { + exynosLayerSetPos(pAnother->layer, LAYER_LOWER1); + } + exynosLayerSetPos(pPort->layer, LAYER_LOWER2); + } + else if (comp == -1) { + if (lpos1 != LAYER_LOWER2) + exynosLayerSetPos(pAnother->layer, LAYER_LOWER2); + exynosLayerSetPos(pPort->layer, LAYER_LOWER1); + } + else { + if (lpos1 == LAYER_LOWER1) + exynosLayerSetPos(pPort->layer, LAYER_LOWER2); + else + exynosLayerSetPos(pPort->layer, LAYER_LOWER1); + } + } + else { + if (!by_notify) + return; + + int comp = _exynosVideoCompareWindow((WindowPtr) pAnother->d.pDraw, + (WindowPtr) pPort->d.pDraw); + + XDBG_TRACE(MVDO, "0x%08x : 0x%08x => %d \n", + _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp); + + if ((comp == 1 && lpos1 != LAYER_LOWER1) || + (comp == -1 && lpos2 != LAYER_LOWER1)) + exynosLayerSwapPos(pAnother->layer, pPort->layer); + } + } +#else + if (!by_notify || !pAnother) + return; + int comp = _exynosVideoCompareWindow((WindowPtr) pAnother->d.pDraw, + (WindowPtr) pPort->d.pDraw); + + XDBG_TRACE(MVDO, "0x%08x : 0x%08x => %d \n", + _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp); + if ((comp == 1 && pAnother->lpos != LAYER_LOWER1) || + (comp == -1 && pPort->lpos != LAYER_LOWER1)) { + if (exynosLayerMngSwapPos(pAnother->lyr_client_id, + pAnother->output, pAnother->lpos, + pPort->lyr_client_id, + pPort->output, pPort->lpos)) { + EXYNOSLayerPos temp_lpos; + + temp_lpos = pAnother->lpos; + pAnother->lpos = pPort->lpos; + pPort->lpos = temp_lpos; + } + } +#endif +} + +static void +_exynosVideoStopTvout(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + XF86VideoAdaptorPtr pAdaptor = pExynos->pVideoPriv->pAdaptor[0]; + int i; + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + EXYNOSPortPrivPtr pPort = + (EXYNOSPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + + if (pPort->grab_tvout) { + _exynosVideoUngrabTvout(pPort); + return; + } + } +} + +/* TRUE : current frame will be shown on TV. free after vblank. + * FALSE : current frame won't be shown on TV. + */ +static Bool +_exynosVideoPutImageTvout(EXYNOSPortPrivPtr pPort, int output, + EXYNOSVideoBuf * inbuf) +{ + ScrnInfoPtr pScrn = pPort->pScrn; + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + xRectangle tv_rect = { 0, }; + Bool first_put = FALSE; + + if (!(output & OUTPUT_EXT)) { + XDBG_DEBUG(MTVO, "!(output (%d) & OUTPUT_EXT)\n", output); + return FALSE; + } + + if (pPort->skip_tvout) { + XDBG_DEBUG(MTVO, "pPort->skip_tvout (%d)\n", pPort->skip_tvout); + return FALSE; + } + + if (!_exynosVideoGrabTvout(pPort)) + goto fail_to_put_tvout; + + if (!pPort->tv) { + EXYNOSCvt *tv_cvt; + EXYNOSWb *wb; + + if (!exynosUtilEnsureExternalCrtc(pScrn)) { + XDBG_ERROR(MVDO, "failed : pPort(%d) connect external crtc\n", + pPort->index); + goto fail_to_put_tvout; + } + + pPort->tv = exynosVideoTvConnect(pScrn, pPort->d.id, LAYER_LOWER1); + XDBG_GOTO_IF_FAIL(pPort->tv != NULL, fail_to_put_tvout); + exynosVideoTvSetAttributes(pPort->tv, pPort->hw_rotate, pPort->hflip, + pPort->vflip); + wb = exynosWbGet(); + if (wb) { + pPort->need_start_wb = TRUE; +#if 0 + /* in case of VIRTUAL, wb's buffer is used by tvout. */ + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) + exynosWbStop(wb, FALSE); + else + exynosWbStop(wb, TRUE); +#endif + } +#if 0 + if (exynosWbIsRunning()) { + XDBG_ERROR(MVDO, "failed: wb still running\n"); + goto fail_to_put_tvout; + } +#endif + if (!exynosVideoTvGetConverter(pPort->tv)) { + if (!exynosVideoTvCanDirectDrawing + (pPort->tv, pPort->d.src.width, pPort->d.src.height, + pPort->d.dst.width, pPort->d.dst.height)) { + XDBG_GOTO_IF_FAIL(exynosVideoTvReCreateConverter(pPort->tv), + fail_to_put_tvout); + } + } + + tv_cvt = exynosVideoTvGetConverter(pPort->tv); + + if (tv_cvt) { + /* HDMI : SN12 + * VIRTUAL : SN12 or RGB32 + */ +#if 0 + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + if (pExynosMode->set_mode == DISPLAY_SET_MODE_CLONE) { + EXYNOSVideoBuf **vbufs = NULL; + int bufnum = 0; + + exynosVideoTvSetConvertFormat(pPort->tv, FOURCC_SN12); + + /* In case of virtual, we draw video on full-size buffer + * for virtual-adaptor + */ + exynosVideoTvSetSize(pPort->tv, + pExynosMode->ext_connector_mode. + hdisplay, + pExynosMode->ext_connector_mode. + vdisplay); + + exynosVirtualVideoGetBuffers(pPort->pScrn, FOURCC_SN12, + pExynosMode->ext_connector_mode. + hdisplay, + pExynosMode->ext_connector_mode. + vdisplay, &vbufs, &bufnum); + + XDBG_GOTO_IF_FAIL(vbufs != NULL, fail_to_put_tvout); + XDBG_GOTO_IF_FAIL(bufnum > 0, fail_to_put_tvout); + + exynosVideoTvSetBuffer(pPort->tv, vbufs, bufnum); + } + else /* desktop */ + exynosVideoTvSetConvertFormat(pPort->tv, FOURCC_RGB32); + } + + else { +#if 0 + exynosVideoTvSetConvertFormat(pPort->tv, FOURCC_SN12); +#endif + } +#endif + exynosCvtAddCallback(tv_cvt, _exynosVideoTvoutCvtCallback, pPort); + } + else { + EXYNOSLayer *layer = exynosVideoTvGetLayer(pPort->tv); + + XDBG_GOTO_IF_FAIL(layer != NULL, fail_to_put_tvout); + exynosLayerEnableVBlank(layer, TRUE); + exynosLayerAddNotifyFunc(layer, _exynosVideoLayerNotifyFunc, pPort); + } + + first_put = TRUE; + } + + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if (pPort->wait_vbuf) { + if (pExynos->pVideoPriv->video_fps) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - pPort->tv_prev_time; + pPort->tv_prev_time = cur; + + XDBG_DEBUG(MVDO, "tvout skip : sub(%ld) vbuf(%ld:%d,%d,%d) \n", + sub, inbuf->stamp, + inbuf->keys[0], inbuf->keys[1], inbuf->keys[2]); + } + XDBG_DEBUG(MVDO, "pPort->wait_vbuf (%p) skip_frame\n", + pPort->wait_vbuf); + return FALSE; + } + else if (pExynos->pVideoPriv->video_fps) + pPort->tv_prev_time = GetTimeInMillis(); + + if (!(output & OUTPUT_FULL)) { + EXYNOSDisplaySetMode disp_mode = exynosDisplayGetDispSetMode(pScrn); + + if (disp_mode == DISPLAY_SET_MODE_EXT) + tv_rect.x = pPort->d.dst.x - pExynosMode->main_lcd_mode.hdisplay; + else + tv_rect.x = pPort->d.dst.x; + tv_rect.y = pPort->d.dst.y; + tv_rect.width = pPort->d.dst.width; + tv_rect.height = pPort->d.dst.height; + } + else { + exynosUtilAlignRect(pPort->d.src.width, pPort->d.src.height, + pExynosMode->ext_connector_mode.hdisplay, + pExynosMode->ext_connector_mode.vdisplay, &tv_rect, + TRUE); + } + + /* if exynosVideoTvPutImage returns FALSE, it means this frame won't show on TV. */ + if (!exynosVideoTvPutImage(pPort->tv, inbuf, &tv_rect, pPort->csc_range)) + return FALSE; + + if (first_put && !(output & OUTPUT_LCD)) + _exynosVideoSetOutputExternalProperty(pPort->d.pDraw, TRUE); + + pPort->wait_vbuf = inbuf; + + return TRUE; + + fail_to_put_tvout: + _exynosVideoUngrabTvout(pPort); + + pPort->skip_tvout = TRUE; + + XDBG_TRACE(MVDO, "pPort(%d) skip tvout \n", pPort->index); + + return FALSE; +} + +static Bool +_exynosVideoPutImageInbuf(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * inbuf) +{ +#ifndef LAYER_MANAGER + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if (!pPort->layer) { + pPort->layer = _exynosVideoCreateLayer(pPort); + XDBG_RETURN_VAL_IF_FAIL(pPort->layer != NULL, FALSE); + + _exynosVideoArrangeLayerPos(pPort, FALSE); + } + exynosLayerSetBuffer(pPort->layer, inbuf); + + if (!exynosLayerIsVisible(pPort->layer) && !pExynos->XVHIDE) + exynosLayerShow(pPort->layer); + else if (pExynos->XVHIDE) + exynosLayerHide(pPort->layer); +#else + if (pPort->lpos == LAYER_NONE) { + XDBG_RETURN_VAL_IF_FAIL(_exynosVideoCreateLayer(pPort), FALSE); + } + else if (pPort->lpos != pPort->old_lpos) { + exynosLayerMngRelease(pPort->lyr_client_id, pPort->output, + pPort->old_lpos); + } + xRectangle src, dst; + + src = dst = pPort->out_crop; + dst.x = pPort->d.dst.x; + dst.y = pPort->d.dst.y; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + XDBG_RETURN_VAL_IF_FAIL(pVideo != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(exynosLayerMngSet(pPort->lyr_client_id, + pVideo->video_offset_x, + pVideo->video_offset_y, &src, + &dst, NULL, inbuf, pPort->output, + pPort->lpos, NULL, NULL) + , FALSE); +#endif + return TRUE; +} + +static Bool +_exynosVideoPutImageInternal(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * inbuf) +{ + EXYNOSPtr pExynos = (EXYNOSPtr) pPort->pScrn->driverPrivate; + EXYNOSCvtProp src_prop = { 0, }, dst_prop = { + 0,}; + EXYNOSVideoBuf *outbuf = NULL; + + outbuf = _exynosVideoGetOutbuf(pPort); + if (!outbuf) + return FALSE; + + /* cacheflush here becasue dst buffer can be created in _exynosVideoGetOutbuf() */ + if (pPort->stream_cnt == 1) + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) + exynosUtilCacheFlush(pPort->pScrn); + + XDBG_DEBUG(MVDO, "'%c%c%c%c' preem(%d) rot(%d) \n", + FOURCC_STR(pPort->d.id), pPort->preemption, pPort->hw_rotate); +#ifndef LAYER_MANAGER + if (pPort->layer) + _exynosVideoArrangeLayerPos(pPort, FALSE); +#endif + _exynosVideoEnsureConverter(pPort); + XDBG_GOTO_IF_FAIL(pPort->cvt != NULL, fail_to_put); + + src_prop.id = pPort->d.id; + src_prop.width = pPort->in_width; + src_prop.height = pPort->in_height; + src_prop.crop = pPort->in_crop; + + dst_prop.id = FOURCC_RGB32; + dst_prop.width = pPort->out_width; + dst_prop.height = pPort->out_height; + dst_prop.crop = pPort->out_crop; + + dst_prop.degree = pPort->hw_rotate; + dst_prop.hflip = pPort->hflip; + dst_prop.vflip = pPort->vflip; + dst_prop.exynosure = pPort->exynosure; + dst_prop.csc_range = pPort->csc_range; + + if (!exynosCvtEnsureSize(&src_prop, &dst_prop)) + goto fail_to_put; + + if (!exynosCvtSetProperpty(pPort->cvt, &src_prop, &dst_prop)) + goto fail_to_put; + + if (!exynosCvtConvert(pPort->cvt, inbuf, outbuf)) + goto fail_to_put; + + if (pExynos->pVideoPriv->video_fps) + _countFps(pPort); + + exynosUtilVideoBufferUnref(outbuf); + + return TRUE; + + fail_to_put: + if (outbuf) + exynosUtilVideoBufferUnref(outbuf); + + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, TRUE); + + return FALSE; +} + +static Bool +_exynosVideoSetHWPortsProperty(ScreenPtr pScreen, int nums) +{ + WindowPtr pWin = pScreen->root; + Atom atom_hw_ports; + + /* With "X_HW_PORTS", an application can know + * how many fimc devices XV uses. + */ + if (!pWin || !serverClient) + return FALSE; + + atom_hw_ports = MakeAtom("XV_HW_PORTS", strlen("XV_HW_PORTS"), TRUE); + + dixChangeWindowProperty(serverClient, + pWin, atom_hw_ports, XA_CARDINAL, 32, + PropModeReplace, 1, (unsigned int *) &nums, FALSE); + + return TRUE; +} + +static Bool +_exynosVideoSetOutputExternalProperty(DrawablePtr pDraw, Bool video_only) +{ + WindowPtr pWin; + Atom atom_external; + + XDBG_RETURN_VAL_IF_FAIL(pDraw != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pDraw->type == DRAWABLE_WINDOW, FALSE); + + pWin = (WindowPtr) pDraw; + + atom_external = + MakeAtom("XV_OUTPUT_EXTERNAL", strlen("XV_OUTPUT_EXTERNAL"), TRUE); + + dixChangeWindowProperty(clients[CLIENT_ID(pDraw->id)], + pWin, atom_external, XA_CARDINAL, 32, + PropModeReplace, 1, (unsigned int *) &video_only, + TRUE); + + XDBG_TRACE(MVDO, "pDraw(0x%lx) video-only(%s)\n", + pDraw->id, (video_only) ? "ON" : "OFF"); + + return TRUE; +} + +static void +_exynosVideoRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) +{ + ScreenPtr pScreen = ((DrawablePtr) pWin)->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + EXYNOSVideoPrivPtr pVideo = pExynos->pVideoPriv; + + if (pVideo->RestackWindow) { + pScreen->RestackWindow = pVideo->RestackWindow; + + if (pScreen->RestackWindow) + (*pScreen->RestackWindow) (pWin, pOldNextSib); + + pVideo->RestackWindow = pScreen->RestackWindow; + pScreen->RestackWindow = _exynosVideoRestackWindow; + } + + if (!xorg_list_is_empty(&layer_owners)) { + EXYNOSPortPrivPtr pCur = NULL, pNext = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &layer_owners, link) { + if (_exynosVideoInBranch(pWin, (WindowPtr) pCur->d.pDraw)) { + XDBG_TRACE(MVDO, "Do re-arrange. 0x%08x(0x%08x) \n", + _XID(pWin), _XID(pCur->d.pDraw)); + _exynosVideoArrangeLayerPos(pCur, TRUE); + break; + } + } + } +} + +static void +_exynosVideoBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + ScreenPtr pScreen = ((ScrnInfoPtr) data)->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + EXYNOSVideoPrivPtr pVideo = pExynos->pVideoPriv; + + pVideo->RestackWindow = pScreen->RestackWindow; + pScreen->RestackWindow = _exynosVideoRestackWindow; + + if (registered_handler && + _exynosVideoSetHWPortsProperty(pScreen, NUM_HW_LAYER)) { + RemoveBlockAndWakeupHandlers(_exynosVideoBlockHandler, + (WakeupHandlerProcPtr) NoopDDA, data); + registered_handler = FALSE; + } +} + +static Bool +_exynosVideoAddDrawableEvent(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoResource *resource; + void *ptr = NULL; + int ret; + + ret = dixLookupResourceByType(&ptr, pPort->d.pDraw->id, + event_drawable_type, NULL, DixWriteAccess); + if (ret == Success) { + return TRUE; + } + + resource = malloc(sizeof(EXYNOSVideoResource)); + if (resource == NULL) + return FALSE; + + if (!AddResource(pPort->d.pDraw->id, event_drawable_type, resource)) { + free(resource); + return FALSE; + } + + XDBG_TRACE(MVDO, "id(0x%08lx). \n", pPort->d.pDraw->id); + + resource->id = pPort->d.pDraw->id; + resource->type = event_drawable_type; + resource->pPort = pPort; + resource->pScrn = pPort->pScrn; + + return TRUE; +} + +static int +_exynosVideoRegisterEventDrawableGone(void *data, XID id) +{ + EXYNOSVideoResource *resource = (EXYNOSVideoResource *) data; + + XDBG_TRACE(MVDO, "id(0x%08lx). \n", id); + + if (!resource) + return Success; + + if (!resource->pPort || !resource->pScrn) + return Success; + + EXYNOSVideoStop(resource->pScrn, (pointer) resource->pPort, 1); + + free(resource); + + return Success; +} + +static Bool +_exynosVideoRegisterEventResourceTypes(void) +{ + event_drawable_type = + CreateNewResourceType(_exynosVideoRegisterEventDrawableGone, + "Sec Video Drawable"); + + if (!event_drawable_type) + return FALSE; + + return TRUE; +} + +static int +_exynosVideoCheckChange(EXYNOSPortPrivPtr pPort) +{ + int ret = CHANGED_NONE; + + if (pPort->d.id != pPort->old_d.id + || pPort->d.width != pPort->old_d.width + || pPort->d.height != pPort->old_d.height + || memcmp(&pPort->d.src, &pPort->old_d.src, sizeof(xRectangle)) + || pPort->old_secure != pPort->exynosure + || pPort->old_csc_range != pPort->csc_range) { + XDBG_DEBUG(MVDO, + "pPort(%d) old_src(%dx%d %d,%d %dx%d) : new_src(%dx%d %d,%d %dx%d)\n", + pPort->index, pPort->old_d.width, pPort->old_d.height, + pPort->old_d.src.x, pPort->old_d.src.y, + pPort->old_d.src.width, pPort->old_d.src.height, + pPort->d.width, pPort->d.height, pPort->d.src.x, + pPort->d.src.y, pPort->d.src.width, pPort->d.src.height); + XDBG_DEBUG(MVDO, + "old_secure(%d) old_csc(%d) : new_secure(%d) new_csc(%d)\n", + pPort->old_secure, pPort->old_csc_range, pPort->exynosure, + pPort->csc_range); + + ret += CHANGED_INPUT; + } + + if (memcmp(&pPort->d.dst, &pPort->old_d.dst, sizeof(xRectangle)) + || pPort->old_rotate != pPort->rotate + || pPort->old_hflip != pPort->hflip + || pPort->old_vflip != pPort->vflip) { + XDBG_DEBUG(MVDO, + "pPort(%d) old_dst(%d,%d %dx%d) : new_dst(%dx%d %dx%d)\n", + pPort->index, pPort->old_d.dst.x, pPort->old_d.dst.y, + pPort->old_d.dst.width, pPort->old_d.dst.height, + pPort->d.dst.x, pPort->d.dst.y, pPort->d.dst.width, + pPort->d.dst.height); + XDBG_DEBUG(MVDO, "old_rotate(%d) old_hflip(%d) old_vflip(%d)\n", + pPort->old_rotate, pPort->old_hflip, pPort->old_vflip); + XDBG_DEBUG(MVDO, "new_rotate (%d) new_hflip(%d) new_vflip(%d)\n", + pPort->rotate, pPort->hflip, pPort->vflip); + ret += CHANGED_OUTPUT; // output changed + } + + return ret; +} + +int +exynosVideoQueryImageAttrs(ScrnInfoPtr pScrn, + int id, + int *w, + int *h, int *pitches, int *offsets, int *lengths) +{ + int size = 0, tmp = 0; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) { + /* RGB565 */ + case FOURCC_SR16: + case FOURCC_RGB565: + size += (*w << 1); + if (pitches) + pitches[0] = size; + size *= *h; + if (lengths) + lengths[0] = size; + break; + /* RGB32 */ + case FOURCC_SR32: + case FOURCC_RGB32: + size += (*w << 2); + if (pitches) + pitches[0] = size; + size *= *h; + if (lengths) + lengths[0] = size; + break; + /* YUV420, 3 planar */ + case FOURCC_I420: + case FOURCC_S420: + case FOURCC_YV12: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) + pitches[0] = size; + + size *= *h; + if (offsets) + offsets[1] = size; + if (lengths) + lengths[0] = size; + + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) + pitches[1] = pitches[2] = tmp; + + tmp *= (*h >> 1); + size += tmp; + if (offsets) + offsets[2] = size; + if (lengths) + lengths[1] = tmp; + + size += tmp; + if (lengths) + lengths[2] = tmp; + + break; + /* YUV422, packed */ + case FOURCC_UYVY: + case FOURCC_SYVY: + case FOURCC_ITLV: + case FOURCC_SUYV: + case FOURCC_YUY2: + size = *w << 1; + if (pitches) + pitches[0] = size; + + size *= *h; + if (lengths) + lengths[0] = size; + break; + + /* YUV420, 2 planar */ + case FOURCC_SN12: + case FOURCC_NV12: + case FOURCC_SN21: + case FOURCC_NV21: + if (pitches) + pitches[0] = *w; + + size = (*w) * (*h); + if (offsets) + offsets[1] = size; + if (lengths) + lengths[0] = size; + + if (pitches) + pitches[1] = *w; + + tmp = (*w) * (*h >> 1); + size += tmp; + if (lengths) + lengths[1] = tmp; + break; + + /* YUV420, 2 planar, tiled */ + case FOURCC_ST12: + if (pitches) + pitches[0] = *w; + + size = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h)); + if (offsets) + offsets[1] = size; + if (lengths) + lengths[0] = size; + + if (pitches) + pitches[1] = *w; + + tmp = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h >> 1)); + size += tmp; + if (lengths) + lengths[1] = tmp; + break; + default: + return 0; + } + + return size; +} + +static int +EXYNOSVideoGetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 *value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_ROTATION)) { + *value = pPort->rotate; + return Success; + } + else if (attribute == _portAtom(PAA_HFLIP)) { + *value = pPort->hflip; + return Success; + } + else if (attribute == _portAtom(PAA_VFLIP)) { + *value = pPort->vflip; + return Success; + } + else if (attribute == _portAtom(PAA_PREEMPTION)) { + *value = pPort->preemption; + return Success; + } + else if (attribute == _portAtom(PAA_OUTPUT)) { + *value = pPort->usr_output; + return Success; + } + else if (attribute == _portAtom(PAA_SECURE)) { + *value = pPort->exynosure; + return Success; + } + else if (attribute == _portAtom(PAA_CSC_RANGE)) { + *value = pPort->csc_range; + return Success; + } + + return BadMatch; +} + +static int +EXYNOSVideoSetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_ROTATION)) { + pPort->rotate = value; + XDBG_DEBUG(MVDO, "rotate(%d) \n", (int) value); + return Success; + } + else if (attribute == _portAtom(PAA_HFLIP)) { + pPort->hflip = value; + XDBG_DEBUG(MVDO, "hflip(%d) \n", (int) value); + return Success; + } + else if (attribute == _portAtom(PAA_VFLIP)) { + pPort->vflip = value; + XDBG_DEBUG(MVDO, "vflip(%d) \n", (int) value); + return Success; + } + else if (attribute == _portAtom(PAA_PREEMPTION)) { + pPort->preemption = value; + XDBG_DEBUG(MVDO, "preemption(%d) \n", (int) value); + return Success; + } + else if (attribute == _portAtom(PAA_OUTPUT)) { + pPort->usr_output = (OUTPUT_LCD | OUTPUT_EXT | OUTPUT_FULL) & value; + + XDBG_DEBUG(MVDO, "output (%d) \n", (int) value); + + return Success; + } + else if (attribute == _portAtom(PAA_SECURE)) { + pPort->exynosure = value; + XDBG_DEBUG(MVDO, "exynosure(%d) \n", (int) value); + return Success; + } + else if (attribute == _portAtom(PAA_CSC_RANGE)) { + pPort->csc_range = value; + XDBG_DEBUG(MVDO, "csc_range(%d) \n", (int) value); + return Success; + } + + return Success; +} + +static void +EXYNOSVideoQueryBestSize(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + uint * p_w, uint * p_h, pointer data) +{ + EXYNOSCvtProp prop = { 0, }; + + if (!p_w && !p_h) + return; + + prop.width = dst_w; + prop.height = dst_h; + prop.crop.width = dst_w; + prop.crop.height = dst_h; + + if (exynosCvtEnsureSize(NULL, &prop)) { + if (p_w) + *p_w = prop.width; + if (p_h) + *p_h = prop.height; + } + else { + if (p_w) + *p_w = dst_w; + if (p_h) + *p_h = dst_h; + } +} + +/** + * Give image size and pitches. + */ +static int +EXYNOSVideoQueryImageAttributes(ScrnInfoPtr pScrn, + int id, + unsigned short *w, + unsigned short *h, int *pitches, int *offsets) +{ + int width, height, size; + + if (!w || !h) + return 0; + + width = (int) *w; + height = (int) *h; + + size = + exynosVideoQueryImageAttrs(pScrn, id, &width, &height, pitches, offsets, + NULL); + + *w = (unsigned short) width; + *h = (unsigned short) height; + + return size; +} + +/* coordinates : HW, SCREEN, PORT + * BadRequest : when video can't be shown or drawn. + * Success : A damage event(pixmap) and inbuf should be return. + * If can't return a damage event and inbuf, should be return + * BadRequest. + */ +static int +EXYNOSVideoPutImage(ScrnInfoPtr pScrn, + short src_x, short src_y, short dst_x, short dst_y, + short src_w, short src_h, short dst_w, short dst_h, + int id, uchar * buf, short width, short height, + Bool sync, RegionPtr clip_boxes, pointer data, + DrawablePtr pDraw) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + +#ifdef NO_CRTC_MODE + if (pExynos->isCrtcOn == FALSE) { + XDBG_WARNING(MVDO, "XV PutImage Disabled (No active CRTCs)\n"); + return BadRequest; + } +#endif + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pScrn)->pVideoPriv; + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + int output, ret; + Bool tvout = FALSE, lcdout = FALSE; + EXYNOSVideoBuf *inbuf = NULL; + int old_drawing; + +#ifdef LAYER_MANAGER + if (pPort->lyr_client_id == LYR_ERROR_ID) { + char client_name[20] = { 0 }; + if (snprintf + (client_name, sizeof(client_name), "XV_PUTIMAGE-%d", + pPort->index) < 0) { + XDBG_ERROR(MVDO, "Can't register layer manager client\n"); + return BadRequest; + } + pPort->lyr_client_id = + exynosLayerMngRegisterClient(pScrn, client_name, 2); + XDBG_RETURN_VAL_IF_FAIL(pPort->lyr_client_id != LYR_ERROR_ID, + BadRequest); + pPort->lpos = LAYER_NONE; + exynosLayerMngAddEvent(pPort->lyr_client_id, EVENT_LAYER_RELEASE, + _exynosVideoReleaseLayerCallback, pPort); + } +#endif + if (!_exynosVideoSupportID(id)) { + XDBG_ERROR(MVDO, "'%c%c%c%c' not supported.\n", FOURCC_STR(id)); + return BadRequest; + } + + TTRACE_VIDEO_BEGIN("XORG:XV:PUTIMAGE"); + + XDBG_TRACE(MVDO, "======================================= \n"); + XDBG_DEBUG(MVDO, "src:(x%d,y%d w%d-h%d), dst:(x%d,y%d w%d-h%d)\n", + src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); + XDBG_DEBUG(MVDO, "image size:(w%d-h%d) fourcc(%c%c%c%c)\n", width, height, + FOURCC_STR(id)); + pPort->pScrn = pScrn; + pPort->d.id = id; + pPort->d.buf = buf; + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_IA) { + unsigned int keys[PLANAR_CNT] = { 0, }; + CARD32 cur, sub; + char temp[64]; + + cur = GetTimeInMillis(); + sub = cur - pPort->prev_time; + pPort->prev_time = cur; + temp[0] = '\0'; + if (IS_ZEROCOPY(id)) { + _exynosVideoGetKeys(pPort, keys, NULL); + snprintf(temp, sizeof(temp), "%d,%d,%d", keys[0], keys[1], keys[2]); + } + ErrorF("pPort(%p) put interval(%s) : %6" PRIXID " ms\n", pPort, temp, + sub); + } + + if (IS_ZEROCOPY(pPort->d.id)) { + unsigned int keys[PLANAR_CNT] = { 0, }; + int i; + + if (_exynosVideoGetKeys(pPort, keys, NULL)) { + TTRACE_VIDEO_END(); + return BadRequest; + } + + for (i = 0; i < INBUF_NUM; i++) + if (pPort->inbuf[i] && pPort->inbuf[i]->keys[0] == keys[0]) { + XDBG_WARNING(MVDO, "got flink_id(%d) twice!\n", keys[0]); + _exynosVideoSendReturnBufferMessage(pPort, NULL, keys); + TTRACE_VIDEO_END(); + return Success; + } + } + + pPort->d.width = width; + pPort->d.height = height; + pPort->d.src.x = src_x; + pPort->d.src.y = src_y; + pPort->d.src.width = src_w; + pPort->d.src.height = src_h; + pPort->d.dst.x = dst_x; /* included pDraw'x */ + pPort->d.dst.y = dst_y; /* included pDraw'y */ + pPort->d.dst.width = dst_w; + pPort->d.dst.height = dst_h; + pPort->d.sync = FALSE; + if (sync) + XDBG_WARNING(MVDO, "not support sync.\n"); + pPort->d.data = data; + pPort->d.pDraw = pDraw; + if (clip_boxes) { + if (!pPort->d.clip_boxes) + pPort->d.clip_boxes = RegionCreate(NullBox, 0); + RegionCopy(pPort->d.clip_boxes, clip_boxes); + } + + old_drawing = pPort->drawing; + pPort->drawing = _exynosVideodrawingOn(pPort); + if (pDraw) { + XDBG_DEBUG(MVDO, "pixmap:(x%d,y%d w%d-h%d) on:%d\n", + pDraw->x, pDraw->y, pDraw->width, pDraw->height, + pPort->drawing); + } + if (old_drawing != pPort->drawing) { + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, TRUE); + + } + + _exynosVideoGetRotation(pPort, &pPort->hw_rotate); + + if (pPort->drawing == ON_FB && pVideo->screen_rotate_degree > 0) + exynosUtilRotateRect(pExynosMode->main_lcd_mode.hdisplay, + pExynosMode->main_lcd_mode.vdisplay, + &pPort->d.dst, pVideo->screen_rotate_degree); + + if (pPort->exynosure) + if (pPort->drawing != ON_FB) { + XDBG_ERROR(MVDO, "exynosure video should drawn on FB.\n"); + TTRACE_VIDEO_END(); + return BadRequest; + } + + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) + if (!_exynosVideoAddDrawableEvent(pPort)) { + TTRACE_VIDEO_END(); + return BadRequest; + } + + if (pPort->stream_cnt == 0) { + pPort->stream_cnt++; + + if (pPort->preemption > -1) + streaming_ports++; + + XDBG_SECURE(MVDO, + "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) exynosure(%d) range(%d) usr_output(%x) on(%s)\n", + pPort->index, streaming_ports, pPort->rotate, pPort->hflip, + pPort->vflip, pPort->exynosure, pPort->csc_range, + pPort->usr_output, drawing_type[pPort->drawing]); + XDBG_SECURE(MVDO, + "id(%c%c%c%c) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n", + FOURCC_STR(id), width, height, src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + + if (streaming_ports > 1) + _exynosVideoStopTvout(pPort->pScrn); + } + else if (pPort->stream_cnt == 1) + pPort->stream_cnt++; + + int frame_changed = _exynosVideoCheckChange(pPort); + + switch (frame_changed) { + case CHANGED_INPUT: + if (pPort->cvt) { + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseInBuffer(pPort); + pPort->inbuf_is_fb = FALSE; + } + if (pPort->tv) { + _exynosVideoUngrabTvout(pPort); + _exynosVideoCloseInBuffer(pPort); + pPort->inbuf_is_fb = FALSE; + pPort->punched = FALSE; + } + break; + case CHANGED_OUTPUT: + if (pPort->cvt) { + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, FALSE); + pPort->inbuf_is_fb = FALSE; + } + if (pPort->tv) { + EXYNOSCvt *old_tv_cvt = exynosVideoTvGetConverter(pPort->tv); + + exynosVideoTvSetAttributes(pPort->tv, pPort->hw_rotate, + pPort->hflip, pPort->vflip); + if (exynosVideoTvResizeOutput + (pPort->tv, &pPort->d.src, &pPort->d.dst) + == TRUE) { + EXYNOSCvt *new_tv_cvt = exynosVideoTvGetConverter(pPort->tv); + + if (new_tv_cvt != NULL) { + if (exynosCvtGetStamp(new_tv_cvt) != + exynosCvtGetStamp(old_tv_cvt)) { + EXYNOSLayer *layer = exynosVideoTvGetLayer(pPort->tv); + + /* TODO: Clear if fail */ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, BadRequest); + exynosLayerRemoveNotifyFunc(layer, + _exynosVideoLayerNotifyFunc); + exynosLayerEnableVBlank(layer, FALSE); + exynosCvtAddCallback(new_tv_cvt, + _exynosVideoTvoutCvtCallback, + pPort); + } + } + else { + EXYNOSLayer *layer = exynosVideoTvGetLayer(pPort->tv); + + /* TODO: Clear if fail */ + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, BadRequest); + exynosLayerEnableVBlank(layer, TRUE); + if (!exynosLayerExistNotifyFunc + (layer, _exynosVideoLayerNotifyFunc)) { + exynosLayerAddNotifyFunc(layer, + _exynosVideoLayerNotifyFunc, + pPort); + } + } + } + else { + exynosVideoTvDisconnect(pPort->tv); + pPort->tv = NULL; + } + pPort->punched = FALSE; + pPort->wait_vbuf = NULL; + } + break; + case CHANGED_ALL: + if (pPort->cvt) { + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, FALSE); + _exynosVideoCloseInBuffer(pPort); + pPort->inbuf_is_fb = FALSE; + } + if (pPort->tv) { + _exynosVideoUngrabTvout(pPort); + _exynosVideoCloseInBuffer(pPort); + pPort->inbuf_is_fb = FALSE; + pPort->punched = FALSE; + } + break; + default: + break; + } + + if (!_exynosVideoCalculateSize(pPort)) { + TTRACE_VIDEO_END(); + return BadRequest; + } + + output = _exynosVideoGetTvoutMode(pPort); + if (!(output & OUTPUT_LCD) && pPort->old_output & OUTPUT_LCD) { + /* If the video of LCD becomes off, we also turn off LCD layer. */ + if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) { + PixmapPtr pPixmap = _getPixmap(pPort->d.pDraw); + EXYNOSPixmapPriv *privPixmap = exaGetPixmapDriverPrivate(pPixmap); + + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + if (pPixmap->devPrivate.ptr && privPixmap->size > 0) + memset(pPixmap->devPrivate.ptr, 0, privPixmap->size); + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + DamageDamageRegion(pPort->d.pDraw, pPort->d.clip_boxes); + } + else { + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseOutBuffer(pPort, TRUE); + } + } + + if (pPort->d.id == FOURCC_SR32 && + pPort->in_crop.width == pPort->out_crop.width && + pPort->in_crop.height == pPort->out_crop.height && + pPort->hw_rotate == 0) + pPort->inbuf_is_fb = TRUE; + else + pPort->inbuf_is_fb = FALSE; + + inbuf = _exynosVideoGetInbuf(pPort); + if (!inbuf) { + TTRACE_VIDEO_END(); + return BadRequest; + } + + /* punch here not only LCD but also HDMI. */ + if (pPort->drawing == ON_FB) + _exynosVideoPunchDrawable(pPort); + + /* HDMI */ + if (output & OUTPUT_EXT) + tvout = _exynosVideoPutImageTvout(pPort, output, inbuf); + else { + _exynosVideoUngrabTvout(pPort); + + EXYNOSWb *wb = exynosWbGet(); + + if (wb) + exynosWbSetSecure(wb, pPort->exynosure); + } + + /* LCD */ + if (output & OUTPUT_LCD) { + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + if (pExynos->isLcdOff) + XDBG_TRACE(MVDO, "port(%d) put image after dpms off.\n", + pPort->index); + else if (pPort->inbuf_is_fb) + lcdout = _exynosVideoPutImageInbuf(pPort, inbuf); + else + lcdout = _exynosVideoPutImageInternal(pPort, inbuf); + } + + if (lcdout || tvout) { + ret = Success; + } + else { + if (IS_ZEROCOPY(pPort->d.id)) { + int i; + + for (i = 0; i < INBUF_NUM; i++) + if (pPort->inbuf[i] == inbuf) { + pPort->inbuf[i] = NULL; + exynosUtilRemoveFreeVideoBufferFunc(inbuf, + _exynosVideoFreeInbuf, + pPort); + break; + } + XDBG_WARNING_IF_FAIL(inbuf->ref_cnt == 1); + } + else + XDBG_WARNING_IF_FAIL(inbuf->ref_cnt == 2); + + ret = BadRequest; + } + + /* decrease ref_cnt here to pass ownership of inbuf to converter or tvout. + * in case of zero-copy, it will be really freed + * when converting is finished or tvout is finished. + */ + exynosUtilVideoBufferUnref(inbuf); + + pPort->old_d = pPort->d; + pPort->old_hflip = pPort->hflip; + pPort->old_vflip = pPort->vflip; + pPort->old_rotate = pPort->rotate; + pPort->old_output = output; + pPort->old_secure = pPort->exynosure; + pPort->old_csc_range = pPort->csc_range; +#ifdef LAYER_MANAGER + pPort->old_lpos = pPort->lpos; +#endif + XDBG_TRACE(MVDO, "=======================================.. \n"); + + TTRACE_VIDEO_END(); + + return ret; +} + +static int +EXYNOSVideoDDPutImage(ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr format, + unsigned char *data, Bool sync, CARD16 width, + CARD16 height) +{ + EXYNOSVideoPortInfo *info = _port_info(pDraw); + int ret; + + if (info) { + info->client = client; + info->pp = pPort; + } + + ret = ddPutImage(client, pDraw, pPort, pGC, + src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h, + format, data, sync, width, height); + + return ret; +} + +static void +EXYNOSVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (!exit) + return; + + XDBG_DEBUG(MVDO, "exit (%d) \n", exit); + + _exynosVideoStreamOff(pPort); + + pPort->preemption = 0; + pPort->rotate = 0; + pPort->hflip = 0; + pPort->vflip = 0; + pPort->punched = FALSE; +} + +/** + * Set up all our internal structures. + */ +static XF86VideoAdaptorPtr +exynosVideoSetupImageVideo(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr pAdaptor; + EXYNOSPortPrivPtr pPort; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int i; + + pAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + + (sizeof(DevUnion) + + sizeof(EXYNOSPortPriv)) * EXYNOS_MAX_PORT); + if (!pAdaptor) + return NULL; + + dummy_encoding[0].width = pScreen->width; + dummy_encoding[0].height = pScreen->height; + + pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask; + pAdaptor->flags = VIDEO_OVERLAID_IMAGES; + pAdaptor->name = "EXYNOS supporting Software Video Conversions"; + pAdaptor->nEncodings = + sizeof(dummy_encoding) / sizeof(XF86VideoEncodingRec); + pAdaptor->pEncodings = dummy_encoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = formats; + pAdaptor->nPorts = EXYNOS_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion *) (&pAdaptor[1]); + + pPort = (EXYNOSPortPrivPtr) (&pAdaptor->pPortPrivates[EXYNOS_MAX_PORT]); + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + pAdaptor->pPortPrivates[i].ptr = &pPort[i]; + pPort[i].index = i; + pPort[i].usr_output = OUTPUT_LCD | OUTPUT_EXT | OUTPUT_FULL; + pPort[i].outbuf_cvting = -1; +#ifdef LAYER_MANAGER + pPort[i].lpos = LAYER_NONE; + pPort[i].lyr_client_id = LYR_ERROR_ID; +#endif + } + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = attributes; + pAdaptor->nImages = NUM_IMAGES; + pAdaptor->pImages = images; + + pAdaptor->GetPortAttribute = EXYNOSVideoGetPortAttribute; + pAdaptor->SetPortAttribute = EXYNOSVideoSetPortAttribute; + pAdaptor->QueryBestSize = EXYNOSVideoQueryBestSize; + pAdaptor->QueryImageAttributes = EXYNOSVideoQueryImageAttributes; + pAdaptor->PutImage = EXYNOSVideoPutImage; + pAdaptor->StopVideo = EXYNOSVideoStop; + + if (!_exynosVideoRegisterEventResourceTypes()) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to register EventResourceTypes. \n"); + return NULL; + } + return pAdaptor; +} + +static void +EXYNOSVideoReplacePutImageFunc(ScreenPtr pScreen) +{ + int i; + + XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, + XvGetScreenKey()); + + if (!xvsp) + return; + + for (i = 0; i < xvsp->nAdaptors; i++) { + XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; + + if (pAdapt->ddPutImage) { + ddPutImage = pAdapt->ddPutImage; + pAdapt->ddPutImage = EXYNOSVideoDDPutImage; + break; + } + } + + if (!dixRegisterPrivateKey + (VideoPortKey, PRIVATE_WINDOW, sizeof(EXYNOSVideoPortInfo))) + return; + if (!dixRegisterPrivateKey + (VideoPortKey, PRIVATE_PIXMAP, sizeof(EXYNOSVideoPortInfo))) + return; +} + +#ifdef XV +/** + * Set up everything we need for Xv. + */ +Bool +exynosVideoInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + EXYNOSVideoPrivPtr pVideo; + + TTRACE_VIDEO_BEGIN("XORG:XV:INIT"); + + pVideo = (EXYNOSVideoPrivPtr) calloc(sizeof(EXYNOSVideoPriv), 1); + if (!pVideo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't alloc memory. %s:%d\n", __func__, __FILE__, + __LINE__); + goto bail; + } + + pVideo->pAdaptor[0] = exynosVideoSetupImageVideo(pScreen); + if (!pVideo->pAdaptor[0]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't setup adaptor 0\n", __func__); + goto bail; + } + + pVideo->pAdaptor[1] = exynosVideoSetupVirtualVideo(pScreen); + if (!pVideo->pAdaptor[1]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't setup adaptor 1\n", __func__); + goto bail; + } + + pVideo->pAdaptor[2] = exynosVideoSetupDisplayVideo(pScreen); + if (!pVideo->pAdaptor[2]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't setup adaptor 2\n", __func__); + goto bail; + } + + pVideo->pAdaptor[3] = exynosVideoSetupCloneVideo(pScreen); + if (!pVideo->pAdaptor[3]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't setup adaptor 3\n", __func__); + goto bail; + } + + if (!xf86XVScreenInit(pScreen, pVideo->pAdaptor, ADAPTOR_NUM)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s. Can't init XV\n", __func__); + goto bail; + } +/* TODO: Check error*/ + EXYNOSVideoReplacePutImageFunc(pScreen); + exynosVirtualVideoReplacePutStillFunc(pScreen); + + if (registered_handler == FALSE) { + if (!RegisterBlockAndWakeupHandlers(_exynosVideoBlockHandler, + (WakeupHandlerProcPtr) NoopDDA, + pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s. Can't register handler\n", __func__); + goto bail; + } + registered_handler = TRUE; + } + + pExynos->pVideoPriv = pVideo; + xorg_list_init(&layer_owners); + + TTRACE_VIDEO_END(); + + return TRUE; + bail: + if (pVideo) { + int i; + + for (i = 0; i < ADAPTOR_NUM; i++) { + if (pVideo->pAdaptor[i]) { + /* TODO: Free pPORT */ + free(pVideo->pAdaptor[i]); + pVideo->pAdaptor[i] = NULL; + } + } + free(pVideo); + } + TTRACE_VIDEO_END(); + return FALSE; +} + +/** + * Shut down Xv, used on regeneration. + */ +void +exynosVideoFini(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + EXYNOSVideoPrivPtr pVideo = pExynos->pVideoPriv; + EXYNOSPortPrivPtr pCur = NULL, pNext = NULL; + int i; + + xorg_list_for_each_entry_safe(pCur, pNext, &layer_owners, link) { + if (pCur->tv) { + exynosVideoTvDisconnect(pCur->tv); + pCur->tv = NULL; + } + + if (pCur->d.clip_boxes) { + RegionDestroy(pCur->d.clip_boxes); + pCur->d.clip_boxes = NULL; + } + } + + for (i = 0; i < ADAPTOR_NUM; i++) + if (pVideo->pAdaptor[i]) + free(pVideo->pAdaptor[i]); + + free(pVideo); + pExynos->pVideoPriv = NULL; +} + +#endif + +void +exynosVideoDpms(ScrnInfoPtr pScrn, Bool on) +{ + if (!on) { + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + XF86VideoAdaptorPtr pAdaptor = pExynos->pVideoPriv->pAdaptor[0]; + int i; + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + EXYNOSPortPrivPtr pPort = + (EXYNOSPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + if (pPort->stream_cnt == 0) + continue; + XDBG_TRACE(MVDO, "port(%d) cvt stop.\n", pPort->index); + _exynosVideoCloseConverter(pPort); + _exynosVideoCloseInBuffer(pPort); + } + } +} + +void +exynosVideoScreenRotate(ScrnInfoPtr pScrn, int degree) +{ +#ifndef LAYER_MANAGER + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSVideoPrivPtr pVideo = pExynos->pVideoPriv; + int old_degree; + + if (pVideo->screen_rotate_degree == degree) + return; + + old_degree = pVideo->screen_rotate_degree; + pVideo->screen_rotate_degree = degree; + XDBG_DEBUG(MVDO, "screen rotate degree: %d\n", degree); + + if (pExynos->isLcdOff) + return; + + EXYNOSPortPrivPtr pCur = NULL, pNext = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &layer_owners, link) { + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + EXYNOSVideoBuf *old_vbuf, *rot_vbuf; + xRectangle rot_rect, dst_rect; + int rot_width, rot_height; + int scn_width, scn_height; + int degree_diff = degree - old_degree; + + if (!pCur->layer) + continue; + + old_vbuf = exynosLayerGetBuffer(pCur->layer); + XDBG_RETURN_IF_FAIL(old_vbuf != NULL); + + rot_width = old_vbuf->width; + rot_height = old_vbuf->height; + rot_rect = old_vbuf->crop; + exynosUtilRotateArea(&rot_width, &rot_height, &rot_rect, degree_diff); + + rot_vbuf = + exynosUtilAllocVideoBuffer(pScrn, FOURCC_RGB32, rot_width, + rot_height, + (pExynos->scanout) ? TRUE : FALSE, FALSE, + pCur->exynosure); + XDBG_RETURN_IF_FAIL(rot_vbuf != NULL); + rot_vbuf->crop = rot_rect; + + exynosUtilConvertBos(pScrn, 0, + old_vbuf->bo[0], old_vbuf->width, old_vbuf->height, + &old_vbuf->crop, old_vbuf->width * 4, + rot_vbuf->bo[0], rot_vbuf->width, rot_vbuf->height, + &rot_vbuf->crop, rot_vbuf->width * 4, FALSE, + degree_diff); + + tbm_bo_map(rot_vbuf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ); + tbm_bo_unmap(rot_vbuf->bo[0]); + + exynosLayerGetRect(pCur->layer, NULL, &dst_rect); + + scn_width = + (old_degree % + 180) ? pExynosMode->main_lcd_mode. + vdisplay : pExynosMode->main_lcd_mode.hdisplay; + scn_height = + (old_degree % + 180) ? pExynosMode->main_lcd_mode. + hdisplay : pExynosMode->main_lcd_mode.vdisplay; + + exynosUtilRotateRect(scn_width, scn_height, &dst_rect, degree_diff); + + exynosLayerFreezeUpdate(pCur->layer, TRUE); + exynosLayerSetRect(pCur->layer, &rot_vbuf->crop, &dst_rect); + exynosLayerFreezeUpdate(pCur->layer, FALSE); + exynosLayerSetBuffer(pCur->layer, rot_vbuf); + + exynosUtilVideoBufferUnref(rot_vbuf); + + _exynosVideoCloseConverter(pCur); + } +#endif +} + +void +exynosVideoSwapLayers(ScreenPtr pScreen) +{ + EXYNOSPortPrivPtr pCur = NULL, pNext = NULL; + EXYNOSPortPrivPtr pPort1 = NULL, pPort2 = NULL; + + xorg_list_for_each_entry_safe(pCur, pNext, &layer_owners, link) { + if (!pPort1) + pPort1 = pCur; + else if (!pPort2) + pPort2 = pCur; + } + + if (pPort1 && pPort2) { +#ifndef LAYER_MANAGER + exynosLayerSwapPos(pPort1->layer, pPort2->layer); + XDBG_TRACE(MVDO, "%p : %p \n", pPort1->layer, pPort2->layer); +#else + exynosLayerMngSwapPos(pPort1->lyr_client_id, pPort1->output, + pPort1->lpos, pPort2->lyr_client_id, + pPort2->output, pPort2->lpos); + XDBG_TRACE(MVDO, "SWAP %d : %d \n", pPort1->lpos, pPort2->lpos); +#endif + } +} + +Bool +exynosVideoIsSecureMode(ScrnInfoPtr pScrn) +{ + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + XF86VideoAdaptorPtr pAdaptor = pExynos->pVideoPriv->pAdaptor[0]; + int i; + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + EXYNOSPortPrivPtr pPort = + (EXYNOSPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + + if (pPort->exynosure) { + XDBG_TRACE(MVDO, "pPort(%d) is exynosure.\n", pPort->index); + return TRUE; + } + } + + XDBG_TRACE(MVDO, "no exynosure port.\n"); + + return FALSE; +} diff --git a/src/xv/sec_video.h b/src/xv/exynos_video.h index 54888bc..4800630 100644 --- a/src/xv/sec_video.h +++ b/src/xv/exynos_video.h @@ -27,20 +27,18 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -#ifndef SEC_VIDEO_H -#define SEC_VIDEO_H +#ifndef EXYNOS_VIDEO_H +#define EXYNOS_VIDEO_H -#define ADAPTOR_NUM 3 +#define ADAPTOR_NUM 4 -enum -{ +enum { OUTPUT_MODE_DEFAULT, OUTPUT_MODE_TVOUT, OUTPUT_MODE_EXT_ONLY, }; -typedef struct -{ +typedef struct { #ifdef XV XF86VideoAdaptorPtr pAdaptor[ADAPTOR_NUM]; #endif @@ -62,25 +60,23 @@ typedef struct int screen_rotate_degree; /* for configure notify */ - RestackWindowProcPtr RestackWindow; + RestackWindowProcPtr RestackWindow; -} SECVideoPriv, *SECVideoPrivPtr; +} EXYNOSVideoPriv, *EXYNOSVideoPrivPtr; -Bool secVideoInit (ScreenPtr pScreen); -void secVideoFini (ScreenPtr pScreen); +Bool exynosVideoInit(ScreenPtr pScreen); +void exynosVideoFini(ScreenPtr pScreen); -void secVideoDpms (ScrnInfoPtr pScrn, Bool on); -void secVideoScreenRotate (ScrnInfoPtr pScrn, int degree); -void secVideoSwapLayers (ScreenPtr pScreen); +void exynosVideoDpms(ScrnInfoPtr pScrn, Bool on); +void exynosVideoScreenRotate(ScrnInfoPtr pScrn, int degree); +void exynosVideoSwapLayers(ScreenPtr pScreen); -int secVideoQueryImageAttrs (ScrnInfoPtr pScrn, - int id, - int *w, - int *h, - int *pitches, - int *offsets, - int *lengths); +int exynosVideoQueryImageAttrs(ScrnInfoPtr pScrn, + int id, + int *w, + int *h, int *pitches, int *offsets, + int *lengths); -Bool secVideoIsSecureMode (ScrnInfoPtr pScrn); +Bool exynosVideoIsSecureMode(ScrnInfoPtr pScrn); -#endif // SEC_VIDEO_H +#endif // EXYNOS_VIDEO_H diff --git a/src/xv/exynos_video_clone.c b/src/xv/exynos_video_clone.c new file mode 100644 index 0000000..5327544 --- /dev/null +++ b/src/xv/exynos_video_clone.c @@ -0,0 +1,380 @@ +/* + * xserver-xorg-video-exynos + * + * Copyright 2014 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Junkyeong Kim <jk0430.kim@samsung.com> + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <pixman.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include <fourcc.h> + +#include <xf86xv.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_video_clone.h" +#include "exynos_video_fourcc.h" +#include "exynos_layer.h" + +#include "fimg2d.h" + +#define EXYNOS_MAX_PORT 1 +#define LAYER_BUF_CNT 3 +#define OUTBUF_NUM 3 + +static XF86VideoEncodingRec dummy_encoding[] = { + {0, "XV_IMAGE", -1, -1, {1, 1}}, + {1, "XV_IMAGE", 4224, 4224, {1, 1}}, +}; + +static XF86VideoFormatRec formats[] = { + {16, TrueColor}, + {24, TrueColor}, + {32, TrueColor}, +}; + +static XF86AttributeRec attributes[] = { + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CLONE"}, +}; + +typedef enum { + PAA_MIN, + PAA_FREEZE, + PAA_ROTATE, + PAA_MAX +} EXYNOSPortAttrAtom; + +static struct { + EXYNOSPortAttrAtom paa; + const char *name; + Atom atom; +} atoms[] = { + { + PAA_FREEZE, "_USER_WM_PORT_ATTRIBUTE_FREEZE", None}, { +PAA_ROTATE, "_USER_WM_PORT_ATTRIBUTE_ROTATE", None},}; + +/* EXYNOS port information structure */ +typedef struct { + int index; + + /* attributes */ + Bool freeze; + int degree; + ScrnInfoPtr pScrn; + + /* writeback */ + EXYNOSWb *wb; + + struct xorg_list link; +} EXYNOSPortPriv, *EXYNOSPortPrivPtr; + +typedef struct _EXYNOSCloneVideoResource { + XID id; + RESTYPE type; + + EXYNOSPortPrivPtr pPort; + ScrnInfoPtr pScrn; +} EXYNOSCloneVideoResource; + +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) +#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) +#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) + +EXYNOSPortPrivPtr g_clone_port; + +static Atom +_portAtom(EXYNOSPortAttrAtom paa) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) { + if (paa == atoms[i].paa) { + if (atoms[i].atom == None) + atoms[i].atom = MakeAtom(atoms[i].name, + strlen(atoms[i].name), TRUE); + + return atoms[i].atom; + } + } + + XDBG_ERROR(MCLON, "Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static int +EXYNOSCloneVideoGetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 *value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_FREEZE)) { + *value = pPort->freeze; + return Success; + } + else if (attribute == _portAtom(PAA_ROTATE)) { + *value = pPort->degree; + return Success; + } + + return BadMatch; +} + +static int +EXYNOSCloneVideoSetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_FREEZE)) { + if (!pPort->wb) { + XDBG_ERROR(MCLON, "do PutVideo first\n"); + return BadMatch; + } + if (pPort->freeze == value) { + XDBG_WARNING(MCLON, "same freeze cmd(%d)\n", (int) value); + return Success; + } + + pPort->freeze = value; + XDBG_DEBUG(MCLON, "freeze(%d)\n", (int) value); + + if (value == 1) + exynosWbPause(pPort->wb); + else + exynosWbResume(pPort->wb); + return Success; + } + else if (attribute == _portAtom(PAA_ROTATE)) { + if (pPort->degree != value) { + pPort->degree = value; + if (pPort->wb) { + XDBG_DEBUG(MCLON, "rotate(%d)\n", (int) value); + exynosWbSetRotate(pPort->wb, pPort->degree); + } + } + + return Success; + } + + return BadMatch; +} + +static int +EXYNOSCloneVideoPutVideo(ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = pExynos->pExynosMode; + int wb_hz; + + XDBG_DEBUG(MCLON, "EXYNOSCloneVideoPutVideo start\n"); + + if (pDraw->type != DRAWABLE_WINDOW) { + XDBG_ERROR(MCLON, "Fail : pDraw->type is not DRAWABLE_WINDOW.\n"); + return BadRequest; + } + + pPort->pScrn = pScrn; + + if (pPort->wb) { + XDBG_ERROR(MCLON, "Fail : wb(%p) already exists.\n", pPort->wb); + return BadRequest; + } + + if (exynosWbIsOpened()) { + XDBG_ERROR(MCLON, "Fail : wb(%d) already opened.\n", exynosWbGet()); + return BadRequest; + } + + if (pExynos->set_mode == DISPLAY_SET_MODE_MIRROR) { + XDBG_ERROR(MCLON, "Fail : wb already set DISPLAY_SET_MODE_MIRROR.\n"); + return BadRequest; + } + + wb_hz = + (pExynos->wb_hz > + 0) ? pExynos->wb_hz : pExynosMode->ext_connector_mode.vrefresh; + XDBG_TRACE(MCLON, "wb_hz(%d) vrefresh(%d)\n", pExynos->wb_hz, + pExynosMode->ext_connector_mode.vrefresh); + + pPort->wb = exynosWbOpen(pPort->pScrn, FOURCC_RGB32, + pDraw->width, pDraw->height, + pExynos->scanout, wb_hz, FALSE); + XDBG_RETURN_VAL_IF_FAIL(pPort->wb != NULL, BadAlloc); + + if (pPort->wb) { + exynosWbSetRotate(pPort->wb, pPort->degree); + XDBG_DEBUG(MCLON, "pPort->degree : %d\n", pPort->degree); + exynosWbSetTvout(pPort->wb, TRUE); + + XDBG_TRACE(MCLON, "wb(%p) start.\n", pPort->wb); + if (!exynosWbStart(pPort->wb)) { + XDBG_ERROR(MCLON, "wb(%p) start fail.\n", pPort->wb); + exynosWbClose(pExynos->wb_clone); + pPort->wb = NULL; + return BadDrawable; + } + } + + if (!exynosWbIsRunning()) { + XDBG_WARNING(MCLON, "wb is stopped.\n"); + return BadRequest; + } + + XDBG_TRACE(MCLON, "wb(%p), running(%d).\n", pPort->wb, exynosWbIsRunning()); + pExynos->set_mode = DISPLAY_SET_MODE_MIRROR; + + return Success; +} + +static void +EXYNOSCloneVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + + XDBG_TRACE(MCLON, "exit (%d) \n", exit); + + if (!exit) + return; + + if (pPort->wb) { + exynosWbClose(pPort->wb); + XDBG_TRACE(MCLON, "excuted\n"); + } + pPort->wb = NULL; + pPort->freeze = 0; + pPort->degree = 0; + pExynos->set_mode = DISPLAY_SET_MODE_OFF; +} + +int +EXYNOSCloneVideoSetDPMS(ScrnInfoPtr pScrn, Bool onoff) +{ + EXYNOSPortPrivPtr pPort = g_clone_port; + + if (onoff == TRUE) { + if (pPort->wb) { + exynosWbSetRotate(pPort->wb, pPort->degree); + XDBG_DEBUG(MCLON, "dpms pPort->degree : %d\n", pPort->degree); + exynosWbSetTvout(pPort->wb, TRUE); + + XDBG_TRACE(MCLON, "dpms wb(%p) start.\n", pPort->wb); + if (!exynosWbStart(pPort->wb)) { + XDBG_ERROR(MCLON, "dpms wb(%p) start fail.\n", pPort->wb); + pPort->wb = NULL; + } + } + } + else { + if (pPort->wb) { + exynosWbStop(pPort->wb, FALSE); + XDBG_TRACE(MCLON, "dpms stop\n"); + } + } + + return 0; +} + +static void +EXYNOSCloneVideoQueryBestSize(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + if (p_w) + *p_w = (unsigned int) dst_w & (~0x1); + if (p_h) + *p_h = (unsigned int) dst_h & (~0x1); +} + +XF86VideoAdaptorPtr +exynosVideoSetupCloneVideo(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr pAdaptor; + EXYNOSPortPrivPtr pPort; + int i; + + pAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + + (sizeof(DevUnion) + + sizeof(EXYNOSPortPriv)) * EXYNOS_MAX_PORT); + if (!pAdaptor) + return NULL; + + dummy_encoding[0].width = pScreen->width; + dummy_encoding[0].height = pScreen->height; + + pAdaptor->type = XvWindowMask | XvInputMask | XvVideoMask; + pAdaptor->flags = VIDEO_OVERLAID_IMAGES; + pAdaptor->name = "EXYNOS Clone Video"; + pAdaptor->nEncodings = + sizeof(dummy_encoding) / sizeof(XF86VideoEncodingRec); + pAdaptor->pEncodings = dummy_encoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = formats; + pAdaptor->nPorts = EXYNOS_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion *) (&pAdaptor[1]); + + pPort = (EXYNOSPortPrivPtr) (&pAdaptor->pPortPrivates[EXYNOS_MAX_PORT]); + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + pAdaptor->pPortPrivates[i].ptr = &pPort[i]; + pPort[i].index = i; + pPort[i].freeze = 0; + pPort[i].degree = 0; + } + + g_clone_port = pPort; + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = attributes; + + pAdaptor->GetPortAttribute = EXYNOSCloneVideoGetPortAttribute; + pAdaptor->SetPortAttribute = EXYNOSCloneVideoSetPortAttribute; + pAdaptor->PutVideo = EXYNOSCloneVideoPutVideo; + pAdaptor->StopVideo = EXYNOSCloneVideoStop; + pAdaptor->QueryBestSize = EXYNOSCloneVideoQueryBestSize; + + return pAdaptor; +} diff --git a/src/xv/exynos_video_clone.h b/src/xv/exynos_video_clone.h new file mode 100644 index 0000000..bf2526e --- /dev/null +++ b/src/xv/exynos_video_clone.h @@ -0,0 +1,37 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2014 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Junkyeong Kim <jk0430.kim@samsung.com> + +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 __SEC_VIDEO_CLONE_H__ +#define __SEC_VIDEO_CLONE_H__ + +/* setup clone adaptor */ +XF86VideoAdaptorPtr exynosVideoSetupCloneVideo(ScreenPtr pScreen); +int EXYNOSCloneVideoSetDPMS(ScrnInfoPtr pScrn, Bool onoff); + +#endif diff --git a/src/xv/exynos_video_display.c b/src/xv/exynos_video_display.c new file mode 100644 index 0000000..f0776f7 --- /dev/null +++ b/src/xv/exynos_video_display.c @@ -0,0 +1,651 @@ +/* + * xserver-xorg-video-exynos + * + * Copyright 2004 Keith Packard + * Copyright 2005 Eric Anholt + * Copyright 2006 Nokia Corporation + * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Boram Park <boram1288.park@samsung.com> + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <pixman.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include <fourcc.h> + +#include <xf86xv.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_video_display.h" +#include "exynos_video_fourcc.h" +#include "exynos_layer.h" + +#include "fimg2d.h" +#ifdef LAYER_MANAGER +#include "exynos_layer_manager.h" +#endif + +#define EXYNOS_MAX_PORT 1 +#define LAYER_BUF_CNT 3 + +static XF86VideoEncodingRec dummy_encoding[] = { + {0, "XV_IMAGE", -1, -1, {1, 1}}, + {1, "XV_IMAGE", 4224, 4224, {1, 1}}, +}; + +static XF86VideoFormatRec formats[] = { + {16, TrueColor}, + {24, TrueColor}, + {32, TrueColor}, +}; + +static XF86AttributeRec attributes[] = { + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_OVERLAY"}, +}; + +typedef enum { + PAA_MIN, + PAA_OVERLAY, + PAA_MAX +} EXYNOSPortAttrAtom; + +static struct { + EXYNOSPortAttrAtom paa; + const char *name; + Atom atom; +} atoms[] = { + { +PAA_OVERLAY, "_USER_WM_PORT_ATTRIBUTE_OVERLAY", None},}; + +typedef struct _GetData { + int width; + int height; + xRectangle src; + xRectangle dst; + DrawablePtr pDraw; +} GetData; + +/* EXYNOS port information structure */ +typedef struct { + int index; + + /* attributes */ + Bool overlay; + + ScrnInfoPtr pScrn; + GetData d; + GetData old_d; +#ifndef LAYER_MANAGER + /* layer */ + EXYNOSLayer *layer; +#else + EXYNOSLayerMngClientID lyr_client_id; + EXYNOSLayerPos lpos; + EXYNOSLayerOutput output; +#endif + EXYNOSVideoBuf *outbuf[LAYER_BUF_CNT]; + + int stream_cnt; + struct xorg_list link; +} EXYNOSPortPriv, *EXYNOSPortPrivPtr; + +static RESTYPE event_drawable_type; + +typedef struct _EXYNOSDisplayVideoResource { + XID id; + RESTYPE type; + + EXYNOSPortPrivPtr pPort; + ScrnInfoPtr pScrn; +} EXYNOSDisplayVideoResource; + +static void _exynosDisplayVideoCloseBuffers(EXYNOSPortPrivPtr pPort); +static void EXYNOSDisplayVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit); + +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) +#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) +#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) + +static PixmapPtr +_getPixmap(DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) + return pDraw->pScreen->GetWindowPixmap((WindowPtr) pDraw); + else + return (PixmapPtr) pDraw; +} + +static Atom +_portAtom(EXYNOSPortAttrAtom paa) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) { + if (paa == atoms[i].paa) { + if (atoms[i].atom == None) + atoms[i].atom = MakeAtom(atoms[i].name, + strlen(atoms[i].name), TRUE); + + return atoms[i].atom; + } + } + + XDBG_ERROR(MDA, "Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static void +_copyBuffer(DrawablePtr pDraw, EXYNOSVideoBuf * vbuf) +{ + PixmapPtr pPixmap = (PixmapPtr) _getPixmap(pDraw); + EXYNOSPixmapPriv *privPixmap = exaGetPixmapDriverPrivate(pPixmap); + Bool need_finish = FALSE; + tbm_bo_handle bo_handle_src, bo_handle_dst; + G2dImage *src_image = NULL, *dst_image = NULL; + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(privPixmap->bo != NULL, done_copy_buf); + } + + bo_handle_src = tbm_bo_get_handle(privPixmap->bo, TBM_DEVICE_DEFAULT); + XDBG_GOTO_IF_FAIL(bo_handle_src.u32 > 0, done_copy_buf); + + bo_handle_dst = tbm_bo_get_handle(vbuf->bo[0], TBM_DEVICE_DEFAULT); + XDBG_GOTO_IF_FAIL(bo_handle_dst.u32 > 0, done_copy_buf); + + src_image = g2d_image_create_bo2(G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB, + (unsigned int) pDraw->width, + (unsigned int) pDraw->height, + (unsigned int) bo_handle_src.u32, + (unsigned int) 0, + (unsigned int) pDraw->width * 4); + XDBG_GOTO_IF_FAIL(src_image != NULL, done_copy_buf); + + dst_image = g2d_image_create_bo2(G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB, + (unsigned int) vbuf->width, + (unsigned int) vbuf->height, + (unsigned int) vbuf->handles[0], + (unsigned int) vbuf->handles[1], + (unsigned int) vbuf->pitches[0]); + XDBG_GOTO_IF_FAIL(dst_image != NULL, done_copy_buf); + + tbm_bo_map(privPixmap->bo, TBM_DEVICE_MM, TBM_OPTION_READ); + tbm_bo_map(vbuf->bo[0], TBM_DEVICE_MM, TBM_OPTION_READ); + + util_g2d_blend_with_scale(G2D_OP_SRC, src_image, dst_image, + (int) vbuf->crop.x, (int) vbuf->crop.y, + (unsigned int) vbuf->crop.width, + (unsigned int) vbuf->crop.height, + (int) vbuf->crop.x, (int) vbuf->crop.y, + (unsigned int) vbuf->crop.width, + (unsigned int) vbuf->crop.height, FALSE); + g2d_exec(); + + tbm_bo_unmap(privPixmap->bo); + tbm_bo_unmap(vbuf->bo[0]); + + done_copy_buf: + if (src_image) + g2d_image_free(src_image); + if (dst_image) + g2d_image_free(dst_image); + if (need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); +} + +static Bool +_exynosDisplayVideoShowLayer(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * vbuf, + EXYNOSLayerOutput output, EXYNOSLayerPos lpos) +{ +#ifndef LAYER_MANAGER + xRectangle src_rect, dst_rect; + + if (!pPort->layer) { + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pPort->pScrn)->pExynosMode; + + if (!exynosUtilEnsureExternalCrtc(pPort->pScrn)) { + XDBG_ERROR(MDA, "failed : pPort(%d) connect external crtc\n", + pPort->index); + return FALSE; + } + + pPort->layer = exynosLayerCreate(pPort->pScrn, output, lpos); + XDBG_RETURN_VAL_IF_FAIL(pPort->layer != NULL, FALSE); + + if (output == LAYER_OUTPUT_EXT && + pExynosMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) + exynosLayerEnableVBlank(pPort->layer, TRUE); + } + + exynosLayerGetRect(pPort->layer, &src_rect, &dst_rect); + + if (memcmp(&pPort->d.src, &src_rect, sizeof(xRectangle)) || + memcmp(&pPort->d.dst, &dst_rect, sizeof(xRectangle))) { + exynosLayerFreezeUpdate(pPort->layer, TRUE); + exynosLayerSetRect(pPort->layer, &pPort->d.src, &pPort->d.dst); + exynosLayerFreezeUpdate(pPort->layer, FALSE); + } + + exynosLayerSetBuffer(pPort->layer, vbuf); + if (!exynosLayerIsVisible(pPort->layer)) + exynosLayerShow(pPort->layer); +#else + if (pPort->lpos == LAYER_NONE) { + if (!exynosUtilEnsureExternalCrtc(pPort->pScrn)) { + XDBG_ERROR(MDA, "failed : pPort(%d) connect external crtc\n", + pPort->index); + return FALSE; + } + if (exynosLayerMngSet + (pPort->lyr_client_id, 0, 0, &pPort->d.src, &pPort->d.dst, NULL, + vbuf, output, lpos, NULL, NULL)) { + pPort->lpos = lpos; + pPort->output = output; + } + else { + XDBG_ERROR(MDA, "Can't set layer %d\n", pPort->index); + return FALSE; + } + + } +#endif + XDBG_DEBUG(MDA, "pDraw(0x%lx), fb_id(%d), (%d,%d %dx%d) (%d,%d %dx%d)\n", + pPort->d.pDraw->id, vbuf->fb_id, + pPort->d.src.x, pPort->d.src.y, pPort->d.src.width, + pPort->d.src.height, pPort->d.dst.x, pPort->d.dst.y, + pPort->d.dst.width, pPort->d.dst.height); + + return TRUE; +} + +static void +_exynosDisplayVideoHideLayer(EXYNOSPortPrivPtr pPort) +{ +#ifndef LAYER_MANAGER + if (!pPort->layer) + return; + + exynosLayerUnref(pPort->layer); + pPort->layer = NULL; +#else + if (pPort->lpos != LAYER_NONE) { + exynosLayerMngRelease(pPort->lyr_client_id, pPort->output, pPort->lpos); + pPort->lpos = LAYER_NONE; + } +#endif +} + +static EXYNOSVideoBuf * +_exynosDisplayVideoGetBuffer(EXYNOSPortPrivPtr pPort) +{ + int i; + + for (i = 0; i < LAYER_BUF_CNT; i++) { + if (!pPort->outbuf[i]) { + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + pPort->outbuf[i] = + exynosUtilAllocVideoBuffer(pPort->pScrn, FOURCC_RGB32, + pPort->d.pDraw->width, + pPort->d.pDraw->height, + (pExynos->scanout) ? TRUE : FALSE, + FALSE, FALSE); + XDBG_GOTO_IF_FAIL(pPort->outbuf[i] != NULL, fail_get_buf); + break; + } + else if (!pPort->outbuf[i]->showing) + break; + } + + if (i == LAYER_BUF_CNT) { + XDBG_ERROR(MDA, "now all outbufs in use!\n"); + return NULL; + } + + XDBG_DEBUG(MDA, "outbuf: stamp(%" PRIuPTR ") index(%d) h(%d,%d,%d)\n", + pPort->outbuf[i]->stamp, i, + pPort->outbuf[i]->handles[0], + pPort->outbuf[i]->handles[1], pPort->outbuf[i]->handles[2]); + + pPort->outbuf[i]->crop = pPort->d.src; + + _copyBuffer(pPort->d.pDraw, pPort->outbuf[i]); + + return pPort->outbuf[i]; + + fail_get_buf: + _exynosDisplayVideoCloseBuffers(pPort); + return NULL; +} + +static void +_exynosDisplayVideoCloseBuffers(EXYNOSPortPrivPtr pPort) +{ + int i; + + for (i = 0; i < LAYER_BUF_CNT; i++) + if (pPort->outbuf[i]) { + exynosUtilVideoBufferUnref(pPort->outbuf[i]); + pPort->outbuf[i] = NULL; + } +} + +static void +_exynosDisplayVideoStreamOff(EXYNOSPortPrivPtr pPort) +{ + _exynosDisplayVideoHideLayer(pPort); + _exynosDisplayVideoCloseBuffers(pPort); +#ifdef LAYER_MANAGER + exynosLayerMngUnRegisterClient(pPort->lyr_client_id); + pPort->lyr_client_id = LYR_ERROR_ID; +#endif + memset(&pPort->old_d, 0, sizeof(GetData)); + memset(&pPort->d, 0, sizeof(GetData)); + + if (pPort->stream_cnt > 0) { + pPort->stream_cnt = 0; + XDBG_SECURE(MDA, "pPort(%d) stream off. \n", pPort->index); + } + + XDBG_TRACE(MDA, "done. \n"); +} + +static Bool +_exynosDisplayVideoAddDrawableEvent(EXYNOSPortPrivPtr pPort) +{ + EXYNOSDisplayVideoResource *resource; + void *ptr = NULL; + int ret; + + ret = dixLookupResourceByType(&ptr, pPort->d.pDraw->id, + event_drawable_type, NULL, DixWriteAccess); + if (ret == Success) { + return TRUE; + } + + resource = malloc(sizeof(EXYNOSDisplayVideoResource)); + if (resource == NULL) + return FALSE; + + if (!AddResource(pPort->d.pDraw->id, event_drawable_type, resource)) { + free(resource); + return FALSE; + } + + XDBG_TRACE(MDA, "id(0x%08lx). \n", pPort->d.pDraw->id); + + resource->id = pPort->d.pDraw->id; + resource->type = event_drawable_type; + resource->pPort = pPort; + resource->pScrn = pPort->pScrn; + + return TRUE; +} + +static int +_exynosDisplayVideoRegisterEventDrawableGone(void *data, XID id) +{ + EXYNOSDisplayVideoResource *resource = (EXYNOSDisplayVideoResource *) data; + + XDBG_TRACE(MDA, "id(0x%08lx). \n", id); + + if (!resource) + return Success; + + if (!resource->pPort || !resource->pScrn) + return Success; + + EXYNOSDisplayVideoStop(resource->pScrn, (pointer) resource->pPort, 1); + + free(resource); + + return Success; +} + +static Bool +_exynosDisplayVideoRegisterEventResourceTypes(void) +{ + event_drawable_type = + CreateNewResourceType(_exynosDisplayVideoRegisterEventDrawableGone, + "Sec Video Drawable"); + + if (!event_drawable_type) + return FALSE; + + return TRUE; +} + +static int +EXYNOSDisplayVideoGetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 *value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_OVERLAY)) { + *value = pPort->overlay; + return Success; + } + + return BadMatch; +} + +static int +EXYNOSDisplayVideoSetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _portAtom(PAA_OVERLAY)) { + pPort->overlay = value; + XDBG_DEBUG(MDA, "overlay(%d) \n", (int) value); + return Success; + } + + return BadMatch; +} + +static int +EXYNOSDisplayVideoGetStill(ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + EXYNOSVideoBuf *vbuf; + EXYNOSLayerOutput output; + EXYNOSLayerPos lpos; + + XDBG_RETURN_VAL_IF_FAIL(pDraw->type == DRAWABLE_PIXMAP, BadRequest); + + pPort->pScrn = pScrn; + + pPort->d.width = pDraw->width; + pPort->d.height = pDraw->height; + pPort->d.src.x = drw_x; + pPort->d.src.y = drw_y; + pPort->d.src.width = drw_w; + pPort->d.src.height = drw_h; + pPort->d.dst.x = vid_x; + pPort->d.dst.y = vid_y; + pPort->d.dst.width = drw_w; + pPort->d.dst.height = drw_h; + pPort->d.pDraw = pDraw; +#ifdef LAYER_MANAGER + if (pPort->lyr_client_id == LYR_ERROR_ID) { + char client_name[20] = { 0 }; + if (snprintf + (client_name, sizeof(client_name), "XV_GETSTILL-%d", + pPort->index) < 0) { + XDBG_ERROR(MDA, "Can't register layer manager client\n"); + return BadRequest; + } + pPort->lyr_client_id = + exynosLayerMngRegisterClient(pScrn, client_name, 2); + XDBG_RETURN_VAL_IF_FAIL(pPort->lyr_client_id != LYR_ERROR_ID, + BadRequest); + pPort->lpos = LAYER_NONE; + } +#endif + if (pPort->old_d.width != pPort->d.width || + pPort->old_d.height != pPort->d.height) { + _exynosDisplayVideoHideLayer(pPort); + _exynosDisplayVideoCloseBuffers(pPort); + } + + if (!_exynosDisplayVideoAddDrawableEvent(pPort)) + return BadRequest; + + if (pPort->stream_cnt == 0) { + pPort->stream_cnt++; + + XDBG_SECURE(MDA, + "pPort(%d) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n", + pPort->index, pDraw->width, pDraw->height, drw_x, drw_y, + drw_w, drw_h, vid_x, vid_y, vid_w, vid_h); + } + + vbuf = _exynosDisplayVideoGetBuffer(pPort); + XDBG_RETURN_VAL_IF_FAIL(vbuf != NULL, BadRequest); + + if (pPort->overlay) { + output = LAYER_OUTPUT_EXT; + lpos = LAYER_UPPER; + } + else { + XDBG_ERROR(MDA, "pPort(%d) implemented for only overlay\n", + pPort->index); + return BadRequest; + } + + if (!_exynosDisplayVideoShowLayer(pPort, vbuf, output, lpos)) + return BadRequest; + + pPort->old_d = pPort->d; + + return Success; +} + +static void +EXYNOSDisplayVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + XDBG_TRACE(MDA, "exit (%d) \n", exit); + + if (!exit) + return; + + _exynosDisplayVideoStreamOff(pPort); + + pPort->overlay = FALSE; +} + +static void +EXYNOSDisplayVideoQueryBestSize(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + if (p_w) + *p_w = (unsigned int) dst_w & ~1; + if (p_h) + *p_h = (unsigned int) dst_h; +} + +XF86VideoAdaptorPtr +exynosVideoSetupDisplayVideo(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr pAdaptor; + EXYNOSPortPrivPtr pPort; + int i; + + pAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + + (sizeof(DevUnion) + + sizeof(EXYNOSPortPriv)) * EXYNOS_MAX_PORT); + if (!pAdaptor) + return NULL; + + dummy_encoding[0].width = pScreen->width; + dummy_encoding[0].height = pScreen->height; + + pAdaptor->type = XvPixmapMask | XvOutputMask | XvStillMask; + pAdaptor->flags = VIDEO_OVERLAID_IMAGES; + pAdaptor->name = "EXYNOS External Overlay Video"; + pAdaptor->nEncodings = + sizeof(dummy_encoding) / sizeof(XF86VideoEncodingRec); + pAdaptor->pEncodings = dummy_encoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = formats; + pAdaptor->nPorts = EXYNOS_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion *) (&pAdaptor[1]); + + pPort = (EXYNOSPortPrivPtr) (&pAdaptor->pPortPrivates[EXYNOS_MAX_PORT]); + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + pAdaptor->pPortPrivates[i].ptr = &pPort[i]; + pPort[i].index = i; +#ifdef LAYER_MANAGER + pPort[i].lpos = LAYER_NONE; + pPort[i].lyr_client_id = LYR_ERROR_ID; +#endif + } + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = attributes; + + pAdaptor->GetPortAttribute = EXYNOSDisplayVideoGetPortAttribute; + pAdaptor->SetPortAttribute = EXYNOSDisplayVideoSetPortAttribute; + pAdaptor->GetStill = EXYNOSDisplayVideoGetStill; + pAdaptor->StopVideo = EXYNOSDisplayVideoStop; + pAdaptor->QueryBestSize = EXYNOSDisplayVideoQueryBestSize; + + if (!_exynosDisplayVideoRegisterEventResourceTypes()) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to register EventResourceTypes. \n"); + return FALSE; + } + + return pAdaptor; +} diff --git a/src/xv/sec_video_display.h b/src/xv/exynos_video_display.h index 96bb952..4a7fed7 100644 --- a/src/xv/sec_video_display.h +++ b/src/xv/exynos_video_display.h @@ -31,6 +31,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define __SEC_VIDEO_DISPLAY_H__ /* setup display adaptor */ -XF86VideoAdaptorPtr secVideoSetupDisplayVideo (ScreenPtr pScreen); +XF86VideoAdaptorPtr exynosVideoSetupDisplayVideo(ScreenPtr pScreen); -#endif
\ No newline at end of file +#endif diff --git a/src/xv/sec_video_fourcc.h b/src/xv/exynos_video_fourcc.h index 2023e49..45ad724 100644 --- a/src/xv/sec_video_fourcc.h +++ b/src/xv/exynos_video_fourcc.h @@ -34,14 +34,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <fourcc.h> #include <drm_fourcc.h> -#define C(b,m) (((b) >> (m)) & 0xFF) +#define C(b,m) (char)(((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 FOURCC_ID(str) FOURCC(((char*)str)[0],((char*)str)[1],((char*)str)[2],((char*)str)[3]) #define IS_ZEROCOPY(id) ((C(id,0) == 'S') || id == FOURCC_ITLV) #define IS_RGB(id) (id == FOURCC_RGB565 || id == FOURCC_RGB32 || \ - id == FOURCC_SR16 || id == FOURCC_SR32) + id == FOURCC_SR16 || id == FOURCC_SR32 || \ + id == FOURCC_RGB24) +#define IS_YUV(id) (id == FOURCC_Y444 || id == FOURCC_S420 || \ + id == FOURCC_SUYV || id == FOURCC_SYVY) /* Specific format for S.LSI * 2x2 subsampled Cr:Cb plane 64x32 macroblocks @@ -322,5 +325,4 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FOURCC_Y444 FOURCC('Y','4','4','4') - -#endif // __SEC_VIDEO_FOURCC_H__ +#endif // __SEC_VIDEO_FOURCC_H__ diff --git a/src/xv/exynos_video_tvout.c b/src/xv/exynos_video_tvout.c new file mode 100644 index 0000000..4df6e3d --- /dev/null +++ b/src/xv/exynos_video_tvout.c @@ -0,0 +1,697 @@ +/************************************************************************** + +xserver-xorg-video-exynos + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park <boram1288.park@samsung.com> + +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 "exynos.h" +#include "exynos_display.h" +#include "exynos_crtc.h" +#include "exynos_output.h" +#include "exynos_accel.h" +#include "exynos_util.h" +#include "exynos_converter.h" +#include "exynos_video_tvout.h" +#include "exynos_video_virtual.h" +#include "exynos_video_fourcc.h" +#include "exynos_drm_ipp.h" +#include "exynos_layer.h" +#include "exynos_prop.h" + +#include <sys/ioctl.h> +#include <exynos/exynos_drm.h> +#include <drm_fourcc.h> + +#define TVBUF_NUM 3 + +/* HW restriction (VP) */ +#define MIN_WIDTH 32 +#define MIN_HEIGHT 4 +#define MAX_WIDTH 1920 +#define MAX_HEIGHT 1080 +#define MIN_SCALE 0.25 +#define MAX_SCALE 16.0 + +/* private structure */ +struct _EXYNOSVideoTv { + ScrnInfoPtr pScrn; + + EXYNOSLayer *layer; + EXYNOSLayerPos lpos; + + /* used if id is not supported in case of lpos == LAYER_LOWER1. */ + EXYNOSCvt *cvt; + EXYNOSVideoBuf **outbuf; + int outbuf_index; + int outbuf_num; + + int tv_width; + int tv_height; + + xRectangle tv_rect; + int is_resized; + unsigned int convert_id; + unsigned int src_id; + /* attributes */ + int rotate; + int hflip; + int vflip; + + EXYNOSLayerOutput output; + +}; + +static EXYNOSVideoBuf * +_exynosVideoTvGetOutBuffer(EXYNOSVideoTv * tv, int width, int height, + Bool exynosure) +{ + int i = tv->outbuf_index, j; + + if (!tv->outbuf) { + tv->outbuf = + (EXYNOSVideoBuf **) calloc(tv->outbuf_num, + sizeof(EXYNOSVideoBuf *)); + XDBG_RETURN_VAL_IF_FAIL(tv->outbuf != NULL, NULL); + } + + i++; + if (i >= tv->outbuf_num) + i = 0; + + for (j = 0; j < tv->outbuf_num; j++) { + if (tv->outbuf[i]) { + XDBG_DEBUG(MTVO, "outbuf(%p) converting(%d) showing(%d)\n", + tv->outbuf[i], VBUF_IS_CONVERTING(tv->outbuf[i]), + tv->outbuf[i]->showing); + + if (tv->outbuf[i] && !VBUF_IS_CONVERTING(tv->outbuf[i]) && + !tv->outbuf[i]->showing) { + if (tv->outbuf[i]->width == width && + tv->outbuf[i]->id == tv->convert_id && + tv->outbuf[i]->height == height) { + tv->outbuf_index = i; + return tv->outbuf[i]; + } + else { + exynosUtilVideoBufferUnref(tv->outbuf[i]); + EXYNOSPtr pExynos = EXYNOSPTR(tv->pScrn); + + tv->outbuf[i] = + exynosUtilAllocVideoBuffer(tv->pScrn, tv->convert_id, + width, height, + (pExynos-> + scanout) ? TRUE : FALSE, + TRUE, exynosure); + XDBG_RETURN_VAL_IF_FAIL(tv->outbuf[i] != NULL, NULL); + + XDBG_DEBUG(MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], + FOURCC_STR(tv->convert_id)); + + tv->outbuf_index = i; + return tv->outbuf[i]; + } + } + } + else { + EXYNOSPtr pExynos = EXYNOSPTR(tv->pScrn); + + tv->outbuf[i] = + exynosUtilAllocVideoBuffer(tv->pScrn, tv->convert_id, width, + height, + (pExynos->scanout) ? TRUE : FALSE, + TRUE, exynosure); + XDBG_RETURN_VAL_IF_FAIL(tv->outbuf[i] != NULL, NULL); + + XDBG_DEBUG(MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], + FOURCC_STR(tv->convert_id)); + + tv->outbuf_index = i; + return tv->outbuf[i]; + } + + i++; + if (i >= tv->outbuf_num) + i = 0; + } + +#if 0 + char buffers[1024]; + + CLEAR(buffers); + for (j = 0; j < tv->outbuf_num; j++) { + if (tv->outbuf[j]) + snprintf(buffers, 1024, "%s %d(%d,%d) ", buffers, + tv->outbuf[j]->keys[0], VBUF_IS_CONVERTING(tv->outbuf[j]), + tv->outbuf[j]->showing); + } + + XDBG_ERROR(MTVO, "now all outbufs in use! %s\n", buffers); +#else + XDBG_ERROR(MTVO, "now all outbufs in use!\n"); +#endif + + return NULL; +} + +static Bool +_exynosVideoTvLayerEnsure(EXYNOSVideoTv * tv) +{ + EXYNOSLayer *layer; + + if (tv->layer) + return TRUE; + + XDBG_RETURN_VAL_IF_FAIL(tv->lpos != LAYER_NONE, FALSE); + + layer = exynosLayerCreate(tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos); + XDBG_RETURN_VAL_IF_FAIL(layer != NULL, FALSE); + + tv->layer = layer; + + return TRUE; +} + +static void +_exynosVideoTvLayerDestroy(EXYNOSVideoTv * tv) +{ + if (tv->layer) { + exynosLayerUnref(tv->layer); + tv->layer = NULL; + } +} + +static int +_exynosVideoTvPutImageInternal(EXYNOSVideoTv * tv, EXYNOSVideoBuf * vbuf, + xRectangle *rect) +{ + int ret = 0; + + XDBG_DEBUG(MTVO, "rect (%d,%d %dx%d) \n", + rect->x, rect->y, rect->width, rect->height); + + xRectangle src_rect, dst_rect; + + exynosLayerGetRect(tv->layer, &src_rect, &dst_rect); + + if (tv->is_resized == 1) { + exynosLayerFreezeUpdate(tv->layer, FALSE); + tv->is_resized = 0; + } + + if (memcmp(&vbuf->crop, &src_rect, sizeof(xRectangle)) || + memcmp(rect, &dst_rect, sizeof(xRectangle))) { + exynosLayerFreezeUpdate(tv->layer, TRUE); + exynosLayerSetRect(tv->layer, &vbuf->crop, rect); + exynosLayerFreezeUpdate(tv->layer, FALSE); + } + + ret = exynosLayerSetBuffer(tv->layer, vbuf); + + if (ret == 0) + return 0; + + exynosLayerShow(tv->layer); + + return ret; +} + +static void +_exynosVideoTvCvtCallback(EXYNOSCvt * cvt, + EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst, void *cvt_data, Bool error) +{ + EXYNOSVideoTv *tv = (EXYNOSVideoTv *) cvt_data; + int i; + + XDBG_RETURN_IF_FAIL(tv != NULL); + XDBG_RETURN_IF_FAIL(cvt != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(dst)); + + XDBG_DEBUG(MTVO, "++++++++++++++++++++++++ \n"); + + for (i = 0; i < tv->outbuf_num; i++) + if (tv->outbuf[i] == dst) + break; + XDBG_RETURN_IF_FAIL(i < tv->outbuf_num); + _exynosVideoTvPutImageInternal(tv, dst, &tv->tv_rect); + + XDBG_DEBUG(MTVO, "++++++++++++++++++++++++.. \n"); +} + +EXYNOSVideoTv * +exynosVideoTvConnect(ScrnInfoPtr pScrn, unsigned int id, EXYNOSLayerPos lpos) +{ + EXYNOSVideoTv *tv = NULL; + EXYNOSModePtr pExynosMode; + unsigned int convert_id = FOURCC_RGB32; + + XDBG_RETURN_VAL_IF_FAIL(pScrn != NULL, NULL); + XDBG_RETURN_VAL_IF_FAIL(lpos >= LAYER_LOWER1 && lpos <= LAYER_UPPER, NULL); + XDBG_RETURN_VAL_IF_FAIL(id > 0, NULL); + + tv = calloc(sizeof(EXYNOSVideoTv), 1); + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, NULL); + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + + if (lpos == LAYER_LOWER1 && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + /* In case of video-only(virtual), we always use converter. */ + tv->cvt = exynosCvtCreate(pScrn, CVT_OP_M2M); + XDBG_GOTO_IF_FAIL(tv->cvt != NULL, fail_connect); + + exynosCvtAddCallback(tv->cvt, _exynosVideoTvCvtCallback, tv); + } + else if (lpos == LAYER_LOWER1 && + pExynosMode->conn_mode == DISPLAY_CONN_MODE_HDMI) { + if (!exynosLayerSupport(pScrn, LAYER_OUTPUT_EXT, lpos, id)) { + /* used if id is not supported in case of lpos == LAYER_LOWER1. */ + convert_id = FOURCC_SN12; + tv->cvt = exynosCvtCreate(pScrn, CVT_OP_M2M); + XDBG_GOTO_IF_FAIL(tv->cvt != NULL, fail_connect); + exynosCvtAddCallback(tv->cvt, _exynosVideoTvCvtCallback, tv); + } + else { + XDBG_DEBUG(MTVO, "Not need converting id(%c%c%c%c)\n", + FOURCC_STR(id)); + convert_id = id; + } + } + + XDBG_DEBUG(MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR(id), lpos); + tv->output = LAYER_OUTPUT_EXT; + tv->pScrn = pScrn; + tv->lpos = lpos; + tv->outbuf_index = -1; + tv->convert_id = convert_id; + tv->outbuf_num = TVBUF_NUM; + tv->src_id = id; + + return tv; + + fail_connect: + if (tv) { + if (tv->cvt) + exynosCvtDestroy(tv->cvt); + free(tv); + } + return NULL; +} + +Bool +exynosVideoTvResizeOutput(EXYNOSVideoTv * tv, xRectanglePtr src, + xRectanglePtr dst) +{ + if (tv == NULL) + return FALSE; + + if (!exynosVideoTvCanDirectDrawing(tv, src->width, src->height, + dst->width, dst->height)) { + if (tv->cvt) { + XDBG_DEBUG(MTVO, "Pause converter\n"); + if (!exynosCvtPause(tv->cvt)) { + XDBG_ERROR(MTVO, "Can't pause ipp converter\n"); + exynosVideoTvReCreateConverter(tv); + } + } + else { + XDBG_DEBUG(MTVO, "Create new converter tasks\n"); + exynosVideoTvReCreateConverter(tv); + } + } + else { + if (tv->cvt) { + XDBG_DEBUG(MTVO, "Driver can use direct drawing way.\n"); + exynosCvtDestroy(tv->cvt); + tv->cvt = NULL; + } + } + + if (tv->outbuf) { + int i; + + for (i = 0; i < tv->outbuf_num; i++) + if (tv->outbuf[i] && !VBUF_IS_CONVERTING(tv->outbuf[i]) && + !tv->outbuf[i]->showing) { + exynosUtilVideoBufferUnref(tv->outbuf[i]); + tv->outbuf[i] = NULL; + } + tv->outbuf_index = -1; + } + + exynosLayerFreezeUpdate(tv->layer, TRUE); + tv->is_resized = 1; + return TRUE; +} + +void +exynosVideoTvDisconnect(EXYNOSVideoTv * tv) +{ + int i; + + XDBG_RETURN_IF_FAIL(tv != NULL); + + XDBG_DEBUG(MTVO, "!\n"); + + if (tv->cvt) + exynosCvtDestroy(tv->cvt); + + _exynosVideoTvLayerDestroy(tv); + + if (tv->outbuf) { + for (i = 0; i < tv->outbuf_num; i++) + if (tv->outbuf[i]) + exynosUtilVideoBufferUnref(tv->outbuf[i]); + + free(tv->outbuf); + } + + free(tv); +} + +Bool +exynosVideoTvSetBuffer(EXYNOSVideoTv * tv, EXYNOSVideoBuf ** vbufs, int bufnum) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(vbufs != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(bufnum >= TVBUF_NUM, FALSE); + + if (tv->outbuf) { + XDBG_ERROR(MTVO, "already has buffers.\n"); + return FALSE; + } + + tv->outbuf_num = bufnum; + tv->outbuf = (EXYNOSVideoBuf **) calloc(bufnum, sizeof(EXYNOSVideoBuf *)); + XDBG_RETURN_VAL_IF_FAIL(tv->outbuf != NULL, FALSE); + + for (i = 0; i < tv->outbuf_num; i++) { + XDBG_GOTO_IF_FAIL(tv->convert_id == vbufs[i]->id, fail_set_buffer); + XDBG_GOTO_IF_FAIL(tv->tv_width == vbufs[i]->width, fail_set_buffer); + XDBG_GOTO_IF_FAIL(tv->tv_height == vbufs[i]->height, fail_set_buffer); + + tv->outbuf[i] = exynosUtilVideoBufferRef(vbufs[i]); + XDBG_GOTO_IF_FAIL(tv->outbuf[i] != NULL, fail_set_buffer); + + if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset) + exynosUtilClearVideoBuffer(tv->outbuf[i]); + else + tv->outbuf[i]->need_reset = TRUE; + } + + return TRUE; + + fail_set_buffer: + if (tv->outbuf) { + for (i = 0; i < tv->outbuf_num; i++) { + if (tv->outbuf[i]) { + exynosUtilVideoBufferUnref(tv->outbuf[i]); + tv->outbuf[i] = NULL; + } + } + + free(tv->outbuf); + tv->outbuf = NULL; + } + + return FALSE; +} + +EXYNOSLayerPos +exynosVideoTvGetPos(EXYNOSVideoTv * tv) +{ + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, LAYER_NONE); + + return tv->lpos; +} + +EXYNOSLayer * +exynosVideoTvGetLayer(EXYNOSVideoTv * tv) +{ + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, NULL); + + _exynosVideoTvLayerEnsure(tv); + + return tv->layer; +} + +/* HDMI : 'handles' is "gem handle" + * VIRTUAL : 'handles' is "physical address" + * 'data' is "raw data" + * only one of 'handles' and 'data' has value. + */ +int +exynosVideoTvPutImage(EXYNOSVideoTv * tv, EXYNOSVideoBuf * vbuf, + xRectangle *rect, int csc_range) +{ + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, 0); + XDBG_RETURN_VAL_IF_FAIL(VBUF_IS_VALID(vbuf), 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->id > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(rect != NULL, 0); + + XDBG_RETURN_VAL_IF_FAIL(vbuf->handles[0] > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->pitches[0] > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(rect->width > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(rect->height > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->width > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(vbuf->height > 0, 0); + _exynosVideoTvLayerEnsure(tv); + XDBG_RETURN_VAL_IF_FAIL(tv->layer != NULL, 0); + + if (tv->cvt) { + /* can't show buffer to HDMI at now. */ + + EXYNOSCvtProp src_prop = { 0, } + , dst_prop = { + 0,}; + EXYNOSVideoBuf *outbuf; + int dst_width, dst_height; + xRectangle dst_crop; + +#if 0 + /* CHECK */ + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(tv->pScrn)->pExynosMode; + + if (pExynosMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) { + XDBG_RETURN_VAL_IF_FAIL(tv->tv_width > 0, 0); + XDBG_RETURN_VAL_IF_FAIL(tv->tv_height > 0, 0); + dst_width = tv->tv_width; + dst_height = tv->tv_height; + dst_crop = *rect; + + tv->tv_rect.x = 0; + tv->tv_rect.y = 0; + tv->tv_rect.width = tv->tv_width; + tv->tv_rect.height = tv->tv_height; + } + else +#endif + { + dst_width = rect->width; + dst_height = rect->height; + dst_crop = *rect; + dst_crop.x = 0; + dst_crop.y = 0; + + tv->tv_rect = *rect; + } + + src_prop.id = vbuf->id; + src_prop.width = vbuf->width; + src_prop.height = vbuf->height; + src_prop.crop = vbuf->crop; + + dst_prop.id = tv->convert_id; + dst_prop.width = dst_width; + dst_prop.height = dst_height; + dst_prop.crop = dst_crop; + dst_prop.exynosure = vbuf->exynosure; + dst_prop.csc_range = csc_range; + dst_prop.hflip = tv->hflip; + dst_prop.vflip = tv->vflip; + dst_prop.degree = tv->rotate; + if (!exynosCvtEnsureSize(&src_prop, &dst_prop)) { + XDBG_ERROR(MTVO, "Can't ensure size\n"); + return 0; + } + + outbuf = + _exynosVideoTvGetOutBuffer(tv, dst_prop.width, dst_prop.height, + vbuf->exynosure); + if (!outbuf) { + XDBG_ERROR(MTVO, "Can't get outbuf\n"); + return 0; + } + outbuf->crop = dst_prop.crop; + + if (!exynosCvtSetProperpty(tv->cvt, &src_prop, &dst_prop)) { + XDBG_ERROR(MTVO, "Can't set cvt property\n"); + return 0; + } + + if (!exynosCvtConvert(tv->cvt, vbuf, outbuf)) { + XDBG_ERROR(MTVO, "Can't start cvt\n"); + return 0; + } + + XDBG_TRACE(MTVO, + "'%c%c%c%c' %dx%d (%d,%d %dx%d) => '%c%c%c%c' %dx%d (%d,%d %dx%d) convert. rect(%d,%d %dx%d)\n", + FOURCC_STR(vbuf->id), vbuf->width, vbuf->height, + vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, + vbuf->crop.height, FOURCC_STR(outbuf->id), outbuf->width, + outbuf->height, outbuf->crop.x, outbuf->crop.y, + outbuf->crop.width, outbuf->crop.height, rect->x, rect->y, + rect->width, rect->height); + + return 1; + } + /* can show buffer to HDMI at now. */ + return _exynosVideoTvPutImageInternal(tv, vbuf, rect); +} + +void +exynosVideoTvSetSize(EXYNOSVideoTv * tv, int width, int height) +{ + XDBG_RETURN_IF_FAIL(tv != NULL); + + tv->tv_width = width; + tv->tv_height = height; + + XDBG_TRACE(MTVO, "size(%dx%d) \n", width, height); +} + +EXYNOSCvt * +exynosVideoTvGetConverter(EXYNOSVideoTv * tv) +{ + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, NULL); + + return tv->cvt; +} + +void +exynosVideoTvSetConvertFormat(EXYNOSVideoTv * tv, unsigned int convert_id) +{ + XDBG_RETURN_IF_FAIL(tv != NULL); + XDBG_RETURN_IF_FAIL(convert_id > 0); + + tv->convert_id = convert_id; + + XDBG_TRACE(MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR(convert_id)); +} + +Bool +exynosVideoTvCanDirectDrawing(EXYNOSVideoTv * tv, int src_w, int src_h, + int dst_w, int dst_h) +{ + XDBG_RETURN_VAL_IF_FAIL(src_w > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src_h > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_w > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst_h > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(tv != 0, FALSE); + int ratio_w = 0; + int ratio_h = 0; + + XDBG_DEBUG(MTVO, "tv(%p) src_w %d, src_h %d, dst_w %d, dst_h %d\n", + tv, src_w, src_h, dst_w, dst_h); + if (tv->hflip != 0 || tv->vflip != 0 || tv->rotate != 0) { + XDBG_DEBUG(MTVO, "Can't direct draw hflip(%d), vflip(%d), rotate(%d)\n", + tv->hflip, tv->vflip, tv->rotate); + return FALSE; + } + if (src_w >= dst_w) { + ratio_w = src_w / dst_w; + if (ratio_w > 4) { + XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (1/%d) < 1/4\n", + ratio_w); + return FALSE; + } + XDBG_DEBUG(MTVO, "ratio_w = 1/%d\n", ratio_w); + } + else if (src_w < dst_w) { + ratio_w = dst_w / src_w; + if (ratio_w > 16) { + XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w); + return FALSE; + } + XDBG_DEBUG(MTVO, "ratio_w = %d\n", ratio_w); + } + + if (src_h >= dst_h) { + ratio_h = src_h / dst_h; + if (ratio_h > 4) { + XDBG_DEBUG(MTVO, "Can't direct draw ratio_h (1/%d) < 1/4\n", + ratio_w); + return FALSE; + } + XDBG_DEBUG(MTVO, "ratio_h = 1/%d\n", ratio_h); + } + else if (src_h < dst_h) { + ratio_h = dst_h / src_h; + if (ratio_h > 16) { + XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w); + return FALSE; + } + XDBG_DEBUG(MTVO, "ratio_h = %d\n", ratio_h); + } + + if (!exynosLayerSupport(tv->pScrn, tv->output, tv->lpos, tv->src_id)) { + XDBG_DEBUG(MTVO, + "Can't direct draw. Layer not support. lpos(%d), src_id (%c%c%c%c)\n", + tv->lpos, FOURCC_STR(tv->src_id)); + return FALSE; + } + + XDBG_DEBUG(MTVO, "Support direct drawing\n"); + return TRUE; +} + +Bool +exynosVideoTvReCreateConverter(EXYNOSVideoTv * tv) +{ + if (tv == NULL) + return FALSE; + if (tv->cvt) { + exynosCvtDestroy(tv->cvt); + } + tv->cvt = exynosCvtCreate(tv->pScrn, CVT_OP_M2M); + XDBG_RETURN_VAL_IF_FAIL(tv->cvt != NULL, FALSE); + exynosCvtAddCallback(tv->cvt, _exynosVideoTvCvtCallback, tv); + return TRUE; +} + +Bool +exynosVideoTvSetAttributes(EXYNOSVideoTv * tv, int rotate, int hflip, int vflip) +{ + XDBG_RETURN_VAL_IF_FAIL(tv != NULL, FALSE); + tv->rotate = rotate; + tv->vflip = vflip; + tv->hflip = hflip; + return TRUE; +} diff --git a/src/xv/sec_video_tvout.h b/src/xv/exynos_video_tvout.h index 9c88dc4..6fa7841 100644 --- a/src/xv/sec_video_tvout.h +++ b/src/xv/exynos_video_tvout.h @@ -33,24 +33,34 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <xf86str.h> #include <X11/Xdefs.h> -#include "sec_layer.h" -#include "sec_converter.h" -#include "sec_video_types.h" +#include "exynos_layer.h" +#include "exynos_converter.h" +#include "exynos_video_types.h" -typedef struct _SECVideoTv SECVideoTv; +typedef struct _EXYNOSVideoTv EXYNOSVideoTv; -SECVideoTv* secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos); -void secVideoTvDisconnect (SECVideoTv *tv); +EXYNOSVideoTv *exynosVideoTvConnect(ScrnInfoPtr pScrn, unsigned int id, + EXYNOSLayerPos lpos); +void exynosVideoTvDisconnect(EXYNOSVideoTv * tv); -Bool secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum); +Bool exynosVideoTvSetBuffer(EXYNOSVideoTv * tv, EXYNOSVideoBuf ** vbufs, + int bufnum); -SECLayerPos secVideoTvGetPos (SECVideoTv *tv); -SECLayer* secVideoTvGetLayer (SECVideoTv *tv); +EXYNOSLayerPos exynosVideoTvGetPos(EXYNOSVideoTv * tv); +EXYNOSLayer *exynosVideoTvGetLayer(EXYNOSVideoTv * tv); -void secVideoTvSetSize (SECVideoTv *tv, int width, int height); -int secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *dst, int csc_range); +void exynosVideoTvSetSize(EXYNOSVideoTv * tv, int width, int height); +int exynosVideoTvPutImage(EXYNOSVideoTv * tv, EXYNOSVideoBuf * vbuf, + xRectangle *dst, int csc_range); -SECCvt* secVideoTvGetConverter (SECVideoTv *tv); -void secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id); +EXYNOSCvt *exynosVideoTvGetConverter(EXYNOSVideoTv * tv); +void exynosVideoTvSetConvertFormat(EXYNOSVideoTv * tv, unsigned int convert_id); +Bool exynosVideoTvResizeOutput(EXYNOSVideoTv * tv, xRectanglePtr src, + xRectanglePtr dst); +Bool exynosVideoTvCanDirectDrawing(EXYNOSVideoTv * tv, int src_w, int src_h, + int dst_w, int dst_h); +Bool exynosVideoTvReCreateConverter(EXYNOSVideoTv * tv); +Bool exynosVideoTvSetAttributes(EXYNOSVideoTv * tv, int rotate, int hflip, + int vflip); -#endif /* __SEC_VIDEO_TVOUT_H__ */ +#endif /* __SEC_VIDEO_TVOUT_H__ */ diff --git a/src/xv/sec_video_types.h b/src/xv/exynos_video_types.h index 1afe0fb..f1bdc63 100644 --- a/src/xv/sec_video_types.h +++ b/src/xv/exynos_video_types.h @@ -35,15 +35,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <fbdevhw.h> #include <X11/Xdefs.h> #include <tbm_bufmgr.h> -#include <exynos_drm.h> +#include <exynos/exynos_drm.h> -/* securezone memory */ +/* exynosurezone memory */ #define TZMEM_IOC_GET_TZMEM 0xC00C5402 -struct tzmem_get_region -{ - const char *key; - unsigned int size; - int fd; +struct tzmem_get_region { + const char *key; + unsigned int size; + int fd; }; /************************************************************ @@ -102,67 +101,70 @@ enum fimc_overlay_mode { typedef unsigned char uchar; #endif -typedef enum -{ +typedef enum { TYPE_NONE, TYPE_RGB, TYPE_YUV444, TYPE_YUV422, TYPE_YUV420, -} SECFormatType; +} EXYNOSFormatType; -typedef struct _SECFormatTable -{ - unsigned int id; - unsigned int drmfmt; - SECFormatType type; -} SECFormatTable; +typedef struct _EXYNOSFormatTable { + unsigned int id; + unsigned int drmfmt; + EXYNOSFormatType type; +} EXYNOSFormatTable; -typedef struct _ConvertInfo -{ +typedef struct _ConvertInfo { void *cvt; struct xorg_list link; } ConvertInfo; -typedef struct _SECVideoBuf -{ +typedef struct _EXYNOSVideoBuf { ScrnInfoPtr pScrn; - int id; + int id; - int width; - int height; + int width; + int height; xRectangle crop; - int pitches[PLANAR_CNT]; - int offsets[PLANAR_CNT]; - int lengths[PLANAR_CNT]; - int size; + int pitches[PLANAR_CNT]; + int offsets[PLANAR_CNT]; + int lengths[PLANAR_CNT]; + int size; - tbm_bo bo[PLANAR_CNT]; + tbm_bo bo[PLANAR_CNT]; unsigned int keys[PLANAR_CNT]; unsigned int phy_addrs[PLANAR_CNT]; unsigned int handles[PLANAR_CNT]; struct xorg_list convert_info; - Bool showing; /* now showing or now waiting to show. */ - Bool dirty; - Bool need_reset; + Bool showing; /* now showing or now waiting to show. */ + Bool dirty; + Bool need_reset; - unsigned int fb_id; /* fb_id of vbuf */ + intptr_t fb_id; /* fb_id of vbuf */ + Bool fb_id_external; /* if fb_id was set from outside (not created in exynosUtilVideoSetFb) fb_id should't be removed */ struct xorg_list free_funcs; - Bool secure; - int csc_range; + Bool exynosure; + int csc_range; - struct xorg_list valid_link; /* to check valid */ - CARD32 stamp; + struct xorg_list valid_link; /* to check valid */ + uintptr_t stamp; unsigned int ref_cnt; - char *func; - int flags; - Bool scanout; + char *func; + int flags; + Bool scanout; CARD32 put_time; -} SECVideoBuf; + + //showing complite event + void (*vblank_handler) (unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *vblank_user_data, + int failed); + void *vblank_user_data; +} EXYNOSVideoBuf; #endif diff --git a/src/xv/exynos_video_virtual.c b/src/xv/exynos_video_virtual.c new file mode 100644 index 0000000..2fc67d3 --- /dev/null +++ b/src/xv/exynos_video_virtual.c @@ -0,0 +1,2414 @@ +/* + * xserver-xorg-video-exynos + * + * Copyright 2004 Keith Packard + * Copyright 2005 Eric Anholt + * Copyright 2006 Nokia Corporation + * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Boram Park <boram1288.park@samsung.com> + * Contact: Oleksandr Rozov<o.rozov@samsung.com> + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pixman.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xv.h> + +#include "exynos.h" +#include "exynos_util.h" +#include "exynos_wb.h" +#include "exynos_crtc.h" +#include "exynos_converter.h" +#include "exynos_output.h" +#include "exynos_video.h" +#include "exynos_video_fourcc.h" +#include "exynos_video_virtual.h" +#include "exynos_video_tvout.h" +#include "exynos_display.h" +#include "exynos_xberc.h" + +#include "xv_types.h" + +#define DEV_INDEX 2 +#define BUF_NUM_EXTERNAL 5 +#define BUF_NUM_STREAM 3 + +enum { + CAPTURE_MODE_NONE, + CAPTURE_MODE_STILL, + CAPTURE_MODE_STREAM, + CAPTURE_MODE_MAX, +}; + +enum { + DISPLAY_MAIN, + DISPLAY_EXTERNAL, +}; + +enum { + DATA_TYPE_NONE, + DATA_TYPE_UI, + DATA_TYPE_VIDEO, + DATA_TYPE_MAX, +}; + +static unsigned int support_formats[] = { + FOURCC_RGB32, + FOURCC_ST12, + FOURCC_SN12, +}; + +static XF86VideoEncodingRec dummy_encoding[] = { + {0, "XV_IMAGE", -1, -1, {1, 1}}, + {1, "XV_IMAGE", 2560, 2560, {1, 1}}, +}; + +static XF86ImageRec images[] = { + XVIMAGE_RGB32, + XVIMAGE_SN12, + XVIMAGE_ST12, +}; + +static XF86VideoFormatRec formats[] = { + {16, TrueColor}, + {24, TrueColor}, + {32, TrueColor}, +}; + +static XF86AttributeRec attributes[] = { + {0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_FORMAT"}, + {0, 0, CAPTURE_MODE_MAX, "_USER_WM_PORT_ATTRIBUTE_CAPTURE"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_DISPLAY"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF"}, + {0, 0, DATA_TYPE_MAX, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE"}, + {0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE"}, + {0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER"}, +}; + +typedef enum { + PAA_MIN, + PAA_FORMAT, + PAA_CAPTURE, + PAA_DISPLAY, + PAA_ROTATE_OFF, + PAA_DATA_TYPE, + PAA_SECURE, + PAA_RETBUF, + PAA_MAX +} EXYNOSPortAttrAtom; + +static struct { + EXYNOSPortAttrAtom paa; + const char *name; + Atom atom; +} atoms[] = { + { + PAA_FORMAT, "_USER_WM_PORT_ATTRIBUTE_FORMAT", None}, { + PAA_CAPTURE, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", None}, { + PAA_DISPLAY, "_USER_WM_PORT_ATTRIBUTE_DISPLAY", None}, { + PAA_ROTATE_OFF, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF", None}, { + PAA_DATA_TYPE, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", None}, { + PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None}, { +PAA_RETBUF, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", None},}; + +typedef struct _RetBufInfo { + EXYNOSVideoBuf *vbuf; + int type; + struct xorg_list link; +} RetBufInfo; + +/* EXYNOS port information structure */ +typedef struct { + /* index */ + int index; + + /* port attribute */ + int id; + int capture; + int display; + Bool exynosure; + Bool data_type; + Bool rotate_off; + + /* information from outside */ + ScrnInfoPtr pScrn; + DrawablePtr pDraw; + RegionPtr clipBoxes; + + /* writeback */ + EXYNOSWb *wb; + Bool need_close_wb; + + /* video */ + EXYNOSCvt *cvt; + EXYNOSCvt *cvt2; + + EXYNOSVideoBuf *dstbuf; + EXYNOSVideoBuf **outbuf; + int outbuf_num; + int outbuf_index; + + struct xorg_list retbuf_info; + Bool need_damage; + + OsTimerPtr retire_timer; + Bool putstill_on; + + unsigned int status; + CARD32 retire_time; + CARD32 prev_time; + + /*convert dst buffer */ + EXYNOSVideoBuf *capture_dstbuf; + Bool wait_rgb_convert; + int active_connector; + + struct xorg_list link; +} EXYNOSPortPriv, *EXYNOSPortPrivPtr; + +static RESTYPE event_drawable_type; + +typedef struct _EXYNOSVideoResource { + XID id; + RESTYPE type; + EXYNOSPortPrivPtr pPort; + ScrnInfoPtr pScrn; +} EXYNOSVideoResource; + +#define EXYNOS_MAX_PORT 1 + +#define NUM_IMAGES (sizeof(images) / sizeof(images[0])) +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) +#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) +#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) + +static DevPrivateKeyRec video_virtual_port_key; + +#define VideoVirtualPortKey (&video_virtual_port_key) +#define GetPortInfo(pDraw) ((EXYNOSVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoVirtualPortKey)) + +typedef struct _EXYNOSVideoPortInfo { + ClientPtr client; + XvPortPtr pp; +} EXYNOSVideoPortInfo; + +static int (*ddPutStill) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + +static void EXYNOSVirtualVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit); +static void _exynosVirtualVideoCloseOutBuffer(EXYNOSPortPrivPtr pPort); +static void _exynosVirtualVideoLayerNotifyFunc(EXYNOSLayer * layer, int type, + void *type_data, void *data); +static void _exynosVirtualVideoWbDumpFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data); +static void _exynosVirtualVideoWbStopFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data); +static EXYNOSVideoBuf *_exynosVirtualVideoGetBlackBuffer(EXYNOSPortPrivPtr + pPort); +static Bool _exynosVirtualVideoEnsureOutBuffers(ScrnInfoPtr pScrn, + EXYNOSPortPrivPtr pPort, int id, + int width, int height); +static void _exynosVirtualVideoWbCloseFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data); + +static Bool + + +exynosCaptureConvertImage(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * vbuf, + int csc_range); +static void _exynosCaptureCloseConverter(EXYNOSPortPrivPtr pPort); +static void _exynosCaptureEnsureConverter(EXYNOSPortPrivPtr pPort); + +static EXYNOSVideoPortInfo * +_port_info(DrawablePtr pDraw) +{ + if (!pDraw) + return NULL; + + if (pDraw->type == DRAWABLE_WINDOW) + return GetPortInfo((WindowPtr) pDraw); + else + return GetPortInfo((PixmapPtr) pDraw); +} + +static Atom +_exynosVideoGetPortAtom(EXYNOSPortAttrAtom paa) +{ + int i; + + XDBG_RETURN_VAL_IF_FAIL(paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) { + if (paa == atoms[i].paa) { + if (atoms[i].atom == None) + atoms[i].atom = MakeAtom(atoms[i].name, + strlen(atoms[i].name), TRUE); + + return atoms[i].atom; + } + } + + XDBG_ERROR(MVA, "Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static void +_exynosVirtualVideoSetSecure(EXYNOSPortPrivPtr pPort, Bool exynosure) +{ + EXYNOSVideoPortInfo *info; + + exynosure = (exynosure > 0) ? TRUE : FALSE; + + if (pPort->exynosure == exynosure) + return; + + pPort->exynosure = exynosure; + + XDBG_TRACE(MVA, "exynosure(%d) \n", exynosure); + + info = _port_info(pPort->pDraw); + if (!info || !info->pp) + return; + + XvdiSendPortNotify(info->pp, _exynosVideoGetPortAtom(PAA_SECURE), + exynosure); +} + +static PixmapPtr +_exynosVirtualVideoGetPixmap(DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) + return pDraw->pScreen->GetWindowPixmap((WindowPtr) pDraw); + else + return (PixmapPtr) pDraw; +} + +static Bool +_exynosVirtualVideoIsSupport(unsigned int id) +{ + int i; + + for (i = 0; i < sizeof(support_formats) / sizeof(unsigned int); i++) + if (support_formats[i] == id) + return TRUE; + + return FALSE; +} + +#if 0 +static char buffers[1024]; + +static void +_buffers(EXYNOSPortPrivPtr pPort) +{ + RetBufInfo *cur = NULL, *next = NULL; + + CLEAR(buffers); + xorg_list_for_each_entry_safe(cur, next, &pPort->retbuf_info, link) { + if (cur->vbuf) + snprintf(buffers, 1024, "%s %d", buffers, cur->vbuf->keys[0]); + } +} +#endif + +static RetBufInfo * +_exynosVirtualVideoFindReturnBuf(EXYNOSPortPrivPtr pPort, unsigned int key) +{ + RetBufInfo *cur = NULL, *next = NULL; + + XDBG_RETURN_VAL_IF_FAIL(pPort->capture != CAPTURE_MODE_STILL, NULL); + + xorg_list_for_each_entry_safe(cur, next, &pPort->retbuf_info, link) { + if (cur->vbuf && cur->vbuf->keys[0] == key) + return cur; + else if (cur->vbuf && cur->vbuf->phy_addrs[0] == key) + return cur; + } + + return NULL; +} + +static Bool +_exynosVirtualVideoAddReturnBuf(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * vbuf) +{ + RetBufInfo *info; + + XDBG_RETURN_VAL_IF_FAIL(pPort->capture != CAPTURE_MODE_STILL, FALSE); + + info = _exynosVirtualVideoFindReturnBuf(pPort, vbuf->keys[0]); + XDBG_RETURN_VAL_IF_FAIL(info == NULL, FALSE); + + info = calloc(1, sizeof(RetBufInfo)); + XDBG_RETURN_VAL_IF_FAIL(info != NULL, FALSE); + + info->vbuf = exynosUtilVideoBufferRef(vbuf); + XDBG_GOTO_IF_FAIL(info->vbuf != NULL, fail); + info->vbuf->showing = TRUE; + + XDBG_DEBUG(MVA, "retbuf (%" PRIuPTR ",%d,%d,%d) added.\n", vbuf->stamp, + vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]); + + xorg_list_add(&info->link, &pPort->retbuf_info); + + return TRUE; + + fail: + if (info) + free(info); + + return FALSE; +} + +static void +_exynosVirtualVideoRemoveReturnBuf(EXYNOSPortPrivPtr pPort, RetBufInfo * info) +{ + XDBG_RETURN_IF_FAIL(pPort->capture != CAPTURE_MODE_STILL); + XDBG_RETURN_IF_FAIL(info != NULL); + XDBG_RETURN_IF_FAIL(info->vbuf != NULL); + + info->vbuf->showing = FALSE; + + XDBG_DEBUG(MVA, "retbuf (%" PRIuPTR ",%d,%d,%d) removed.\n", + info->vbuf->stamp, info->vbuf->keys[0], info->vbuf->keys[1], + info->vbuf->keys[2]); + + if (pPort->wb) + exynosWbQueueBuffer(pPort->wb, info->vbuf); + + exynosUtilVideoBufferUnref(info->vbuf); + xorg_list_del(&info->link); + free(info); +} + +static void +_exynosVirtualVideoRemoveReturnBufAll(EXYNOSPortPrivPtr pPort) +{ + RetBufInfo *cur = NULL, *next = NULL; + + XDBG_RETURN_IF_FAIL(pPort->capture != CAPTURE_MODE_STILL); + + xorg_list_for_each_entry_safe(cur, next, &pPort->retbuf_info, link) { + _exynosVirtualVideoRemoveReturnBuf(pPort, cur); + } +} + +static void +_exynosVirtualVideoDraw(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * buf) +{ + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + if (!pPort->pDraw) { + XDBG_TRACE(MVA, "drawable gone!\n"); + return; + } + + XDBG_RETURN_IF_FAIL(pPort->need_damage == TRUE); + XDBG_GOTO_IF_FAIL(VBUF_IS_VALID(buf), draw_done); + + XDBG_TRACE(MVA, "%c%c%c%c, %dx%d. \n", + FOURCC_STR(buf->id), buf->width, buf->height); + + if (pPort->id == FOURCC_RGB32) { + PixmapPtr pPixmap = _exynosVirtualVideoGetPixmap(pPort->pDraw); + tbm_bo_handle bo_handle; + + XDBG_GOTO_IF_FAIL(buf->exynosure == FALSE, draw_done); + + if (pPort->pDraw->width != buf->width || + pPort->pDraw->height != buf->height) { + XDBG_ERROR(MVA, "not matched. (%dx%d != %dx%d) \n", + pPort->pDraw->width, pPort->pDraw->height, buf->width, + buf->height); + goto draw_done; + } + + bo_handle = tbm_bo_map(buf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_READ); + XDBG_GOTO_IF_FAIL(bo_handle.ptr != NULL, draw_done); + XDBG_GOTO_IF_FAIL(buf->size > 0, draw_done); + + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + + if (pPixmap->devPrivate.ptr) { + XDBG_DEBUG(MVA, "vir(%p) size(%d) => pixmap(%p)\n", + bo_handle.ptr, buf->size, pPixmap->devPrivate.ptr); + + memcpy(pPixmap->devPrivate.ptr, bo_handle.ptr, buf->size); + } + + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + tbm_bo_unmap(buf->bo[0]); + } + else { /* FOURCC_ST12 */ + + PixmapPtr pPixmap = _exynosVirtualVideoGetPixmap(pPort->pDraw); + XV_DATA xv_data = { 0, }; + + _exynosVirtualVideoSetSecure(pPort, buf->exynosure); + + XV_INIT_DATA(&xv_data); + + if (buf->phy_addrs[0] > 0) { + xv_data.YBuf = buf->phy_addrs[0]; + xv_data.CbBuf = buf->phy_addrs[1]; + xv_data.CrBuf = buf->phy_addrs[2]; + + xv_data.BufType = XV_BUF_TYPE_LEGACY; + } + else { + xv_data.YBuf = buf->keys[0]; + xv_data.CbBuf = buf->keys[1]; + xv_data.CrBuf = buf->keys[2]; + + xv_data.BufType = XV_BUF_TYPE_DMABUF; + } + +#if 0 + _buffers(pPort); + ErrorF("[Xorg] send : %d (%s)\n", xv_data.YBuf, buffers); +#endif + + XDBG_DEBUG(MVA, "still_data(%d,%d,%d) type(%d) \n", + xv_data.YBuf, xv_data.CbBuf, xv_data.CrBuf, xv_data.BufType); + + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + + if (pPixmap->devPrivate.ptr) + memcpy(pPixmap->devPrivate.ptr, &xv_data, sizeof(XV_DATA)); + + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + _exynosVirtualVideoAddReturnBuf(pPort, buf); + } + + draw_done: + DamageDamageRegion(pPort->pDraw, pPort->clipBoxes); + pPort->need_damage = FALSE; + + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if ((pExynos->dump_mode & XBERC_DUMP_MODE_CA) && pExynos->dump_info) { + char file[128]; + static int i; + + snprintf(file, sizeof(file), "capout_stream_%c%c%c%c_%dx%d_%03d.%s", + FOURCC_STR(buf->id), buf->width, buf->height, i++, + IS_RGB(buf->id) ? "bmp" : "yuv"); + exynosUtilDoDumpVBuf(pExynos->dump_info, buf, file); + } + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_CA) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - pPort->prev_time; + ErrorF("damage send : %6" PRIXID " ms\n", sub); + } +} + +static void +_exynosVirtualVideoWbDumpFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) user_data; + EXYNOSVideoBuf *vbuf = (EXYNOSVideoBuf *) noti_data; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(vbuf)); + XDBG_RETURN_IF_FAIL(vbuf->showing == FALSE); + + XDBG_TRACE(MVA, "dump (%" PRIuPTR ",%d,%d,%d)\n", vbuf->stamp, + vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]); + + if (pPort->need_damage) { + _exynosVirtualVideoDraw(pPort, vbuf); + } + + return; +} + +static void +_exynosVirtualVideoWbDumpDoneFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) user_data; + + if (!pPort) + return; + + XDBG_DEBUG(MVA, "close wb after ipp event done\n"); + + XDBG_RETURN_IF_FAIL(pPort->wb != NULL); + + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbStopFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbDumpFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbDumpDoneFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbCloseFunc); + if (pPort->need_close_wb) + exynosWbClose(pPort->wb); + pPort->wb = NULL; +} + +static void +_exynosVirtualVideoWbStopFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) user_data; + + if (!pPort) + return; + + if (pPort->need_damage) { + EXYNOSVideoBuf *black = _exynosVirtualVideoGetBlackBuffer(pPort); + + XDBG_TRACE(MVA, "black buffer(%d) return: wb stop\n", + (black) ? black->keys[0] : 0); + _exynosVirtualVideoDraw(pPort, black); + } +} + +static void +_exynosVirtualVideoWbCloseFunc(EXYNOSWb * wb, EXYNOSWbNotify noti, + void *noti_data, void *user_data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) user_data; + + if (!pPort) + return; + + pPort->wb = NULL; +} + +static void +_exynosVirtualVideoStreamOff(EXYNOSPortPrivPtr pPort) +{ + EXYNOSLayer *layer; + + XDBG_TRACE(MVA, "STREAM_OFF!\n"); + + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + if (pPort->wb) { + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbStopFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbDumpFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbDumpDoneFunc); + exynosWbRemoveNotifyFunc(pPort->wb, _exynosVirtualVideoWbCloseFunc); + if (pPort->need_close_wb) + exynosWbClose(pPort->wb); + pPort->wb = NULL; + } + + if (pPort->id != FOURCC_RGB32) + _exynosVirtualVideoRemoveReturnBufAll(pPort); + + layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1); + if (layer) + exynosLayerRemoveNotifyFunc(layer, _exynosVirtualVideoLayerNotifyFunc); + + if (pPort->need_damage) { + /* all callbacks has been removed from wb/layer. We can't expect + * any event. So we send black image at the end. + */ + EXYNOSVideoBuf *black = _exynosVirtualVideoGetBlackBuffer(pPort); + + XDBG_TRACE(MVA, "black buffer(%d) return: stream off\n", + (black) ? black->keys[0] : 0); + _exynosVirtualVideoDraw(pPort, black); + } + + _exynosVirtualVideoCloseOutBuffer(pPort); + + if (pPort->clipBoxes) { + RegionDestroy(pPort->clipBoxes); + pPort->clipBoxes = NULL; + } + + pPort->pDraw = NULL; + pPort->capture = CAPTURE_MODE_NONE; + pPort->id = FOURCC_RGB32; + pPort->exynosure = FALSE; + pPort->data_type = DATA_TYPE_UI; + pPort->need_damage = FALSE; + + if (pPort->putstill_on) { + pPort->putstill_on = FALSE; + XDBG_SECURE(MVA, "pPort(%d) putstill off. \n", pPort->index); + } +} + +static int +_exynosVirtualVideoAddDrawableEvent(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoResource *resource; + void *ptr; + int ret = 0; + + XDBG_RETURN_VAL_IF_FAIL(pPort->pScrn != NULL, BadImplementation); + XDBG_RETURN_VAL_IF_FAIL(pPort->pDraw != NULL, BadImplementation); + + ptr = NULL; + ret = dixLookupResourceByType(&ptr, pPort->pDraw->id, + event_drawable_type, NULL, DixWriteAccess); + if (ret == Success) + return Success; + + resource = malloc(sizeof(EXYNOSVideoResource)); + if (resource == NULL) + return BadAlloc; + + if (!AddResource(pPort->pDraw->id, event_drawable_type, resource)) { + free(resource); + return BadAlloc; + } + + XDBG_TRACE(MVA, "id(0x%08lx). \n", pPort->pDraw->id); + + resource->id = pPort->pDraw->id; + resource->type = event_drawable_type; + resource->pPort = pPort; + resource->pScrn = pPort->pScrn; + + return Success; +} + +static int +_exynosVirtualVideoRegisterEventDrawableGone(void *data, XID id) +{ + EXYNOSVideoResource *resource = (EXYNOSVideoResource *) data; + + XDBG_TRACE(MVA, "id(0x%08lx). \n", id); + + if (!resource) + return Success; + + if (!resource->pPort || !resource->pScrn) + return Success; + + resource->pPort->pDraw = NULL; + + EXYNOSVirtualVideoStop(resource->pScrn, (pointer) resource->pPort, 1); + + free(resource); + + return Success; +} + +static Bool +_exynosVirtualVideoRegisterEventResourceTypes(void) +{ + event_drawable_type = + CreateNewResourceType(_exynosVirtualVideoRegisterEventDrawableGone, + "Sec Virtual Video Drawable"); + + if (!event_drawable_type) + return FALSE; + + return TRUE; +} + +static tbm_bo +_exynosVirtualVideoGetFrontBo(EXYNOSPortPrivPtr pPort, int connector_type) +{ + xf86CrtcConfigPtr pCrtcConfig; + int i; + + pCrtcConfig = XF86_CRTC_CONFIG_PTR(pPort->pScrn); + XDBG_RETURN_VAL_IF_FAIL(pCrtcConfig != NULL, NULL); + + for (i = 0; i < pCrtcConfig->num_output; i++) { + xf86OutputPtr pOutput = pCrtcConfig->output[i]; + EXYNOSOutputPrivPtr pOutputPriv = pOutput->driver_private; + + if (pOutputPriv->mode_output->connector_type == connector_type) { + if (pOutput->crtc) { + EXYNOSCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; + + return pCrtcPriv->front_bo; + } + else + XDBG_ERROR(MVA, "no crtc.\n"); + } + } + + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVirtualVideoGetBlackBuffer(EXYNOSPortPrivPtr pPort) +{ + int i; + + if (!pPort->outbuf) { + XDBG_RETURN_VAL_IF_FAIL(pPort->pDraw != NULL, NULL); + _exynosVirtualVideoEnsureOutBuffers(pPort->pScrn, pPort, pPort->id, + pPort->pDraw->width, + pPort->pDraw->height); + } + + for (i = 0; i < pPort->outbuf_num; i++) { + if (pPort->outbuf[i] && !pPort->outbuf[i]->showing) { + if (pPort->outbuf[i]->dirty) + exynosUtilClearVideoBuffer(pPort->outbuf[i]); + + return pPort->outbuf[i]; + } + } + + XDBG_ERROR(MVA, "now all buffers are in showing\n"); + + return NULL; +} + +static Bool +_exynosVirtualVideoEnsureOutBuffers(ScrnInfoPtr pScrn, EXYNOSPortPrivPtr pPort, + int id, int width, int height) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + int i; + + if (pPort->display == DISPLAY_EXTERNAL) + pPort->outbuf_num = BUF_NUM_EXTERNAL; + else + pPort->outbuf_num = BUF_NUM_STREAM; + + if (!pPort->outbuf) { + pPort->outbuf = + (EXYNOSVideoBuf **) calloc(pPort->outbuf_num, + sizeof(EXYNOSVideoBuf *)); + XDBG_RETURN_VAL_IF_FAIL(pPort->outbuf != NULL, FALSE); + } + + for (i = 0; i < pPort->outbuf_num; i++) { + int scanout; + + if (pPort->outbuf[i]) + continue; + + XDBG_RETURN_VAL_IF_FAIL(width > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(height > 0, FALSE); + + if (pPort->display == DISPLAY_MAIN) + scanout = FALSE; + else + scanout = pExynos->scanout; + + /* pPort->pScrn can be NULL if XvPutStill isn't called. */ + pPort->outbuf[i] = exynosUtilAllocVideoBuffer(pScrn, id, + width, height, + scanout, TRUE, + pPort->exynosure); + + XDBG_GOTO_IF_FAIL(pPort->outbuf[i] != NULL, ensure_buffer_fail); + } + + return TRUE; + + ensure_buffer_fail: + _exynosVirtualVideoCloseOutBuffer(pPort); + + return FALSE; +} + +static Bool +_exynosVirtualVideoEnsureDstBuffer(EXYNOSPortPrivPtr pPort) +{ + if (pPort->dstbuf) { + exynosUtilClearVideoBuffer(pPort->dstbuf); + return TRUE; + } + + pPort->dstbuf = exynosUtilAllocVideoBuffer(pPort->pScrn, FOURCC_RGB32, + pPort->pDraw->width, + pPort->pDraw->height, + FALSE, FALSE, pPort->exynosure); + XDBG_RETURN_VAL_IF_FAIL(pPort->dstbuf != NULL, FALSE); + + return TRUE; +} + +static EXYNOSVideoBuf * +_exynosVirtualVideoGetUIBuffer(EXYNOSPortPrivPtr pPort, int connector_type) +{ + EXYNOSVideoBuf *uibuf = NULL; + tbm_bo bo[PLANAR_CNT] = { 0, }; + EXYNOSFbBoDataPtr bo_data = NULL; + tbm_bo_handle bo_handle; + + bo[0] = _exynosVirtualVideoGetFrontBo(pPort, connector_type); + XDBG_RETURN_VAL_IF_FAIL(bo[0] != NULL, NULL); + + tbm_bo_get_user_data(bo[0], TBM_BO_DATA_FB, (void **) &bo_data); + XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, NULL); + + uibuf = exynosUtilCreateVideoBuffer(pPort->pScrn, FOURCC_RGB32, + bo_data->pos.x2 - bo_data->pos.x1, + bo_data->pos.y2 - bo_data->pos.y1, + FALSE); + XDBG_RETURN_VAL_IF_FAIL(uibuf != NULL, NULL); + + uibuf->bo[0] = tbm_bo_ref(bo[0]); + XDBG_GOTO_IF_FAIL(uibuf->bo[0] != NULL, fail_get); + + bo_handle = tbm_bo_get_handle(bo[0], TBM_DEVICE_DEFAULT); + uibuf->handles[0] = bo_handle.u32; + + XDBG_GOTO_IF_FAIL(uibuf->handles[0] > 0, fail_get); + + return uibuf; + + fail_get: + if (uibuf) + exynosUtilVideoBufferUnref(uibuf); + + return NULL; +} + +static EXYNOSVideoBuf * +_exynosVirtualVideoGetDrawableBuffer(EXYNOSPortPrivPtr pPort) +{ + EXYNOSVideoBuf *vbuf = NULL; + PixmapPtr pPixmap = NULL; + tbm_bo_handle bo_handle; + EXYNOSPixmapPriv *privPixmap; + Bool need_finish = FALSE; + + XDBG_GOTO_IF_FAIL(pPort->exynosure == FALSE, fail_get); + XDBG_GOTO_IF_FAIL(pPort->pDraw != NULL, fail_get); + + pPixmap = _exynosVirtualVideoGetPixmap(pPort->pDraw); + XDBG_GOTO_IF_FAIL(pPixmap != NULL, fail_get); + + privPixmap = exaGetPixmapDriverPrivate(pPixmap); + XDBG_GOTO_IF_FAIL(privPixmap != NULL, fail_get); + + if (!privPixmap->bo) { + need_finish = TRUE; + exynosExaPrepareAccess(pPixmap, EXA_PREPARE_DEST); + XDBG_GOTO_IF_FAIL(privPixmap->bo != NULL, fail_get); + } + + vbuf = exynosUtilCreateVideoBuffer(pPort->pScrn, FOURCC_RGB32, + pPort->pDraw->width, + pPort->pDraw->height, FALSE); + XDBG_GOTO_IF_FAIL(vbuf != NULL, fail_get); + + vbuf->bo[0] = tbm_bo_ref(privPixmap->bo); + bo_handle = tbm_bo_get_handle(privPixmap->bo, TBM_DEVICE_DEFAULT); + vbuf->handles[0] = bo_handle.u32; + + XDBG_GOTO_IF_FAIL(vbuf->handles[0] > 0, fail_get); + + return vbuf; + + fail_get: + if (pPixmap && need_finish) + exynosExaFinishAccess(pPixmap, EXA_PREPARE_DEST); + + if (vbuf) + exynosUtilVideoBufferUnref(vbuf); + + return NULL; +} + +static void +_exynosVirtualVideoCloseOutBuffer(EXYNOSPortPrivPtr pPort) +{ + int i; + + if (pPort->outbuf) { + for (i = 0; i < pPort->outbuf_num; i++) { + if (pPort->outbuf[i]) + exynosUtilVideoBufferUnref(pPort->outbuf[i]); + pPort->outbuf[i] = NULL; + } + + free(pPort->outbuf); + pPort->outbuf = NULL; + } + + if (pPort->dstbuf) { + exynosUtilVideoBufferUnref(pPort->dstbuf); + pPort->dstbuf = NULL; + } + + pPort->outbuf_index = -1; +} + +static int +_exynosVirtualVideoDataType(EXYNOSPortPrivPtr pPort) +{ + int ret = DATA_TYPE_NONE; + + if (exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1)) { + ret += DATA_TYPE_VIDEO; + } + if (exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_DEFAULT)) { + ret += DATA_TYPE_UI; + } + return ret; +} + +static int +_exynosVirtualVideoPreProcess(ScrnInfoPtr pScrn, EXYNOSPortPrivPtr pPort, + RegionPtr clipBoxes, DrawablePtr pDraw) +{ + if (pPort->pScrn == pScrn && pPort->pDraw == pDraw && + pPort->clipBoxes && clipBoxes && + RegionEqual(pPort->clipBoxes, clipBoxes)) + return Success; + + pPort->pScrn = pScrn; + pPort->pDraw = pDraw; + + if (clipBoxes) { + if (!pPort->clipBoxes) + pPort->clipBoxes = RegionCreate(NULL, 1); + + XDBG_RETURN_VAL_IF_FAIL(pPort->clipBoxes != NULL, BadAlloc); + + RegionCopy(pPort->clipBoxes, clipBoxes); + } + + XDBG_TRACE(MVA, "pDraw(0x%lx, %dx%d). \n", pDraw->id, pDraw->width, + pDraw->height); + + return Success; +} + +static int +_exynosVirtualVideoGetOutBufferIndex(EXYNOSPortPrivPtr pPort) +{ + if (!pPort->outbuf) + return -1; + + pPort->outbuf_index++; + if (pPort->outbuf_index >= pPort->outbuf_num) + pPort->outbuf_index = 0; + + return pPort->outbuf_index; +} + +static int +_exynosVirtualVideoSendPortNotify(EXYNOSPortPrivPtr pPort, + EXYNOSPortAttrAtom paa, INT32 value) +{ + EXYNOSVideoPortInfo *info; + Atom atom = None; + + XDBG_RETURN_VAL_IF_FAIL(pPort->pDraw != NULL, BadValue); + + info = _port_info(pPort->pDraw); + XDBG_RETURN_VAL_IF_FAIL(info != NULL, BadValue); + XDBG_RETURN_VAL_IF_FAIL(info->pp != NULL, BadValue); + + atom = _exynosVideoGetPortAtom(paa); + XDBG_RETURN_VAL_IF_FAIL(atom != None, BadValue); + + XDBG_TRACE(MVA, "paa(%d), value(%d)\n", paa, (int) value); + + return XvdiSendPortNotify(info->pp, atom, value); +} + +static Bool +_exynosVirtualVideoComposite(EXYNOSVideoBuf * src, EXYNOSVideoBuf * dst, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, + Bool composite, int rotate) +{ + xRectangle src_rect = { 0, }, dst_rect = { + 0,}; + + XDBG_RETURN_VAL_IF_FAIL(src != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src->bo[0] != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst->bo[0] != NULL, FALSE); + XDBG_RETURN_VAL_IF_FAIL(src->pitches[0] > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(dst->pitches[0] > 0, FALSE); + XDBG_RETURN_VAL_IF_FAIL(IS_RGB(src->id) || IS_YUV(src->id), FALSE); + XDBG_RETURN_VAL_IF_FAIL(IS_RGB(dst->id) || IS_YUV(dst->id), FALSE); + + XDBG_DEBUG(MVA, + "comp(%d) src : %" PRIuPTR + " %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %" PRIuPTR + " %c%c%c%c %dx%d (%d,%d %dx%d)\n", composite, src->stamp, + FOURCC_STR(src->id), src->width, src->height, src_x, src_y, + src_w, src_h, dst->stamp, FOURCC_STR(dst->id), dst->width, + dst->height, dst_x, dst_y, dst_w, dst_h); + + src_rect.x = src_x; + src_rect.y = src_y; + src_rect.width = src_w; + src_rect.height = src_h; + dst_rect.x = dst_x; + dst_rect.y = dst_y; + dst_rect.width = dst_w; + dst_rect.height = dst_h; + + exynosUtilConvertBos(src->pScrn, src->id, + src->bo[0], src->width, src->height, &src_rect, + src->pitches[0], dst->bo[0], dst->width, dst->height, + &dst_rect, dst->pitches[0], composite, rotate); + + return TRUE; +} + +static int +_exynosVirtualStillCompositeExtLayers(EXYNOSPortPrivPtr pPort, + int connector_type, Bool complete) +{ + EXYNOSLayer *lower_layer = NULL; + EXYNOSLayer *upper_layer = NULL; + EXYNOSVideoBuf *pix_buf = NULL; + EXYNOSVideoBuf *ui_buf = NULL; + EXYNOSVideoBuf *dst_buf = NULL; + xRectangle rect = { 0, }; + xRectangle src_rect, dst_rect; + int off_x = 0, off_y = 0; + Bool comp = FALSE; + int rotate = 0; + + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pPort->pScrn)->pExynosMode; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + lower_layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1); + if (lower_layer) { + exynosLayerGetRect(lower_layer, &src_rect, &dst_rect); + exynosLayerGetOffset(lower_layer, &off_x, &off_y); + dst_rect.x += off_x; + dst_rect.y += off_y; + } + //convertion is finished ? + if (!complete) { + /* check if operation in process */ + if (pPort->wait_rgb_convert) + goto convert_ipp_still; + + if (lower_layer) { + EXYNOSVideoBuf *lower_buf = exynosLayerGetBuffer(lower_layer); + + XDBG_GOTO_IF_FAIL(lower_buf != NULL, done_ipp_still); + if (!IS_RGB(lower_buf->id) || !IS_YUV(lower_buf->id)) { + /*convert vbuf to RGB format */ + pPort->capture_dstbuf = NULL; + if (exynosCaptureConvertImage(pPort, lower_buf, 0)) { + /* convertion in process */ + pPort->wait_rgb_convert = TRUE; + goto convert_ipp_still; + } + + } + + if (!lower_buf->exynosure && lower_buf && VBUF_IS_VALID(lower_buf)) { + /* In case of virtual, lower layer already has full-size. */ + dst_buf = lower_buf; + comp = TRUE; + } + } + } + else { + if (pPort->capture_dstbuf) + dst_buf = pPort->capture_dstbuf; + pPort->wait_rgb_convert = FALSE; + } + + pix_buf = _exynosVirtualVideoGetDrawableBuffer(pPort); + XDBG_GOTO_IF_FAIL(pix_buf != NULL, done_ipp_still); + + tbm_bo_map(pix_buf->bo[0], TBM_DEVICE_2D, TBM_OPTION_WRITE); + + int vwidth = pExynosMode->ext_connector_mode.hdisplay; + int vheight = pExynosMode->ext_connector_mode.vdisplay; + + rotate = (360 - pVideo->screen_rotate_degree) % 360; + + /* rotate upper_rect */ + exynosUtilRotateArea(&vwidth, &vheight, &dst_rect, rotate); + + /* scale upper_rect */ + exynosUtilScaleRect(vwidth, vheight, pix_buf->width, pix_buf->height, + &dst_rect); + + /* before compositing, flush all */ + exynosUtilCacheFlush(pPort->pScrn); + + comp = TRUE; + + if (dst_buf) { + + if (!_exynosVirtualVideoComposite(dst_buf, pix_buf, + 0, 0, dst_buf->width, dst_buf->height, + dst_rect.x, dst_rect.y, + dst_rect.width, dst_rect.height, + comp, rotate)) { + exynosUtilVideoBufferUnref(dst_buf); + goto done_ipp_still; + } + } + + ui_buf = _exynosVirtualVideoGetUIBuffer(pPort, connector_type); //Need to choose active connector DRM_MODE_CONNECTOR_VIRTUAL + XDBG_GOTO_IF_FAIL(ui_buf != NULL, done_ipp_still); + + if (ui_buf) { + ui_buf = exynosUtilVideoBufferRef(ui_buf); + tbm_bo_map(ui_buf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ); + + src_rect.x = src_rect.y = 0; + src_rect.width = ui_buf->width; + src_rect.height = ui_buf->height; + + dst_rect.x = dst_rect.y = 0; + dst_rect.width = ui_buf->width; + dst_rect.height = ui_buf->height; + + /* scale upper_rect */ + exynosUtilScaleRect(vwidth, vheight, pix_buf->width, pix_buf->height, + &dst_rect); + + XDBG_DEBUG(MVA, + "%dx%d(%d,%d, %dx%d) => %dx%d(%d,%d, %dx%d) :comp(%d) r(%d)\n", + ui_buf->width, ui_buf->height, src_rect.x, src_rect.y, + src_rect.width, src_rect.height, pix_buf->width, + pix_buf->height, dst_rect.x, dst_rect.y, dst_rect.width, + dst_rect.height, comp, rotate); + + if (!_exynosVirtualVideoComposite(ui_buf, pix_buf, + ui_buf->crop.x, ui_buf->crop.y, + ui_buf->crop.width, + ui_buf->crop.height, dst_rect.x, + dst_rect.y, dst_rect.width, + dst_rect.height, comp, rotate)) { + exynosUtilVideoBufferUnref(ui_buf); + goto done_ipp_still; + } + +// comp = TRUE; + } + + upper_layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_UPPER); + if (upper_layer) { + EXYNOSVideoBuf *upper_buf = exynosLayerGetBuffer(upper_layer); + + if (upper_buf && VBUF_IS_VALID(upper_buf)) { + exynosLayerGetRect(upper_layer, &upper_buf->crop, &rect); + + XDBG_DEBUG(MVA, + "upper : %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %c%c%c%c %dx%d (%d,%d %dx%d)\n", + FOURCC_STR(upper_buf->id), upper_buf->width, + upper_buf->height, upper_buf->crop.x, upper_buf->crop.y, + upper_buf->crop.width, upper_buf->crop.height, + FOURCC_STR(dst_buf->id), dst_buf->width, dst_buf->height, + rect.x, rect.y, rect.width, rect.height); + + _exynosVirtualVideoComposite(upper_buf, pix_buf, + upper_buf->crop.x, upper_buf->crop.y, + upper_buf->crop.width, + upper_buf->crop.height, rect.x, rect.y, + rect.width, rect.height, comp, 0); + } + } + + DamageDamageRegion(pPort->pDraw, pPort->clipBoxes); + pPort->need_damage = FALSE; + + done_ipp_still: + + if (dst_buf) + exynosUtilVideoBufferUnref(dst_buf); + if (ui_buf) + exynosUtilVideoBufferUnref(ui_buf); + if (pix_buf) + exynosUtilVideoBufferUnref(pix_buf); + + convert_ipp_still: + + return Success; +} + +static int +_exynosVirtualVideoCompositeExtLayers(EXYNOSPortPrivPtr pPort, + int connector_type) +{ + EXYNOSVideoBuf *dst_buf = NULL; + EXYNOSLayer *lower_layer = NULL; + EXYNOSLayer *upper_layer = NULL; + EXYNOSVideoBuf *ui_buf = NULL; + xRectangle rect = { 0, }; + int index; + Bool comp = FALSE; + + if (!_exynosVirtualVideoEnsureOutBuffers + (pPort->pScrn, pPort, pPort->id, pPort->pDraw->width, + pPort->pDraw->height)) + return FALSE; + + index = _exynosVirtualVideoGetOutBufferIndex(pPort); + if (index < 0) { + XDBG_WARNING(MVA, "all out buffers are in use.\n"); + return FALSE; + } + + lower_layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1); + if (lower_layer) { + EXYNOSVideoBuf *lower_buf = exynosLayerGetBuffer(lower_layer); + + XDBG_RETURN_VAL_IF_FAIL(lower_buf != NULL, FALSE); + + if (lower_buf && !lower_buf->exynosure && VBUF_IS_VALID(lower_buf)) { + /* In case of virtual, lower layer already has full-size. */ + dst_buf = lower_buf; + comp = TRUE; + } + } + + if (!dst_buf) { + if (!_exynosVirtualVideoEnsureDstBuffer(pPort)) + return FALSE; + + dst_buf = pPort->dstbuf; + } + + /* before compositing, flush all */ + exynosUtilCacheFlush(pPort->pScrn); + + comp = TRUE; //if set to FALSE capture may be black. something with layers? + + ui_buf = _exynosVirtualVideoGetUIBuffer(pPort, connector_type); //Need to choose active connector DRM_MODE_CONNECTOR_VIRTUAL + if (ui_buf) { + XDBG_DEBUG(MVA, + "ui : %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %c%c%c%c %dx%d (%d,%d %dx%d)\n", + FOURCC_STR(ui_buf->id), ui_buf->width, ui_buf->height, + ui_buf->crop.x, ui_buf->crop.y, ui_buf->crop.width, + ui_buf->crop.height, FOURCC_STR(dst_buf->id), dst_buf->width, + dst_buf->height, 0, 0, dst_buf->width, dst_buf->height); + + if (!_exynosVirtualVideoComposite(ui_buf, dst_buf, + ui_buf->crop.x, ui_buf->crop.y, + ui_buf->crop.width, + ui_buf->crop.height, 0, 0, + dst_buf->width, dst_buf->height, comp, + 0)) { + exynosUtilVideoBufferUnref(ui_buf); + return FALSE; + } + +// comp = TRUE; + } + + upper_layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_UPPER); + if (upper_layer) { + EXYNOSVideoBuf *upper_buf = exynosLayerGetBuffer(upper_layer); + + if (upper_buf && VBUF_IS_VALID(upper_buf)) { + exynosLayerGetRect(upper_layer, &upper_buf->crop, &rect); + + XDBG_DEBUG(MVA, + "upper : %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %c%c%c%c %dx%d (%d,%d %dx%d)\n", + FOURCC_STR(upper_buf->id), upper_buf->width, + upper_buf->height, upper_buf->crop.x, upper_buf->crop.y, + upper_buf->crop.width, upper_buf->crop.height, + FOURCC_STR(dst_buf->id), dst_buf->width, dst_buf->height, + rect.x, rect.y, rect.width, rect.height); + + _exynosVirtualVideoComposite(upper_buf, dst_buf, + upper_buf->crop.x, upper_buf->crop.y, + upper_buf->crop.width, + upper_buf->crop.height, rect.x, rect.y, + rect.width, rect.height, comp, 0); + } + } + + dst_buf->crop.x = 0; + dst_buf->crop.y = 0; + dst_buf->crop.width = dst_buf->width; + dst_buf->crop.height = dst_buf->height; + + XDBG_RETURN_VAL_IF_FAIL(pPort->outbuf[index] != NULL, FALSE); + + pPort->outbuf[index]->crop.x = 0; + pPort->outbuf[index]->crop.y = 0; + pPort->outbuf[index]->crop.width = pPort->outbuf[index]->width; + pPort->outbuf[index]->crop.height = pPort->outbuf[index]->height; + _exynosVirtualVideoComposite(dst_buf, pPort->outbuf[index], + 0, 0, dst_buf->width, dst_buf->height, + 0, 0, pPort->outbuf[index]->width, + pPort->outbuf[index]->height, FALSE, 0); + + _exynosVirtualVideoDraw(pPort, pPort->outbuf[index]); + + if (ui_buf) + exynosUtilVideoBufferUnref(ui_buf); + + return TRUE; +} + +static void +_exynosVirtualVideoCompositeSubtitle(EXYNOSPortPrivPtr pPort, + EXYNOSVideoBuf * vbuf) +{ + EXYNOSLayer *subtitle_layer; + EXYNOSVideoBuf *subtitle_vbuf; + xRectangle src_rect; + xRectangle dst_rect; + + subtitle_layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_UPPER); + if (!subtitle_layer) + return; + + subtitle_vbuf = exynosLayerGetBuffer(subtitle_layer); + if (!subtitle_vbuf || !VBUF_IS_VALID(subtitle_vbuf)) + return; + + CLEAR(src_rect); + CLEAR(dst_rect); + exynosLayerGetRect(subtitle_layer, &src_rect, &dst_rect); + + XDBG_DEBUG(MVA, "subtitle : %dx%d (%d,%d %dx%d) => %dx%d (%d,%d %dx%d)\n", + subtitle_vbuf->width, subtitle_vbuf->height, + src_rect.x, src_rect.y, src_rect.width, src_rect.height, + vbuf->width, vbuf->height, + dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height); + + _exynosVirtualVideoComposite(subtitle_vbuf, vbuf, + src_rect.x, src_rect.y, src_rect.width, + src_rect.height, dst_rect.x, dst_rect.y, + dst_rect.width, dst_rect.height, TRUE, 0); +} + +static CARD32 +_exynosVirtualVideoRetireTimeout(OsTimerPtr timer, CARD32 now, pointer arg) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) arg; + EXYNOSModePtr pExynosMode; + int diff; + + if (!pPort) + return 0; + + pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pPort->pScrn)->pExynosMode; + + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + XDBG_ERROR(MVA, "capture(%d) mode(%d) conn(%d) type(%d) status(%x). \n", + pPort->capture, pExynosMode->set_mode, pExynosMode->conn_mode, + pPort->data_type, pPort->status); + + diff = GetTimeInMillis() - pPort->retire_time; + XDBG_ERROR(MVA, "failed : +++ Retire Timeout!! diff(%d)\n", diff); + + return 0; +} + +static void +_exynosVirtualVideoLayerNotifyFunc(EXYNOSLayer * layer, int type, + void *type_data, void *data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + EXYNOSVideoBuf *vbuf = (EXYNOSVideoBuf *) type_data; + EXYNOSVideoBuf *black; + + exynosLayerRemoveNotifyFunc(layer, _exynosVirtualVideoLayerNotifyFunc); + + if (type == LAYER_DESTROYED || type != LAYER_BUF_CHANGED || !vbuf) + goto fail_layer_noti; + + XDBG_GOTO_IF_FAIL(VBUF_IS_VALID(vbuf), fail_layer_noti); + XDBG_GOTO_IF_FAIL(vbuf->showing == FALSE, fail_layer_noti); + + XDBG_DEBUG(MVA, "------------------------------\n"); + + _exynosVirtualVideoCompositeSubtitle(pPort, vbuf); + _exynosVirtualVideoDraw(pPort, vbuf); + XDBG_DEBUG(MVA, "------------------------------...\n"); + + return; + + fail_layer_noti: + black = _exynosVirtualVideoGetBlackBuffer(pPort); + XDBG_TRACE(MVA, "black buffer(%d) return: layer noti. type(%d), vbuf(%p)\n", + (black) ? black->keys[0] : 0, type, vbuf); + _exynosVirtualVideoDraw(pPort, black); +} + +static int +_exynosVirtualVideoPutStill(EXYNOSPortPrivPtr pPort, int connector_type) +{ + EXYNOSModePtr pExynosMode = + (EXYNOSModePtr) EXYNOSPTR(pPort->pScrn)->pExynosMode; + EXYNOSVideoBuf *pix_buf = NULL; + EXYNOSVideoBuf *ui_buf = NULL; + Bool comp; + int i; + CARD32 start = GetTimeInMillis(); + + TTRACE_VIDEO_BEGIN("XORG:XV:VIDEOPUTSTILL"); + + XDBG_GOTO_IF_FAIL(pPort->exynosure == FALSE, done_still); + + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + comp = TRUE; //if set to FALSE capture will be black. something with layers? + + pix_buf = _exynosVirtualVideoGetDrawableBuffer(pPort); + XDBG_GOTO_IF_FAIL(pix_buf != NULL, done_still); + + ui_buf = _exynosVirtualVideoGetUIBuffer(pPort, connector_type); + XDBG_GOTO_IF_FAIL(ui_buf != NULL, done_still); + + tbm_bo_map(pix_buf->bo[0], TBM_DEVICE_2D, TBM_OPTION_WRITE); + + for (i = LAYER_LOWER2; i < LAYER_MAX; i++) { + EXYNOSVideoBuf *upper = NULL; + xRectangle src_rect, dst_rect; + int vwidth = pExynosMode->main_lcd_mode.hdisplay; + int vheight = pExynosMode->main_lcd_mode.vdisplay; + int rotate; + + if (i == LAYER_DEFAULT) { + upper = exynosUtilVideoBufferRef(ui_buf); + tbm_bo_map(upper->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ); + + src_rect.x = src_rect.y = 0; + src_rect.width = ui_buf->width; + src_rect.height = ui_buf->height; + + dst_rect.x = dst_rect.y = 0; + dst_rect.width = ui_buf->width; + dst_rect.height = ui_buf->height; + + rotate = 0; + } + else { + EXYNOSLayer *layer = + exynosLayerFind(LAYER_OUTPUT_LCD, (EXYNOSLayerPos) i); + int off_x = 0, off_y = 0; + EXYNOSVideoPrivPtr pVideo = EXYNOSPTR(pPort->pScrn)->pVideoPriv; + + if (!layer) + continue; + + upper = exynosUtilVideoBufferRef(exynosLayerGetBuffer(layer)); + if (!upper || !VBUF_IS_VALID(upper)) + continue; + + exynosLayerGetRect(layer, &src_rect, &dst_rect); + exynosLayerGetOffset(layer, &off_x, &off_y); + dst_rect.x += off_x; + dst_rect.y += off_y; + + rotate = (360 - pVideo->screen_rotate_degree) % 360; + + /* rotate upper_rect */ + exynosUtilRotateArea(&vwidth, &vheight, &dst_rect, rotate); + } + + /* scale upper_rect */ + exynosUtilScaleRect(vwidth, vheight, pix_buf->width, pix_buf->height, + &dst_rect); + + XDBG_DEBUG(MVA, + "%dx%d(%d,%d, %dx%d) => %dx%d(%d,%d, %dx%d) :comp(%d) r(%d)\n", + upper->width, upper->height, src_rect.x, src_rect.y, + src_rect.width, src_rect.height, pix_buf->width, + pix_buf->height, dst_rect.x, dst_rect.y, dst_rect.width, + dst_rect.height, comp, rotate); + + if (!_exynosVirtualVideoComposite(upper, pix_buf, + src_rect.x, src_rect.y, + src_rect.width, src_rect.height, + dst_rect.x, dst_rect.y, + dst_rect.width, dst_rect.height, + comp, rotate)) { + if (i == LAYER_DEFAULT) + tbm_bo_unmap(upper->bo[0]); + tbm_bo_unmap(pix_buf->bo[0]); + goto done_still; + } + + if (i == LAYER_DEFAULT) + tbm_bo_unmap(upper->bo[0]); + + exynosUtilVideoBufferUnref(upper); + + comp = TRUE; + } + + XDBG_TRACE(MVA, "make still: %ldms\n", GetTimeInMillis() - start); + + tbm_bo_unmap(pix_buf->bo[0]); + + done_still: + + exynosUtilCacheFlush(pPort->pScrn); + + if (pix_buf) + exynosUtilVideoBufferUnref(pix_buf); + if (ui_buf) + exynosUtilVideoBufferUnref(ui_buf); + + DamageDamageRegion(pPort->pDraw, pPort->clipBoxes); + pPort->need_damage = FALSE; + + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + if ((pExynos->dump_mode & XBERC_DUMP_MODE_CA) && pExynos->dump_info) { + PixmapPtr pPixmap = _exynosVirtualVideoGetPixmap(pPort->pDraw); + char file[128]; + static int i; + + snprintf(file, sizeof(file), "capout_still_%03d.bmp", i++); + exynosUtilDoDumpPixmaps(pExynos->dump_info, pPixmap, file, + DUMP_TYPE_BMP); + } + + TTRACE_VIDEO_END(); + + return Success; +} + +static int +_exynosVirtualVideoPutWB(EXYNOSPortPrivPtr pPort) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pPort->pScrn); + + XDBG_RETURN_VAL_IF_FAIL(pPort->pScrn != NULL, BadImplementation); + XDBG_RETURN_VAL_IF_FAIL(pPort->pDraw != NULL, BadImplementation); + + if (!pPort->wb) { + if (!exynosWbIsOpened()) { + int scanout; + + if (!_exynosVirtualVideoEnsureOutBuffers + (pPort->pScrn, pPort, pPort->id, pPort->pDraw->width, + pPort->pDraw->height)) + return BadAlloc; + if (pPort->display == DISPLAY_MAIN) + scanout = FALSE; + else + scanout = pExynos->scanout; + + /* For capture mode, we don't need to create contiguous buffer. + * Rotation should be considered when wb begins. + */ + pPort->wb = exynosWbOpen(pPort->pScrn, pPort->id, + pPort->pDraw->width, pPort->pDraw->height, + scanout, 60, + (pPort->rotate_off) ? FALSE : TRUE); + XDBG_RETURN_VAL_IF_FAIL(pPort->wb != NULL, BadAlloc); + exynosWbSetBuffer(pPort->wb, pPort->outbuf, pPort->outbuf_num); + + XDBG_TRACE(MVA, "wb(%p) start. \n", pPort->wb); + + if (!exynosWbStart(pPort->wb)) { + exynosWbClose(pPort->wb); + pPort->wb = NULL; + return BadAlloc; + } + pPort->need_close_wb = TRUE; + } + else { + pPort->wb = exynosWbGet(); + pPort->need_close_wb = FALSE; + } + if (pPort->capture == CAPTURE_MODE_STILL) { + exynosWbAddNotifyFunc(pPort->wb, WB_NOTI_IPP_EVENT_DONE, + _exynosVirtualVideoWbDumpDoneFunc, pPort); + } + + exynosWbAddNotifyFunc(pPort->wb, WB_NOTI_STOP, + _exynosVirtualVideoWbStopFunc, pPort); + exynosWbAddNotifyFunc(pPort->wb, WB_NOTI_IPP_EVENT, + _exynosVirtualVideoWbDumpFunc, pPort); + + exynosWbAddNotifyFunc(pPort->wb, WB_NOTI_CLOSED, + _exynosVirtualVideoWbCloseFunc, pPort); + } + + /* no available buffer, need to return buffer by client. */ + if (!exynosWbIsRunning()) { + XDBG_WARNING(MVA, "wb is stopped.\n"); + return BadRequest; + } +#if 0 + /* no available buffer, need to return buffer by client. */ + if (!exynosWbCanDequeueBuffer(pPort->wb)) { + XDBG_TRACE(MVA, "no available buffer\n"); + return BadRequest; + } +#endif + XDBG_TRACE(MVA, "wb(%p), running(%d). \n", pPort->wb, exynosWbIsRunning()); + + return Success; +} + +static int +_exynosVirtualVideoPutVideoOnly(EXYNOSPortPrivPtr pPort) +{ + EXYNOSLayer *layer; + EXYNOSVideoBuf *vbuf; + int i; + + XDBG_RETURN_VAL_IF_FAIL(pPort->display == DISPLAY_EXTERNAL, BadRequest); + XDBG_RETURN_VAL_IF_FAIL(pPort->capture == CAPTURE_MODE_STREAM, BadRequest); + + TTRACE_VIDEO_BEGIN("XORG:XV:PUTVIDEOONLY"); + + layer = exynosLayerFind(LAYER_OUTPUT_EXT, LAYER_LOWER1); + if (!layer) { + TTRACE_VIDEO_END(); + return BadRequest; + } + + if (!pPort->outbuf) { + if (!_exynosVirtualVideoEnsureOutBuffers + (pPort->pScrn, pPort, pPort->id, pPort->pDraw->width, + pPort->pDraw->height)) { + XDBG_ERROR(MVA, "Didn't create outbuf array\n"); + TTRACE_VIDEO_END(); + return BadAlloc; + } + } + + for (i = 0; i < pPort->outbuf_num; i++) { + if (!pPort->outbuf[i]) { + XDBG_ERROR(MVA, "Didn't create outbuf %d\n", i); + TTRACE_VIDEO_END(); + return BadRequest; + } + + if (!pPort->outbuf[i]->showing) + break; + } + + if (i == pPort->outbuf_num) { + XDBG_ERROR(MVA, "now all buffers are in showing\n"); + TTRACE_VIDEO_END(); + return BadRequest; + } + + vbuf = exynosLayerGetBuffer(layer); + /* if layer is just created, vbuf can't be null. */ + if (!vbuf || !VBUF_IS_VALID(vbuf)) { + EXYNOSVideoBuf *black = _exynosVirtualVideoGetBlackBuffer(pPort); + + XDBG_GOTO_IF_FAIL(black != NULL, put_fail); + + XDBG_TRACE(MVA, "black buffer(%d) return: vbuf invalid\n", + black->keys[0]); + _exynosVirtualVideoDraw(pPort, black); + TTRACE_VIDEO_END(); + return Success; + } + + /* Wait the next frame if it's same as previous one */ + if (_exynosVirtualVideoFindReturnBuf(pPort, vbuf->keys[0])) { + exynosLayerAddNotifyFunc(layer, _exynosVirtualVideoLayerNotifyFunc, + pPort); + XDBG_DEBUG(MVA, "wait notify.\n"); + TTRACE_VIDEO_END(); + return Success; + } + + _exynosVirtualVideoCompositeSubtitle(pPort, vbuf); + _exynosVirtualVideoDraw(pPort, vbuf); + + TTRACE_VIDEO_END(); + + return Success; + + put_fail: + TTRACE_VIDEO_END(); + return BadRequest; +} + +static int +_exynosVirtualVideoPutExt(EXYNOSPortPrivPtr pPort, int active_connector) +{ + if (_exynosVirtualVideoCompositeExtLayers(pPort, active_connector)) + return Success; + + return BadRequest; +} + +static int +EXYNOSVirtualVideoGetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 *value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _exynosVideoGetPortAtom(PAA_FORMAT)) { + *value = pPort->id; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_CAPTURE)) { + *value = pPort->capture; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_DISPLAY)) { + *value = pPort->display; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_ROTATE_OFF)) { + *value = pPort->rotate_off; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_DATA_TYPE)) { + *value = pPort->data_type; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_SECURE)) { + *value = pPort->exynosure; + return Success; + } + return BadMatch; +} + +static int +EXYNOSVirtualVideoSetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (attribute == _exynosVideoGetPortAtom(PAA_FORMAT)) { + if (!_exynosVirtualVideoIsSupport((unsigned int) value)) { + XDBG_ERROR(MVA, "id(%c%c%c%c) not supported.\n", FOURCC_STR(value)); + return BadRequest; + } + + pPort->id = (unsigned int) value; + XDBG_DEBUG(MVA, "id(%d) \n", (int) value); + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_CAPTURE)) { + if (value < CAPTURE_MODE_NONE || value >= CAPTURE_MODE_MAX) { + XDBG_ERROR(MVA, "capture value(%d) is out of range\n", (int) value); + return BadRequest; + } + + pPort->capture = value; + XDBG_DEBUG(MVA, "capture(%d) \n", pPort->capture); + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_DISPLAY)) { + pPort->display = value; + XDBG_DEBUG(MVA, "display: %d \n", pPort->display); + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_ROTATE_OFF)) { + XDBG_DEBUG(MVA, "ROTATE_OFF: %d! \n", pPort->rotate_off); + pPort->rotate_off = value; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_SECURE)) { + XDBG_TRACE(MVA, "not implemented 'exynosure' attr. (%d) \n", + pPort->exynosure); +// pPort->exynosure = value; + return Success; + } + else if (attribute == _exynosVideoGetPortAtom(PAA_RETBUF)) { + RetBufInfo *info; + + if (!pPort->pDraw) + return Success; + + info = _exynosVirtualVideoFindReturnBuf(pPort, value); + if (!info) { + XDBG_WARNING(MVA, "wrong gem name(%d) returned\n", (int) value); + return Success; + } + + if (info->vbuf && info->vbuf->need_reset) + exynosUtilClearVideoBuffer(info->vbuf); + + _exynosVirtualVideoRemoveReturnBuf(pPort, info); +#if 0 + _buffers(pPort); + ErrorF("[Xorg] retbuf : %ld (%s)\n", value, buffers); +#endif + + return Success; + } + + return Success; +} + +/* vid_w, vid_h : no meaning for us. not using. + * dst_w, dst_h : size to hope for PutStill. + * p_w, p_h : real size for PutStill. + */ +static void +EXYNOSVirtualVideoQueryBestSize(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + if (pPort->display == DISPLAY_EXTERNAL) { + if (p_w) + *p_w = pExynosMode->ext_connector_mode.hdisplay; + if (p_h) + *p_h = pExynosMode->ext_connector_mode.vdisplay; + } + else { + if (p_w) + *p_w = (unsigned int) dst_w; + if (p_h) + *p_h = (unsigned int) dst_h; + } +} + +/* vid_x, vid_y, vid_w, vid_h : no meaning for us. not using. + * drw_x, drw_y, dst_w, dst_h : no meaning for us. not using. + * Only pDraw's size is used. + */ +static int +EXYNOSVirtualVideoPutStill(ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) +{ + EXYNOSPtr pExynos = EXYNOSPTR(pScrn); + EXYNOSModePtr pExynosMode = (EXYNOSModePtr) EXYNOSPTR(pScrn)->pExynosMode; + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + int ret = BadRequest; + + XDBG_GOTO_IF_FAIL(pPort->need_damage == FALSE, put_still_fail); + +#if 0 + ErrorF("[Xorg] PutStill\n"); +#endif + + TTRACE_VIDEO_BEGIN("XORG:XV:PUTSTILL"); + + XDBG_DEBUG(MVA, "*************************************** \n"); + + if (pExynos->xvperf_mode & XBERC_XVPERF_MODE_CA) { + CARD32 cur, sub; + + cur = GetTimeInMillis(); + sub = cur - pPort->prev_time; + pPort->prev_time = cur; + ErrorF("getstill interval : %6" PRIXID " ms\n", sub); + } + + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + if (pExynos->pVideoPriv->no_retbuf) + _exynosVirtualVideoRemoveReturnBufAll(pPort); + + pPort->retire_timer = TimerSet(pPort->retire_timer, 0, 4000, + _exynosVirtualVideoRetireTimeout, pPort); + XDBG_GOTO_IF_FAIL(pPort->id > 0, put_still_fail); + + pPort->status = 0; + pPort->retire_time = GetTimeInMillis(); + + ret = _exynosVirtualVideoPreProcess(pScrn, pPort, clipBoxes, pDraw); + XDBG_GOTO_IF_FAIL(ret == Success, put_still_fail); + + ret = _exynosVirtualVideoAddDrawableEvent(pPort); + XDBG_GOTO_IF_FAIL(ret == Success, put_still_fail); + +#if 0 + /* check drawable */ + XDBG_RETURN_VAL_IF_FAIL(pDraw->type == DRAWABLE_PIXMAP, BadPixmap); +#endif + + if (!pPort->putstill_on) { + pPort->putstill_on = TRUE; + XDBG_SECURE(MVA, + "pPort(%d) putstill on. exynosure(%d), capture(%d), display(%d) format(%c%c%c%c)\n", + pPort->index, pPort->exynosure, pPort->capture, + pPort->display, FOURCC_STR(pPort->id)); + } + + pPort->need_damage = TRUE; + + /*find what connector is active */ + int active_connector = -1; //DRM_MODE_CONNECTOR_HDMIA + + active_connector = findActiveConnector(pPort->pScrn); + + if (active_connector == -1) { + ret = BadRequest; + goto put_still_fail; + } + pPort->active_connector = active_connector; + + if (pPort->capture == CAPTURE_MODE_STILL && pPort->display == DISPLAY_MAIN) { + if (pPort->active_connector == DRM_MODE_CONNECTOR_LVDS) { + XDBG_DEBUG(MVA, "still mode LCD.\n"); + + ret = _exynosVirtualVideoPutStill(pPort, active_connector); + XDBG_GOTO_IF_FAIL(ret == Success, put_still_fail); + } + else { + XDBG_DEBUG(MVA, "still mode HDMI or Virtual Display.\n"); + ret = + _exynosVirtualStillCompositeExtLayers(pPort, active_connector, + FALSE); + XDBG_GOTO_IF_FAIL(ret == Success, put_still_fail); + } + } + else if (pPort->capture == CAPTURE_MODE_STREAM && + pPort->display == DISPLAY_MAIN) { + XDBG_DEBUG(MVA, "stream mode.\n"); + if (EXYNOSPTR(pScrn)->isLcdOff) { + XDBG_TRACE(MVA, "DPMS status: off. \n"); + ret = BadRequest; + goto put_still_fail; + } + + if (0) + ret = _exynosVirtualVideoPutWB(pPort); + else + ret = _exynosVirtualVideoPutExt(pPort, active_connector); + if (ret != Success) + goto put_still_fail; + } + else if (pPort->capture == CAPTURE_MODE_STREAM && + pPort->display == DISPLAY_EXTERNAL) { + int old_data_type = pPort->data_type; + EXYNOSVideoBuf *black; + + switch (pExynosMode->set_mode) { + case DISPLAY_SET_MODE_OFF: + XDBG_DEBUG(MVA, "display mode is off. \n"); + black = _exynosVirtualVideoGetBlackBuffer(pPort); + if (black == NULL) { + ret = BadRequest; + goto put_still_fail; + } + XDBG_DEBUG(MVA, "black buffer(%d) return: lcd off\n", + black->keys[0]); + _exynosVirtualVideoDraw(pPort, black); + ret = Success; + goto put_still_fail; +#if 0 + case DISPLAY_SET_MODE_CLONE: + pPort->data_type = _exynosVirtualVideoDataType(pPort); + + if (pPort->data_type != old_data_type) + _exynosVirtualVideoSendPortNotify(pPort, PAA_DATA_TYPE, + pPort->data_type); + + if (pPort->data_type == DATA_TYPE_UI) { + XDBG_DEBUG(MVA, "clone mode.\n"); + + ret = _exynosVirtualVideoPutWB(pPort); + if (ret != Success) + goto put_still_fail; + } + else { + XDBG_DEBUG(MVA, "video only mode.\n"); + ret = _exynosVirtualVideoPutVideoOnly(pPort); + if (ret != Success) + goto put_still_fail; + } + break; + + case DISPLAY_SET_MODE_EXT: + XDBG_DEBUG(MVA, "desktop mode.\n"); + + if (pExynosMode->ext_connector_mode.hdisplay != pDraw->width || + pExynosMode->ext_connector_mode.vdisplay != pDraw->height) { + XDBG_ERROR(MVA, + "drawble should have %dx%d size. mode(%d), conn(%d)\n", + pExynosMode->ext_connector_mode.hdisplay, + pExynosMode->ext_connector_mode.vdisplay, + pExynosMode->set_mode, pExynosMode->conn_mode); + ret = BadRequest; + goto put_still_fail; + } + + ret = _exynosVirtualVideoPutExt(pPort, active_connector); + if (ret != Success) + goto put_still_fail; + break; +#else + case DISPLAY_SET_MODE_EXT: + pPort->data_type = _exynosVirtualVideoDataType(pPort); + + if (pPort->data_type != old_data_type) + _exynosVirtualVideoSendPortNotify(pPort, PAA_DATA_TYPE, + pPort->data_type); + if (pPort->data_type == DATA_TYPE_NONE) { + XDBG_DEBUG(MVA, "enable clone mode.\n"); + + ret = _exynosVirtualVideoPutWB(pPort); + + if (ret != Success) + goto put_still_fail; + } + else if (pPort->data_type == DATA_TYPE_UI || pPort->need_close_wb) { + XDBG_DEBUG(MVA, "clone mode.\n"); + + ret = _exynosVirtualVideoPutWB(pPort); + + if (ret != Success) + goto put_still_fail; + } + else if (pPort->data_type == DATA_TYPE_VIDEO && + !pPort->need_close_wb) { + XDBG_DEBUG(MVA, "video only mode.\n"); + + ret = _exynosVirtualVideoPutVideoOnly(pPort); + + if (ret != Success) + goto put_still_fail; + } + + break; +#endif + default: + break; + } + } + else { + XDBG_NEVER_GET_HERE(MVA); + ret = BadRequest; + goto put_still_fail; + } + + XDBG_DEBUG(MVA, "***************************************.. \n"); + + TTRACE_VIDEO_END(); + + return Success; + + put_still_fail: + pPort->need_damage = FALSE; + + if (pPort->retire_timer) { + TimerFree(pPort->retire_timer); + pPort->retire_timer = NULL; + } + + XDBG_DEBUG(MVA, "***************************************.. \n"); + + TTRACE_VIDEO_END(); + + return ret; +} + +static void +EXYNOSVirtualVideoStop(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) data; + + _exynosVirtualVideoStreamOff(pPort); +} + +static int +EXYNOSVirtualVideoDDPutStill(ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, CARD16 drw_w, + CARD16 drw_h) +{ + EXYNOSVideoPortInfo *info = _port_info(pDraw); + int ret; + + if (info) { + info->client = client; + info->pp = pPort; + } + + ret = ddPutStill(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h); + + return ret; +} + +XF86VideoAdaptorPtr +exynosVideoSetupVirtualVideo(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr pAdaptor; + EXYNOSPortPrivPtr pPort; + int i; + + pAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + + (sizeof(DevUnion) + + sizeof(EXYNOSPortPriv)) * EXYNOS_MAX_PORT); + if (!pAdaptor) + return NULL; + + dummy_encoding[0].width = pScreen->width; + dummy_encoding[0].height = pScreen->height; + + pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvStillMask; + pAdaptor->flags = 0; + pAdaptor->name = "EXYNOS Virtual Video"; + pAdaptor->nEncodings = + sizeof(dummy_encoding) / sizeof(XF86VideoEncodingRec); + pAdaptor->pEncodings = dummy_encoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = formats; + pAdaptor->nPorts = EXYNOS_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion *) (&pAdaptor[1]); + + pPort = (EXYNOSPortPrivPtr) (&pAdaptor->pPortPrivates[EXYNOS_MAX_PORT]); + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + pAdaptor->pPortPrivates[i].ptr = &pPort[i]; + pPort[i].index = i; + pPort[i].id = FOURCC_RGB32; + pPort[i].outbuf_index = -1; + + xorg_list_init(&pPort[i].retbuf_info); + } + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = attributes; + pAdaptor->nImages = NUM_IMAGES; + pAdaptor->pImages = images; + + pAdaptor->GetPortAttribute = EXYNOSVirtualVideoGetPortAttribute; + pAdaptor->SetPortAttribute = EXYNOSVirtualVideoSetPortAttribute; + pAdaptor->QueryBestSize = EXYNOSVirtualVideoQueryBestSize; + pAdaptor->PutStill = EXYNOSVirtualVideoPutStill; + pAdaptor->StopVideo = EXYNOSVirtualVideoStop; + + if (!_exynosVirtualVideoRegisterEventResourceTypes()) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to register EventResourceTypes. \n"); + return NULL; + } + + return pAdaptor; +} + +void +exynosVirtualVideoDpms(ScrnInfoPtr pScrn, Bool on) +{ + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + XF86VideoAdaptorPtr pAdaptor = pExynos->pVideoPriv->pAdaptor[1]; + int i; + + if (on) + return; + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + EXYNOSPortPrivPtr pPort = + (EXYNOSPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + + if (pPort->wb) { + exynosWbClose(pPort->wb); + pPort->wb = NULL; + } + } +} + +void +exynosVirtualVideoReplacePutStillFunc(ScreenPtr pScreen) +{ + int i; + + XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, + XvGetScreenKey()); + + if (!xvsp) + return; + + for (i = 1; i < xvsp->nAdaptors; i++) { + XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; + + if (pAdapt->ddPutStill) { + ddPutStill = pAdapt->ddPutStill; + pAdapt->ddPutStill = EXYNOSVirtualVideoDDPutStill; + break; + } + } + + if (!dixRegisterPrivateKey + (VideoVirtualPortKey, PRIVATE_WINDOW, sizeof(EXYNOSVideoPortInfo))) + return; + if (!dixRegisterPrivateKey + (VideoVirtualPortKey, PRIVATE_PIXMAP, sizeof(EXYNOSVideoPortInfo))) + return; +} + +void +exynosVirtualVideoGetBuffers(ScrnInfoPtr pScrn, int id, int width, int height, + EXYNOSVideoBuf *** vbufs, int *bufnum) +{ + EXYNOSPtr pExynos = (EXYNOSPtr) pScrn->driverPrivate; + XF86VideoAdaptorPtr pAdaptor = pExynos->pVideoPriv->pAdaptor[1]; + int i; + + for (i = 0; i < EXYNOS_MAX_PORT; i++) { + EXYNOSPortPrivPtr pPort = + (EXYNOSPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + + if (pPort->pDraw) { + XDBG_RETURN_IF_FAIL(pPort->id == id); + XDBG_RETURN_IF_FAIL(pPort->pDraw->width == width); + XDBG_RETURN_IF_FAIL(pPort->pDraw->height == height); + } + + if (!_exynosVirtualVideoEnsureOutBuffers + (pScrn, pPort, id, width, height)) + return; + + *vbufs = pPort->outbuf; + *bufnum = pPort->outbuf_num; + } +} + +static void +_exynosCaptureCvtCallback(EXYNOSCvt * cvt, + EXYNOSVideoBuf * src, + EXYNOSVideoBuf * dst, void *cvt_data, Bool error) +{ + EXYNOSPortPrivPtr pPort = (EXYNOSPortPrivPtr) cvt_data; + + XDBG_RETURN_IF_FAIL(pPort != NULL); + XDBG_RETURN_IF_FAIL(cvt != NULL); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(src)); + XDBG_RETURN_IF_FAIL(VBUF_IS_VALID(dst)); + + XDBG_DEBUG(MVA, "++++++++++++++++++++++++ \n"); + XDBG_DEBUG(MVA, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst); + + pPort->capture_dstbuf = dst; + + /*begin composition again */ + _exynosVirtualStillCompositeExtLayers(pPort, pPort->active_connector, TRUE); +} + +static void +_exynosCaptureEnsureConverter(EXYNOSPortPrivPtr pPort) +{ + if (pPort->cvt2) + return; + + pPort->cvt2 = exynosCvtCreate(pPort->pScrn, CVT_OP_M2M); + XDBG_RETURN_IF_FAIL(pPort->cvt2 != NULL); + + exynosCvtAddCallback(pPort->cvt2, _exynosCaptureCvtCallback, pPort); +} + +static void +_exynosCaptureCloseConverter(EXYNOSPortPrivPtr pPort) +{ + if (pPort->cvt2) { + exynosCvtDestroy(pPort->cvt2); + pPort->cvt2 = NULL; + } + + XDBG_TRACE(MVA, "done. \n"); +} + +static Bool +exynosCaptureConvertImage(EXYNOSPortPrivPtr pPort, EXYNOSVideoBuf * inbuf, + int csc_range) +{ + EXYNOSCvtProp src_prop = { 0, }, dst_prop = { + 0,}; + EXYNOSVideoBuf *outbuf = NULL; + + pPort->exynosure = 0; + + src_prop.id = inbuf->id; + src_prop.width = inbuf->width; + src_prop.height = inbuf->height; + src_prop.crop = inbuf->crop; + + dst_prop.id = FOURCC_RGB32; + dst_prop.width = inbuf->width; + dst_prop.height = inbuf->height; + dst_prop.crop = inbuf->crop; + + dst_prop.degree = 0; + dst_prop.hflip = 0; + dst_prop.vflip = 0; + dst_prop.exynosure = pPort->exynosure; + dst_prop.csc_range = 0; // pPort->csc_range; + + if (!exynosCvtEnsureSize(&src_prop, &dst_prop)) + goto fail_to_convert; + + XDBG_GOTO_IF_FAIL(pPort != NULL, fail_to_convert); + + outbuf = pPort->capture_dstbuf; + if (outbuf == NULL) { + outbuf = exynosUtilAllocVideoBuffer(pPort->pScrn, FOURCC_RGB32, + dst_prop.width, dst_prop.height, + FALSE, FALSE, pPort->exynosure); + XDBG_GOTO_IF_FAIL(outbuf != NULL, fail_to_convert); + + outbuf->crop = dst_prop.crop; + } + + _exynosCaptureEnsureConverter(pPort); + XDBG_GOTO_IF_FAIL(pPort->cvt2 != NULL, fail_to_convert); + + if (!exynosCvtSetProperpty(pPort->cvt2, &src_prop, &dst_prop)) + goto fail_to_convert; + + if (!exynosCvtConvert(pPort->cvt2, inbuf, outbuf)) + goto fail_to_convert; + + exynosUtilVideoBufferUnref(outbuf); + + return TRUE; + + fail_to_convert: + + if (outbuf) + exynosUtilVideoBufferUnref(outbuf); + + _exynosCaptureCloseConverter(pPort); + + return FALSE; +} diff --git a/src/xv/sec_video_virtual.h b/src/xv/exynos_video_virtual.h index a3400b4..95d70aa 100644 --- a/src/xv/sec_video_virtual.h +++ b/src/xv/exynos_video_virtual.h @@ -31,10 +31,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define __SEC_VIDEO_VIRTUAL_H__ /* setup virtual adaptor */ -XF86VideoAdaptorPtr secVideoSetupVirtualVideo (ScreenPtr pScreen); -void secVirtualVideoReplacePutStillFunc (ScreenPtr pScreen); +XF86VideoAdaptorPtr exynosVideoSetupVirtualVideo(ScreenPtr pScreen); +void exynosVirtualVideoReplacePutStillFunc(ScreenPtr pScreen); -void secVirtualVideoDpms (ScrnInfoPtr pScrn, Bool on); -void secVirtualVideoGetBuffers (ScrnInfoPtr pScrn, int id, int width, int height, SECVideoBuf ***vbufs, int *bufnum); +void exynosVirtualVideoDpms(ScrnInfoPtr pScrn, Bool on); +void exynosVirtualVideoGetBuffers(ScrnInfoPtr pScrn, int id, int width, + int height, EXYNOSVideoBuf *** vbufs, + int *bufnum); -#endif // __SEC_VIDEO_VIRTUAL_H__ +#endif // __SEC_VIDEO_VIRTUAL_H__ diff --git a/src/xv/sec_video.c b/src/xv/sec_video.c deleted file mode 100644 index 9eb7d01..0000000 --- a/src/xv/sec_video.c +++ /dev/null @@ -1,3095 +0,0 @@ -/* - * xserver-xorg-video-exynos - * - * Copyright 2004 Keith Packard - * Copyright 2005 Eric Anholt - * Copyright 2006 Nokia Corporation - * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - * - * Contact: Boram Park <boram1288.park@samsung.com> - * - * Permission to use, copy, modify, distribute and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the names of the authors and/or copyright holders - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. The authors and - * copyright holders make no representations about the suitability of this - * software for any purpose. It is provided "as is" without any express - * or implied warranty. - * - * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <string.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/ioctl.h> - -#include <pixman.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> -#include <fourcc.h> - -#include <fb.h> -#include <fbdevhw.h> -#include <damage.h> - -#include <xf86xv.h> - -#include "sec.h" - -#include "sec_accel.h" -#include "sec_display.h" -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_video.h" -#include "sec_prop.h" -#include "sec_util.h" -#include "sec_wb.h" -#include "sec_video_virtual.h" -#include "sec_video_display.h" -#include "sec_video_tvout.h" -#include "sec_video_fourcc.h" -#include "sec_converter.h" -#include "sec_plane.h" -#include "sec_xberc.h" - -#include "xv_types.h" - -#include <exynos_drm.h> - -#define DONT_FILL_ALPHA -1 -#define SEC_MAX_PORT 16 - -#define INBUF_NUM 6 -#define OUTBUF_NUM 3 -#define NUM_HW_LAYER 2 - -#define OUTPUT_LCD (1 << 0) -#define OUTPUT_EXT (1 << 1) -#define OUTPUT_FULL (1 << 8) - -static XF86VideoEncodingRec dummy_encoding[] = -{ - { 0, "XV_IMAGE", -1, -1, { 1, 1 } }, - { 1, "XV_IMAGE", 4224, 4224, { 1, 1 } }, -}; - -static XF86ImageRec images[] = -{ - XVIMAGE_YUY2, - XVIMAGE_SUYV, - XVIMAGE_UYVY, - XVIMAGE_SYVY, - XVIMAGE_ITLV, - XVIMAGE_YV12, - XVIMAGE_I420, - XVIMAGE_S420, - XVIMAGE_ST12, - XVIMAGE_NV12, - XVIMAGE_SN12, - XVIMAGE_NV21, - XVIMAGE_SN21, - XVIMAGE_RGB32, - XVIMAGE_SR32, - XVIMAGE_RGB565, - XVIMAGE_SR16, -}; - -static XF86VideoFormatRec formats[] = -{ - { 16, TrueColor }, - { 24, TrueColor }, - { 32, TrueColor }, -}; - -static XF86AttributeRec attributes[] = -{ - { 0, 0, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP" }, - { 0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION" }, - { 0, 0, OUTPUT_MODE_EXT_ONLY, "_USER_WM_PORT_ATTRIBUTE_OUTPUT" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE" }, -}; - -typedef enum -{ - PAA_MIN, - PAA_ROTATION, - PAA_HFLIP, - PAA_VFLIP, - PAA_PREEMPTION, - PAA_OUTPUT, - PAA_SECURE, - PAA_CSC_RANGE, - PAA_MAX -} SECPortAttrAtom; - -static struct -{ - SECPortAttrAtom paa; - const char *name; - Atom atom; -} atoms[] = -{ - { PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None }, - { PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None }, - { PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None }, - { PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None }, - { PAA_OUTPUT, "_USER_WM_PORT_ATTRIBUTE_OUTPUT", None }, - { PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None }, - { PAA_CSC_RANGE, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE", None }, -}; - -enum -{ - ON_NONE, - ON_FB, - ON_WINDOW, - ON_PIXMAP -}; - -static char *drawing_type[4] = {"NONE", "FB", "WIN", "PIX"}; - -typedef struct _PutData -{ - unsigned int id; - int width; - int height; - xRectangle src; - xRectangle dst; - void *buf; - Bool sync; - RegionPtr clip_boxes; - void *data; - DrawablePtr pDraw; -} PutData; - -/* SEC port information structure */ -typedef struct -{ - CARD32 prev_time; - int index; - - /* attributes */ - int rotate; - int hflip; - int vflip; - int preemption; /* 1:high, 0:default, -1:low */ - Bool secure; - int csc_range; - - ScrnInfoPtr pScrn; - PutData d; - PutData old_d; - - /* draw inform */ - int drawing; - int hw_rotate; - - int in_width; - int in_height; - xRectangle in_crop; - SECVideoBuf *inbuf[INBUF_NUM]; - Bool inbuf_is_fb; - - /* converter */ - SECCvt *cvt; - - /* layer */ - SECLayer *layer; - int out_width; - int out_height; - xRectangle out_crop; - SECVideoBuf *outbuf[OUTBUF_NUM]; - int outbuf_cvting; - DrawablePtr pDamageDrawable[OUTBUF_NUM]; - - /* tvout */ - int usr_output; - int old_output; - int grab_tvout; - SECVideoTv *tv; - void *gem_list; - Bool skip_tvout; - Bool need_start_wb; - SECVideoBuf *wait_vbuf; - CARD32 tv_prev_time; - - /* count */ - unsigned int put_counts; - OsTimerPtr timer; - - Bool punched; - int stream_cnt; - struct xorg_list link; -} SECPortPriv, *SECPortPrivPtr; - -static RESTYPE event_drawable_type; - -typedef struct _SECVideoResource -{ - XID id; - RESTYPE type; - - SECPortPrivPtr pPort; - ScrnInfoPtr pScrn; -} SECVideoResource; - -typedef struct _SECVideoPortInfo -{ - ClientPtr client; - XvPortPtr pp; -} SECVideoPortInfo; - -static int (*ddPutImage) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char *, Bool, CARD16, CARD16); - -static void _secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys); -static void SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit); -static void _secVideoCloseInBuffer (SECPortPrivPtr pPort); -static void _secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer); -static void _secVideoCloseConverter (SECPortPrivPtr pPort); -static Bool _secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool tvout); - -static int streaming_ports; -static int registered_handler; -static struct xorg_list layer_owners; - -static DevPrivateKeyRec video_port_key; -#define VideoPortKey (&video_port_key) -#define GetPortInfo(pDraw) ((SECVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoPortKey)) - -#define NUM_IMAGES (sizeof(images) / sizeof(images[0])) -#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) -#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) -#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) - -#define ENSURE_AREA(off, lng, max) (lng = ((off + lng) > max ? (max - off) : lng)) - -static CARD32 -_countPrint (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)arg; - - if (pPort->timer) - { - TimerFree (pPort->timer); - pPort->timer = NULL; - } - - ErrorF ("PutImage(%d) : %d fps. \n", pPort->index, pPort->put_counts); - - pPort->put_counts = 0; - - return 0; -} - -static void -_countFps (SECPortPrivPtr pPort) -{ - pPort->put_counts++; - - if (pPort->timer) - return; - - pPort->timer = TimerSet (NULL, 0, 1000, _countPrint, pPort); -} - -static SECVideoPortInfo* -_port_info (DrawablePtr pDraw) -{ - if (!pDraw) - return NULL; - - if (pDraw->type == DRAWABLE_WINDOW) - return GetPortInfo ((WindowPtr)pDraw); - else - return GetPortInfo ((PixmapPtr)pDraw); -} - -static PixmapPtr -_getPixmap (DrawablePtr pDraw) -{ - if (pDraw->type == DRAWABLE_WINDOW) - return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); - else - return (PixmapPtr) pDraw; -} - -static XF86ImagePtr -_get_image_info (int id) -{ - int i; - - for (i = 0; i < NUM_IMAGES; i++) - if (images[i].id == id) - return &images[i]; - - return NULL; -} - -static Atom -_portAtom (SECPortAttrAtom paa) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None); - - for (i = 0; i < NUM_ATOMS; i++) - { - if (paa == atoms[i].paa) - { - if (atoms[i].atom == None) - atoms[i].atom = MakeAtom (atoms[i].name, - strlen (atoms[i].name), TRUE); - - return atoms[i].atom; - } - } - - XDBG_ERROR (MVDO, "Error: Unknown Port Attribute Name!\n"); - - return None; -} - -static void -_DestroyData (void *port, void *data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)port; - unsigned int handle = (unsigned int)data; - - secUtilFreeHandle (pPort->pScrn, handle); -} - -static Bool -_secVideoGrabTvout (SECPortPrivPtr pPort) -{ - SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv; - - if (pPort->grab_tvout) - return TRUE; - - /* other port already grabbed */ - if (pVideo->tvout_in_use) - { - XDBG_WARNING (MVDO, "*** pPort(%p) can't grab tvout. It's in use.\n", pPort); - return FALSE; - } - - if (pPort->tv) - { - XDBG_ERROR (MVDO, "*** wrong handle if you reach here. %p \n", pPort->tv); - return FALSE; - } - - pPort->grab_tvout = TRUE; - pVideo->tvout_in_use = TRUE; - - XDBG_TRACE (MVDO, "pPort(%p) grabs tvout.\n", pPort); - - return TRUE; -} - -static void -_secVideoUngrabTvout (SECPortPrivPtr pPort) -{ - if (pPort->tv) - { - secVideoTvDisconnect (pPort->tv); - pPort->tv = NULL; - } - - /* This port didn't grab tvout */ - if (!pPort->grab_tvout) - return; - - _secVideoSetOutputExternalProperty (pPort->d.pDraw, FALSE); - - if (pPort->need_start_wb) - { - SECWb *wb = secWbGet (); - if (wb) - { - secWbSetSecure (wb, pPort->secure); - secWbStart (wb); - } - pPort->need_start_wb = FALSE; - } - - XDBG_TRACE (MVDO, "pPort(%p) ungrabs tvout.\n", pPort); - - pPort->grab_tvout = FALSE; - - if (pPort->pScrn) - { - SECVideoPrivPtr pVideo; - pVideo = SECPTR(pPort->pScrn)->pVideoPriv; - pVideo->tvout_in_use = FALSE; - } - pPort->wait_vbuf = NULL; -} - -static int -_secVideoGetTvoutMode (SECPortPrivPtr pPort) -{ - SECModePtr pSecMode = (SECModePtr) SECPTR (pPort->pScrn)->pSecMode; - SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv; - SECDisplaySetMode disp_mode = secDisplayGetDispSetMode (pPort->pScrn); - int output = OUTPUT_LCD; - - if (disp_mode == DISPLAY_SET_MODE_CLONE) - { - if (pPort->preemption > -1) - { - if (pVideo->video_output > 0 && streaming_ports == 1) - { - int video_output = pVideo->video_output - 1; - - if (video_output == OUTPUT_MODE_DEFAULT) - output = OUTPUT_LCD; - else if (video_output == OUTPUT_MODE_TVOUT) - output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL; - else - output = OUTPUT_EXT|OUTPUT_FULL; - } - else if (streaming_ports == 1) - { - output = pPort->usr_output; - if (!(output & OUTPUT_FULL)) - output &= ~(OUTPUT_EXT); - } - else if (streaming_ports > 1) - output = OUTPUT_LCD; - else - XDBG_NEVER_GET_HERE (MVDO); - } - else - output = OUTPUT_LCD; - } - else if (disp_mode == DISPLAY_SET_MODE_EXT) - { - if (pPort->drawing == ON_PIXMAP) - output = OUTPUT_LCD; - else - { - xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pPort->pScrn, - (int)pPort->d.pDraw->x, (int)pPort->d.pDraw->y, - (int)pPort->d.pDraw->width, (int)pPort->d.pDraw->height); - int c = secCrtcGetConnectType (pCrtc); - - if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown) - output = OUTPUT_LCD; - else if (c == DRM_MODE_CONNECTOR_HDMIA || c == DRM_MODE_CONNECTOR_HDMIB) - output = OUTPUT_EXT; - else if (c == DRM_MODE_CONNECTOR_VIRTUAL) - output = OUTPUT_EXT; - else - XDBG_NEVER_GET_HERE (MVDO); - } - } - else /* DISPLAY_SET_MODE_OFF */ - { - output = OUTPUT_LCD; - } - - if (pPort->drawing == ON_PIXMAP) - output = OUTPUT_LCD; - - XDBG_DEBUG (MVDO, "drawing(%d) disp_mode(%d) preemption(%d) streaming_ports(%d) conn_mode(%d) usr_output(%d) video_output(%d) output(%x) skip(%d)\n", - pPort->drawing, disp_mode, pPort->preemption, streaming_ports, pSecMode->conn_mode, - pPort->usr_output, pVideo->video_output, output, pPort->skip_tvout); - - return output; -} - -static int -_secVideodrawingOn (SECPortPrivPtr pPort) -{ - if (pPort->old_d.pDraw != pPort->d.pDraw) - pPort->drawing = ON_NONE; - - if (pPort->drawing != ON_NONE) - return pPort->drawing; - - if (pPort->d.pDraw->type == DRAWABLE_PIXMAP) - return ON_PIXMAP; - else if (pPort->d.pDraw->type == DRAWABLE_WINDOW) - { - PropertyPtr prop = secUtilGetWindowProperty ((WindowPtr)pPort->d.pDraw, - "XV_ON_DRAWABLE"); - if (prop && *(int*)prop->data > 0) - return ON_WINDOW; - } - - return ON_FB; -} - -static void -_secVideoGetRotation (SECPortPrivPtr pPort, int *hw_rotate) -{ - SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv; - - /* - * RR_Rotate_90: Target turns to 90. UI turns to 270. - * RR_Rotate_270: Target turns to 270. UI turns to 90. - * - * [Target] ---------- - * | | - * Top (RR_Rotate_90) | | Top (RR_Rotate_270) - * | | - * ---------- - * [UI,FIMC] ---------- - * | | - * Top (degree: 270) | | Top (degree: 90) - * | | - * ---------- - */ - - if (pPort->drawing == ON_FB) - *hw_rotate = (pPort->rotate + pVideo->screen_rotate_degree) % 360; - else - *hw_rotate = pPort->rotate % 360; -} - -static int -_secVideoGetKeys (SECPortPrivPtr pPort, unsigned int *keys, unsigned int *type) -{ - XV_DATA_PTR data = (XV_DATA_PTR) pPort->d.buf; - int valid = XV_VALIDATE_DATA (data); - - if (valid == XV_HEADER_ERROR) - { - XDBG_ERROR (MVDO, "XV_HEADER_ERROR\n"); - return valid; - } - else if (valid == XV_VERSION_MISMATCH) - { - XDBG_ERROR (MVDO, "XV_VERSION_MISMATCH\n"); - return valid; - } - - if (keys) - { - keys[0] = data->YBuf; - keys[1] = data->CbBuf; - keys[2] = data->CrBuf; - } - - if (type) - *type = data->BufType; - - return 0; -} - -static void -_secVideoFreeInbuf (SECVideoBuf *vbuf, void *data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)data; - int i; - - XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE); - - for (i = 0; i < INBUF_NUM; i++) - if (pPort->inbuf[i] == vbuf) - { - _secVideoSendReturnBufferMessage (pPort, vbuf, NULL); - pPort->inbuf[i] = NULL; - return; - } - - XDBG_NEVER_GET_HERE (MVDO); -} - -static void -_secVideoFreeOutbuf (SECVideoBuf *vbuf, void *data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)data; - int i; - - XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE); - - for (i = 0; i < OUTBUF_NUM; i++) - if (pPort->outbuf[i] == vbuf) - { - pPort->pDamageDrawable[i] = NULL; - pPort->outbuf[i] = NULL; - return; - } - - XDBG_NEVER_GET_HERE (MVDO); -} - -static SECLayer* -_secVideoCreateLayer (SECPortPrivPtr pPort) -{ - ScrnInfoPtr pScrn = pPort->pScrn; - SECVideoPrivPtr pVideo = SECPTR(pScrn)->pVideoPriv; - DrawablePtr pDraw = pPort->d.pDraw; - xf86CrtcConfigPtr pCrtcConfig; - xf86OutputPtr pOutput = NULL; - int i; - xf86CrtcPtr pCrtc; - SECLayer *layer; - Bool full = TRUE; - xRectangle src, dst; - - pCrtc = secCrtcGetAtGeometry (pScrn, pDraw->x, pDraw->y, pDraw->width, pDraw->height); - XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL); - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn); - XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, NULL); - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pTemp = pCrtcConfig->output[i]; - if (pTemp->crtc == pCrtc) - { - pOutput = pTemp; - break; - } - } - XDBG_RETURN_VAL_IF_FAIL (pOutput != NULL, NULL); - - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - SECLayerOutput output = LAYER_OUTPUT_LCD; - - if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown) - { - output = LAYER_OUTPUT_LCD; - } - else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB || - pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) - { - output = LAYER_OUTPUT_EXT; - } - else - XDBG_NEVER_GET_HERE (MVDO); - - if (!secLayerFind (output, LAYER_LOWER2) || !secLayerFind (output, LAYER_LOWER1)) - full = FALSE; - - if (full) - return NULL; - - layer = secLayerCreate (pScrn, output, LAYER_NONE); - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL); - - src = dst = pPort->out_crop; - dst.x = pPort->d.dst.x; - dst.y = pPort->d.dst.y; - - secLayerSetRect (layer, &src, &dst); - secLayerEnableVBlank (layer, TRUE); - - xorg_list_add (&pPort->link, &layer_owners); - - secLayerSetOffset (layer, pVideo->video_offset_x, pVideo->video_offset_y); - - return layer; -} - -static SECVideoBuf* -_secVideoGetInbufZeroCopy (SECPortPrivPtr pPort, unsigned int *names, unsigned int buf_type) -{ - SECVideoBuf *inbuf = NULL; - int i, empty; - tbm_bo_handle bo_handle; - - for (empty = 0; empty < INBUF_NUM; empty++) - if (!pPort->inbuf[empty]) - break; - - if (empty == INBUF_NUM) - { - XDBG_ERROR (MVDO, "now all inbufs in use!\n"); - return NULL; - } - - /* make sure both widths are same.*/ - XDBG_RETURN_VAL_IF_FAIL (pPort->d.width == pPort->in_width, NULL); - XDBG_RETURN_VAL_IF_FAIL (pPort->d.height == pPort->in_height, NULL); - - inbuf = secUtilCreateVideoBuffer (pPort->pScrn, pPort->d.id, - pPort->in_width, pPort->in_height, - pPort->secure); - XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL); - - inbuf->crop = pPort->in_crop; - - for (i = 0; i < PLANAR_CNT; i++) - { - if (names[i] > 0) - { - inbuf->keys[i] = names[i]; - - if (buf_type == XV_BUF_TYPE_LEGACY) - { - void *data = secUtilListGetData (pPort->gem_list, (void*)names[i]); - if (!data) - { - secUtilConvertPhyaddress (pPort->pScrn, names[i], inbuf->lengths[i], &inbuf->handles[i]); - - pPort->gem_list = secUtilListAdd (pPort->gem_list, (void*)names[i], - (void*)inbuf->handles[i]); - } - else - inbuf->handles[i] = (unsigned int)data; - - XDBG_DEBUG (MVDO, "%d, %p => %d \n", i, (void*)names[i], inbuf->handles[i]); - } - else - { - XDBG_GOTO_IF_FAIL (inbuf->lengths[i] > 0, fail_dma); - XDBG_GOTO_IF_FAIL (inbuf->bo[i] == NULL, fail_dma); - - inbuf->bo[i] = tbm_bo_import (SECPTR (pPort->pScrn)->tbm_bufmgr, inbuf->keys[i]); - XDBG_GOTO_IF_FAIL (inbuf->bo[i] != NULL, fail_dma); - - bo_handle = tbm_bo_get_handle(inbuf->bo[i], TBM_DEVICE_DEFAULT); - inbuf->handles[i] = bo_handle.u32; - XDBG_GOTO_IF_FAIL (inbuf->handles[i] > 0, fail_dma); - - XDBG_DEBUG (MVDO, "%d, key(%d) => bo(%p) handle(%d)\n", - i, inbuf->keys[i], inbuf->bo[i], inbuf->handles[i]); - } - } - } - - /* not increase ref_cnt to free inbuf when converting/showing is done. */ - pPort->inbuf[empty] = inbuf; - - secUtilAddFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort); - - return inbuf; - -fail_dma: - if (inbuf) - secUtilFreeVideoBuffer (inbuf); - - return NULL; -} - -static SECVideoBuf* -_secVideoGetInbufRAW (SECPortPrivPtr pPort) -{ - SECVideoBuf *inbuf = NULL; - void *vir_addr = NULL; - int i; - tbm_bo_handle bo_handle; - - /* we can't access virtual pointer. */ - XDBG_RETURN_VAL_IF_FAIL (pPort->secure == FALSE, NULL); - - for (i = 0; i < INBUF_NUM; i++) - { - if (pPort->inbuf[i]) - continue; - - pPort->inbuf[i] = secUtilAllocVideoBuffer (pPort->pScrn, pPort->d.id, - pPort->in_width, pPort->in_height, - FALSE, FALSE, pPort->secure); - XDBG_GOTO_IF_FAIL (pPort->inbuf[i] != NULL, fail_raw_alloc); - } - - for (i = 0; i < INBUF_NUM; i++) - { - XDBG_DEBUG (MVDO, "? inbuf(%d,%p) converting(%d) showing(%d)\n", i, - pPort->inbuf[i], VBUF_IS_CONVERTING (pPort->inbuf[i]), pPort->inbuf[i]->showing); - - if (pPort->inbuf[i] && !VBUF_IS_CONVERTING (pPort->inbuf[i]) && !pPort->inbuf[i]->showing) - { - /* increase ref_cnt to keep inbuf until stream_off. */ - inbuf = secUtilVideoBufferRef (pPort->inbuf[i]); - break; - } - } - - if (!inbuf) - { - XDBG_ERROR (MVDO, "now all inbufs in use!\n"); - return NULL; - } - - inbuf->crop = pPort->in_crop; - - bo_handle = tbm_bo_map (inbuf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE); - vir_addr = bo_handle.ptr; - XDBG_RETURN_VAL_IF_FAIL (vir_addr != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (inbuf->size > 0, NULL); - - if (pPort->d.width != pPort->in_width || pPort->d.height != pPort->in_height) - { - XF86ImagePtr image_info = _get_image_info (pPort->d.id); - XDBG_RETURN_VAL_IF_FAIL (image_info != NULL, NULL); - int pitches[3] = {0,}; - int offsets[3] = {0,}; - int lengths[3] = {0,}; - int width, height; - - width = pPort->d.width; - height = pPort->d.height; - - secVideoQueryImageAttrs (pPort->pScrn, pPort->d.id, - &width, &height, - pitches, offsets, lengths); - - secUtilCopyImage (width, height, - pPort->d.buf, width, height, - pitches, offsets, lengths, - vir_addr, inbuf->width, inbuf->height, - inbuf->pitches, inbuf->offsets, inbuf->lengths, - image_info->num_planes, - image_info->horz_u_period, - image_info->vert_u_period); - } - else - memcpy (vir_addr, pPort->d.buf, inbuf->size); - - tbm_bo_unmap (inbuf->bo[0]); - secUtilCacheFlush (pPort->pScrn); - return inbuf; - -fail_raw_alloc: - _secVideoCloseInBuffer (pPort); - return NULL; -} - -static SECVideoBuf* -_secVideoGetInbuf (SECPortPrivPtr pPort) -{ - unsigned int keys[PLANAR_CNT] = {0,}; - unsigned int buf_type = 0; - SECVideoBuf *inbuf = NULL; - SECPtr pSec = SECPTR (pPort->pScrn); - - if (IS_ZEROCOPY (pPort->d.id)) - { - if (_secVideoGetKeys (pPort, keys, &buf_type)) - return NULL; - - XDBG_RETURN_VAL_IF_FAIL (keys[0] > 0, NULL); - - if (pPort->d.id == FOURCC_SN12 || pPort->d.id == FOURCC_ST12) - XDBG_RETURN_VAL_IF_FAIL (keys[1] > 0, NULL); - - inbuf = _secVideoGetInbufZeroCopy (pPort, keys, buf_type); - - XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL); - XDBG_TRACE (MVDO, "keys: %d,%d,%d. stamp(%ld)\n", keys[0], keys[1], keys[2], inbuf->stamp); - } - else - inbuf = _secVideoGetInbufRAW (pPort); - - XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL); - - if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info) - { - char file[128]; - static int i; - snprintf (file, sizeof(file), "xvin_%c%c%c%c_%dx%d_p%d_%03d.%s", - FOURCC_STR(inbuf->id), - inbuf->width, inbuf->height, pPort->index, i++, - IS_RGB(inbuf->id)?"bmp":"yuv"); - secUtilDoDumpVBuf (pSec->dump_info, inbuf, file); - } - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA) - inbuf->put_time = GetTimeInMillis (); - - return inbuf; -} - -static SECVideoBuf* -_secVideoGetOutbufDrawable (SECPortPrivPtr pPort) -{ - ScrnInfoPtr pScrn = pPort->pScrn; - DrawablePtr pDraw = pPort->d.pDraw; - PixmapPtr pPixmap = (PixmapPtr)_getPixmap (pDraw); - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap); - Bool need_finish = FALSE; - SECVideoBuf *outbuf = NULL; - int empty; - tbm_bo_handle bo_handle; - - for (empty = 0; empty < OUTBUF_NUM; empty++) - if (!pPort->outbuf[empty]) - break; - - if (empty == OUTBUF_NUM) - { - XDBG_ERROR (MVDO, "now all outbufs in use!\n"); - return NULL; - } - - if ((pDraw->width % 16) && (pPixmap->usage_hint != CREATE_PIXMAP_USAGE_XVIDEO)) - { - ScreenPtr pScreen = pScrn->pScreen; - SECFbBoDataPtr bo_data = NULL; - - pPixmap->usage_hint = CREATE_PIXMAP_USAGE_XVIDEO; - pScreen->ModifyPixmapHeader (pPixmap, - pDraw->width, pDraw->height, - pDraw->depth, - pDraw->bitsPerPixel, - pPixmap->devKind, 0); - XDBG_RETURN_VAL_IF_FAIL (privPixmap->bo != NULL, NULL); - - tbm_bo_get_user_data(privPixmap->bo, TBM_BO_DATA_FB, (void**)&bo_data); - XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.x2 - bo_data->pos.x1) == pPort->out_width, NULL); - XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.y2 - bo_data->pos.y1) == pPort->out_height, NULL); - } - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, fail_drawable); - } - - outbuf = secUtilCreateVideoBuffer (pScrn, FOURCC_RGB32, - pPort->out_width, - pPort->out_height, - pPort->secure); - XDBG_GOTO_IF_FAIL (outbuf != NULL, fail_drawable); - outbuf->crop = pPort->out_crop; - - XDBG_TRACE (MVDO, "outbuf(%p)(%dx%d) created. [%s]\n", - outbuf, pPort->out_width, pPort->out_height, - (pPort->drawing==ON_PIXMAP)?"PIX":"WIN"); - - outbuf->bo[0] = tbm_bo_ref (privPixmap->bo); - - bo_handle = tbm_bo_get_handle (outbuf->bo[0], TBM_DEVICE_DEFAULT); - outbuf->handles[0] = bo_handle.u32; - XDBG_GOTO_IF_FAIL (outbuf->handles[0] > 0, fail_drawable); - - if (need_finish) - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - pPort->pDamageDrawable[empty] = pPort->d.pDraw; - -// RegionTranslate (pPort->d.clip_boxes, -pPort->d.dst.x, -pPort->d.dst.y); - - /* not increase ref_cnt to free outbuf when converting/showing is done. */ - pPort->outbuf[empty] = outbuf; - - secUtilAddFreeVideoBufferFunc (outbuf, _secVideoFreeOutbuf, pPort); - - return outbuf; - -fail_drawable: - if (outbuf) - secUtilFreeVideoBuffer (outbuf); - - return NULL; -} - -static SECVideoBuf* -_secVideoGetOutbufFB (SECPortPrivPtr pPort) -{ - ScrnInfoPtr pScrn = pPort->pScrn; - SECVideoBuf *outbuf = NULL; - int i, next; - - if (!pPort->layer) - { - pPort->layer = _secVideoCreateLayer (pPort); - XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, NULL); - } - else - { - SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer); - if (vbuf && (vbuf->width == pPort->out_width && vbuf->height == pPort->out_height)) - { - xRectangle src = {0,}, dst = {0,}; - - secLayerGetRect (pPort->layer, &src, &dst); - - /* CHECK */ - if (pPort->d.dst.x != dst.x || pPort->d.dst.y != dst.y) - { - /* x,y can be changed when window is moved. */ - dst.x = pPort->d.dst.x; - dst.y = pPort->d.dst.y; - secLayerSetRect (pPort->layer, &src, &dst); - } - } - } - - for (i = 0; i < OUTBUF_NUM; i++) - { - SECPtr pSec = SECPTR (pPort->pScrn); - - if (pPort->outbuf[i]) - continue; - - pPort->outbuf[i] = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32, - pPort->out_width, pPort->out_height, - (pSec->scanout)?TRUE:FALSE, - FALSE, pPort->secure); - XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, fail_fb); - pPort->outbuf[i]->crop = pPort->out_crop; - - XDBG_TRACE (MVDO, "out bo(%p, %d, %dx%d) created. [FB]\n", - pPort->outbuf[i]->bo[0], pPort->outbuf[i]->handles[0], - pPort->out_width, pPort->out_height); - } - - next = ++pPort->outbuf_cvting; - if (next >= OUTBUF_NUM) - next = 0; - - for (i = 0; i < OUTBUF_NUM; i++) - { - XDBG_DEBUG (MVDO, "? outbuf(%d,%p) converting(%d)\n", next, - pPort->outbuf[next], VBUF_IS_CONVERTING (pPort->outbuf[next])); - - if (pPort->outbuf[next] && !VBUF_IS_CONVERTING (pPort->outbuf[next])) - { - /* increase ref_cnt to keep outbuf until stream_off. */ - outbuf = secUtilVideoBufferRef (pPort->outbuf[next]); - break; - } - - next++; - if (next >= OUTBUF_NUM) - next = 0; - } - - if (!outbuf) - { - XDBG_ERROR (MVDO, "now all outbufs in use!\n"); - return NULL; - } - - pPort->outbuf_cvting = next; - - return outbuf; - -fail_fb: - _secVideoCloseConverter (pPort); - _secVideoCloseOutBuffer (pPort, TRUE); - - return NULL; -} - -static SECVideoBuf* -_secVideoGetOutbuf (SECPortPrivPtr pPort) -{ - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - return _secVideoGetOutbufDrawable (pPort); - else /* ON_FB */ - return _secVideoGetOutbufFB (pPort); -} - -static void -_secVideoCloseInBuffer (SECPortPrivPtr pPort) -{ - int i; - - _secVideoUngrabTvout (pPort); - - if (pPort->gem_list) - { - secUtilListDestroyData (pPort->gem_list, _DestroyData, pPort); - secUtilListDestroy (pPort->gem_list); - pPort->gem_list = NULL; - } - - if (!IS_ZEROCOPY (pPort->d.id)) - for (i = 0; i < INBUF_NUM; i++) - { - if (pPort->inbuf[i]) - { - secUtilVideoBufferUnref (pPort->inbuf[i]); - pPort->inbuf[i] = NULL; - } - } - - pPort->in_width = 0; - pPort->in_height = 0; - memset (&pPort->in_crop, 0, sizeof (xRectangle)); - - XDBG_DEBUG (MVDO, "done\n"); -} - -static void -_secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer) -{ - int i; - - /* before close outbuf, layer/cvt should be finished. */ - if (close_layer && pPort->layer) - { - secLayerUnref (pPort->layer); - pPort->layer = NULL; - xorg_list_del (&pPort->link); - } - - for (i = 0; i < OUTBUF_NUM; i++) - { - if (pPort->outbuf[i]) - { - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - XDBG_NEVER_GET_HERE (MVDO); - - secUtilVideoBufferUnref (pPort->outbuf[i]); - pPort->outbuf[i] = NULL; - } - } - - pPort->out_width = 0; - pPort->out_height = 0; - memset (&pPort->out_crop, 0, sizeof (xRectangle)); - pPort->outbuf_cvting = -1; - - XDBG_DEBUG (MVDO, "done\n"); -} - -static void -_secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys) -{ - static Atom return_atom = None; - SECVideoPortInfo *info = _port_info (pPort->d.pDraw); - - if (return_atom == None) - return_atom = MakeAtom ("XV_RETURN_BUFFER", - strlen ("XV_RETURN_BUFFER"), TRUE); - - if (!info) - return; - - xEvent event; - - CLEAR (event); - event.u.u.type = ClientMessage; - event.u.u.detail = 32; - event.u.clientMessage.u.l.type = return_atom; - if (vbuf) - { - event.u.clientMessage.u.l.longs0 = (INT32)vbuf->keys[0]; - event.u.clientMessage.u.l.longs1 = (INT32)vbuf->keys[1]; - event.u.clientMessage.u.l.longs2 = (INT32)vbuf->keys[2]; - - XDBG_TRACE (MVDO, "%ld: %d,%d,%d out. diff(%ld)\n", vbuf->stamp, - vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], GetTimeInMillis()-vbuf->stamp); - } - else if (keys) - { - event.u.clientMessage.u.l.longs0 = (INT32)keys[0]; - event.u.clientMessage.u.l.longs1 = (INT32)keys[1]; - event.u.clientMessage.u.l.longs2 = (INT32)keys[2]; - - XDBG_TRACE (MVDO, "%d,%d,%d out. \n", - keys[0], keys[1], keys[2]); - } - else - XDBG_NEVER_GET_HERE (MVDO); - - WriteEventsToClient(info->client, 1, (xEventPtr) &event); - - SECPtr pSec = SECPTR (pPort->pScrn); - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA) - { - if (vbuf) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - vbuf->put_time; - ErrorF ("vbuf(%d,%d,%d) retbuf : %6ld ms\n", - vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], sub); - } - else if (keys) - ErrorF ("vbuf(%d,%d,%d) retbuf : 0 ms\n", - keys[0], keys[1], keys[2]); - else - XDBG_NEVER_GET_HERE (MVDO); - } -} - -static void -_secVideoCvtCallback (SECCvt *cvt, - SECVideoBuf *src, - SECVideoBuf *dst, - void *cvt_data, - Bool error) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data; - DrawablePtr pDamageDrawable = NULL; - int out_index; - - XDBG_RETURN_IF_FAIL (pPort != NULL); - XDBG_RETURN_IF_FAIL (cvt != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src)); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst)); - XDBG_DEBUG (MVDO, "++++++++++++++++++++++++ \n"); - XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst); - - for (out_index = 0; out_index < OUTBUF_NUM; out_index++) - if (pPort->outbuf[out_index] == dst) - break; - XDBG_RETURN_IF_FAIL (out_index < OUTBUF_NUM); - - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - pDamageDrawable = pPort->pDamageDrawable[out_index]; - else - pDamageDrawable = pPort->d.pDraw; - - XDBG_RETURN_IF_FAIL (pDamageDrawable != NULL); - - if (error) - { - DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes); - return; - } - - SECPtr pSec = SECPTR (pPort->pScrn); - if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info) - { - char file[128]; - static int i; - snprintf (file, sizeof(file), "xvout_p%d_%03d.bmp", pPort->index, i++); - secUtilDoDumpVBuf (pSec->dump_info, dst, file); - } - - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - { - DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes); - } - else if (pPort->layer) - { - SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer); - Bool reset_layer = FALSE; - xRectangle src_rect, dst_rect; - - if (vbuf) - if (vbuf->width != pPort->out_width || vbuf->height != pPort->out_height) - reset_layer = TRUE; - - secLayerGetRect (pPort->layer, &src_rect, &dst_rect); - if (memcmp (&src_rect, &pPort->out_crop, sizeof(xRectangle)) || - dst_rect.x != pPort->d.dst.x || - dst_rect.y != pPort->d.dst.y || - dst_rect.width != pPort->out_crop.width || - dst_rect.height != pPort->out_crop.height) - reset_layer = TRUE; - - if (reset_layer) - { - secLayerFreezeUpdate (pPort->layer, TRUE); - - src_rect = pPort->out_crop; - dst_rect.x = pPort->d.dst.x; - dst_rect.y = pPort->d.dst.y; - dst_rect.width = pPort->out_crop.width; - dst_rect.height = pPort->out_crop.height; - - secLayerSetRect (pPort->layer, &src_rect, &dst_rect); - secLayerFreezeUpdate (pPort->layer, FALSE); - secLayerSetBuffer (pPort->layer, dst); - } - else - secLayerSetBuffer (pPort->layer, dst); - - if (!secLayerIsVisible (pPort->layer)) - secLayerShow (pPort->layer); - } - - XDBG_DEBUG (MVDO, "++++++++++++++++++++++++.. \n"); -} - -static void -_secVideoTvoutCvtCallback (SECCvt *cvt, - SECVideoBuf *src, - SECVideoBuf *dst, - void *cvt_data, - Bool error) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data; - - XDBG_RETURN_IF_FAIL (pPort != NULL); - XDBG_RETURN_IF_FAIL (cvt != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src)); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst)); - - XDBG_DEBUG (MVDO, "######################## \n"); - XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst); - - if (pPort->wait_vbuf != src) - XDBG_WARNING (MVDO, "wait_vbuf(%p) != src(%p). \n", - pPort->wait_vbuf, src); - - pPort->wait_vbuf = NULL; - - XDBG_DEBUG (MVDO, "########################.. \n"); -} - -static void -_secVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)data; - SECVideoBuf *vbuf = (SECVideoBuf*)type_data; - - if (type != LAYER_VBLANK) - return; - - XDBG_RETURN_IF_FAIL (pPort != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf)); - - if (pPort->wait_vbuf != vbuf) - XDBG_WARNING (MVDO, "wait_vbuf(%p) != vbuf(%p). \n", - pPort->wait_vbuf, vbuf); - - XDBG_DEBUG (MVBUF, "now_showing(%p). \n", vbuf); - - pPort->wait_vbuf = NULL; -} - -static void -_secVideoEnsureConverter (SECPortPrivPtr pPort) -{ - if (pPort->cvt) - return; - - pPort->cvt = secCvtCreate (pPort->pScrn, CVT_OP_M2M); - XDBG_RETURN_IF_FAIL (pPort->cvt != NULL); - - secCvtAddCallback (pPort->cvt, _secVideoCvtCallback, pPort); -} - -static void -_secVideoCloseConverter (SECPortPrivPtr pPort) -{ - if (pPort->cvt) - { - secCvtDestroy (pPort->cvt); - pPort->cvt = NULL; - } - - XDBG_TRACE (MVDO, "done. \n"); -} - -static void -_secVideoStreamOff (SECPortPrivPtr pPort) -{ - _secVideoCloseConverter (pPort); - _secVideoCloseInBuffer (pPort); - _secVideoCloseOutBuffer (pPort, TRUE); - - SECWb *wb = secWbGet (); - if (wb) - { - if (pPort->need_start_wb) - { - secWbSetSecure (wb, FALSE); - secWbStart (wb); - pPort->need_start_wb = FALSE; - } - else - secWbSetSecure (wb, FALSE); - } - - if (pPort->d.clip_boxes) - { - RegionDestroy (pPort->d.clip_boxes); - pPort->d.clip_boxes = NULL; - } - - memset (&pPort->old_d, 0, sizeof (PutData)); - memset (&pPort->d, 0, sizeof (PutData)); - - pPort->need_start_wb = FALSE; - pPort->skip_tvout = FALSE; - pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT; - pPort->outbuf_cvting = -1; - pPort->drawing = 0; - pPort->tv_prev_time = 0; - pPort->secure = FALSE; - pPort->csc_range = 0; - pPort->inbuf_is_fb = FALSE; - - if (pPort->stream_cnt > 0) - { - pPort->stream_cnt = 0; - XDBG_SECURE (MVDO, "pPort(%d) stream off. \n", pPort->index); - - if (pPort->preemption > -1) - streaming_ports--; - - XDBG_WARNING_IF_FAIL (streaming_ports >= 0); - } - - XDBG_TRACE (MVDO, "done. \n"); -} - -static Bool -_secVideoCalculateSize (SECPortPrivPtr pPort) -{ - SECCvtProp src_prop = {0,}, dst_prop = {0,}; - - src_prop.id = pPort->d.id; - src_prop.width = pPort->d.width; - src_prop.height = pPort->d.height; - src_prop.crop = pPort->d.src; - - dst_prop.id = FOURCC_RGB32; - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - { - dst_prop.width = pPort->d.pDraw->width; - dst_prop.height = pPort->d.pDraw->height; - dst_prop.crop = pPort->d.dst; - dst_prop.crop.x -= pPort->d.pDraw->x; - dst_prop.crop.y -= pPort->d.pDraw->y; - } - else - { - dst_prop.width = pPort->d.dst.width; - dst_prop.height = pPort->d.dst.height; - dst_prop.crop = pPort->d.dst; - dst_prop.crop.x = 0; - dst_prop.crop.y = 0; - } - - XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n", - src_prop.width, src_prop.height, - src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height, - dst_prop.width, dst_prop.height, - dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height); - - if (!secCvtEnsureSize (&src_prop, &dst_prop)) - return FALSE; - - XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n", - src_prop.width, src_prop.height, - src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height, - dst_prop.width, dst_prop.height, - dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height); - - XDBG_RETURN_VAL_IF_FAIL (src_prop.width > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src_prop.height > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.width > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.height > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_prop.width > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_prop.height > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.width > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.height > 0, FALSE); - - pPort->in_width = src_prop.width; - pPort->in_height = src_prop.height; - pPort->in_crop = src_prop.crop; - - pPort->out_width = dst_prop.width; - pPort->out_height = dst_prop.height; - pPort->out_crop = dst_prop.crop; - - return TRUE; -} - -static void -_secVideoPunchDrawable (SECPortPrivPtr pPort) -{ - PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw); - SECPtr pSec = SECPTR (pPort->pScrn); - - if (pPort->drawing != ON_FB || !pSec->pVideoPriv->video_punch) - return; - - if (!pPort->punched) - { - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - if (pPixmap->devPrivate.ptr) - memset (pPixmap->devPrivate.ptr, 0, - pPixmap->drawable.width * pPixmap->drawable.height * 4); - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_TRACE (MVDO, "Punched (%dx%d) %p. \n", - pPixmap->drawable.width, pPixmap->drawable.height, - pPixmap->devPrivate.ptr); - pPort->punched = TRUE; - DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes); - } -} - -static Bool -_secVideoSupportID (int id) -{ - int i; - - for (i = 0; i < NUM_IMAGES; i++) - if (images[i].id == id) - if (secCvtSupportFormat (CVT_OP_M2M, id)) - return TRUE; - - return FALSE; -} - -static Bool -_secVideoInBranch (WindowPtr p, WindowPtr w) -{ - for (; w; w = w->parent) - if (w == p) - return TRUE; - - return FALSE; -} - -/* Return the child of 'p' which includes 'w'. */ -static WindowPtr -_secVideoGetChild (WindowPtr p, WindowPtr w) -{ - WindowPtr c; - - for (c = w, w = w->parent; w; c = w, w = w->parent) - if (w == p) - return c; - - return NULL; -} - -/* ancestor : Return the parent of 'a' and 'b'. - * ancestor_a : Return the child of 'ancestor' which includes 'a'. - * ancestor_b : Return the child of 'ancestor' which includes 'b'. - */ -static Bool -_secVideoGetAncestors (WindowPtr a, WindowPtr b, - WindowPtr *ancestor, - WindowPtr *ancestor_a, - WindowPtr *ancestor_b) -{ - WindowPtr child_a, child_b; - - if (!ancestor || !ancestor_a || !ancestor_b) - return FALSE; - - for (child_b = b, b = b->parent; b; child_b = b, b = b->parent) - { - child_a = _secVideoGetChild (b, a); - if (child_a) - { - *ancestor = b; - *ancestor_a = child_a; - *ancestor_b = child_b; - return TRUE; - } - } - - return FALSE; -} - -static int -_secVideoCompareWindow (WindowPtr pWin1, WindowPtr pWin2) -{ - WindowPtr a, a1, a2, c; - - if (!pWin1 || !pWin2) - return -2; - - if (pWin1 == pWin2) - return 0; - - if (_secVideoGetChild (pWin1, pWin2)) - return -1; - - if (_secVideoGetChild (pWin2, pWin1)) - return 1; - - if (!_secVideoGetAncestors (pWin1, pWin2, &a, &a1, &a2)) - return -3; - - for (c = a->firstChild; c; c = c->nextSib) - { - if (c == a1) - return 1; - else if (c == a2) - return -1; - } - - return -4; -} - -static void -_secVideoArrangeLayerPos (SECPortPrivPtr pPort, Bool by_notify) -{ - SECPortPrivPtr pCur = NULL, pNext = NULL; - SECPortPrivPtr pAnother = NULL; - int i = 0; - - xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link) - { - if (pCur == pPort) - continue; - - i++; - - if (!pAnother) - pAnother = pCur; - else - XDBG_WARNING (MVDO, "There are 3 more V4L2 ports. (%d) \n", i); - } - - if (!pAnother) - { - SECLayerPos lpos = secLayerGetPos (pPort->layer); - - if (lpos == LAYER_NONE) - secLayerSetPos (pPort->layer, LAYER_LOWER2); - } - else - { - SECLayerPos lpos1 = LAYER_NONE; - SECLayerPos lpos2 = LAYER_NONE; - - if (pAnother->layer) - lpos1 = secLayerGetPos (pAnother->layer); - if (pPort->layer) - lpos2 = secLayerGetPos (pPort->layer); - - if (lpos2 == LAYER_NONE) - { - int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw, - (WindowPtr)pPort->d.pDraw); - - XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n", - _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp); - - if (comp == 1) - { - if (lpos1 != LAYER_LOWER1) - secLayerSetPos (pAnother->layer, LAYER_LOWER1); - secLayerSetPos (pPort->layer, LAYER_LOWER2); - } - else if (comp == -1) - { - if (lpos1 != LAYER_LOWER2) - secLayerSetPos (pAnother->layer, LAYER_LOWER2); - secLayerSetPos (pPort->layer, LAYER_LOWER1); - } - else - { - if (lpos1 == LAYER_LOWER1) - secLayerSetPos (pPort->layer, LAYER_LOWER2); - else - secLayerSetPos (pPort->layer, LAYER_LOWER1); - } - } - else - { - if (!by_notify) - return; - - int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw, - (WindowPtr)pPort->d.pDraw); - - XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n", - _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp); - - if ((comp == 1 && lpos1 != LAYER_LOWER1) || - (comp == -1 && lpos2 != LAYER_LOWER1)) - secLayerSwapPos (pAnother->layer, pPort->layer); - } - } -} - -static void -_secVideoStopTvout (ScrnInfoPtr pScrn) -{ - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0]; - int i; - - for (i = 0; i < SEC_MAX_PORT; i++) - { - SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; - - if (pPort->grab_tvout) - { - _secVideoUngrabTvout (pPort); - return; - } - } -} - -/* TRUE : current frame will be shown on TV. free after vblank. - * FALSE : current frame won't be shown on TV. - */ -static Bool -_secVideoPutImageTvout (SECPortPrivPtr pPort, int output, SECVideoBuf *inbuf) -{ - ScrnInfoPtr pScrn = pPort->pScrn; - SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - xRectangle tv_rect = {0,}; - Bool first_put = FALSE; - - if (!(output & OUTPUT_EXT)) - return FALSE; - - if (pPort->skip_tvout) - return FALSE; - - if (!_secVideoGrabTvout(pPort)) - goto fail_to_put_tvout; - - if (!pPort->tv) - { - SECCvt *tv_cvt; - SECWb *wb; - - if (!secUtilEnsureExternalCrtc (pScrn)) - { - XDBG_ERROR (MVDO, "failed : pPort(%d) connect external crtc\n", pPort->index); - goto fail_to_put_tvout; - } - - pPort->tv = secVideoTvConnect (pScrn, pPort->d.id, LAYER_LOWER1); - XDBG_GOTO_IF_FAIL (pPort->tv != NULL, fail_to_put_tvout); - - wb = secWbGet (); - if (wb) - { - pPort->need_start_wb = TRUE; - - /* in case of VIRTUAL, wb's buffer is used by tvout. */ - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - secWbStop (wb, FALSE); - else - secWbStop (wb, TRUE); - } - - if (secWbIsRunning ()) - { - XDBG_ERROR (MVDO, "failed: wb still running\n"); - goto fail_to_put_tvout; - } - - tv_cvt = secVideoTvGetConverter (pPort->tv); - if (tv_cvt) - { - /* HDMI : SN12 - * VIRTUAL : SN12 or RGB32 - */ - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - if (pSecMode->set_mode == DISPLAY_SET_MODE_CLONE) - { - SECVideoBuf **vbufs = NULL; - int bufnum = 0; - - secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12); - - /* In case of virtual, we draw video on full-size buffer - * for virtual-adaptor - */ - secVideoTvSetSize (pPort->tv, - pSecMode->ext_connector_mode.hdisplay, - pSecMode->ext_connector_mode.vdisplay); - - secVirtualVideoGetBuffers (pPort->pScrn, FOURCC_SN12, - pSecMode->ext_connector_mode.hdisplay, - pSecMode->ext_connector_mode.vdisplay, - &vbufs, &bufnum); - - XDBG_GOTO_IF_FAIL (vbufs != NULL, fail_to_put_tvout); - XDBG_GOTO_IF_FAIL (bufnum > 0, fail_to_put_tvout); - - secVideoTvSetBuffer (pPort->tv, vbufs, bufnum); - } - else /* desktop */ - secVideoTvSetConvertFormat (pPort->tv, FOURCC_RGB32); - } - else - secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12); - - secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort); - } - else - { - SECLayer *layer = secVideoTvGetLayer (pPort->tv); - XDBG_GOTO_IF_FAIL (layer != NULL, fail_to_put_tvout); - - secLayerEnableVBlank (layer, TRUE); - secLayerAddNotifyFunc (layer, _secVideoLayerNotifyFunc, pPort); - } - - first_put = TRUE; - } - - SECPtr pSec = SECPTR (pPort->pScrn); - if (pPort->wait_vbuf) - { - if (pSec->pVideoPriv->video_fps) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - pPort->tv_prev_time; - pPort->tv_prev_time = cur; - - XDBG_DEBUG (MVDO, "tvout skip : sub(%ld) vbuf(%ld:%d,%d,%d) \n", - sub, inbuf->stamp, - inbuf->keys[0], inbuf->keys[1], inbuf->keys[2]); - } - - return FALSE; - } - else if (pSec->pVideoPriv->video_fps) - pPort->tv_prev_time = GetTimeInMillis (); - - if (!(output & OUTPUT_FULL)) - { - tv_rect.x = pPort->d.dst.x - - pSecMode->main_lcd_mode.hdisplay; - tv_rect.y = pPort->d.dst.y; - tv_rect.width = pPort->d.dst.width; - tv_rect.height = pPort->d.dst.height; - } - else - { - secUtilAlignRect (pPort->d.src.width, pPort->d.src.height, - pSecMode->ext_connector_mode.hdisplay, - pSecMode->ext_connector_mode.vdisplay, - &tv_rect, TRUE); - } - - /* if secVideoTvPutImage returns FALSE, it means this frame won't show on TV. */ - if (!secVideoTvPutImage (pPort->tv, inbuf, &tv_rect, pPort->csc_range)) - return FALSE; - - if (first_put && !(output & OUTPUT_LCD)) - _secVideoSetOutputExternalProperty (pPort->d.pDraw, TRUE); - - pPort->wait_vbuf = inbuf; - - return TRUE; - -fail_to_put_tvout: - _secVideoUngrabTvout (pPort); - - pPort->skip_tvout = TRUE; - - XDBG_TRACE (MVDO, "pPort(%d) skip tvout \n", pPort->index); - - return FALSE; -} - -static Bool -_secVideoPutImageInbuf (SECPortPrivPtr pPort, SECVideoBuf *inbuf) -{ - if (!pPort->layer) - { - pPort->layer = _secVideoCreateLayer (pPort); - XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE); - - _secVideoArrangeLayerPos (pPort, FALSE); - } - - secLayerSetBuffer (pPort->layer, inbuf); - - if (!secLayerIsVisible (pPort->layer)) - secLayerShow (pPort->layer); - - return TRUE; -} - -static Bool -_secVideoPutImageInternal (SECPortPrivPtr pPort, SECVideoBuf *inbuf) -{ - SECPtr pSec = (SECPtr) pPort->pScrn->driverPrivate; - SECCvtProp src_prop = {0,}, dst_prop = {0,}; - SECVideoBuf *outbuf = NULL; - - outbuf = _secVideoGetOutbuf (pPort); - if (!outbuf) - return FALSE; - - /* cacheflush here becasue dst buffer can be created in _secVideoGetOutbuf() */ - if (pPort->stream_cnt == 1) - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - secUtilCacheFlush (pPort->pScrn); - - XDBG_DEBUG (MVDO, "'%c%c%c%c' preem(%d) rot(%d) \n", - FOURCC_STR (pPort->d.id), - pPort->preemption, pPort->hw_rotate); - - if (pPort->layer) - _secVideoArrangeLayerPos (pPort, FALSE); - - _secVideoEnsureConverter (pPort); - XDBG_GOTO_IF_FAIL (pPort->cvt != NULL, fail_to_put); - - src_prop.id = pPort->d.id; - src_prop.width = pPort->in_width; - src_prop.height = pPort->in_height; - src_prop.crop = pPort->in_crop; - - dst_prop.id = FOURCC_RGB32; - dst_prop.width = pPort->out_width; - dst_prop.height = pPort->out_height; - dst_prop.crop = pPort->out_crop; - - dst_prop.degree = pPort->hw_rotate; - dst_prop.hflip = pPort->hflip; - dst_prop.vflip = pPort->vflip; - dst_prop.secure = pPort->secure; - dst_prop.csc_range = pPort->csc_range; - - if (!secCvtEnsureSize (&src_prop, &dst_prop)) - goto fail_to_put; - - if (!secCvtSetProperpty (pPort->cvt, &src_prop, &dst_prop)) - goto fail_to_put; - - if (!secCvtConvert (pPort->cvt, inbuf, outbuf)) - goto fail_to_put; - - if (pSec->pVideoPriv->video_fps) - _countFps (pPort); - - secUtilVideoBufferUnref (outbuf); - - return TRUE; - -fail_to_put: - if (outbuf) - secUtilVideoBufferUnref (outbuf); - - _secVideoCloseConverter (pPort); - _secVideoCloseOutBuffer (pPort, TRUE); - - return FALSE; -} - -static Bool -_secVideoSetHWPortsProperty (ScreenPtr pScreen, int nums) -{ - WindowPtr pWin = pScreen->root; - Atom atom_hw_ports; - - /* With "X_HW_PORTS", an application can know - * how many fimc devices XV uses. - */ - if (!pWin || !serverClient) - return FALSE; - - atom_hw_ports = MakeAtom ("XV_HW_PORTS", strlen ("XV_HW_PORTS"), TRUE); - - dixChangeWindowProperty (serverClient, - pWin, atom_hw_ports, XA_CARDINAL, 32, - PropModeReplace, 1, (unsigned int*)&nums, FALSE); - - return TRUE; -} - -static Bool -_secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool video_only) -{ - WindowPtr pWin; - Atom atom_external; - - XDBG_RETURN_VAL_IF_FAIL (pDraw != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_WINDOW, FALSE); - - pWin = (WindowPtr)pDraw; - - atom_external = MakeAtom ("XV_OUTPUT_EXTERNAL", strlen ("XV_OUTPUT_EXTERNAL"), TRUE); - - dixChangeWindowProperty (clients[CLIENT_ID(pDraw->id)], - pWin, atom_external, XA_CARDINAL, 32, - PropModeReplace, 1, (unsigned int*)&video_only, TRUE); - - XDBG_TRACE (MVDO, "pDraw(0x%08x) video-only(%s)\n", - pDraw->id, (video_only)?"ON":"OFF"); - - return TRUE; -} - -static void -_secVideoRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib) -{ - ScreenPtr pScreen = ((DrawablePtr)pWin)->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - SECVideoPrivPtr pVideo = pSec->pVideoPriv; - - if (pVideo->RestackWindow) - { - pScreen->RestackWindow = pVideo->RestackWindow; - - if (pScreen->RestackWindow) - (*pScreen->RestackWindow)(pWin, pOldNextSib); - - pVideo->RestackWindow = pScreen->RestackWindow; - pScreen->RestackWindow = _secVideoRestackWindow; - } - - if (!xorg_list_is_empty (&layer_owners)) - { - SECPortPrivPtr pCur = NULL, pNext = NULL; - xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link) - { - if (_secVideoInBranch (pWin, (WindowPtr)pCur->d.pDraw)) - { - XDBG_TRACE (MVDO, "Do re-arrange. 0x%08x(0x%08x) \n", - _XID(pWin), _XID(pCur->d.pDraw)); - _secVideoArrangeLayerPos (pCur, TRUE); - break; - } - } - } -} - -static void -_secVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead) -{ - ScreenPtr pScreen = ((ScrnInfoPtr)data)->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - SECVideoPrivPtr pVideo = pSec->pVideoPriv; - - pVideo->RestackWindow = pScreen->RestackWindow; - pScreen->RestackWindow = _secVideoRestackWindow; - - if(registered_handler && _secVideoSetHWPortsProperty (pScreen, NUM_HW_LAYER)) - { - RemoveBlockAndWakeupHandlers(_secVideoBlockHandler, - (WakeupHandlerProcPtr)NoopDDA, data); - registered_handler = FALSE; - } -} - -static Bool -_secVideoAddDrawableEvent (SECPortPrivPtr pPort) -{ - SECVideoResource *resource; - void *ptr=NULL; - int ret; - - ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id, - event_drawable_type, NULL, DixWriteAccess); - if (ret == Success) - { - return TRUE; - } - - resource = malloc (sizeof (SECVideoResource)); - if (resource == NULL) - return FALSE; - - if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource)) - { - free (resource); - return FALSE; - } - - XDBG_TRACE (MVDO, "id(0x%08lx). \n", pPort->d.pDraw->id); - - resource->id = pPort->d.pDraw->id; - resource->type = event_drawable_type; - resource->pPort = pPort; - resource->pScrn = pPort->pScrn; - - return TRUE; -} - -static int -_secVideoRegisterEventDrawableGone (void *data, XID id) -{ - SECVideoResource *resource = (SECVideoResource*)data; - - XDBG_TRACE (MVDO, "id(0x%08lx). \n", id); - - if (!resource) - return Success; - - if (!resource->pPort || !resource->pScrn) - return Success; - - SECVideoStop (resource->pScrn, (pointer)resource->pPort, 1); - - free(resource); - - return Success; -} - -static Bool -_secVideoRegisterEventResourceTypes (void) -{ - event_drawable_type = CreateNewResourceType (_secVideoRegisterEventDrawableGone, "Sec Video Drawable"); - - if (!event_drawable_type) - return FALSE; - - return TRUE; -} - -int -secVideoQueryImageAttrs (ScrnInfoPtr pScrn, - int id, - int *w, - int *h, - int *pitches, - int *offsets, - int *lengths) -{ - int size = 0, tmp = 0; - - *w = (*w + 1) & ~1; - if (offsets) - offsets[0] = 0; - - switch (id) - { - /* RGB565 */ - case FOURCC_SR16: - case FOURCC_RGB565: - size += (*w << 1); - if (pitches) - pitches[0] = size; - size *= *h; - if (lengths) - lengths[0] = size; - break; - /* RGB32 */ - case FOURCC_SR32: - case FOURCC_RGB32: - size += (*w << 2); - if (pitches) - pitches[0] = size; - size *= *h; - if (lengths) - lengths[0] = size; - break; - /* YUV420, 3 planar */ - case FOURCC_I420: - case FOURCC_S420: - case FOURCC_YV12: - *h = (*h + 1) & ~1; - size = (*w + 3) & ~3; - if (pitches) - pitches[0] = size; - - size *= *h; - if (offsets) - offsets[1] = size; - if (lengths) - lengths[0] = size; - - tmp = ((*w >> 1) + 3) & ~3; - if (pitches) - pitches[1] = pitches[2] = tmp; - - tmp *= (*h >> 1); - size += tmp; - if (offsets) - offsets[2] = size; - if (lengths) - lengths[1] = tmp; - - size += tmp; - if (lengths) - lengths[2] = tmp; - - break; - /* YUV422, packed */ - case FOURCC_UYVY: - case FOURCC_SYVY: - case FOURCC_ITLV: - case FOURCC_SUYV: - case FOURCC_YUY2: - size = *w << 1; - if (pitches) - pitches[0] = size; - - size *= *h; - if (lengths) - lengths[0] = size; - break; - - /* YUV420, 2 planar */ - case FOURCC_SN12: - case FOURCC_NV12: - case FOURCC_SN21: - case FOURCC_NV21: - if (pitches) - pitches[0] = *w; - - size = (*w) * (*h); - if (offsets) - offsets[1] = size; - if (lengths) - lengths[0] = size; - - if (pitches) - pitches[1] = *w >> 1; - - tmp = (*w) * (*h >> 1); - size += tmp; - if (lengths) - lengths[1] = tmp; - break; - - /* YUV420, 2 planar, tiled */ - case FOURCC_ST12: - if (pitches) - pitches[0] = *w; - - size = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h)); - if (offsets) - offsets[1] = size; - if (lengths) - lengths[0] = size; - - if (pitches) - pitches[1] = *w >> 1; - - tmp = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h >> 1)); - size += tmp; - if (lengths) - lengths[1] = tmp; - break; - default: - return 0; - } - - return size; -} - -static int -SECVideoGetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 *value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _portAtom (PAA_ROTATION)) - { - *value = pPort->rotate; - return Success; - } - else if (attribute == _portAtom (PAA_HFLIP)) - { - *value = pPort->hflip; - return Success; - } - else if (attribute == _portAtom (PAA_VFLIP)) - { - *value = pPort->vflip; - return Success; - } - else if (attribute == _portAtom (PAA_PREEMPTION)) - { - *value = pPort->preemption; - return Success; - } - else if (attribute == _portAtom (PAA_OUTPUT)) - { - *value = pPort->usr_output; - return Success; - } - else if (attribute == _portAtom (PAA_SECURE)) - { - *value = pPort->secure; - return Success; - } - else if (attribute == _portAtom (PAA_CSC_RANGE)) - { - *value = pPort->csc_range; - return Success; - } - - return BadMatch; -} - -static int -SECVideoSetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _portAtom (PAA_ROTATION)) - { - pPort->rotate = value; - XDBG_DEBUG (MVDO, "rotate(%d) \n", value); - return Success; - } - else if (attribute == _portAtom (PAA_HFLIP)) - { - pPort->hflip = value; - XDBG_DEBUG (MVDO, "hflip(%d) \n", value); - return Success; - } - else if (attribute == _portAtom (PAA_VFLIP)) - { - pPort->vflip = value; - XDBG_DEBUG (MVDO, "vflip(%d) \n", value); - return Success; - } - else if (attribute == _portAtom (PAA_PREEMPTION)) - { - pPort->preemption = value; - XDBG_DEBUG (MVDO, "preemption(%d) \n", value); - return Success; - } - else if (attribute == _portAtom (PAA_OUTPUT)) - { - if (value == OUTPUT_MODE_TVOUT) - pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL; - else if (value == OUTPUT_MODE_EXT_ONLY) - pPort->usr_output = OUTPUT_EXT|OUTPUT_FULL; - else - pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT; - - XDBG_DEBUG (MVDO, "output (%d) \n", value); - - return Success; - } - else if (attribute == _portAtom (PAA_SECURE)) - { - pPort->secure = value; - XDBG_DEBUG (MVDO, "secure(%d) \n", value); - return Success; - } - else if (attribute == _portAtom (PAA_CSC_RANGE)) - { - pPort->csc_range = value; - XDBG_DEBUG (MVDO, "csc_range(%d) \n", value); - return Success; - } - - return Success; -} - -static void -SECVideoQueryBestSize (ScrnInfoPtr pScrn, - Bool motion, - short vid_w, short vid_h, - short dst_w, short dst_h, - uint *p_w, uint *p_h, - pointer data) -{ - SECCvtProp prop = {0,}; - - if (!p_w && !p_h) - return; - - prop.width = dst_w; - prop.height = dst_h; - prop.crop.width = dst_w; - prop.crop.height = dst_h; - - if (secCvtEnsureSize (NULL, &prop)) - { - if (p_w) - *p_w = prop.width; - if (p_h) - *p_h = prop.height; - } - else - { - if (p_w) - *p_w = dst_w; - if (p_h) - *p_h = dst_h; - } -} - -/** - * Give image size and pitches. - */ -static int -SECVideoQueryImageAttributes (ScrnInfoPtr pScrn, - int id, - unsigned short *w, - unsigned short *h, - int *pitches, - int *offsets) -{ - int width, height, size; - - if (!w || !h) - return 0; - - width = (int)*w; - height = (int)*h; - - size = secVideoQueryImageAttrs (pScrn, id, &width, &height, pitches, offsets, NULL); - - *w = (unsigned short)width; - *h = (unsigned short)height; - - return size; -} - -/* coordinates : HW, SCREEN, PORT - * BadRequest : when video can't be shown or drawn. - * Success : A damage event(pixmap) and inbuf should be return. - * If can't return a damage event and inbuf, should be return - * BadRequest. - */ -static int -SECVideoPutImage (ScrnInfoPtr pScrn, - short src_x, short src_y, short dst_x, short dst_y, - short src_w, short src_h, short dst_w, short dst_h, - int id, uchar *buf, short width, short height, - Bool sync, RegionPtr clip_boxes, pointer data, - DrawablePtr pDraw) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode; - SECVideoPrivPtr pVideo = SECPTR (pScrn)->pVideoPriv; - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - int output, ret; - Bool tvout = FALSE, lcdout = FALSE; - SECVideoBuf *inbuf = NULL; - int old_drawing; - - if (!_secVideoSupportID (id)) - { - XDBG_ERROR (MVDO, "'%c%c%c%c' not supported.\n", FOURCC_STR (id)); - return BadRequest; - } - - XDBG_TRACE (MVDO, "======================================= \n"); - - pPort->pScrn = pScrn; - pPort->d.id = id; - pPort->d.buf = buf; - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA) - { - unsigned int keys[PLANAR_CNT] = {0,}; - CARD32 cur, sub; - char temp[64]; - cur = GetTimeInMillis (); - sub = cur - pPort->prev_time; - pPort->prev_time = cur; - temp[0] = '\0'; - if (IS_ZEROCOPY (id)) - { - _secVideoGetKeys (pPort, keys, NULL); - snprintf (temp, sizeof(temp), "%d,%d,%d", keys[0], keys[1], keys[2]); - } - ErrorF ("pPort(%p) put interval(%s) : %6ld ms\n", pPort, temp, sub); - } - - if (IS_ZEROCOPY (pPort->d.id)) - { - unsigned int keys[PLANAR_CNT] = {0,}; - int i; - - if (_secVideoGetKeys (pPort, keys, NULL)) - return BadRequest; - - for (i = 0; i < INBUF_NUM; i++) - if (pPort->inbuf[i] && pPort->inbuf[i]->keys[0] == keys[0]) - { - XDBG_WARNING (MVDO, "got flink_id(%d) twice!\n", keys[0]); - _secVideoSendReturnBufferMessage (pPort, NULL, keys); - return Success; - } - } - - pPort->d.width = width; - pPort->d.height = height; - pPort->d.src.x = src_x; - pPort->d.src.y = src_y; - pPort->d.src.width = src_w; - pPort->d.src.height = src_h; - pPort->d.dst.x = dst_x; /* included pDraw'x */ - pPort->d.dst.y = dst_y; /* included pDraw'y */ - pPort->d.dst.width = dst_w; - pPort->d.dst.height = dst_h; - pPort->d.sync = FALSE; - if (sync) - XDBG_WARNING (MVDO, "not support sync.\n"); - pPort->d.data = data; - pPort->d.pDraw = pDraw; - if (clip_boxes) - { - if (!pPort->d.clip_boxes) - pPort->d.clip_boxes = RegionCreate(NullBox, 0); - RegionCopy (pPort->d.clip_boxes, clip_boxes); - } - - old_drawing = pPort->drawing; - pPort->drawing = _secVideodrawingOn (pPort); - if (old_drawing != pPort->drawing) - { - _secVideoCloseConverter (pPort); - _secVideoCloseOutBuffer (pPort, TRUE); - } - - _secVideoGetRotation (pPort, &pPort->hw_rotate); - - if (pPort->drawing == ON_FB && pVideo->screen_rotate_degree > 0) - secUtilRotateRect (pSecMode->main_lcd_mode.hdisplay, - pSecMode->main_lcd_mode.vdisplay, - &pPort->d.dst, - pVideo->screen_rotate_degree); - - if (pPort->secure) - if (pPort->drawing != ON_FB) - { - XDBG_ERROR (MVDO, "secure video should drawn on FB.\n"); - return BadRequest; - } - - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - if (!_secVideoAddDrawableEvent (pPort)) - return BadRequest; - - if (pPort->stream_cnt == 0) - { - pPort->stream_cnt++; - - if (pPort->preemption > -1) - streaming_ports++; - - XDBG_SECURE (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n", - pPort->index, streaming_ports, - pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range, - pPort->usr_output, drawing_type[pPort->drawing]); - XDBG_SECURE (MVDO, "id(%c%c%c%c) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n", - FOURCC_STR (id), width, height, - src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); - - if (streaming_ports > 1) - _secVideoStopTvout (pPort->pScrn); - } - else if (pPort->stream_cnt == 1) - pPort->stream_cnt++; - - if (pPort->cvt) - { - SECCvtProp dst_prop; - - secCvtGetProperpty (pPort->cvt, NULL, &dst_prop); - - if (pPort->d.id != pPort->old_d.id || - pPort->d.width != pPort->old_d.width || - pPort->d.height != pPort->old_d.height || - memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)) || - dst_prop.degree != pPort->hw_rotate || - dst_prop.hflip != pPort->hflip || - dst_prop.vflip != pPort->vflip || - dst_prop.secure != pPort->secure || - dst_prop.csc_range != pPort->csc_range) - { - XDBG_DEBUG (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n", - pPort->index, streaming_ports, - pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range, - pPort->usr_output, drawing_type[pPort->drawing]); - XDBG_DEBUG (MVDO, "pPort(%d) old_src(%dx%d %d,%d %dx%d) : new_src(%dx%d %d,%d %dx%d)\n", - pPort->index, pPort->old_d.width, pPort->old_d.height, - pPort->old_d.src.x, pPort->old_d.src.y, - pPort->old_d.src.width, pPort->old_d.src.height, - pPort->d.width, pPort->d.height, - pPort->d.src.x, pPort->d.src.y, - pPort->d.src.width, pPort->d.src.height); - _secVideoCloseConverter (pPort); - _secVideoCloseInBuffer (pPort); - pPort->inbuf_is_fb = FALSE; - } - } - - if (memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle))) - { - XDBG_DEBUG (MVDO, "pPort(%d) old_dst(%d,%d %dx%d) : new_dst(%dx%d %dx%d)\n", - pPort->index, - pPort->old_d.dst.x, pPort->old_d.dst.y, - pPort->old_d.dst.width, pPort->old_d.dst.height, - pPort->d.dst.x, pPort->d.dst.y, - pPort->d.dst.width, pPort->d.dst.height); - _secVideoCloseConverter (pPort); - _secVideoCloseOutBuffer (pPort, FALSE); - pPort->inbuf_is_fb = FALSE; - } - - if (!_secVideoCalculateSize (pPort)) - return BadRequest; - - output = _secVideoGetTvoutMode (pPort); - if (!(output & OUTPUT_LCD) && pPort->old_output & OUTPUT_LCD) - { - /* If the video of LCD becomes off, we also turn off LCD layer. */ - if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW) - { - PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw); - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap); - - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - if (pPixmap->devPrivate.ptr && privPixmap->size > 0) - memset (pPixmap->devPrivate.ptr, 0, privPixmap->size); - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes); - } - else - { - _secVideoCloseConverter (pPort); - _secVideoCloseOutBuffer (pPort, TRUE); - } - } - - if (pPort->d.id == FOURCC_SR32 && - pPort->in_crop.width == pPort->out_crop.width && - pPort->in_crop.height == pPort->out_crop.height && - pPort->hw_rotate == 0) - pPort->inbuf_is_fb = TRUE; - else - pPort->inbuf_is_fb = FALSE; - - inbuf = _secVideoGetInbuf (pPort); - if (!inbuf) - return BadRequest; - - /* punch here not only LCD but also HDMI. */ - if (pPort->drawing == ON_FB) - _secVideoPunchDrawable (pPort); - - /* HDMI */ - if (output & OUTPUT_EXT) - tvout = _secVideoPutImageTvout (pPort, output, inbuf); - else - { - _secVideoUngrabTvout (pPort); - - SECWb *wb = secWbGet (); - if (wb) - secWbSetSecure (wb, pPort->secure); - } - - /* LCD */ - if (output & OUTPUT_LCD) - { - SECPtr pSec = SECPTR (pScrn); - - if (pSec->isLcdOff) - XDBG_TRACE (MVDO, "port(%d) put image after dpms off.\n", pPort->index); - else if (pPort->inbuf_is_fb) - lcdout = _secVideoPutImageInbuf (pPort, inbuf); - else - lcdout = _secVideoPutImageInternal (pPort, inbuf); - } - - if (lcdout || tvout) - { - ret = Success; - } - else - { - if (IS_ZEROCOPY (pPort->d.id)) - { - int i; - - for (i = 0; i < INBUF_NUM; i++) - if (pPort->inbuf[i] == inbuf) - { - pPort->inbuf[i] = NULL; - secUtilRemoveFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort); - break; - } - XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 1); - } - else - XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 2); - - ret = BadRequest; - } - - /* decrease ref_cnt here to pass ownership of inbuf to converter or tvout. - * in case of zero-copy, it will be really freed - * when converting is finished or tvout is finished. - */ - secUtilVideoBufferUnref (inbuf); - - pPort->old_d = pPort->d; - pPort->old_output = output; - - XDBG_TRACE (MVDO, "=======================================.. \n"); - - return ret; -} - -static int -SECVideoDDPutImage (ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 src_x, INT16 src_y, - CARD16 src_w, CARD16 src_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h, - XvImagePtr format, - unsigned char *data, Bool sync, CARD16 width, CARD16 height) -{ - SECVideoPortInfo *info = _port_info (pDraw); - int ret; - - if (info) - { - info->client = client; - info->pp = pPort; - } - - ret = ddPutImage (client, pDraw, pPort, pGC, - src_x, src_y, src_w, src_h, - drw_x, drw_y, drw_w, drw_h, - format, data, sync, width, height); - - return ret; -} - -static void -SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (!exit) - return; - - XDBG_DEBUG (MVDO, "exit (%d) \n", exit); - - _secVideoStreamOff (pPort); - - pPort->preemption = 0; - pPort->rotate = 0; - pPort->hflip = 0; - pPort->vflip = 0; - pPort->punched = FALSE; -} - -/** - * Set up all our internal structures. - */ -static XF86VideoAdaptorPtr -secVideoSetupImageVideo (ScreenPtr pScreen) -{ - XF86VideoAdaptorPtr pAdaptor; - SECPortPrivPtr pPort; - int i; - - pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) + - (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT); - if (!pAdaptor) - return NULL; - - dummy_encoding[0].width = pScreen->width; - dummy_encoding[0].height = pScreen->height; - - pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask; - pAdaptor->flags = VIDEO_OVERLAID_IMAGES; - pAdaptor->name = "SEC supporting Software Video Conversions"; - pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec); - pAdaptor->pEncodings = dummy_encoding; - pAdaptor->nFormats = NUM_FORMATS; - pAdaptor->pFormats = formats; - pAdaptor->nPorts = SEC_MAX_PORT; - pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]); - - pPort = - (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]); - - for (i = 0; i < SEC_MAX_PORT; i++) - { - pAdaptor->pPortPrivates[i].ptr = &pPort[i]; - pPort[i].index = i; - pPort[i].usr_output = OUTPUT_LCD|OUTPUT_EXT; - pPort[i].outbuf_cvting = -1; - } - - pAdaptor->nAttributes = NUM_ATTRIBUTES; - pAdaptor->pAttributes = attributes; - pAdaptor->nImages = NUM_IMAGES; - pAdaptor->pImages = images; - - pAdaptor->GetPortAttribute = SECVideoGetPortAttribute; - pAdaptor->SetPortAttribute = SECVideoSetPortAttribute; - pAdaptor->QueryBestSize = SECVideoQueryBestSize; - pAdaptor->QueryImageAttributes = SECVideoQueryImageAttributes; - pAdaptor->PutImage = SECVideoPutImage; - pAdaptor->StopVideo = SECVideoStop; - - if (!_secVideoRegisterEventResourceTypes ()) - { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n"); - return FALSE; - } - - return pAdaptor; -} - -static void -SECVideoReplacePutImageFunc (ScreenPtr pScreen) -{ - int i; - - XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates, - XvGetScreenKey()); - if (!xvsp) - return; - - for (i = 0; i < xvsp->nAdaptors; i++) - { - XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; - if (pAdapt->ddPutImage) - { - ddPutImage = pAdapt->ddPutImage; - pAdapt->ddPutImage = SECVideoDDPutImage; - break; - } - } - - if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo))) - return; - if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo))) - return; -} - -#ifdef XV -/** - * Set up everything we need for Xv. - */ -Bool secVideoInit (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - SECVideoPrivPtr pVideo; - - pVideo = (SECVideoPrivPtr)calloc (sizeof (SECVideoPriv), 1); - if (!pVideo) - return FALSE; - - pVideo->pAdaptor[0] = secVideoSetupImageVideo (pScreen); - if (!pVideo->pAdaptor[0]) - { - free (pVideo); - return FALSE; - } - - pVideo->pAdaptor[1] = secVideoSetupVirtualVideo (pScreen); - if (!pVideo->pAdaptor[1]) - { - free (pVideo->pAdaptor[0]); - free (pVideo); - return FALSE; - } - - pVideo->pAdaptor[2] = secVideoSetupDisplayVideo (pScreen); - if (!pVideo->pAdaptor[2]) - { - free (pVideo->pAdaptor[1]); - free (pVideo->pAdaptor[0]); - free (pVideo); - return FALSE; - } - - xf86XVScreenInit (pScreen, pVideo->pAdaptor, ADAPTOR_NUM); - - SECVideoReplacePutImageFunc (pScreen); - secVirtualVideoReplacePutStillFunc (pScreen); - - if(registered_handler == FALSE) - { - RegisterBlockAndWakeupHandlers(_secVideoBlockHandler, - (WakeupHandlerProcPtr)NoopDDA, pScrn); - registered_handler = TRUE; - } - - pSec->pVideoPriv = pVideo; - xorg_list_init (&layer_owners); - - return TRUE; -} - -/** - * Shut down Xv, used on regeneration. - */ -void secVideoFini (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - SECVideoPrivPtr pVideo = pSec->pVideoPriv; - SECPortPrivPtr pCur = NULL, pNext = NULL; - int i; - - xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link) - { - if (pCur->tv) - { - secVideoTvDisconnect (pCur->tv); - pCur->tv = NULL; - } - - if (pCur->d.clip_boxes) - { - RegionDestroy (pCur->d.clip_boxes); - pCur->d.clip_boxes = NULL; - } - } - - for (i = 0; i < ADAPTOR_NUM; i++) - if (pVideo->pAdaptor[i]) - free (pVideo->pAdaptor[i]); - - free (pVideo); - pSec->pVideoPriv= NULL; -} - -#endif - -void -secVideoDpms (ScrnInfoPtr pScrn, Bool on) -{ - if (!on) - { - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0]; - int i; - - for (i = 0; i < SEC_MAX_PORT; i++) - { - SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; - if (pPort->stream_cnt == 0) - continue; - XDBG_TRACE (MVDO, "port(%d) cvt stop.\n", pPort->index); - _secVideoCloseConverter (pPort); - _secVideoCloseInBuffer (pPort); - } - } -} - -void -secVideoScreenRotate (ScrnInfoPtr pScrn, int degree) -{ - SECPtr pSec = SECPTR(pScrn); - SECVideoPrivPtr pVideo = pSec->pVideoPriv; - int old_degree; - - if (pVideo->screen_rotate_degree == degree) - return; - - old_degree = pVideo->screen_rotate_degree; - pVideo->screen_rotate_degree = degree; - XDBG_DEBUG (MVDO, "screen rotate degree: %d\n", degree); - - if (pSec->isLcdOff) - return; - - SECPortPrivPtr pCur = NULL, pNext = NULL; - xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link) - { - SECModePtr pSecMode = pSec->pSecMode; - SECVideoBuf *old_vbuf, *rot_vbuf; - xRectangle rot_rect, dst_rect; - int rot_width, rot_height; - int scn_width, scn_height; - int degree_diff = degree - old_degree; - - if (!pCur->layer) - continue; - - old_vbuf = secLayerGetBuffer (pCur->layer); - XDBG_RETURN_IF_FAIL (old_vbuf != NULL); - - rot_width = old_vbuf->width; - rot_height = old_vbuf->height; - rot_rect = old_vbuf->crop; - secUtilRotateArea (&rot_width, &rot_height, &rot_rect, degree_diff); - - rot_vbuf = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32, rot_width, rot_height, - (pSec->scanout)?TRUE:FALSE, FALSE, pCur->secure); - XDBG_RETURN_IF_FAIL (rot_vbuf != NULL); - rot_vbuf->crop = rot_rect; - - secUtilConvertBos (pScrn, - old_vbuf->bo[0], old_vbuf->width, old_vbuf->height, &old_vbuf->crop, old_vbuf->width*4, - rot_vbuf->bo[0], rot_vbuf->width, rot_vbuf->height, &rot_vbuf->crop, rot_vbuf->width*4, - FALSE, degree_diff); - - tbm_bo_map (rot_vbuf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ); - tbm_bo_unmap (rot_vbuf->bo[0]); - - secLayerGetRect (pCur->layer, NULL, &dst_rect); - - scn_width = (old_degree % 180)?pSecMode->main_lcd_mode.vdisplay:pSecMode->main_lcd_mode.hdisplay; - scn_height = (old_degree % 180)?pSecMode->main_lcd_mode.hdisplay:pSecMode->main_lcd_mode.vdisplay; - - secUtilRotateRect (scn_width, scn_height, &dst_rect, degree_diff); - - secLayerFreezeUpdate (pCur->layer, TRUE); - secLayerSetRect (pCur->layer, &rot_vbuf->crop, &dst_rect); - secLayerFreezeUpdate (pCur->layer, FALSE); - secLayerSetBuffer (pCur->layer, rot_vbuf); - - secUtilVideoBufferUnref (rot_vbuf); - - _secVideoCloseConverter (pCur); - } -} - -void -secVideoSwapLayers (ScreenPtr pScreen) -{ - SECPortPrivPtr pCur = NULL, pNext = NULL; - SECPortPrivPtr pPort1 = NULL, pPort2 = NULL; - - xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link) - { - if (!pPort1) - pPort1 = pCur; - else if (!pPort2) - pPort2 = pCur; - } - - if (pPort1 && pPort2) - { - secLayerSwapPos (pPort1->layer, pPort2->layer); - XDBG_TRACE (MVDO, "%p : %p \n", pPort1->layer, pPort2->layer); - } -} - -Bool -secVideoIsSecureMode (ScrnInfoPtr pScrn) -{ - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0]; - int i; - - for (i = 0; i < SEC_MAX_PORT; i++) - { - SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; - if (pPort->secure) - { - XDBG_TRACE (MVDO, "pPort(%d) is secure.\n", pPort->index); - return TRUE; - } - } - - XDBG_TRACE (MVDO, "no secure port.\n"); - - return FALSE; -} diff --git a/src/xv/sec_video_display.c b/src/xv/sec_video_display.c deleted file mode 100644 index e1f50c8..0000000 --- a/src/xv/sec_video_display.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * xserver-xorg-video-exynos - * - * Copyright 2004 Keith Packard - * Copyright 2005 Eric Anholt - * Copyright 2006 Nokia Corporation - * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - * - * Contact: Boram Park <boram1288.park@samsung.com> - * - * Permission to use, copy, modify, distribute and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the names of the authors and/or copyright holders - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. The authors and - * copyright holders make no representations about the suitability of this - * software for any purpose. It is provided "as is" without any express - * or implied warranty. - * - * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <string.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/ioctl.h> - -#include <pixman.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> -#include <fourcc.h> - -#include <xf86xv.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_video_display.h" -#include "sec_video_fourcc.h" -#include "sec_layer.h" - -#include "fimg2d.h" - -#define SEC_MAX_PORT 1 -#define LAYER_BUF_CNT 3 - -static XF86VideoEncodingRec dummy_encoding[] = -{ - { 0, "XV_IMAGE", -1, -1, { 1, 1 } }, - { 1, "XV_IMAGE", 4224, 4224, { 1, 1 } }, -}; - -static XF86VideoFormatRec formats[] = -{ - { 16, TrueColor }, - { 24, TrueColor }, - { 32, TrueColor }, -}; - -static XF86AttributeRec attributes[] = -{ - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_OVERLAY" }, -}; - -typedef enum -{ - PAA_MIN, - PAA_OVERLAY, - PAA_MAX -} SECPortAttrAtom; - -static struct -{ - SECPortAttrAtom paa; - const char *name; - Atom atom; -} atoms[] = -{ - { PAA_OVERLAY, "_USER_WM_PORT_ATTRIBUTE_OVERLAY", None }, -}; - -typedef struct _GetData -{ - int width; - int height; - xRectangle src; - xRectangle dst; - DrawablePtr pDraw; -} GetData; - -/* SEC port information structure */ -typedef struct -{ - int index; - - /* attributes */ - Bool overlay; - - ScrnInfoPtr pScrn; - GetData d; - GetData old_d; - - /* layer */ - SECLayer *layer; - SECVideoBuf *outbuf[LAYER_BUF_CNT]; - - int stream_cnt; - struct xorg_list link; -} SECPortPriv, *SECPortPrivPtr; - -static RESTYPE event_drawable_type; - -typedef struct _SECDisplayVideoResource -{ - XID id; - RESTYPE type; - - SECPortPrivPtr pPort; - ScrnInfoPtr pScrn; -} SECDisplayVideoResource; - -static void _secDisplayVideoCloseBuffers (SECPortPrivPtr pPort); -static void SECDisplayVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit); - -#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) -#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) -#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) - -static PixmapPtr -_getPixmap (DrawablePtr pDraw) -{ - if (pDraw->type == DRAWABLE_WINDOW) - return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); - else - return (PixmapPtr) pDraw; -} - -static Atom -_portAtom (SECPortAttrAtom paa) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None); - - for (i = 0; i < NUM_ATOMS; i++) - { - if (paa == atoms[i].paa) - { - if (atoms[i].atom == None) - atoms[i].atom = MakeAtom (atoms[i].name, - strlen (atoms[i].name), TRUE); - - return atoms[i].atom; - } - } - - XDBG_ERROR (MDA, "Error: Unknown Port Attribute Name!\n"); - - return None; -} - -static void -_copyBuffer (DrawablePtr pDraw, SECVideoBuf *vbuf) -{ - PixmapPtr pPixmap = (PixmapPtr)_getPixmap (pDraw); - SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap); - Bool need_finish = FALSE; - tbm_bo_handle bo_handle_src, bo_handle_dst; - G2dImage *src_image = NULL, *dst_image = NULL; - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, done_copy_buf); - } - - bo_handle_src = tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_DEFAULT); - XDBG_GOTO_IF_FAIL (bo_handle_src.u32 > 0, done_copy_buf); - - bo_handle_dst = tbm_bo_get_handle (vbuf->bo[0], TBM_DEVICE_DEFAULT); - XDBG_GOTO_IF_FAIL (bo_handle_dst.u32 > 0, done_copy_buf); - - src_image = g2d_image_create_bo2 (G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB, - (unsigned int)pDraw->width, - (unsigned int)pDraw->height, - (unsigned int)bo_handle_src.u32, - (unsigned int)0, - (unsigned int)pDraw->width * 4); - XDBG_GOTO_IF_FAIL (src_image != NULL, done_copy_buf); - - dst_image = g2d_image_create_bo2 (G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB, - (unsigned int)vbuf->width, - (unsigned int)vbuf->height, - (unsigned int)vbuf->handles[0], - (unsigned int)vbuf->handles[1], - (unsigned int)vbuf->pitches[0]); - XDBG_GOTO_IF_FAIL (dst_image != NULL, done_copy_buf); - - tbm_bo_map (privPixmap->bo, TBM_DEVICE_MM, TBM_OPTION_READ); - tbm_bo_map (vbuf->bo[0], TBM_DEVICE_MM, TBM_OPTION_READ); - - util_g2d_blend_with_scale (G2D_OP_SRC, src_image, dst_image, - (int)vbuf->crop.x, (int)vbuf->crop.y, - (unsigned int)vbuf->crop.width, - (unsigned int)vbuf->crop.height, - (int)vbuf->crop.x, (int)vbuf->crop.y, - (unsigned int)vbuf->crop.width, - (unsigned int)vbuf->crop.height, - FALSE); - g2d_exec(); - - tbm_bo_unmap (privPixmap->bo); - tbm_bo_unmap (vbuf->bo[0]); - -done_copy_buf: - if (src_image) - g2d_image_free (src_image); - if (dst_image) - g2d_image_free (dst_image); - if (need_finish) - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); -} - -static Bool -_secDisplayVideoShowLayer (SECPortPrivPtr pPort, SECVideoBuf *vbuf, - SECLayerOutput output, SECLayerPos lpos) -{ - xRectangle src_rect, dst_rect; - - if (!pPort->layer) - { - SECModePtr pSecMode = (SECModePtr) SECPTR (pPort->pScrn)->pSecMode; - - if (!secUtilEnsureExternalCrtc (pPort->pScrn)) - { - XDBG_ERROR (MDA, "failed : pPort(%d) connect external crtc\n", pPort->index); - return FALSE; - } - - pPort->layer = secLayerCreate (pPort->pScrn, output, lpos); - XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE); - - if (output == LAYER_OUTPUT_EXT && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) - secLayerEnableVBlank (pPort->layer, TRUE); - } - - secLayerGetRect (pPort->layer, &src_rect, &dst_rect); - - if (memcmp (&pPort->d.src, &src_rect, sizeof (xRectangle)) || - memcmp (&pPort->d.dst, &dst_rect, sizeof (xRectangle))) - { - secLayerFreezeUpdate (pPort->layer, TRUE); - secLayerSetRect (pPort->layer, &pPort->d.src, &pPort->d.dst); - secLayerFreezeUpdate (pPort->layer, FALSE); - } - - secLayerSetBuffer (pPort->layer, vbuf); - if (!secLayerIsVisible (pPort->layer)) - secLayerShow (pPort->layer); - - XDBG_DEBUG (MDA, "pDraw(0x%lx), fb_id(%d), (%d,%d %dx%d) (%d,%d %dx%d)\n", - pPort->d.pDraw->id, vbuf->fb_id, - pPort->d.src.x, pPort->d.src.y, pPort->d.src.width, pPort->d.src.height, - pPort->d.dst.x, pPort->d.dst.y, pPort->d.dst.width, pPort->d.dst.height); - - return TRUE; -} - -static void -_secDisplayVideoHideLayer (SECPortPrivPtr pPort) -{ - if (!pPort->layer) - return; - - secLayerUnref (pPort->layer); - pPort->layer = NULL; -} - -static SECVideoBuf* -_secDisplayVideoGetBuffer (SECPortPrivPtr pPort) -{ - int i; - - for (i = 0; i < LAYER_BUF_CNT; i++) - { - if (!pPort->outbuf[i]) - { - SECPtr pSec = SECPTR (pPort->pScrn); - - pPort->outbuf[i] = secUtilAllocVideoBuffer (pPort->pScrn, FOURCC_RGB32, - pPort->d.pDraw->width, - pPort->d.pDraw->height, - (pSec->scanout)?TRUE:FALSE, - FALSE, FALSE); - XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, fail_get_buf); - break; - } - else if (!pPort->outbuf[i]->showing) - break; - } - - if (i == LAYER_BUF_CNT) - { - XDBG_ERROR (MDA, "now all outbufs in use!\n"); - return NULL; - } - - XDBG_DEBUG (MDA, "outbuf: stamp(%ld) index(%d) h(%d,%d,%d)\n", - pPort->outbuf[i]->stamp, i, - pPort->outbuf[i]->handles[0], - pPort->outbuf[i]->handles[1], - pPort->outbuf[i]->handles[2]); - - pPort->outbuf[i]->crop = pPort->d.src; - - _copyBuffer (pPort->d.pDraw, pPort->outbuf[i]); - - return pPort->outbuf[i]; - -fail_get_buf: - _secDisplayVideoCloseBuffers (pPort); - return NULL; -} - -static void -_secDisplayVideoCloseBuffers (SECPortPrivPtr pPort) -{ - int i; - - for (i = 0; i < LAYER_BUF_CNT; i++) - if (pPort->outbuf[i]) - { - secUtilVideoBufferUnref (pPort->outbuf[i]); - pPort->outbuf[i] = NULL; - } -} - -static void -_secDisplayVideoStreamOff (SECPortPrivPtr pPort) -{ - _secDisplayVideoHideLayer (pPort); - _secDisplayVideoCloseBuffers (pPort); - - memset (&pPort->old_d, 0, sizeof (GetData)); - memset (&pPort->d, 0, sizeof (GetData)); - - if (pPort->stream_cnt > 0) - { - pPort->stream_cnt = 0; - XDBG_SECURE (MDA, "pPort(%d) stream off. \n", pPort->index); - } - - XDBG_TRACE (MDA, "done. \n"); -} - -static Bool -_secDisplayVideoAddDrawableEvent (SECPortPrivPtr pPort) -{ - SECDisplayVideoResource *resource; - void *ptr=NULL; - int ret; - - ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id, - event_drawable_type, NULL, DixWriteAccess); - if (ret == Success) - { - return TRUE; - } - - resource = malloc (sizeof (SECDisplayVideoResource)); - if (resource == NULL) - return FALSE; - - if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource)) - { - free (resource); - return FALSE; - } - - XDBG_TRACE (MDA, "id(0x%08lx). \n", pPort->d.pDraw->id); - - resource->id = pPort->d.pDraw->id; - resource->type = event_drawable_type; - resource->pPort = pPort; - resource->pScrn = pPort->pScrn; - - return TRUE; -} - -static int -_secDisplayVideoRegisterEventDrawableGone (void *data, XID id) -{ - SECDisplayVideoResource *resource = (SECDisplayVideoResource*)data; - - XDBG_TRACE (MDA, "id(0x%08lx). \n", id); - - if (!resource) - return Success; - - if (!resource->pPort || !resource->pScrn) - return Success; - - SECDisplayVideoStop (resource->pScrn, (pointer)resource->pPort, 1); - - free(resource); - - return Success; -} - -static Bool -_secDisplayVideoRegisterEventResourceTypes (void) -{ - event_drawable_type = CreateNewResourceType (_secDisplayVideoRegisterEventDrawableGone, "Sec Video Drawable"); - - if (!event_drawable_type) - return FALSE; - - return TRUE; -} - -static int -SECDisplayVideoGetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 *value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _portAtom (PAA_OVERLAY)) - { - *value = pPort->overlay; - return Success; - } - - return BadMatch; -} - -static int -SECDisplayVideoSetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _portAtom (PAA_OVERLAY)) - { - pPort->overlay = value; - XDBG_DEBUG (MDA, "overlay(%d) \n", value); - return Success; - } - - return BadMatch; -} - -static int -SECDisplayVideoGetStill (ScrnInfoPtr pScrn, - short vid_x, short vid_y, short drw_x, short drw_y, - short vid_w, short vid_h, short drw_w, short drw_h, - RegionPtr clipBoxes, pointer data, - DrawablePtr pDraw) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - SECVideoBuf *vbuf; - SECLayerOutput output; - SECLayerPos lpos; - - XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_PIXMAP, BadRequest); - - pPort->pScrn = pScrn; - - pPort->d.width = pDraw->width; - pPort->d.height = pDraw->height; - pPort->d.src.x = drw_x; - pPort->d.src.y = drw_y; - pPort->d.src.width = drw_w; - pPort->d.src.height = drw_h; - pPort->d.dst.x = vid_x; - pPort->d.dst.y = vid_y; - pPort->d.dst.width = drw_w; - pPort->d.dst.height = drw_h; - pPort->d.pDraw = pDraw; - - if (pPort->old_d.width != pPort->d.width || - pPort->old_d.height != pPort->d.height) - { - _secDisplayVideoHideLayer (pPort); - _secDisplayVideoCloseBuffers (pPort); - } - - if (!_secDisplayVideoAddDrawableEvent (pPort)) - return BadRequest; - - if (pPort->stream_cnt == 0) - { - pPort->stream_cnt++; - - XDBG_SECURE (MDA, "pPort(%d) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n", - pPort->index, pDraw->width, pDraw->height, - drw_x, drw_y, drw_w, drw_h, vid_x, vid_y, vid_w, vid_h); - } - - vbuf = _secDisplayVideoGetBuffer (pPort); - XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, BadRequest); - - if (pPort->overlay) - { - output = LAYER_OUTPUT_EXT; - lpos = LAYER_UPPER; - } - else - { - XDBG_ERROR (MDA, "pPort(%d) implemented for only overlay\n", pPort->index); - return BadRequest; - } - - if (!_secDisplayVideoShowLayer (pPort, vbuf, output, lpos)) - return BadRequest; - - pPort->old_d = pPort->d; - - return Success; -} - -static void -SECDisplayVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - XDBG_TRACE (MDA, "exit (%d) \n", exit); - - if (!exit) - return; - - _secDisplayVideoStreamOff (pPort); - - pPort->overlay = FALSE; -} - -static void -SECDisplayVideoQueryBestSize (ScrnInfoPtr pScrn, - Bool motion, - short vid_w, short vid_h, - short dst_w, short dst_h, - unsigned int *p_w, unsigned int *p_h, - pointer data) -{ - if (p_w) - *p_w = (unsigned int)dst_w & ~1; - if (p_h) - *p_h = (unsigned int)dst_h; -} - -XF86VideoAdaptorPtr -secVideoSetupDisplayVideo (ScreenPtr pScreen) -{ - XF86VideoAdaptorPtr pAdaptor; - SECPortPrivPtr pPort; - int i; - - pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) + - (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT); - if (!pAdaptor) - return NULL; - - dummy_encoding[0].width = pScreen->width; - dummy_encoding[0].height = pScreen->height; - - pAdaptor->type = XvPixmapMask | XvOutputMask | XvStillMask; - pAdaptor->flags = VIDEO_OVERLAID_IMAGES; - pAdaptor->name = "SEC External Overlay Video"; - pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec); - pAdaptor->pEncodings = dummy_encoding; - pAdaptor->nFormats = NUM_FORMATS; - pAdaptor->pFormats = formats; - pAdaptor->nPorts = SEC_MAX_PORT; - pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]); - - pPort = (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]); - - for (i = 0; i < SEC_MAX_PORT; i++) - { - pAdaptor->pPortPrivates[i].ptr = &pPort[i]; - pPort[i].index = i; - } - - pAdaptor->nAttributes = NUM_ATTRIBUTES; - pAdaptor->pAttributes = attributes; - - pAdaptor->GetPortAttribute = SECDisplayVideoGetPortAttribute; - pAdaptor->SetPortAttribute = SECDisplayVideoSetPortAttribute; - pAdaptor->GetStill = SECDisplayVideoGetStill; - pAdaptor->StopVideo = SECDisplayVideoStop; - pAdaptor->QueryBestSize = SECDisplayVideoQueryBestSize; - - if (!_secDisplayVideoRegisterEventResourceTypes ()) - { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n"); - return FALSE; - } - - return pAdaptor; -} diff --git a/src/xv/sec_video_tvout.c b/src/xv/sec_video_tvout.c deleted file mode 100644 index 20492ce..0000000 --- a/src/xv/sec_video_tvout.c +++ /dev/null @@ -1,529 +0,0 @@ -/************************************************************************** - -xserver-xorg-video-exynos - -Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: Boram Park <boram1288.park@samsung.com> - -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 "sec.h" -#include "sec_display.h" -#include "sec_crtc.h" -#include "sec_output.h" -#include "sec_accel.h" -#include "sec_util.h" -#include "sec_converter.h" -#include "sec_video_tvout.h" -#include "sec_video_virtual.h" -#include "sec_video_fourcc.h" -#include "sec_drm_ipp.h" -#include "sec_layer.h" -#include "sec_prop.h" - -#include <sys/ioctl.h> -#include <exynos_drm.h> -#include <drm_fourcc.h> - -#define TVBUF_NUM 3 - -/* HW restriction (VP) */ -#define MIN_WIDTH 32 -#define MIN_HEIGHT 4 -#define MAX_WIDTH 1920 -#define MAX_HEIGHT 1080 -#define MIN_SCALE 0.25 -#define MAX_SCALE 16.0 - -/* private structure */ -struct _SECVideoTv -{ - ScrnInfoPtr pScrn; - - SECLayer *layer; - SECLayerPos lpos; - - /* used if id is not supported in case of lpos == LAYER_LOWER1. */ - SECCvt *cvt; - SECVideoBuf **outbuf; - int outbuf_index; - int outbuf_num; - - int tv_width; - int tv_height; - - xRectangle tv_rect; - - unsigned int convert_id; -}; - -static Bool -_secVieoTvCalSize (SECVideoTv* tv, int src_w, int src_h, int dst_w, int dst_h) -{ - float r; - - if (src_w < MIN_WIDTH || src_h < MIN_HEIGHT) - { - XDBG_WARNING (MTVO, "size(%dx%d) must be more than (%dx%d).\n", - src_w, src_h, MIN_WIDTH, MAX_WIDTH); - } - - r = (float)dst_w / src_w; - if (r < MIN_SCALE || r > MAX_SCALE) - { - XDBG_WARNING (MTVO, "ratio_w(%f) is out of range(%f~%f).\n", - r, MIN_SCALE, MAX_SCALE); - } - - r = (float)dst_h / src_h; - if (r < MIN_SCALE || r > MAX_SCALE) - { - XDBG_WARNING (MTVO, "ratio_h(%d) is out of range(%f~%f).\n", - r, MIN_SCALE, MAX_SCALE); - } - - return TRUE; -} - -static SECVideoBuf* -_secVideoTvGetOutBuffer (SECVideoTv* tv, int width, int height, Bool secure) -{ - int i = tv->outbuf_index, j; - - if (!tv->outbuf) - { - tv->outbuf = (SECVideoBuf**)calloc (tv->outbuf_num, sizeof (SECVideoBuf*)); - XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, NULL); - } - - i++; - if (i >= tv->outbuf_num) - i = 0; - - for (j = 0; j < tv->outbuf_num; j++) - { - if (tv->outbuf[i]) - { - XDBG_DEBUG (MTVO, "outbuf(%p) converting(%d) showing(%d)\n", - tv->outbuf[i], VBUF_IS_CONVERTING (tv->outbuf[i]), tv->outbuf[i]->showing); - - if (tv->outbuf[i] && !VBUF_IS_CONVERTING (tv->outbuf[i]) && !tv->outbuf[i]->showing) - { - tv->outbuf_index = i; - return tv->outbuf[i]; - } - } - else - { - SECPtr pSec = SECPTR (tv->pScrn); - - tv->outbuf[i] = secUtilAllocVideoBuffer (tv->pScrn, tv->convert_id, width, height, - (pSec->scanout)?TRUE:FALSE, TRUE, secure); - XDBG_RETURN_VAL_IF_FAIL (tv->outbuf[i] != NULL, NULL); - - XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id)); - - tv->outbuf_index = i; - return tv->outbuf[i]; - } - - i++; - if (i >= tv->outbuf_num) - i = 0; - } - -#if 0 - char buffers[1024]; - CLEAR (buffers); - for (j = 0; j < tv->outbuf_num; j++) - { - if (tv->outbuf[j]) - snprintf (buffers, 1024, "%s %d(%d,%d) ", buffers, tv->outbuf[j]->keys[0], - VBUF_IS_CONVERTING (tv->outbuf[j]), tv->outbuf[j]->showing); - } - - XDBG_ERROR (MTVO, "now all outbufs in use! %s\n", buffers); -#else - XDBG_ERROR (MTVO, "now all outbufs in use!\n"); -#endif - - return NULL; -} - -static Bool -_secVideoTvLayerEnsure (SECVideoTv* tv) -{ - SECLayer *layer; - - if (tv->layer) - return TRUE; - - XDBG_RETURN_VAL_IF_FAIL (tv->lpos != LAYER_NONE, FALSE); - - layer = secLayerCreate (tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos); - XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE); - - tv->layer = layer; - - return TRUE; -} - -static void -_secVideoTvLayerDestroy (SECVideoTv* tv) -{ - if (tv->layer) - { - secLayerUnref (tv->layer); - tv->layer = NULL; - } -} - -static int -_secVideoTvPutImageInternal (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect) -{ - int ret = 0; - - XDBG_DEBUG (MTVO, "rect (%d,%d %dx%d) \n", - rect->x, rect->y, rect->width, rect->height); - - secLayerSetRect (tv->layer, &vbuf->crop, rect); - - if (tv->lpos == LAYER_LOWER1) - if (!_secVieoTvCalSize (tv, vbuf->width, vbuf->height, - rect->width, rect->height)) - return 0; - - ret = secLayerSetBuffer (tv->layer, vbuf); - - if (ret == 0) - return 0; - - secLayerShow (tv->layer); - - return ret; -} - -static void -_secVideoTvCvtCallback (SECCvt *cvt, - SECVideoBuf *src, - SECVideoBuf *dst, - void *cvt_data, - Bool error) -{ - SECVideoTv *tv = (SECVideoTv*)cvt_data; - int i; - - XDBG_RETURN_IF_FAIL (tv != NULL); - XDBG_RETURN_IF_FAIL (cvt != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst)); - - XDBG_DEBUG (MTVO, "++++++++++++++++++++++++ \n"); - - for (i = 0; i < tv->outbuf_num; i++) - if (tv->outbuf[i] == dst) - break; - XDBG_RETURN_IF_FAIL (i < tv->outbuf_num); - - _secVideoTvPutImageInternal (tv, dst, &tv->tv_rect); - - XDBG_DEBUG (MTVO, "++++++++++++++++++++++++.. \n"); -} - -SECVideoTv* -secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos) -{ - SECVideoTv* tv = NULL; - SECModePtr pSecMode; - - XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL); - XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_LOWER1 && lpos <= LAYER_UPPER, NULL); - XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL); - - tv = calloc (sizeof (SECVideoTv), 1); - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL); - - pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode; - - if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - /* In case of video-only(virtual), we always use converter. */ - tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M); - XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect); - - secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv); - } - else if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI) - { - if (!secLayerSupport (pScrn, LAYER_OUTPUT_EXT, lpos, id)) - { - /* used if id is not supported in case of lpos == LAYER_LOWER1. */ - tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M); - XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect); - - secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv); - } - } - - XDBG_DEBUG (MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR (id), lpos); - - tv->pScrn = pScrn; - tv->lpos = lpos; - tv->outbuf_index = -1; - tv->convert_id = FOURCC_RGB32; - tv->outbuf_num = TVBUF_NUM; - - return tv; - -fail_connect: - if (tv) - { - if (tv->cvt) - secCvtDestroy (tv->cvt); - free (tv); - } - return NULL; -} - -void -secVideoTvDisconnect (SECVideoTv* tv) -{ - int i; - - XDBG_RETURN_IF_FAIL (tv != NULL); - - XDBG_DEBUG (MTVO, "!\n"); - - if (tv->cvt) - secCvtDestroy (tv->cvt); - - _secVideoTvLayerDestroy (tv); - - if (tv->outbuf) - { - for (i = 0; i < tv->outbuf_num; i++) - if (tv->outbuf[i]) - secUtilVideoBufferUnref (tv->outbuf[i]); - - free (tv->outbuf); - } - - free (tv); -} - -Bool -secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (vbufs != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (bufnum >= TVBUF_NUM, FALSE); - - if (tv->outbuf) - { - XDBG_ERROR (MTVO, "already has buffers.\n"); - return FALSE; - } - - tv->outbuf_num = bufnum; - tv->outbuf = (SECVideoBuf**)calloc (bufnum, sizeof (SECVideoBuf*)); - XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, FALSE); - - for (i = 0; i < tv->outbuf_num; i++) - { - XDBG_GOTO_IF_FAIL (tv->convert_id == vbufs[i]->id, fail_set_buffer); - XDBG_GOTO_IF_FAIL (tv->tv_width == vbufs[i]->width, fail_set_buffer); - XDBG_GOTO_IF_FAIL (tv->tv_height == vbufs[i]->height, fail_set_buffer); - - tv->outbuf[i] = secUtilVideoBufferRef (vbufs[i]); - XDBG_GOTO_IF_FAIL (tv->outbuf[i] != NULL, fail_set_buffer); - - if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset) - secUtilClearVideoBuffer (tv->outbuf[i]); - else - tv->outbuf[i]->need_reset = TRUE; - } - - return TRUE; - -fail_set_buffer: - if (tv->outbuf) - { - for (i = 0; i < tv->outbuf_num; i++) - { - if (tv->outbuf[i]) - { - secUtilVideoBufferUnref (tv->outbuf[i]); - tv->outbuf[i] = NULL; - } - } - - free (tv->outbuf); - tv->outbuf = NULL; - } - - return FALSE; -} -SECLayerPos -secVideoTvGetPos (SECVideoTv *tv) -{ - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, LAYER_NONE); - - return tv->lpos; -} - -SECLayer* -secVideoTvGetLayer (SECVideoTv *tv) -{ - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL); - - _secVideoTvLayerEnsure (tv); - - return tv->layer; -} - -/* HDMI : 'handles' is "gem handle" - * VIRTUAL : 'handles' is "physical address" - * 'data' is "raw data" - * only one of 'handles' and 'data' has value. - */ -int -secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect, int csc_range) -{ - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, 0); - XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0); - XDBG_RETURN_VAL_IF_FAIL (vbuf->id > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (rect != NULL, 0); - - XDBG_RETURN_VAL_IF_FAIL (vbuf->handles[0] > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (vbuf->pitches[0] > 0, 0); - - _secVideoTvLayerEnsure (tv); - XDBG_RETURN_VAL_IF_FAIL (tv->layer != NULL, 0); - - if (tv->cvt) - { - /* can't show buffer to HDMI at now. */ - SECModePtr pSecMode = (SECModePtr) SECPTR (tv->pScrn)->pSecMode; - SECCvtProp src_prop = {0,}, dst_prop = {0,}; - SECVideoBuf *outbuf; - int dst_width, dst_height; - xRectangle dst_crop; - - - /* CHECK */ - if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL) - { - XDBG_RETURN_VAL_IF_FAIL (tv->tv_width > 0, 0); - XDBG_RETURN_VAL_IF_FAIL (tv->tv_height > 0, 0); - dst_width = tv->tv_width; - dst_height = tv->tv_height; - dst_crop = *rect; - - tv->tv_rect.x = 0; - tv->tv_rect.y = 0; - tv->tv_rect.width = tv->tv_width; - tv->tv_rect.height = tv->tv_height; - } - else - { - dst_width = rect->width; - dst_height = rect->height; - dst_crop = *rect; - dst_crop.x = 0; - dst_crop.y = 0; - - tv->tv_rect = *rect; - } - - src_prop.id = vbuf->id; - src_prop.width = vbuf->width; - src_prop.height = vbuf->height; - src_prop.crop = vbuf->crop; - - dst_prop.id = tv->convert_id; - dst_prop.width = dst_width; - dst_prop.height = dst_height; - dst_prop.crop = dst_crop; - dst_prop.secure = vbuf->secure; - dst_prop.csc_range = csc_range; - - if (!secCvtEnsureSize (&src_prop, &dst_prop)) - return 0; - - outbuf = _secVideoTvGetOutBuffer (tv, dst_prop.width, dst_prop.height, vbuf->secure); - if (!outbuf) - return 0; - outbuf->crop = dst_prop.crop; - - if (!secCvtSetProperpty (tv->cvt, &src_prop, &dst_prop)) - return 0; - - if (!secCvtConvert (tv->cvt, vbuf, outbuf)) - return 0; - - XDBG_TRACE (MTVO, "'%c%c%c%c' %dx%d (%d,%d %dx%d) => '%c%c%c%c' %dx%d (%d,%d %dx%d) convert. rect(%d,%d %dx%d)\n", - FOURCC_STR (vbuf->id), vbuf->width, vbuf->height, - vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height, - FOURCC_STR (outbuf->id), outbuf->width, outbuf->height, - outbuf->crop.x, outbuf->crop.y, outbuf->crop.width, outbuf->crop.height, - rect->x, rect->y, rect->width, rect->height); - - return 1; - } - - /* can show buffer to HDMI at now. */ - - return _secVideoTvPutImageInternal (tv, vbuf, rect); -} - -void -secVideoTvSetSize (SECVideoTv *tv, int width, int height) -{ - XDBG_RETURN_IF_FAIL (tv != NULL); - - tv->tv_width = width; - tv->tv_height = height; - - XDBG_TRACE (MTVO, "size(%dx%d) \n", width, height); -} - -SECCvt* -secVideoTvGetConverter (SECVideoTv *tv) -{ - XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL); - - return tv->cvt; -} - -void -secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id) -{ - XDBG_RETURN_IF_FAIL (tv != NULL); - XDBG_RETURN_IF_FAIL (convert_id > 0); - - tv->convert_id = convert_id; - - XDBG_TRACE (MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR (convert_id)); -} diff --git a/src/xv/sec_video_virtual.c b/src/xv/sec_video_virtual.c deleted file mode 100644 index fac74b8..0000000 --- a/src/xv/sec_video_virtual.c +++ /dev/null @@ -1,2066 +0,0 @@ -/* - * xserver-xorg-video-exynos - * - * Copyright 2004 Keith Packard - * Copyright 2005 Eric Anholt - * Copyright 2006 Nokia Corporation - * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. - * - * Contact: Boram Park <boram1288.park@samsung.com> - * - * Permission to use, copy, modify, distribute and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the names of the authors and/or copyright holders - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. The authors and - * copyright holders make no representations about the suitability of this - * software for any purpose. It is provided "as is" without any express - * or implied warranty. - * - * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <pixman.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xv.h> - -#include "sec.h" -#include "sec_util.h" -#include "sec_wb.h" -#include "sec_crtc.h" -#include "sec_converter.h" -#include "sec_output.h" -#include "sec_video.h" -#include "sec_video_fourcc.h" -#include "sec_video_virtual.h" -#include "sec_video_tvout.h" -#include "sec_display.h" -#include "sec_xberc.h" - -#include "xv_types.h" - -#define DEV_INDEX 2 -#define BUF_NUM_EXTERNAL 5 -#define BUF_NUM_STREAM 3 - -enum -{ - CAPTURE_MODE_NONE, - CAPTURE_MODE_STILL, - CAPTURE_MODE_STREAM, - CAPTURE_MODE_MAX, -}; - -enum -{ - DISPLAY_LCD, - DISPLAY_EXTERNAL, -}; - -enum -{ - DATA_TYPE_UI, - DATA_TYPE_VIDEO, - DATA_TYPE_MAX, -}; - -static unsigned int support_formats[] = -{ - FOURCC_RGB32, - FOURCC_ST12, - FOURCC_SN12, -}; - -static XF86VideoEncodingRec dummy_encoding[] = -{ - { 0, "XV_IMAGE", -1, -1, { 1, 1 } }, - { 1, "XV_IMAGE", 2560, 2560, { 1, 1 } }, -}; - -static XF86ImageRec images[] = -{ - XVIMAGE_RGB32, - XVIMAGE_SN12, - XVIMAGE_ST12, -}; - -static XF86VideoFormatRec formats[] = -{ - { 16, TrueColor }, - { 24, TrueColor }, - { 32, TrueColor }, -}; - -static XF86AttributeRec attributes[] = -{ - { 0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_FORMAT" }, - { 0, 0, CAPTURE_MODE_MAX, "_USER_WM_PORT_ATTRIBUTE_CAPTURE" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_DISPLAY" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF" }, - { 0, 0, DATA_TYPE_MAX, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE" }, - { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE" }, - { 0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER" }, -}; - -typedef enum -{ - PAA_MIN, - PAA_FORMAT, - PAA_CAPTURE, - PAA_DISPLAY, - PAA_ROTATE_OFF, - PAA_DATA_TYPE, - PAA_SECURE, - PAA_RETBUF, - PAA_MAX -} SECPortAttrAtom; - -static struct -{ - SECPortAttrAtom paa; - const char *name; - Atom atom; -} atoms[] = -{ - { PAA_FORMAT, "_USER_WM_PORT_ATTRIBUTE_FORMAT", None }, - { PAA_CAPTURE, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", None }, - { PAA_DISPLAY, "_USER_WM_PORT_ATTRIBUTE_DISPLAY", None }, - { PAA_ROTATE_OFF, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF", None }, - { PAA_DATA_TYPE, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", None }, - { PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None }, - { PAA_RETBUF, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", None }, -}; - -typedef struct _RetBufInfo -{ - SECVideoBuf *vbuf; - int type; - struct xorg_list link; -} RetBufInfo; - -/* SEC port information structure */ -typedef struct -{ - /* index */ - int index; - - /* port attribute */ - int id; - int capture; - int display; - Bool secure; - Bool data_type; - Bool rotate_off; - - /* information from outside */ - ScrnInfoPtr pScrn; - DrawablePtr pDraw; - RegionPtr clipBoxes; - - /* writeback */ - SECWb *wb; - - /* video */ - SECCvt *cvt; - - SECVideoBuf *dstbuf; - SECVideoBuf **outbuf; - int outbuf_num; - int outbuf_index; - - struct xorg_list retbuf_info; - Bool need_damage; - - OsTimerPtr retire_timer; - Bool putstill_on; - - unsigned int status; - CARD32 retire_time; - CARD32 prev_time; - - struct xorg_list link; -} SECPortPriv, *SECPortPrivPtr; - -static RESTYPE event_drawable_type; - -typedef struct _SECVideoResource -{ - XID id; - RESTYPE type; - SECPortPrivPtr pPort; - ScrnInfoPtr pScrn; -} SECVideoResource; - -#define SEC_MAX_PORT 1 - -#define NUM_IMAGES (sizeof(images) / sizeof(images[0])) -#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) -#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) -#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) - -static DevPrivateKeyRec video_virtual_port_key; -#define VideoVirtualPortKey (&video_virtual_port_key) -#define GetPortInfo(pDraw) ((SECVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoVirtualPortKey)) - -typedef struct _SECVideoPortInfo -{ - ClientPtr client; - XvPortPtr pp; -} SECVideoPortInfo; - -static int (*ddPutStill) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - -static void SECVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit); -static void _secVirtualVideoCloseOutBuffer (SECPortPrivPtr pPort); -static void _secVirtualVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data); -static void _secVirtualVideoWbDumpFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data); -static void _secVirtualVideoWbStopFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data); -static SECVideoBuf* _secVirtualVideoGetBlackBuffer (SECPortPrivPtr pPort); -static Bool _secVirtualVideoEnsureOutBuffers (ScrnInfoPtr pScrn, SECPortPrivPtr pPort, int id, int width, int height); -static void _secVirtualVideoWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data); - -static SECVideoPortInfo* -_port_info (DrawablePtr pDraw) -{ - if (!pDraw) - return NULL; - - if (pDraw->type == DRAWABLE_WINDOW) - return GetPortInfo ((WindowPtr)pDraw); - else - return GetPortInfo ((PixmapPtr)pDraw); -} - -static Atom -_secVideoGetPortAtom (SECPortAttrAtom paa) -{ - int i; - - XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None); - - for (i = 0; i < NUM_ATOMS; i++) - { - if (paa == atoms[i].paa) - { - if (atoms[i].atom == None) - atoms[i].atom = MakeAtom (atoms[i].name, - strlen (atoms[i].name), TRUE); - - return atoms[i].atom; - } - } - - XDBG_ERROR (MVA, "Error: Unknown Port Attribute Name!\n"); - - return None; -} - -static void -_secVirtualVideoSetSecure (SECPortPrivPtr pPort, Bool secure) -{ - SECVideoPortInfo *info; - - secure = (secure > 0) ? TRUE : FALSE; - - if (pPort->secure == secure) - return; - - pPort->secure = secure; - - XDBG_TRACE (MVA, "secure(%d) \n", secure); - - info = _port_info (pPort->pDraw); - if (!info || !info->pp) - return; - - XvdiSendPortNotify (info->pp, _secVideoGetPortAtom (PAA_SECURE), secure); -} - -static PixmapPtr -_secVirtualVideoGetPixmap (DrawablePtr pDraw) -{ - if (pDraw->type == DRAWABLE_WINDOW) - return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); - else - return (PixmapPtr) pDraw; -} - -static Bool -_secVirtualVideoIsSupport (unsigned int id) -{ - int i; - - for (i = 0; i < sizeof (support_formats) / sizeof (unsigned int); i++) - if (support_formats[i] == id) - return TRUE; - - return FALSE; -} - -#if 0 -static char buffers[1024]; - -static void -_buffers (SECPortPrivPtr pPort) -{ - RetBufInfo *cur = NULL, *next = NULL; - - CLEAR (buffers); - xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link) - { - if (cur->vbuf) - snprintf (buffers, 1024, "%s %d", buffers, cur->vbuf->keys[0]); - } -} -#endif - -static RetBufInfo* -_secVirtualVideoFindReturnBuf (SECPortPrivPtr pPort, unsigned int key) -{ - RetBufInfo *cur = NULL, *next = NULL; - - XDBG_RETURN_VAL_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL, NULL); - - xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link) - { - if (cur->vbuf && cur->vbuf->keys[0] == key) - return cur; - } - - return NULL; -} - -static Bool -_secVirtualVideoAddReturnBuf (SECPortPrivPtr pPort, SECVideoBuf *vbuf) -{ - RetBufInfo *info; - - XDBG_RETURN_VAL_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL, FALSE); - - info = _secVirtualVideoFindReturnBuf (pPort, vbuf->keys[0]); - XDBG_RETURN_VAL_IF_FAIL (info == NULL, FALSE); - - info = calloc (1, sizeof (RetBufInfo)); - XDBG_RETURN_VAL_IF_FAIL (info != NULL, FALSE); - - info->vbuf = secUtilVideoBufferRef (vbuf); - XDBG_GOTO_IF_FAIL (info->vbuf != NULL, fail); - info->vbuf->showing = TRUE; - - XDBG_DEBUG (MVA, "retbuf (%ld,%d,%d,%d) added.\n", vbuf->stamp, - vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]); - - xorg_list_add (&info->link, &pPort->retbuf_info); - - return TRUE; - -fail : - if (info) - free (info); - - return FALSE; -} - -static void -_secVirtualVideoRemoveReturnBuf (SECPortPrivPtr pPort, RetBufInfo *info) -{ - XDBG_RETURN_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL); - XDBG_RETURN_IF_FAIL (info != NULL); - XDBG_RETURN_IF_FAIL (info->vbuf != NULL); - - info->vbuf->showing = FALSE; - - XDBG_DEBUG (MVA, "retbuf (%ld,%d,%d,%d) removed.\n", info->vbuf->stamp, - info->vbuf->keys[0], info->vbuf->keys[1], info->vbuf->keys[2]); - - if (pPort->wb) - secWbQueueBuffer (pPort->wb, info->vbuf); - - secUtilVideoBufferUnref (info->vbuf); - xorg_list_del (&info->link); - free (info); -} - -static void -_secVirtualVideoRemoveReturnBufAll (SECPortPrivPtr pPort) -{ - RetBufInfo *cur = NULL, *next = NULL; - - XDBG_RETURN_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL); - - xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link) - { - _secVirtualVideoRemoveReturnBuf (pPort, cur); - } -} - -static void -_secVirtualVideoDraw (SECPortPrivPtr pPort, SECVideoBuf *buf) -{ - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - if (!pPort->pDraw) - { - XDBG_TRACE (MVA, "drawable gone!\n"); - return; - } - - XDBG_RETURN_IF_FAIL (pPort->need_damage == TRUE); - XDBG_GOTO_IF_FAIL (VBUF_IS_VALID (buf), draw_done); - - XDBG_TRACE (MVA, "%c%c%c%c, %dx%d. \n", - FOURCC_STR (buf->id), buf->width, buf->height); - - if (pPort->id == FOURCC_RGB32) - { - PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw); - tbm_bo_handle bo_handle; - - XDBG_GOTO_IF_FAIL (buf->secure == FALSE, draw_done); - - if (pPort->pDraw->width != buf->width || pPort->pDraw->height != buf->height) - { - XDBG_ERROR (MVA, "not matched. (%dx%d != %dx%d) \n", - pPort->pDraw->width, pPort->pDraw->height, - buf->width, buf->height); - goto draw_done; - } - - bo_handle = tbm_bo_map (buf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_READ); - XDBG_GOTO_IF_FAIL (bo_handle.ptr != NULL, draw_done); - XDBG_GOTO_IF_FAIL (buf->size > 0, draw_done); - - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - - if (pPixmap->devPrivate.ptr) - { - XDBG_DEBUG (MVA, "vir(%p) size(%d) => pixmap(%p)\n", - bo_handle.ptr, buf->size, pPixmap->devPrivate.ptr); - - memcpy (pPixmap->devPrivate.ptr, bo_handle.ptr, buf->size); - } - - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - tbm_bo_unmap (buf->bo[0]); - } - else /* FOURCC_ST12 */ - { - PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw); - XV_DATA xv_data = {0,}; - - _secVirtualVideoSetSecure (pPort, buf->secure); - - XV_INIT_DATA (&xv_data); - - if (buf->phy_addrs[0] > 0) - { - xv_data.YBuf = buf->phy_addrs[0]; - xv_data.CbBuf = buf->phy_addrs[1]; - xv_data.CrBuf = buf->phy_addrs[2]; - - xv_data.BufType = XV_BUF_TYPE_LEGACY; - } - else - { - xv_data.YBuf = buf->keys[0]; - xv_data.CbBuf = buf->keys[1]; - xv_data.CrBuf = buf->keys[2]; - - xv_data.BufType = XV_BUF_TYPE_DMABUF; - } - -#if 0 - _buffers (pPort); - ErrorF ("[Xorg] send : %d (%s)\n", xv_data.YBuf, buffers); -#endif - - XDBG_DEBUG (MVA, "still_data(%d,%d,%d) type(%d) \n", - xv_data.YBuf, xv_data.CbBuf, xv_data.CrBuf, - xv_data.BufType); - - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - - if (pPixmap->devPrivate.ptr) - memcpy (pPixmap->devPrivate.ptr, &xv_data, sizeof (XV_DATA)); - - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - _secVirtualVideoAddReturnBuf (pPort, buf); - } - -draw_done: - DamageDamageRegion (pPort->pDraw, pPort->clipBoxes); - pPort->need_damage = FALSE; - - SECPtr pSec = SECPTR (pPort->pScrn); - if ((pSec->dump_mode & XBERC_DUMP_MODE_CA) && pSec->dump_info) - { - char file[128]; - static int i; - snprintf (file, sizeof(file), "capout_stream_%c%c%c%c_%dx%d_%03d.%s", - FOURCC_STR(buf->id), buf->width, buf->height, i++, - IS_RGB (buf->id)?"bmp":"yuv"); - secUtilDoDumpVBuf (pSec->dump_info, buf, file); - } - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CA) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - pPort->prev_time; - ErrorF ("damage send : %6ld ms\n", sub); - } -} - -static void -_secVirtualVideoWbDumpFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)user_data; - SECVideoBuf *vbuf = (SECVideoBuf*)noti_data; - - XDBG_RETURN_IF_FAIL (pPort != NULL); - XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf)); - XDBG_RETURN_IF_FAIL (vbuf->showing == FALSE); - - XDBG_TRACE (MVA, "dump (%ld,%d,%d,%d)\n", vbuf->stamp, - vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]); - - if (pPort->need_damage) - { - _secVirtualVideoDraw (pPort, vbuf); - } - - return; -} - -static void -_secVirtualVideoWbDumpDoneFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)user_data; - - if (!pPort) - return; - - XDBG_DEBUG (MVA, "close wb after ipp event done\n"); - - XDBG_RETURN_IF_FAIL (pPort->wb != NULL); - - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbStopFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpDoneFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbCloseFunc); - - secWbClose (pPort->wb); - pPort->wb = NULL; -} - -static void -_secVirtualVideoWbStopFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)user_data; - - if (!pPort) - return; - - if (pPort->need_damage) - { - SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort); - XDBG_TRACE (MVA, "black buffer(%d) return: wb stop\n", (black)?black->keys[0]:0); - _secVirtualVideoDraw (pPort, black); - } -} - -static void -_secVirtualVideoWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)user_data; - - if (!pPort) - return; - - pPort->wb = NULL; -} - -static void -_secVirtualVideoStreamOff (SECPortPrivPtr pPort) -{ - SECLayer *layer; - - XDBG_TRACE (MVA, "STREAM_OFF!\n"); - - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - if (pPort->wb) - { - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbStopFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpDoneFunc); - secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbCloseFunc); - - secWbClose (pPort->wb); - pPort->wb = NULL; - } - - if (pPort->id != FOURCC_RGB32) - _secVirtualVideoRemoveReturnBufAll (pPort); - - layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1); - if (layer) - secLayerRemoveNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc); - - if (pPort->need_damage) - { - /* all callbacks has been removed from wb/layer. We can't expect - * any event. So we send black image at the end. - */ - SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort); - XDBG_TRACE (MVA, "black buffer(%d) return: stream off\n", (black)?black->keys[0]:0); - _secVirtualVideoDraw (pPort, black); - } - - _secVirtualVideoCloseOutBuffer (pPort); - - if (pPort->clipBoxes) - { - RegionDestroy (pPort->clipBoxes); - pPort->clipBoxes = NULL; - } - - pPort->pDraw = NULL; - pPort->capture = CAPTURE_MODE_NONE; - pPort->id = FOURCC_RGB32; - pPort->secure = FALSE; - pPort->data_type = DATA_TYPE_UI; - pPort->need_damage = FALSE; - - if (pPort->putstill_on) - { - pPort->putstill_on = FALSE; - XDBG_SECURE (MVA, "pPort(%d) putstill off. \n", pPort->index); - } -} - -static int -_secVirtualVideoAddDrawableEvent (SECPortPrivPtr pPort) -{ - SECVideoResource *resource; - void *ptr; - int ret = 0; - - XDBG_RETURN_VAL_IF_FAIL (pPort->pScrn != NULL, BadImplementation); - XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadImplementation); - - ptr = NULL; - ret = dixLookupResourceByType (&ptr, pPort->pDraw->id, - event_drawable_type, NULL, DixWriteAccess); - if (ret == Success) - return Success; - - resource = malloc (sizeof (SECVideoResource)); - if (resource == NULL) - return BadAlloc; - - if (!AddResource (pPort->pDraw->id, event_drawable_type, resource)) - { - free (resource); - return BadAlloc; - } - - XDBG_TRACE (MVA, "id(0x%08lx). \n", pPort->pDraw->id); - - resource->id = pPort->pDraw->id; - resource->type = event_drawable_type; - resource->pPort = pPort; - resource->pScrn = pPort->pScrn; - - return Success; -} - -static int -_secVirtualVideoRegisterEventDrawableGone (void *data, XID id) -{ - SECVideoResource *resource = (SECVideoResource*)data; - - XDBG_TRACE (MVA, "id(0x%08lx). \n", id); - - if (!resource) - return Success; - - if (!resource->pPort || !resource->pScrn) - return Success; - - resource->pPort->pDraw = NULL; - - SECVirtualVideoStop (resource->pScrn, (pointer)resource->pPort, 1); - - free(resource); - - return Success; -} - -static Bool -_secVirtualVideoRegisterEventResourceTypes (void) -{ - event_drawable_type = CreateNewResourceType (_secVirtualVideoRegisterEventDrawableGone, - "Sec Virtual Video Drawable"); - - if (!event_drawable_type) - return FALSE; - - return TRUE; -} - -static tbm_bo -_secVirtualVideoGetFrontBo (SECPortPrivPtr pPort, int connector_type) -{ - xf86CrtcConfigPtr pCrtcConfig; - int i; - - pCrtcConfig = XF86_CRTC_CONFIG_PTR (pPort->pScrn); - XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, NULL); - - for (i = 0; i < pCrtcConfig->num_output; i++) - { - xf86OutputPtr pOutput = pCrtcConfig->output[i]; - SECOutputPrivPtr pOutputPriv = pOutput->driver_private; - - if (pOutputPriv->mode_output->connector_type == connector_type) - { - if (pOutput->crtc) - { - SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private; - return pCrtcPriv->front_bo; - } - else - XDBG_ERROR (MVA, "no crtc.\n"); - } - } - - return NULL; -} - -static SECVideoBuf* -_secVirtualVideoGetBlackBuffer (SECPortPrivPtr pPort) -{ - int i; - - if (!pPort->outbuf[0]) - { - XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, NULL); - _secVirtualVideoEnsureOutBuffers (pPort->pScrn, pPort, pPort->id, - pPort->pDraw->width, pPort->pDraw->height); - } - - for (i = 0; i < pPort->outbuf_num; i++) - { - if (pPort->outbuf[i] && !pPort->outbuf[i]->showing) - { - if (pPort->outbuf[i]->dirty) - secUtilClearVideoBuffer (pPort->outbuf[i]); - - return pPort->outbuf[i]; - } - } - - XDBG_ERROR (MVA, "now all buffers are in showing\n"); - - return NULL; -} - -static Bool -_secVirtualVideoEnsureOutBuffers (ScrnInfoPtr pScrn, SECPortPrivPtr pPort, int id, int width, int height) -{ - SECPtr pSec = SECPTR (pScrn); - int i; - - if (pPort->display == DISPLAY_EXTERNAL) - pPort->outbuf_num = BUF_NUM_EXTERNAL; - else - pPort->outbuf_num = BUF_NUM_STREAM; - - if (!pPort->outbuf) - { - pPort->outbuf = (SECVideoBuf**)calloc(pPort->outbuf_num, sizeof (SECVideoBuf*)); - XDBG_RETURN_VAL_IF_FAIL (pPort->outbuf != NULL, FALSE); - } - - for (i = 0; i < pPort->outbuf_num; i++) - { - int scanout; - - if (pPort->outbuf[i]) - continue; - - XDBG_RETURN_VAL_IF_FAIL (width > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (height > 0, FALSE); - - if (pPort->display == DISPLAY_LCD) - scanout = FALSE; - else - scanout = pSec->scanout; - - /* pPort->pScrn can be NULL if XvPutStill isn't called. */ - pPort->outbuf[i] = secUtilAllocVideoBuffer (pScrn, id, - width, height, - scanout, TRUE, pPort->secure); - - XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, ensure_buffer_fail); - } - - return TRUE; - -ensure_buffer_fail: - _secVirtualVideoCloseOutBuffer (pPort); - - return FALSE; -} - -static Bool -_secVirtualVideoEnsureDstBuffer (SECPortPrivPtr pPort) -{ - if (pPort->dstbuf) - { - secUtilClearVideoBuffer (pPort->dstbuf); - return TRUE; - } - - pPort->dstbuf = secUtilAllocVideoBuffer (pPort->pScrn, FOURCC_RGB32, - pPort->pDraw->width, - pPort->pDraw->height, - FALSE, FALSE, pPort->secure); - XDBG_RETURN_VAL_IF_FAIL (pPort->dstbuf != NULL, FALSE); - - return TRUE; -} - -static SECVideoBuf* -_secVirtualVideoGetUIBuffer (SECPortPrivPtr pPort, int connector_type) -{ - SECVideoBuf *uibuf = NULL; - tbm_bo bo[PLANAR_CNT] = {0,}; - SECFbBoDataPtr bo_data = NULL; - tbm_bo_handle bo_handle; - - bo[0] = _secVirtualVideoGetFrontBo (pPort, connector_type); - XDBG_RETURN_VAL_IF_FAIL (bo[0] != NULL, NULL); - - tbm_bo_get_user_data (bo[0], TBM_BO_DATA_FB, (void**)&bo_data); - XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, NULL); - - uibuf = secUtilCreateVideoBuffer (pPort->pScrn, FOURCC_RGB32, - bo_data->pos.x2 - bo_data->pos.x1, - bo_data->pos.y2 - bo_data->pos.y1, - FALSE); - XDBG_RETURN_VAL_IF_FAIL (uibuf != NULL, NULL); - - uibuf->bo[0] = tbm_bo_ref (bo[0]); - XDBG_GOTO_IF_FAIL (uibuf->bo[0] != NULL, fail_get); - - bo_handle = tbm_bo_get_handle (bo[0], TBM_DEVICE_DEFAULT); - uibuf->handles[0] = bo_handle.u32; - - XDBG_GOTO_IF_FAIL (uibuf->handles[0] > 0, fail_get); - - return uibuf; - -fail_get: - if (uibuf) - secUtilVideoBufferUnref (uibuf); - - return NULL; -} - -static SECVideoBuf* -_secVirtualVideoGetDrawableBuffer (SECPortPrivPtr pPort) -{ - SECVideoBuf *vbuf = NULL; - PixmapPtr pPixmap = NULL; - tbm_bo_handle bo_handle; - SECPixmapPriv *privPixmap; - Bool need_finish = FALSE; - - XDBG_GOTO_IF_FAIL (pPort->secure == FALSE, fail_get); - XDBG_GOTO_IF_FAIL (pPort->pDraw != NULL, fail_get); - - pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw); - XDBG_GOTO_IF_FAIL (pPixmap != NULL, fail_get); - - privPixmap = exaGetPixmapDriverPrivate (pPixmap); - XDBG_GOTO_IF_FAIL (privPixmap != NULL, fail_get); - - if (!privPixmap->bo) - { - need_finish = TRUE; - secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST); - XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, fail_get); - } - - vbuf = secUtilCreateVideoBuffer (pPort->pScrn, FOURCC_RGB32, - pPort->pDraw->width, - pPort->pDraw->height, - FALSE); - XDBG_GOTO_IF_FAIL (vbuf != NULL, fail_get); - - vbuf->bo[0] = tbm_bo_ref (privPixmap->bo); - bo_handle = tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_DEFAULT); - vbuf->handles[0] = bo_handle.u32; - - XDBG_GOTO_IF_FAIL (vbuf->handles[0] > 0, fail_get); - - return vbuf; - -fail_get: - if (pPixmap && need_finish) - secExaFinishAccess (pPixmap, EXA_PREPARE_DEST); - - if (vbuf) - secUtilVideoBufferUnref (vbuf); - - return NULL; -} - -static void -_secVirtualVideoCloseOutBuffer (SECPortPrivPtr pPort) -{ - int i; - - if (pPort->outbuf) - { - for (i = 0; i < pPort->outbuf_num; i++) - { - if (pPort->outbuf[i]) - secUtilVideoBufferUnref (pPort->outbuf[i]); - pPort->outbuf[i] = NULL; - } - - free (pPort->outbuf); - pPort->outbuf = NULL; - } - - if (pPort->dstbuf) - { - secUtilVideoBufferUnref (pPort->dstbuf); - pPort->dstbuf = NULL; - } - - pPort->outbuf_index = -1; -} - -static int -_secVirtualVideoDataType (SECPortPrivPtr pPort) -{ - SECLayer *video_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1); - - return (video_layer) ? DATA_TYPE_VIDEO : DATA_TYPE_UI; -} - -static int -_secVirtualVideoPreProcess (ScrnInfoPtr pScrn, SECPortPrivPtr pPort, - RegionPtr clipBoxes, DrawablePtr pDraw) -{ - if (pPort->pScrn == pScrn && pPort->pDraw == pDraw && - pPort->clipBoxes && clipBoxes && RegionEqual (pPort->clipBoxes, clipBoxes)) - return Success; - - pPort->pScrn = pScrn; - pPort->pDraw = pDraw; - - if (clipBoxes) - { - if (!pPort->clipBoxes) - pPort->clipBoxes = RegionCreate (NULL, 1); - - XDBG_RETURN_VAL_IF_FAIL (pPort->clipBoxes != NULL, BadAlloc); - - RegionCopy (pPort->clipBoxes, clipBoxes); - } - - XDBG_TRACE (MVA, "pDraw(0x%x, %dx%d). \n", pDraw->id, pDraw->width, pDraw->height); - - return Success; -} - -static int -_secVirtualVideoGetOutBufferIndex (SECPortPrivPtr pPort) -{ - if (!pPort->outbuf) - return -1; - - pPort->outbuf_index++; - if (pPort->outbuf_index >= pPort->outbuf_num) - pPort->outbuf_index = 0; - - return pPort->outbuf_index; -} - -static int -_secVirtualVideoSendPortNotify (SECPortPrivPtr pPort, SECPortAttrAtom paa, INT32 value) -{ - SECVideoPortInfo *info; - Atom atom = None; - - XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadValue); - - info = _port_info (pPort->pDraw); - XDBG_RETURN_VAL_IF_FAIL (info != NULL, BadValue); - XDBG_RETURN_VAL_IF_FAIL (info->pp != NULL, BadValue); - - atom = _secVideoGetPortAtom (paa); - XDBG_RETURN_VAL_IF_FAIL (atom != None, BadValue); - - XDBG_TRACE (MVA, "paa(%d), value(%d)\n", paa, value); - - return XvdiSendPortNotify (info->pp, atom, value); -} - -static Bool -_secVirtualVideoComposite (SECVideoBuf *src, SECVideoBuf *dst, - int src_x, int src_y, int src_w, int src_h, - int dst_x, int dst_y, int dst_w, int dst_h, - Bool composite, int rotate) -{ - xRectangle src_rect = {0,}, dst_rect = {0,}; - - XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src->bo[0] != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst->bo[0] != NULL, FALSE); - XDBG_RETURN_VAL_IF_FAIL (src->pitches[0] > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (dst->pitches[0] > 0, FALSE); - XDBG_RETURN_VAL_IF_FAIL (IS_RGB (src->id), FALSE); - XDBG_RETURN_VAL_IF_FAIL (IS_RGB (dst->id), FALSE); - - XDBG_DEBUG (MVA, "comp(%d) src : %ld %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %ld %c%c%c%c %dx%d (%d,%d %dx%d)\n", - composite, src->stamp, FOURCC_STR (src->id), src->width, src->height, - src_x, src_y, src_w, src_h, - dst->stamp, FOURCC_STR (dst->id), dst->width, dst->height, - dst_x, dst_y, dst_w, dst_h); - - src_rect.x = src_x; - src_rect.y = src_y; - src_rect.width = src_w; - src_rect.height = src_h; - dst_rect.x = dst_x; - dst_rect.y = dst_y; - dst_rect.width = dst_w; - dst_rect.height = dst_h; - - secUtilConvertBos (src->pScrn, - src->bo[0], src->width, src->height, &src_rect, src->pitches[0], - dst->bo[0], dst->width, dst->height, &dst_rect, dst->pitches[0], - composite, rotate); - - return TRUE; -} - -static int -_secVirtualVideoCompositeExtLayers (SECPortPrivPtr pPort) -{ - SECVideoBuf *dst_buf = NULL; - SECLayer *lower_layer = NULL; - SECLayer *upper_layer = NULL; - SECVideoBuf *ui_buf = NULL; - xRectangle rect = {0,}; - int index; - Bool comp = FALSE; - - index = _secVirtualVideoGetOutBufferIndex (pPort); - if (index < 0) - { - XDBG_WARNING (MVA, "all out buffers are in use.\n"); - return FALSE; - } - - lower_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1); - if (lower_layer) - { - SECVideoBuf *lower_buf = secLayerGetBuffer (lower_layer); - - if (lower_buf && !lower_buf->secure && VBUF_IS_VALID (lower_buf)) - { - /* In case of virtual, lower layer already has full-size. */ - dst_buf = lower_buf; - comp = TRUE; - } - } - - if (!dst_buf) - { - if (!_secVirtualVideoEnsureDstBuffer (pPort)) - return FALSE; - - dst_buf = pPort->dstbuf; - } - - /* before compositing, flush all */ - secUtilCacheFlush (pPort->pScrn); - - ui_buf = _secVirtualVideoGetUIBuffer (pPort, DRM_MODE_CONNECTOR_VIRTUAL); - if (ui_buf) - { - XDBG_DEBUG (MVA, "ui : %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %c%c%c%c %dx%d (%d,%d %dx%d)\n", - FOURCC_STR (ui_buf->id), - ui_buf->width, ui_buf->height, - ui_buf->crop.x, ui_buf->crop.y, - ui_buf->crop.width, ui_buf->crop.height, - FOURCC_STR (dst_buf->id), - dst_buf->width, dst_buf->height, - 0, 0, - dst_buf->width, dst_buf->height); - - if (!_secVirtualVideoComposite (ui_buf, dst_buf, - ui_buf->crop.x, ui_buf->crop.y, - ui_buf->crop.width, ui_buf->crop.height, - 0, 0, - dst_buf->width, dst_buf->height, - comp, 0)) - { - secUtilVideoBufferUnref (ui_buf); - return FALSE; - } - - comp = TRUE; - } - - upper_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_UPPER); - if (upper_layer) - { - SECVideoBuf *upper_buf = secLayerGetBuffer (upper_layer); - - if (upper_buf && VBUF_IS_VALID (upper_buf)) - { - secLayerGetRect (upper_layer, &upper_buf->crop, &rect); - - XDBG_DEBUG (MVA, "upper : %c%c%c%c %dx%d (%d,%d %dx%d) => dst : %c%c%c%c %dx%d (%d,%d %dx%d)\n", - FOURCC_STR (upper_buf->id), - upper_buf->width, upper_buf->height, - upper_buf->crop.x, upper_buf->crop.y, - upper_buf->crop.width, upper_buf->crop.height, - FOURCC_STR (dst_buf->id), - dst_buf->width, dst_buf->height, - rect.x, rect.y, rect.width, rect.height); - - _secVirtualVideoComposite (upper_buf, dst_buf, - upper_buf->crop.x, upper_buf->crop.y, - upper_buf->crop.width, upper_buf->crop.height, - rect.x, rect.y, rect.width, rect.height, - comp, 0); - } - } - - dst_buf->crop.x = 0; - dst_buf->crop.y = 0; - dst_buf->crop.width = dst_buf->width; - dst_buf->crop.height = dst_buf->height; - - XDBG_RETURN_VAL_IF_FAIL (pPort->outbuf[index] != NULL, FALSE); - - pPort->outbuf[index]->crop.x = 0; - pPort->outbuf[index]->crop.y = 0; - pPort->outbuf[index]->crop.width = pPort->outbuf[index]->width; - pPort->outbuf[index]->crop.height = pPort->outbuf[index]->height; - _secVirtualVideoComposite (dst_buf, pPort->outbuf[index], - 0, 0, dst_buf->width, dst_buf->height, - 0, 0, pPort->outbuf[index]->width, pPort->outbuf[index]->height, - FALSE, 0); - - _secVirtualVideoDraw (pPort, pPort->outbuf[index]); - - if (ui_buf) - secUtilVideoBufferUnref (ui_buf); - - return TRUE; -} - -static void -_secVirtualVideoCompositeSubtitle (SECPortPrivPtr pPort, SECVideoBuf *vbuf) -{ - SECLayer *subtitle_layer; - SECVideoBuf *subtitle_vbuf; - xRectangle src_rect; - xRectangle dst_rect; - - subtitle_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_UPPER); - if (!subtitle_layer) - return; - - subtitle_vbuf = secLayerGetBuffer (subtitle_layer); - if (!subtitle_vbuf || !VBUF_IS_VALID (subtitle_vbuf)) - return; - - CLEAR (src_rect); - CLEAR (dst_rect); - secLayerGetRect (subtitle_layer, &src_rect, &dst_rect); - - XDBG_DEBUG (MVA, "subtitle : %dx%d (%d,%d %dx%d) => %dx%d (%d,%d %dx%d)\n", - subtitle_vbuf->width, subtitle_vbuf->height, - src_rect.x, src_rect.y, src_rect.width, src_rect.height, - vbuf->width, vbuf->height, - dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height); - - _secVirtualVideoComposite (subtitle_vbuf, vbuf, - src_rect.x, src_rect.y, src_rect.width, src_rect.height, - dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height, - TRUE, 0); -} - -static CARD32 -_secVirtualVideoRetireTimeout (OsTimerPtr timer, CARD32 now, pointer arg) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) arg; - SECModePtr pSecMode; - int diff; - - if (!pPort) - return 0; - - pSecMode = (SECModePtr)SECPTR (pPort->pScrn)->pSecMode; - - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - XDBG_ERROR (MVA, "capture(%d) mode(%d) conn(%d) type(%d) status(%x). \n", - pPort->capture, pSecMode->set_mode, pSecMode->conn_mode, - pPort->data_type, pPort->status); - - diff = GetTimeInMillis () - pPort->retire_time; - XDBG_ERROR (MVA, "failed : +++ Retire Timeout!! diff(%d)\n", diff); - - return 0; -} - -static void -_secVirtualVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr)data; - SECVideoBuf *vbuf = (SECVideoBuf*)type_data; - SECVideoBuf *black; - - secLayerRemoveNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc); - - if (type == LAYER_DESTROYED || type != LAYER_BUF_CHANGED || !vbuf) - goto fail_layer_noti; - - XDBG_GOTO_IF_FAIL (VBUF_IS_VALID (vbuf), fail_layer_noti); - XDBG_GOTO_IF_FAIL (vbuf->showing == FALSE, fail_layer_noti); - - XDBG_DEBUG (MVA, "------------------------------\n"); - - _secVirtualVideoCompositeSubtitle (pPort, vbuf); - _secVirtualVideoDraw (pPort, vbuf); - XDBG_DEBUG (MVA, "------------------------------...\n"); - - return; - -fail_layer_noti: - black = _secVirtualVideoGetBlackBuffer (pPort); - XDBG_TRACE (MVA, "black buffer(%d) return: layer noti. type(%d), vbuf(%p)\n", - (black)?black->keys[0]:0, type, vbuf); - _secVirtualVideoDraw (pPort, black); -} - -static int -_secVirtualVideoPutStill (SECPortPrivPtr pPort) -{ - SECModePtr pSecMode = (SECModePtr)SECPTR (pPort->pScrn)->pSecMode; - SECVideoBuf *pix_buf = NULL; - SECVideoBuf *ui_buf = NULL; - Bool comp; - int i; - CARD32 start = GetTimeInMillis (); - - XDBG_GOTO_IF_FAIL (pPort->secure == FALSE, done_still); - - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - comp = FALSE; - - pix_buf = _secVirtualVideoGetDrawableBuffer (pPort); - XDBG_GOTO_IF_FAIL (pix_buf != NULL, done_still); - - ui_buf = _secVirtualVideoGetUIBuffer (pPort, DRM_MODE_CONNECTOR_LVDS); - XDBG_GOTO_IF_FAIL (ui_buf != NULL, done_still); - - tbm_bo_map (pix_buf->bo[0], TBM_DEVICE_2D, TBM_OPTION_WRITE); - - for (i = LAYER_LOWER2; i < LAYER_MAX; i++) - { - SECVideoBuf *upper = NULL; - xRectangle src_rect, dst_rect; - int vwidth = pSecMode->main_lcd_mode.hdisplay; - int vheight = pSecMode->main_lcd_mode.vdisplay; - int rotate; - - if (i == LAYER_DEFAULT) - { - upper = secUtilVideoBufferRef (ui_buf); - tbm_bo_map (upper->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ); - - src_rect.x = src_rect.y = 0; - src_rect.width = ui_buf->width; - src_rect.height = ui_buf->height; - - dst_rect.x = dst_rect.y = 0; - dst_rect.width = ui_buf->width; - dst_rect.height = ui_buf->height; - - rotate = 0; - } - else - { - SECLayer *layer = secLayerFind (LAYER_OUTPUT_LCD, (SECLayerPos)i); - int off_x = 0, off_y = 0; - SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv; - - if (!layer) - continue; - - upper = secUtilVideoBufferRef (secLayerGetBuffer (layer)); - if (!upper || !VBUF_IS_VALID (upper)) - continue; - - secLayerGetRect (layer, &src_rect, &dst_rect); - secLayerGetOffset (layer, &off_x, &off_y); - dst_rect.x += off_x; - dst_rect.y += off_y; - - rotate = (360 - pVideo->screen_rotate_degree) % 360; - - /* rotate upper_rect */ - secUtilRotateArea (&vwidth, &vheight, &dst_rect, rotate); - } - - /* scale upper_rect */ - secUtilScaleRect (vwidth, vheight, pix_buf->width, pix_buf->height, &dst_rect); - - XDBG_DEBUG (MVA, "%dx%d(%d,%d, %dx%d) => %dx%d(%d,%d, %dx%d) :comp(%d) r(%d)\n", - upper->width, upper->height, - src_rect.x, src_rect.y, src_rect.width, src_rect.height, - pix_buf->width, pix_buf->height, - dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height, - comp, rotate); - - if (!_secVirtualVideoComposite (upper, pix_buf, - src_rect.x, src_rect.y, - src_rect.width, src_rect.height, - dst_rect.x, dst_rect.y, - dst_rect.width, dst_rect.height, - comp, rotate)) - { - if (i == LAYER_DEFAULT) - tbm_bo_unmap (upper->bo[0]); - tbm_bo_unmap (pix_buf->bo[0]); - goto done_still; - } - - if (i == LAYER_DEFAULT) - tbm_bo_unmap (upper->bo[0]); - - secUtilVideoBufferUnref (upper); - - comp = TRUE; - } - - XDBG_TRACE (MVA, "make still: %ldms\n", GetTimeInMillis() - start); - - tbm_bo_unmap (pix_buf->bo[0]); - -done_still: - - secUtilCacheFlush (pPort->pScrn); - - if (pix_buf) - secUtilVideoBufferUnref (pix_buf); - if (ui_buf) - secUtilVideoBufferUnref (ui_buf); - - DamageDamageRegion (pPort->pDraw, pPort->clipBoxes); - pPort->need_damage = FALSE; - - SECPtr pSec = SECPTR (pPort->pScrn); - if ((pSec->dump_mode & XBERC_DUMP_MODE_CA) && pSec->dump_info) - { - PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw); - char file[128]; - static int i; - snprintf (file, sizeof(file), "capout_still_%03d.bmp", i++); - secUtilDoDumpPixmaps (pSec->dump_info, pPixmap, file); - } - - return Success; -} - -static int -_secVirtualVideoPutWB (SECPortPrivPtr pPort) -{ - SECPtr pSec = SECPTR (pPort->pScrn); - - XDBG_RETURN_VAL_IF_FAIL (pPort->pScrn != NULL, BadImplementation); - XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadImplementation); - - if (!_secVirtualVideoEnsureOutBuffers (pPort->pScrn, pPort, pPort->id, pPort->pDraw->width, pPort->pDraw->height)) - return BadAlloc; - - if (!pPort->wb) - { - int scanout; - - if (secWbIsOpened ()) - { - XDBG_ERROR (MVA, "Fail : wb open. \n"); - return BadRequest; - } - - if (pPort->display == DISPLAY_LCD) - scanout = FALSE; - else - scanout = pSec->scanout; - - /* For capture mode, we don't need to create contiguous buffer. - * Rotation should be considered when wb begins. - */ - pPort->wb = secWbOpen (pPort->pScrn, pPort->id, - pPort->pDraw->width, pPort->pDraw->height, - scanout, 60, - (pPort->rotate_off)?FALSE:TRUE); - XDBG_RETURN_VAL_IF_FAIL (pPort->wb != NULL, BadAlloc); - - secWbSetBuffer (pPort->wb, pPort->outbuf, pPort->outbuf_num); - - XDBG_TRACE (MVA, "wb(%p) start. \n", pPort->wb); - - if (!secWbStart (pPort->wb)) - { - secWbClose (pPort->wb); - pPort->wb = NULL; - return BadAlloc; - } - secWbAddNotifyFunc (pPort->wb, WB_NOTI_STOP, - _secVirtualVideoWbStopFunc, pPort); - secWbAddNotifyFunc (pPort->wb, WB_NOTI_IPP_EVENT, - _secVirtualVideoWbDumpFunc, pPort); - if (pPort->capture == CAPTURE_MODE_STILL) - secWbAddNotifyFunc (pPort->wb, WB_NOTI_IPP_EVENT_DONE, - _secVirtualVideoWbDumpDoneFunc, pPort); - secWbAddNotifyFunc (pPort->wb, WB_NOTI_CLOSED, - _secVirtualVideoWbCloseFunc, pPort); - } - - /* no available buffer, need to return buffer by client. */ - if (!secWbIsRunning ()) - { - XDBG_WARNING (MVA, "wb is stopped.\n"); - return BadRequest; - } - - /* no available buffer, need to return buffer by client. */ - if (!secWbCanDequeueBuffer (pPort->wb)) - { - XDBG_TRACE (MVA, "no available buffer\n"); - return BadRequest; - } - - XDBG_TRACE (MVA, "wb(%p), running(%d). \n", pPort->wb, secWbIsRunning ()); - - return Success; -} - -static int -_secVirtualVideoPutVideoOnly (SECPortPrivPtr pPort) -{ - SECLayer *layer; - SECVideoBuf *vbuf; - int i; - - XDBG_RETURN_VAL_IF_FAIL (pPort->display == DISPLAY_EXTERNAL, BadRequest); - XDBG_RETURN_VAL_IF_FAIL (pPort->capture == CAPTURE_MODE_STREAM, BadRequest); - - layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1); - if (!layer) - return BadRequest; - - for (i = 0; i < pPort->outbuf_num; i++) - { - if (!pPort->outbuf[i]->showing) - break; - } - - if (i == pPort->outbuf_num) - { - XDBG_ERROR (MVA, "now all buffers are in showing\n"); - return BadRequest; - } - - vbuf = secLayerGetBuffer (layer); - /* if layer is just created, vbuf can't be null. */ - if (!vbuf || !VBUF_IS_VALID (vbuf)) - { - SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort); - XDBG_RETURN_VAL_IF_FAIL (black != NULL, BadRequest); - - XDBG_TRACE (MVA, "black buffer(%d) return: vbuf invalid\n", black->keys[0]); - _secVirtualVideoDraw (pPort, black); - return Success; - } - - /* Wait the next frame if it's same as previous one */ - if (_secVirtualVideoFindReturnBuf (pPort, vbuf->keys[0])) - { - secLayerAddNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc, pPort); - XDBG_DEBUG (MVA, "wait notify.\n"); - return Success; - } - - _secVirtualVideoCompositeSubtitle (pPort, vbuf); - _secVirtualVideoDraw (pPort, vbuf); - - return Success; -} - -static int -_secVirtualVideoPutExt (SECPortPrivPtr pPort) -{ - if (_secVirtualVideoCompositeExtLayers (pPort)) - return Success; - - return BadRequest; -} - -static int -SECVirtualVideoGetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 *value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _secVideoGetPortAtom (PAA_FORMAT)) - { - *value = pPort->id; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_CAPTURE)) - { - *value = pPort->capture; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_DISPLAY)) - { - *value = pPort->display; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_ROTATE_OFF)) - { - *value = pPort->rotate_off; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_DATA_TYPE)) - { - *value = pPort->data_type; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_SECURE)) - { - *value = pPort->secure; - return Success; - } - return BadMatch; -} - -static int -SECVirtualVideoSetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 value, - pointer data) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (attribute == _secVideoGetPortAtom (PAA_FORMAT)) - { - if (!_secVirtualVideoIsSupport ((unsigned int)value)) - { - XDBG_ERROR (MVA, "id(%c%c%c%c) not supported.\n", FOURCC_STR (value)); - return BadRequest; - } - - pPort->id = (unsigned int)value; - XDBG_DEBUG (MVA, "id(%d) \n", value); - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_CAPTURE)) - { - if (value < CAPTURE_MODE_NONE || value >= CAPTURE_MODE_MAX) - { - XDBG_ERROR (MVA, "capture value(%d) is out of range\n", value); - return BadRequest; - } - - pPort->capture = value; - XDBG_DEBUG (MVA, "capture(%d) \n", pPort->capture); - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_DISPLAY)) - { - XDBG_DEBUG (MVA, "display: %d \n", pPort->display); - pPort->display = value; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_ROTATE_OFF)) - { - XDBG_DEBUG (MVA, "ROTATE_OFF: %d! \n", pPort->rotate_off); - pPort->rotate_off = value; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_SECURE)) - { - XDBG_TRACE (MVA, "not implemented 'secure' attr. (%d) \n", pPort->secure); -// pPort->secure = value; - return Success; - } - else if (attribute == _secVideoGetPortAtom (PAA_RETBUF)) - { - RetBufInfo *info; - - if (!pPort->pDraw) - return Success; - - info = _secVirtualVideoFindReturnBuf (pPort, value); - if (!info) - { - XDBG_WARNING (MVA, "wrong gem name(%d) returned\n", value); - return Success; - } - - if (info->vbuf && info->vbuf->need_reset) - secUtilClearVideoBuffer (info->vbuf); - - _secVirtualVideoRemoveReturnBuf (pPort, info); -#if 0 - _buffers (pPort); - ErrorF ("[Xorg] retbuf : %ld (%s)\n", value, buffers); -#endif - - return Success; - } - - return Success; -} - -/* vid_w, vid_h : no meaning for us. not using. - * dst_w, dst_h : size to hope for PutStill. - * p_w, p_h : real size for PutStill. - */ -static void -SECVirtualVideoQueryBestSize (ScrnInfoPtr pScrn, - Bool motion, - short vid_w, short vid_h, - short dst_w, short dst_h, - unsigned int *p_w, unsigned int *p_h, - pointer data) -{ - SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode; - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - if (pPort->display == DISPLAY_EXTERNAL) - { - if (p_w) - *p_w = pSecMode->ext_connector_mode.hdisplay; - if (p_h) - *p_h = pSecMode->ext_connector_mode.vdisplay; - } - else - { - if (p_w) - *p_w = (unsigned int)dst_w; - if (p_h) - *p_h = (unsigned int)dst_h; - } -} - -/* vid_x, vid_y, vid_w, vid_h : no meaning for us. not using. - * drw_x, drw_y, dst_w, dst_h : no meaning for us. not using. - * Only pDraw's size is used. - */ -static int -SECVirtualVideoPutStill (ScrnInfoPtr pScrn, - short vid_x, short vid_y, short drw_x, short drw_y, - short vid_w, short vid_h, short drw_w, short drw_h, - RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ) -{ - SECPtr pSec = SECPTR (pScrn); - SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode; - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - int ret = BadRequest; - - XDBG_GOTO_IF_FAIL (pPort->need_damage == FALSE, put_still_fail); - - if (pPort->capture == CAPTURE_MODE_STILL && pPort->display == DISPLAY_EXTERNAL) - { - XDBG_ERROR (MVA, "not implemented to capture still of external display. \n"); - return BadImplementation; - } - - if (pPort->display == DISPLAY_EXTERNAL && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL) - { - XDBG_ERROR (MVA, "virtual display not connected!. \n"); - return BadRequest; - } - -#if 0 - ErrorF ("[Xorg] PutStill\n"); -#endif - - XDBG_DEBUG (MVA, "*************************************** \n"); - - if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CA) - { - CARD32 cur, sub; - cur = GetTimeInMillis (); - sub = cur - pPort->prev_time; - pPort->prev_time = cur; - ErrorF ("getstill interval : %6ld ms\n", sub); - } - - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - if (pSec->pVideoPriv->no_retbuf) - _secVirtualVideoRemoveReturnBufAll (pPort); - - pPort->retire_timer = TimerSet (pPort->retire_timer, 0, 4000, - _secVirtualVideoRetireTimeout, - pPort); - XDBG_GOTO_IF_FAIL (pPort->id > 0, put_still_fail); - - pPort->status = 0; - pPort->retire_time = GetTimeInMillis (); - - ret = _secVirtualVideoPreProcess (pScrn, pPort, clipBoxes, pDraw); - XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail); - - ret = _secVirtualVideoAddDrawableEvent (pPort); - XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail); - - /* check drawable */ - XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_PIXMAP, BadPixmap); - - if (!pPort->putstill_on) - { - pPort->putstill_on = TRUE; - XDBG_SECURE (MVA, "pPort(%d) putstill on. secure(%d), capture(%d), format(%c%c%c%c)\n", - pPort->index, pPort->secure, pPort->capture, FOURCC_STR (pPort->id), 60); - } - - pPort->need_damage = TRUE; - - if (pPort->capture == CAPTURE_MODE_STILL && pPort->display == DISPLAY_LCD) - { - XDBG_DEBUG (MVA, "still mode.\n"); - - if (1) - ret = _secVirtualVideoPutStill (pPort); - else - /* camera buffer can't be mapped. we should use WB to capture screen */ - ret = _secVirtualVideoPutWB (pPort); - - XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail); - } - else if (pPort->capture == CAPTURE_MODE_STREAM && pPort->display == DISPLAY_LCD) - { - XDBG_DEBUG (MVA, "stream mode.\n"); - if (SECPTR (pScrn)->isLcdOff) - { - XDBG_TRACE (MVA, "DPMS status: off. \n"); - ret = BadRequest; - goto put_still_fail; - } - - ret = _secVirtualVideoPutWB (pPort); - if (ret != Success) - goto put_still_fail; - } - else if (pPort->capture == CAPTURE_MODE_STREAM && pPort->display == DISPLAY_EXTERNAL) - { - int old_data_type = pPort->data_type; - SECVideoBuf *black; - - switch (pSecMode->set_mode) - { - case DISPLAY_SET_MODE_OFF: - XDBG_DEBUG (MVA, "display mode is off. \n"); - black = _secVirtualVideoGetBlackBuffer (pPort); - XDBG_RETURN_VAL_IF_FAIL (black != NULL, BadRequest); - XDBG_DEBUG (MVA, "black buffer(%d) return: lcd off\n", black->keys[0]); - _secVirtualVideoDraw (pPort, black); - ret = Success; - goto put_still_fail; - - case DISPLAY_SET_MODE_CLONE: - pPort->data_type = _secVirtualVideoDataType (pPort); - - if (pPort->data_type != old_data_type) - _secVirtualVideoSendPortNotify (pPort, PAA_DATA_TYPE, pPort->data_type); - - if (pPort->data_type == DATA_TYPE_UI) - { - XDBG_DEBUG (MVA, "clone mode.\n"); - - ret = _secVirtualVideoPutWB (pPort); - if (ret != Success) - goto put_still_fail; - } - else - { - XDBG_DEBUG (MVA, "video only mode.\n"); - ret = _secVirtualVideoPutVideoOnly (pPort); - if (ret != Success) - goto put_still_fail; - } - break; - - case DISPLAY_SET_MODE_EXT: - XDBG_DEBUG (MVA, "desktop mode.\n"); - - if (pSecMode->ext_connector_mode.hdisplay != pDraw->width || - pSecMode->ext_connector_mode.vdisplay != pDraw->height) - { - XDBG_ERROR (MVA, "drawble should have %dx%d size. mode(%d), conn(%d)\n", - pSecMode->ext_connector_mode.hdisplay, - pSecMode->ext_connector_mode.vdisplay, - pSecMode->set_mode, pSecMode->conn_mode); - ret = BadRequest; - goto put_still_fail; - } - - ret = _secVirtualVideoPutExt (pPort); - if (ret != Success) - goto put_still_fail; - break; - - default: - break; - } - } - else - { - XDBG_NEVER_GET_HERE (MVA); - ret = BadRequest; - goto put_still_fail; - } - - XDBG_DEBUG (MVA, "***************************************.. \n"); - return Success; - -put_still_fail: - pPort->need_damage = FALSE; - - if (pPort->retire_timer) - { - TimerFree (pPort->retire_timer); - pPort->retire_timer = NULL; - } - - XDBG_DEBUG (MVA, "***************************************.. \n"); - - return ret; -} - -static void -SECVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit) -{ - SECPortPrivPtr pPort = (SECPortPrivPtr) data; - - _secVirtualVideoStreamOff (pPort); -} - -static int -SECVirtualVideoDDPutStill (ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h) -{ - SECVideoPortInfo *info = _port_info (pDraw); - int ret; - - if (info) - { - info->client = client; - info->pp = pPort; - } - - ret = ddPutStill (client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - return ret; -} - -XF86VideoAdaptorPtr -secVideoSetupVirtualVideo (ScreenPtr pScreen) -{ - XF86VideoAdaptorPtr pAdaptor; - SECPortPrivPtr pPort; - int i; - - pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) + - (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT); - if (!pAdaptor) - return NULL; - - dummy_encoding[0].width = pScreen->width; - dummy_encoding[0].height = pScreen->height; - - pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvStillMask; - pAdaptor->flags = 0; - pAdaptor->name = "SEC Virtual Video"; - pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec); - pAdaptor->pEncodings = dummy_encoding; - pAdaptor->nFormats = NUM_FORMATS; - pAdaptor->pFormats = formats; - pAdaptor->nPorts = SEC_MAX_PORT; - pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]); - - pPort = (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]); - - for (i = 0; i < SEC_MAX_PORT; i++) - { - pAdaptor->pPortPrivates[i].ptr = &pPort[i]; - pPort[i].index = i; - pPort[i].id = FOURCC_RGB32; - pPort[i].outbuf_index = -1; - - xorg_list_init (&pPort[i].retbuf_info); - } - - pAdaptor->nAttributes = NUM_ATTRIBUTES; - pAdaptor->pAttributes = attributes; - pAdaptor->nImages = NUM_IMAGES; - pAdaptor->pImages = images; - - pAdaptor->GetPortAttribute = SECVirtualVideoGetPortAttribute; - pAdaptor->SetPortAttribute = SECVirtualVideoSetPortAttribute; - pAdaptor->QueryBestSize = SECVirtualVideoQueryBestSize; - pAdaptor->PutStill = SECVirtualVideoPutStill; - pAdaptor->StopVideo = SECVirtualVideoStop; - - if (!_secVirtualVideoRegisterEventResourceTypes ()) - { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n"); - return NULL; - } - - return pAdaptor; -} - -void -secVirtualVideoDpms (ScrnInfoPtr pScrn, Bool on) -{ - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[1]; - int i; - - if (on) - return; - - for (i = 0; i < SEC_MAX_PORT; i++) - { - SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; - - if (pPort->wb) - { - secWbClose (pPort->wb); - pPort->wb = NULL; - } - } -} - -void -secVirtualVideoReplacePutStillFunc (ScreenPtr pScreen) -{ - int i; - - XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates, - XvGetScreenKey()); - if (!xvsp) - return; - - for (i = 1; i < xvsp->nAdaptors; i++) - { - XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; - if (pAdapt->ddPutStill) - { - ddPutStill = pAdapt->ddPutStill; - pAdapt->ddPutStill = SECVirtualVideoDDPutStill; - break; - } - } - - if (!dixRegisterPrivateKey (VideoVirtualPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo))) - return; - if (!dixRegisterPrivateKey (VideoVirtualPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo))) - return; -} - -void -secVirtualVideoGetBuffers (ScrnInfoPtr pScrn, int id, int width, int height, SECVideoBuf ***vbufs, int *bufnum) -{ - SECPtr pSec = (SECPtr) pScrn->driverPrivate; - XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[1]; - int i; - - for (i = 0; i < SEC_MAX_PORT; i++) - { - SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; - - if (pPort->pDraw) - { - XDBG_RETURN_IF_FAIL (pPort->id == id); - XDBG_RETURN_IF_FAIL (pPort->pDraw->width == width); - XDBG_RETURN_IF_FAIL (pPort->pDraw->height == height); - } - - if (!_secVirtualVideoEnsureOutBuffers (pScrn, pPort, id, width, height)) - return; - - *vbufs = pPort->outbuf; - *bufnum = pPort->outbuf_num; - } -} diff --git a/src/xv/xv_types.h b/src/xv/xv_types.h index e82b4e4..32dc720 100644 --- a/src/xv/xv_types.h +++ b/src/xv/xv_types.h @@ -50,23 +50,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XV_BUF_TYPE_LEGACY 1 /* Data structure for XvPutImage / XvShmPutImage */ -typedef struct -{ - unsigned int _header; /* for internal use only */ - unsigned int _version; /* for internal use only */ +typedef struct { + unsigned int _header; /* for internal use only */ + unsigned int _version; /* for internal use only */ unsigned int YBuf; unsigned int CbBuf; unsigned int CrBuf; unsigned int BufType; -} XV_DATA, * XV_DATA_PTR; +} XV_DATA, *XV_DATA_PTR; static void #ifdef __GNUC__ -__attribute__ ((unused)) + __attribute__ ((unused)) #endif -XV_INIT_DATA (XV_DATA_PTR data) + XV_INIT_DATA(XV_DATA_PTR data) { data->_header = XV_DATA_HEADER; data->_version = XV_DATA_VERSION; @@ -74,9 +73,9 @@ XV_INIT_DATA (XV_DATA_PTR data) static int #ifdef __GNUC__ -__attribute__ ((unused)) + __attribute__ ((unused)) #endif -XV_VALIDATE_DATA (XV_DATA_PTR data) + XV_VALIDATE_DATA(XV_DATA_PTR data) { if (data->_header != XV_DATA_HEADER) return XV_HEADER_ERROR; diff --git a/template.spec b/template.spec new file mode 100644 index 0000000..23a5039 --- /dev/null +++ b/template.spec @@ -0,0 +1,95 @@ +# >> macros +# << macros +?include_ftests? +%bcond_with ftests=1 + +Name: xorg-x11-drv-exynos +Summary: X.Org X server driver for exynos +Version: 1.0.0 +Release: 3 +ExclusiveArch: %arm +Group: System/X Hardware Support +License: MIT +Source0: %{name}-%{version}.tar.gz + +BuildRequires: prelink +BuildRequires: pkgconfig(xorg-macros) +BuildRequires: pkgconfig(xorg-server) +BuildRequires: pkgconfig(xproto) +BuildRequires: pkgconfig(fontsproto) +BuildRequires: pkgconfig(randrproto) +BuildRequires: pkgconfig(renderproto) +BuildRequires: pkgconfig(videoproto) +BuildRequires: pkgconfig(resourceproto) +BuildRequires: pkgconfig(libudev) +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(xdbg) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(libpng) +BuildRequires: pkgconfig(dri3proto) +BuildRequires: pkgconfig(presentproto) +BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(xcb) +BuildRequires: pkgconfig(xcb-util) +BuildRequires: pkgconfig(xrandr) +BuildRequires: pkgconfig(hwaproto) + +%description +This package provides the driver for the Samsung display device exynos + +%prep +%setup -q + + +%build +rm -rf %{buildroot} + +%if %{?tizen_profile_name} == "wearable" +export CFLAGS+=" -D_F_WEARABLE_FEATURE_ " +%endif + +%if %{with ftests} +export FTESTS="--enable-ftests" +%endif + +?SUBSTITUTE_PARAMETERS? + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp -af COPYING %{buildroot}/usr/share/license/%{name} +%make_install + +%if %{without ftests} + # >> install post + execstack -c %{buildroot}%{_libdir}/xorg/modules/drivers/exynos_drv.so + # << install post +%endif + +%files +%defattr(-,root,root,-) +%if %{without ftests} + %{_libdir}/xorg/modules/drivers/*.so + %{_datadir}/man/man4/* + /usr/share/license/%{name} +%else + /usr/share/license/%{name} + + # to build functional tests simple add option to gbs "--define with_ftests=1" + # Note: if you build functional tests, ddx driver willn't be built + %{_libdir}/libdri2_dri3.so + %{_bindir}/test_xv + %{_bindir}/hwc-sample + %{_bindir}/square-bubbles + %{_bindir}/clock + %{_bindir}/snowflake + %{_bindir}/wander-stripe + %{_bindir}/hwa_sample + %{_bindir}/pixmap_copy + %{_datadir}/launch.sh + +%post + chmod +x %{_datadir}/launch.sh +%endif diff --git a/tests/functional/Makefile.am b/tests/functional/Makefile.am new file mode 100644 index 0000000..1990d80 --- /dev/null +++ b/tests/functional/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = xv_test hwc_test hwa_test pixmap_copy_test diff --git a/tests/functional/hwa_test/Makefile.am b/tests/functional/hwa_test/Makefile.am new file mode 100644 index 0000000..51df582 --- /dev/null +++ b/tests/functional/hwa_test/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_FT + bin_PROGRAMS = hwa_sample + +hwa_sample_CFLAGS = $(HWA_TEST_CFLAGS) +hwa_sample_LDADD = $(HWA_TEST_LIBS) +hwa_sample_SOURCES = \ +@top_srcdir@/tests/functional/hwa_test/hwa_sample.c + +endif diff --git a/tests/functional/hwa_test/hwa_sample.c b/tests/functional/hwa_test/hwa_sample.c new file mode 100644 index 0000000..7fc6ee2 --- /dev/null +++ b/tests/functional/hwa_test/hwa_sample.c @@ -0,0 +1,531 @@ + +/* Standart headers */ +#include <stdio.h> +#include <stdlib.h> + +#include <string.h> +#include <getopt.h> + +/* X Server's headers */ +#include <X11/Xlib.h> +#include <xcb/xcb.h> +#include <xcb/hwa.h> +#include <xcb/dri3.h> +#include <xcb/randr.h> + +#include "hwa_sample.h" + +void test_hwc( void ); + +xcb_connection_t *c; +xcb_generic_error_t *error; + +xcb_randr_crtc_t randr_crtc = 0; +char con_name[20] = {0,}; + +int main( int argc, char **argv ) +{ + int rez; + int option_index; + int enable; + int angle; + char *scale_params = NULL; + const char* short_options = "ic:r:a:x:s:h:o:"; + + const struct option long_options[] = + { + {"help",no_argument,NULL,'?'}, + {"info",no_argument,NULL,'i'}, + {"version",no_argument,NULL,'v'}, + {"cursore",required_argument,NULL,'c'}, + {"cursorr",required_argument,NULL,'r'}, + {"accessibility",required_argument,NULL,'a'}, + {"scale",required_argument,NULL,'x'}, + {"show",required_argument,NULL,'s'}, + {"hide",required_argument,NULL,'h'}, + {"output",required_argument,NULL,'o'}, + {NULL,0,NULL,0} + }; + + c = xcb_connect (NULL, NULL); + + while ( ( rez = getopt_long_only( argc,argv, short_options, long_options,&option_index ) ) != -1 ) + { + switch(rez) + { + case '?': + help(); + break; + + case 'i': + extensions_info(); + break; + + case 'v': + hwa_query_version(); + break; + + case 'c': + enable = atoi(optarg); + hwa_cursor_enable( enable ); + break; + + case 'r': + angle = atoi(optarg); + hwa_cursor_rotate( angle ); + break; + + case 'a': + enable = atoi(optarg); + hwa_accessibility( enable ); + + break; + + case 'x': + scale_params = (char *)calloc(30, sizeof( char ) ); + + enable = 0; + + optind--; + for( ;optind < argc; optind++) + { + if ( 2 == optind ) + enable = atoi(argv[optind]); + else + strcpy( scale_params, argv[optind] ); + } + + hwa_scale( enable, scale_params ); + free( scale_params ); + + break; + + case 's': + printf("show layer = %s\n",optarg); + hwa_show_layer(atoi(optarg)); + + break; + + case 'h': + printf("hide layer= %s\n",optarg); + hwa_hide_layer(atoi(optarg)); + break; + + /* + * TODO + * output selector need implement + * */ + case 'o': + printf("[%s] output chosen \n",optarg); + strcpy( con_name, optarg); + printf("con_name = [%s] \n",con_name); + break; + + default: + PRINT(4); + printf("ERROR: found unknown option\n\n"); + + help(); + break; + } + } + + xcb_disconnect(c); + + return 0; +} + +void extensions_info( void ) +{ + xcb_list_extensions_reply_t *rep; + xcb_query_extension_reply_t *q_rep; + + xcb_list_extensions_cookie_t ext_cookie; + xcb_query_extension_cookie_t query_c; + + ext_cookie = xcb_list_extensions( c ); + rep = xcb_list_extensions_reply( c, ext_cookie, &error ); + xcb_flush(c); + + + /* List all Extensions which X Server supports */ + printf( "\n-----------------------------------\n"); + + xcb_str_iterator_t str_iter = xcb_list_extensions_names_iterator( rep ); + + printf( "+++ index %d\n+++ %d\n", str_iter.index, str_iter.rem ); + + while (str_iter.rem) + { + printf("%d bytes: ", xcb_str_name_length(str_iter.data)); + fwrite(xcb_str_name(str_iter.data), 1, xcb_str_name_length(str_iter.data), stdout); + printf("\n"); + fixed_xcb_str_next(&str_iter); + } + + printf( "\n-----------------------------------\n"); + + /* Check does X Server support HWA */ + query_c = xcb_query_extension( c, 3, "HWA" ); + q_rep = xcb_query_extension_reply( c, query_c, &error ); + + printf( "\n-----------------------------------\n"); + printf( "Check HWA:\n" + "present: %d\n" + "major opcode: %d\n" + "first event: %d\n" + "first error: %d\n", + q_rep->present, + q_rep->major_opcode, + q_rep->first_event, + q_rep->first_error ); + + /* TODO process errors */ + + free(rep); + free(q_rep); + printf( "-----------------------------------\n"); +} + +void hwa_query_version( void ) +{ + xcb_hwa_query_version_cookie_t hwa_version_cookie; + xcb_hwa_query_version_reply_t *hwa_version_reply = NULL; + + /* 111 and 222 are just random numbers */ + hwa_version_cookie = xcb_hwa_query_version ( c, 111, 222 ); + xcb_flush(c); + + hwa_version_reply = xcb_hwa_query_version_reply( c, hwa_version_cookie, &error ); + + if(hwa_version_reply) + { + printf( "\n-----------------------------------\n"); + printf("Query Version:\n"); + printf("hwa_query_version: Call was ok\nmajor_version=%d\nminor_version=%d \n", + hwa_version_reply->major_version, + hwa_version_reply->minor_version ); + printf( "-----------------------------------\n"); + + free(hwa_version_reply); + } + else + { + printf("hwa_query_version: ERROR" ); + } + + +} + +void hwa_cursor_enable( int enable ) +{ + xcb_hwa_cursor_enable_cookie_t cursor_cookie; + xcb_hwa_cursor_enable_reply_t *cursor_enb_reply = NULL; + + cursor_cookie = xcb_hwa_cursor_enable_unchecked( c, enable ); + xcb_flush(c); + + cursor_enb_reply = xcb_hwa_cursor_enable_reply( c,cursor_cookie, &error); + + if(cursor_enb_reply) + { + printf( "\n-----------------------------------\n"); + printf("Cursor Enable:\n"); + printf("hwa_cursor_enable: Call was ok\nreply.status=%d \n", cursor_enb_reply->status ); + printf( "-----------------------------------\n"); + + free(cursor_enb_reply); + } + else + { + printf("hwa_cursor_enable: ERROR" ); + exit(1); + } +} + +void hwa_cursor_rotate( int angle ) +{ + xcb_hwa_cursor_rotate_cookie_t cursor_rotate_cookie; + xcb_hwa_cursor_rotate_reply_t *cursor_rot_reply = NULL; + + /*hwa_cursor_enable( ON );*/ + + randr_crtc = (xcb_randr_crtc_t) get_crtc_via_randr("LVDS1"); + + cursor_rotate_cookie = xcb_hwa_cursor_rotate_unchecked (c, randr_crtc, angle ); + xcb_flush(c); + cursor_rot_reply = xcb_hwa_cursor_rotate_reply ( c, cursor_rotate_cookie, &error); + + if(cursor_rot_reply) + { + printf( "\n-----------------------------------\n"); + printf("Cursor Rotate:\n"); + printf("hwa_cursor_rotate: Call was ok\nreply.status=%d, angle = %d \n ", cursor_rot_reply->status, angle ); + printf( "-----------------------------------\n"); + + free(cursor_rot_reply); + } + else + { + printf("hwa_cursor_rotate: ERROR" ); + } +} + +void hwa_accessibility( int enable ) +{ + xcb_hwa_screen_invert_negative_cookie_t hwa_scrn_invert_cookie = {0,}; + xcb_hwa_screen_invert_negative_reply_t *hwa_scrn_invert_reply = NULL; + + int crtc = get_crtc_via_randr("LVDS1"); + if (-1 == crtc) + { + printf ("Didn't find randr crtc!! :\n"); + exit (0); + } + + hwa_scrn_invert_cookie = xcb_hwa_screen_invert_negative( c, crtc, enable ); + xcb_flush(c); + + hwa_scrn_invert_reply = xcb_hwa_screen_invert_negative_reply( c, hwa_scrn_invert_cookie, &error ); + + if(hwa_scrn_invert_reply) + { + printf( "\n-----------------------------------\n"); + printf("Accessibility:\n"); + printf("hwa_accessibility: Call was ok\nreply.status=%d \n", hwa_scrn_invert_reply->status ); + printf( "-----------------------------------\n"); + + free(hwa_scrn_invert_reply); + } + else + { + printf("hwa_accessibility: ERROR" ); + } +} + +void hwa_scale( int enable, char* scale_param ) +{ + xcb_hwa_screen_scale_cookie_t hwa_scale_cookie; + xcb_hwa_screen_scale_reply_t *hwa_scale_reply; + + int x = 0, y = 0, width = 0, height = 0; + int crtc = -1; + + if( enable && !scale_param ) + { + printf( "hwa_scale: ERROR, parameters was not specified\n"); + help(); + exit(1); + } + else if ( enable && scale_param ) + { + int *xywh = pars_params( scale_param ); + + printf("x=%d y=%d w=%d h=%d\n", + xywh[0], + xywh[1], + xywh[2], + xywh[3] ); + + int i = 0; + for( ; i < NUM_PARAMS; i++ ) + { + if( 0 > xywh[i] ) + { + printf( "hwa_scale: ERROR, At least four parameters must be specified herein\n" + " Parameters must not to be negative\n"); + free(xywh); + exit(1); + } + } + + x = xywh[0]; + y = xywh[1]; + width = xywh[2]; + height = xywh[3]; + + free(xywh); + } + else if( 0 == enable ) + { + x = 0; + y = 0; + width = 0; + height = 0; + } + + crtc = get_crtc_via_randr("LVDS1"); + if (-1 == crtc) + { + printf ("Didn't find randr crtc!! :\n"); + exit (0); + } + + hwa_scale_cookie = xcb_hwa_screen_scale( c, crtc , enable, x, y, width, height ); + hwa_scale_reply = xcb_hwa_screen_scale_reply ( c, hwa_scale_cookie, &error ); + + if(hwa_scale_reply) + { + printf( "\n-----------------------------------\n"); + printf("Scale:\n"); + printf("hwa_scale: Call was ok\nreply.status=%d \n", hwa_scale_reply->status ); + printf( "-----------------------------------\n"); + + free(hwa_scale_reply); + } + else + { + printf("hwa_scale: ERROR" ); + } +} + +void hwa_show_layer(int layer) +{ + randr_crtc = (xcb_randr_crtc_t) get_crtc_via_randr("LVDS1"); + if (-1 == randr_crtc) + { + printf ("Didn't find randr crtc!! :\n"); + exit (0); + } + + printf ("<=== Overlay Layer Show ==> \n"); + printf ("<=== Randr crtc=%d, layer=%d ==> \n", randr_crtc, layer); + xcb_hwa_overlay_show_layer (c, (xcb_randr_crtc_t) randr_crtc, layer); + xcb_flush (c); + +} + +void hwa_hide_layer( int layer ) +{ + randr_crtc = (xcb_randr_crtc_t) get_crtc_via_randr("LVDS1"); + if (-1 == randr_crtc) + { + printf ("Didn't find randr crtc!! :\n"); + exit (0); + } + + printf ("<=== Overlay Layer Hide ==> \n"); + printf ("<=== Randr crtc=%d, layer=%d ==> \n", randr_crtc, layer); + xcb_hwa_overlay_hide_layer (c, (xcb_randr_crtc_t) randr_crtc, layer); + xcb_flush (c); + +} + +/* + * output = LVDS, HDMI, Virtual + * + * */ +int get_crtc_via_randr( char* output_to_find ) +{ + xcb_randr_get_screen_resources_cookie_t screenresc_cookie; + xcb_randr_get_screen_resources_reply_t* screenresc_reply = NULL; + xcb_randr_crtc_t randrcrtc_first; + int i = 0, k = 0; + + /* Get the first X screen */ + xcb_screen_t* x_first_screen = xcb_setup_roots_iterator( xcb_get_setup(c)).data; + + xcb_window_t x_window_dummy = xcb_generate_id(c); + + /* Create dummy X window */ + xcb_create_window(c, 0, x_window_dummy, x_first_screen->root, 0, 0, 1, 1, 0, 0, 0, 0, 0); + + //Flush pending requests to the X server + xcb_flush(c); + + //Send a request for screen resources to the X server + screenresc_cookie = xcb_randr_get_screen_resources( c, x_window_dummy ); + + /* Take reply from Xserver */ + screenresc_reply = xcb_randr_get_screen_resources_reply( c, screenresc_cookie, 0); + + if(screenresc_reply) + { + + /* Take each crtc, and create screen for each of them*/ + xcb_randr_crtc_t *randr_crtcs = xcb_randr_get_screen_resources_crtcs(screenresc_reply); + + for (i = 0; i < screenresc_reply->num_crtcs; ++i) + { + /* We take information of the output crtc */ + xcb_randr_get_crtc_info_cookie_t crtc_info_cookie = + xcb_randr_get_crtc_info (c, randr_crtcs [i], XCB_CURRENT_TIME); + xcb_randr_get_crtc_info_reply_t *crtc_randr_info = + xcb_randr_get_crtc_info_reply (c, crtc_info_cookie, NULL); + + /* Ignore CRTC if it hasn't OUTPUT */ + if (!xcb_randr_get_crtc_info_outputs_length (crtc_randr_info)) + continue; + + xcb_randr_output_t *randr_outputs = xcb_randr_get_crtc_info_outputs (crtc_randr_info); + + for (k = 0; k < xcb_randr_get_crtc_info_outputs_length (crtc_randr_info); ++k) + { + xcb_randr_get_output_info_cookie_t output_info_cookie = + xcb_randr_get_output_info (c, randr_outputs [k], XCB_CURRENT_TIME); + xcb_randr_get_output_info_reply_t *output_randr_info = + xcb_randr_get_output_info_reply (c, output_info_cookie, NULL); + + if (!output_randr_info) + continue; + + int length = xcb_randr_get_output_info_name_length (output_randr_info); + + /* Add null to name, it doesn't '\0' terminated */ + char *outputname = malloc ((length + 1) * sizeof(char *)); + memcpy (outputname, xcb_randr_get_output_info_name (output_randr_info), length); + outputname [length] = '\0'; + + /* + printf ("<-Screen[%i] INFO: (%s):\n", j, name); + printf (" width_mm: %i\n", output_info_r->mm_width); + printf (" height_mm: %i\n", output_info_r->mm_height); + */ + + if (!strcmp (outputname, output_to_find)){ + randrcrtc_first = output_randr_info->crtc; + free (output_randr_info); + free (crtc_randr_info); + printf ("<-RANDR CRTCID= %d\n",randrcrtc_first ); + return randrcrtc_first; + } + + free (output_randr_info); + } + + free (crtc_randr_info); + } + + free (screenresc_reply); + } + else + return -1; + + return -1; +} + +int* pars_params( char* scale_param ) +{ + int indx = 0; + int i = 0; + int* xywh = (int*)calloc( NUM_PARAMS, sizeof( int ) ); + char *delimeter = ":"; + + for( ; i < NUM_PARAMS; i++ ) + xywh[i] = -1; + + char *token = (char *)strtok( scale_param, delimeter ); + + while( token != NULL ) + { + xywh[indx++] = atoi(token); + token = (char *)strtok( NULL, delimeter ); + } + + return xywh; +} + + + + + diff --git a/tests/functional/hwa_test/hwa_sample.h b/tests/functional/hwa_test/hwa_sample.h new file mode 100644 index 0000000..cfc6e44 --- /dev/null +++ b/tests/functional/hwa_test/hwa_sample.h @@ -0,0 +1,79 @@ +/* + * hwa_sample.h + * + * Created on: Mar 20, 2015 + * Author: roma + */ + +#ifndef HWA_SAMPLE_H_ +#define HWA_SAMPLE_H_ + +/* Standart headers */ +#include <stdio.h> +#include <stdlib.h> + +#include <getopt.h> + +/* X Server's headers */ +#include <X11/Xlib.h> +#include <xcb/xcb.h> +#include <xcb/hwa.h> +#include <xcb/dri3.h> +#include <xcb/randr.h> + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#define NUM_ARG 2 +#define NUM_PARAMS 4 + +#define ON 1 +#define OFF 1 + +#define PRINT( a ) ( printf("%d\n", a) ) + +void +fixed_xcb_str_next(xcb_str_iterator_t* it) +{ + it->data = (void*) ((char*) it->data + it->data->name_len + 1); + --it->rem; +} + +void xcb_init( void ); + +void help( void ) +{ + printf( " \nUsage options:\n\n" + " --version HWA query version\n" + " --info list all extension and get some data about HWA \n" + " -c --cursore [0-1] 0:disable 1:enable\n" + " -r --cursorr [0-90-180-270-360] are angle degrees to be turned cursor.\n\n" + " -a --accessibility [0-1] 0:disable 1:enable.\n\n" + " -x --scale [0-1] [x:y:width:height] 0:disable 1:enable \n" + " if enable was chosen x:y:width:height must be specified.\n\n" + " <-SHOW/HIDE Layer options:-> \n" + " -s --show [0-1] 0: UI Layer, 1: XV Layer.\n" + " -h --hide [0-1] 0: UI Layer, 1: XV Layer.\n" + ); +} + +void hwa_query_version( void ); +void hwa_cursor_enable( int enable ); +void hwa_cursor_rotate( int angle ); +void hwa_accessibility( int enable ); +void hwa_scale( int enable, char* scale_param ); +void extensions_info( void ); + +int get_crtc_via_randr( char* output_to_find ); +int* pars_params( char* scale_param ); + +void hwa_show_layer( int layer ); +void hwa_hide_layer( int layer ); + + + + + + +#endif /* HWA_SAMPLE_H_ */ diff --git a/tests/functional/hwc_test/Makefile.am b/tests/functional/hwc_test/Makefile.am new file mode 100644 index 0000000..3a3cfdf --- /dev/null +++ b/tests/functional/hwc_test/Makefile.am @@ -0,0 +1,41 @@ +if HAVE_FT + + lib_LTLIBRARIES = libdri2_dri3.la + libdri2_dri3_la_CFLAGS = $(HWC_TEST_CFLAGS) + libdri2_dri3_la_LIBADD = $(HWC_TEST_LIBS) -lpthread + libdri2_dri3_la_LDFLAGS = -avoid-version + libdri2_dri3_la_SOURCES = aux_dri2_dri3_lib/dri2_dri3.c \ + aux_dri2_dri3_lib/dri2.c \ + aux_dri2_dri3_lib/dri3.c \ + aux_dri2_dri3_lib/fps.c \ + aux_dri2_dri3_lib/aux_draw.c + + bin_PROGRAMS = hwc-sample square-bubbles clock snowflake wander-stripe + + hwc_sample_CFLAGS = $(HWC_TEST_CFLAGS) + hwc_sample_LDADD = $(HWC_TEST_LIBS) -lpthread + hwc_sample_SOURCES = ./hwc_sample/hwc-sample.c \ + ./hwc_sample/hwc-thread.c + + square_bubbles_CFLAGS = $(HWC_TEST_CFLAGS) + square_bubbles_LDADD = $(HWC_TEST_LIBS) -lm -lX11 + square_bubbles_SOURCES = ./square_bubbles/square_bubbles.c + + clock_CFLAGS = $(HWC_TEST_CFLAGS) -I@top_srcdir@/tests/functional/hwc_test/aux_dri2_dri3_lib + clock_LDADD = $(HWC_TEST_LIBS) libdri2_dri3.la -lm + clock_SOURCES = ./clock.c \ + ./aux_apps.c + + snowflake_CFLAGS = $(HWC_TEST_CFLAGS) -I@top_srcdir@/tests/functional/hwc_test/aux_dri2_dri3_lib + snowflake_LDADD = $(HWC_TEST_LIBS) libdri2_dri3.la -lm + snowflake_SOURCES = ./snowflake.c \ + ./aux_apps.c + + wander_stripe_CFLAGS = $(HWC_TEST_CFLAGS) -I@top_srcdir@/tests/functional/hwc_test/aux_dri2_dri3_lib + wander_stripe_LDADD = $(HWC_TEST_LIBS) libdri2_dri3.la + wander_stripe_SOURCES = ./wander_stripe.c \ + ./aux_apps.c + +# install-data-hook: + dist_data_DATA = launch.sh +endif diff --git a/tests/functional/hwc_test/aux_apps.c b/tests/functional/hwc_test/aux_apps.c new file mode 100644 index 0000000..5a1d2fb --- /dev/null +++ b/tests/functional/hwc_test/aux_apps.c @@ -0,0 +1,324 @@ +/************************************************************************** + + auxilary module's source + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <xcb/composite.h> + +#include "aux_apps.h" +#include "dri2_dri3.h" + +extern xcb_rectangle_t wnd_pos; +extern int mode; +extern uint32_t present_bufs; +extern uint32_t swap_interval; +extern uint32_t root_parent; + +// get name of app, which uses this library +//======================================================================== +char* +app_name (void) +{ + FILE* f; + char* slash; + static int initialized; + static char app_name[128]; + + if (initialized) + return app_name; + + // get the application name + f = fopen ("/proc/self/cmdline", "r"); + + if (!f) + return NULL; + + if (fgets (app_name, sizeof(app_name), f) == NULL) + { + fclose (f); + return NULL; + } + + fclose (f); + + if ((slash = strrchr (app_name, '/')) != NULL) + { + memmove (app_name, slash + 1, strlen(slash)); + } + + initialized = 1; + + return app_name; +} + +// +//======================================================================== +void +print_help (void) +{ + printf ("%s - test application.\n" + "This app can be used to test dri2, dri3, present and hwc extensions.\n" + "You can choose work mode among dri2, present or dri3 + present modes.\n" + "You can use this app wiht hwc-sample to test hwc extension (with dri2, present or dri3 + present).\n" + "You can set amount of buffers for present work mode, by default app uses triple buffering in present\n" + "mode, amount of buffers in dri2 mode depends on ddx driver implementation.\n" + "You can use this app with square-bubbles to test properly window's size & position changes.\n" + "To test flip mode, you must launch app in full-screen mode.\n" + "By default frame rate is limited to (vblank)vertical blank (60 Hz), so you cann't see fps more then 60,\n" + "you can disable binding to vblank - set swap interval to 0.\n\n" + "available options:\n" + "\t -geo 'width'x'height' -- set window's size,\n" + "\t -geo 'width'x'height' 'x' 'y' -- set window's geometry,\n" + "\t -dri3 -- dri3 + present Exts. mode (default mode),\n" + "\t -dri2 -- dri2 Exts. mode,\n" + "\t -present -- present Exts. mode,\n" + "\t -present_bufs -- amount of buffers used in no-dri2 mode (default value: 3),\n" + "\t -s_i -- buffers swap interval (both dri2 and present) (default value: 1),\n" + "\t -root_parent -- is parent a root window (default value: 1).\n", app_name()); +} + +// parse command line +// if you want to do some specific for your app - implement yourself's cmd parsing +//======================================================================== +void +cmd_parse (int argc, char* const argv[]) +{ + int i; + + if (argc < 2) return; + + // if we want to set window's size and position + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-geo")) + { + if ((i + 1 < argc) && (i + 2 >= argc)) + sscanf (argv[i + 1], "%hux%hu", &wnd_pos.width, &wnd_pos.height); + else if (i + 3 < argc) + { + sscanf (argv[i + 1], "%hux%hu", &wnd_pos.width, &wnd_pos.height); + sscanf (argv[i + 2], "%hd", &wnd_pos.x); + sscanf (argv[i + 3], "%hd", &wnd_pos.y); + } + break; + } + } + + // if we want to use dri3 + present Exts. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-dri3")) + { + mode = DRI3_PRESENT_MODE; + break; + } + } + + // if we want to use dri2 Ext. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-dri2")) + { + mode = DRI2_MODE; + break; + } + } + + // if we want to use present Exts. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-present")) + { + mode = PRESENT_MODE; + break; + } + } + + // if we want to set amount of buffers for present usage. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-present_bufs") && (argc - i > 1)) + { + sscanf (argv[i + 1], "%u", &present_bufs); + break; + } + } + + // if we want to set buffer swap interval. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-s_i") && (argc - i > 1)) + { + sscanf (argv[i + 1], "%u", &swap_interval); + break; + } + } + + // if we want to insert window between root and window to render. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-root_parent") && (argc - i > 1)) + { + sscanf (argv[i + 1], "%u", &root_parent); + break; + } + } + + // if we want to print help + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-help") || !strcmp (argv[i], "-h")) + { + print_help (); + exit (0); + } + } +} + +// check is composite extension existed +//======================================================================== +int +check_composite_ext (xcb_connection_t* dpy) +{ + if (!dpy) return 0; + + xcb_composite_query_version_cookie_t q_c; + xcb_composite_query_version_reply_t* q_r; + xcb_generic_error_t* xcb_errors = NULL; + + q_c = xcb_composite_query_version (dpy, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION); + q_r = xcb_composite_query_version_reply (dpy, q_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + printf ("error while composite_query_version call.\n"); + return 0; + } + else + printf ("composite extension: %d.%d.\n", q_r->major_version, q_r->minor_version); + + free (q_r); + + return 1; +} + +// create window with 'background' background +// root_parent - if cleared, then two windows will be created (parent and child), +// and id of child window will be returned +//=================================================================== +xcb_window_t +create_window (xcb_connection_t* dpy, uint32_t background, uint32_t root_parent, char* name) +{ + uint32_t window_mask; + uint32_t window_values[3]; + xcb_window_t wnd, wnd_child; + xcb_screen_t* screen; + uint16_t border_width; + uint32_t gravity; + int is_composite_ext = 0; + + if (!dpy || !name) + return 0; + + if(root_parent) + is_composite_ext = 0;//check_composite_ext (dpy); + + // copy xeyes behavior... :-) + border_width = root_parent ? 0 : 1; + gravity = root_parent ? XCB_GRAVITY_BIT_FORGET : XCB_GRAVITY_NORTH_WEST; + + // get first screen of display + screen = xcb_setup_roots_iterator (xcb_get_setup (dpy)).data; + + window_mask = XCB_CW_BACK_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_EVENT_MASK; + window_values[0] = 0x00;//background; + window_values[1] = gravity; + window_values[2] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; + + wnd = xcb_generate_id (dpy); + xcb_create_window (dpy, DEPTH, wnd, screen->root, wnd_pos.x, wnd_pos.y, + wnd_pos.width, wnd_pos.height, border_width, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, window_mask, window_values); + + // hwc-sample and square_bubbles manipulate only named windows + xcb_change_property (dpy, XCB_PROP_MODE_REPLACE, wnd, XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, 8, strlen (name), name); + + // see XSizeHints struct definintion in X11/Xutil.h + // The x, y, width, and height members are now obsolete, but wihtout them + // WM doesn't listen our request about keep window's size. + uint32_t x_size_hints[] = + { + 3, // user specified x, y & user specified width, height + (uint32_t)wnd_pos.x, (uint32_t)wnd_pos.y, + (uint32_t)wnd_pos.width, (uint32_t)wnd_pos.height, + 0, 0, // int min_width, min_height; + 0, 0, // int max_width, max_height; + 0, 0, // int width_inc, height_inc; + 0,0, 0,0, // struct { int x; int y; } min_aspect, max_aspect; + 0, 0, // int base_width, base_height; + 0 // int win_gravity; + }; + + // set WM_NORMAL_HINTS property + xcb_change_property (dpy, XCB_PROP_MODE_REPLACE, wnd, XCB_ATOM_WM_NORMAL_HINTS, + XCB_ATOM_WM_SIZE_HINTS, 32, sizeof(x_size_hints)/sizeof(uint32_t), + x_size_hints); + + if(root_parent && is_composite_ext) + { + printf ("wnd: 0x%x will be redirected.\n", wnd); + xcb_composite_redirect_window (dpy, wnd, XCB_COMPOSITE_REDIRECT_MANUAL); + } + + // Make window visible + xcb_map_window (dpy, wnd); + + // copy xeyes behavior... :-) + if(!root_parent) + { + window_values[1] = XCB_GRAVITY_BIT_FORGET; + + wnd_child = xcb_generate_id (dpy); + xcb_create_window (dpy, DEPTH, wnd_child, wnd, 0, 0, + wnd_pos.width, wnd_pos.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, window_mask, window_values); + + // Make window visible + xcb_map_window (dpy, wnd_child); + + return wnd_child; + } + + return wnd; +} + diff --git a/tests/functional/hwc_test/aux_apps.h b/tests/functional/hwc_test/aux_apps.h new file mode 100644 index 0000000..8292bd6 --- /dev/null +++ b/tests/functional/hwc_test/aux_apps.h @@ -0,0 +1,47 @@ +/************************************************************************** + + auxilary module's header + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 _AUX_APPS_H +#define _AUX_APPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <xcb/xcb.h> + +void cmd_parse (int argc, char* const argv[]); +xcb_window_t create_window (xcb_connection_t* dpy, uint32_t background, uint32_t root_parent, char* name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/aux_draw.c b/tests/functional/hwc_test/aux_dri2_dri3_lib/aux_draw.c new file mode 100644 index 0000000..0fa5ecf --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/aux_draw.c @@ -0,0 +1,265 @@ +/************************************************************************** + + source of auxiliary functions for direct rendering + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "dri2_dri3.h" + +// set pixel with 'color' in 'buf' on (x, y) position +// no memory bound out checks, do it within caller !!! +//======================================================================== +static inline void +draw_point (int x, int y, void* buf, uint16_t stride, unsigned int color) +{ + *((int*)(buf + x*(BPP/8) + y*stride)) = color; +} + +// draws line(s) into bo (Bresenham algorithm) +// points_num - number of elements of xcb_point_t array +// points - array of points, which will be used to draw line(s) +// line(s) is(are) drawn between each pair of points +// any attempts to draw line(s), which is(are) out of pixmap/bo size are rejected +//========================================================================= +int raw_draw_line (const bo_t* bo_e, uint32_t points_num, const xcb_point_t* points, + unsigned int color) +{ + tbm_bo bo = NULL; + tbm_bo_handle hndl; + uint16_t stride; + uint16_t width, height; + + int x, y, x1, x2, y1, y2; + int dx, dy, error, direct, invert; + int temp, i; + + if (!points || points_num < 2 || !bo_e) + { + printf ("raw_draw_line: invalid input parameters.\n"); + return 1; + } + + hndl.ptr = NULL; + bo = bo_e->bo; + stride = bo_e->stride; + width = bo_e->width; + height = bo_e->height; + + hndl = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + if (!hndl.ptr) + { + printf ("raw_draw_line: Error while tbm_bo_map.\n"); + exit (1); + } + + // x1, y1 - first point (in pixels) + // x2, y2 - second point (in pixels) + // x grows from left to right + // y grows from up to down + // draw (points_num - 1) line(s) + for (i = 0; i < points_num - 1; i++) + { + x1 = points->x; + y1 = points++->y; + x2 = points->x; + y2 = points->y; + + if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0) + { + printf ("raw_draw_line: invalid input parameters.\n"); + continue; + } + + if (x1 > (width - 1) || x2 > (width - 1) || y1 > (height - 1) || y2 > (height - 1)) + { + printf ("raw_draw_line: you are beyond image boundaries:\n" + " x1 = %d, y1 = %d, x2 = %d, y2 = %d, \twidth = %hu, height = %hu\n", + x1, y1, x2, y2, width, height); + continue; + } + + // to draw vertical lines + if (x1 == x2) + { + // we bypass image from bottom to top coordinates, so we must + // swap points if it necessary + if (y2 < y1) + { + temp = y1; + y1 = y2; + y2 = temp; + } + + for (y = y1; y <= y2; y++) + draw_point (x1, y, hndl.ptr, stride, color); + + continue; + } + + // if y-component of line is changed quickly then x-component, + // we must exchange axis to use Bresenham algorithm more effectively, + // due to that we have for cycle from x1 to x2, therefore we can change + // body of for cycle insted exchange axis, but this's not pretty + invert = abs (y2 - y1) > abs (x2 - x1); + if (invert) + { + temp = x1; + x1 = y1; + y1 = temp; + + temp = x2; + x2 = y2; + y2 = temp; + } + + // algorithm can draw line only if x of first point is less + // then x of second point, so we simple swap points if it's necessary + if (x1 > x2) + { + temp = x1; + x1 = x2; + x2 = temp; + + temp = y1; + y1 = y2; + y2 = temp; + } + + // where do we go while draw line: up(or straight) or down + if (y2 < y1) + direct = -1; + else + direct = 1; + + error = 0; + dx = x2 - x1; + dy = abs(y2 - y1); + + // to draw another cases of line (it's Bresenham algorithm implementation, + // which supports varios line's directions) + for (x = x1, y = y1; x <= x2; x++) + { + draw_point (invert ? y : x, invert ? x : y, hndl.ptr, stride, color); + + error += dy; + + if (error * 2 >= dx) + { + y += direct; + error -= dx; + } + } + } // for (i = 0; i < points_num - 1; i++) + + tbm_bo_unmap (bo); + + return 0; +} + +// draw filled rect into bo +// rect_num - amount of rectangles to draw (in current implemantation must be '1') +// rects - array of rectangles to draw +// any attempts to draw rectangle, which is out of pixmap/bo size are rejected +// draw only one rectangle !!! +//========================================================================= +int raw_fill_rect (const bo_t* bo_e, uint32_t rect_num, const xcb_rectangle_t* rects, + unsigned int color) +{ + tbm_bo bo = NULL; + tbm_bo_handle hndl; + uint16_t height; + uint16_t width; + uint16_t stride; + int i, j; + + if ( + rects->x < 0 || rects->y < 0 || rects->width <= 0 || rects->height <= 0 || + !rect_num || rect_num > 1 || !rects || !bo_e + ) + { + printf ("raw_fill_rect: invalid input parameters.\n"); + return 1; + } + + bo = bo_e->bo; + stride = bo_e->stride; + width = bo_e->width; + height = bo_e->height; + + if (rects->x + rects->width > width || rects->y + rects->height > height) + { + printf ("raw_fill_rect: you are beyond image boundaries:\n" + " x = %d, y = %d, width = %d, height = %d, widht_bo = %hu, height_bo = %hu.\n", + rects->x, rects->y, rects->width, rects->height, width, height); + return 1; + } + + hndl = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + if (!hndl.ptr) + { + printf ("raw_fill_rect: Error while tbm_bo_map.\n"); + exit (1); + } + + // this code works quikly then below code. + // if caller wants to clear (black color) all bo. + // another colors cann't be used due to memset semantic + // (memset use only low byte of second parameter) + if (width == rects->width && height == rects->height && !color) + { + memset (hndl.ptr, 0, bo_e->stride * bo_e->height); + goto success; + } + + // x grows from left to right + // y grows from up to down + + // shift to pixel, from which we must draw + hndl.ptr += rects->x*(BPP/8) + rects->y*stride; + + // memory boundaries were checked above + for (i = 0; i < rects->height; i++) + { + for (j = 0; j < rects->width; j++) + { + *((int*)hndl.ptr) = (int)color; + hndl.ptr += (BPP/8); + } + + // shift to pixel, from which we must draw + hndl.ptr -= j*(BPP/8) - stride; + } + +success: + tbm_bo_unmap (bo); + + return 0; +} diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2.c b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2.c new file mode 100644 index 0000000..0340f13 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2.c @@ -0,0 +1,394 @@ +/************************************************************************** + + dri2 backend + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implements preparing dri2 extension to use and dri2 events handling + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <unistd.h> +#include <fcntl.h> + +#include <xcb/dri2.h> + +#include "dri2_dri3_inner.h" + + +#define CACHE_BO_SIZE (3) + +typedef struct dri2_info_t +{ + int drm_fd; + drm_magic_t drm_magic; + char* device_name; + char* driver_name; + tbm_bufmgr bufmgr; + const xcb_query_extension_reply_t* dri2_ext; +}dri2_info_t; + +static dri2_info_t dri2_info; + +// cycle bo's cache +static bo_t bo_cache[CACHE_BO_SIZE]; +static uint32_t bo_cache_idx; + + +// next two functions avoid call to tbm_bo_import, when we have tbm_bo for +// appropriate buf_name, returned by dri2 extension + +// returns, if exist, tbm_bo for gem object's name 'buf_name' +//======================================================================== +static tbm_bo +get_tbm_bo_from_cache (uint32_t buf_name) +{ + int i; + + for (i = 0; i < CACHE_BO_SIZE; i++) + { + if (bo_cache[i].name == buf_name) return bo_cache[i].bo; + } + + return NULL; +} + +// add bo to cycle bo's cache +//======================================================================== +static void +add_bo_to_cache (const bo_t* bo) +{ + if (!bo) return; + + if (bo_cache[bo_cache_idx].bo) + tbm_bo_unref(bo_cache[bo_cache_idx].bo); + + memcpy ((bo_cache + bo_cache_idx++), bo, sizeof(bo_t)); + bo_cache_idx %= CACHE_BO_SIZE; +} + +// wrap over DRI2GetBuffers request +// return all information for rendering +//======================================================================== +static bo_t +get_bo (void) +{ + bo_t bo; + uint32_t attachments; + xcb_dri2_get_buffers_cookie_t get_buf_c; + xcb_dri2_get_buffers_reply_t* get_buf_r = NULL; + xcb_generic_error_t* xcb_errors = NULL; + xcb_dri2_dri2_buffer_t* dri2_buf = NULL; + + attachments = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT; + + get_buf_c = xcb_dri2_get_buffers (display.dpy, display.wnd, 1, 1, &attachments); + get_buf_r = xcb_dri2_get_buffers_reply (display.dpy, get_buf_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + set_error ("Error while xcb_dri2_get_buffers call.\n"); + pthread_cancel(thread_id); + } + + dri2_buf = xcb_dri2_get_buffers_buffers (get_buf_r); + if (!dri2_buf) + { + free (get_buf_r); + set_error ("dri2_buf = NULL.\n"); + pthread_cancel(thread_id); + } + + bo.stride = dri2_buf->pitch; + bo.width = get_buf_r->width; + bo.height = get_buf_r->height; + bo.name = dri2_buf->name; + + // cache bos + bo.bo = get_tbm_bo_from_cache (bo.name); + if (!bo.bo) + { + bo.bo = tbm_bo_import (dri2_info.bufmgr, bo.name); + add_bo_to_cache (&bo); + } + + // this memory will be used for next xcb_dri2_get_buffers_buffers calls, + // so don't need to free it + //free (dri2_buf); + + DEBUG_OUT ("buf_name: %u, bo: %p, stride: %u, cpp: %u, flags: %u, width: %u, " + "height: %u, count: %u\n", + bo.name, bo.bo, bo.stride, dri2_buf->cpp, dri2_buf->flags, + bo.width, bo.height, get_buf_r->count); + + free (get_buf_r); + + return bo; +} + +// this function is called in event handling and calls app's callbacks to draw +//======================================================================== +static void +draw (void) +{ + bo_t bo; + + TIME_START(); + bo = get_bo (); + TIME_END ("get_bo"); + + TIME_START(); + + if (gr_ctx.draw_funcs.raw_clear) + gr_ctx.draw_funcs.raw_clear (&bo); + + if (gr_ctx.draw_funcs.raw_draw) + gr_ctx.draw_funcs.raw_draw (&bo); + + TIME_END ("draw"); +} + +// wrap over DRI2SwapBuffers request +// this function is called in event handling +//======================================================================== +static void +swap_buffers (uint32_t msc_hi, uint32_t msc_lo) +{ + DEBUG_OUT ("ask to swap buffers for window: 0x%x at msc_hi: %u, msc_lo: %u\n", + display.wnd, msc_hi, msc_lo); + + TIME_START(); + xcb_dri2_swap_buffers (display.dpy, display.wnd, msc_hi, msc_lo, 0, 0, 0 ,0); + TIME_END ("xcb_dri2_swap_buffers"); + +#ifdef _DEBUG_ + printf ("----------------------------\n"); +#endif +} + + +//======================================================================== +//======================================================================== +//======================================================================== + + +// check dri2 extension, connect, authenticate, create dri2 drawable +// and initiate tizen buffer manager +// return 0 if success, 1 otherwise +//=================================================================== +int +prepare_dri2_ext (void) +{ + xcb_dri2_query_version_cookie_t query_ver_c; + xcb_dri2_query_version_reply_t* query_ver_r = NULL; + xcb_generic_error_t* xcb_errors = NULL; + + xcb_dri2_connect_cookie_t connect_c; + xcb_dri2_connect_reply_t* connect_r = NULL; + + xcb_dri2_authenticate_cookie_t auth_c; + xcb_dri2_authenticate_reply_t* auth_r = NULL; + + int res; + + // whait for main thread + usleep (500000); + + // dri2_query_version + + query_ver_c = xcb_dri2_query_version (display.dpy, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION); + query_ver_r = xcb_dri2_query_version_reply (display.dpy, query_ver_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + set_error ("Error while dri2_query_version call.\n"); + return 1; + } + + printf ("DRI2 Extension: %u.%u.\n", query_ver_r->major_version, query_ver_r->minor_version); + + free (query_ver_r); + + // dri2_connect + + connect_c = xcb_dri2_connect (display.dpy, display.screen->root, XCB_DRI2_DRIVER_TYPE_DRI); + connect_r = xcb_dri2_connect_reply (display.dpy, connect_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + set_error ("Error while dri2_connect call.\n"); + return 1; + } + + dri2_info.driver_name = xcb_dri2_connect_driver_name (connect_r); + dri2_info.device_name = xcb_dri2_connect_device_name (connect_r); + free (connect_r); + + printf ("DRI2 driver_name: %s, device_name: %s.\n", dri2_info.driver_name, dri2_info.device_name); + + // open drm device + dri2_info.drm_fd = open (dri2_info.device_name, O_RDWR); + if (dri2_info.drm_fd < 0) + { + char* temp = malloc (512); + + sprintf (temp, "Error while open call for file: %s.\n", dri2_info.device_name); + set_error (temp); + free (temp); + + return 1; + } + + // dri2_authenticate + res = drmGetMagic (dri2_info.drm_fd, &dri2_info.drm_magic); + if (res) + { + close (dri2_info.drm_fd); + set_error ("Error while drmGetMagic call.\n"); + return 1; + } + + auth_c = xcb_dri2_authenticate (display.dpy, display.screen->root, (uint32_t)dri2_info.drm_magic); + auth_r = xcb_dri2_authenticate_reply (display.dpy, auth_c, &xcb_errors); + if (xcb_errors) + { + close (dri2_info.drm_fd); + free (xcb_errors); + set_error ("Error while dri2_authenticate call.\n"); + return 1; + } + + if (!auth_r->authenticated) + { + close (dri2_info.drm_fd); + set_error ("Error while dri2_authenticate call.\n"); + return 1; + } + + free (auth_r); + + xcb_dri2_create_drawable (display.dpy, display.wnd); + + // for determine dri2's events + dri2_info.dri2_ext = xcb_get_extension_data (display.dpy, &xcb_dri2_id); + + dri2_info.bufmgr = tbm_bufmgr_init (dri2_info.drm_fd); + + return 0; +} + +// dri2 events loop +//======================================================================== +void +dri2_loop (void) +{ + xcb_generic_event_t* event = NULL; +#ifndef _DEBUG_ + struct timespec start; +#endif + uint64_t target_msc = 0; + + draw (); + swap_buffers (0, 0); + + while (1) + { + xcb_flush (display.dpy); + DEBUG_OUT("before xcb_wait_for_event.\n"); + event = xcb_wait_for_event (display.dpy); + DEBUG_OUT("after xcb_wait_for_event.\n"); + if (!event) + { + printf("event is NULL.\n"); + break; + } + + switch (event->response_type) + { + default: + { + // if XCB_DRI2_BUFFER_SWAP_COMPLETE event + if (event->response_type == dri2_info.dri2_ext->first_event + + XCB_DRI2_BUFFER_SWAP_COMPLETE) + { + xcb_dri2_buffer_swap_complete_event_t* ev; + ev = (xcb_dri2_buffer_swap_complete_event_t*)event; + +#ifdef _DEBUG_ + DEBUG_OUT ("XCB_DRI2_BUFFER_SWAP_COMPLETE:\n"); + switch (ev->event_type) + { + case XCB_DRI2_EVENT_TYPE_EXCHANGE_COMPLETE: + DEBUG_OUT (" EXCHANGE_COMPLETE.\n"); + break; + case XCB_DRI2_EVENT_TYPE_BLIT_COMPLETE: + DEBUG_OUT (" BLIT_COMPLETE.\n"); + break; + case XCB_DRI2_EVENT_TYPE_FLIP_COMPLETE: + DEBUG_OUT (" FLIP_COMPLETE.\n"); + break; + } + DEBUG_OUT (" drawable: 0x%x, msc_hi: %u, msc_lo: %u, sbc: %u, " + "ust_hi: %u, ust_lo: %u\n", + ev->drawable, ev->msc_hi, ev->msc_lo, ev->sbc, + ev->ust_hi, ev->ust_lo); + +#endif + // adjust target_msc to real msc + target_msc = ((uint64_t)ev->msc_hi << 32) | (uint64_t)ev->msc_lo; + + // prepare target_msc for use when DRI2InvalidateBuffers event is came + target_msc += 2*gr_ctx.params.swap_interval; + } + else if (event->response_type == dri2_info.dri2_ext->first_event + + XCB_DRI2_INVALIDATE_BUFFERS) + { +#ifdef _DEBUG_ + xcb_dri2_invalidate_buffers_event_t* ev; + ev = (xcb_dri2_invalidate_buffers_event_t*)event; + + DEBUG_OUT ("XCB_DRI2_INVALIDATE_BUFFERS.\n drawable: 0x%x\n", ev->drawable); +#else + fps_calc( &start ); + clock_gettime( CLOCK_REALTIME, &start ); +#endif + // we draw frame when obtained DRI2InvalidateBuffers event due to be able to + // handle situation when DRI2InvalidateBuffers event signals about mismatching + // drawable and buffer sizes and DRI2BufferSwapComplete event will not be issued and + // delivered to us and we will hang out in xcb_wait_for_event, so we draw frame + // here and for swap it use target_msc obtained from DRI2BufferSwapComplete event + // on previous swap + draw (); + swap_buffers ((uint32_t)(target_msc >> 32), (uint32_t)(target_msc & 0xFFFFFFFF)); + } + } + break; + } + }// while (1) +} diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.c b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.c new file mode 100644 index 0000000..b59cc57 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.c @@ -0,0 +1,227 @@ +/************************************************************************** + + dri2_dri3 dispatcher's source + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implemets dri2/dri3 dispatcher and some auxiliary functions + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <pthread.h> + +#include "dri2_dri3_inner.h" + +display_t display; +graphics_ctx gr_ctx; +pthread_t thread_id; +xcb_rectangle_t wnd_pos; + +static char* error; + +static void* dri2_dri3 (void* arg); +static int init_graphic_context (void); + +// this function gets copy of passed arguments !!! +// dpy - connection to Xserver, initialized by client, used for obtain wnd's geometry +// draw_funcs - set of callback function to drawing, which functions to use +// will be dedicated according to mode value +// mode - mode in which dri2_dri3 module will work +// window - window's id in which drawing will be occured +// params - dri2/dri3 configure parameters +//========================================================================= +int init_dri2_dri3 (xcb_connection_t* dpy, const draw_funcs_t* draw_funcs, + int mode, xcb_window_t window, const dri2_dri3_params_t* params) +{ + int res; + + if (!draw_funcs || !dpy || !params) + { + set_error ("invalid input arguments"); + return 1; + } + + display.client_dpy = dpy; // used for obtain window's geometry only + display.dpy = xcb_connect (NULL, NULL); // dpy from client cann't be used + // for processing dri2/dri3 events + // get first screen of display + display.screen = xcb_setup_roots_iterator (xcb_get_setup (display.dpy)).data; + display.wnd = window; + + gr_ctx.mode = mode; + memcpy (&gr_ctx.draw_funcs, draw_funcs, sizeof (gr_ctx.draw_funcs)); + memcpy (&gr_ctx.params, params, sizeof (gr_ctx.params)); + + get_wnd_geometry (display.wnd, &wnd_pos); + + res = pthread_create (&thread_id, NULL, dri2_dri3, NULL); + if (res) + { + set_error ("error while pthread_create"); + return 1; + } + + return 0; +} + +// any dri2_dri3 module's functions return error code or message, +// only DRI2_DRI3_TRUE or DRI2_DRI3_FALSE +// use this function, if you need, to obtain more detail information about error +// you must free memory, pointed by returned value +//========================================================================= +char* get_last_error (void) +{ + char* temp; + + if (!error) return NULL; + + // TODO: need thread synchronize + temp = strdup (error); + free (error); + error = NULL; + + return temp; +} + + +//======================================================================== +//======================================================================== +//======================================================================== + + +// dri2/dri3 xcb events loop +//======================================================================== +static void* +dri2_dri3 (void* arg) +{ + int res; + + res = init_graphic_context (); + if (res) + pthread_cancel(thread_id); + + switch (gr_ctx.mode) + { + case DRI2_MODE: + { + dri2_loop (); + } + break; + + case DRI3_PRESENT_MODE: + case PRESENT_MODE: + { + dri3_loop (); + } + break; + } + + return NULL; +} + +// fill gr_ctx struct to use it on drawing and presenting on screen phases +// return 0 if success, 1 otherwise +//=================================================================== +static int +init_graphic_context (void) +{ + int res; + + switch (gr_ctx.mode) + { + case DRI2_MODE: + { + res = prepare_dri2_ext (); + if (res) return 1; + + printf ("usecase: dri2.\n"); + } + break; + + case DRI3_PRESENT_MODE: + case PRESENT_MODE: + { + res = prepare_dri3_present_ext (); + if (res) return 1; + + if (gr_ctx.mode == DRI3_PRESENT_MODE) + printf ("usecase: dri3 + present.\n"); + else + printf ("usecase: present.\n"); + } + break; + + default: + printf ("invalid gr_ctx.mode.\n"); + break; + } + + return 0; +} + +// return geometry of specified, by win_id, window +//======================================================================== +void +get_wnd_geometry (xcb_window_t win_id, xcb_rectangle_t* geometry) +{ + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t* reply = NULL; + xcb_generic_error_t* error = NULL; + + if (!geometry) + { + printf ("error while get_wnd_geometry call.\n"); + exit (1); + } + + cookie = xcb_get_geometry (display.client_dpy, win_id); + reply = xcb_get_geometry_reply (display.client_dpy, cookie, &error); + if (error) + { + printf ("error while xcb_get_geometry call.\n"); + free (error); + exit (1); + } + + geometry->x = reply->x; + geometry->y = reply->y; + geometry->width = reply->width; + geometry->height = reply->height; + + free (reply); +} + +// for inner use +//=================================================================== +void +set_error (const char* str) +{ + // to prevent rewriting of previous error message + if (!error) error = strdup (str); +} diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.h b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.h new file mode 100644 index 0000000..5b12e44 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3.h @@ -0,0 +1,135 @@ +/************************************************************************** + + dri2_dri3 library's source + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// dri2_dri3 library's API + +#ifndef _DRI2_DRI3_H +#define _DRI2_DRI3_H + +#include <xcb/xcb.h> +#include <tbm_bufmgr.h> + +#ifdef _DEBUG_ + #define DEBUG_OUT(format, args...) { printf("%s: "format, __FUNCTION__, ##args); } +#else + #define DEBUG_OUT(...) {;} +#endif + +#define BPP (32) // bits per pixel +#define DEPTH (24) + +#define DRI2_DRI3_TRUE 0x1 +#define DRI2_DRI3_FALSE 0x0 + +// modes for use in init_dri2_dri3() function +#define DRI2_MODE 0x0 +#define DRI3_MODE 0x1 +#define DRI3_PRESENT_MODE 0x2 +#define PRESENT_MODE 0x4 + +typedef struct dri2_dri3_params_t +{ + uint32_t num_of_bufs; // number of buffers for use with Present extension only + uint64_t swap_interval; // buffer(frame) swap interval +} dri2_dri3_params_t; + +// describes buffer for direct access +typedef struct bo_t +{ + tbm_bo bo; // these bos represents such gem object as pxmap in graphics_ctx_t structure + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t name; // name of gem object, used only by dri2 + int dma_buf_fd; // fd of dmabuf file, used only by dri3 +} bo_t; + +typedef void (*xcb_clear_func_ptr)(xcb_drawable_t drawable, uint32_t draw_w, uint32_t draw_h); +typedef void (*xcb_draw_func_ptr)(xcb_drawable_t drawable, uint32_t draw_w, uint32_t draw_h); + +typedef void (*raw_clear_func_ptr)(const bo_t* bo_e); +typedef void (*raw_draw_func_ptr)(const bo_t* bo_e); + +typedef struct draw_funcs_t +{ + xcb_clear_func_ptr xcb_clear; + xcb_draw_func_ptr xcb_draw; + raw_clear_func_ptr raw_clear; + raw_draw_func_ptr raw_draw; +} draw_funcs_t; + + +// this function gets copy of passed arguments !!! +// dpy - connection to Xserver, initialized by client, used for obtain wnd's geometry +// draw_funcs - set of callback function to drawing, which functions to use +// will be dedicated according to mode value +// mode - mode in which dri2_dri3 module will work +// window - window's id in which drawing will be occured +// params - dri2/dri3 configure parameters +// Note: if you use PRESENT_MODE or DRI3_PRESENT_MODE size of pixmaps or bos +// mayn't be equal size of window, now it isn't used, but maybe in future... +// therefore xcb_clear_func_ptr and xcb_draw_func_ptr functions have passed +// real size of pixmaps or bos as second and third arguments +__attribute__ ((visibility ("default"))) +int init_dri2_dri3 (xcb_connection_t* dpy, const draw_funcs_t* draw_funcs, + int mode, xcb_window_t window, const dri2_dri3_params_t* params); + +// any dri2_dri3 module's functions return error code or message, +// only DRI2_DRI3_TRUE or DRI2_DRI3_FALSE +// use this function, if you need, to obtain more detail information about error +// you must free memory, pointed by returned value +__attribute__ ((visibility ("default"))) +char* get_last_error (void); + +// you can use this auxiliary functions to direct drawing in bo + +// draws line(s) into tbm_bo (Bresenham algorithm) +// bo_e - pointer to struct returned by raw_draw or raw_clear function +// points_num - number of elements of xcb_point_t array +// points - array of points, which will be used to draw line(s) +// color - color of line(s) +// line(s) is(are) drawn between each pair of points +// any attempts to draw line(s), which is(are) out of pixmap/bo size are rejected +__attribute__ ((visibility ("default"))) +int raw_draw_line (const bo_t* bo_e, uint32_t points_num, const xcb_point_t* points, + unsigned int color); + +// draw filled rect into tbm_bo +// bo_e - pointer to struct returned by raw_draw or raw_clear function +// rect_num - amount of rectangles to draw (in current implemantation must be '1') +// rects - array of rectangles to draw +// color - color of rectangle +// any attempts to draw rectangle, which is out of pixmap/bo size are rejected +// draw only one rectangle !!! +__attribute__ ((visibility ("default"))) +int raw_fill_rect (const bo_t* bo_e, uint32_t rect_num, const xcb_rectangle_t* rects, + unsigned int color); + +#endif diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3_inner.h b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3_inner.h new file mode 100644 index 0000000..491d267 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri2_dri3_inner.h @@ -0,0 +1,82 @@ +/************************************************************************** + + dri2_dri3 library's inner header + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 _DRI2_DRI3_INNER_H +#define _DRI2_DRI3_INNER_H + +#include <xf86drm.h> + +#include "dri2_dri3.h" +#include "fps.h" + +#ifdef _DEBUG_ + #define TIME_START()\ + {\ + struct timespec start;\ + clock_gettime (CLOCK_REALTIME, &start); + #define TIME_END(str) \ + DEBUG_OUT ("%s: %f.\n", str, get_time_diff (&start) / 1000000.0f);\ + } +#else + #define TIME_START() {;} + #define TIME_END(...) {;} +#endif + +typedef struct display_t +{ + xcb_connection_t* dpy; + xcb_connection_t* client_dpy; + xcb_screen_t* screen; + xcb_window_t wnd; +} display_t; + +typedef struct graphics_ctx_t +{ + int mode; + draw_funcs_t draw_funcs; + dri2_dri3_params_t params; +} graphics_ctx; + +extern display_t display; +extern graphics_ctx gr_ctx; +extern pthread_t thread_id; + +extern xcb_rectangle_t wnd_pos; + +void get_wnd_geometry (xcb_window_t win_id, xcb_rectangle_t* geometry); +void set_error (const char* str); + +int prepare_dri2_ext (void); +void dri2_loop (void); + +int prepare_dri3_present_ext (void); +void dri3_loop (void); + +#endif diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/dri3.c b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri3.c new file mode 100644 index 0000000..0075fc6 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/dri3.c @@ -0,0 +1,542 @@ +/************************************************************************** + + dri3 backend + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implements preparing dri3 extension to use and dri3 events handling + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <unistd.h> + +#include <xcb/dri3.h> +#pragma pack(push, 1) +#include <xcb/present.h> +#pragma pack(pop) + + +#include "dri2_dri3_inner.h" + +typedef struct dri3_buffer_t +{ + xcb_pixmap_t pxmap; + bo_t bo; + xcb_rectangle_t pxmap_size; // bo size is equal pixmap size and can be found in bo field + uint32_t busy; // whether pixmap busy or not + + // whether pixmap must be reallocated, due to wnd size changes, or not + uint32_t buff_must_be_realloc; +} dri3_buffer_t; + +typedef struct dri3_present_info_t +{ + int drm_fd; + tbm_bufmgr bufmgr; + const xcb_query_extension_reply_t* present_ext; +} dri3_present_info_t; + +static dri3_buffer_t* dri3_buffers; +static dri3_present_info_t dri3_present_info; + +static uint64_t target_msc; + +// check present extenstion +// return 0 if success, 1 otherwise +//=================================================================== +static int +check_present_ext (void) +{ + xcb_present_query_version_cookie_t c; + xcb_present_query_version_reply_t* r = NULL; + xcb_generic_error_t* xcb_errors = NULL; + + c = xcb_present_query_version (display.dpy, XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION); + r = xcb_present_query_version_reply (display.dpy, c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("Error while Present Extension query_version call.\n"); + return 1; + } + else + printf ("Present Extension: %d.%d.\n", r->major_version, r->minor_version); + + free (r); + + return 0; +} + +// check dri3 extenstion and ask X server to send us auth drm_fd (fd of drm device file) +// return -1, if error was occured, +// otherwise drm_fd +//=================================================================== +static int +prepare_dri3_ext (void) +{ + int* drm_fd_p = NULL; + int drm_fd; + xcb_dri3_query_version_cookie_t query_version_c; + xcb_dri3_query_version_reply_t* query_version_r = NULL; + xcb_generic_error_t* xcb_errors = NULL; + + xcb_dri3_open_cookie_t open_c; + xcb_dri3_open_reply_t* open_r = NULL; + + // query version --------------------- + + query_version_c = xcb_dri3_query_version (display.dpy, XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION); + query_version_r = xcb_dri3_query_version_reply (display.dpy, query_version_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("Error while DRI3 Extension query_version call.\n"); + return -1; + } + else + printf ("DRI3 Extension: %d.%d.\n", query_version_r->major_version, query_version_r->minor_version); + + free (query_version_r); + + // open ------------------------------ + + // I don't know why open call require drawable, maybe it dedicates screen and drm device + // which is responsible for showing this screen ? + // about third parameter I'm still in confuse. + open_c = xcb_dri3_open (display.dpy, (xcb_drawable_t)display.screen->root, 0); + open_r = xcb_dri3_open_reply (display.dpy, open_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("Error while DRI3 Extension open call.\n"); + return -1; + } + + drm_fd_p = xcb_dri3_open_reply_fds (display.dpy, open_r); + drm_fd = *drm_fd_p; + + printf (" drm fd provided by DRI3: %d.\n", drm_fd); + printf (" OBSERVE: nfd returned by open_dri: %d.\n", open_r->nfd); + + // this memory will be used for next xcb_dri3_open_reply_fds calls, if we will do them, + // so don't need to free it + //free (drm_fd_p); + free (open_r); + + return drm_fd; +} + +// obtains tbm_bo(bo_t) from pixmap via dri3 extension +// aborts app, if error was occured, +// otherwise returns tbm_bo(bo_t), that represents such gem object that pixmap represents +//=================================================================== +static bo_t +get_bo_from_pixmap (xcb_pixmap_t pixmap) +{ + bo_t bo; + int* dma_buf_fd = NULL; + xcb_dri3_buffer_from_pixmap_cookie_t bf_from_pixmap_c; + xcb_dri3_buffer_from_pixmap_reply_t* bf_from_pixmap_r = NULL; + xcb_generic_error_t* xcb_errors = NULL; + + DEBUG_OUT ("before xcb_dri3_buffer_from_pixmap.\n"); + bf_from_pixmap_c = xcb_dri3_buffer_from_pixmap (display.dpy, pixmap); + + DEBUG_OUT ("before xcb_dri3_buffer_from_pixmap_reply.\n"); + bf_from_pixmap_r = xcb_dri3_buffer_from_pixmap_reply (display.dpy, bf_from_pixmap_c, + &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + printf ("Error while DRI3 Extension buffer_from_pixmap call.\n"); + exit (1); + } + + DEBUG_OUT ("size: %u, w: %hu, h: %hu, stride: %hu, bpp: %hhu, depth: %hhu.\n", + (bf_from_pixmap_r)->size, (bf_from_pixmap_r)->width, + (bf_from_pixmap_r)->height, (bf_from_pixmap_r)->stride, + (bf_from_pixmap_r)->bpp, (bf_from_pixmap_r)->depth); + + dma_buf_fd = xcb_dri3_buffer_from_pixmap_reply_fds (display.dpy, bf_from_pixmap_r); + + DEBUG_OUT ("dma_buf fd, returned by dri3, for pixmap[0x%06x]: %d.\n", pixmap, *dma_buf_fd); + + bo.bo = tbm_bo_import_fd (dri3_present_info.bufmgr, (tbm_fd)(*dma_buf_fd)); + if (!bo.bo) + { + free (bf_from_pixmap_r); + printf ("Error while tbm_bo_import_fd call.\n"); + exit (1); + } + + bo.dma_buf_fd = *dma_buf_fd; + bo.width = bf_from_pixmap_r->width; + bo.height = bf_from_pixmap_r->height; + bo.stride = bf_from_pixmap_r->stride; + // now, I don't see any necessity to use these values + // bf_from_pixmap_r->depth; + // bf_from_pixmap_r->bpp; + + DEBUG_OUT ("OBSERVE: nfd returned by buffer_from_pixmap: %d.\n", bf_from_pixmap_r->nfd); + + // this memory will be used for next xcb_dri3_buffer_from_pixmap_reply_fds calls, + // so don't need to free it + //free (dma_buf_fd); + free (bf_from_pixmap_r); + + return bo; +} + +// this function is called in event handling and calls app's callbacks to draw +//======================================================================== +static void +draw (uint32_t idx) +{ + if (gr_ctx.mode == DRI3_PRESENT_MODE || gr_ctx.mode == DRI3_MODE) + { + bo_t back_bo; + + // library client must not be able to do any changes in real bo object, + // now it isn't important, but what about a future ? + memcpy (&back_bo, &dri3_buffers[idx].bo, sizeof (back_bo)); + + if (gr_ctx.draw_funcs.raw_clear) + gr_ctx.draw_funcs.raw_clear (&back_bo); + + if (gr_ctx.draw_funcs.raw_draw) + gr_ctx.draw_funcs.raw_draw (&back_bo); + + DEBUG_OUT ("render in tbm bo: 0x%p (tied pixmap: 0x%x)\n", dri3_buffers[idx].bo.bo, + dri3_buffers[idx].pxmap); + } + else if (gr_ctx.mode == PRESENT_MODE) + { + xcb_pixmap_t back_pxmap; + xcb_rectangle_t pxmap_size; + + back_pxmap = dri3_buffers[idx].pxmap; + pxmap_size = dri3_buffers[idx].pxmap_size; + + if (gr_ctx.draw_funcs.xcb_clear) + gr_ctx.draw_funcs.xcb_clear (back_pxmap, pxmap_size.width, pxmap_size.height); + + if (gr_ctx.draw_funcs.xcb_draw) + gr_ctx.draw_funcs.xcb_draw (back_pxmap, pxmap_size.width, pxmap_size.height); + + DEBUG_OUT ("render in pixmap: 0x%x.\n", back_pxmap); + } +} + +// wrap over present pixmap request +//======================================================================== +static void +swap_buffers (uint64_t msc, uint32_t idx) +{ + xcb_pixmap_t back_pxmap; + + back_pxmap = dri3_buffers[idx].pxmap; + + xcb_present_pixmap (display.dpy, display.wnd, back_pxmap, idx, + 0, 0, 0, 0, 0, 0, 0, XCB_PRESENT_OPTION_NONE, msc, 0, 0, 0, NULL); + + DEBUG_OUT ("swap pixmap[%d]: 0x%x, msc: %llu\n", idx, back_pxmap, msc); + + // block pixmap/bo to next draw and swap operations + dri3_buffers[idx].busy = 1; +} + +// reallocate dri3_buff and corresponding pixmap and tbm bo +// idx - index inner array of dri3 buffers +//=================================================================== +static void +realloc_dri3_buff (uint32_t idx, uint16_t width, uint16_t height) +{ + if (idx >= gr_ctx.params.num_of_bufs) return; + + // release dmabuf file, old bo and pixmap + if (gr_ctx.mode != PRESENT_MODE) + { + if (dri3_buffers[idx].bo.bo) + { + tbm_bo_unref(dri3_buffers[idx].bo.bo); + DEBUG_OUT ("tbm bo: 0x%p has been unrefed.\n", dri3_buffers[idx].bo.bo); + } + + if (dri3_buffers[idx].bo.dma_buf_fd) + close (dri3_buffers[idx].bo.dma_buf_fd); + } + + if (dri3_buffers[idx].pxmap) + { + xcb_free_pixmap(display.dpy, dri3_buffers[idx].pxmap); + DEBUG_OUT ("pixmap: 0x%x has been freed.\n", dri3_buffers[idx].pxmap); + } + + // create new bo and pixmap + dri3_buffers[idx].pxmap_size.width = width; + dri3_buffers[idx].pxmap_size.height = height; + dri3_buffers[idx].pxmap = xcb_generate_id (display.dpy); + xcb_create_pixmap (display.dpy, DEPTH, dri3_buffers[idx].pxmap, display.wnd, + dri3_buffers[idx].pxmap_size.width, + dri3_buffers[idx].pxmap_size.height); + + DEBUG_OUT ("pixmap: 0x%x has been created.\n", dri3_buffers[idx].pxmap); + + // creates bo, tied toward pixmap, to do direct drawing in it + if (gr_ctx.mode != PRESENT_MODE) + dri3_buffers[idx].bo = get_bo_from_pixmap (dri3_buffers[idx].pxmap); + + dri3_buffers[idx].buff_must_be_realloc = 0; + + DEBUG_OUT ("buffer: %u has been reallocated (tbm_bo: 0x%p, pixamp: 0x%x, wxh: %hux%hu).\n", + idx, dri3_buffers[idx].bo.bo, dri3_buffers[idx].pxmap, width, height); +} + +//======================================================================== +//======================================================================== +//======================================================================== + + +// checks dri3 and present extensions, does dri3_open request and initiates +// tizen buffer manager +// return 0 if success, 1 otherwise +//=================================================================== +int +prepare_dri3_present_ext (void) +{ + uint32_t present_eid; + int i; + + // present initialization + + if (check_present_ext ()) return 1; + + // ask present extension to notify us about events + present_eid = xcb_generate_id (display.dpy); + xcb_present_select_input (display.dpy, present_eid, display.wnd, + XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY | + XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY | + XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY); + + // for determine dri3's events + dri3_present_info.present_ext = xcb_get_extension_data (display.dpy, &xcb_present_id); + if (!dri3_present_info.present_ext) + { + printf ("Error while xcb_get_extension_data call.\n"); + return 1; + } + + // dri3 initialization + + if (gr_ctx.mode != PRESENT_MODE) + { + dri3_present_info.drm_fd = prepare_dri3_ext(); + if (dri3_present_info.drm_fd < 0) return 1; + dri3_present_info.bufmgr = tbm_bufmgr_init (dri3_present_info.drm_fd); + } + + // allocate neccessary memory for dri3 buffers + dri3_buffers = calloc (gr_ctx.params.num_of_bufs, sizeof (dri3_buffer_t)); + + // set up dri3 buffers + for (i = 0; i < gr_ctx.params.num_of_bufs; i++) + realloc_dri3_buff (i, wnd_pos.width, wnd_pos.height); + + printf ("%u buffer(s) will be used.\n", gr_ctx.params.num_of_bufs); + + return 0; +} + +// dri3 events loop +//======================================================================== +void +dri3_loop (void) +{ + xcb_generic_event_t* event = NULL; + xcb_ge_generic_event_t* generic_event = NULL; + int i; +#ifndef _DEBUG_ + struct timespec start; +#endif + + // ask to be notifed by present extension about current msc + xcb_present_notify_msc (display.dpy, display.wnd, 0, 0, 0, 0); + + while (1) + { + xcb_flush (display.dpy); + event = xcb_wait_for_event (display.dpy); + if (!event) + { + DEBUG_OUT ("event returned by xcb_wait_for_event is NULL.\n"); + break; + } + + switch (event->response_type) + { + case XCB_GE_GENERIC: + { + generic_event = (xcb_ge_generic_event_t*)event; + + // if event is from present Ext. + if (generic_event->extension == dri3_present_info.present_ext->major_opcode) + { + switch (generic_event->event_type) + { + case XCB_PRESENT_CONFIGURE_NOTIFY: + { + xcb_present_configure_notify_event_t* config_ev; + config_ev = (xcb_present_configure_notify_event_t*)event; + + DEBUG_OUT ("XCB_PRESENT_CONFIGURE_NOTIFY: (%hd, %hd) [%hux%hu]\n", + config_ev->x, config_ev->y, config_ev->width, config_ev->height); + + for (i = 0; i < gr_ctx.params.num_of_bufs; i++) + dri3_buffers[i].buff_must_be_realloc = 1; + + wnd_pos.x = config_ev->x; + wnd_pos.y = config_ev->y; + wnd_pos.width = config_ev->width; + wnd_pos.height = config_ev->height; + } + break; + + case XCB_PRESENT_COMPLETE_NOTIFY: + { + DEBUG_OUT ("XCB_PRESENT_COMPLETE_NOTIFY:\n"); + + xcb_present_complete_notify_event_t* complete_ev; + complete_ev = (xcb_present_complete_notify_event_t*)event; + + if (complete_ev->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) + { +#ifdef _DEBUG_ + DEBUG_OUT (" XCB_PRESENT_COMPLETE_KIND_PIXMAP, serial = %u, msc = %llu, ", + complete_ev->serial, complete_ev->msc); + switch (complete_ev->mode) + { + case XCB_PRESENT_COMPLETE_MODE_COPY: + printf ("COPY.\n"); + break; + case XCB_PRESENT_COMPLETE_MODE_FLIP: + printf ("FLIP.\n"); + break; + case XCB_PRESENT_COMPLETE_MODE_SKIP: + printf ("SKIP.\n"); + break; + + default: + printf (" What is it?\n"); + break; + } +#endif + } + else if (complete_ev->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC) + { + DEBUG_OUT ("XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC\n"); + + // compute msc to use with present_pixmap request + target_msc = complete_ev->msc + gr_ctx.params.swap_interval; + } +#ifndef _DEBUG_ + fps_calc( &start ); + clock_gettime( CLOCK_REALTIME, &start ); +#endif + // if some delays are occured + if (target_msc <= complete_ev->msc) + target_msc = complete_ev->msc + gr_ctx.params.swap_interval; + + // complete_ev->msc - number of frame that is displayed now, + // or will be displayed soon, after vblank end. + // so we draw new frames in idle pixmaps and ask to present + // our frames to next mscs with some interval. + + // if we obtained XCB_PRESENT_IDLE_NOTIFY event without + // XCB_PRESENT_COMPLETE_NOTIFY, this means that present + // drop our frame and we can draw new frame, and ask to + // present it immediately, without waiting for XCB_PRESENT_COMPLETE_NOTIFY + // event, that will be delivered with some delay, but in this case, + // we don't know about real msc and new present may results new drop, + // so we will do present only when handling XCB_PRESENT_COMPLETE_NOTIFY event, + // despite of some performance decrease + for (i = 0; i < gr_ctx.params.num_of_bufs; i++) + { + // if buffer is busy (non-idle) + if (dri3_buffers[i].busy) + continue; + + draw (i); // draw our mesh + swap_buffers (target_msc, i); + + target_msc += gr_ctx.params.swap_interval; + } + } + break; + + case XCB_PRESENT_IDLE_NOTIFY: + { + xcb_present_idle_notify_event_t* idle_ev; + idle_ev = (xcb_present_idle_notify_event_t*)event; + + if (idle_ev->serial >= gr_ctx.params.num_of_bufs) + { + set_error ("invalid parameters from present extension.\n"); + pthread_cancel(thread_id); + } + + DEBUG_OUT ("----------------------------\n" + "XCB_PRESENT_IDLE_NOTIFY: pixmap: 0x%x (tied tbm bo: 0x%p), serial: %u, event: %u\n", + idle_ev->pixmap, dri3_buffers[idle_ev->serial].bo.bo, idle_ev->serial, idle_ev->event); + + // unblock pixmap/bo to next draw and swap operations + dri3_buffers[idle_ev->serial].busy = 0; + + // adjust pixmap/bo size to wnd's size before start render into it + if (dri3_buffers[idle_ev->serial].buff_must_be_realloc) + realloc_dri3_buff (idle_ev->serial, wnd_pos.width, wnd_pos.height); + } + break; + + default: + break; + } + } + } //case XCB_GE_GENERIC: + break; + + default: + DEBUG_OUT ("dri3_loop: default case.\n event->response_type = %d.\n", + event->response_type); + break; + } //switch (event->response_type) + } //while (1) +} diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.c b/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.c new file mode 100755 index 0000000..29df183 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.c @@ -0,0 +1,108 @@ +/************************************************************************** + + fps computation module's source + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 <stdio.h> + +#include "fps.h" + +#define BILLION 1000000000 +#define BILLION_F 1000000000.0f + +#define FPS_AVERAGE 1 // fps average value (in seconds) + +// for fps calculation +//===================================================================================== +void +fps_calc (const struct timespec* start) +{ + struct timespec end; + double time_diff; + double fps; + + static double sum_fps; + static time_t prev_time; + static int cnt = 1; + + if (!start) return; + + // note: start variable contains start time of time-execution measured code section + + // get time end of time-execution measured code section + clock_gettime (CLOCK_REALTIME, &end); + + // get difference in nanoseconds + time_diff = (double)( ( end.tv_sec - start->tv_sec ) * BILLION + + ( end.tv_nsec - start->tv_nsec ) ); + + // get frames per second value + fps = BILLION_F / time_diff; + + // average fps calculation + if (end.tv_sec - prev_time >= FPS_AVERAGE) + { + printf ("\033[8D"); + printf (" "); + printf ("\033[8D"); + printf ("%8.1f", sum_fps/cnt); + fflush (stdout); + + cnt = 0; + sum_fps = 0; + + prev_time = end.tv_sec; + } + else + { + cnt++; + sum_fps += fps; + } +} + +// return time diff (between time in 'start' and time when this function is called) +// in nanoseconds +//===================================================================================== +double +get_time_diff (const struct timespec* start) +{ + struct timespec end; + double time_diff; + + if (!start) return 0; + + // note: start variable contains start time of time-execution measured code section + + // get time end of time-execution measured code section + clock_gettime (CLOCK_REALTIME, &end); + + // get difference in nanoseconds + time_diff = (double)( ( end.tv_sec - start->tv_sec ) * BILLION + + ( end.tv_nsec - start->tv_nsec ) ); + return time_diff; +} diff --git a/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.h b/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.h new file mode 100755 index 0000000..bef0100 --- /dev/null +++ b/tests/functional/hwc_test/aux_dri2_dri3_lib/fps.h @@ -0,0 +1,47 @@ +/************************************************************************** + + fps computation module's header + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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 _FPS_H +#define _FPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <time.h> + +void fps_calc (const struct timespec* start); +double get_time_diff (const struct timespec* start); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/functional/hwc_test/clock.c b/tests/functional/hwc_test/clock.c new file mode 100644 index 0000000..97b24e8 --- /dev/null +++ b/tests/functional/hwc_test/clock.c @@ -0,0 +1,316 @@ +/************************************************************************** + + watch + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Roman Marchenko <r.marchenko@samsung.com> + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implements analog watch for using in semiautomatic tests for +// keep safe ddx driver devoloping + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <unistd.h> +#include <math.h> + +#include "aux_apps.h" +#include "dri2_dri3.h" + + +#define DEGREE_PER_SECOND (6) + + +typedef struct _point +{ + int x, y; + int color; +} PointRec, *PointPtr; + +typedef struct _circle +{ + PointRec center; + int R; +} CircleRec, *CirclePtr; + +typedef struct _warch +{ + CircleRec crcl; + int time; +} WatchRec, *WatchPtr; + + +xcb_connection_t* dpy = NULL; +xcb_screen_t* screen = NULL; +xcb_rectangle_t wnd_pos = {100, 100, 200, 200}; + +// work behavior flags: (see aux_apps.c for details) + +// mode of work (dri2/dri3+present) +int mode = DRI3_PRESENT_MODE; // by default dri3 + present will be used +int stop; +WatchRec watch; +uint32_t present_bufs = 3; +uint32_t swap_interval = 1; +uint32_t root_parent = 1; + +// functions set for render watch: + +inline void +set_point(PointPtr p, uint32_t *map, uint32_t pitch, uint32_t size) +{ + int off = (pitch * p->y + p->x); + if (off < size && off >= 0) + map[off] = p->color; +} + +inline void +draw_point(PointPtr p, uint32_t *map, uint32_t pitch, uint32_t size) +{ + set_point(p, map, pitch, size); + + p->x += 1; + set_point(p, map, pitch, size); + p->x -= 1; + + p->y += 1; + set_point(p, map, pitch, size); + p->y -= 1; + + p->x -= 1; + set_point(p, map, pitch, size); + p->x += 1; + + p->y -= 1; + set_point(p, map, pitch, size); + p->y += 1; +} + +void +draw_circle(CirclePtr c, uint32_t *map, uint32_t pitch, uint32_t size) +{ + double x0 = c->center.x; + double y0 = c->center.y; + double R = c->R; + + PointRec p = { 0, 0, c->center.color }; + + double fi; + int a; + for (a = 0; a < 360; a += DEGREE_PER_SECOND) + { + fi = M_PI / 180 * a; + p.x = (int) (x0 + R * cos(fi)); + p.y = (int) (y0 + R * sin(fi)); + draw_point(&p, map, pitch, size); + } +} + +void +draw_watch(WatchPtr w, uint32_t *map, uint32_t pitch, uint32_t size) +{ + draw_circle(&w->crcl, map, pitch, size); + + //drawing hand of the clock, use the change of radius + PointRec p = { 0, 0, w->crcl.center.color }; + + double fi = M_PI / 180 * (w->time * DEGREE_PER_SECOND); + + int R; + for (R = 0; R < (w->crcl.R - 3); R += 10) + { + p.x = (int) (w->crcl.center.x + R * cos(fi)); + p.y = (int) (w->crcl.center.y + R * sin(fi)); + draw_point(&p, map, pitch, size); + } +} + +/* +// +//=================================================================== +void +rotate (void) +{ + #define REFRESHE_TIME (16.0) // in ms + + struct timespec current; + static struct timespec prev; + double time_diff; + + clock_gettime (CLOCK_REALTIME, ¤t); + + // get difference in nanoseconds + time_diff = (double)( ( current.tv_sec - prev.tv_sec ) * 1000000000 + + ( current.tv_nsec - prev.tv_nsec ) ); + + if (time_diff / 1000000.0 > REFRESHE_TIME) + { + prev = current; + + watch.time++; + } + + #undef REFRESHE_TIME +} +*/ + +// direct accessing memory clear callback +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_clear (const bo_t* bo_e) +{ + xcb_rectangle_t rect; + + if (!bo_e) + { + printf ("raw_clear: invalid parameters.\n"); + return; + } + + rect.x = 0; + rect.y = 0; + rect.width = bo_e->width; + rect.height = bo_e->height; + + // simple draw black rectangle with size as window has + raw_fill_rect (bo_e, 1, &rect, screen->black_pixel); +} + +// direct accessing memory draw callback (watch drawing) +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_draw (const bo_t* bo_e) +{ + tbm_bo_handle hndl; + int* temp_map; + int i; + + if (!bo_e) + { + printf ("raw_draw: invalid parameters.\n"); + return; + } + + watch.crcl.R = (bo_e->width > bo_e->height) ? bo_e->height/2 : bo_e->width/2; + watch.crcl.center.x = bo_e->width / 2; + watch.crcl.center.y = bo_e->height / 2; + + hndl = tbm_bo_map (bo_e->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + if (!hndl.ptr) + { + printf ("raw_draw_line: Error while tbm_bo_map.\n"); + exit (1); + } + + // clear buffer + // we set all transparency bits to make buffer content fully + // un-transparency, actually to see this content over other buffers + temp_map = (int*)hndl.ptr; + for (i = 0; i < (bo_e->stride * bo_e->height)/sizeof(int); i++) + *temp_map++ = 0xff000000; + + draw_watch (&watch, (uint32_t*)hndl.ptr, bo_e->stride/4, + tbm_bo_size (bo_e->bo)/4); + + if (!stop) + watch.time++;//rotate (); + + tbm_bo_unmap (bo_e->bo); +} + +// +//=================================================================== +int +main (int argc, char** argv) +{ + xcb_generic_event_t* event = NULL; + xcb_window_t main_wnd; + draw_funcs_t draw_func; + dri2_dri3_params_t params; + int res; + + cmd_parse (argc, argv); + + dpy = xcb_connect (NULL, NULL); + + // get first screen of display + screen = xcb_setup_roots_iterator (xcb_get_setup (dpy)).data; + + main_wnd = create_window (dpy, 0xff, root_parent, "clock"); + + watch.crcl.R = (wnd_pos.width > wnd_pos.height) ? wnd_pos.height/2 : wnd_pos.width/2; + watch.crcl.center.x = wnd_pos.width / 2; + watch.crcl.center.y = wnd_pos.height / 2; + watch.crcl.center.color = 0xff00ff00; // set all transparency bits + + draw_func.raw_clear = NULL; + draw_func.raw_draw = raw_draw; + draw_func.xcb_clear = NULL; + draw_func.xcb_draw = NULL; + + params.num_of_bufs = present_bufs; + params.swap_interval = swap_interval; + + // inside init_dri2_dri3 new thread, responsible for dri2/dri3/present events + // handling, will be created + res = init_dri2_dri3 (dpy, &draw_func, mode, main_wnd, ¶ms); + if (res) + { + printf ("init_dri2_dri3: %s.\n", get_last_error()); + exit (1); + } + + printf ("before xcb loop.\n"); + + while (1) + { + xcb_flush (dpy); + event = xcb_wait_for_event (dpy); + if (!event) break; + + switch (event->response_type) + { + case XCB_EXPOSE: + DEBUG_OUT ("XCB_MAP_WINDOW\n"); + break; + + // if we are notified by XCB_BUTTON_PRESS event, we start/stop + // to change our frames, simple draw the same thing + case XCB_BUTTON_PRESS: + stop ^= 1; + break; + + default: + break; + } + } + + return 0; +} diff --git a/tests/functional/hwc_test/hwc_sample/hwc-sample.c b/tests/functional/hwc_test/hwc_sample/hwc-sample.c new file mode 100755 index 0000000..4e8ce0e --- /dev/null +++ b/tests/functional/hwc_test/hwc_sample/hwc-sample.c @@ -0,0 +1,1377 @@ +/************************************************************************** + + hwc_sample + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: SooChan Lim <sc1.lim@samsung.com> + Contact: Olexandr Rozov <o.rozov@samsung.com> + Contact: Roman Marchenko <r.marchenko@samsung.com> + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +/* This file contains implementation of software/hardware composition manager. + This app uses hwc, composite and damage extensions to create image of screen + from window's contents by using copy_area/drm planes.*/ + +#include <stdio.h> +#include <stdlib.h> + +#include <dlog.h> + +#include <xcb/composite.h> +#include <xcb/damage.h> +#include <xcb/hwc.h> + +#include "list.h" + +#define _DEBUG_ +#ifdef _DEBUG_ + #define DEBUG_OUT(format, args...) { ALOG(LOG_INFO, "HWC_SAMPLE", format, ##args); } +#else + #define DEBUG_OUT(...) {;} +#endif + +typedef struct cmd_options_t +{ + int not_use_hw_layers; // whether we want to use hardware layers to make compositing or not +} cmd_options_t; + +// thus structure describes window in window's list +typedef struct window_t +{ + struct list_head list_member; + xcb_window_t wnd_id; // X11 client sees only this id + xcb_window_t parent_id; // parent, after reparenting ! + xcb_pixmap_t wnd_content; // refered to off-screen storage of redirected window + xcb_hwc_draw_info_t hwc_info; // info for use in hwc_set_drawable + uint8_t use_hw_layer; // whether this window must be compositing via hardware layer + uint8_t off_hw_layer; // user can specify use or not hw layer for this window + uint8_t is_hidden; // is window hidden, this means window doesn't participate + // in composition + xcb_damage_damage_t damage; +} window_t; + +typedef struct window_manager_t +{ + struct list_head wnds_list_head; // list of grabbed windows, arranged by stack order position + u_int32_t amount; // amout of windows in above list + const xcb_query_extension_reply_t* damage_ext; // for determine damage's events + u_int32_t max_amount_hw_layers; // maximum available hardware layers + u_int32_t cur_amount_hw_layers; // current amount of utilized hardware layers + xcb_gcontext_t gc_soft_composite; // used for software compositing + xcb_gcontext_t gc_fill_root_buf; // used to fill root buffer + + // to avoid flickering, we just composite all windows to this pixmap, then, after + // composition of all window completed, composite this pixmap to root window + xcb_pixmap_t root_buffer; + + // information about windows which will be composited via hardware layers + xcb_hwc_draw_info_t* hwc_info; + cmd_options_t cmd_opts; // cmd line options + + // window pushed out from hw layer stack, when some window was set on top of this stack, + // this variable used for composite pushed out window in software only mode in time + // when hw composition for this (some) window occur + struct window_t* pushed_from_hw_stack; + +} window_manager_t; + +xcb_connection_t* xcb_dpy; +xcb_screen_t* xcb_screen; + +window_manager_t wm; + +// update root window +//======================================================================== +static void +_update_root (void) +{ + // composite root_buffer to root window to show on screen + xcb_copy_area (xcb_dpy, wm.root_buffer, xcb_screen->root, wm.gc_soft_composite, 0, 0, + 0, 0, xcb_screen->width_in_pixels, xcb_screen->height_in_pixels); + DEBUG_OUT (" composite root_buffer to root wnd.\n"); +} + +// update root_buffer, that can be then copied to root window via _update_root() +//======================================================================== +static void +_update_root_buf (window_t* wnd) +{ + if (!wnd) return; + + // composite window to root_buffer + xcb_copy_area (xcb_dpy, wnd->wnd_content, wm.root_buffer, wm.gc_soft_composite, 0, 0, + wnd->hwc_info.dstX, wnd->hwc_info.dstY, wnd->hwc_info.dstWidth, + wnd->hwc_info.dstHeight); + DEBUG_OUT (" off-screen storage: 0x%06x of wnd: 0x%06x (child wnd: 0x%06x) has been" + " composited to root_buffer at %hd, %hd, [%hux%hu].\n", wnd->wnd_content, + wnd->parent_id, wnd->wnd_id, wnd->hwc_info.dstX, wnd->hwc_info.dstY, + wnd->hwc_info.dstWidth, wnd->hwc_info.dstHeight); +} + +// fill root buffer before composite on it +//======================================================================== +static void +_fill_root_buffer (void) +{ + xcb_rectangle_t rect; + + rect.x = 0; + rect.y = 0; + rect.width = xcb_screen->width_in_pixels; + rect.height = xcb_screen->height_in_pixels; + + xcb_poly_fill_rectangle (xcb_dpy, wm.root_buffer, wm.gc_fill_root_buf, 1, &rect); + + DEBUG_OUT ("root_buffer has been filled.\n"); +} + +// +//======================================================================== +static void +_hwc_set_print_info (void) +{ + int i; + + DEBUG_OUT (" hwc_set_drawable:\n"); + + for (i = 0; i < wm.cur_amount_hw_layers; i++) + DEBUG_OUT (" drawable: 0x%06x, composite_method: %d, from %hd, %hd [ %hux%hu], " + "to %hd, %hd [%hux%hu].\n", + wm.hwc_info[i].drawable, wm.hwc_info[i].composite_methods, + wm.hwc_info[i].srcX, wm.hwc_info[i].srcY, wm.hwc_info[i].srcWidth, wm.hwc_info[i].srcHeight, + wm.hwc_info[i].dstX, wm.hwc_info[i].dstY, wm.hwc_info[i].dstWidth, wm.hwc_info[i].dstHeight); +} + +// do compositing of one drawable +// drawable - window id user application knows about which (passed root wnd will be ignored) !!! +//======================================================================== +static void +composite_drawable (xcb_drawable_t drawable) +{ + window_t* wnd; + int update_root = 0; + + // iterate over grabbed windows list, from topmost window to lowermost window + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + // look for window which must be recomposited + if (wnd->wnd_id != drawable || wnd->wnd_id == xcb_screen->root) continue; + + // if we in software only composite mode + if (wm.cmd_opts.not_use_hw_layers) + { + _update_root_buf (wnd); + _update_root (); + + break; + } + else + { + // if wnd isn't on hw layer, copy window content to root window + if (!wnd->use_hw_layer) + { + update_root = 1; + _update_root_buf (wnd); + } + + // if window is on hw layer it can pushed out, from hw layer stack, window that + // was on hw layer previously (it can be occurred after MapRequest for some window), + // so we must do sw composition for this pushed out window + else if (wm.pushed_from_hw_stack) + { + update_root = 1; + _update_root_buf (wm.pushed_from_hw_stack); + wm.pushed_from_hw_stack = NULL; + } + + // composite root_buffer to root window to show on screen, if root buffer was changed + if (update_root) _update_root (); + + // we must reset drawables, the main reason to do this, for windows which are on hw + // layers, is that present extension in X server makes swap of buffers, not copy + // (see present/present.c in Xorg) and we cann't distinguish no-dri, dri2 and present windows + xcb_hwc_set_drawable (xcb_dpy, 0, wm.cur_amount_hw_layers, wm.hwc_info); + _hwc_set_print_info (); + + break; + } + } + + xcb_flush (xcb_dpy); +} + +// do compositing of all windows, in any cases root window will be updated +//======================================================================== +static void +composite_all (void) +{ + window_t* wnd; + + DEBUG_OUT ("compositing of all windows:\n"); + + // fill root buffer before composite on it + _fill_root_buffer (); + + // if user doesn't want to do hardware compositing + if (wm.cmd_opts.not_use_hw_layers) + { + // iterate over grabbed windows list, from lowermost window to topmost window + // NOTE: this implementation of list ala stack, so we must use _prev suffix + list_for_each_prev_entry (wnd, &wm.wnds_list_head, list_member) + { + if (wnd->wnd_id == xcb_screen->root) + continue; + + _update_root_buf (wnd); + } + + _update_root (); + } + else + { + list_for_each_prev_entry (wnd, &wm.wnds_list_head, list_member) + { + if (wnd->use_hw_layer || wnd->wnd_id == xcb_screen->root) continue; + + _update_root_buf (wnd); + } + + // composite root_buffer to root window to show on screen, + _update_root (); + + xcb_hwc_set_drawable (xcb_dpy, 0, wm.cur_amount_hw_layers, wm.hwc_info); + _hwc_set_print_info (); + } + + xcb_flush (xcb_dpy); +} + +// return geometry of specified, by win_id, window (via second parameter) +// return -1 if fail +//======================================================================== +static int +get_wnd_geometry (xcb_window_t win_id, xcb_get_geometry_reply_t* geo) +{ + xcb_get_geometry_cookie_t gg_c; + xcb_get_geometry_reply_t* gg_r = NULL; + xcb_generic_error_t* xcb_error = NULL; + + if (!geo) return -1; + + gg_c = xcb_get_geometry (xcb_dpy, win_id); + gg_r = xcb_get_geometry_reply (xcb_dpy, gg_c, &xcb_error); + if (xcb_error) + { + printf ("error while xcb_get_geometry call.\n"); + free (xcb_error); + return -1; + } + + memcpy (geo, gg_r, sizeof(xcb_get_geometry_reply_t)); + + free (gg_r); + + return 0; +} + +// turn on external window events tracking +// in this function we ask X server to send us DestroyNotify, UnmapNotify events +// for window specified via @wnd->wnd_id +//======================================================================== +static int +turn_on_track_ext_wnd_events (window_t* wnd) +{ + xcb_void_cookie_t cookie; + xcb_generic_error_t* xcb_error; + + uint32_t value_mask; + uint32_t value_list[1]; + + if (!wnd) return -1; + + value_mask = XCB_CW_EVENT_MASK; + value_list[0] = XCB_EVENT_MASK_STRUCTURE_NOTIFY; + + // ask X server to send us DestroyNotify, UnmapNotify and other notify events + // for @wnd->wnd_id window + cookie = xcb_change_window_attributes_checked (xcb_dpy, wnd->wnd_id, value_mask, value_list); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_change_window_attributes call.\n"); + free (xcb_error); + return -1; + } + + printf (" turn on events tracking for external window: 0x%06x.\n\n", wnd->wnd_id); + + return 0; +} + +// TODO: +//======================================================================== +static void +unreparent_wnd (xcb_window_t wnd_id, xcb_window_t parent_id) +{ + xcb_destroy_window (xcb_dpy, parent_id); +} + +// create new window @parent_id with parent like parent of @wnd_id, +// with same geometry, visual, border width and depth, and reparent +// @wnd_id to new parent @parent_id +//======================================================================== +static int +reparent_wnd (xcb_window_t wnd_id, xcb_window_t* parent_id) +{ + xcb_get_geometry_reply_t geo; + + xcb_get_window_attributes_cookie_t get_attr_c; + xcb_get_window_attributes_reply_t* get_attr_r; + xcb_generic_error_t* xcb_errors = NULL; + + xcb_query_tree_cookie_t query_tree_c; + xcb_query_tree_reply_t* query_tree_r; + + xcb_void_cookie_t cookie; + int res; + + if (!parent_id) return -1; + + get_attr_c = xcb_get_window_attributes (xcb_dpy, wnd_id); + get_attr_r = xcb_get_window_attributes_reply (xcb_dpy, get_attr_c, &xcb_errors); + if (xcb_errors) + { + printf ("error while xcb_get_window_attributes call.\n"); + free (xcb_errors); + return -1; + } + + // for determine parent of window, identifiable by wnd_id + query_tree_c = xcb_query_tree (xcb_dpy, wnd_id); + query_tree_r = xcb_query_tree_reply (xcb_dpy, query_tree_c, &xcb_errors); + if (xcb_errors) + { + printf ("error while query_tree call.\n"); + free (xcb_errors); + goto fail_1; + } + + res = get_wnd_geometry (wnd_id, &geo); + if (res < 0) + goto fail_2; + + *parent_id = xcb_generate_id (xcb_dpy); + + cookie = xcb_create_window_checked (xcb_dpy, geo.depth, *parent_id, query_tree_r->parent, + geo.x, geo.y, geo.width, geo.height, geo.border_width, + get_attr_r->_class, get_attr_r->visual, 0, NULL); + if ((xcb_errors = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_create_window call.\n"); + free (xcb_errors); + goto fail_2; + } + + cookie = xcb_reparent_window_checked (xcb_dpy, wnd_id, *parent_id, 0, 0); + if ((xcb_errors = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_reparent_window call.\n"); + xcb_destroy_window (xcb_dpy, *parent_id); + free (xcb_errors); + goto fail_2; + } + + xcb_map_window (xcb_dpy, wnd_id); + + free (query_tree_r); + free (get_attr_r); + + return 0; + + // we cann't reparent window +fail_2: + free (query_tree_r); +fail_1: + free (get_attr_r); + return -1; +} + +// this function determines for which windows hw layers will be used, for composition +// Note: only this function can change @wnd->use_hw_layer field !!! +//======================================================================== +static void +_reorder_hw_layers_stack (void) +{ + window_t* wnd; + int i = 0; + + // iterate over grabbed windows list, from topmost window to lowermost window + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + // if window isn't hidden, if user allowed to use hw layer for this window + if (wnd->wnd_id != xcb_screen->root && !wnd->is_hidden && !wnd->off_hw_layer && i < (wm.max_amount_hw_layers - 1)) + { + i++; + wnd->use_hw_layer = 1; + } + else + { + // in this branch, only one window can has use_hw_layer field set to 1 + // this is window pushed out from hw layers stack, so we must save it + // and, then, when we will do composition for window that push, we also + // will do composition for pushed out window + if (wnd->use_hw_layer) + wm.pushed_from_hw_stack = wnd; + + wnd->use_hw_layer = 0; // all other window will be composited via sw way, except root wnd + } + } + + // Note: if some window was mapped it can result to push out lowest window (in hw layers stack) + // from hw layers stack. And if window was unmapped (hidden) in can result to push in + // window (for which wasn't available hw layer previously) to hw layer stack. +} + +// this function fills wm.hwc_info array used for hw composition (hwc_set_drawable request) +// we must call this function when: +// we have grabbed window - new grabbed window must be set on topmost hw layer +// wnd hierarchy is changed - to show this changes +// wnd geometry has been changed - to show this changes +// wnd was unmapped (hidden) - to show this changes +// NOTE: only this function can change wm.hwc_info array !!! +//======================================================================== +static void +set_hw_layers_stack (void) +{ + window_t* wnd; + int i = 0; + + _reorder_hw_layers_stack (); + + // reset hw layers stack + memset (wm.hwc_info, 0, wm.max_amount_hw_layers * sizeof(xcb_hwc_draw_info_t)); + + // iterate over grabbed windows list, from topmost window to lowermost window + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + // root is lowermost window in list + if (wnd->wnd_id == xcb_screen->root) + memcpy (&wm.hwc_info[i++], &wnd->hwc_info, sizeof(wnd->hwc_info)); + else if (wnd->use_hw_layer && i < (wm.max_amount_hw_layers - 1)) + memcpy (&wm.hwc_info[i++], &wnd->hwc_info, sizeof(wnd->hwc_info)); + } + + // set current amount of utilized hw layers to use in hwc_set_drawable request + wm.cur_amount_hw_layers = i; +} + +// init/reinit info for set window on hw layer +// wnd - id of window which hwc_info must be changed +// return -1 if fail +//======================================================================== +static int +init_hwc_info (window_t* wnd) +{ + xcb_get_geometry_reply_t geo; + int res; + + if (!wnd) return -1; + + res = get_wnd_geometry (wnd->wnd_id, &geo); + if (res < 0) return -1; + + wnd->hwc_info.drawable = wnd->wnd_id; + + wnd->hwc_info.srcX = 0; + wnd->hwc_info.srcY = 0; + wnd->hwc_info.srcWidth = geo.width; + wnd->hwc_info.srcHeight = geo.height; + + wnd->hwc_info.dstX = geo.x; + wnd->hwc_info.dstY = geo.y; + wnd->hwc_info.dstWidth = geo.width; + wnd->hwc_info.dstHeight = geo.height; + + wnd->hwc_info.composite_methods = XCB_HWC_COMPOSITE_METHOD_DEFAULT; + + return 0; +} + +// ungrab window - forget about window +// undo operations were done when window was grabbed +//======================================================================== +static void +ungrab_wnd (xcb_window_t wnd_id) +{ + window_t* wnd; + int res = 0; + + // iterate over grabbed windows list + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + if (wnd->wnd_id == wnd_id) + { + res = 1; + break; + } + } + + // check if we are asked to ungrab ungrabbed window + if (!res) return; + + // if we here we must ungrab window + + printf ("ungrab window: 0x%06x\n", wnd_id); + + wm.amount--; + + // just undo what have done when window grabbing was + xcb_damage_destroy (xcb_dpy, wnd->damage); + xcb_free_pixmap (xcb_dpy, wnd->wnd_content); + xcb_composite_unredirect_window (xcb_dpy, wnd->parent_id, XCB_COMPOSITE_REDIRECT_MANUAL); + xcb_destroy_window (xcb_dpy, wnd->parent_id); + list_del (&wnd->list_member); + free (wnd); + + // we destroy (unlink) window, so we must reset hw layers stack to new condition + if (!wm.cmd_opts.not_use_hw_layers) + set_hw_layers_stack (); +} + +// grab window - 'grab' means allocate window_t structure, add it to list of grabbed windows, +// fill it fields, reparent window, redirect parent window, obtain pixmap refered to off-screen +// storage of parent window, ask notice about damage on window, turn on external window events +// tracking and prepare hw layer stack +// wnd_id - id of window to grab +//======================================================================== +static void +grab_wnd (xcb_window_t wnd_id) +{ + window_t* wnd; + xcb_generic_error_t* xcb_error; + xcb_void_cookie_t cookie; + int res; + + // iterate over grabbed windows list, maybe we have grabbed window already + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + if (wnd->wnd_id == wnd_id) return; + } + + printf ("grab window: 0x%06x\n", wnd_id); + + // if we here, window hasn't be grabbed yet, so grap it + wnd = (window_t*)calloc (1, sizeof(window_t)); + + // add window to begin of grabbed windows list + // so we will obtain stack-ala list + list_add (&wnd->list_member, &wm.wnds_list_head); + + wnd->wnd_id = wnd_id; + + // prepare information to use in hwc_set_drawable request + res = init_hwc_info (wnd); + if (res < 0) + goto fail_1; + + // we mustn't reparent, redirect, create damage, obtain off-screen pixmap + // and reoder hw layers stack for root window + if (wnd->wnd_id != xcb_screen->root) + { + cookie = xcb_grab_server_checked (xcb_dpy); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_grab_server call.\n"); + free(xcb_error); + goto fail_1; + } + + res = reparent_wnd (wnd->wnd_id, &wnd->parent_id); + if (res < 0) + goto fail_1; + + cookie = xcb_composite_redirect_window_checked (xcb_dpy, wnd->parent_id, XCB_COMPOSITE_REDIRECT_MANUAL); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_composite_redirect_window call.\n"); + free(xcb_error); + goto fail_2; + } + + printf (" window: 0x%06x (child wnd: 0x%06x) has been redirected to off-screen storage.\n", + wnd->parent_id, wnd->wnd_id); + + xcb_map_window (xcb_dpy, wnd->parent_id); + + // obtain pixmap refered to off-screen storage of redirected window + wnd->wnd_content = xcb_generate_id (xcb_dpy); + cookie = xcb_composite_name_window_pixmap_checked (xcb_dpy, wnd->parent_id, wnd->wnd_content); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_composite_name_window_pixmap call.\n"); + free(xcb_error); + goto fail_3; + } + + printf (" off-screen storage: 0x%06x for window: 0x%06x (child wnd: 0x%06x) has been obtained.\n", + wnd->wnd_content, wnd->parent_id, wnd->wnd_id); + + // we track damage notification for window user know about which, not for it parent ! + wnd->damage = xcb_generate_id (xcb_dpy); + cookie = xcb_damage_create_checked (xcb_dpy, wnd->damage, wnd->wnd_id, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_damage_create call.\n"); + free(xcb_error); + goto fail_4; + } + + printf (" damage object: 0x%06x for window: 0x%06x (child wnd: 0x%06x) has been created.\n", + wnd->damage, wnd->parent_id, wnd->wnd_id); + + cookie = xcb_ungrab_server_checked (xcb_dpy); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_ungrab_server call.\n"); + free(xcb_error); + goto fail_5; + } + + // we must do this due to inability to set XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT and + // XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY flags together (for root wnd), so we must track + // events for all windows, via turn on tracking events for each window itself, no for + // their parent, as we did for MAP_REQUEST event + res = turn_on_track_ext_wnd_events (wnd); + if (res < 0) goto fail_5; + } + + // we have grabbed new window, so we must reset hw layers stack to new condition + if (!wm.cmd_opts.not_use_hw_layers) + set_hw_layers_stack (); + + wm.amount++; + + return; + + // we cann't grab this window +fail_5: + xcb_damage_destroy (xcb_dpy, wnd->damage); +fail_4: + xcb_free_pixmap (xcb_dpy, wnd->wnd_content); +fail_3: + xcb_composite_unredirect_window (xcb_dpy, wnd->parent_id, XCB_COMPOSITE_REDIRECT_MANUAL); +fail_2: + unreparent_wnd (wnd->wnd_id, wnd->parent_id); +fail_1: + list_del (&wnd->list_member); + free (wnd); + + return; +} + +// +//======================================================================== +/*static void +show_wnd (xcb_window_t wnd_id) +{ + +}*/ + +// when X11 client issue UnmapRequest for @wnd_id window we must remove this window +// from composition process, it isn't ungrabbing, we only 'hide' window from +// compositor and accordingly from user +//======================================================================== +static void +hide_wnd (xcb_window_t wnd_id) +{ + window_t* wnd; + xcb_generic_error_t* xcb_error; + xcb_void_cookie_t cookie; + int res = 0; + + // iterate over grabbed windows list + list_for_each_entry (wnd, &wm.wnds_list_head, list_member) + { + if (wnd->wnd_id == wnd_id) + { + res = 1; + break; + } + } + + // check if we are asked to hide ungrabbed window + if (!res) return; + + // if we here we must hide window + + printf ("hide window: 0x%06x\n", wnd_id); + + // hide window to avoid it to be composition participant + wnd->is_hidden = 1; + + // destroy damage to avoid unneccessary damage events, for this hidden window, handling + cookie = xcb_damage_destroy_checked (xcb_dpy, wnd->damage); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_damage_destroy call.\n"); + free(xcb_error); + } + + // we hide window, so we must reset hw layers stack to new condition + if (!wm.cmd_opts.not_use_hw_layers) + set_hw_layers_stack (); +} + +// check does @wnd_id window exist +// return -1 if doesn't, 0 otherwise +//======================================================================== +static int +check_wnd_existing (xcb_window_t wnd_id) +{ + xcb_generic_error_t* xcb_error; + xcb_void_cookie_t cookie; + + cookie = xcb_unmap_window_checked (xcb_dpy, wnd_id); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + free(xcb_error); + return -1; + } + + return 0; +} + +// handle X11 protocol events for children of root window +//======================================================================== +static void +handle_x11_events (xcb_generic_event_t* xcb_event) +{ + xcb_generic_error_t* xcb_error; + xcb_void_cookie_t cookie; + int ret; + + if (!xcb_event) return; + + switch (xcb_event->response_type) + { + #ifdef _DEBUG_ + case XCB_CLIENT_MESSAGE: + { + xcb_client_message_event_t* client_msg; + client_msg = (xcb_client_message_event_t*)xcb_event; + + DEBUG_OUT ("client message for window: 0x%06x, type: %u, format: %hhu.\n", + client_msg->window, client_msg->type, client_msg->format); + } + break; + #endif + + // when another X11 client call MapRequest we are notified about this, and only we + // can issue real MapRequest request + case XCB_MAP_REQUEST: + { + xcb_map_request_event_t* map_request; + map_request = (xcb_map_request_event_t*)xcb_event; + + printf ("somebody try to map window: 0x%06x.\n", map_request->window); + + grab_wnd (map_request->window); + + // after new window was grabbed we must composite it, only it + composite_drawable (map_request->window); + } + break; + + // when X11 client unmaps window, via xcb_unmap_window or just close sX11 connection, + // for example, just kills app's process + case XCB_UNMAP_NOTIFY: + { + break; + xcb_unmap_notify_event_t* unmap_notify; + unmap_notify = (xcb_unmap_notify_event_t*)xcb_event; + + printf ("unmap notify: window: 0x%06x, event: 0x%06x.\n", unmap_notify->window, + unmap_notify->event); + + hide_wnd (unmap_notify->window); + + // check does window still exist (UnmapNotify can be sent just before DestroyNotify, + // so we must not call composite_all() for XCB_UNMAP_NOTIFY handler, we will call it + // for XCB_DESTROY_NOTIFY handler) + xcb_grab_server (xcb_dpy); + + ret = check_wnd_existing (unmap_notify->window); + if (ret < 0) + { + printf (" window: 0x%06x still doesn't exist :-).\n", unmap_notify->window); + xcb_ungrab_server (xcb_dpy); + break; + } + + // after window was hidden we must composite all, currently... + composite_all (); + + // TODO: it is very expensive way... + xcb_ungrab_server (xcb_dpy); + } + break; + + // when X11 client destroys window, via xcb_destroy_window or just close sX11 connection, + // for example, just kills app's process + case XCB_DESTROY_NOTIFY: + { + xcb_destroy_notify_event_t* destroy_notify; + destroy_notify = (xcb_destroy_notify_event_t*)xcb_event; + + printf ("destroy notify: window: 0x%06x, event: 0x%06x.\n", destroy_notify->window, + destroy_notify->event); + + ungrab_wnd (destroy_notify->window); + + // after window was ungrabbed we must composite all, currently... + composite_all (); + } + break; + + default: + { + // handle damage events + // when client app has finished draw operations we receive damage notification + if (xcb_event->response_type == wm.damage_ext->first_event + XCB_DAMAGE_NOTIFY) + { + xcb_damage_notify_event_t* damage_ev; + damage_ev = (xcb_damage_notify_event_t*)xcb_event; + + DEBUG_OUT ("damage notification for wnd: 0x%06x, area: %hd %hd [%hux%hu], geo: %hd %hd [%hux%hu].\n", damage_ev->drawable, + damage_ev->area.x, damage_ev->area.y, damage_ev->area.width, damage_ev->area.height, + damage_ev->geometry.x, damage_ev->geometry.y, damage_ev->geometry.width, damage_ev->geometry.height); + + cookie = xcb_damage_subtract_checked (xcb_dpy, damage_ev->damage, XCB_NONE, XCB_NONE); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_damage_subtract call.\n"); + free(xcb_error); + } + + // we do composite only for window damage event has received for which + composite_drawable (damage_ev->drawable); + } + } + } +} + +// find all windows, which are root window's childrens and print information about them +// return -1 if fail +//======================================================================== +static int +find_all_window_ids (xcb_window_t** wnds_list, u_int32_t* wnds_amount) +{ + xcb_query_tree_cookie_t q_c; + xcb_query_tree_reply_t* q_r; + xcb_generic_error_t* xcb_errors = NULL; + int i; + + if (!wnds_list || !wnds_amount) return -1; + + q_c = xcb_query_tree (xcb_dpy, xcb_screen->root); + q_r = xcb_query_tree_reply (xcb_dpy, q_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("error while query_tree call.\n"); + return -1; + } + + // don't free *wnds_list, it points on no dynamic allocated memory + *wnds_list = xcb_query_tree_children (q_r); + *wnds_amount = xcb_query_tree_children_length (q_r); + + // print info ----------------------------------- + + printf (" RootWindow: 0x%06x.\n", xcb_screen->root); + printf (" root_return: 0x%06x.\n", q_r->root); + printf (" parent_return: 0x%06x.\n", q_r->parent); + printf (" nchildren_return: %u.\n", *wnds_amount); + + free (q_r); + + printf ("\nnumber window's id window's name\n"); + printf (" 0 0x%06x root\n", xcb_screen->root); + + for (i = 0; i < *wnds_amount; i++) + { + xcb_get_property_cookie_t gp_c; + xcb_get_property_reply_t* gp_r; + char* window_name; + + gp_c = xcb_get_property (xcb_dpy, 0, (*wnds_list)[i], XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 0); + gp_r = xcb_get_property_reply (xcb_dpy, gp_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + window_name = NULL; + } + else + { + if(!xcb_get_property_value_length (gp_r)) + window_name = NULL; + else + window_name = xcb_get_property_value (gp_r); + + free (gp_r); + } + + printf (" %d ", i + 1); + printf (" 0x%06x ", (*wnds_list)[i]); + printf (" %s\n", window_name); + + if (window_name) + free (window_name); + + } + printf ("\n"); + + return 0; +} + +// fill ai structure by using information about external windows +// ask X server to give us messages, which will be generated to external +// windows (for interception them) +//================================================================== +static int +grab_external_wnds (void) +{ + xcb_window_t* wnds_list = NULL; + uint32_t wnds_amount = 0; + int i, res; + + xcb_window_t* wnds_list_cp = NULL; + + printf ("\ngrab root window:\n "); + + // add root window to list of grabbed windows + grab_wnd (xcb_screen->root); + + printf ("grab all external windows:\n"); + + res = find_all_window_ids (&wnds_list, &wnds_amount); + if (res < 0) return -1; + + // if no external windows are on this time we don't grab them :-) + if (!wnds_amount) return 0; + + // we must do copy, because wnds_list points to array + // allocated inside xcb, so it will be rewritten on next xcb_query_tree call + // we mustn't free memory wnds_list points into, because it is not dynamic + // allocated memory + wnds_list_cp = (xcb_window_t*)calloc (wnds_amount, sizeof(xcb_window_t)); + memcpy (wnds_list_cp, wnds_list, wnds_amount * sizeof(xcb_window_t)); + + for (i = 0; i < wnds_amount; i++) + grab_wnd (wnds_list_cp[i]); + + free (wnds_list_cp); + + return 0; +} + +// prepare HWC extension for use +// return -1 if fail, otherwise amount of available layers(planes) +//======================================================================== +static int +hwc_ext_prepare (xcb_connection_t* c, xcb_screen_t* screen) +{ + xcb_hwc_query_version_cookie_t q_c; + xcb_hwc_query_version_reply_t* q_r; + xcb_generic_error_t* xcb_errors = NULL; + + xcb_hwc_open_cookie_t o_c; + xcb_hwc_open_reply_t* o_r; + + xcb_void_cookie_t s_i_c; + uint32_t max_layer; + + if (!c || !screen) return -1; + + // TODO: define XCB_HWC_MAJOR_VERSION is set to 1, but current version of hwc extension, + // supported by X server is 2 + q_c = xcb_hwc_query_version (c, 2, XCB_HWC_MINOR_VERSION); + q_r = xcb_hwc_query_version_reply (c, q_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("error while HWC query_version call.\n"); + return -1; + } + else if (q_r->major_version != 2 || q_r->minor_version != XCB_HWC_MINOR_VERSION) + { + printf ("HWC extension versions mismatch (between server: %u.%u and client: %u.%u).\n", + q_r->major_version, q_r->minor_version, XCB_HWC_MAJOR_VERSION, XCB_HWC_MINOR_VERSION); + free (q_r); + return -1; + } + + printf ("HWC extension: %d.%d.\n", q_r->major_version, q_r->minor_version); + + free (q_r); + + o_c = xcb_hwc_open (c, 0); + o_r = xcb_hwc_open_reply (c, o_c, &xcb_errors); + if (xcb_errors) + { + free (xcb_errors); + printf ("error while HWC open call.\n"); + return -1; + } + + max_layer = o_r->maxlayer; + free (o_r); + + printf (" hwc_open: maximum amount of hardware layers available to use: %u.\n", max_layer); + + // TODO: no define for mask for this call (third parameter), + // and I'm not sure about second parameter + s_i_c = xcb_hwc_select_input_checked (c, screen->root, 1); + + if ((xcb_errors = xcb_request_check (c, s_i_c))) + { + printf ("error while xcb_hwc_select_input call.\n"); + free(xcb_errors); + return -1; + } + + return max_layer; +} + +// prepare DAMAGE extension for use +// return NULL if fail +//================================================================== +static const xcb_query_extension_reply_t* +damage_ext_prepare (xcb_connection_t* c) +{ + xcb_damage_query_version_cookie_t q_c; + xcb_damage_query_version_reply_t* q_r; + xcb_generic_error_t* xcb_errors = NULL; + const xcb_query_extension_reply_t* damage_ext; + + if (!c) return NULL; + + // for determine damage's events + damage_ext = xcb_get_extension_data (c, &xcb_damage_id); + if (!damage_ext) + { + printf ("error while xcb_get_extension_data call.\n"); + return NULL; + } + + q_c = xcb_damage_query_version (c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); + q_r = xcb_damage_query_version_reply (c, q_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("error while DAMAGE extension query_version call.\n"); + return NULL; + } + else if (q_r->major_version != XCB_DAMAGE_MAJOR_VERSION || q_r->minor_version != XCB_DAMAGE_MINOR_VERSION) + { + printf ("DAMAGE extension versions mismatch (between server: %u.%u and client: %u.%u).\n", + q_r->major_version, q_r->minor_version, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); + free (q_r); + return NULL; + } + + printf ("DAMAGE extension: %d.%d.\n", q_r->major_version, q_r->minor_version); + printf (" major_opcode: %hhu, first_event: %hhu, first_erorr: %hhu.\n", + damage_ext->major_opcode, damage_ext->first_event, damage_ext->first_error); + + free (q_r); + + return damage_ext; +} + +// prepare COMPOSITE extension for use +// return -1 if fail +//======================================================================== +static int +composite_ext_prepare (xcb_connection_t* c) +{ + xcb_composite_query_version_cookie_t q_c; + xcb_composite_query_version_reply_t* q_r; + xcb_generic_error_t* xcb_errors = NULL; + + if (!c) return -1; + + q_c = xcb_composite_query_version (c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION); + q_r = xcb_composite_query_version_reply (c, q_c, &xcb_errors); + + if (xcb_errors) + { + free (xcb_errors); + printf ("error while COMPOSITE query_version call.\n"); + return -1; + } + else if (q_r->major_version != XCB_COMPOSITE_MAJOR_VERSION || q_r->minor_version != XCB_COMPOSITE_MINOR_VERSION) + { + printf ("COMPOSITE extension versions mismatch (between server: %u.%u and client: %u.%u).\n", + q_r->major_version, q_r->minor_version, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION); + free (q_r); + return -1; + } + + printf ("COMPOSITE extension: %d.%d.\n", q_r->major_version, q_r->minor_version); + + free (q_r); + + return 0; +} + +// create root_buffer to composite on it contents of windows (to avoid flickering) +// after all window contents will be on root_buffer composite it to root window to show +// also we ask X server to send us MapRequest, ConfigureRequest, CirculateRequest and +// ResizeRequest events for all root's children. +// (these request are sent when somebody try to map, reconfigure or resize root's children +// window, and we can decide what to do whith this request. +// for example: when somebody issues MapRequest via xcb_map_window, real map isn't occured, but +// MapRequest event is sent us and we can properly react on it.) +// also fill root_buffer pixmap and root window +// return -1 if fail +//======================================================================== +static int +prepare_root (void) +{ + xcb_void_cookie_t cookie; + xcb_generic_error_t* xcb_error; + + uint32_t value_mask; + uint32_t value_list[1]; + + wm.root_buffer = xcb_generate_id (xcb_dpy); + cookie = xcb_create_pixmap_checked (xcb_dpy, xcb_screen->root_depth, wm.root_buffer, xcb_screen->root, + xcb_screen->width_in_pixels, xcb_screen->height_in_pixels); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_create_pixmap call.\n"); + free(xcb_error); + return -1; + } + + value_mask = XCB_CW_EVENT_MASK; + value_list[0] = XCB_EVENT_MASK_RESIZE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; + + // this call must be done after any windows create call !!! + // also we ask X server to send us MapRequest, ConfigureRequest, CirculateRequest and + // ResizeRequest events for all root's children. + cookie = xcb_change_window_attributes_checked (xcb_dpy, xcb_screen->root, value_mask, value_list); + if ((xcb_error = xcb_request_check (xcb_dpy, cookie))) + { + printf ("error while xcb_change_window_attributes call.\n"); + free(xcb_error); + return -1; + } + + return 0; +} + +// +//======================================================================== +static xcb_gcontext_t +create_gc (xcb_connection_t* c, xcb_screen_t* screen, uint32_t foreground) +{ + xcb_gcontext_t gc; + xcb_void_cookie_t cookie; + xcb_generic_error_t* error; + uint32_t value[2]; + + if (!c || !screen) + { + printf ("error while create_gc call.\n"); + exit (EXIT_FAILURE); + } + + value[0] = XCB_GX_COPY; + value[1] = foreground; + + gc = xcb_generate_id (c); + cookie = xcb_create_gc_checked (c, gc, screen->root, XCB_GC_FUNCTION | XCB_GC_FOREGROUND, value); + xcb_flush (c); + + if ((error = xcb_request_check (c, cookie))) + { + printf ("error while xcb_create_gc call.\n"); + free(error); + exit (EXIT_FAILURE); + } + + return gc; +} + +// +//================================================================== +static void +usage (char *argv) +{ + printf ("This application is simple sw/hw compositor manager. It can be used to test " + "ddx's side of hwc, dri2 and dri3/present extensions.\n" + "You can launch clients apps and then launch this compositor manager, or you " + "can launch firstly compositor manager and then\nclient apps.\n\n"); + + printf ("%s usage : \n", argv); + printf (" %s (options) (parameters)\n", argv); + printf (" (options) :\n"); + printf (" -no_hw : don't use hw layers to composition (only software composition)\n"); +} + +// parse command line +// returns -1 if failed +//================================================================== +static int +check_options (int argc, char *argv[]) +{ + int j = 0; + + if (!argv) return -1; + + // check if we want to know how use this app + for (j = 1; j < argc; j++) + { + if (!strcmp (argv[j], "--help")) + { + usage (argv[0]); + return -1; + } + } + + // check if we don't want to use hardware layers + for (j = 1; j < argc; j++) + { + if (!strcmp (argv[j], "--no_hw")) + { + wm.cmd_opts.not_use_hw_layers = 1; // we will do only software composition + break; + } + } + + return 0; +} + +// +//======================================================================== +int +main (int argc, char *argv[]) +{ + xcb_generic_event_t* xcb_event = NULL; + int res; + + // parse cmdline + res = check_options (argc, argv); + if (res < 0) goto fail; + + // open the connection to the X server + xcb_dpy = xcb_connect (NULL, NULL); + res = xcb_connection_has_error (xcb_dpy); + if (res > 0) + { + printf ("error while open X display.\n"); + goto fail; + } + + // get first screen of display + xcb_screen = xcb_setup_roots_iterator (xcb_get_setup (xcb_dpy)).data; + if (!xcb_screen) + { + printf ("error while obtain first screen of X display.\n"); + goto fail; + } + + wm.gc_soft_composite = create_gc (xcb_dpy, xcb_screen, 0x00); + wm.gc_fill_root_buf = create_gc (xcb_dpy, xcb_screen, 0x555555); + + res = prepare_root (); + if (res < 0) goto fail; + + // prepare extensions needed for this window manager + res = composite_ext_prepare (xcb_dpy); + if (res < 0) goto fail; + + wm.damage_ext = damage_ext_prepare (xcb_dpy); + if (!wm.damage_ext) goto fail; + + res = hwc_ext_prepare (xcb_dpy, xcb_screen); + if (res < 0) goto fail; + + wm.max_amount_hw_layers = res; + + // if we haven't available hardware layers, we will use only software compositing + if (wm.max_amount_hw_layers) + wm.hwc_info = calloc (wm.max_amount_hw_layers, sizeof(xcb_hwc_draw_info_t)); + + // init list of grabbed windows + list_init (&wm.wnds_list_head); + + // grab external windows + res = grab_external_wnds (); + if (res < 0) goto fail; + + // in this point we have list of grabbed windows, arranged by stack order position, + // so we can do compositing (software or hardware depend on not_use_hw_layers flag and amount of + // available hardware layers) + + composite_all (); + + // events handle loop + + while (1) + { + xcb_flush (xcb_dpy); + xcb_event = xcb_wait_for_event (xcb_dpy); + if (!xcb_event) + { + printf ("event returned by xcb_wait_for_event is NULL.\n"); + goto fail; + } + + DEBUG_OUT ("event: %hhu.\n", xcb_event->response_type); + + handle_x11_events (xcb_event); + free (xcb_event); + } + +fail: + printf ("abnormal exit.\n"); + + if (wm.gc_fill_root_buf) + xcb_free_gc (xcb_dpy, wm.gc_fill_root_buf); + + if (wm.gc_soft_composite) + xcb_free_gc (xcb_dpy, wm.gc_soft_composite); + + if (xcb_dpy) + xcb_disconnect (xcb_dpy); + + return 1; +} diff --git a/tests/functional/hwc_test/hwc_sample/hwc-sample.h b/tests/functional/hwc_test/hwc_sample/hwc-sample.h new file mode 100644 index 0000000..f41a302 --- /dev/null +++ b/tests/functional/hwc_test/hwc_sample/hwc-sample.h @@ -0,0 +1,69 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +//#include <X11/X.h> +#include <X11/Xlib.h> +//#include <X11/Xutil.h> +//#include <X11/Xatom.h> +//#include <X11/Xos.h> +//#include <X11/cursorfont.h> +//#include <X11/extensions/hwc.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <pthread.h> +#include <sys/types.h> + +#define AMOUNT_OF_PLANES 4 + +// hwc_set values: +// 1 - set pixmap(s) +// 2 - set window(s) (internal or external) +// 3 - loop +// 4 - move window +// 5 - resize window + +typedef struct _ThreadData +{ + //Pixmap pixmap; + int width; + int height; + + pthread_t thread; +} ThreadData; + +struct app_info +{ + int maxLayer; + int count; + int wnd_to_change; + //Drawable draws[AMOUNT_OF_PLANES]; + //XRectangle dst[AMOUNT_OF_PLANES]; + //XRectangle src[AMOUNT_OF_PLANES]; + int hwc_set; // picked work mode + int use_root; + int hwc_unset; + int hwc_loop; + int redirect; // whether X server does redirect to each created window or not + int not_use_hw_layers; // whether we want to use hardware layers to make compositing or not + int set_all_ext_wnds; // whether we want to use all existing external windows or not + int set_spec_ext_wnds; // only specified wnds + int num_of_ext_wnds; // amount of all/specified external windows to want to set + //Window* ext_wnd_ids; // array of specified external windows id's +}; + +extern struct app_info ai; +//extern Window root, change_size, move_btn, change_stack_order; +extern int wd1, ht1; +extern int dispsize_width, dispsize_height; + +extern void* thread1_hwcsample (void *data); +void change_focus (void); +void hwc_set (void); +void hwc_movew (void); +void hwc_resizew (void); + +int launch_clients (char* clients[], int num_of_clients); + +#endif diff --git a/tests/functional/hwc_test/hwc_sample/hwc-thread.c b/tests/functional/hwc_test/hwc_sample/hwc-thread.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/functional/hwc_test/hwc_sample/hwc-thread.c diff --git a/tests/functional/hwc_test/hwc_sample/list.h b/tests/functional/hwc_test/hwc_sample/list.h new file mode 100644 index 0000000..51a841d --- /dev/null +++ b/tests/functional/hwc_test/hwc_sample/list.h @@ -0,0 +1,24 @@ +#ifndef _LIST_H +#define _LIST_H + +#include <X11/X.h> +#include <xorg/list.h> + +// just because without xorg_ prefix macros look more pretty +// Note: this isn't bridge between linux kernel list and xorg list. +#define list_head xorg_list +#define list_entry xorg_list_entry +#define list_add xorg_list_add +#define list_append xorg_list_append +#define list_del xorg_list_del +#define list_for_each_entry xorg_list_for_each_entry + +// be carefully, this macros checked only in gdb +#define list_for_each_prev_entry(pos, head, member) \ + for (pos = __container_of((head)->prev, pos, member);\ + &pos->member != (head);\ + pos = __container_of(pos->member.prev, pos, member)) + +#define list_init xorg_list_init + +#endif diff --git a/tests/functional/hwc_test/launch.sh b/tests/functional/hwc_test/launch.sh new file mode 100755 index 0000000..9009e96 --- /dev/null +++ b/tests/functional/hwc_test/launch.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# restart X server without Enlightenment +echo -n "restart X server..." + +pkill X +startx --only 2> /dev/null +sleep 2 + +echo " ok." + +echo -n "close all windows..." + +# sometimes, after startx --only, we have few strange windows, +# we must close them to proper work of hwc-sample and square_bubbles +square_bubbles -cls > /dev/null + +echo " ok." + +echo "start apps:" + +snowflake -geo 200x200 100 100& +snowflake -geo 200x200 200 200& +snowflake -geo 200x200 500 500& + +echo " snowflake -geo 200x200 100 100" +echo " snowflake -geo 200x200 200 200" +echo " snowflake -geo 200x200 500 500" + +sleep 1 + +echo -n "start square_bubbles..." +square_bubbles -m -s > /dev/null & +echo " ok." + +echo " sleep 15 sec" +sleep 15 + +echo -n "start hwc_sample..." +hwc_sample -redir -setr > /dev/null & +echo " ok." + +echo " sleep 15 sec" +sleep 15 + +pkill square_bubbles +pkill hwc_sample +pkill snowflake diff --git a/tests/functional/hwc_test/snowflake.c b/tests/functional/hwc_test/snowflake.c new file mode 100644 index 0000000..ee1fee0 --- /dev/null +++ b/tests/functional/hwc_test/snowflake.c @@ -0,0 +1,327 @@ +/************************************************************************** + + rotated snowflake + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Roman Peresipkyn <r.peresipkyn@samsung.com> + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implements rotated snowflake for using in semiautomatic tests for +// keep safe ddx driver devoloping + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <unistd.h> +#include <math.h> +#include <time.h> + +#include "aux_apps.h" +#include "dri2_dri3.h" + + +#define DEPTH (24) + +#define ROTATE_SPEED (-180.0) // degrees per second +#define MARGIN (10) +#define SNOWFLAKE_POINTS (36) + +typedef struct point_t +{ + double x; + double y; +} point; + +typedef struct matrix_t +{ + double a1; + double a2; + double b1; + double b2; +} matrix; + +xcb_connection_t* dpy = NULL; +xcb_screen_t* screen = NULL; +xcb_rectangle_t wnd_pos = {100, 100, 150, 150}; + +// work behavior flags: (see aux_apps.c for details) + +// mode of work (dri2/dri3+present) +int mode = DRI3_PRESENT_MODE; // by default dri3 + present will be used +int stop; +double rotate_speed = ROTATE_SPEED; +uint32_t present_bufs = 3; +uint32_t swap_interval = 1; +uint32_t root_parent = 1; + +// matrix for rotation +matrix current_rot; + +// our mesh +const point snowflake[SNOWFLAKE_POINTS] = { + // up-down + {0.0, -4.0 * 0.25}, {0.0, 4.0 * 0.25}, + + // left-right + {-4.0 * 0.25, 0.0}, {4.0 * 0.25, 0.0}, + + // upleft-downright + {-3.0 * 0.25, 3.0 * 0.25}, {3.0 * 0.25, -3.0 * 0.25}, + + // upright-downleft + {3.0 * 0.25, 3.0 * 0.25}, {-3.0 * 0.25, -3.0 * 0.25}, + + // branch up-right + {2.0 * 0.25, 3.0 * 0.25}, {2.0 * 0.25, 2.0 * 0.25}, {3.0 * 0.25, 2.0 * 0.25}, + + // branch up + {-1.0 * 0.25, 4.0 * 0.25}, {0.0, 3.0 * 0.25}, {1.0 * 0.25, 4.0 * 0.25}, + + // branch up-left + {-2.0 * 0.25, 3.0 * 0.25}, {-2.0 * 0.25, 2.0 * 0.25}, {-3.0 * 0.25, 2.0 * 0.25}, + + // branch left + {-4.0 * 0.25, 1.0 * 0.25}, {-3.0 * 0.25, 0.0 * 0.25}, {-4.0 * 0.25, -1.0 * 0.25}, + + // branch down-left + {-3.0 * 0.25, -2.0 * 0.25}, {-2.0 * 0.25, -2.0 * 0.25}, {-2.0 * 0.25, -3.0 * 0.25}, + + // branch down + {-1.0 * 0.25, -4.0 * 0.25}, {0.0 * 0.25, -3.0 * 0.25}, {1.0 * 0.25, -4.0 * 0.25}, + + // branch down-right + {2.0 * 0.25, -3.0 * 0.25}, {2.0 * 0.25, -2.0 * 0.25}, {3.0 * 0.25, -2.0 * 0.25}, + + // branch right + {4.0 * 0.25, -1.0 * 0.25}, {3.0 * 0.25, 0.0 * 0.25}, {4.0 * 0.25, 1.0 * 0.25}, + + // + {-1.5 * 0.25, 0.0 * 0.25}, {0.0 * 0.25, 1.5 * 0.25}, {1.5 * 0.25, 0.0 * 0.25}, {0.0 * 0.25, -1.5 * 0.25} +}; + +// calculate rotation matrix 'mtrx' for rotate at angle 'alpha' +//=================================================================== +inline void +set_rotation_matrix (double alpha, matrix* mtrx) +{ + mtrx->a1 = cos (alpha); + mtrx->a2 = -sin (alpha); + mtrx->b1 = -mtrx->a2; + mtrx->b2 = mtrx->a1; +} + +// make fps-independent rotation +//=================================================================== +void +rotate (void) +{ + #define REFRESHE_TIME (16.0) // in ms + + static double angle; + struct timespec current; + static struct timespec prev; + double time_diff; + + clock_gettime (CLOCK_REALTIME, ¤t); + + // get difference in nanoseconds + time_diff = (double)( ( current.tv_sec - prev.tv_sec ) * 1000000000 + + ( current.tv_nsec - prev.tv_nsec ) ); + + if (time_diff / 1000000.0 > REFRESHE_TIME) + { + prev = current; + + angle += rotate_speed * 2.0 * M_PI / 360.0 * (REFRESHE_TIME/1000.0); + + set_rotation_matrix (angle, ¤t_rot); + } + + #undef REFRESHE_TIME +} + +// direct accessing memory clear callback +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_clear (const bo_t* bo_e) +{ + xcb_rectangle_t rect; + + if (!bo_e) + { + printf ("raw_clear: invalid parameters.\n"); + return; + } + + rect.x = 0; + rect.y = 0; + rect.width = bo_e->width; + rect.height = bo_e->height; + + // simple draw black rectangle with size as window has + raw_fill_rect (bo_e, 1, &rect, 0xff000000 | screen->black_pixel); +} + +// direct accessing memory draw callback (snowflake drawing) +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_draw (const bo_t* bo_e) +{ + int i; + point temp[SNOWFLAKE_POINTS]; + xcb_point_t xcb_points[SNOWFLAKE_POINTS + 1]; + + if (!bo_e) + { + printf ("raw_draw: invalid parameters.\n"); + return; + } + + for (i = 0; i < SNOWFLAKE_POINTS; i++) + { + // calculate point's coords (in OpenGL world) of mesh taking in account + // current rotate angle (current_rot matrix) + temp[i].x = snowflake[i].x * current_rot.a1 + snowflake[i].y * current_rot.a2; + temp[i].y = snowflake[i].x * current_rot.b1 + snowflake[i].y * current_rot.b2; + + // convert coordinates into X world + xcb_points[i].x = MARGIN + (1.0 / 2.0) * (temp[i].x + 1.0) * (bo_e->width - 2 * MARGIN); + xcb_points[i].y = MARGIN + (-1.0 / 2.0) * (temp[i].y - 1.0) * (bo_e->height - 2 * MARGIN); + } + + raw_draw_line (bo_e, 2, &xcb_points[0], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 2, &xcb_points[2], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 2, &xcb_points[4], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 2, &xcb_points[6], 0xff000000 | screen->white_pixel); + + raw_draw_line (bo_e, 3, &xcb_points[8], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[11], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[14], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[17], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[20], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[23], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[26], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[29], 0xff000000 | screen->white_pixel); + raw_draw_line (bo_e, 3, &xcb_points[29], 0xff000000 | screen->white_pixel); + + xcb_points[SNOWFLAKE_POINTS] = xcb_points[32]; // loop + raw_draw_line (bo_e, 5, &xcb_points[32], screen->white_pixel); + + if (stop) return; + + rotate (); +} + +// parse command line +//======================================================================== +void +cmd_parse_inner (int argc, char* const argv[]) +{ + int i; + + if (argc < 2) return; + + // if we want to set rotate speed. + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-rot_speed") && (argc - i > 1)) + { + sscanf (argv[i + 1], "%lf", &rotate_speed); + break; + } + } + + // call default cl parser to parse another arguments + cmd_parse (argc, argv); + } + +// +//=================================================================== +int +main (int argc, char** argv) +{ + xcb_generic_event_t* event = NULL; + xcb_window_t main_wnd; + draw_funcs_t draw_func; + dri2_dri3_params_t params; + int res; + + cmd_parse_inner (argc, argv); + + dpy = xcb_connect (NULL, NULL); + + // get first screen of display + screen = xcb_setup_roots_iterator (xcb_get_setup (dpy)).data; + + main_wnd = create_window (dpy, 0xff, root_parent, "rotated snowflake"); + + draw_func.raw_clear = raw_clear; + draw_func.raw_draw = raw_draw; + draw_func.xcb_clear = NULL; + draw_func.xcb_draw = NULL; + + params.num_of_bufs = present_bufs; + params.swap_interval = swap_interval; + + // inside init_dri2_dri3 new thread, responsible for dri2/dri3/present events + // handling, will be created + res = init_dri2_dri3 (dpy, &draw_func, mode, main_wnd, ¶ms); + if (res) + { + printf ("init_dri2_dri3: %s.\n", get_last_error()); + exit (1); + } + + printf ("before xcb loop.\n"); + + while (1) + { + xcb_flush (dpy); + event = xcb_wait_for_event (dpy); + if (!event) break; + + switch (event->response_type) + { + case XCB_EXPOSE: + DEBUG_OUT ("XCB_MAP_WINDOW\n"); + break; + + // if we are notified by XCB_BUTTON_PRESS event, we start/stop + // to change our frames, simple draw the same thing + case XCB_BUTTON_PRESS: + stop ^= 1; + break; + + default: + break; + } + } + + return 0; +} diff --git a/tests/functional/hwc_test/square_bubbles/square_bubbles.c b/tests/functional/hwc_test/square_bubbles/square_bubbles.c new file mode 100755 index 0000000..f454f0c --- /dev/null +++ b/tests/functional/hwc_test/square_bubbles/square_bubbles.c @@ -0,0 +1,647 @@ +/************************************************************************** + + square_bubbles + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// This file implements window's manipulation like side-bump bubbles +// through Xlib. This app can be used with hwc-sample to pretty view of HWC work. +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> +#include <math.h> +#include <fcntl.h> + +#include <X11/X.h> +#include <X11/Xlib.h> + +#define _DEBUG 1 +#define MAX_WNDS (3) // apart root window +#define SCREEN_WIDTH (720) +#define SCREEN_HEIGHT (1280) +#define ODD_INTERVAL (10) // interval of wnd's size odd changing (in seconds) +#define RESIZE_SPEED (0.8) // radians per second + +typedef enum Direct_t +{ + UP_RIGHT, + DOWN_RIGHT, + UP_LEFT, + DOWN_LEFT +} Direct; + +typedef struct bubbles_t +{ + XRectangle curr_geometry; + XRectangle first_geometry; + u_int32_t x_range; + u_int32_t y_range; + Window id; + Direct direct; + double angle; +} bubbles; + +// Xsever specific variables +Display* dpy; +Window root; +int depth; +int screen; + +// information about all external windows (with names) +Window* root_childrens; +unsigned int nchildrens; + +bubbles square_bubbles[MAX_WNDS]; +unsigned int real_cnt; + +// we can only close all windows by pass '-cls' to this app +int cls; // whether we need to close all windows or not + +int move; // whether we need to move all windows or not +int change_size; // whether we need to change size of all windows or not +int delay = 50; // delay between bubbles's position&size calculation in ms + +int debug = 1; // whether we want to print or not + +int all_wnds = 1; // whether we want to manipulate all windows or not +int odd_size; // whether we want to use odd sizes of windows + +void cmd_parse (int argc, char* argv[]); +int find_all_window_ids (void); +XRectangle get_wnd_geometry (Window win_id); +void shift_wnd (bubbles* s_b); + +// this function returns randomized 32 bit unsigned value +// in order to bypass prevent (static analizator) warning (don't use rand() function) +//======================================================================== +u_int32_t +hand_made_rand (void) +{ + int ret, fd; + u_int32_t rand_number; + + fd = open ("/dev/urandom", O_RDONLY); + if (fd < 0) + return 11; // why 11, why not? + + // simple read 4 random bytes from /dev/urandom + ret = read (fd, &rand_number, sizeof(u_int32_t)); + if (ret < 0 || ret != sizeof(rand_number)) + rand_number = 11; // why 11, why not? + + close (fd); + + return rand_number; +} + +//======================================================================== +int +main (int argc, char* argv[]) +{ + int i; + + cmd_parse (argc, argv); + + if (!change_size && !move) + { + printf ("nothing to do, specify what you want (i.e: square_bubbles -m -s).\n"); + return 1; + } + + // delay is passed in ms, but usleep requires delay in mcs + delay *= 1000; + + dpy = XOpenDisplay ( NULL); + + if (!dpy) + { + printf ("error while XOpenDisplay call.\n"); + return 1; + } + + root = DefaultRootWindow(dpy); + screen = DefaultScreen(dpy); + depth = DefaultDepth(dpy, screen); + + if (all_wnds) + { + // allocate memory for root_childrens[] array + if (find_all_window_ids ()) + { + XCloseDisplay (dpy); + return 0; + } + } + + // we can supply up to MAX_WNDS windows only + real_cnt = nchildrens <= MAX_WNDS ? nchildrens : MAX_WNDS; + + if (!real_cnt) + { + printf ("no windows to manipulate.\n"); + XCloseDisplay (dpy); + return 0; + } + + // prior initialization + for (i = 0; i < real_cnt; i++) + { + square_bubbles[i].id = root_childrens[i]; + square_bubbles[i].curr_geometry = get_wnd_geometry (root_childrens[i]); + square_bubbles[i].direct = hand_made_rand () % 4; + + memcpy (&square_bubbles[i].first_geometry, &square_bubbles[i].curr_geometry, + sizeof(square_bubbles[i].first_geometry)); + square_bubbles[i].x_range = square_bubbles[i].first_geometry.width / 4; + square_bubbles[i].y_range = square_bubbles[i].first_geometry.height / 4; + } + + while (1) + { + for (i = 0; i < real_cnt; i++) + { + shift_wnd (&square_bubbles[i]); + + XMoveResizeWindow (dpy, square_bubbles[i].id, square_bubbles[i].curr_geometry.x, + square_bubbles[i].curr_geometry.y, square_bubbles[i].curr_geometry.width, + square_bubbles[i].curr_geometry.height); + +#ifdef _DEBUG + printf (" move and resize wnd (id: 0x%06lx) to %d,%d [%dx%d].\n", square_bubbles[i].id, + square_bubbles[i].curr_geometry.x, square_bubbles[i].curr_geometry.y, + square_bubbles[i].curr_geometry.width, square_bubbles[i].curr_geometry.height); +#endif + } + XFlush (dpy); + usleep (delay); + } + + if (all_wnds) + XFree ((void*) root_childrens); + else + free ((void*) root_childrens); + + XCloseDisplay (dpy); + + return 0; +} + +// parse command line +//======================================================================== +void +cmd_parse (int argc, char* argv[]) +{ + int i; + + if (argc < 2) return; + + // if we want to obtain help + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-help")) + { + printf ("usage:\n"); + printf (" -help : print this help.\n"); + printf (" -cls : close all root's children windows.\n"); + printf (" -m : move bubbles.\n"); + printf (" -s : change bubbles's size.\n"); + printf (" -delay : delay between bubbles's position&size calculation in ms.\n"); + printf (" -odd : use window's odd sizes.\n"); + printf ("\n"); + break; + } + } + + // if we want to close all windows + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-cls")) + { + cls = 1; + return; + } + } + + // if we want to move windows + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-m")) + { + move = 1; + break; + } + } + + // if we want to change windows's size + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-s")) + { + change_size = 1; + break; + } + } + + // if we want to change delay in ms + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-delay")) + { + if (i + 1 >= argc) + printf ("error while argument parsing. i.e: square_bubbles -m -delay 30\n"); + else + sscanf (argv[i + 1], "%d", &delay); + break; + } + } + + // check if we want to set specified windows + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-set")) + { + // if we have 'square_bubbles -set' + if (i + 1 >= argc) + { + all_wnds = 1; // set all windows + printf ("all named windows will be used.\n"); + } + + // if we have 'square_bubbles -set wnd_ids' + // we simple store all specified numbers (in hex), after '-set' key, as + // a window's ids in allocated array (root_childrens[]) + else + { + all_wnds = 0; // set specified windows + nchildrens = argc - i - 1; + + root_childrens = (Window*) calloc (nchildrens, sizeof(Window)); + + while (++i < argc) + sscanf (argv[i], "%lx", root_childrens++); + + root_childrens -= nchildrens; + + printf ("these named windows will be used:\n"); + + for (i = 0; i < nchildrens; i++) + printf (" wnd's id: 0x%06lx.\n", root_childrens[i]); + } + + break; + } + } + + // if we want to use even/odd size switch + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "-odd")) + { + odd_size = 1; + break; + } + } +} + +// find all windows, which are root window's childrens and have names, and +// print information about them +//======================================================================== +int +find_all_window_ids (void) +{ + int i; + Window root_return; + Window parent_return; + char* window_name = NULL; + + int j; + Window* tmp = NULL; + + // find all windows, which are childrens of root window and store their + // id's in 'tmp[] array' + if (!XQueryTree (dpy, RootWindow(dpy, screen), &root_return, &parent_return, &tmp, &nchildrens)) + { + printf ("error while first XQueryTree call.\n"); + return 1; + } + + if (cls) + { + // destroy all windows + for (i = 0; i < nchildrens; i++) + XDestroyWindow (dpy, tmp[i]); + + XFree ((void*) tmp); + return 1; + } + + // calculate amount of named windows + for (i = 0, j = 0; i < nchildrens; i++) + { + if (XFetchName (dpy, tmp[i], &window_name)) + { + j++; + XFree ((void*) window_name); + } + } + + root_childrens = calloc (j, sizeof(Window)); + + // create array root_childrens[] which consists of wnd's id to named windows only + for (i = 0, j = 0; i < nchildrens; i++) + { + if (XFetchName (dpy, tmp[i], &window_name)) + { + root_childrens[j++] = tmp[i]; + XFree ((void*) window_name); + } + } + + nchildrens = j; + + printf (" RootWindow: 0x%06lx.\n", RootWindow(dpy, screen)); + printf (" root_return: 0x%06lx.\n", root_return); + printf (" parent_return: 0x%06lx.\n", parent_return); + printf (" nchildren_return: %d.\n", nchildrens); + + printf ("\nnumber window's id window's name\n"); + + for (i = 0; i < nchildrens && i < MAX_WNDS; i++) + { + printf (" %d ", i); + printf (" 0x%06lx ", root_childrens[i]); + + XFetchName (dpy, root_childrens[i], &window_name); + printf (" %s\n", window_name); + XFree ((void*) window_name); + } + printf ("\n\n"); + + XFlush (dpy); + + return 0; +} + +// return geometry of specified, by win_id, window +//======================================================================== +XRectangle +get_wnd_geometry (Window win_id) +{ + XRectangle geometry; + XWindowAttributes win_attr; + + XGetWindowAttributes (dpy, win_id, &win_attr); + + geometry.x = win_attr.x; + geometry.y = win_attr.y; + geometry.width = win_attr.width; + geometry.height = win_attr.height; + + return geometry; +} + +// calculate new coordinates +//======================================================================== +void +shift_wnd (bubbles* s_b) +{ + short x_step = 5; + short y_step = 5; + int width; + int height; + + // each ODD_INTERVAL seconds we change wnd's size odd mode + int up_edge = ODD_INTERVAL * 1E6 / delay; + static int cnt_odd; + static int even = 1; + + if (!s_b) return; + + if (change_size) + { + width = s_b->x_range * sin (s_b->angle) + s_b->first_geometry.width; + height = s_b->y_range * sin (s_b->angle) + s_b->first_geometry.height; + + // if we want to use odd size of windows (first condition) + if ((odd_size) && (cnt_odd++ >= up_edge)) + { + cnt_odd = 0; + even ^= 0x01; + printf ("even/odd wnd's size changed.\n"); + } + + // make even w&h + if (even) + { + width &= ~0x01; + height &= ~0x01; + } + // make odd w&h (w&h values is checked in followed code) + else + { + width |= 0x01; + height |= 0x01; + } + + if ((s_b->curr_geometry.x + width <= (SCREEN_WIDTH - 1)) + && (s_b->curr_geometry.y + s_b->curr_geometry.height <= (SCREEN_HEIGHT - 1))) + { + s_b->curr_geometry.width = width; + s_b->curr_geometry.height = height; + s_b->angle += RESIZE_SPEED * delay * 1E-6; + } + } + + if (!move) return; + + switch (s_b->direct) + { + case UP_RIGHT: + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y -= y_step; + + // if bubble has striked in up right corner, + // it will be pushed to up_left direct + + // right side bump + if (s_b->curr_geometry.x + s_b->curr_geometry.width > (SCREEN_WIDTH - 1)) + { + if (s_b->curr_geometry.y <= 0) + { + printf ("UP_RIGHT: right side bump\n"); + s_b->curr_geometry.y = y_step; + } + + s_b->direct = UP_LEFT; + + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y -= y_step; + } + + // top side bump + else if (s_b->curr_geometry.y < 0) + { + if (s_b->curr_geometry.x + s_b->curr_geometry.width >= (SCREEN_WIDTH - 1)) + { + printf ("UP_RIGHT: top side bump\n"); + s_b->curr_geometry.x -= x_step; + } + + s_b->direct = DOWN_RIGHT; + + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y += y_step; + } + break; + + case DOWN_RIGHT: + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y += y_step; + + // if bubble has striked in bottom right corner, + // it will be pushed to down_left direct + + // right side bump + if (s_b->curr_geometry.x + s_b->curr_geometry.width > (SCREEN_WIDTH - 1)) + { + if (s_b->curr_geometry.y + s_b->curr_geometry.height >= (SCREEN_HEIGHT - 1)) + { + printf ("DOWN_RIGHT: right side bump\n"); + s_b->curr_geometry.y = (SCREEN_HEIGHT - 1) - s_b->curr_geometry.height - y_step; + } + + s_b->direct = DOWN_LEFT; + + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y += y_step; + } + + // bottom side bump + else if (s_b->curr_geometry.y + s_b->curr_geometry.height > (SCREEN_HEIGHT - 1)) + { + if (s_b->curr_geometry.x + s_b->curr_geometry.width >= (SCREEN_WIDTH - 1)) + { + printf ("DOWN_RIGHT: bottom side bump\n"); + s_b->curr_geometry.x -= x_step; + } + + s_b->direct = UP_RIGHT; + + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y -= y_step; + } + break; + + case UP_LEFT: + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y -= y_step; + + // if bubble has striked in top left corner, + // it will be pushed to up_right direct + + // left side bump + if (s_b->curr_geometry.x < 0) + { + if (s_b->curr_geometry.y <= 0) + { + printf ("UP_LEFT: left side bump\n"); + s_b->curr_geometry.y = y_step; + } + + s_b->direct = UP_RIGHT; + + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y -= y_step; + } + + // top side bump + else if (s_b->curr_geometry.y < 0) + { + if (s_b->curr_geometry.x <= 0) + { + printf ("UP_LEFT: top side bump\n"); + s_b->curr_geometry.x = x_step; + } + + s_b->direct = DOWN_LEFT; + + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y += y_step; + } + break; + + case DOWN_LEFT: + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y += y_step; + + // if bubble has striked in bottom left corner, + // it will be pushed to down_right direct + + // left side bump + if (s_b->curr_geometry.x < 0) + { + if (s_b->curr_geometry.y + s_b->curr_geometry.height >= (SCREEN_HEIGHT - 1)) + { + printf ("DOWN_LEFT: left side bump\n"); + s_b->curr_geometry.y = (SCREEN_HEIGHT - 1) - s_b->curr_geometry.height - y_step; + } + + s_b->direct = DOWN_RIGHT; + + s_b->curr_geometry.x += x_step; + s_b->curr_geometry.y += y_step; + } + + // bottom side bump + else if (s_b->curr_geometry.y + s_b->curr_geometry.height > (SCREEN_HEIGHT - 1)) + { + if (s_b->curr_geometry.x <= 0) + { + printf ("DOWN_LEFT: bottom side bump\n"); + s_b->curr_geometry.x = x_step; + } + + s_b->direct = UP_LEFT; + + s_b->curr_geometry.x -= x_step; + s_b->curr_geometry.y -= y_step; + } + break; + + default: + printf (" no correct direction.\n"); + break; + } + + if (s_b->curr_geometry.x < 0 || s_b->curr_geometry.y < 0) + { + printf ("error with calculation algorithm.\n"); + exit (1); + } +} diff --git a/tests/functional/hwc_test/wander_stripe.c b/tests/functional/hwc_test/wander_stripe.c new file mode 100644 index 0000000..9195660 --- /dev/null +++ b/tests/functional/hwc_test/wander_stripe.c @@ -0,0 +1,259 @@ +/************************************************************************** + + wander_strip + + Copyright 2010 - 2015 Samsung Electronics co., Ltd. All Rights Reserved. + + Contact: Keith Packard <keithp@keithp.com> + Contact: Sergey Sizonov <s.sizonov@samsung.com> + + 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. + + **************************************************************************/ + +// this file implements wander_stripe for using in semiautomatic tests for +// keep safe ddx driver devoloping + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <unistd.h> + +#include "aux_apps.h" +#include "dri2_dri3.h" + + +xcb_connection_t* dpy = NULL; +xcb_screen_t* screen = NULL; +xcb_rectangle_t wnd_pos = {100, 100, 200, 200}; +xcb_rectangle_t wander_strip; +xcb_gc_t gc; + +// work behavior flags: (see aux_apps.c for details) + +// mode of work (dri2/dri3+present) +int mode = DRI3_PRESENT_MODE; // by default dri3 + present will be used +int stop; +int x_step = 1; +uint32_t present_bufs = 3; +uint32_t swap_interval = 1; +uint32_t root_parent = 1; + + +// direct accessing memory clear callback +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_clear (const bo_t* bo_e) +{ + xcb_rectangle_t rect; + + if (!bo_e) + { + printf ("raw_clear: invalid parameters.\n"); + return; + } + + rect.x = 0; + rect.y = 0; + rect.width = bo_e->width; + rect.height = bo_e->height; + + // draw white rectangle with size as window has + raw_fill_rect (bo_e, 1, &rect, 0xff000000 | screen->white_pixel); +} + +// direct accessing memory draw callback (wander stripe drawing) +// bo_e - contains all information to do direct render in memory +//=================================================================== +void +raw_draw (const bo_t* bo_e) +{ + static int x; + + if (!bo_e) + { + printf ("raw_draw: invalid parameters.\n"); + return; + } + + wander_strip.height = bo_e->height; + wander_strip.width = bo_e->width / 4; + + // move stripe + if (x_step > 0) + { + if (x + wander_strip.width > bo_e->width) + { + x_step = -x_step; + x += x_step; + } + } + else + { + if (x < 0) + { + x_step = -x_step; + x += x_step; + } + } + + wander_strip.x = x; + + // draw white wrandered rectangle + raw_fill_rect (bo_e, 1, &wander_strip, 0xff0000ff); + + if (!stop) + x += x_step; +} + +// xcb based draw callback (wander stripe drawing) +// drawable - drawable to render into it +// draw_w, draw_h - size of drawable +//=================================================================== +void +xcb_draw (xcb_drawable_t drawable, uint32_t draw_w, uint32_t draw_h) +{ + static int x; + uint32_t gc_mask; + uint32_t gc_values; + xcb_rectangle_t temp_rect; + + // draw white rectangle with size as window has + gc_mask = XCB_GC_FOREGROUND; + gc_values = 0xffffffff; + + xcb_change_gc (dpy, gc, gc_mask, &gc_values); + temp_rect.x = 0; + temp_rect.y = 0; + temp_rect.width = draw_w; + temp_rect.height = draw_h; + xcb_poly_fill_rectangle(dpy, drawable, gc, 1, &temp_rect); + + // draw black wander strip + gc_mask = XCB_GC_FOREGROUND; + gc_values = 0x0; + xcb_change_gc (dpy, gc, gc_mask, &gc_values); + + wander_strip.height = draw_h; + + // move stripe + if (x_step > 0) + { + if (x + wander_strip.width > draw_w) + { + x_step = -x_step; + x += x_step; + } + } + else + { + if (x < 0) + { + x_step = -x_step; + x += x_step; + } + } + + wander_strip.x = x; + + // draw white wrandered rectangle + xcb_poly_fill_rectangle (dpy, drawable, gc, 1, &wander_strip); + + if (!stop) + x += x_step; + + xcb_flush (dpy); +} + +// +//=================================================================== +int +main (int argc, char** argv) +{ + xcb_generic_event_t* event = NULL; + xcb_window_t main_wnd; + draw_funcs_t draw_func; + dri2_dri3_params_t params; + int res; + + cmd_parse (argc, argv); + + dpy = xcb_connect (NULL, NULL); + + // get first screen of display + screen = xcb_setup_roots_iterator (xcb_get_setup (dpy)).data; + + main_wnd = create_window (dpy, 0xff, root_parent, "wander stripe"); + + gc = xcb_generate_id (dpy); + xcb_create_gc (dpy, gc, main_wnd, 0, NULL); + + draw_func.raw_clear = raw_clear; + draw_func.raw_draw = raw_draw; + draw_func.xcb_draw = xcb_draw; + draw_func.xcb_clear = NULL; + + // init for drawing + wander_strip.y = 0; + wander_strip.width = wnd_pos.width / 4; + wander_strip.height = wnd_pos.height; + + params.num_of_bufs = present_bufs; + params.swap_interval = swap_interval; + + // inside init_dri2_dri3 new thread, responsible for dri2/dri3/present events + // handling, will be created + res = init_dri2_dri3 (dpy, &draw_func, mode, main_wnd, ¶ms); + if (res) + { + printf ("init_dri2_dri3: %s.\n", get_last_error()); + exit (1); + } + + printf ("before xcb loop.\n"); + + while (1) + { + xcb_flush (dpy); + event = xcb_wait_for_event (dpy); + if (!event) break; + + switch (event->response_type) + { + case XCB_EXPOSE: + DEBUG_OUT ("XCB_MAP_WINDOW\n"); + break; + + // if we are notified by XCB_BUTTON_PRESS event, we start/stop + // to change our frames, simple draw the same thing + case XCB_BUTTON_PRESS: + stop ^= 1; + break; + + default: + break; + } + } + + return 0; +} diff --git a/tests/functional/pixmap_copy_test/Makefile.am b/tests/functional/pixmap_copy_test/Makefile.am new file mode 100644 index 0000000..13c461f --- /dev/null +++ b/tests/functional/pixmap_copy_test/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_FT + bin_PROGRAMS = pixmap_copy + +pixmap_copy_CFLAGS = $(PIXMAP_COPY_TEST_CFLAGS) +pixmap_copy_LDADD = $(PIXMAP_COPY_TEST_LIBS) +pixmap_copy_SOURCES = \ +@top_srcdir@/tests/functional/pixmap_copy_test/pixmap_copy.c + +endif diff --git a/tests/functional/pixmap_copy_test/pixmap_copy.c b/tests/functional/pixmap_copy_test/pixmap_copy.c new file mode 100644 index 0000000..b6bbbcc --- /dev/null +++ b/tests/functional/pixmap_copy_test/pixmap_copy.c @@ -0,0 +1,122 @@ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <unistd.h> + +#define ERROR(str, arg...) \ + do \ + { \ + printf(str, ##arg); \ + exit(1); \ + } \ + while(0) \ + +#define WIDTH 720 +#define HEIGHT 1280 + +extern int errno; + +int main(int argc, char **argv) +{ + Display *display; + Window window; + Visual *visual; + Pixmap pixmap, pixmap2; + GC gr_context; + XGCValues gr_values; + XSetWindowAttributes attributes; + int depth = 0; + int screen = 0; + int num = 0; + time_t start, current; + +/* Connect to X Server */ + if ((display = XOpenDisplay(NULL)) == NULL) + ERROR("Can't connect X server: %s\n", strerror(errno)); + +/* Get default screen, visual etc */ + screen = XDefaultScreen(display); + visual = XDefaultVisual(display,screen); + depth = XDefaultDepth(display,screen); + attributes.background_pixel = XWhitePixel(display,screen); + + printf("depth %d\n", depth); + +/* Create window */ + window = XCreateWindow(display, XRootWindow(display,screen), + 0, 0, WIDTH, HEIGHT, 0, depth, InputOutput, + visual , CWBackPixel, &attributes); + +/* Chose events we are intrested in */ + XSelectInput(display, window, ExposureMask | KeyPressMask); + XFlush(display); + +/* Create pxmap */ + pixmap = XCreatePixmap(display, window, WIDTH, HEIGHT, depth); + +/* Create graphic contexts */ + gr_values.foreground = 0xAABBCC; + gr_context = XCreateGC(display, pixmap, GCForeground, &gr_values); + + XFillRectangle(display, pixmap, gr_context, 0, 0, WIDTH, HEIGHT); + XCopyArea(display, pixmap, window, gr_context, 0, 0, WIDTH, HEIGHT, 0, 0); + +/* Display the window on screen*/ + XMapWindow(display, window); + XFlush(display); + + +/*--------------- pixmap -> window -----------------*/ + + printf("-------------------------\n"); + printf("wait 2\n"); + sleep(2); + printf("start\n\n"); + + num = 0; + start = time(NULL); + while (time(¤t) < start + 5) + { + XCopyArea(display, pixmap, window, gr_context, 0, 0, WIDTH, HEIGHT, 0, 0); + ++num; + XFlush(display); + } + + printf("pixmap -> window: %d\n", num); + printf("-------------------------\n\n"); + + pixmap2 = XCreatePixmap(display, window, WIDTH, HEIGHT, depth); + XFillRectangle(display, pixmap2, gr_context, 0, 0, WIDTH, HEIGHT); + XFlush(display); + + +/*--------------- pixmap -> pixmap -----------------*/ + + printf("-------------------------\n"); + printf("wait 2\n"); + sleep(2); + printf("start\n\n"); + + num = 0; + start = time(NULL); + while (time(¤t) < start + 5) + { + XCopyArea(display, pixmap, pixmap2, gr_context, 0, 0, WIDTH, HEIGHT, 0, 0); + ++num; + XFlush(display); + } + + printf("pixmap -> pixmap: %d\n", num); + printf("-------------------------\n"); + + +/* Close connection with X */ + XCloseDisplay(display); + + return 0; +} + diff --git a/tests/functional/xv_test/Makefile.am b/tests/functional/xv_test/Makefile.am new file mode 100644 index 0000000..67f3fd6 --- /dev/null +++ b/tests/functional/xv_test/Makefile.am @@ -0,0 +1,12 @@ +if HAVE_FT +bin_PROGRAMS = test_xv +test_xv_CFLAGS = @XV_TEST_CFLAGS@ \ +-I@top_srcdir@/tests/functional/xv_test \ +-I@top_srcdir@/src/xv +test_xv_LDADD = @XV_TEST_LIBS@ +test_xv_SOURCES = \ +@top_srcdir@/tests/functional/xv_test/xv_test.c \ +@top_srcdir@/tests/functional/xv_test/data.c \ +@top_srcdir@/tests/functional/xv_test/xcb_api.c \ +@top_srcdir@/tests/functional/xv_test/test_xv_resize.c +endif diff --git a/tests/functional/xv_test/data.c b/tests/functional/xv_test/data.c new file mode 100644 index 0000000..08ca1d4 --- /dev/null +++ b/tests/functional/xv_test/data.c @@ -0,0 +1,242 @@ +#include <stdlib.h> +#include <stdio.h> +#include "data.h" +#include <xcb/shm.h> +#include <xcb/dri2.h> +#include <tbm_bufmgr.h> +#include <xf86drm.h> +#include <assert.h> +#include <sys/shm.h> +#include <fcntl.h> +#include "xv_types.h" +#include <string.h> + +static tbm_bufmgr bufmgr_p = NULL; +typedef struct +{ + int fd; + error_s error; +} dri_fd_s; + +static dri_fd_s +open_dri2 (xcb_connection_t *c, xcb_screen_t *screen) +{ + xcb_dri2_connect_cookie_t dri2_conn_ck; + xcb_dri2_connect_reply_t *dri2_conn_reply_p = NULL; + xcb_dri2_authenticate_cookie_t dri2_auth_ck; + xcb_dri2_authenticate_reply_t *dri2_auth_reply_p = NULL; + xcb_generic_error_t *error_p = NULL; + int error = -1; + dri_fd_s ret = {}; + char *device_name_p = NULL; + drm_magic_t drm_magic; + xcb_window_t window_id = screen->root; + + dri2_conn_ck = xcb_dri2_connect(c, window_id, XCB_DRI2_DRIVER_TYPE_DRI); + dri2_conn_reply_p = xcb_dri2_connect_reply(c, dri2_conn_ck, &error_p); + if (error_p) + { + ret.error.error_str = "Can't connect to DRI2 driver"; + ret.error.error_code = error_p->error_code; + goto close; + } + + device_name_p = strndup(xcb_dri2_connect_device_name (dri2_conn_reply_p), + xcb_dri2_connect_device_name_length (dri2_conn_reply_p)); + + ret.fd = open(device_name_p, O_RDWR); + + if (ret.fd < 0) + { + ret.error.error_str = "Can't open DRI2 file descriptor"; + ret.error.error_code = ret.fd; + goto close; + } + + error = drmGetMagic(ret.fd, &drm_magic); + if (error < 0) + { + ret.error.error_str = "Can't get drm magic"; + ret.error.error_code = error; + goto close; + } + + dri2_auth_ck = xcb_dri2_authenticate(c, window_id, drm_magic); + dri2_auth_reply_p = xcb_dri2_authenticate_reply(c, dri2_auth_ck, &error_p); + if (error_p) + { + ret.error.error_str = "Can't auth DRI2"; + ret.error.error_code = error_p->error_code; + goto close; + } + +close: + if (error_p) + free(error_p); + if (dri2_conn_reply_p) + free(dri2_conn_reply_p); + if (dri2_auth_reply_p) + free(dri2_auth_reply_p); + if (device_name_p) + free(device_name_p); + return ret; +} + +static shm_data_s +open_shm(xcb_connection_t *c, size_t data_size) +{ + xcb_generic_error_t *error_p = NULL; + shm_data_s ret_shm = {}; + + ret_shm.shm_seg_id = xcb_generate_id (c); + + int shm_id = shmget (IPC_PRIVATE, data_size, IPC_CREAT | 0777); + if (shm_id == -1) + { + ret_shm.error.error_str = "shm alloc error"; + ret_shm.error.error_code = shm_id; + goto close; + } + + ret_shm.shm_seg_addr = shmat (shm_id, NULL, 0); + if (!ret_shm.shm_seg_addr) + { + ret_shm.error.error_str = "shm attach error"; + goto close; + } + xcb_void_cookie_t xcb_shm_c = + xcb_shm_attach_checked (c, ret_shm.shm_seg_id, shm_id, 0); + error_p = xcb_request_check (c, xcb_shm_c); + if (error_p) + { + ret_shm.error.error_str = "xcb_shm attach error"; + goto close; + } +close: + shmctl (shm_id, IPC_RMID, NULL); + if (error_p) + free(error_p); + return ret_shm; +} + +static tbm_bo +get_data_random (size_t size, tbm_bufmgr bufmgr) +{ + FILE *fp = fopen ("/dev/urandom", "r"); + if (fp == NULL) + { + return NULL; + } + + tbm_bo tbo = tbm_bo_alloc (bufmgr, size, TBM_BO_DEFAULT); + if (tbo == NULL) + { + return NULL; + } + + /* copy raw data to tizen buffer object */ + tbm_bo_handle bo_handle = tbm_bo_map (tbo, TBM_DEVICE_CPU, TBM_OPTION_WRITE); + size_t error = fread (bo_handle.ptr, 1, size , fp); + tbm_bo_unmap (tbo); + fclose (fp); + if (error == 0) + { + tbm_bo_unref(tbo); + tbo = NULL; + } + return tbo; +} + +shm_data_s +get_image_random (xcb_connection_t *p_xcb_conn, xcb_screen_t *screen, + size_t *sizes, int num_planes) +{ + shm_data_s ret = {0,}; + XV_DATA_PTR xv_data = NULL; + if (bufmgr_p == NULL) + { + dri_fd_s dri2 = open_dri2 (p_xcb_conn, screen); + if (dri2.error.error_str) + { + ret.error = dri2.error; + goto close_l; + } + bufmgr_p = tbm_bufmgr_init (dri2.fd); + if (!bufmgr_p) + { + ret.error.error_str = "Can't open TBM connection\n"; + ret.error.error_code = 0; + goto close_l; + } + } + + if (sizes == NULL) + { + ret.error.error_str = "Sizes argument is NULL"; + goto close_l; + } + + if (num_planes > 3 || num_planes < 1) + { + ret.error.error_str = "Wrong num_planes argument"; + goto close_l; + } + size_t full_size = 0; + int i; + for (i = 0; i < num_planes; i++) + { + full_size += sizes[i]; + } + ret = open_shm(p_xcb_conn, full_size); + if (ret.error.error_str) + goto close_l; + + xv_data = ret.shm_seg_addr; + XV_INIT_DATA (xv_data); + tbm_bo temp_bo = NULL; + switch (num_planes) + { + case 3: + temp_bo = get_data_random (sizes[2], bufmgr_p); + if (temp_bo == NULL) + { + ret.error.error_str = "Can't alloc tbm object"; + goto close_l; + } + xv_data->CrBuf = tbm_bo_export(temp_bo); + case 2: + temp_bo = get_data_random (sizes[1], bufmgr_p); + if (temp_bo == NULL) + { + ret.error.error_str = "Can't alloc tbm object"; + goto close_l; + } + xv_data->CbBuf = tbm_bo_export(temp_bo); + case 1: + temp_bo = get_data_random (sizes[0], bufmgr_p); + if (temp_bo == NULL) + { + ret.error.error_str = "Can't alloc tbm object\n"; + goto close_l; + } + xv_data->YBuf = tbm_bo_export(temp_bo); + break; + } + + return ret; +close_l: + // TODO: Close DRI + // TODO: Close tbm + if (xv_data) + { + if (xv_data->YBuf != 0) + tbm_bo_unref(tbm_bo_import(bufmgr_p, xv_data->YBuf)); + if (xv_data->CbBuf != 0) + tbm_bo_unref(tbm_bo_import(bufmgr_p, xv_data->CbBuf)); + if (xv_data->CrBuf != 0) + tbm_bo_unref(tbm_bo_import(bufmgr_p, xv_data->CrBuf)); + } + + return ret; +} + diff --git a/tests/functional/xv_test/data.h b/tests/functional/xv_test/data.h new file mode 100644 index 0000000..81329c0 --- /dev/null +++ b/tests/functional/xv_test/data.h @@ -0,0 +1,18 @@ +#ifndef DATA_H +#define DATA_H +#include <xcb/xcb.h> +#include <xcb/shm.h> +#include <xcb/xv.h> +#include "xv_test.h" + +typedef struct +{ + xcb_shm_seg_t shm_seg_id; + void *shm_seg_addr; + error_s error; +} shm_data_s; + +shm_data_s get_image_random (xcb_connection_t *xcb_conn_p, xcb_screen_t *screen, + size_t * sizes, int num_planes); + +#endif // DATA_H diff --git a/tests/functional/xv_test/test_xv_resize.c b/tests/functional/xv_test/test_xv_resize.c new file mode 100644 index 0000000..0c77dd7 --- /dev/null +++ b/tests/functional/xv_test/test_xv_resize.c @@ -0,0 +1,520 @@ +#include <xcb/xcb.h> +#include <xcb/xv.h> +#include <xcb/shm.h> +#include <xcb/dri2.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <xf86drm.h> +#include <fcntl.h> +#include <unistd.h> +#include <tbm_bufmgr.h> +#include <assert.h> +#include "xv_test.h" +#include "data.h" +#include "xcb_api.h" + +typedef struct +{ + xcb_atom_t atom_hflip; + xcb_atom_t atom_vflip; + xcb_atom_t atom_rotate; + xcb_atom_t atom_buffer; + error_s error; +} test_atom_s; + +typedef struct +{ + size_t steps; + rectangle_s *src_crop_p; + rectangle_s *dst_crop_p; +} route_map_s; + +typedef struct +{ + error_s error; + route_map_s route_map; +} get_route_map_s; + +typedef struct +{ + xcb_xv_port_t xv_open_port; + test_atom_s atoms; + xcb_connection_t *xcb_conn_p; + xcb_screen_t *screen_p; + xcb_window_t window_id; + xcb_gcontext_t gc_id; + route_map_s route_map; +} test_data_s; + +static test_data_s *st_test_data_p = NULL; + +static error_s test_xv_resize_prepare(xcb_connection_t *xcb_conn_p, + xcb_screen_t * screen_p, rule_s rule); + +static error_s test_xv_resize_run(xcb_connection_t *xcb_conn_p, + xcb_screen_t * screen_p, rule_s rule); + +static error_s test_xv_resize_close(xcb_connection_t *xcb_conn_p, + xcb_screen_t * screen_p, rule_s rule); + +test_atom_s +create_atoms (xcb_connection_t *xcb_conn_p) +{ + char const *atom_name_a[4] = { + "_USER_WM_PORT_ATTRIBUTE_HFLIP", + "_USER_WM_PORT_ATTRIBUTE_VFLIP", + "_USER_WM_PORT_ATTRIBUTE_ROTATION", + "XV_RETURN_BUFFER"}; + xcb_intern_atom_cookie_t atom_ck_a[4] = {}; + xcb_intern_atom_reply_t *atom_reply_p = NULL; + test_atom_s ret = {}; + xcb_generic_error_t *error_p = NULL; + int i; + for (i = 0; i < 4; i++) + { + atom_ck_a[i] = + xcb_intern_atom (xcb_conn_p, 0, (uint16_t) strlen(atom_name_a[i]), + atom_name_a[i]); + } + for (i = 0; i < 4; i++) + { + atom_reply_p = + xcb_intern_atom_reply (xcb_conn_p , atom_ck_a[i], &error_p); + + if (error_p) + { + ret.error.error_str = "Can't register atom"; + ret.error.error_code = error_p->error_code; + goto close_l; + } + if (atom_reply_p == NULL) + { + ret.error.error_str = "Can't register atom"; + goto close_l; + } + switch (i) + { + case 0: + ret.atom_hflip = atom_reply_p->atom; + break; + case 1: + ret.atom_vflip = atom_reply_p->atom; + break; + case 2: + ret.atom_rotate = atom_reply_p->atom; + break; + case 3: + ret.atom_buffer = atom_reply_p->atom; + break; + } + free(atom_reply_p); + atom_reply_p = NULL; + } + +close_l: + + if (error_p) + free(error_p); + if (atom_reply_p) + free(atom_reply_p); + return ret; +} + +get_route_map_s +create_route_map (rule_s *rules) +{ + get_route_map_s ret = {}; + rectangle_s *src_crop_p = NULL; + rectangle_s *dst_crop_p = NULL; + if (rules == NULL) + { + ret.error.error_str = "Wrong input arguments"; + goto close_l; + } + size_t steps_width = (rules->max_width - rules->min_width)/10; + size_t steps_height = (rules->max_height - rules->max_height)/10; + size_t steps = (max(steps_width, steps_height))*2; + + src_crop_p = calloc(steps, sizeof(rectangle_s)); + if (!src_crop_p) + { + ret.error.error_str = "Can't alloc memory"; + goto close_l; + } + dst_crop_p = calloc(steps, sizeof(rectangle_s)); + if (!dst_crop_p) + { + ret.error.error_str = "Can't alloc memory"; + goto close_l; + } +// pace_dst_crop.height = (uint32_t) +// ((double)(rules->max_size.height - rules->min_size.height)/ +// (rules->steps * 2)); +// pace_dst_crop.width = (uint32_t) +// ((double)(rules->max_size.width - rules->min_size.width)/ +// (rules->steps * 2)); +// pace_src_crop.height = (uint32_t) +// ((double)(rules->image_height - rules->min_size.height)/ +// (rules->steps * 2)); +// pace_src_crop.width = (uint32_t) +// ((double)(rules->image_width - rules->min_size.width)/ +// (rules->steps * 2)); + if (!rules->src_change) + { + src_crop_p[0].x = 0; + src_crop_p[0].y = 0; + src_crop_p[0].width = rules->image_width; + src_crop_p[0].height = rules->image_height; + } + else + { + src_crop_p[0].x = 0; + src_crop_p[0].y = 0; + src_crop_p[0].width = rules->min_width; + src_crop_p[0].height = rules->min_height; + } + + if (!rules->dst_change) + { + dst_crop_p[0].x = 0; + dst_crop_p[0].y = 0; + dst_crop_p[0].width = rules->image_width; + dst_crop_p[0].height = rules->image_height; + } + else + { + dst_crop_p[0].x = 0; + dst_crop_p[0].y = 0; + dst_crop_p[0].width = rules->min_width; + dst_crop_p[0].height = rules->min_height; + } + int i; + for (i = 1; i < (steps/2); i++) + { + if (!rules->src_change) + { + src_crop_p[i].x = 0; + src_crop_p[i].y = 0; + src_crop_p[i].width = rules->image_width; + src_crop_p[i].height = rules->image_height; + } + else + { + src_crop_p[i].x = 0; + src_crop_p[i].y = 0; + src_crop_p[i].width = + ((src_crop_p[i-1].width + 10) <= rules->image_width) ? + (src_crop_p[i-1].width + 10) : src_crop_p[i-1].width; + src_crop_p[i].height = + ((src_crop_p[i-1].height + 10) <= rules->image_height) ? + (src_crop_p[i-1].height + 10) : src_crop_p[i-1].height; + } + if (!rules->dst_change) + { + dst_crop_p[i].x = 0; + dst_crop_p[i].y = 0; + dst_crop_p[i].width = rules->image_width; + dst_crop_p[i].height = rules->image_height; + } + else + { + dst_crop_p[i].x = 0; + dst_crop_p[i].y = 0; + dst_crop_p[i].width = + ((dst_crop_p[i-1].width + 10) <= rules->max_width) ? + (dst_crop_p[i-1].width + 10) : dst_crop_p[i-1].width; + dst_crop_p[i].height = + ((dst_crop_p[i-1].height + 10) <= rules->max_height) ? + (dst_crop_p[i-1].height + 10) : dst_crop_p[i-1].height; + } + } + for (i = (steps/2); i < steps; i++) + { + if (!rules->src_change) + { + src_crop_p[i].x = 0; + src_crop_p[i].y = 0; + src_crop_p[i].width = rules->image_width; + src_crop_p[i].height = rules->image_height; + } + else + { + src_crop_p[i].x = 0; + src_crop_p[i].y = 0; + src_crop_p[i].width = + ((src_crop_p[i-1].width - 10) >= rules->min_width) ? + (src_crop_p[i-1].width - 10) : src_crop_p[i-1].width; + src_crop_p[i].height = + ((src_crop_p[i-1].height - 10) >= rules->min_height) ? + (src_crop_p[i-1].height - 10) : src_crop_p[i-1].height; + } + if (!rules->dst_change) + { + dst_crop_p[i].x = 0; + dst_crop_p[i].y = 0; + dst_crop_p[i].width = rules->image_width; + dst_crop_p[i].height = rules->image_height; + } + else + { + dst_crop_p[i].x = 0; + dst_crop_p[i].y = 0; + dst_crop_p[i].width = + ((dst_crop_p[i-1].width - 10) >= rules->min_width) ? + (dst_crop_p[i-1].width - 10) : dst_crop_p[i-1].width; + dst_crop_p[i].height = + ((dst_crop_p[i-1].height - 10) >= rules->min_height) ? + (dst_crop_p[i-1].height - 10) : dst_crop_p[i-1].height; + } + } + + ret.route_map.src_crop_p = src_crop_p; + ret.route_map.dst_crop_p = dst_crop_p; + ret.route_map.steps = steps; + return ret; +close_l: + if (src_crop_p) + free(src_crop_p); + if (dst_crop_p) + free(dst_crop_p); + return ret; +} +test_case_s +test_xv_resize_init (void) +{ + test_case_s ret = {}; + ret.prepare_test = test_xv_resize_prepare; + ret.run_test = test_xv_resize_run; + ret.close_test = test_xv_resize_close; + return ret; +} + + +static error_s +test_xv_resize_prepare(xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p, rule_s rule) +{ + error_s ret = {}; + st_test_data_p = malloc(sizeof(test_data_s)); + DBG; + if (!st_test_data_p) + { + ret.error_str = "Can't alloc memory for test_data_s"; + ret.error_code = 0; + goto close_l; + } + st_test_data_p->xcb_conn_p = xcb_conn_p; + st_test_data_p->screen_p = screen_p; + DBG; + get_xv_port_s xv_port = open_adaptor (xcb_conn_p, screen_p->root); + if (xv_port.error.error_str) + { + ret = xv_port.error; + goto close_l; + } + DBG; + st_test_data_p->xv_open_port = xv_port.xv_port_id; + st_test_data_p->atoms = create_atoms (xcb_conn_p); + if(st_test_data_p->atoms.error.error_str) + { + ret = st_test_data_p->atoms.error; + goto close_l; + } + DBG; + + get_window_s window = create_window(xcb_conn_p, screen_p); + if (window.error.error_str) + { + ret = window.error; + goto close_l; + } + st_test_data_p->window_id = window.window_id; + get_gc_s gc = create_gc (xcb_conn_p, st_test_data_p->window_id, screen_p); + if (gc.error.error_str) + { + ret = gc.error; + goto close_l; + } + st_test_data_p->gc_id = gc.gc_id; + + get_route_map_s route = create_route_map (&rule); + + if (route.error.error_str) + { + ret = route.error; + goto close_l; + } + + st_test_data_p->route_map = route.route_map; + return ret; + +close_l: + DBG; + if (st_test_data_p) + free(st_test_data_p); +/* TODO: close port */ + st_test_data_p = NULL; + return ret; +} +static +error_s +test_xv_resize_run(xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p, rule_s rule) +{ + + DBG; + xcb_generic_error_t *error_p = NULL; + error_s ret = {}; + shm_data_s shm; + if (st_test_data_p == NULL) + { + ret.error_str = "Wrong argument"; + return ret; + } + frame_attr_s frame[st_test_data_p->route_map.steps]; + + DBG; + get_image_attr_s image_attr = + get_image_attr (xcb_conn_p, st_test_data_p->xv_open_port, + rule.image_fourcc, rule.image_width, rule.image_height); + DBG; + if (image_attr.error.error_str) + { + ret = image_attr.error; + goto close_l; + } + /* get raw data */ + + size_t max_j = rule.count_uniqes_frames; + DBG; + int i,j = 0; + for (i = 0; i < st_test_data_p->route_map.steps; i++) + { + + if (i == 0) + printf("Generate data:\n"); + if (i < max_j) + { + shm = get_image_random (xcb_conn_p, screen_p, + image_attr.image.sizes, + image_attr.image.num_planes); + if (shm.error.error_str) + { + ret = shm.error; + goto close_l; + } + frame[i].segment = shm.shm_seg_id; + printf("%f%%\n", ((double)i/max_j)); + } + else + { + if (j == max_j) + { + j = 0; + } + frame[i].segment = frame[j].segment; + j++; + } + + frame[i].image_p = &image_attr.image; + frame[i].src_crop_p = &st_test_data_p->route_map.src_crop_p[i]; + frame[i].dst_crop_p = &st_test_data_p->route_map.dst_crop_p[i]; + + } + DBG; + xcb_void_cookie_t map_window_ck = + xcb_map_window_checked (xcb_conn_p, st_test_data_p->window_id); + xcb_void_cookie_t put_image_ck = + put_image (xcb_conn_p, st_test_data_p->xv_open_port, + st_test_data_p->window_id, st_test_data_p->gc_id, &frame[0]); + j = 1; + + error_p = xcb_request_check (xcb_conn_p, map_window_ck); + if (error_p) + { + ret.error_str = "Can't make transparent window"; + ret.error_code = error_p->error_code; + goto close_l; + } + + xcb_generic_event_t *e; + xcb_client_message_event_t* msg; + DBG; + while (1) + { + e = xcb_poll_for_event(xcb_conn_p); + while (e) + { + switch (e->response_type) + { + case XCB_CLIENT_MESSAGE: + msg = (xcb_client_message_event_t *)e; + if (msg->type == st_test_data_p->atoms.atom_buffer) + { + unsigned int keys[3] = {0, }; + keys[0] = msg->data.data32[0]; + keys[1] = msg->data.data32[1]; + keys[2] = msg->data.data32[2]; + printf ("receive: %d, %d, %d (<= Xorg)\n", + keys[0], keys[1], keys[2]); + } + + break; + case XCB_EXPOSE: + break; + default: + break; + } + free(e); + e = xcb_poll_for_event(xcb_conn_p); + } + + error_p = xcb_request_check (xcb_conn_p, put_image_ck); + if (error_p) + { + ret.error_str = "Can't draw image frame"; + ret.error_code = error_p->error_code; + goto close_l; + } + if (j >= st_test_data_p->route_map.steps) + j = 0; + put_image_ck = put_image (xcb_conn_p, st_test_data_p->xv_open_port, + st_test_data_p->window_id, st_test_data_p->gc_id, + &frame[j]); + printf("src:(%dwx%dh) dst: (%dwx%dh)\n", + frame[j].src_crop_p->width, frame[j].src_crop_p->height, + frame[j].dst_crop_p->width, frame[j].dst_crop_p->height); + j++; + usleep(1000000/rule.frame_per_second); + } + +close_l: + if (error_p) + free(error_p); + return ret; +} + +static error_s +test_xv_resize_close(xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p, rule_s rule) +{ + error_s ret = {}; + return ret; +} + +#if 0 +xcb_xv_list_image_formats_reply_t *list = + xcb_xv_list_image_formats_reply (conn, + xcb_xv_list_image_formats (conn, a->base_id), NULL); +if (list == NULL) + return NULL; + +/* Check available XVideo chromas */ +xcb_xv_query_image_attributes_reply_t *attr = NULL; +unsigned rank = UINT_MAX; + +for (const xcb_xv_image_format_info_t *f = + xcb_xv_list_image_formats_format (list), + *f_end = + f + xcb_xv_list_image_formats_format_length (list); + f < f_end; + f++) +#endif diff --git a/tests/functional/xv_test/test_xv_resize.h b/tests/functional/xv_test/test_xv_resize.h new file mode 100644 index 0000000..fdff351 --- /dev/null +++ b/tests/functional/xv_test/test_xv_resize.h @@ -0,0 +1,6 @@ +#ifndef TEST_XV_RESIZE_H +#define TEST_XV_RESIZE_H +#include "xv_test.h" +test_case_s test_xv_resize_init (void); + +#endif // TEST_XV_RESIZE_H diff --git a/tests/functional/xv_test/xcb_api.c b/tests/functional/xv_test/xcb_api.c new file mode 100644 index 0000000..4f5b013 --- /dev/null +++ b/tests/functional/xv_test/xcb_api.c @@ -0,0 +1,258 @@ +#include "xcb_api.h" +get_image_attr_s +get_image_attr(xcb_connection_t * xcb_conn_p, xcb_xv_port_t xv_port, + uint32_t fourcc_id, uint16_t width, uint16_t height) +{ + get_image_attr_s ret = {}; + xcb_generic_error_t *error_p = NULL; + xcb_xv_query_image_attributes_reply_t * xv_attr_reply_p = NULL; + + if (!xcb_conn_p || xv_port == XCB_XV_BAD_PORT) + { + ret.error.error_str = "Wrong arguments"; + ret.error.error_code = 0; + goto close; + } + + xcb_xv_query_image_attributes_cookie_t xv_attr_ck = + xcb_xv_query_image_attributes (xcb_conn_p /**< */, + xv_port /**< */, + fourcc_id /**< */, + width /**< */, + height /**< */); + xv_attr_reply_p = + xcb_xv_query_image_attributes_reply (xcb_conn_p /**< */, + xv_attr_ck /**< */, + &error_p /**< */); + if (error_p) + { + ret.error.error_str = "Can't query image attr"; + ret.error.error_code = error_p->error_code; + goto close; + } + + if (xv_attr_reply_p->data_size == 0) + { + ret.error.error_str = "Wrong input data format"; + ret.error.error_code = 0; + goto close; + } + + const uint32_t *offsets= + xcb_xv_query_image_attributes_offsets (xv_attr_reply_p); + const uint32_t *pitches= + xcb_xv_query_image_attributes_pitches (xv_attr_reply_p); + ret.image.num_planes = xv_attr_reply_p->num_planes; + ret.image.full_size = xv_attr_reply_p->data_size; + ret.image.fourcc_id = fourcc_id; + ret.image.width = xv_attr_reply_p->width; + ret.image.height = xv_attr_reply_p->height; + switch (ret.image.num_planes) + { + case 3: + ret.image.sizes[0] = offsets[1]; + ret.image.sizes[1] = offsets[2] - offsets[1]; + ret.image.sizes[2] = ret.image.full_size - offsets[2]; + break; + case 2: + ret.image.sizes[1] = ret.image.full_size - offsets[1]; + ret.image.sizes[0] = offsets[1]; + break; + case 1: + ret.image.sizes[0] = ret.image.full_size; + break; + default: + ret.error.error_str = "Wrong input data format"; + goto close; + break; + } + int i; + for (i = 0; i < ret.image.num_planes; ++i) + { + ret.image.offsets[i] = offsets[i]; + ret.image.pitches[i] = pitches[i]; + } + +close: + + if (error_p) + free(error_p); + if (xv_attr_reply_p) + free(xv_attr_reply_p); + + return ret; +} + +xcb_void_cookie_t +put_image (xcb_connection_t * xcb_conn_p, xcb_xv_port_t xv_port, + xcb_window_t window_id, xcb_gcontext_t gc_id, frame_attr_s *frame_p) +{ + xcb_void_cookie_t ret = {}; + ret = xcb_xv_shm_put_image_checked ( + xcb_conn_p, xv_port, window_id, gc_id, + frame_p->segment, frame_p->image_p->fourcc_id, 0, + frame_p->src_crop_p->x, frame_p->src_crop_p->y, + frame_p->src_crop_p->width, frame_p->src_crop_p->height, + frame_p->dst_crop_p->x, frame_p->dst_crop_p->y, + frame_p->dst_crop_p->width, frame_p->dst_crop_p->height, + frame_p->image_p->width, frame_p->image_p->height, 0); + return ret; +} + +get_xv_port_s +open_adaptor (xcb_connection_t *xcb_conn_p, xcb_window_t window_id) +{ + xcb_generic_error_t *error_p = NULL; + get_xv_port_s ret = {}; + xcb_xv_adaptor_info_iterator_t xv_adaptor_iter; + xcb_xv_grab_port_reply_t *xv_grab_port_p = NULL; + xcb_xv_query_adaptors_cookie_t xv_adaptor_ck = + xcb_xv_query_adaptors (xcb_conn_p, window_id); + xcb_xv_query_adaptors_reply_t *xv_adaptors_list_p = + xcb_xv_query_adaptors_reply (xcb_conn_p, xv_adaptor_ck, &error_p); + if (error_p) + { + ret.error.error_str = "Can't query xv adaptor"; + ret.error.error_code = error_p->error_code; + goto close; + } + + for (xv_adaptor_iter = xcb_xv_query_adaptors_info_iterator (xv_adaptors_list_p); + xv_adaptor_iter.rem > 0; + xcb_xv_adaptor_info_next (&xv_adaptor_iter)) + { + if (!(xv_adaptor_iter.data->type & XCB_XV_TYPE_IMAGE_MASK)) + continue; + int i; + for (i = 0; i < xv_adaptor_iter.data->num_ports; i++) + { + xcb_xv_port_t xv_port = xv_adaptor_iter.data->base_id + i; + xcb_xv_grab_port_cookie_t xv_grab_port_c = + xcb_xv_grab_port (xcb_conn_p, xv_port, XCB_CURRENT_TIME); + xv_grab_port_p = + xcb_xv_grab_port_reply (xcb_conn_p, xv_grab_port_c, &error_p); + if (error_p) + { + ret.error.error_str = "Can't query xv adaptor"; + ret.error.error_code = error_p->error_code; + goto close; + } + + if (xv_grab_port_p && xv_grab_port_p->result == 0) + { + ret.xv_port_id = xv_port; + break; + } + } + if (ret.xv_port_id != 0) + { + break; + } + } + +close: + if (xv_adaptors_list_p) + free(xv_adaptors_list_p); + if (xv_grab_port_p) + free(xv_grab_port_p); + if (error_p) + free(error_p); + + return ret; +} + +get_gc_s +create_gc (xcb_connection_t *xcb_conn_p, xcb_drawable_t drawable_id, xcb_screen_t * screen_p) +{ + get_gc_s ret = {}; + xcb_void_cookie_t gc_ck; + xcb_generic_error_t *error_p = NULL; + uint32_t values[2]; + ret.gc_id = xcb_generate_id (xcb_conn_p); + uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES; + values[0] = 0; +// values[0] = screen_p->white_pixel; + gc_ck = xcb_create_gc_checked (xcb_conn_p, ret.gc_id, drawable_id, mask, values); + + error_p = xcb_request_check (xcb_conn_p, gc_ck); + if (error_p) + { + ret.error.error_str = "Can't create graphic context"; + ret.error.error_code = error_p->error_code; + goto close; + } +close: + if (error_p) + free(error_p); + return ret; +} + +get_window_s +create_window (xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p) +{ + get_window_s ret = {}; + ret.window_id = xcb_generate_id (xcb_conn_p); + uint32_t mask; + uint32_t values[3]; + xcb_generic_error_t *error_p = NULL; + mask = XCB_CW_EVENT_MASK; +// values[0] = screen_p->black_pixel; + values[0] = XCB_EVENT_MASK_EXPOSURE; + xcb_void_cookie_t window_ck = + xcb_create_window_checked (xcb_conn_p, + screen_p->root_depth, + ret.window_id, screen_p->root, + 0, 0, screen_p->width_in_pixels, + screen_p->height_in_pixels, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen_p->root_visual, + mask, values); + + error_p = xcb_request_check (xcb_conn_p, window_ck); + if (error_p) + { + ret.error.error_str = "Can't create window"; + ret.error.error_code = error_p->error_code; + goto close; + } + +close: + if (error_p) + free(error_p); + return ret; +} + +static xcb_format_t * +find_format_by_depth (const xcb_setup_t *setup, uint8_t depth) +{ + xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); + xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup); + for(; fmt != fmtend; ++fmt) + if(fmt->depth == depth) + return fmt; + return 0; +} + +#if 1 +xcb_void_cookie_t +make_transparent (xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p, + xcb_drawable_t drawable_id, xcb_gcontext_t gc_id) +{ + xcb_format_t *fmt = find_format_by_depth(xcb_get_setup (xcb_conn_p), 32); + + uint32_t base = 1920 * fmt->bits_per_pixel; + uint32_t pad = fmt->scanline_pad >> 3; + uint32_t b = base + pad - 1; + /* faster if pad is a power of two */ + if (((pad - 1) & pad) == 0) + b = b & -pad; + else + b = b - b % pad; + uint32_t size = 1080 * b; + uint8_t *data = (uint8_t *)calloc (1, size); + return + xcb_put_image_checked (xcb_conn_p, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable_id, gc_id, + screen_p->width_in_pixels, screen_p->height_in_pixels, 0, 0, + 0, 32, size, data); +} +#endif diff --git a/tests/functional/xv_test/xcb_api.h b/tests/functional/xv_test/xcb_api.h new file mode 100644 index 0000000..5eaf9e5 --- /dev/null +++ b/tests/functional/xv_test/xcb_api.h @@ -0,0 +1,80 @@ +#ifndef XV_API_H +#define XV_API_H +#include <xcb/xcb.h> +#include <xcb/xv.h> +#include <xcb/xfixes.h> + +#include <xcb/xcb_util.h> +#include "xv_test.h" + +typedef struct +{ + uint32_t width; + uint32_t height; +} size_s; + +typedef struct +{ + int32_t x; + int32_t y; + uint32_t width; + uint32_t height; +} rectangle_s; + +typedef struct +{ + uint32_t fourcc_id; + uint16_t num_planes; + size_t full_size; + size_t sizes[3]; + uint32_t offsets[3]; + uint32_t pitches[3]; + uint32_t width; + uint32_t height; +} image_attr_s; + +typedef struct +{ + rectangle_s *src_crop_p; + rectangle_s *dst_crop_p; + image_attr_s *image_p; + xcb_shm_seg_t segment; +} frame_attr_s; + +typedef struct +{ + xcb_xv_port_t xv_port_id; + error_s error; +} get_xv_port_s; + +typedef struct +{ + error_s error; + image_attr_s image; +} get_image_attr_s; + +typedef struct +{ + xcb_window_t window_id; + error_s error; +} get_window_s; + +typedef struct +{ + xcb_gcontext_t gc_id; + error_s error; +} get_gc_s; + +get_gc_s create_gc (xcb_connection_t *xcb_conn_p, xcb_drawable_t drawable_id, xcb_screen_t * screen_p); +get_window_s create_window (xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p); + + +get_image_attr_s get_image_attr(xcb_connection_t * xcb_conn_p, xcb_xv_port_t xv_port, + uint32_t fourcc_id, uint16_t width, uint16_t height); +get_xv_port_s open_adaptor (xcb_connection_t *xcb_conn_p, xcb_window_t window_id); +xcb_void_cookie_t put_image (xcb_connection_t * xcb_conn_p, xcb_xv_port_t xv_port, + xcb_window_t window_id, xcb_gcontext_t gc_id, frame_attr_s *frame_p); + +xcb_void_cookie_t make_transparent (xcb_connection_t *xcb_conn_p, xcb_screen_t * screen_p, + xcb_drawable_t drawable_id, xcb_gcontext_t gc_id); +#endif // XV_API_H diff --git a/tests/functional/xv_test/xv_test.c b/tests/functional/xv_test/xv_test.c new file mode 100644 index 0000000..e6929c6 --- /dev/null +++ b/tests/functional/xv_test/xv_test.c @@ -0,0 +1,219 @@ +#include "xv_test.h" +#include <xcb/xcb.h> +#include <xcb/xv.h> +#include <xcb/shm.h> +#include <xcb/dri2.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <xcb/dri2.h> +#include <xf86drm.h> +#include <fcntl.h> +#include "xv_types.h" +#include <tbm_bufmgr.h> +#include "data.h" +#include <sys/time.h> +#include "test_xv_resize.h" + +typedef struct +{ + size_t num_tests; + test_case_s * test_case_array; + error_s * error_array; +} test_map_s; + +error_s +check_xv (xcb_connection_t *xcb_conn_p) +{ + xcb_xv_query_extension_cookie_t xv_cookie; + xcb_xv_query_extension_reply_t *xv_reply = NULL; + xcb_generic_error_t * error_p = NULL; + error_s ret = {}; + xv_cookie = xcb_xv_query_extension (xcb_conn_p); + xv_reply = xcb_xv_query_extension_reply (xcb_conn_p, xv_cookie, &error_p); + if (error_p) + { + ret.error_str = "Can't find xv extension"; + ret.error_code = error_p->error_code; + } + + if (xv_reply) + free(xv_reply); + if (error_p) + free(error_p); + return ret; +} + +error_s +check_shm (xcb_connection_t *xcb_conn_p) +{ + xcb_shm_query_version_cookie_t shm_cookie; + xcb_shm_query_version_reply_t *shm_reply_p = NULL; + xcb_generic_error_t * error_p = NULL; + error_s ret = {}; + shm_cookie = xcb_shm_query_version (xcb_conn_p); + shm_reply_p = xcb_shm_query_version_reply (xcb_conn_p, shm_cookie, &error_p); + if (error_p) + { + ret.error_str = "Can't find shm extension"; + ret.error_code = error_p->error_code; + } + + if (shm_reply_p) + free(shm_reply_p); + if (error_p) + free(error_p); + return ret; +} + +error_s +check_dri2 (xcb_connection_t *xcb_conn_p) +{ + error_s ret = {}; + xcb_generic_error_t *error_p = NULL; + xcb_dri2_query_version_cookie_t xcb_dri2_ck = + xcb_dri2_query_version (xcb_conn_p, + XCB_DRI2_MAJOR_VERSION, + XCB_DRI2_MINOR_VERSION); + xcb_dri2_query_version_reply_t * xcb_dri2_reply_p = + xcb_dri2_query_version_reply (xcb_conn_p, + xcb_dri2_ck, + &error_p); + if (error_p) + { + ret.error_str = "Can't find dri2 extension"; + ret.error_code = error_p->error_code; + } + + if (xcb_dri2_reply_p) + free(xcb_dri2_reply_p); + if (error_p) + free(error_p); + return ret; +} + +rule_s +make_rule (xcb_connection_t *xcb_conn_p, xcb_screen_t *screen_p) +{ + rule_s ret = {}; + ret.count_frame_per_change = 2; + ret.count_uniqes_frames = 10; + ret.frame_per_second = 30; + ret.max_width = screen_p->width_in_pixels; + ret.max_height = screen_p->height_in_pixels; + ret.dst_change = 1; + ret.src_change = 0; + ret.min_height = 100; + ret.min_width = 100; + ret.image_width = 640; + ret.image_height = 480; + ret.image_fourcc = FOURCC_SR32; + return ret; +} + +test_map_s +init_tests (void) +{ + test_map_s ret = {}; + ret.num_tests = 1; + ret.test_case_array = calloc(ret.num_tests, sizeof(test_case_s)); + if (ret.test_case_array == NULL) + { + fprintf(stderr, "Can't alloc memory for test"); + ret.num_tests = 0; + goto error_close; + } + + ret.error_array = calloc(ret.num_tests, sizeof(error_s)); + if (ret.error_array == NULL) + { + fprintf(stderr, "Can't alloc memory for test"); + ret.num_tests = 0; + goto error_close; + } + ret.test_case_array[0] = test_xv_resize_init(); + return ret; +error_close: + if (ret.test_case_array) + free(ret.test_case_array); + if (ret.error_array) + free(ret.error_array); + + return ret; +} + +int main () +{ + xcb_screen_iterator_t screen_iter; + xcb_connection_t *xcb_conn_p; + const xcb_setup_t *setup; + xcb_screen_t *screen_p; + int screen_number; + test_map_s tests = {}; + rule_s rule_p = {}; + error_s ret; + /* getting the connection */ + xcb_conn_p = xcb_connect (NULL, &screen_number); + if (!xcb_conn_p) + { + fprintf(stderr, "ERROR: can't connect to an X server\n"); + } + ret = check_xv (xcb_conn_p); + exit_if_fail (ret); + ret = check_shm (xcb_conn_p); + exit_if_fail (ret); + ret = check_dri2 (xcb_conn_p); + exit_if_fail (ret); + DBG; + /* getting the current screen */ + setup = xcb_get_setup (xcb_conn_p); + screen_p = NULL; + screen_iter = xcb_setup_roots_iterator (setup); + for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter)) + if (screen_number == 0) + { + screen_p = screen_iter.data; + break; + } + if (!screen_p) { + fprintf (stderr, "ERROR: can't get the current screen\n"); + xcb_disconnect (xcb_conn_p); + return -1; + } + rule_p = make_rule (xcb_conn_p, screen_p); + tests = init_tests(); + if (tests.num_tests == 0) + { + fprintf (stderr, "Nothing to test. num_tests = 0\n"); + return 0; + } + int i; + DBG; + for (i = 0; i < tests.num_tests; i++) + { + ret = tests.test_case_array[i].prepare_test(xcb_conn_p, screen_p, rule_p); + if (ret.error_str) + { + tests.error_array[i] = ret; + continue; + } + ret = tests.test_case_array[i].run_test(xcb_conn_p, screen_p, rule_p); + if (ret.error_str) + { + tests.error_array[i] = ret; + continue; + } + ret = tests.test_case_array[i].close_test(xcb_conn_p, screen_p, rule_p); + if (ret.error_str) + { + tests.error_array[i] = ret; + continue; + } + } + for (i = 0; i < tests.num_tests; i++) + { + fprintf(stderr, "%s %d\n", tests.error_array[i].error_str, + tests.error_array[i].error_code); + } + return 0; +} diff --git a/tests/functional/xv_test/xv_test.h b/tests/functional/xv_test/xv_test.h new file mode 100644 index 0000000..3c33e27 --- /dev/null +++ b/tests/functional/xv_test/xv_test.h @@ -0,0 +1,111 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> + +#include <pthread.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <xcb/xcb.h> + +#include <xf86drm.h> +#include <tbm_bufmgr.h> + +#include "xv_types.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define exit_if_fail(error_s) \ + {if (error_s.error_str) {\ + fprintf (stderr, "Error: '%s' code: '%d'\n", \ + error_s.error_str, error_s.error_code); \ + exit(-1);}} + +#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 FOURCC_RGB565 FOURCC('R','G','B','P') +#define FOURCC_RGB32 FOURCC('R','G','B','4') +#define FOURCC_I420 FOURCC('I','4','2','0') +#define FOURCC_SR16 FOURCC('S','R','1','6') +#define FOURCC_SR32 FOURCC('S','R','3','2') +#define FOURCC_S420 FOURCC('S','4','2','0') + +#define FOURCC_SN12 FOURCC('S','N','1','2') +#define XVIMAGE_SN12 \ + { \ + FOURCC_SN12, \ + XvYUV, \ + LSBFirst, \ + {'S','N','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 2, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define DBG \ +{printf("%s %d\n", __FUNCTION__, __LINE__);} + +typedef struct +{ + uint32_t min_width; + uint32_t min_height; + uint32_t max_width; + uint32_t max_height; + int src_change; + int dst_change; + uint32_t image_width; + uint32_t image_height; + uint32_t image_fourcc; + size_t count_frame_per_change; + size_t frame_per_second; + size_t count_uniqes_frames; + /* TODO: More rules */ +} rule_s; + +typedef struct +{ + uint8_t error_code; + char const * error_str; +} error_s; + +typedef error_s (*prepare_test_case) (xcb_connection_t *, xcb_screen_t *, rule_s); +typedef error_s (*run_test_case) (xcb_connection_t *, xcb_screen_t *, rule_s); +typedef error_s (*close_test_case)(xcb_connection_t *, xcb_screen_t *, rule_s); + +typedef struct _test_case_s +{ + prepare_test_case prepare_test; + run_test_case run_test; + close_test_case close_test; +} test_case_s; +#endif |