From 07a1dfb819624224ea30635238b4be1dad981ff3 Mon Sep 17 00:00:00 2001 From: Peter Vicman Date: Sun, 10 Jul 2016 18:41:55 +0200 Subject: [PATCH] projects/imx6: update Linux kernel, libcec and Kodi Krypton --- packages/linux/package.mk | 9 + projects/imx6/bootloader/uEnv-matrix.txt | 15 +- projects/imx6/bootloader/uEnv-udoo.txt | 22 +- projects/imx6/bootloader/uEnv.txt | 15 +- projects/imx6/kodi/guisettings.xml | 16 + projects/imx6/linux/4.4-xbian/linux.arm.conf | 209 +- projects/imx6/options | 1 + .../kodi/kodi-100-krypton-from-mk01.patch | 98158 ++++++++++++++++ .../libcec/libcec-00-imx6-support.patch | 884 - .../libcec/libcec-100-from-xbian.patch | 1749 + .../linux-000-commits-d08b62d-ade5a7b.patch | 16315 --- .../linux/4.4-xbian/linux-000-from-mk01.patch | 63383 ++++++++++ .../linux-004-fix-build-with-gcc-5.patch | 16 + .../linux-320-udoo-lvds-support.patch | 268 - .../4.4-xbian/linux-330-tbs2910-dts-fix.patch | 11 - .../linux/4.4-xbian/linux-999-warn-only.patch | 13 + 16 files changed, 163493 insertions(+), 17591 deletions(-) create mode 100644 projects/imx6/kodi/guisettings.xml create mode 100644 projects/imx6/patches/kodi/kodi-100-krypton-from-mk01.patch delete mode 100644 projects/imx6/patches/libcec/libcec-00-imx6-support.patch create mode 100644 projects/imx6/patches/libcec/libcec-100-from-xbian.patch delete mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-000-commits-d08b62d-ade5a7b.patch create mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-000-from-mk01.patch create mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-004-fix-build-with-gcc-5.patch delete mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-320-udoo-lvds-support.patch delete mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-330-tbs2910-dts-fix.patch create mode 100644 projects/imx6/patches/linux/4.4-xbian/linux-999-warn-only.patch diff --git a/packages/linux/package.mk b/packages/linux/package.mk index ceeb2e6439..15a826a7a5 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -118,6 +118,15 @@ post_patch() { sed -i -e "s|^CONFIG_ISCSI_IBFT=.*$|# CONFIG_ISCSI_IBFT is not set|" $PKG_BUILD/.config fi + # enable different libcec version for imx6 project with kernel 4.4 + # using customized kernel driver + if [ "$PROJECT" = "imx6" ]; then + if [ "$LIBCEC_TYPE" = "xbian" -a "$LINUX" = "imx6-4.4-xbian" ]; then + sed -i -e "s|# CONFIG_MXC_HDMI_CEC is not set|CONFIG_MXC_HDMI_CEC=y|" $PKG_BUILD/.config + sed -i -e "s|CONFIG_MXC_HDMI_CEC_SR=y||" $PKG_BUILD/.config + fi + fi + # copy some extra firmware to linux tree cp -R $PKG_DIR/firmware/* $PKG_BUILD/firmware diff --git a/projects/imx6/bootloader/uEnv-matrix.txt b/projects/imx6/bootloader/uEnv-matrix.txt index 6e60f0b358..f6d06340d2 100644 --- a/projects/imx6/bootloader/uEnv-matrix.txt +++ b/projects/imx6/bootloader/uEnv-matrix.txt @@ -1,4 +1,17 @@ +# make boot more quiet +console_arg=quiet morequiet +# or having quiet and serial console +#console_arg=console=ttymxc0,115200 quiet morequiet +# show messages in serial console +#console_arg=console=ttymxc0,115200 no_console_suspend=1 + +# enable ssh +#ssh_arg=ssh + +# enable debugging (kodi debug) +#debugging_arg=debugging + zImage=/KERNEL bootfile=/KERNEL -mmcargs=setenv bootargs 'boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 quiet video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 dmfc=3 consoleblank=0' +mmcargs=setenv bootargs "boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 ${ssh_arg} ${console_arg} ${debugging_arg} video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 dmfc=3 consoleblank=0" uenvcmd=if test -n $ethaddr; then true; else setenv ethaddr 1E:ED:19:27:1A:B2; fi diff --git a/projects/imx6/bootloader/uEnv-udoo.txt b/projects/imx6/bootloader/uEnv-udoo.txt index f640b83628..a23d57f235 100644 --- a/projects/imx6/bootloader/uEnv-udoo.txt +++ b/projects/imx6/bootloader/uEnv-udoo.txt @@ -1,22 +1,32 @@ -# enable only one video line +# enable only one video section + # HDMI -video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 +video=mxcfb0:dev=hdmi,1920x1080M@60,bpp=32 + # 7" LVDS #video=mxcfb0:dev=ldb,800x480M@60,if=RGB666,bpp=32 +#fdt_file=imx6q-udoo-7lvds.dtb +#fdt_file=imx6dl-udoo-7lvds.dtb + # 15.6" LVDS -#video=mxcfb0:dev=ldb,1366x768M@60,if=RGB24,bpp=32 +#video=mxcfb0:dev=ldb,1360x768M@60,if=RGB24,bpp=32 +#fdt_file=imx6q-udoo-15lvds.dtb +#fdt_file=imx6dl-udoo-15lvds.dtb # make boot more quiet console_arg=quiet morequiet -# or having quiet and console +# or having quiet and serial console #console_arg=console=ttymxc0,115200 quiet morequiet -# show messages too +# show messages in serial console #console_arg=console=ttymxc0,115200 no_console_suspend=1 # enable ssh #ssh_arg=ssh +# enable debugging (kodi debug) +#debugging_arg=debugging + zImage=/KERNEL bootfile=/KERNEL -mmcargs=setenv bootargs boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 ${ssh_arg} ${console_arg} video=${video} dmfc=3 consoleblank=0 +mmcargs=setenv bootargs boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 ${ssh_arg} ${console_arg} ${debugging_arg} video=${video} dmfc=3 consoleblank=0 diff --git a/projects/imx6/bootloader/uEnv.txt b/projects/imx6/bootloader/uEnv.txt index e0e2762e33..3ff7e45c5d 100644 --- a/projects/imx6/bootloader/uEnv.txt +++ b/projects/imx6/bootloader/uEnv.txt @@ -1,3 +1,16 @@ +# make boot more quiet +console_arg=quiet morequiet +# or having quiet and serial console +#console_arg=console=ttymxc0,115200 quiet morequiet +# show messages in serial console +#console_arg=console=ttymxc0,115200 no_console_suspend=1 + +# enable ssh +#ssh_arg=ssh + +# enable debugging (kodi debug) +#debugging_arg=debugging + zImage=/KERNEL bootfile=/KERNEL -mmcargs=setenv bootargs 'boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 quiet video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 dmfc=3 consoleblank=0' +mmcargs=setenv bootargs "boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 ${ssh_arg} ${console_arg} ${debugging_arg} video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 dmfc=3 consoleblank=0" diff --git a/projects/imx6/kodi/guisettings.xml b/projects/imx6/kodi/guisettings.xml new file mode 100644 index 0000000000..7e4ba03a97 --- /dev/null +++ b/projects/imx6/kodi/guisettings.xml @@ -0,0 +1,16 @@ + + + /storage/screenshots/ + + + 3 + + + ALSA:hdmi:CARD=imxhdmisoc,DEV=0 + + + diff --git a/projects/imx6/linux/4.4-xbian/linux.arm.conf b/projects/imx6/linux/4.4-xbian/linux.arm.conf index 734f48ad9a..fa530f5839 100644 --- a/projects/imx6/linux/4.4-xbian/linux.arm.conf +++ b/projects/imx6/linux/4.4-xbian/linux.arm.conf @@ -1,9 +1,12 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.6 Kernel Configuration +# Linux/arm 4.4.14 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_ARM_DMA_USE_IOMMU=y +CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8 CONFIG_MIGHT_HAVE_PCI=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_HAVE_PROC_CPU=y @@ -104,12 +107,12 @@ CONFIG_RCU_EXPERT=y CONFIG_SRCU=y # CONFIG_TASKS_RCU is not set CONFIG_RCU_STALL_COMMON=y -CONFIG_RCU_FANOUT=16 -CONFIG_RCU_FANOUT_LEAF=8 +CONFIG_RCU_FANOUT=4 +CONFIG_RCU_FANOUT_LEAF=2 # CONFIG_TREE_RCU_TRACE is not set CONFIG_RCU_BOOST=y -CONFIG_RCU_KTHREAD_PRIO=1 -CONFIG_RCU_BOOST_DELAY=500 +CONFIG_RCU_KTHREAD_PRIO=7 +CONFIG_RCU_BOOST_DELAY=200 CONFIG_RCU_NOCB_CPU=y CONFIG_RCU_NOCB_CPU_NONE=y # CONFIG_RCU_NOCB_CPU_ZERO is not set @@ -179,7 +182,7 @@ CONFIG_EVENTFD=y # CONFIG_BPF_SYSCALL is not set CONFIG_SHMEM=y CONFIG_AIO=y -# CONFIG_ADVISE_SYSCALLS is not set +CONFIG_ADVISE_SYSCALLS=y CONFIG_USERFAULTFD=y CONFIG_PCI_QUIRKS=y CONFIG_MEMBARRIER=y @@ -193,7 +196,7 @@ CONFIG_PERF_USE_VMALLOC=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set -# CONFIG_COMPAT_BRK is not set +CONFIG_COMPAT_BRK=y CONFIG_SLUB=y # CONFIG_SYSTEM_DATA_VERIFICATION is not set # CONFIG_PROFILING is not set @@ -207,7 +210,6 @@ CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y @@ -222,9 +224,9 @@ CONFIG_HAVE_PERF_USER_STACK_DUMP=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_HAVE_CC_STACKPROTECTOR=y -CONFIG_CC_STACKPROTECTOR=y -# CONFIG_CC_STACKPROTECTOR_NONE is not set -CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set # CONFIG_CC_STACKPROTECTOR_STRONG is not set CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y @@ -542,10 +544,10 @@ CONFIG_HZ_FIXED=0 # CONFIG_HZ_100 is not set # CONFIG_HZ_200 is not set # CONFIG_HZ_250 is not set -CONFIG_HZ_300=y -# CONFIG_HZ_500 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_500=y # CONFIG_HZ_1000 is not set -CONFIG_HZ=300 +CONFIG_HZ=500 CONFIG_SCHED_HRTICK=y # CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y @@ -558,7 +560,7 @@ CONFIG_HIGHMEM=y # CONFIG_CPU_SW_DOMAIN_PAN is not set CONFIG_HW_PERF_EVENTS=y CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ARM_MODULE_PLTS=y +# CONFIG_ARM_MODULE_PLTS is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y @@ -572,7 +574,7 @@ CONFIG_MIGRATION=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y # CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=16384 +CONFIG_DEFAULT_MMAP_MIN_ADDR=8192 # CONFIG_CLEANCACHE is not set # CONFIG_FRONTSWAP is not set CONFIG_CMA=y @@ -681,14 +683,18 @@ CONFIG_BINFMT_MISC=m CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_SUSPEND_SKIP_SYNC is not set -# CONFIG_HIBERNATION is not set +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_PM_STD_PARTITION="" CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y # CONFIG_PM_AUTOSLEEP is not set -# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=100 +CONFIG_PM_WAKELOCKS_GC=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set -# CONFIG_APM_EMULATION is not set +CONFIG_APM_EMULATION=m CONFIG_PM_OPP=y CONFIG_PM_CLK=y CONFIG_PM_GENERIC_DOMAINS=y @@ -756,25 +762,10 @@ CONFIG_INET_LRO=m CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y CONFIG_INET_UDP_DIAG=m -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=m -CONFIG_TCP_CONG_CUBIC=m -CONFIG_TCP_CONG_WESTWOOD=m -CONFIG_TCP_CONG_HTCP=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=y -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_TCP_CONG_LP=m -CONFIG_TCP_CONG_VENO=m -CONFIG_TCP_CONG_YEAH=y -CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_TCP_CONG_DCTCP=m -# CONFIG_TCP_CONG_CDG is not set -CONFIG_DEFAULT_VEGAS=y -# CONFIG_DEFAULT_RENO is not set -CONFIG_DEFAULT_TCP_CONG="vegas" -CONFIG_TCP_MD5SIG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -1137,13 +1128,13 @@ CONFIG_IP_DCCP_CCID3=y CONFIG_IP_DCCP_TFRC_LIB=y CONFIG_IP_SCTP=m # CONFIG_SCTP_DBG_OBJCNT is not set -CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set # CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set -# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set -CONFIG_SCTP_COOKIE_HMAC_MD5=y -CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y +# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set +# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set CONFIG_RDS=m -# CONFIG_RDS_TCP is not set +CONFIG_RDS_TCP=m # CONFIG_RDS_DEBUG is not set CONFIG_TIPC=m CONFIG_TIPC_MEDIA_UDP=y @@ -1154,6 +1145,8 @@ CONFIG_L2TP_V3=y CONFIG_L2TP_IP=m CONFIG_L2TP_ETH=m CONFIG_STP=m +CONFIG_GARP=m +CONFIG_MRP=m CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y CONFIG_BRIDGE_VLAN_FILTERING=y @@ -1162,8 +1155,8 @@ CONFIG_NET_DSA=y CONFIG_NET_DSA_HWMON=y CONFIG_NET_DSA_TAG_EDSA=y CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_VLAN_8021Q_MVRP is not set +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y # CONFIG_DECNET is not set CONFIG_LLC=m CONFIG_LLC2=m @@ -1174,7 +1167,7 @@ CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_PHONET is not set +CONFIG_PHONET=m # CONFIG_6LOWPAN is not set # CONFIG_IEEE802154 is not set CONFIG_NET_SCHED=y @@ -1263,7 +1256,7 @@ CONFIG_NET_MPLS_GSO=m # CONFIG_MPLS_ROUTING is not set # CONFIG_HSR is not set CONFIG_NET_SWITCHDEV=y -# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_NET_L3_MASTER_DEV=y CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -1515,7 +1508,7 @@ CONFIG_DMA_CMA=y # # Default contiguous memory area size: # -CONFIG_CMA_SIZE_MBYTES=288 +CONFIG_CMA_SIZE_MBYTES=320 CONFIG_CMA_SIZE_SEL_MBYTES=y # CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set # CONFIG_CMA_SIZE_SEL_MIN is not set @@ -1639,7 +1632,7 @@ CONFIG_MTD_NAND_MXC=y CONFIG_MTD_SPI_NOR=m CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y CONFIG_SPI_FSL_QUADSPI=m -CONFIG_MTD_UBI=y +CONFIG_MTD_UBI=m CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_LIMIT=20 # CONFIG_MTD_UBI_FASTMAP is not set @@ -2014,19 +2007,19 @@ CONFIG_DM_VERITY=m # CONFIG_FIREWIRE is not set # CONFIG_FIREWIRE_NOSY is not set CONFIG_NETDEVICES=y -CONFIG_MII=y +CONFIG_MII=m CONFIG_NET_CORE=y CONFIG_BONDING=m CONFIG_DUMMY=m CONFIG_EQUALIZER=m # CONFIG_NET_FC is not set # CONFIG_IFB is not set -CONFIG_NET_TEAM=y -CONFIG_NET_TEAM_MODE_BROADCAST=y -CONFIG_NET_TEAM_MODE_ROUNDROBIN=y -CONFIG_NET_TEAM_MODE_RANDOM=y -CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=y -CONFIG_NET_TEAM_MODE_LOADBALANCE=y +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m CONFIG_IPVLAN=m @@ -2041,6 +2034,7 @@ CONFIG_TUN=m CONFIG_VETH=m # CONFIG_VIRTIO_NET is not set CONFIG_NLMON=m +# CONFIG_NET_VRF is not set # CONFIG_ARCNET is not set # @@ -2067,7 +2061,7 @@ CONFIG_NET_DSA_MV88E6XXX=y CONFIG_NET_DSA_MV88E6352=y # CONFIG_NET_DSA_BCM_SF2 is not set CONFIG_ETHERNET=y -CONFIG_MDIO=y +CONFIG_MDIO=m # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set # CONFIG_NET_VENDOR_AGERE is not set @@ -2076,11 +2070,11 @@ CONFIG_MDIO=y # CONFIG_NET_VENDOR_AMD is not set # CONFIG_NET_VENDOR_ARC is not set CONFIG_NET_VENDOR_ATHEROS=y -CONFIG_ATL2=y -CONFIG_ATL1=y -CONFIG_ATL1E=y -CONFIG_ATL1C=y -CONFIG_ALX=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_ALX=m # CONFIG_NET_VENDOR_AURORA is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set @@ -2100,7 +2094,7 @@ CONFIG_ALX=y CONFIG_NET_VENDOR_FREESCALE=y CONFIG_FEC=y CONFIG_FSL_PQ_MDIO=y -CONFIG_FSL_XGMAC_MDIO=y +# CONFIG_FSL_XGMAC_MDIO is not set CONFIG_GIANFAR=y # CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_NET_VENDOR_HP is not set @@ -2245,6 +2239,7 @@ CONFIG_USB_NET_KALMIA=m CONFIG_USB_NET_QMI_WWAN=m CONFIG_USB_HSO=m CONFIG_USB_NET_INT51X1=m +# CONFIG_USB_CDC_PHONET is not set CONFIG_USB_IPHETH=m CONFIG_USB_SIERRA_NET=m CONFIG_USB_VL600=m @@ -2570,6 +2565,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m +# CONFIG_INPUT_APMPOWER is not set # # Input Device Drivers @@ -2591,7 +2587,7 @@ CONFIG_KEYBOARD_MATRIX=m # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set -CONFIG_KEYBOARD_IMX=y +CONFIG_KEYBOARD_IMX=m # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_OPENCORES is not set # CONFIG_KEYBOARD_SAMSUNG is not set @@ -2653,7 +2649,7 @@ CONFIG_JOYSTICK_XPAD_LEDS=y # CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_PROPERTIES=y -# CONFIG_TOUCHSCREEN_88PM860X is not set +CONFIG_TOUCHSCREEN_88PM860X=m CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_TOUCHSCREEN_AD7877=m CONFIG_TOUCHSCREEN_AD7879=m @@ -2735,8 +2731,8 @@ CONFIG_TOUCHSCREEN_TPS6507X=m CONFIG_TOUCHSCREEN_ZFORCE=m CONFIG_TOUCHSCREEN_ROHM_BU21023=m CONFIG_INPUT_MISC=y -# CONFIG_INPUT_88PM860X_ONKEY is not set -# CONFIG_INPUT_88PM80X_ONKEY is not set +CONFIG_INPUT_88PM860X_ONKEY=m +CONFIG_INPUT_88PM80X_ONKEY=m CONFIG_INPUT_AD714X=m CONFIG_INPUT_AD714X_I2C=m CONFIG_INPUT_AD714X_SPI=m @@ -2824,7 +2820,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DW=m # CONFIG_SERIAL_8250_EM is not set # CONFIG_SERIAL_8250_RT288X is not set # CONFIG_SERIAL_8250_INGENIC is not set @@ -2845,14 +2841,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_OF_PLATFORM is not set # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SC16IS7XX is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y +CONFIG_SERIAL_BCM63XX=m # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_XILINX_PS_UART is not set -CONFIG_SERIAL_ARC=y -CONFIG_SERIAL_ARC_CONSOLE=y +CONFIG_SERIAL_ARC=m CONFIG_SERIAL_ARC_NR_PORTS=1 # CONFIG_SERIAL_RP2 is not set CONFIG_SERIAL_FSL_LPUART=y @@ -3007,11 +3001,8 @@ CONFIG_PPS_CLIENT_GPIO=m # PTP clock support # CONFIG_PTP_1588_CLOCK=y -CONFIG_PTP_1588_CLOCK_GIANFAR=y - -# -# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. -# +CONFIG_PTP_1588_CLOCK_GIANFAR=m +# CONFIG_DP83640_PHY is not set CONFIG_PINCTRL=y # @@ -3057,8 +3048,7 @@ CONFIG_GPIO_ADP5588=m CONFIG_GPIO_ADNP=m # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set -CONFIG_GPIO_PCA953X=y -CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GPIO_PCA953X=m CONFIG_GPIO_PCF857X=m CONFIG_GPIO_SX150X=y @@ -3077,14 +3067,14 @@ CONFIG_GPIO_SX150X=y # # SPI GPIO expanders # -CONFIG_GPIO_74X164=y +CONFIG_GPIO_74X164=m # CONFIG_GPIO_MAX7301 is not set -CONFIG_GPIO_MC33880=y +CONFIG_GPIO_MC33880=m # # SPI or I2C GPIO expanders # -CONFIG_GPIO_MCP23S08=y +CONFIG_GPIO_MCP23S08=m # # USB GPIO expanders @@ -3123,6 +3113,7 @@ CONFIG_W1_SLAVE_BQ27000=m CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set +# CONFIG_APM_POWER is not set # CONFIG_GENERIC_ADC_BATTERY is not set CONFIG_TEST_POWER=m # CONFIG_BATTERY_88PM860X is not set @@ -3154,6 +3145,7 @@ CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_IMX=y CONFIG_POWER_RESET_LTC2952=y +# CONFIG_POWER_RESET_QNAP is not set CONFIG_POWER_RESET_RESTART=y CONFIG_POWER_RESET_VERSATILE=y # CONFIG_POWER_RESET_SNVS is not set @@ -3210,10 +3202,10 @@ CONFIG_SENSORS_MC13783_ADC=y # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4260 is not set # CONFIG_SENSORS_LTC4261 is not set -CONFIG_SENSORS_MAX1111=y -CONFIG_SENSORS_MAX16065=y -CONFIG_SENSORS_MAX1619=y -CONFIG_SENSORS_MAX1668=y +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m # CONFIG_SENSORS_MAX197 is not set # CONFIG_SENSORS_MAX6639 is not set # CONFIG_SENSORS_MAX6642 is not set @@ -3434,7 +3426,7 @@ CONFIG_MFD_88PM860X=y # CONFIG_MFD_RK808 is not set # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set -CONFIG_MFD_SI476X_CORE=y +CONFIG_MFD_SI476X_CORE=m # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set @@ -4973,9 +4965,9 @@ CONFIG_USB_HSIC_USB3503=m # CONFIG_USB_PHY=y CONFIG_NOP_USB_XCEIV=y -CONFIG_AM335X_CONTROL_USB=y -CONFIG_AM335X_PHY_USB=y -CONFIG_USB_GPIO_VBUS=y +CONFIG_AM335X_CONTROL_USB=m +CONFIG_AM335X_PHY_USB=m +CONFIG_USB_GPIO_VBUS=m CONFIG_USB_ISP1301=y CONFIG_USB_MXS_PHY=y # CONFIG_USB_ULPI is not set @@ -4988,7 +4980,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 # # USB Peripheral Controller # -CONFIG_USB_FSL_USB2=m +CONFIG_USB_FSL_USB2=y # CONFIG_USB_FUSB300 is not set # CONFIG_USB_FOTG210_UDC is not set # CONFIG_USB_GR_UDC is not set @@ -5034,6 +5026,7 @@ CONFIG_USB_CONFIGFS_ECM=y CONFIG_USB_CONFIGFS_ECM_SUBSET=y CONFIG_USB_CONFIGFS_RNDIS=y CONFIG_USB_CONFIGFS_EEM=y +# CONFIG_USB_CONFIGFS_PHONET is not set CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_LB_SS=y CONFIG_USB_CONFIGFS_F_FS=y @@ -5061,6 +5054,7 @@ CONFIG_USB_G_SERIAL=m CONFIG_USB_MIDI_GADGET=m CONFIG_USB_G_PRINTER=m CONFIG_USB_CDC_COMPOSITE=m +# CONFIG_USB_G_NOKIA is not set CONFIG_USB_G_ACM_MS=m CONFIG_USB_G_MULTI=m CONFIG_USB_G_MULTI_RNDIS=y @@ -5270,6 +5264,7 @@ CONFIG_DMADEVICES=y # # DMA Devices # +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y CONFIG_DMA_ENGINE=y CONFIG_DMA_VIRTUAL_CHANNELS=y CONFIG_DMA_OF=y @@ -5291,6 +5286,7 @@ CONFIG_DW_DMAC_PCI=m # CONFIG_ASYNC_TX_DMA=y # CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE_RAID=y # CONFIG_AUXDISPLAY is not set CONFIG_UIO=m # CONFIG_UIO_CIF is not set @@ -5302,6 +5298,7 @@ CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set # CONFIG_UIO_PRUSS is not set # CONFIG_UIO_MF624 is not set +# CONFIG_VFIO is not set # CONFIG_VIRT_DRIVERS is not set CONFIG_VIRTIO=m @@ -5556,13 +5553,17 @@ CONFIG_CLKSRC_MMIO=y # CONFIG_EM_TIMER_STI is not set CONFIG_CLKSRC_IMX_GPT=y # CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y CONFIG_IOMMU_SUPPORT=y # # Generic IOMMU Pagetable Support # -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -# CONFIG_ARM_SMMU is not set +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_OF_IOMMU=y +CONFIG_ARM_SMMU=y # # Remoteproc drivers @@ -5923,7 +5924,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT2=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_ENCRYPTION=m CONFIG_EXT4_FS_ENCRYPTION=y # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y @@ -6173,7 +6174,7 @@ CONFIG_NLS_ISO8859_7=m CONFIG_NLS_ISO8859_9=m CONFIG_NLS_ISO8859_13=m CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_MAC_ROMAN=m @@ -6214,7 +6215,6 @@ CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y -CONFIG_FRAME_POINTER=y CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 # CONFIG_DEBUG_KERNEL is not set @@ -6248,7 +6248,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_TIMEOUT=300 CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -6265,7 +6265,7 @@ CONFIG_GENERIC_TRACER=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y CONFIG_FUNCTION_TRACER=y -CONFIG_FUNCTION_GRAPH_TRACER=y +# CONFIG_FUNCTION_GRAPH_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set @@ -6312,7 +6312,6 @@ CONFIG_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_STRICT_DEVMEM is not set CONFIG_ARM_UNWIND=y -CONFIG_OLD_MCOUNT=y # CONFIG_DEBUG_USER is not set CONFIG_DEBUG_IMX_UART_PORT=1 CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" @@ -6364,7 +6363,7 @@ CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_CRYPTODEV=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_NULL=y @@ -6455,14 +6454,14 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ZLIB=y CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_842=y +CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=y CONFIG_CRYPTO_LZ4HC=y # # Random Number Generation # -CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_ANSI_CPRNG=m CONFIG_CRYPTO_DRBG_MENU=y CONFIG_CRYPTO_DRBG_HMAC=y # CONFIG_CRYPTO_DRBG_HASH is not set @@ -6534,8 +6533,8 @@ CONFIG_LIBCRC32C=y CONFIG_CRC8=m # CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set # CONFIG_RANDOM32_SELFTEST is not set -CONFIG_842_COMPRESS=y -CONFIG_842_DECOMPRESS=y +CONFIG_842_COMPRESS=m +CONFIG_842_DECOMPRESS=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y @@ -6543,7 +6542,7 @@ CONFIG_LZO_DECOMPRESS=y CONFIG_LZ4_COMPRESS=y CONFIG_LZ4HC_COMPRESS=y CONFIG_LZ4_DECOMPRESS=y -CONFIG_XZ_DEC=y +CONFIG_XZ_DEC=m # CONFIG_XZ_DEC_X86 is not set # CONFIG_XZ_DEC_POWERPC is not set # CONFIG_XZ_DEC_IA64 is not set diff --git a/projects/imx6/options b/projects/imx6/options index 179e170d45..4c06f2c953 100644 --- a/projects/imx6/options +++ b/projects/imx6/options @@ -66,6 +66,7 @@ # default is 4.4 from xbian if [ -z "$LINUX_VERSION" -o "$LINUX_VERSION" != "sr-3.14" ]; then LINUX="imx6-4.4-xbian" + LIBCEC_TYPE="xbian" else LINUX="imx6" fi diff --git a/projects/imx6/patches/kodi/kodi-100-krypton-from-mk01.patch b/projects/imx6/patches/kodi/kodi-100-krypton-from-mk01.patch new file mode 100644 index 0000000000..fd9958ade6 --- /dev/null +++ b/projects/imx6/patches/kodi/kodi-100-krypton-from-mk01.patch @@ -0,0 +1,98158 @@ +From fe368163f2279b1dfe40c603d852a2eb7763c38c Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Sun, 10 Jul 2016 13:46:33 +0200 +Subject: [PATCH] patch for kodi krypton from mk01 + +kodi base: kodi-17.0-alpha2-f3ca4ea +kodi mk01: + https://github.com/mk01/xbmc/tree/treeKrypton 0b3954d54c41c494e30143794ccfba0b690f926d +--- + Makefile.in | 26 + + Makefile.python-interfaces | 15 + + README.md | 2 +- + addons/repository.xbmc.org/addon.xml | 8 +- + .../resource.language.en_gb/resources/strings.po | 241 +- + addons/screensaver.gles.ball/addon.xml | 121 + + addons/screensaver.gles.ball/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.noise/addon.xml | 121 + + addons/screensaver.gles.noise/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.plasma/addon.xml | 121 + + addons/screensaver.gles.plasma/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.plasma2/addon.xml | 121 + + addons/screensaver.gles.plasma2/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.solarwinds/addon.xml | 119 + + addons/screensaver.gles.solarwinds/icon.png | Bin 0 -> 14774 bytes + addons/screensaver.gles.spiral/addon.xml | 121 + + addons/screensaver.gles.spiral/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.stellar/addon.xml | 121 + + addons/screensaver.gles.stellar/icon.png | Bin 0 -> 5657 bytes + addons/screensaver.gles.warp/addon.xml | 119 + + addons/screensaver.gles.warp/icon.png | Bin 0 -> 9424 bytes + addons/webinterface.default/addon.xml | 10 +- + addons/webinterface.default/js/MediaLibrary.js | 8 +- + appveyor.yml | 12 +- + codegenerator.mk | 5 - + configure.ac | 209 +- + lib/libUPnP/CMakeLists.txt | 2 +- + lib/libdvd/Makefile.in | 14 +- + project/BuildDependencies/scripts/0_package.list | 16 +- + project/VS2010Express/XBMC for Windows.sln | 20 +- + project/VS2010Express/XBMC.vcxproj | 114 +- + project/VS2010Express/XBMC.vcxproj.filters | 309 +- + project/cmake/CMakeLists.txt | 40 +- + project/cmake/KodiConfig.cmake.in | 40 +- + project/cmake/README.md | 10 - + project/cmake/addons/CMakeLists.txt | 13 +- + project/cmake/installdata/cmake-files.txt | 2 + + project/cmake/installdata/darwin/packaging.txt | 3 + + project/cmake/installdata/darwin/runtime.txt | 2 + + project/cmake/modules/FindCCache.cmake | 2 +- + project/cmake/modules/FindCXX11.cmake | 4 +- + project/cmake/modules/FindCrossGUID.cmake | 6 +- + project/cmake/modules/FindD3DX11Effects.cmake | 7 +- + project/cmake/modules/FindEMBEDDED.cmake | 2 +- + project/cmake/modules/FindFFMPEG.cmake | 3 +- + project/cmake/modules/FindLibDvd.cmake | 53 +- + project/cmake/modules/FindLibSmbClient.cmake | 32 +- + project/cmake/modules/FindLzo2.cmake | 6 +- + project/cmake/modules/FindMicroHttpd.cmake | 82 +- + project/cmake/modules/FindOpenGl.cmake | 2 +- + project/cmake/modules/FindPulseAudio.cmake | 36 +- + project/cmake/modules/FindRTMP.cmake | 21 + + project/cmake/modules/FindSSE.cmake | 118 +- + project/cmake/modules/FindTagLib.cmake | 2 +- + project/cmake/modules/FindXslt.cmake | 4 - + project/cmake/modules/FindYajl.cmake | 2 +- + project/cmake/scripts/android/ArchSetup.cmake | 7 +- + project/cmake/scripts/android/Install.cmake | 118 - + project/cmake/scripts/android/PathSetup.cmake | 34 +- + project/cmake/scripts/common/AddOptions.cmake | 84 +- + project/cmake/scripts/common/AddonHelpers.cmake | 197 +- + .../cmake/scripts/common/CheckTargetPlatform.cmake | 4 +- + .../scripts/common/GenerateVersionedFiles.cmake | 19 +- + project/cmake/scripts/common/GeneratorSetup.cmake | 5 - + project/cmake/scripts/common/HandleDepends.cmake | 14 +- + project/cmake/scripts/common/Macros.cmake | 50 +- + project/cmake/scripts/common/ManageString.cmake | 235 + + project/cmake/scripts/common/PathSetup.cmake | 3 + + project/cmake/scripts/common/PrepareEnv.cmake | 27 +- + project/cmake/scripts/darwin/ArchSetup.cmake | 33 + + project/cmake/scripts/darwin/Install.cmake | 38 + + project/cmake/scripts/darwin/Macros.cmake | 110 + + project/cmake/scripts/darwin/PathSetup.cmake | 32 + + project/cmake/scripts/ios/Macros.cmake | 2 +- + project/cmake/scripts/ios/PathSetup.cmake | 2 +- + project/cmake/scripts/linux/Install.cmake | 181 +- + project/cmake/scripts/windows/CFlagOverrides.cmake | 2 +- + .../cmake/scripts/windows/CXXFlagOverrides.cmake | 2 +- + project/cmake/treedata/darwin/subdirs.txt | 12 + + system/keymaps/appcommand.xml | 6 +- + system/keymaps/customcontroller.AppleRemote.xml | 15 +- + system/keymaps/customcontroller.Harmony.xml | 66 +- + system/keymaps/gamepad.xml | 43 +- + system/keymaps/joystick.xml | 36 +- + system/keymaps/keyboard.xml | 67 +- + system/keymaps/mouse.xml | 10 +- + system/keymaps/remote.xml | 66 +- + system/keymaps/touchscreen.xml | 6 +- + system/peripherals.xml | 13 +- + system/settings/imx6.xml | 28 +- + system/settings/rbp.xml | 2 +- + system/settings/settings.xml | 274 +- + tools/EventClients/Clients/WiiRemote/Makefile | 2 +- + tools/android/packaging/Makefile.in | 1 + + tools/buildsteps/android/make-binary-addons | 9 +- + tools/buildsteps/android/package | 17 +- + tools/buildsteps/androidx86/make-binary-addons | 9 +- + tools/buildsteps/androidx86/package | 19 +- + tools/depends/configure.ac | 4 +- + tools/depends/native/Makefile | 2 +- + tools/depends/native/gettext-native/Makefile | 2 +- + tools/depends/native/giflib-native/Makefile | 2 +- + tools/depends/native/liblzo2-native/Makefile | 2 +- + tools/depends/native/swig-native/Makefile | 2 +- + tools/depends/target/Makefile | 5 +- + tools/depends/target/Toolchain.cmake.in | 105 +- + tools/depends/target/config-binaddons.site.in | 2 +- + tools/depends/target/config.site.in | 2 +- + tools/depends/target/crossguid/CMakeLists.txt | 2 +- + tools/depends/target/crossguid/FindCXX11.cmake | 4 +- + tools/depends/target/crossguid/Makefile | 4 +- + tools/depends/target/curl/Makefile | 2 +- + ...-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch | 69 + + .../0001-Squashed-commit-of-the-following.patch | 2180 ++ + ...vcodec-add-h264_mvc-codec-id-and-profiles.patch | 67 + + ...er-add-support-for-parsing-h264-mvc-NALUs.patch | 113 + + ...Signal-unsupported-GMC-with-more-than-one.patch | 48 + + .../73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch | 24 + + tools/depends/target/ffmpeg/CMakeLists.txt | 2 +- + tools/depends/target/ffmpeg/Makefile | 47 +- + .../added_ARM_NEON_optimized_SAO_patches.patch | 3328 ++ + tools/depends/target/ffmpeg/autobuild.sh | 10 +- + ...arsing_of_mvc_slices_in_some_corner_cases.patch | 66 + + ...hevcdsp_ARM_NEON_optimized_epel_functions.patch | 409 + + .../target/ffmpeg/pfcd_hevc_optimisations.patch | 38136 +++++++++++++++++++ + tools/depends/target/gettext/Makefile | 2 +- + tools/depends/target/jpeg/Makefile | 39 + + tools/depends/target/liblzo2/Makefile | 2 +- + tools/depends/target/libmicrohttpd/Makefile | 2 +- + tools/depends/target/libmodplug/Makefile | 42 + + tools/depends/target/libpng/Makefile | 2 +- + tools/depends/target/librtmp/Makefile | 2 +- + tools/depends/target/python27/Makefile | 3 +- + .../python27/Python-2.7.10-crosscompile.patch | 10 +- + .../target/python27/Python-no-export-path.patch | 2 +- + tools/depends/target/python27/Python-setup.patch | 4 +- + tools/depends/target/python27/fix-ffi.patch | 4 +- + .../target/python27/urllib-ssl-no-cert_check.patch | 14 + + xbmc/Application.cpp | 161 +- + xbmc/Application.h | 28 +- + xbmc/ApplicationPlayer.cpp | 2 - + xbmc/ApplicationPlayer.h | 5 +- + xbmc/AutoSwitch.cpp | 14 + + xbmc/Autorun.cpp | 12 +- + xbmc/ContextMenuItem.h | 2 +- + xbmc/ContextMenuManager.cpp | 2 +- + xbmc/CueDocument.h | 3 - + xbmc/DatabaseManager.cpp | 2 +- + xbmc/DllPaths_generated.h.in | 2 + + xbmc/DllPaths_generated_android.h.in | 2 + + xbmc/DllPaths_win32.h | 1 + + xbmc/FileItem.cpp | 28 +- + xbmc/FileItem.h | 1 + + xbmc/GUIInfoManager.cpp | 71 +- + xbmc/GUIInfoManager.h | 1 - + xbmc/GUILargeTextureManager.h | 1 - + xbmc/GUIPassword.cpp | 16 +- + xbmc/LangInfo.cpp | 17 +- + xbmc/PartyModeManager.cpp | 5 +- + xbmc/PlayListPlayer.cpp | 9 +- + xbmc/ServiceManager.cpp | 5 +- + xbmc/ServiceManager.h | 6 +- + xbmc/TextureCache.cpp | 2 +- + xbmc/TextureCache.h | 2 +- + xbmc/TextureDatabase.cpp | 2 +- + xbmc/TextureDatabase.h | 3 - + xbmc/ThumbnailCache.cpp | 1 + + xbmc/URL.cpp | 7 +- + xbmc/Util.cpp | 16 +- + xbmc/XBDateTime.cpp | 2 +- + xbmc/addons/Addon.cpp | 2 +- + xbmc/addons/Addon.h | 14 +- + xbmc/addons/AddonBuilder.cpp | 5 +- + xbmc/addons/AddonBuilder.h | 2 - + xbmc/addons/AddonDatabase.cpp | 435 +- + xbmc/addons/AddonDatabase.h | 36 +- + xbmc/addons/AddonDll.h | 1 - + xbmc/addons/AddonInstaller.cpp | 19 +- + xbmc/addons/AddonInstaller.h | 2 - + xbmc/addons/AddonManager.cpp | 12 +- + xbmc/addons/AddonStatusHandler.cpp | 6 +- + xbmc/addons/ContextMenuAddon.h | 3 - + xbmc/addons/GUIDialogAddonInfo.cpp | 82 +- + xbmc/addons/GUIDialogAddonInfo.h | 15 +- + xbmc/addons/GUIDialogAddonSettings.cpp | 2 +- + xbmc/addons/GUIDialogAddonSettings.h | 4 - + xbmc/addons/GUIWindowAddonBrowser.h | 3 - + xbmc/addons/IAddon.h | 2 - + xbmc/addons/InputStream.cpp | 30 +- + xbmc/addons/InputStream.h | 7 +- + xbmc/addons/LanguageResource.cpp | 2 +- + xbmc/addons/PVRClient.cpp | 16 +- + xbmc/addons/PVRClient.h | 5 +- + xbmc/addons/Repository.cpp | 7 +- + xbmc/addons/Repository.h | 4 - + xbmc/addons/Scraper.cpp | 6 +- + xbmc/addons/Scraper.h | 5 - + xbmc/addons/Skin.cpp | 4 +- + xbmc/addons/Visualisation.h | 1 - + xbmc/addons/binary/interfaces/AddonInterfaces.cpp | 2 +- + .../api1/AudioDSP/AddonCallbacksAudioDSP.cpp | 4 +- + .../binary/interfaces/api1/GUI/AddonGUIWindow.cpp | 7 +- + .../include/kodi/dlfcn-win32.cpp | 2 +- + .../include/kodi/kodi_peripheral_dll.h | 2 +- + .../include/kodi/kodi_peripheral_types.h | 2 +- + .../kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h | 2 +- + xbmc/commons/ilog.h | 2 + + xbmc/cores/AudioEngine/AESinkFactory.cpp | 7 +- + xbmc/cores/AudioEngine/CMakeLists.txt | 22 +- + xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp | 935 + + xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h | 413 + + .../AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp | 871 + + .../cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h | 424 + + .../AudioEngine/DSPAddons/ActiveAEDSPDatabase.cpp | 545 + + .../AudioEngine/DSPAddons/ActiveAEDSPDatabase.h | 216 + + .../AudioEngine/DSPAddons/ActiveAEDSPMode.cpp | 430 + + xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h | 325 + + .../AudioEngine/DSPAddons/ActiveAEDSPProcess.cpp | 1801 + + .../AudioEngine/DSPAddons/ActiveAEDSPProcess.h | 353 + + .../AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 37 +- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h | 8 +- + .../Engines/ActiveAE/ActiveAEBuffer.cpp | 2 +- + .../AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h | 2 +- + .../AudioEngine/Engines/ActiveAE/ActiveAESink.cpp | 31 +- + .../AudioEngine/Engines/ActiveAE/ActiveAESound.cpp | 2 +- + .../Engines/ActiveAE/ActiveAEStream.cpp | 15 +- + xbmc/cores/AudioEngine/Makefile.in | 10 +- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 49 +- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp | 18 +- + xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp | 2 +- + xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp | 8 +- + xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp | 11 +- + .../AudioEngine/Sinks/osx/AEDeviceEnumerationOSX.h | 4 - + xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h | 2 - + .../AudioEngine/Sinks/osx/CoreAudioStream.cpp | 4 +- + xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h | 1 - + xbmc/cores/AudioEngine/Utils/AEELDParser.cpp | 2 +- + xbmc/cores/DllLoader/DllLoader.cpp | 4 +- + xbmc/cores/DllLoader/Win32DllLoader.cpp | 4 +- + xbmc/cores/DllLoader/exports/CMakeLists.txt | 6 +- + xbmc/cores/DllLoader/exports/emu_msvcrt.cpp | 11 + + xbmc/cores/IPlayer.h | 5 +- + xbmc/cores/VideoPlayer/DVDClock.cpp | 40 +- + xbmc/cores/VideoPlayer/DVDClock.h | 5 +- + .../DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp | 5 - + .../DVDCodecs/Overlay/contrib/cc_decoder708.cpp | 36 +- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 233 +- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 17 +- + .../VideoPlayer/DVDCodecs/Video/CMakeLists.txt | 2 +- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h | 2 + + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 43 +- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 4 +- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 10 +- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1947 +- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 376 +- + .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 2 +- + .../VideoPlayer/DVDCodecs/Video/MMALCodec.cpp | 55 +- + xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h | 3 - + .../VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp | 56 +- + .../cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h | 3 - + xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMax.h | 2 - + .../VideoPlayer/DVDCodecs/Video/OpenMaxVideo.cpp | 26 +- + .../VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h | 4 +- + xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h | 1 - + xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h | 2 - + xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h | 4 + + .../VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp | 7 +- + .../cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h | 1 - + .../VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 20 +- + .../VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 3 +- + .../VideoPlayer/DVDInputStreams/CMakeLists.txt | 3 + + .../DVDInputStreams/DVDFactoryInputStream.cpp | 13 +- + .../DVDInputStreams/DVDFactoryInputStream.h | 2 - + .../VideoPlayer/DVDInputStreams/DVDInputStream.h | 1 + + .../DVDInputStreams/DVDInputStreamBluray.cpp | 2 +- + .../DVDInputStreams/DVDInputStreamPVRManager.cpp | 5 +- + .../DVDInputStreams/DVDInputStreamPVRManager.h | 2 +- + .../DVDInputStreams/DVDInputStreamRTMP.cpp | 265 + + .../DVDInputStreams/DVDInputStreamRTMP.h | 61 + + .../DVDInputStreams/DVDInputStreamStack.h | 1 - + .../cores/VideoPlayer/DVDInputStreams/DllLibRTMP.h | 79 + + .../VideoPlayer/DVDInputStreams/InputStreamAddon.h | 3 - + xbmc/cores/VideoPlayer/DVDInputStreams/Makefile | 1 + + xbmc/cores/VideoPlayer/DVDMessage.h | 2 +- + xbmc/cores/VideoPlayer/DVDStreamInfo.cpp | 8 + + xbmc/cores/VideoPlayer/DVDStreamInfo.h | 2 + + xbmc/cores/VideoPlayer/Edl.cpp | 7 +- + xbmc/cores/VideoPlayer/IVideoPlayer.h | 5 - + xbmc/cores/VideoPlayer/VideoPlayer.cpp | 42 +- + xbmc/cores/VideoPlayer/VideoPlayer.h | 4 +- + xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp | 18 +- + xbmc/cores/VideoPlayer/VideoPlayerAudio.h | 1 - + xbmc/cores/VideoPlayer/VideoPlayerTeletext.cpp | 2 +- + xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp | 25 +- + xbmc/cores/VideoPlayer/VideoPlayerVideo.h | 1 - + .../VideoPlayer/VideoRenderers/BaseRenderer.cpp | 10 + + .../VideoRenderers/HwDecRender/CMakeLists.txt | 2 +- + .../VideoRenderers/HwDecRender/MMALRenderer.cpp | 109 +- + .../VideoRenderers/HwDecRender/MMALRenderer.h | 20 +- + .../VideoRenderers/HwDecRender/RendererAML.cpp | 14 +- + .../VideoRenderers/HwDecRender/RendererAML.h | 3 - + .../VideoRenderers/HwDecRender/RendererIMX.cpp | 63 +- + .../VideoRenderers/HwDecRender/RendererIMX.h | 2 + + .../VideoPlayer/VideoRenderers/LinuxRendererGL.cpp | 7 +- + .../VideoPlayer/VideoRenderers/LinuxRendererGL.h | 2 - + .../VideoRenderers/LinuxRendererGLES.cpp | 16 +- + .../VideoPlayer/VideoRenderers/LinuxRendererGLES.h | 1 - + .../VideoRenderers/OverlayRendererGUI.cpp | 5 - + .../VideoPlayer/VideoRenderers/RenderFlags.cpp | 5 + + .../cores/VideoPlayer/VideoRenderers/RenderFlags.h | 5 +- + .../VideoPlayer/VideoRenderers/RenderManager.cpp | 62 +- + .../VideoPlayer/VideoRenderers/RenderManager.h | 1 + + .../VideoRenderers/VideoShaders/GLSLOutput.cpp | 2 +- + .../VideoRenderers/VideoShaders/WinVideoFilter.h | 2 - + .../cores/VideoPlayer/VideoRenderers/WinRenderer.h | 1 - + xbmc/cores/omxplayer/OMXImage.cpp | 4 +- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 4 +- + xbmc/cores/paplayer/AudioDecoder.cpp | 2 +- + xbmc/cores/paplayer/ICodec.h | 5 +- + xbmc/cores/paplayer/PAPlayer.h | 1 - + xbmc/cores/paplayer/VideoPlayerCodec.cpp | 4 +- + xbmc/cores/playercorefactory/PlayerSelectionRule.h | 3 - + xbmc/dbwrappers/Database.cpp | 3 + + xbmc/dbwrappers/dataset.h | 5 +- + xbmc/dbwrappers/mysqldataset.cpp | 2 +- + xbmc/dialogs/GUIDialogContextMenu.cpp | 10 +- + xbmc/dialogs/GUIDialogContextMenu.h | 2 - + xbmc/dialogs/GUIDialogExtendedProgressBar.h | 3 - + xbmc/dialogs/GUIDialogFileBrowser.cpp | 2 +- + xbmc/dialogs/GUIDialogFileBrowser.h | 3 - + xbmc/dialogs/GUIDialogGamepad.cpp | 4 +- + xbmc/dialogs/GUIDialogKeyboardGeneric.h | 3 - + xbmc/dialogs/GUIDialogMediaFilter.h | 1 - + xbmc/dialogs/GUIDialogMediaSource.h | 3 - + xbmc/dialogs/GUIDialogSelect.h | 3 - + xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp | 2 +- + xbmc/epg/Epg.cpp | 120 +- + xbmc/epg/Epg.h | 43 +- + xbmc/epg/EpgContainer.cpp | 78 +- + xbmc/epg/EpgContainer.h | 64 +- + xbmc/epg/EpgDatabase.cpp | 20 +- + xbmc/epg/EpgDatabase.h | 5 +- + xbmc/epg/EpgInfoTag.cpp | 9 +- + xbmc/epg/EpgInfoTag.h | 20 +- + xbmc/epg/EpgSearchFilter.cpp | 72 + + xbmc/epg/EpgSearchFilter.h | 3 + + xbmc/epg/GUIEPGGridContainer.cpp | 16 +- + xbmc/epg/GUIEPGGridContainer.h | 17 +- + xbmc/epg/GUIEPGGridContainerModel.cpp | 2 +- + xbmc/epg/GUIEPGGridContainerModel.h | 8 +- + xbmc/events/MediaLibraryEvent.cpp | 14 +- + xbmc/events/windows/GUIWindowEventLog.h | 2 +- + xbmc/filesystem/AFPDirectory.cpp | 326 + + xbmc/filesystem/AFPDirectory.h | 47 + + xbmc/filesystem/AFPFile.cpp | 728 + + xbmc/filesystem/AFPFile.h | 134 + + xbmc/filesystem/APKDirectory.cpp | 2 +- + xbmc/filesystem/AddonsDirectory.cpp | 3 +- + xbmc/filesystem/CMakeLists.txt | 2 + + xbmc/filesystem/CurlFile.cpp | 21 +- + xbmc/filesystem/Directory.cpp | 2 +- + xbmc/filesystem/DirectoryFactory.cpp | 13 +- + xbmc/filesystem/DllLibAfp.h | 214 + + xbmc/filesystem/FavouritesDirectory.cpp | 2 +- + xbmc/filesystem/FileFactory.cpp | 10 +- + xbmc/filesystem/FileReaderFile.cpp | 105 + + xbmc/filesystem/FileReaderFile.h | 51 + + xbmc/filesystem/Makefile.in | 6 + + xbmc/filesystem/MultiPathDirectory.h | 2 - + xbmc/filesystem/NFSFile.cpp | 6 +- + xbmc/filesystem/PipeFile.h | 2 - + xbmc/filesystem/PluginDirectory.cpp | 2 +- + xbmc/filesystem/RSSDirectory.cpp | 4 +- + xbmc/filesystem/RarManager.cpp | 19 +- + xbmc/filesystem/RarManager.h | 2 +- + xbmc/filesystem/SMBFile.cpp | 14 +- + xbmc/filesystem/SourcesDirectory.h | 2 - + xbmc/filesystem/StackDirectory.h | 1 - + .../VideoDatabaseDirectory/DirectoryNode.cpp | 1 + + xbmc/filesystem/VirtualDirectory.cpp | 2 +- + xbmc/filesystem/XbtFile.cpp | 6 +- + xbmc/filesystem/XbtFile.h | 2 - + xbmc/filesystem/XbtManager.h | 1 - + xbmc/filesystem/ZeroconfDirectory.cpp | 6 +- + xbmc/filesystem/posix/PosixFile.cpp | 4 +- + xbmc/filesystem/test/TestRarFile.cpp | 21 +- + xbmc/filesystem/test/TestZipFile.cpp | 3 +- + xbmc/filesystem/udf25.cpp | 6 +- + xbmc/filesystem/win32/Win32Directory.cpp | 2 +- + xbmc/filesystem/win32/Win32File.cpp | 2 +- + xbmc/filesystem/win32/Win32SMBDirectory.cpp | 4 +- + xbmc/games/controllers/ControllerLayout.cpp | 2 +- + .../controllers/guicontrols/GUIGameController.cpp | 4 +- + .../controllers/windows/GUIControllerList.cpp | 153 +- + xbmc/games/controllers/windows/GUIControllerList.h | 12 +- + .../controllers/windows/GUIControllerWindow.cpp | 27 +- + .../controllers/windows/IConfigurationWindow.h | 4 +- + xbmc/guiinfo/GUIInfoLabels.h | 3 - + xbmc/guilib/D3DResource.cpp | 2 +- + xbmc/guilib/DirtyRegionSolvers.cpp | 2 +- + xbmc/guilib/GUIBaseContainer.h | 1 - + xbmc/guilib/GUIControl.cpp | 4 +- + xbmc/guilib/GUIControl.h | 2 - + xbmc/guilib/GUIControlFactory.cpp | 4 +- + xbmc/guilib/GUIControlFactory.h | 3 - + xbmc/guilib/GUIControlGroup.h | 2 - + xbmc/guilib/GUIControlProfiler.h | 2 - + xbmc/guilib/GUIEditControl.cpp | 4 +- + xbmc/guilib/GUIFadeLabelControl.cpp | 3 +- + xbmc/guilib/GUIFadeLabelControl.h | 2 - + xbmc/guilib/GUIFontManager.cpp | 2 +- + xbmc/guilib/GUIFontManager.h | 1 - + xbmc/guilib/GUIFontTTFDX.h | 1 - + xbmc/guilib/GUIFontTTFGL.h | 3 - + xbmc/guilib/GUIImage.h | 2 - + xbmc/guilib/GUIKeyboardFactory.cpp | 3 +- + xbmc/guilib/GUILabel.cpp | 2 +- + xbmc/guilib/GUIMoverControl.cpp | 6 +- + xbmc/guilib/GUIMultiImage.cpp | 3 +- + xbmc/guilib/GUIMultiImage.h | 2 - + xbmc/guilib/GUIRSSControl.h | 2 - + xbmc/guilib/GUIRenderingControl.cpp | 4 +- + xbmc/guilib/GUIRenderingControl.h | 2 +- + xbmc/guilib/GUIResizeControl.cpp | 6 +- + xbmc/guilib/GUISpinControl.h | 2 - + xbmc/guilib/GUIStaticItem.h | 1 - + xbmc/guilib/GUITextLayout.cpp | 8 +- + xbmc/guilib/GUITexture.cpp | 6 +- + xbmc/guilib/GUIVideoControl.cpp | 6 +- + xbmc/guilib/GUIVisualisationControl.h | 2 +- + xbmc/guilib/GUIWindowManager.cpp | 24 +- + xbmc/guilib/GUIWindowManager.h | 1 - + xbmc/guilib/GraphicContext.cpp | 4 +- + xbmc/guilib/GraphicContext.h | 2 +- + xbmc/guilib/LocalizeStrings.cpp | 16 +- + xbmc/guilib/Resolution.cpp | 113 +- + xbmc/guilib/Resolution.h | 9 +- + xbmc/guilib/TextureBundle.cpp | 34 +- + xbmc/guilib/TextureBundle.h | 6 +- + xbmc/guilib/TextureBundleXBT.cpp | 32 +- + xbmc/guilib/TextureBundleXBT.h | 12 +- + xbmc/guilib/TextureManager.cpp | 2 +- + xbmc/guilib/WindowIDs.h | 7 +- + xbmc/input/ButtonTranslator.cpp | 15 +- + xbmc/input/InputCodingTableBaiduPY.h | 3 - + xbmc/input/InputCodingTableBasePY.h | 1 - + xbmc/input/InputCodingTableKorean.h | 1 - + xbmc/input/InputManager.cpp | 2 +- + xbmc/input/KeyboardLayoutManager.h | 1 - + xbmc/input/joysticks/DefaultJoystick.cpp | 4 +- + xbmc/input/linux/LinuxInputDevices.cpp | 15 + + xbmc/input/linux/LinuxInputDevices.h | 1 + + xbmc/interfaces/AnnouncementManager.cpp | 12 +- + xbmc/interfaces/IActionListener.h | 2 +- + xbmc/interfaces/IAnnouncer.h | 7 +- + xbmc/interfaces/builtins/AddonBuiltins.cpp | 4 +- + xbmc/interfaces/builtins/ApplicationBuiltins.cpp | 3 - + xbmc/interfaces/builtins/GUIBuiltins.cpp | 1 - + xbmc/interfaces/builtins/GUIControlBuiltins.cpp | 4 +- + xbmc/interfaces/builtins/PlayerBuiltins.cpp | 2 +- + xbmc/interfaces/builtins/SystemBuiltins.cpp | 9 +- + xbmc/interfaces/generic/LanguageInvokerThread.h | 3 - + xbmc/interfaces/generic/ScriptInvocationManager.h | 3 +- + xbmc/interfaces/json-rpc/ApplicationOperations.cpp | 1 - + xbmc/interfaces/json-rpc/AudioLibrary.h | 2 - + xbmc/interfaces/json-rpc/FileItemHandler.cpp | 2 +- + xbmc/interfaces/json-rpc/InputOperations.cpp | 7 +- + .../interfaces/json-rpc/JSONServiceDescription.cpp | 1 - + xbmc/interfaces/json-rpc/JSONUtils.h | 1 - + xbmc/interfaces/json-rpc/SettingsOperations.h | 2 - + xbmc/interfaces/json-rpc/VideoLibrary.cpp | 83 +- + xbmc/interfaces/json-rpc/VideoLibrary.h | 5 - + xbmc/interfaces/json-rpc/schema/methods.json | 37 +- + xbmc/interfaces/json-rpc/schema/types.json | 49 +- + xbmc/interfaces/json-rpc/schema/version.txt | 2 +- + xbmc/interfaces/legacy/CallbackHandler.h | 4 +- + xbmc/interfaces/legacy/Control.h | 2 - + xbmc/interfaces/legacy/InfoTagMusic.cpp | 10 - + xbmc/interfaces/legacy/InfoTagMusic.h | 36 - + xbmc/interfaces/legacy/InfoTagVideo.cpp | 9 +- + xbmc/interfaces/legacy/InfoTagVideo.h | 18 - + xbmc/interfaces/legacy/ListItem.cpp | 10 +- + xbmc/interfaces/legacy/ModuleXbmc.cpp | 7 +- + xbmc/interfaces/legacy/ModuleXbmcplugin.h | 2 - + xbmc/interfaces/legacy/PlayList.cpp | 4 +- + xbmc/interfaces/legacy/Player.h | 2 - + xbmc/interfaces/legacy/Window.cpp | 23 +- + xbmc/interfaces/legacy/Window.h | 1 - + xbmc/interfaces/legacy/WindowDialogMixin.cpp | 2 +- + xbmc/interfaces/legacy/WindowXML.cpp | 42 +- + xbmc/interfaces/legacy/WindowXML.h | 26 - + xbmc/interfaces/legacy/wsgi/WsgiResponse.h | 2 - + xbmc/interfaces/python/CallbackHandler.cpp | 2 +- + xbmc/interfaces/python/PythonInvoker.h | 1 - + xbmc/interfaces/python/swig.cpp | 6 +- + xbmc/linux/LinuxTimezone.cpp | 2 +- + xbmc/linux/OMXCore.h | 3 +- + xbmc/linux/PosixMountProvider.h | 3 - + xbmc/linux/RBP.cpp | 16 + + xbmc/linux/RBP.h | 3 + + xbmc/linux/imx/IMX.h | 135 +- + xbmc/listproviders/DirectoryProvider.cpp | 2 +- + xbmc/listproviders/DirectoryProvider.h | 16 +- + xbmc/listproviders/StaticProvider.cpp | 2 +- + xbmc/listproviders/StaticProvider.h | 14 +- + xbmc/messaging/ApplicationMessenger.h | 3 + + xbmc/music/Album.cpp | 6 +- + xbmc/music/GUIViewStateMusic.cpp | 53 +- + xbmc/music/GUIViewStateMusic.h | 10 + + xbmc/music/MusicDatabase.cpp | 74 +- + xbmc/music/MusicDatabase.h | 1 - + xbmc/music/dialogs/GUIDialogMusicInfo.cpp | 21 +- + xbmc/music/dialogs/GUIDialogSongInfo.cpp | 6 +- + xbmc/music/infoscanner/MusicInfoScanner.cpp | 2 +- + xbmc/music/infoscanner/MusicInfoScanner.h | 4 +- + xbmc/music/infoscanner/MusicInfoScraper.cpp | 4 +- + xbmc/music/infoscanner/MusicInfoScraper.h | 2 - + xbmc/music/tags/MusicInfoTagLoaderFactory.cpp | 3 +- + xbmc/music/tags/MusicInfoTagLoaderShn.cpp | 2 +- + xbmc/music/tags/TagLoaderTagLib.cpp | 34 +- + xbmc/music/windows/GUIWindowMusicBase.cpp | 77 +- + xbmc/music/windows/GUIWindowMusicBase.h | 2 - + xbmc/music/windows/GUIWindowMusicNav.h | 24 +- + xbmc/music/windows/GUIWindowMusicPlaylist.cpp | 1 - + xbmc/music/windows/GUIWindowVisualisation.cpp | 4 +- + xbmc/network/AirPlayServer.cpp | 1 - + xbmc/network/AirPlayServer.h | 1 - + xbmc/network/AirTunesServer.cpp | 1 - + xbmc/network/DNSNameCache.cpp | 86 +- + xbmc/network/DNSNameCache.h | 6 + + xbmc/network/EventClient.cpp | 6 +- + xbmc/network/EventPacket.h | 1 - + xbmc/network/GUIDialogNetworkSetup.cpp | 10 +- + xbmc/network/GUIDialogNetworkSetup.h | 25 +- + xbmc/network/Makefile.in | 1 + + xbmc/network/Network.cpp | 365 +- + xbmc/network/Network.h | 271 +- + xbmc/network/NetworkServices.cpp | 9 +- + xbmc/network/Socket.h | 2 +- + xbmc/network/TCPServer.cpp | 22 +- + xbmc/network/UdpClient.h | 1 - + xbmc/network/WakeOnAccess.cpp | 34 +- + xbmc/network/WakeOnAccess.h | 1 - + xbmc/network/WebServer.cpp | 30 +- + xbmc/network/Zeroconf.h | 4 +- + xbmc/network/ZeroconfBrowser.cpp | 3 + + xbmc/network/cddb.cpp | 2 +- + .../HTTPImageTransformationHandler.cpp | 2 +- + .../httprequesthandler/IHTTPRequestHandler.cpp | 3 - + xbmc/network/linux/Makefile | 1 + + xbmc/network/linux/NetworkLinux.cpp | 466 +- + xbmc/network/linux/NetworkLinux.h | 59 +- + xbmc/network/linux/ZeroconfAvahi.cpp | 6 +- + xbmc/network/linux/ZeroconfBrowserAvahi.cpp | 4 +- + xbmc/network/linux/ZeroconfBrowserAvahi.h | 1 - + xbmc/network/linux/android-ifaddrs/Makefile | 6 + + xbmc/network/linux/android-ifaddrs/README.md | 6 + + xbmc/network/linux/android-ifaddrs/ifaddrs.c | 663 + + xbmc/network/linux/android-ifaddrs/ifaddrs.h | 54 + + xbmc/network/mdns/ZeroconfBrowserMDNS.h | 1 - + xbmc/network/mdns/ZeroconfMDNS.cpp | 1 - + xbmc/network/mdns/ZeroconfMDNS.h | 2 - + xbmc/network/osx/ZeroconfBrowserOSX.h | 4 +- + xbmc/network/osx/priv_netlink.h | 120 + + xbmc/network/upnp/UPnP.cpp | 5 +- + xbmc/network/upnp/UPnPInternal.cpp | 29 +- + xbmc/network/upnp/UPnPRenderer.cpp | 8 +- + xbmc/network/upnp/UPnPServer.cpp | 4 +- + xbmc/network/windows/NetworkWin32.cpp | 33 +- + xbmc/network/windows/NetworkWin32.h | 10 +- + xbmc/peripherals/EventScanner.h | 4 +- + xbmc/peripherals/PeripheralTypes.h | 24 + + xbmc/peripherals/Peripherals.cpp | 38 +- + xbmc/peripherals/Peripherals.h | 8 +- + xbmc/peripherals/addons/AddonButtonMap.cpp | 2 +- + xbmc/peripherals/bus/Makefile.in | 1 + + xbmc/peripherals/bus/PeripheralBus.cpp | 17 + + xbmc/peripherals/bus/PeripheralBus.h | 3 + + .../bus/android/PeripheralBusAndroid.cpp | 4 +- + .../bus/linux/PeripheralBusPLATFORMLibUdev.cpp | 142 + + .../bus/linux/PeripheralBusPLATFORMLibUdev.h | 47 + + .../bus/linux/PeripheralBusUSBLibUdev.cpp | 16 +- + .../bus/linux/PeripheralBusUSBLibUdev.h | 2 +- + xbmc/peripherals/bus/virtual/PeripheralBusAddon.h | 1 - + xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp | 4 + + xbmc/peripherals/devices/Makefile.in | 1 + + xbmc/peripherals/devices/Peripheral.cpp | 2 +- + xbmc/peripherals/devices/Peripheral.h | 13 +- + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 123 +- + xbmc/peripherals/devices/PeripheralCecAdapter.h | 8 +- + xbmc/peripherals/devices/PeripheralJoystick.h | 2 +- + xbmc/peripherals/devices/PeripheralVideo.cpp | 121 + + xbmc/peripherals/devices/PeripheralVideo.h | 62 + + .../dialogs/GUIDialogPeripheralSettings.cpp | 2 +- + xbmc/pictures/GUIWindowPictures.cpp | 1 - + xbmc/pictures/GUIWindowSlideShow.cpp | 1 - + xbmc/pictures/SlideShowPicture.cpp | 2 +- + .../platform/darwin/ios-common/AnnounceReceiver.mm | 1 - + xbmc/platform/darwin/ios/Info.plist.in | 23 +- + xbmc/platform/darwin/ios/XBMCController.mm | 18 +- + xbmc/platform/xbmc.cpp | 16 +- + xbmc/playlists/PlayList.cpp | 3 +- + xbmc/playlists/PlayList.h | 1 - + xbmc/playlists/PlayListPLS.h | 4 - + xbmc/playlists/SmartPlayList.cpp | 13 +- + xbmc/powermanagement/linux/LogindUPowerSyscall.cpp | 10 +- + xbmc/powermanagement/linux/UPowerSyscall.cpp | 15 +- + xbmc/powermanagement/osx/CocoaPowerSyscall.cpp | 4 +- + xbmc/profiles/ProfilesManager.cpp | 8 +- + xbmc/programs/GUIWindowPrograms.h | 12 +- + xbmc/pvr/PVRActionListener.cpp | 2 +- + xbmc/pvr/PVRDatabase.cpp | 52 +- + xbmc/pvr/PVRDatabase.h | 10 +- + xbmc/pvr/PVRGUIInfo.h | 2 - + xbmc/pvr/PVRManager.cpp | 287 +- + xbmc/pvr/PVRManager.h | 49 +- + xbmc/pvr/addons/PVRClients.cpp | 43 +- + xbmc/pvr/addons/PVRClients.h | 26 + + xbmc/pvr/channels/PVRChannel.cpp | 7 +- + xbmc/pvr/channels/PVRChannel.h | 6 + + xbmc/pvr/channels/PVRChannelGroup.cpp | 119 +- + xbmc/pvr/channels/PVRChannelGroup.h | 24 +- + xbmc/pvr/channels/PVRChannelGroups.cpp | 52 +- + xbmc/pvr/channels/PVRChannelGroups.h | 1 + + xbmc/pvr/channels/PVRChannelGroupsContainer.cpp | 7 +- + xbmc/pvr/channels/PVRChannelGroupsContainer.h | 6 + + xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp | 105 + + xbmc/pvr/channels/PVRRadioRDSInfoTag.h | 21 + + xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp | 4 +- + xbmc/pvr/dialogs/GUIDialogPVRChannelManager.h | 2 - + xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp | 2 +- + xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.h | 8 +- + xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp | 5 + + xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h | 2 + + xbmc/pvr/dialogs/GUIDialogPVRRecordingInfo.h | 6 +- + xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp | 4 +- + xbmc/pvr/recordings/PVRRecording.cpp | 35 +- + xbmc/pvr/recordings/PVRRecording.h | 19 +- + xbmc/pvr/recordings/PVRRecordings.cpp | 15 +- + xbmc/pvr/recordings/PVRRecordings.h | 2 + + xbmc/pvr/timers/PVRTimerInfoTag.cpp | 170 +- + xbmc/pvr/timers/PVRTimerInfoTag.h | 33 +- + xbmc/pvr/timers/PVRTimers.cpp | 80 +- + xbmc/pvr/timers/PVRTimers.h | 10 +- + xbmc/pvr/windows/GUIWindowPVRBase.cpp | 26 +- + xbmc/pvr/windows/GUIWindowPVRBase.h | 6 +- + xbmc/pvr/windows/GUIWindowPVRChannels.cpp | 11 +- + xbmc/pvr/windows/GUIWindowPVRGuide.cpp | 42 +- + xbmc/pvr/windows/GUIWindowPVRGuide.h | 8 - + xbmc/pvr/windows/GUIWindowPVRRecordings.cpp | 16 +- + xbmc/pvr/windows/GUIWindowPVRSearch.cpp | 2 +- + xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp | 7 +- + xbmc/rendering/RenderSystem.h | 2 +- + xbmc/rendering/dx/RenderSystemDX.cpp | 119 +- + xbmc/rendering/dx/RenderSystemDX.h | 155 +- + xbmc/rendering/gl/RenderSystemGL.cpp | 4 +- + xbmc/rendering/gl/RenderSystemGL.h | 2 +- + xbmc/rendering/gles/RenderSystemGLES.cpp | 9 +- + xbmc/rendering/gles/RenderSystemGLES.h | 2 +- + xbmc/screensavers/gles/Makefile.in | 6 + + xbmc/screensavers/gles/ball/Makefile.in | 36 + + xbmc/screensavers/gles/ball/wrapper.cc | 102 + + xbmc/screensavers/gles/noise/Makefile.in | 36 + + xbmc/screensavers/gles/noise/wrapper.cc | 102 + + xbmc/screensavers/gles/plasma/Makefile.in | 36 + + xbmc/screensavers/gles/plasma/wrapper.cc | 102 + + xbmc/screensavers/gles/plasma2/Makefile.in | 36 + + xbmc/screensavers/gles/plasma2/wrapper.cc | 102 + + xbmc/screensavers/gles/solarwinds/Makefile.in | 36 + + xbmc/screensavers/gles/solarwinds/solarwinds.c | 530 + + xbmc/screensavers/gles/solarwinds/solarwinds.h | 60 + + xbmc/screensavers/gles/solarwinds/wrapper.cc | 96 + + xbmc/screensavers/gles/spiral/Makefile.in | 36 + + xbmc/screensavers/gles/spiral/wrapper.cc | 102 + + xbmc/screensavers/gles/stellar/Makefile.in | 36 + + xbmc/screensavers/gles/stellar/wrapper.cc | 102 + + xbmc/screensavers/gles/triangle2.c | 988 + + xbmc/screensavers/gles/triangle2.h | 64 + + xbmc/screensavers/gles/warp/Makefile.in | 36 + + xbmc/screensavers/gles/warp/wrapper.cc | 102 + + xbmc/settings/AdvancedSettings.cpp | 16 +- + xbmc/settings/AdvancedSettings.h | 1 + + xbmc/settings/AudioDSPSettings.cpp | 2 +- + xbmc/settings/DisplaySettings.cpp | 18 +- + xbmc/settings/MediaSettings.cpp | 2 +- + xbmc/settings/MediaSourceSettings.cpp | 2 +- + xbmc/settings/Settings.cpp | 10 +- + xbmc/settings/Settings.h | 9 +- + xbmc/settings/dialogs/GUIDialogAudioDSPManager.cpp | 11 +- + xbmc/settings/dialogs/GUIDialogAudioDSPManager.h | 2 +- + .../settings/dialogs/GUIDialogAudioDSPSettings.cpp | 4 +- + xbmc/settings/dialogs/GUIDialogAudioDSPSettings.h | 3 +- + .../settings/dialogs/GUIDialogSettingsManualBase.h | 2 - + .../windows/GUIWindowSettingsScreenCalibration.h | 2 - + xbmc/storage/AutorunMediaJob.cpp | 4 +- + xbmc/storage/DetectDVDType.cpp | 2 +- + xbmc/storage/IStorageProvider.h | 4 - + xbmc/storage/MediaManager.cpp | 11 +- + xbmc/storage/MediaManager.h | 4 +- + xbmc/storage/android/AndroidStorageProvider.cpp | 2 +- + xbmc/storage/android/AndroidStorageProvider.h | 3 - + xbmc/storage/cdioSupport.cpp | 2 +- + xbmc/storage/linux/DeviceKitDisksProvider.cpp | 4 +- + xbmc/storage/linux/DeviceKitDisksProvider.h | 4 - + xbmc/storage/linux/LinuxStorageProvider.h | 3 - + xbmc/storage/linux/UDevProvider.h | 3 - + xbmc/storage/linux/UDisksProvider.cpp | 4 +- + xbmc/storage/linux/UDisksProvider.h | 4 - + xbmc/storage/osx/DarwinStorageProvider.h | 4 - + xbmc/storage/windows/Win32StorageProvider.h | 4 - + xbmc/system.h | 5 + + xbmc/test/TestBasicEnvironment.cpp | 10 +- + xbmc/test/TestURL.cpp | 10 +- + xbmc/threads/Atomics.h | 2 +- + xbmc/threads/platform/pthreads/ThreadImpl.cpp | 4 + + xbmc/utils/AMLUtils.cpp | 15 - + xbmc/utils/AliasShortcutUtils.cpp | 2 +- + xbmc/utils/BitstreamConverter.cpp | 17 +- + xbmc/utils/BitstreamConverter.h | 4 +- + xbmc/utils/CPUInfo.cpp | 32 +- + xbmc/utils/CPUInfo.h | 1 + + xbmc/utils/CryptThreading.cpp | 2 - + xbmc/utils/DatabaseUtils.cpp | 8 +- + xbmc/utils/GroupUtils.cpp | 4 +- + xbmc/utils/HTMLUtil.cpp | 2 +- + xbmc/utils/IRssObserver.h | 2 - + xbmc/utils/JSONVariantParser.cpp | 5 - + xbmc/utils/JSONVariantParser.h | 5 - + xbmc/utils/LabelFormatter.cpp | 6 +- + xbmc/utils/Makefile.in | 3 +- + xbmc/utils/Mime.cpp | 4 +- + xbmc/utils/RecentlyAddedJob.cpp | 4 +- + xbmc/utils/RssManager.cpp | 4 +- + xbmc/utils/RssReader.cpp | 2 +- + xbmc/utils/SaveFileStateJob.cpp | 2 +- + xbmc/utils/ScraperParser.cpp | 18 +- + xbmc/utils/Screen.cpp | 147 + + xbmc/utils/Screen.h | 52 + + xbmc/utils/SortUtils.cpp | 2 +- + xbmc/utils/SortUtils.h | 3 +- + xbmc/utils/Splash.cpp | 2 +- + xbmc/utils/StringUtils.cpp | 28 +- + xbmc/utils/StringUtils.h | 11 - + xbmc/utils/URIUtils.cpp | 72 +- + xbmc/utils/URIUtils.h | 5 + + xbmc/utils/Weather.cpp | 4 +- + xbmc/utils/log.cpp | 30 +- + xbmc/utils/test/TestCPUInfo.cpp | 2 +- + xbmc/utils/test/TestCharsetConverter.cpp | 9 +- + xbmc/utils/test/TestDatabaseUtils.cpp | 30 +- + xbmc/utils/test/TestJobManager.cpp | 3 +- + xbmc/utils/test/TestLabelFormatter.cpp | 1 - + xbmc/utils/test/TestRegExp.cpp | 2 +- + xbmc/utils/test/TestStringUtils.cpp | 23 - + xbmc/utils/test/TestURIUtils.cpp | 6 + + xbmc/video/ContextMenus.cpp | 3 +- + xbmc/video/ContextMenus.h | 1 + + xbmc/video/Episode.h | 4 - + xbmc/video/GUIViewStateVideo.cpp | 40 + + xbmc/video/GUIViewStateVideo.h | 10 + + xbmc/video/VideoDatabase.cpp | 178 +- + xbmc/video/VideoDatabase.h | 64 +- + xbmc/video/VideoInfoDownloader.h | 1 - + xbmc/video/VideoInfoScanner.cpp | 16 +- + xbmc/video/VideoInfoScanner.h | 9 +- + xbmc/video/VideoInfoTag.cpp | 118 +- + xbmc/video/VideoInfoTag.h | 28 +- + xbmc/video/VideoLibraryQueue.cpp | 1 + + xbmc/video/VideoReferenceClock.cpp | 3 +- + xbmc/video/VideoThumbLoader.cpp | 2 +- + xbmc/video/VideoThumbLoader.h | 1 - + .../dialogs/GUIDialogAudioSubtitleSettings.cpp | 8 +- + .../video/dialogs/GUIDialogAudioSubtitleSettings.h | 2 - + xbmc/video/dialogs/GUIDialogSubtitles.cpp | 6 +- + xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp | 3 + + xbmc/video/dialogs/GUIDialogVideoInfo.cpp | 22 +- + xbmc/video/dialogs/GUIDialogVideoOSD.cpp | 2 +- + xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 6 +- + xbmc/video/dialogs/GUIDialogVideoSettings.h | 4 - + xbmc/video/videosync/CMakeLists.txt | 2 +- + xbmc/video/windows/GUIWindowFullScreen.cpp | 4 +- + xbmc/video/windows/GUIWindowVideoBase.cpp | 12 +- + xbmc/video/windows/GUIWindowVideoNav.cpp | 6 +- + xbmc/video/windows/GUIWindowVideoPlaylist.cpp | 1 - + xbmc/view/GUIViewState.cpp | 12 +- + xbmc/view/GUIViewState.h | 2 - + xbmc/win32/WIN32Util.cpp | 5 +- + xbmc/win32/WIN32Util.h | 2 - + xbmc/win32/Win32DelayedDllLoad.cpp | 13 - + xbmc/windowing/WinEvents.cpp | 19 + + xbmc/windowing/WinEvents.h | 1 + + xbmc/windowing/WinEventsLinux.cpp | 5 + + xbmc/windowing/WinEventsLinux.h | 1 + + xbmc/windowing/WinSystem.cpp | 4 +- + xbmc/windowing/X11/WinSystemX11.h | 3 - + xbmc/windowing/X11/WinSystemX11GLContext.cpp | 2 +- + xbmc/windowing/X11/WinSystemX11GLESContext.cpp | 2 +- + xbmc/windowing/X11/XRandR.cpp | 4 +- + xbmc/windowing/android/CMakeLists.txt | 1 - + xbmc/windowing/egl/EGLEdid.cpp | 94 + + xbmc/windowing/egl/EGLEdid.h | 71 + + xbmc/windowing/egl/EGLNativeTypeAmlAndroid.h | 3 - + xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 3 +- + xbmc/windowing/egl/EGLNativeTypeAmlogic.h | 3 - + xbmc/windowing/egl/EGLNativeTypeAndroid.h | 3 - + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 247 +- + xbmc/windowing/egl/EGLNativeTypeIMX.h | 24 +- + xbmc/windowing/egl/EGLNativeTypeRKAndroid.h | 3 - + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 228 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h | 11 +- + xbmc/windowing/egl/EGLWrapper.cpp | 1 + + xbmc/windowing/egl/EGLWrapper.h | 3 - + xbmc/windowing/egl/Makefile.in | 1 + + xbmc/windowing/egl/WinSystemEGL.cpp | 87 +- + xbmc/windowing/egl/WinSystemEGL.h | 6 - + xbmc/windowing/egl/vc_hdmi.h | 565 + + xbmc/windowing/osx/CMakeLists.txt | 2 +- + xbmc/windowing/osx/WinSystemIOS.h | 3 - + xbmc/windowing/osx/WinSystemOSX.h | 3 - + xbmc/windowing/windows/WinSystemWin32.cpp | 4 +- + xbmc/windowing/windows/WinSystemWin32.h | 1 - + xbmc/windowing/windows/WinSystemWin32DX.cpp | 2 +- + xbmc/windowing/windows/WinSystemWin32DX.h | 2 +- + xbmc/windows/GUIMediaWindow.cpp | 26 +- + xbmc/windows/GUIMediaWindow.h | 26 +- + xbmc/windows/GUIWindowFileManager.cpp | 16 +- + xbmc/windows/GUIWindowFileManager.h | 3 - + xbmc/windows/GUIWindowLoginScreen.cpp | 3 +- + xbmc/windows/GUIWindowSystemInfo.cpp | 2 + + xbmc/windows/GUIWindowSystemInfo.h | 3 - + 831 files changed, 67874 insertions(+), 7106 deletions(-) + create mode 100644 Makefile.python-interfaces + create mode 100644 addons/screensaver.gles.ball/addon.xml + create mode 100644 addons/screensaver.gles.ball/icon.png + create mode 100644 addons/screensaver.gles.noise/addon.xml + create mode 100644 addons/screensaver.gles.noise/icon.png + create mode 100644 addons/screensaver.gles.plasma/addon.xml + create mode 100644 addons/screensaver.gles.plasma/icon.png + create mode 100644 addons/screensaver.gles.plasma2/addon.xml + create mode 100644 addons/screensaver.gles.plasma2/icon.png + create mode 100644 addons/screensaver.gles.solarwinds/addon.xml + create mode 100644 addons/screensaver.gles.solarwinds/icon.png + create mode 100644 addons/screensaver.gles.spiral/addon.xml + create mode 100644 addons/screensaver.gles.spiral/icon.png + create mode 100644 addons/screensaver.gles.stellar/addon.xml + create mode 100644 addons/screensaver.gles.stellar/icon.png + create mode 100644 addons/screensaver.gles.warp/addon.xml + create mode 100644 addons/screensaver.gles.warp/icon.png + create mode 100644 project/cmake/installdata/darwin/packaging.txt + create mode 100644 project/cmake/installdata/darwin/runtime.txt + create mode 100644 project/cmake/modules/FindRTMP.cmake + mode change 100644 => 120000 project/cmake/scripts/android/PathSetup.cmake + create mode 100644 project/cmake/scripts/common/ManageString.cmake + create mode 100644 project/cmake/scripts/common/PathSetup.cmake + create mode 100644 project/cmake/scripts/darwin/ArchSetup.cmake + create mode 100644 project/cmake/scripts/darwin/Install.cmake + create mode 100644 project/cmake/scripts/darwin/Macros.cmake + create mode 100644 project/cmake/scripts/darwin/PathSetup.cmake + create mode 100644 project/cmake/treedata/darwin/subdirs.txt + create mode 100644 tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + create mode 100644 tools/depends/target/ffmpeg/0001-Squashed-commit-of-the-following.patch + create mode 100644 tools/depends/target/ffmpeg/0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch + create mode 100644 tools/depends/target/ffmpeg/0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch + create mode 100644 tools/depends/target/ffmpeg/0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch + create mode 100644 tools/depends/target/ffmpeg/73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch + create mode 100644 tools/depends/target/ffmpeg/added_ARM_NEON_optimized_SAO_patches.patch + create mode 100644 tools/depends/target/ffmpeg/h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch + create mode 100644 tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch + create mode 100644 tools/depends/target/ffmpeg/pfcd_hevc_optimisations.patch + create mode 100644 tools/depends/target/jpeg/Makefile + create mode 100644 tools/depends/target/libmodplug/Makefile + create mode 100644 tools/depends/target/python27/urllib-ssl-no-cert_check.patch + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.cpp + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.h + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.cpp + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.cpp + create mode 100644 xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h + create mode 100644 xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.cpp + create mode 100644 xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.h + create mode 100644 xbmc/cores/VideoPlayer/DVDInputStreams/DllLibRTMP.h + create mode 100644 xbmc/filesystem/AFPDirectory.cpp + create mode 100644 xbmc/filesystem/AFPDirectory.h + create mode 100644 xbmc/filesystem/AFPFile.cpp + create mode 100644 xbmc/filesystem/AFPFile.h + create mode 100644 xbmc/filesystem/DllLibAfp.h + create mode 100644 xbmc/filesystem/FileReaderFile.cpp + create mode 100644 xbmc/filesystem/FileReaderFile.h + create mode 100644 xbmc/network/linux/android-ifaddrs/Makefile + create mode 100644 xbmc/network/linux/android-ifaddrs/README.md + create mode 100644 xbmc/network/linux/android-ifaddrs/ifaddrs.c + create mode 100644 xbmc/network/linux/android-ifaddrs/ifaddrs.h + create mode 100644 xbmc/network/osx/priv_netlink.h + create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.cpp + create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h + create mode 100644 xbmc/peripherals/devices/PeripheralVideo.cpp + create mode 100644 xbmc/peripherals/devices/PeripheralVideo.h + create mode 100644 xbmc/screensavers/gles/Makefile.in + create mode 100644 xbmc/screensavers/gles/ball/Makefile.in + create mode 100644 xbmc/screensavers/gles/ball/wrapper.cc + create mode 100644 xbmc/screensavers/gles/noise/Makefile.in + create mode 100644 xbmc/screensavers/gles/noise/wrapper.cc + create mode 100644 xbmc/screensavers/gles/plasma/Makefile.in + create mode 100644 xbmc/screensavers/gles/plasma/wrapper.cc + create mode 100644 xbmc/screensavers/gles/plasma2/Makefile.in + create mode 100644 xbmc/screensavers/gles/plasma2/wrapper.cc + create mode 100644 xbmc/screensavers/gles/solarwinds/Makefile.in + create mode 100644 xbmc/screensavers/gles/solarwinds/solarwinds.c + create mode 100644 xbmc/screensavers/gles/solarwinds/solarwinds.h + create mode 100644 xbmc/screensavers/gles/solarwinds/wrapper.cc + create mode 100644 xbmc/screensavers/gles/spiral/Makefile.in + create mode 100644 xbmc/screensavers/gles/spiral/wrapper.cc + create mode 100644 xbmc/screensavers/gles/stellar/Makefile.in + create mode 100644 xbmc/screensavers/gles/stellar/wrapper.cc + create mode 100644 xbmc/screensavers/gles/triangle2.c + create mode 100644 xbmc/screensavers/gles/triangle2.h + create mode 100644 xbmc/screensavers/gles/warp/Makefile.in + create mode 100644 xbmc/screensavers/gles/warp/wrapper.cc + create mode 100644 xbmc/utils/Screen.cpp + create mode 100644 xbmc/utils/Screen.h + create mode 100644 xbmc/windowing/egl/EGLEdid.cpp + create mode 100644 xbmc/windowing/egl/EGLEdid.h + create mode 100644 xbmc/windowing/egl/vc_hdmi.h + +diff --git a/Makefile.in b/Makefile.in +index 957fb92..f7d19db 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -171,6 +171,7 @@ DIRECTORY_ARCHIVES += xbmc/network/linux/network_linux.a + DIRECTORY_ARCHIVES += xbmc/powermanagement/android/powermanagement_android.a + DIRECTORY_ARCHIVES += xbmc/storage/android/storage_android.a + DIRECTORY_ARCHIVES += xbmc/windowing/X11/windowing_X11.a ++DIRECTORY_ARCHIVES += xbmc/network/linux/android-ifaddrs/android-ifaddrs.a + else + DIRECTORY_ARCHIVES += xbmc/input/joysticks/input_joysticks.a + DIRECTORY_ARCHIVES += xbmc/input/joysticks/generic/input_joysticks_generic.a +@@ -209,6 +210,20 @@ LIB_DIRS=\ + lib/cpluff \ + lib/xbmc-dll-symbols + ++SS_DIRS= ++ifneq (@DISABLE_GLESSCREENSAVERS@,1) ++ SS_DIRS+= xbmc/screensavers/gles/solarwinds ++ SS_DIRS+= xbmc/screensavers/gles/plasma ++ SS_DIRS+= xbmc/screensavers/gles/plasma2 ++ SS_DIRS+= xbmc/screensavers/gles/noise ++ SS_DIRS+= xbmc/screensavers/gles/warp ++ SS_DIRS+= xbmc/screensavers/gles/stellar ++ SS_DIRS+= xbmc/screensavers/gles/spiral ++ SS_DIRS+= xbmc/screensavers/gles/ball ++else ++ INSTALL_FILTER+= .*screensaver\.gles.* ++endif ++ + LIBADDON_DIRS=\ + lib/addons/library.xbmc.addon \ + lib/addons/library.kodi.adsp \ +@@ -333,6 +348,17 @@ exports: xbmc/cores/DllLoader/exports/exports.a xbmc/cores/DllLoader/exports/uti + $(MAKE) -C xbmc/cores/DllLoader/exports wrapper.def + dllloader: exports xbmc/cores/DllLoader/dllloader.a + ++ifeq (@USE_OPENGLES@,1) ++GLESHELPERS=xbmc/screensavers/gles/gleshelpers.a ++$(GLESHELPERS): force exports ++ $(MAKE) -C xbmc/screensavers/gles ++endif ++ ++$(SS_DIRS): force exports $(GLESHELPERS) ++ $(MAKE) -C $@ ++ ++screensavers: $(SS_DIRS) ++ + libaddon: exports + $(MAKE) -C lib/addons/library.xbmc.addon + $(MAKE) -C lib/addons/library.kodi.adsp +diff --git a/Makefile.python-interfaces b/Makefile.python-interfaces +new file mode 100644 +index 0000000..22b0059 +--- /dev/null ++++ b/Makefile.python-interfaces +@@ -0,0 +1,15 @@ ++include bootstrap.mk ++ ++null := ++space := ${null} ${null} ++${space} := ${space} ++ ++AUTOGENERATED_MAKEFILE = xbmc/interfaces/python/Makefile ++ ++# hack targets to keep build system up to date ++Makefile : config.status $(addsuffix .in, $(AUTOGENERATED_MAKEFILES)) ++ @echo "Regenerating Makefiles..." ++ @./config.status &> /dev/null ++ @echo "done" ++ ++config.status: configure +diff --git a/README.md b/README.md +index 2b147d5..78ee0db 100644 +--- a/README.md ++++ b/README.md +@@ -25,7 +25,7 @@ around. It was designed for network playback, so you can stream your multimedia + from anywhere in the house or directly from the internet using practically any + protocol available. + +-Use your media as-is: Kodi can play CDs and DVDs directly ++Use your media as-is: Kodi can play CD's and DVD's directly + from the disk or image file, almost all popular archive formats from your hard + drive, and even files inside ZIP and RAR archives. It will even scan all of + your media and automatically create a personalized library complete with box +diff --git a/addons/repository.xbmc.org/addon.xml b/addons/repository.xbmc.org/addon.xml +index 96010aa..e106ce1 100644 +--- a/addons/repository.xbmc.org/addon.xml ++++ b/addons/repository.xbmc.org/addon.xml +@@ -1,7 +1,7 @@ + + + + +@@ -59,7 +59,7 @@ + Add-ons van Kodi.tv installeren + Instaluj dodatki z Kodi.tv + Instale Add-ons do Kodi.tv +- Instalar Add-ons a partir de Kodi.tv ++ Instalar add-ons a partir de Kodi.tv + Instalați suplimente de la Kodi.tv + Установить дополнения с сайта Kodi.tv + Inštalovať rozšírenia z Kodi.tv +@@ -115,7 +115,7 @@ + Download en installeer add-ons uit de officiële Kodi.tv add-on depot.[CR] Wanneer u de officiële depot gebruikt beschikt u over onze uitgebreide mirrorservice, waardoor u snel kan downloaden van locaties in uw buurt.[CR] Alle add-ons in dit depot ondergingen standaardtests; indien u een defecte of niet-werkende add-on vindt, meld dit dan aan Team Kodi zodat zij actie kunnen ondernemen. + Pobieraj i instaluj dodatki z oficjalnego repozytorium Kodi.tv.[CR] Używając oficjalnego repozytorium korzystasz z serwerów lustrzanych, rozsianych po całym świecie. Wybierany jest ten, który znajduje się najbliżej ciebie, zapewniając dużą prędkość połączenia.[CR]Wszystkie dodatki znajdujące się w tym repozytorium są testowane, ale mogą okazać się niesprawne. Zgłoś wówczas błąd, aby zespół Kodi mógł podjąć odpowiednie działanie. + Transfira e instale add-ons a partir do repositório oficial do Kodi.tv.[CR]|Ao utilizar o repositório oficial, você será capaz de tirar proveito do nosso serviço de espelhamento de arquivos, auxiliando em downloads mais rápidos a partir de uma região perto de você.[CR]|Todos os add-ons neste repositório passam por testes básicos, se você encontrar algum quebrado ou que não esteja funcionando, por favor reporte para a equipe do Kodi, para que possamos tomar as ações necessárias. +- Transferir e instalar add-ons a partir do repositório de add-ons oficiais de Kodi.tv.[CR]Ao utilizar o Repositório oficial, irá beneficiar do nosso serviço de servidores de ficheiros para o ajudar a ter transferências mais rápidas da região mais perto de si.[CR]Todos os Add-ons neste repositório foram alvo de testes básicos. Se encontrar um danificado ou que não funciona, por favor, informe Tema Kodi, para que a situação seja resolvida. ++ Transferir e instalar os add-ons do repositório de add-ons Oficiais de Kodi.tv.[CR]Ao utilizar o Repositório oficial, irá beneficiar do nosso serviço de servidores de ficheiro para o ajudar a ter transferências mais rápidas a partir da região mais perto de si.[CR]Todos os Add-ons neste repositório foram alvo de testes básicos. Se encontrar um danificado ou que não funciona, por favor, informe a Equipa do Kodi, para que a situação seja resolva. + Descărcați și instalați suplimente din depozitul de suplimente Kodi.tv oficial.[CR] Folosind depozitul (repository) oficial puteți beneficia de serviciul nostru de găzduire distribuită pentru a vă ajuta să descărcați mai repede dintr-o regiune mai apropiată de dumneavoastră.[CR] Toate suplimentele din acest depozit au trecut testele de bază, în caz că găsiți un supliment defect vă rugăm să îl raportați echipei Kodi pentru a lua măsurile necesare. + Загружайте и устанавливайте обновления из официального репозитория Kodi.tv[CR]Используя официальный репозиторий, вы сможете воспользоваться преимуществами распределенного хранилища для быстрой загрузки файлов с ближайшего к вам сервера.[CR]Все дополнения в данном репозитории прошли тестирование. Если вы обнаружили нерабочее дополнение, сообщите об этом разработчикам Kodi. + Stiahnuť a nainštalovať rozšírenia z oficiálneho zdroja rozšírení Kodi.tv.[CR] Použitím oficiálneho zdroja získavate možnosť využiť rozsiahly systém zrkadiel, ktorý Vám umožní rýchlejšie sťahovanie z Vám blízkeho regiónu.[CR] Všetky rozšírenia v tomto zdroji boli podrobené základnému testovaniu. Ak nájdete poškodené alebo nefunkčné rozšírenie, oznámte to prosím týmu Kodi aby mohol podľa potreby zakročiť. +@@ -172,7 +172,7 @@ + Team Kodi heeft niet alle add-ons in deze depot geschreven en is niet verantwoordelijk voor hun inhoud. + Zespół Kodi nie tworzy wszystkich dodatków i nie bierze odpowiedzialności za ich zawartość + O Time do Kodi não produziu todos os add-ons deste repositório, e portanto não é responsável ​​por seu conteúdo +- A Team Kodi não desenvolveu todos os add-ons neste repositório, e não é responsável pelo seu conteúdo. ++ A equipa Kodi não desenvolveu todos os add-ons neste repositório e não é responsável pelo seu conteúdo. + Echipa Kodi nu a creat toate aceste suplimente din acest depozit și nu este responsabilă pentru conținutul lor. + Разработчики Kodi не являются авторами всех дополнений в данном репозитории и не несут ответственность за их содержимое. + Team Kodi nevytvoril všetky rozšírenia v tomto zdroji nie je zodpovedný za ich obsah +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 3cb5426..d4ee85e 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -3029,7 +3029,10 @@ msgctxt "#672" + msgid "Verbose logging for the [B]FFmpeg[/B] libraries" + msgstr "" + +-#empty string with id 673 ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#673" ++msgid "Verbose logging for the [B]RTMP[/B] library" ++msgstr "" + + #: xbmc/settings/AdvancedSettings.cpp + msgctxt "#674" +@@ -5085,7 +5088,12 @@ msgctxt "#10524" + msgid "Movie information" + msgstr "" + +-#empty strings from id 10525 to 11999 ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#10525" ++msgid "Verbose logging for the [B]PVR[/B] component" ++msgstr "" ++ ++#empty strings from id 10526 to 11999 + + #: xbmc/guilib/WindowIDs.h + msgctxt "#12000" +@@ -5576,7 +5584,12 @@ msgctxt "#13005" + msgid "Shutdown" + msgstr "" + +-#empty strings from id 13006 to 13007 ++#empty strings from id 13006 ++ ++#: system/peripherals.xml ++msgctxt "#13007" ++msgid "Same as \"switching source\"" ++msgstr "" + + #: system/settings/settings.xml + msgctxt "#13008" +@@ -6080,7 +6093,12 @@ msgctxt "#13287" + msgid "Screen resolution:" + msgstr "" + +-#empty strings from id 13288 to 13291 ++#: peripheral/devices/PeripheralVideo.cpp ++msgctxt "#13288" ++msgid "Probing available resolutions" ++msgstr "Probing available resolutions" ++ ++#empty strings from id 13289 to 13291 + + msgctxt "#13292" + msgid "A/V cable:" +@@ -6544,7 +6562,7 @@ msgstr "" + + #: system/settings/settings.xml + msgctxt "#13414" +-msgid "Show song and album artists" ++msgid "Include artists who appear only on compilations" + msgstr "" + + #: system/settings/settings.xml +@@ -6857,7 +6875,17 @@ msgctxt "#13557" + msgid "Skip delay" + msgstr "" + +-#empty strings from id 13558 to 13599 ++#: system/settings/settings.xml ++msgctxt "#13558" ++msgid "Adjust display resolution" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#13559" ++msgid "Include interlaced modes" ++msgstr "" ++ ++#empty strings from id 13560 to 13599 + + #: system/settings/darwin.xml + msgctxt "#13600" +@@ -6998,6 +7026,7 @@ msgid "Change area code 3" + msgstr "" + + #: system/settings/settings.xml ++#: xbmc/music/windows/GUIWindowMusicBase.cpp + #: xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp + #: xbmc/vide/windows/GUIWindowVideoBase.cpp + msgctxt "#14022" +@@ -8741,16 +8770,40 @@ msgstr "" + #. Description of OSD video settings for deinterlace method with label #16334 + #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp + msgctxt "#16334" +-msgid "IMX - Fast motion" ++msgid "IMX - Bob (half)" + msgstr "" + + #. Description of OSD video settings for deinterlace method with label #16335 + #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp + msgctxt "#16335" +-msgid "IMX - Fast motion (double)" ++msgid "IMX - Bob" + msgstr "" + +-#empty strings from id 16336 to 16399 ++#. Description of OSD video settings for deinterlace method with label #16336 ++#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++msgctxt "#16336" ++msgid "IMX - Bob (inverted)" ++msgstr "" ++ ++#. Description of OSD video settings for deinterlace method with label #16337 ++#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++msgctxt "#16337" ++msgid "IMX - Advanced (half)" ++msgstr "" ++ ++#. Description of OSD video settings for deinterlace method with label #16337 ++#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++msgctxt "#16338" ++msgid "IMX - Advanced" ++msgstr "" ++ ++#. Description of OSD video settings for deinterlace method with label #16337 ++#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++msgctxt "#16339" ++msgid "IMX - Weave" ++msgstr "" ++ ++#empty strings from id 16340 to 16399 + + #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp + msgctxt "#16400" +@@ -9251,56 +9304,7 @@ msgctxt "#19085" + msgid "Unknown channel %u" + msgstr "" + +-#. Label for "Instant recording action" setting +-#: system/settings/settings.xml +-#: xbmc/pvr/PVRMananger.cpp +-msgctxt "#19086" +-msgid "Instant recording action" +-msgstr "" +- +-#. Label for "Instant recording action" settings value +-#: system/settings/settings.xml +-msgctxt "#19087" +-msgid "Record current show (if guide data available)" +-msgstr "" +- +-#. Label for "Instant recording action" settings value +-#: system/settings/settings.xml +-msgctxt "#19088" +-msgid "Record for a fixed period of time (Instant recording duration)" +-msgstr "" +- +-#. Label for "Instant recording action" settings value +-#: system/settings/settings.xml +-msgctxt "#19089" +-msgid "Ask what to do" +-msgstr "" +- +-#. Label for "Instant recording action" dialog settings value +-#: xbmc/pvr/PVRMananger.cpp +-msgctxt "#19090" +-msgid "Record the next %d minutes" +-msgstr "" +- +-#. Label for "Instant recording action" dialog settings value +-#: xbmc/pvr/PVRMananger.cpp +-msgctxt "#19091" +-msgid "Record current show (%s)" +-msgstr "" +- +-#. Label for "Instant recording action" dialog settings value +-#: xbmc/pvr/PVRMananger.cpp +-msgctxt "#19092" +-msgid "Record next show (%s)" +-msgstr "" +- +-#. Instant recording summary. Expands to "Instant recording: ", for example "Instant recording: 31/05/2016 from 9:00 to 11:00" +-#: xbmc/pvr/PVRTimerInfoTag.cpp +-msgctxt "#19093" +-msgid "Instant recording: %s" +-msgstr "" +- +-#empty strings from id 19094 to 19096 ++#empty strings from id 19086 to 19096 + + msgctxt "#19097" + msgid "Enter the name for the recording" +@@ -11724,7 +11728,10 @@ msgctxt "#20260" + msgid "Secure Shell (SSH / SFTP)" + msgstr "" + +-#empty string with id 20261 ++#: xbmc/network/GUIDialogNetworkSetup.cpp ++msgctxt "#20261" ++msgid "Apple Filing Protocol (AFP)" ++msgstr "" + + #: xbmc/storage/MediaManager.cpp + msgctxt "#20262" +@@ -14046,9 +14053,9 @@ msgctxt "#24053" + msgid "License:" + msgstr "" + +-#: addons/skin.estuary/1080i/DialogAddonInfo.xml ++#: xbmc/addons/GUIDialogAddonInfo.cpp + msgctxt "#24054" +-msgid "What's new" ++msgid "Changelog" + msgstr "" + + #. Used in the Add-on Manager +@@ -15909,7 +15916,7 @@ msgstr "" + #. Help text for controller window + #: xbmc/games/controllers/windows/GUIControllerWindow.cpp + msgctxt "#35055" +-msgid "Use the keyboard or remote to select a controller profile. When prompted, press the button on your game controller that best matches what you see on the screen. If you make a mistake you can repeat the process." ++msgid "Use the keyboard or remote to select a controller profile. Move to the buttons and select the first one. When prompted, press the button on your game controller that best matches what you see on the screen. If you make a mistake you can repeat the process." + msgstr "" + + #. Title of error dialog shown when no joystick add-ons provide button mapping +@@ -16643,7 +16650,7 @@ msgstr "" + #. Description of setting with label #13435 "Enable HQ Scalers for scaling above" + #: system/settings/settings.xml + msgctxt "#36154" +-msgid "Use high quality scalers when upscaling a video by at least this percentage. A value below 5% makes little sense as video is processed with high GPU load without any visible picture quality improvements." ++msgid "Use high quality scalers when upscaling a video by at least this percentage." + msgstr "" + + #. Description of setting with label #13425 "Allow hardware acceleration (VDPAU)" +@@ -16748,7 +16755,11 @@ msgctxt "#36171" + msgid "Select the zoom level that 4:3 videos are shown on widescreen displays." + msgstr "" + +-#empty string with id 36172 ++#. Description of setting "Videos -> Playback -> Adjust display resolution" with label #13558 ++#: system/settings/settings.xml ++msgctxt "#36172" ++msgid "Allow the resolution of the display to be changed so that it best matches the video resolution." ++msgstr "" + + #. Description of setting with label #14109 "Short date format" + #: system/settings/settings.xml +@@ -17004,7 +17015,11 @@ msgctxt "#36218" + msgid "This category contains the electronic programming guide (EPG) settings." + msgstr "" + +-#empty string with id 36219 ++#. Description of setting "Videos -> Playback -> Include interlaced modes" with label #13559 ++#: system/settings/settings.xml ++msgctxt "#36219" ++msgid "Interlaced modes will be used for interlaced content (deinterlacing will be deactivated)." ++msgstr "" + + #: system/settings/settings.xml + msgctxt "#36220" +@@ -17078,7 +17093,7 @@ msgstr "" + + #: system/settings/settings.xml + msgctxt "#36234" +-msgid "Duration of instant recordings when pressing the record button. This value will be taken into account if \"Instant recording action\" is set to \"Record for a fixed period of time\"" ++msgid "Duration of instant recordings when pressing the record button." + msgstr "" + + #: system/settings/settings.xml +@@ -17177,15 +17192,12 @@ msgctxt "#36253" + msgid "Section that contains settings related to music files and how they are handled." + msgstr "" + +-#: system/settings/settings.xml +-msgctxt "#36254" +-msgid "Action to perform when pressing the record button. [Record current show] will record the current show from \"now\" to the end of the show. If no TV guide data is currently available a fixed length recording starting \"now\", with the value set for \"Instant recording duration\" will be scheduled. [Record for a fixed period of time] will schedule a fixed length recording starting \"now\", with the value set for \"Instant recording duration\". [Ask what to do] will open a dialogue containing different recording actions to choose from, like \"Record current show\", \"Record next show\" and some fixed duration recordings." +-msgstr "" ++#empty string with id 36254 + +-#. Description of setting with label #13414 "Show song and album artists" ++#. Description of setting with label #13414 "Include artists who appear only on compilations" + #: system/settings/settings.xml + msgctxt "#36255" +-msgid "When enabled, both song and album artists are shown. When disabled, only album artists are shown and artists that appear only on individual songs from an album are excluded." ++msgid "Determine if artists that appear only on compilations are shown in the library artist view." + msgstr "" + + #. Description of setting with label #20192 "Fetch additional information during updates" +@@ -17403,7 +17415,12 @@ msgctxt "#36291" + msgid "Auto eject disc after rip is complete." + msgstr "" + +-#empty strings from id 36292 to 36301 ++#empty strings from id 36292 to 36300 ++ ++#: system/settings/settings.xml ++msgctxt "#36301" ++msgid "No info available yet." ++msgstr "" + + #: system/settings/settings.xml + msgctxt "#36302" +@@ -19187,8 +19204,6 @@ msgctxt "#38111" + msgid "This category contains other settings for the GUI interface" + msgstr "" + +-#empty strings from id 38112 to 38999 +- + #: system/settings/settings.xml + msgctxt "#39000" + msgid "HD and up" +@@ -19208,3 +19223,77 @@ msgstr "" + msgctxt "#39003" + msgid "Accelerate h264" + msgstr "" ++ ++#. Label of setting "System -> Video output -> Refresh resolutions" ++#: system/settings/settings.xml ++msgctxt "#40000" ++msgid "Update available resolutions on Display device changes" ++msgstr "" ++ ++#. Description of setting "System -> Video output -> Refresh resolutions" ++#: system/settings/settings.xml ++msgctxt "#40001" ++msgid "Available resolutions will be updated on HDMI hotplug events. Currently active resolution will be matched agains new mode list. If new mode list doesn't provide same mode, closest mode will be used and changed to" ++msgstr "" ++ ++#. Label of "System -> Input devices -> HDMI Video -> Enable hotplug events be passed to Kodi" ++#: system/peripherals.xml ++msgctxt "#40002" ++msgid "Detect hotplug events" ++msgstr "" ++ ++#. Label of setting "System -> Video output -> Blank framebuffer" ++#: system/settings/settings.xml ++msgctxt "#40003" ++msgid "Intelligently power off/on GPU to save power" ++msgstr "" ++ ++#. Description of setting "System -> Video output -> Blank framebuffer" ++#: system/settings/settings.xml ++msgctxt "#40004" ++msgid "Kodi will powerdown the GPU (when not in use), thus provide significant powersavings. TV being powered OFF, Kodi no longer active source (CEC) or start of BlackScreensaver will trigger this action (HDMI Audio will be powered down too)" ++msgstr "" ++ ++#. Label of setting "System -> Network -> Restart services" ++#: system/settings/settings.xml ++msgctxt "#40005" ++msgid "Restart services on network change" ++msgstr "" ++ ++#. Description of setting "System -> Network -> Restart services" ++#: system/settings/settings.xml ++msgctxt "#40006" ++msgid "If physical network parameters change (add/remove of network card or interface), automatically restart all Kodi services (sevices will re-read network settings and use new network parameters)" ++msgstr "" ++ ++msgctxt "#40007" ++msgid "480p" ++msgstr "" ++ ++msgctxt "#40008" ++msgid "576p" ++msgstr "" ++ ++msgctxt "#40009" ++msgid "720p" ++msgstr "" ++ ++msgctxt "#40010" ++msgid "900" ++msgstr "" ++ ++msgctxt "#40011" ++msgid "1080p" ++msgstr "" ++ ++#. Label of setting "Settings -> Videos -> Minimum vertical resolution" ++#: system/settings/settings.xml ++msgctxt "#40012" ++msgid "Only modes having higher vertical resolution" ++msgstr "" ++ ++#. Label of setting "Settings -> Videos -> Allow non-CEA" ++#: system/settings/settings.xml ++msgctxt "#40013" ++msgid "Allow changing to non-CEA modes" ++msgstr "" +diff --git a/addons/screensaver.gles.ball/addon.xml b/addons/screensaver.gles.ball/addon.xml +new file mode 100644 +index 0000000..523e339 +--- /dev/null ++++ b/addons/screensaver.gles.ball/addon.xml +@@ -0,0 +1,121 @@ ++ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ Rotating ball screensaver ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.ball/icon.png b/addons/screensaver.gles.ball/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.noise/addon.xml b/addons/screensaver.gles.noise/addon.xml +new file mode 100644 +index 0000000..ed29862 +--- /dev/null ++++ b/addons/screensaver.gles.noise/addon.xml +@@ -0,0 +1,121 @@ ++ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ Random noise. Useful for fixing image retention on a plasma TV ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.noise/icon.png b/addons/screensaver.gles.noise/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.plasma/addon.xml b/addons/screensaver.gles.plasma/addon.xml +new file mode 100644 +index 0000000..3f334f1 +--- /dev/null ++++ b/addons/screensaver.gles.plasma/addon.xml +@@ -0,0 +1,121 @@ ++ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.plasma/icon.png b/addons/screensaver.gles.plasma/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.plasma2/addon.xml b/addons/screensaver.gles.plasma2/addon.xml +new file mode 100644 +index 0000000..e772cc4 +--- /dev/null ++++ b/addons/screensaver.gles.plasma2/addon.xml +@@ -0,0 +1,121 @@ ++ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.plasma2/icon.png b/addons/screensaver.gles.plasma2/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.solarwinds/addon.xml b/addons/screensaver.gles.solarwinds/addon.xml +new file mode 100644 +index 0000000..820fa9c +--- /dev/null ++++ b/addons/screensaver.gles.solarwinds/addon.xml +@@ -0,0 +1,119 @@ ++ ++ ++ ++ ++ ++ ++ ++ 'n Betoverende deeltjie effek sluimerskerm ++ أداة ساحرة تؤثر بشاشة التوقف ++ Ахоўнік экрану з зачаравальнымі эфэктамі часьціцаў ++ Скрийнсейвър от частици, които очароват ++ Un estalvi de pantalla amb uns efectes de partícula fascinants ++ Spořič obrazovky s fascinujícími částicovými efekty ++ Arbedwr sgrin effeithiau gronynnau llesmeiriol ++ En tryllebindende pauseskærm med partikeleffekter ++ Ein faszinierender Bildschirmschoner mit Partikeleffekten ++ Μία μαγευτική σωματιδιακή προφύλαξη οθόνης ++ A mesmerising particle effects screensaver ++ A mesmerising particle effects screensaver ++ A mesmerising particle effects screensaver ++ A mesmerizing particle effects screensaver ++ Un salvapantallas con unos efectos de partículas hipnotizantes ++ Un protector de pantalla con unos efectos de partículas hipnotizantes ++ Un sorprendente protector de pantalla de partículas ++ Hüpnotiseeriv osakeste efektiga ekraanisäästja ++ Lumoava partikkelitehostenäytönsäästäjä ++ Un économiseur envoûtant à effets de particules ++ Un économiseur d'écran hypnotisant à effets de particules ++ Un hipnotizante protector de pantalla con efectos de partículas ++ שומר מסך עם אפקט חלקיקים מהפנט ++ Čuvar zaslona - Očaravajuće kretanje čestica. ++ Egy igéző részecske-effektus képernyővédő ++ Penyelamat layar dengan efek partikel yang mencuri perhatian ++ Dáleiðandi skjáhvíla með brellum með agnir ++ Un salvaschermo con effetti particellari ipnotizzanti ++ 幻想的な粒子エフェクトのスクリーンセーバー ++ 매혹적인 파티클 이펙트 화면보호기 ++ Įtaigaus dalelių poveikio ekrano užsklanda ++ Hipnotizējošs daļiņu efekta ekrānsaudzētājs ++ Заштита на екран со смирувачки честички ++ Een hypnotiserende schermbeveiliging met partikeleffecten ++ En hypnotiserende skjermsparer med partikkeleffekter ++ Wygaszacz hipnotyzujący efektami cząsteczek ++ Protector de ecrã com um impressionante efeito de partículas ++ Um protetor de tela hipnotizante com efeitos de partículas ++ Un srceensaver cu efecte de particule fascinant ++ Завораживающая заставка с эффектами частиц ++ En fascinerande skärmsläckare av partikeleffekter ++ මෝහනය කිරීම් තිරමෙහෙයුම් වෙත ප්‍රයෝගිකව බලපෑම ++ Fascinujúci šetrič s efektom častíc ++ Ohranjevalnik zaslona z dih jemajočimi delčki ++ En hypnotiserande partikeleffektskärmsläckare ++ Пардаи экрани аҷоиб бо таъсири зарраҳо ++ Büyüleyici bir parçacık efektli ekran koruyucu ++ Заставка із частинок, що має гіпнотизуючий ефект ++ Một trình bảo vệ màn hình với hiệu ứng thôi miên tạo từ các hạt ++ 一个迷人的粒子效果屏幕保护程序 ++ 一個令人著迷的粒子效果的螢幕保護程式 ++ Hierdie is 'n uiters betoverende deeltjie effek sluimerskerm. Jy sal vind dat jy 'n ongelooflike aantal verskillende patrone kan bewerkstellig. ++ أداة ساحرة جدا تؤثر بشاشة التوقف. ستجد أنك تستطيع أن تحقق عدد مذهل من الأنماط المختلفة. ++ This is a very mesmerizing particle effects screensaver. You'll find that you can achieve an amazing number of different patterns. ++ Това е скрийнсейвър, който очарова с частиците си. Ще откриете, че можете да създадете изключително голям брой различни модели. ++ Aquest és un estalvi de pantalla amb uns efectes de partícules fascinants. Veuràs que pot obtenir un nombre increïble de patrons diferents. ++ Spořič obrazovky s velmi fascinujícími částicovými efekty. Zjistíte, že můžete dosáhnout úžasného množství různých vzorů. ++ Mae hwn yn arbedwr sgrin effeithiau gronynnau hynod lesmeiriol. Mae modd cynhyrchu nifer anferthol o batrymau gwahanol. ++ Dette er en meget tryllebindende pauseskærm med partikeleffekter. Du vil opdage, at man kan opnå et forbløffende antal af forskellige mønstre. ++ Dies ist ein faszinierender Bildschirmschoner mit Partikeleffekten. Du kannst eine verblüffend große Anzahl an verschiedenen Animationen einstellen. ++ Αυτή είναι μία μαγευτική σωματιδιακή προφύλαξη οθόνης. Θα διαπιστώσετε ότι μπορείτε να επιτύχετε έναν απίστευτο αριθμό διαφορετικών σχεδίων. ++ This is a very mesmerising particle effects screensaver. You'll find that you can achieve an amazing number of different patterns. ++ This is a very mesmerising particle effects screensaver. You'll find that you can achieve an amazing number of different patterns. ++ This is a very mesmerising particle effects screensaver. You'll find that you can achieve an amazing number of different patterns. ++ This is a very mesmerizing particle effects screensaver. You'll find that you can achieve an amazing number of different patterns. ++ Este es un salvapantallas con unos efectos de partículas hipnotizantes. Descubrirás que puedes obtener un número increíble de patrones diferentes. ++ Este es un protector de pantalla con unos efectos de partículas hipnotizantes. Descubrirás que puedes obtener un número increíble de patrones diferentes. ++ Éste es un sorprendente protector de pantalla de partículas. Encontrará que puede obtener un gran número de patrones diferentes. ++ See on väga hüpnotiseeriv osakeste efektiga ekraanisäästja. Võimalik on koostada tohutul hulgal erinevaid mustreid. ++ Erittäin lumoava partikkelitehostenäytönsäästäjä. Tulet huomaamaan uskomattoman määrän erilaisia kuvioita. ++ Voici un économiseur d'écran à effets de particules particulièrement envoûtant. Vous trouverez qu'il permet d'obtenir un nombre incroyable de modèles et d'effets différents. ++ C'est un économiseur d'écran à effets de particules particulièrement hypnotisant. Il vous permettra d'obtenir un nombre incroyable de modèles différents. ++ Este é un protector de pantalla con efectos de partículas moi hipnotizante. Atopará que pode acadar un incrible número de patróns diferentes. ++ זהו שומר מסך עם אפקט חלקיקים מהפנט ביותר. מספר מפתיע של צורות שונות ומרהיבות יתקבלו. ++ Ovo je zaista očaravajuči čuvar zaslona. Moguće je ostvariti zapanjujući broj različitih uzoraka. ++ Ez egy lebilincselő hatású részecske-effektus képernyővédő. Hihetetlen mennyiségű különböző minta képes benne kialakulni. ++ Ini adalah penyelamat layar dengan efek partikel yang sangat mencuri perhatian. Anda akan lihat bahwa Anda bisa mendapat sejumlah yang mengagumkan dari pola yang berbeda. ++ Þetta er mjög dáleiðandi skjáhvíla með brellum með ögnum. Þú munt komast að því að þú getur fengið ótrúlegan fjölda af mismunandi mynstri. ++ Questo è un salvaschermo con effetti particellari è veramente ipnotizzante. E' inoltre possibile ottenere un incredibile numero di differenti schemi. ++ 非常に幻想的な粒子エフェクトのスクリーンセーバーです。驚くほどの様々なパターンを知ることになるでしょう。 ++ 매혹적인 파티클 이펙트 화면보호기입니다. 아주 다양한 패턴의 보여줍니다. ++ Tai labai įtaigaus dalelių poveikio ekrano užsklanda. Atrasite, kad galite sukurti neįtikėtina skaičių skirtingų šablonų. ++ Šis ir ļoti valdzinošs daļiņu efekta ekrānsaudzētājs. Jūs redzēsit, ka tas spēj izveidot neticamu skaitu dažādu musturu. ++ Ова е заштита на екран со смирувачки честички. Ќе откриете дека можете да постигнете зачудувачки шеми. ++ Dit is een erg hypnotiserende screensaver. Je kunt ongelooflijk veel verschillende patronen maken. ++ Dette er en veldig hypnotiserende skjermsparer med partikkeleffekter. Du vil finne ut av at du kan oppnå en utrolig mengde forskjellige mønstre. ++ Bardzo hipnotyzujący wygaszacz. Przekonaj się, ile niespotykanch wzorów da się osiągnąć. ++ Um fantástico protector de ecrã com um impressionante efeito de partículas. Experimente e verá que pode obter um número quase infinito de padrões. ++ Este é um protetor de tela com efeitos de partícula bem hipnotizante. Você verá que pode alcançar um incrível número de diferentes padrões. ++ Acesta este un screensaver cu efecte de particule foarte fascinant. O să vedeți că veți putea obține un număr uimitor de modele diferite. ++ Завораживающая заставка с эффектами частиц. Для этой заставки на выбор доступно огромное количество вариаций эффектов. ++ Detta är en mycket fascinerande partikeleffektsskärmsläckare. Du kommer att upptäcka att du kan uppnå ett otroligt antal olika mönster. ++ මෙම මෝහනය කිරීම් තිරමෙහෙයුම් වෙත ප්‍රයෝගිකව මහත් බලපෑම සහිතයි. පුදුම සහගත විවිධ මෝස්‌තර ප්‍රමාණයක් ඔබට ලබා ගැනීමට හැකි බව ඔබ සොයගනිවී ++ Toto je veľmi fascinujúci šetrič s efektom častíc. Zistíte, že môžete dosiahnuť neskutočné číslo rôznych vzorov. ++ To je ohranjevalnik zaslona z dih jemajočimi delčki. Odkrili boste, da lahko dosežejo neverjetno število različnih vzorcev. ++ Detta är en väldigt hypnotiserande partikeleffektskärmsläckare. Du kommer att upptäcka att du kan åstadkomma ett häpnadsväckande antal olika mönster. ++ Ин пардаи экран бо таъсири зарраҳо аҷоиб мебошад. Барои ин парда шумо бисёр таъсирҳои аҷиби нотакрорро пайдо мекунед. ++ Son derece büyüleyici bir parçacık efektli ekran koruyucu. Birçok değişik şekle ulaşabildiğinizi farkedeceksiniz. ++ Це дуже гіпнотизуюча заставка із різноманітних ефектів частинок. Ви побачите надзвичайно велику кількість різноманітних візерунків. ++ Đây là trình bảo vệ có hiệu ứng thôi miên cục kỳ lợi hại. Bạn sẽ thấy sự sáng tạo từ những kiểu kết hợp có thể là không giới hạn ++ 这是一个非常迷人的粒子效果屏幕保护程序。你会发现你能看到惊人数量的不同图案。 ++ 這是一個非常令人著迷的粒子效果螢幕保護程式。您會發現可以達到一個另人驚豔的圖形數。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.solarwinds/icon.png b/addons/screensaver.gles.solarwinds/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..1f5800360734c51b7d628f644d65625f9c6d39df +GIT binary patch +literal 14774 +zcmd6OQ*fkhv~J9aZB6WnZA@$@9oxyob~5qAwr$(CZQDHk-=8{F=W6eZuCJ@Rs`1sk +z)_SzU733rk;BetUKtK?FONuIifPey@f`Y(+0Wb5&0?fb*jjP{`>^RmpClsY?lH%D-#JAsQ~{;Ld6*mVY|GF^oRAeGgaHjSyzk?l^r%VpZgNs&-Q8*59{Z15&ncz84h +zQX&>q9qD9VOrmTMCrJYX1Jk9VwKd!t6joFDe-HoQ9$Zm8a{uHg#izE;vb$C5wnP2I +zkfYUkE8npF-s;e^^A-tYj%69=+>yO)A^8+>x!j1$$oMgb1iin%U*Bwv!}SZ5jU>2% +z82Gakt`Nj@SQ?PMh=}m;>~G}cq*&20{#Z?^#S9x+#ik}6>iZ~M{ZJ(k8yr+sbwTWj +z%gZz5{5xIiJc^1pKa(U_DA~SeEkX>Y)BfP(G*8)|0i8f-B6m24#La!eMO|82SXkHw +zKXR_yZoAp!+EnY*1~(02gGj_r7lgf5Tu_AlMdX5K$_`OSZcLQWa3xNRx09~?KrgN0 +zl^Q`y5wUD%j)fZ?5Xkc}U7AtB*ZPu66dDrJ=d7rEY5L2KlcTnC{?yveE|eXmiUdU@ +zl%0w7mlkKH%$xTZ#-%pBU#(Cax~QL>_**N0h22HROGn4q+1bKEQ_qJ`k`gYdy$v_S +za((3ooV=}GR_@jbGXkR6`N;{V`(432PJo=ZG4uvlIx$gNT6%g~+OCdd*j6N8m +zJsA^-_4Fturs^%;3w3I&BLjr64P;M72<7bYU)KcwvE}+pr`9@)5)}; +zAU6?*>ah_GMP+R(27PK_q2-sB3UDz%y>M7XtPcqP=uU5->(vIc;4ko(e+5fROJ#_g +za{B)g*y8(^F#KU=c);vCi3*4YY`-OlR;L0EWHVTQyF5v>=;XBdi9-z7!(bbA7$O-c +z%rqpb&@p@tQLDOM(FTCPY1`jN;p2>M=G@w6wF}i-Vk6bk0=~aK|NV>CPXmLjs3|Gw +z=;$k@RU7~wQnuADK|cv1_n-7OrM~H6)YKRliBt!|eX2$$7`SqR{VLG`L$lr^JH6iT +zPp20js4B#ij>E)$8jeR5teJde7Ev{5pKp)jQ(LHLXk=IM>FMo`i!7Wdqfbz)AVJkV +z!L(82WdQTC177b#k%$nX@$m4rz0NPklNlT?!z`YJ-$0+YcnS{`U`sTX +zDu2n;LzmrZiU9b1$LlgU@k5%udB67 +zNlObYBf&bX{jmxcMg?t16?j9D66iT}oXmL5-`L=ND2R^0G4V|C2Zz?{uvb)G6}~$d +z{bx3r1`DmNrPb8g{<+cWgs95WC+JBz+3-^zl0FDB-iLZA9@+)BTsLBFZ7D6ONruh{ +z^y!*WM*E3#xr}^pO#`o~I{Ee)_?e@w_z(iPDqM9G{%iP$e}6MS4obA$w5 +zZ$-RqJ5}kJ;L{x7%CZD$Q3ZA3Q1Wncu;v(HZBrDvz~{8@*>#4|OvWk;l6-A>2n`MG +z#r`qJ$lzdn6;%!eXUsg)6l3eikGe@_qd4KW#A1&}T*|>#zmEW-%C;Wv#EQtI@ +zZp-8SlKLN|{}5Qd<6&Gr=TE%;j=TpNt5_Tv|I6KfT#FAC&Fe+DUQN(MUQ9baAE7=U +zMn%S@y)E405HNIn+D=VF!^7kFC1sA)y3Kk>XUtI6{Aw)uuUG9?5r1R;+PBJOazB1S +zd#2Wor+>ZLml|G#2yq<+SV6JDfUB&jtrFnjr6;6>Ap(1C$Hyk5sW|a(VRyg!eBk*W +zOQ7E4qK(04CeW&bD=@#kb@&2cKF>g0!r`C@Dt;vS2o0>QtsPBfCZ{C8u)-i2X-_%b +z-?g?~s2~)IF{`;i2Zai}?0~VlOGM!wI<~TReBf=iJm4u5p7!zgqmmVS*<8BGURJjg(uNdp44-6$7Z1=NP=VbA-TqpUiD7_v%Bsq-q{BU30QQ +z!RbExH*Zl?9Rs1NAMo%9hKHjiuoQgsx=`4!YustbPnWqAG&NxZ{-iU*vI0RW8^>-6 +z%^{QVb9f{^wX}fYY@V2QUHvXip_wi(9i5B}C+3@jVO}w`YB_)NR-1k=*aQD*Zc#Gh +z?s7?G>2F!t$%zefIy+CtCfm&pcNR~T++`HdfGF@3?VI4^?0?NG0SZM$1x>Eb*y&mm +zi^{9|J;*_f-5n1{zFn{s6jZ|WSPWh_y?Pr2rqQ2oZ)vDRSVT9>J4@+x?2iS7RBxt$ +zIId;N5X;xz8}I)r@)>Svq@#6oz4<$u)>fvpoX_2H2_#Ecx$tZK*B3DZcVh2R$5&u +zEkFw^a`pZBT3%8zc6zVLLqy!W?@xiGw4+Y8_#t$fVjD@Tq_>3cV +zX?pW|8J+-*mq)+!th+y8l-l9sXvxN_`^w>R&xtvZ%;SNX8z__%44!hBK^=6qh9-%!U;V2B2h +zxIk}`L|BKQ`lFvVSI_>TZRcUq>pfA=%K@;%G})}XoZgwJwoqe;AsWXnhu`1bVbSZD +zuUCvHbzxwE+i6Hf7x`~B8XlHa$flE$l6DYQx3{e^xi`-E5Sbjd5n42$FS4WASQKV8R28zDp?fSx05Jiu(3D_E3!F5ge{9cLR2 +z??1|=@($vl8q%L|F*^BAn3$SI(ErWZD5m$s +z4_X-|TPXko4-puvz?tu~I<87dF;BOtak~|fBeOzYyWiafABx67Fgrgxlgs9!wF~07 +zZ+HGPnaTov@-suOx7CW@%?!kOD#tQ5Is01Puab+)Yjybn2~Lra(>!M*zI;0XduPX=LzZREx-;bTDnPo!@yx|4BwdwYA*)q6Z|l>3S)J9yS~XF!PY#iifzoG148 +zA(B?;pEk#e4G3RU;L*soE{LVf#mlXEd{bj1m*)(`4hYp!zeFT*^mkq#se7ehf=!%m +zIg?5;y{_d!tkVe3$dB1)i#avy(8bYtykOCkO{J8wAr8s9Fc@kx6wl*AC@^9g?l&M0 +z{S^=x3CUzmgNU3l76JEzDOTFy6*hZqVo2dAFiN`*c$=EgI@G0r +z!4MKcbHPQgasT~}oi{CmE%%k{>rP;2G9%#bwdHoKZ!4khuFg*$prI00kB%y44#=0- +zW=WEeBJ!8ubxGJBGnn$?0~ta3hl)b15vi|v+H>R1f|m;*4#dCly4@Sx+XIiddR#UN +zI*>I0)h!1y%BbjwGCp^uS~^r(Y{ln)*&i!m)VPGZjwU8Hjv<_pBR?eE-MLmu*_Hgu +z)Rg;CV`vQL`MTc^e*Y7N3rFb>MZ#sh>FE^^rd>>-y}P^naDw*#O<)ag5KWxyqpLkD +zy=viD&}9yc}U=w{DoInK|3kFJ0^H +z^%v?&(XGSn?yf;$p$T1bC8^GCUCP-V(mv~miG-P%uI^@`bTU3^-fGiH`Q1-mz7uRI +zJ8~H`nO~ecD;@6lMY8FSogj4RtfFd*9(6h?&R7%6=F!^1RmAEmh^B`uwm +z1og-9aL)HmAeReVPNv0-9NxP*;5}3;TU!R}#pC0S7CHIw^guRySlPVw|5VqZvd8SB1G&4+P?Jc +z)KYOvFukm#V!$7>oMconPl@XX5yJ)z;$M_8e9_IGJRfbJ_ogu7G$sRKML+cnr4}flwnweiW;_@{BtHi%RL^k) +z*>IT+A=W^MKZTX=hhlp>rYS=C4a-Skz_zk|-Ym2~@IP8y +zCeN}zKaNS$154L(izBvGRAsgk&YB;;fI~i+Qg9}L@OyO{s79#rll^=-$bx5m>jMu4 +z@y{%idZZX&BgUAVJkIjn4c_e!>8)*>HxnJqEtg^Sz-9LapOK0<84&)UrKz`w(Df;JG3;n +zZgW13pGW3di~$#C$`Bis3yTSbHTzFI#NjJzYG{C2F1wL}Qc9I~s~=vWqhk +zwYm=gLA(+&Jd2_yvy)fOS-*Tb_QR6IFy`40bR-azOhe{WMT$(qOvXo5Wo4zKludh> +z&;BsJSgBPm{+h=Ec+D;>{G6lJw(P$dX>!;fDl9Huw}rz8!OL%KR5hMBGrz_r52o+< +z?u73?vK~Er$MMD +z?^%O|1*V8X$8<2Nhc9S*WR|0(gamXV&XHoae{zz`A0L}DcvPQtkKO-`_bP@Ir2+_7 +z))GbN$i&9zFu&BCj*5+5a->GG1MsyVaA?GuM-T}=5No}p3Kj4z;p&5 +znd7OiW-%q;m3!cHL%MZx=bl=}&Au +z4Hb>RC;8Y!WW+Q57F#_9kIAz|SlG5-3IITMQd31!(j|=IE58__QN^7#JYemOIcDUq +zgt)=q5JFVJgruZ!0)`3XWj=Hv2!$?hxN +zTQ^kGkDC1az~oLRsy8{OqlMJ(o^H5eSursaTRjFSqc>S@;yBzhDDG*TYSyU +zWt>$kG+QNcDXUP^v2RC!B-2`MLI@lh`}J6bdI&l@jKJkLB2kc4*!jlmec#&RLm`LF +zMvFt<1;EWs!_o1V`8OoU~vlOnmyHa7>FjvesrzM(2^hde3U +z?YRJ!kiF!jh2!i$1QQM}3h-xpwbM@GTGU+qx{?eWHHEd47aH;*y%^cs&1R +z#0&88<=56S>krxM&|veKK78IE?Z$atcXF_>{H=s4Nh2rAL&u^wWI{k|#cOzi-5>5( +zH8C-XijtM%s|c$l=isQWx^kA0Va2cJRSGXm+9`9`r%SvM-17%P%(`XbVC-&r>FE&y +zmtW2ts_{8Dvg+jip$LW+>^$`->}{>YW4sEbl`s_Nq1|5E&_v`n{`Ht?%NO885B-& +zM*UT|om-7e+t+_Cu-q%udI3NtZ4n`9NdRocq19Q6bm_QETb-{PTXz>Pfkmx?)AK1( +z*)^4WA*TWvtz$LUqlBeam#S21k;X< +zuD-^Lvmw0Vuf3iN$NL{S5+fx%67O^k-4kh=AC +zi7A5l=p07pA)!P92Kz5!tnK>>vx`N!KKLQ5G9|=f@|p1ln?!63>?cNmS=B84s`f#n +znL=|0xLIUJa)iYA{{Y>HVm&+M-R1lKI&GtEC#2cE|Fr&mwN9%poj8c2 +zycU4buHX9s#5(^C(1lWE;udx>$)#DOWWujrBp-X|VEnRbz~UwpkkvVrPEjg60E{RK3spb-0BUS2*=w+k>k$U(?IUAxrpNxns6X0uZ= +zJ7lUf1SDE(wn{NO$_4HWN8_~{k18qLcIq)|)LJc9+U-BG9sG>=y7A!qiXifbxoLFI +zr!p!K{ypLkv?EeAzCeWqg8~Bhgtdf{4HvIj0XiEGfBdDIDtvFnCV2R~-ySApyp4?A +z+&D8J=ZXr7nwlGp4A1N8dS2(H$H#uiWBnFb1>wW)2X%tzr7B8i80B24W&x!radwbgr^V4+p#BXb{P_K!ho_%W&V3w#`(EAy=N{y25ls(@*>MOc7_!gMCbpST^1 +z(L)eyP%1z+X6}6#3yN+PjCVk_?5^%tO56t}C{z9?9C}I7x{B60#VJx)j!Phol1vZ{ +zhJ+(_YAVL}o}?i$$FI_n^X{1f`D|?>&xcvh>r7M}94?cwgrSg-X@PGd6a#~Q!d!mP +zE2z7Uqg;ZTqe&()08^fkmHv$H4=>>ko97}9o7H{Y%}vBbgCRpnq(frBu_`2SiU^6Z +zYt&0NeXW7D^#z0;cU^8Szkn|XK&Wn*E^H72;QBo98}0Cdnx3A%`}Ns(xMK#?>11te +zabPIA-;2h+owp^kYoq8{!27M?;c%R}1Z^|Nt8&c({%97=4k>;)}E4q`GzF1$D|W +zE<#yq=}{Qe0c2YlcY$<49y!HS?V)^hc(h)dad>4*L4j!P^q)V)hth5cpv<|>+KvZf +zV&^}g<0eJQpe@hr=uV<->V7!fAtaG_;Q5|%un-!E2FuF_3loDq_^`uh9J5k$tpegB +zJFH~jkUn3hDdjSd-=?E8+nLCaMhx6ER&-rAaWFBLHW$ey5MXg(9Fj8&A}$0vwU}ZG +z`DI;QvAg%_Nk}$PPfuc`^>VhDh=Djpn}~A>As@BL?t62GL&NG8OH#eHEO}k^;jcr$*P&h(bz6PC)A5upaERe*_OpUN +zY;m1EdVC_)^96-e&?u>rN>`XmjsWM$RMuy?Ee(}rHotf911;SEmF>+=uct +zS##_PiE=wp$Y(_cZ^|z(`ddOI>~e`j(Pa(!+5EIwj%0P*Y~J!XPnk7(+gfTaD=TY# +z%{a(VO|O9b;Ku24ep3f2?q+Wl`kVxmPEms|DY>?nYiny48V5#5s#;-U-mv@*_H>>b +z2(LFi^_-)np>@4n3!dYB%bF$4!BtREao*_>QoZ|(!Qu1R$?^a5=a1P`21=s#>(qqy +zToMDyAe-R0fXhb;%!VHi1tnz^i_(wV`r*tJs!gGJ{z(w^3=mcogs6)jdB$ZO6p0BX +z%lu&F#AfF_jcjag;r(`(uspB#y8_FZRp;x)NRb1wld{4}Vz_hzHM{-ZgV1gfE-uN1 +z(n&Cn;m2d2Gmp-4wj9hH>~>X8b32-qmOb{sMNS4YD{xFbfOzu`y +ztpY{+(l%~4X4%gZMb&BL!T<}}?LJAb^7+$~*?e*+cfmJ-mG))2b((+b3E{<@FiQSi +zC_#@kPQg5XS=R{-Rn#XG6jp^nw39R&rT)m$&j>bSiUzBNE_qeqP=OY)oZJ$Bu5WEJ +z9FZn&_O)L33tVhI=jK5pYN|z>pw4GU!rUOpK;}IuYHFtXdb`Jjnza4-g;dH%pKJLd +z!N%p#U|?C_Fjsa2Fz}Nnh=>E8Wz-X4TbPbR@m|gCV3-@%A@ +z#YltU1>?*=jup-vT+Iax6gYzkB;4)19LTXk2F_B=f7P)M{}66CiUqYjwJj~nR(z(; +z&giwDrkY$+0NIp`r>@%F0RG1VBL0o%WO)Ji_sZs>XaX|BUx|XNV`4Aq;&qr1)i +zD+0AhQJ>3S9EHI(TOwOjWMZJH)PEfOU5=+Rn_fxiZC3pQp+D<=)5NYl2)pS=QDIrZ +zKdR-y`f_pldf~*<;w#B1DBg}KW#j=20e2>t;n*!%hKax5!aA8 +zDk>@~38J~(YSL;m=qOo+VN??7bV++2CBez0;XEOo;{$Rx6t;W%C0ALIakv~O&)Arm +z+lmfu-ISF6qZbbUs;?vyopz*XEecTLP`onNhK1`_Tlb%5eZ=i={SAM7Km2)5NyIm@ +z=oz1{kMER&UMeyha_;s4CS6d6hHL=Z+81!wZ_Mbv?Wf2e2+9V6gI)XKb+ow%Pp#^tN%4Oi}k5c2MS?fDJdy0FE233 +zOW9iWWREWI)!l@_jd+-ItfUwZr@$O1aA5fKqT +z;Ni`73l9$svvxEaQsB+c7A#Wn0Kw%&vSz`jNa$GZyj!jJM{FD%`%8L-uI>Vd#i#@P +zE(tbw9cB;MizBcb=>THju_@eujvzwLWlPhMtO_+vD?r6I(-?x5?TqNkJ-&fW$dtO; +ze(Uk-&KnAOU0eGXab)!FIysSRYHsG>;Gnfu_waCNco7PWui-J*2d2jLUDG~4jH9S5 +zPb_HJyN1duE@b)oi~5~wycK?`E9J2+t}q&o6_V%6rT-j78INd? +z7er+{MbzqvORRS3MepI~#wgv29OaZf7F2XlG&k3iW->Tlkr!Y0|ZNYYC^1o6Gc|3dg>6(<(HA`-G!i^`d728zw& +z2hEiP)Q*Ve!k#UUz+{tkoR@oZ>p%*zUBK0G9C=Tc?W9<-`e7e}O= +zW9`1Uh8o|=5V`+ddVp+ +z9;urn$+W$#jmY~U4oQGD{nKaoI#&~`;rwdJi$9$@42n4;2x|N5sTuGZ^UcKY@qk2h +zrCp=%qprSOoQ?ktp*I{O^n4S5WPdO(FMz{!w{B0y8yub^@O3TV{|B_0Wsl$6?Qf~_ +z_vuNTl$&h&o4ljjNkge}jEY)9aw2IZ|JU_*2%&-1Oa7_{vm` +zbp7cDs(+AK%7|lr(rU&9$H#|hF~|3~q9CJlfmkCaV5BVOC+%D>>{FnLNwFAfrC9 +z79qxCQ=`56`$L0u)X+Hdm(pP|5{r=hCt~0)r9lub9VI0&jl3Iw`~umkDCwl70~uSq +zUhjhOf#!Ya7clo{nCshVr>2bI4sVvsAgkSCj?!Tytr!gJ8+z+7?=OtUVM;+k!5}X$ +zFDHjdsBs6Td#!>@B%i^_44nDC9rsfRjGZcg?Ha>DxQ8Y>tri6cbbNjScJ} +z>xG4ca5PFsi!eDUnThdfW!Cg|acOC7nus~?hgk_=c;a=)g`SPv1n3T8CWj|_o}S_W +zv!yNgP?wumXK!yF#DZ&c?AcqSl3tRC!-EU- +z(__+0IjFZgouCEbD4cQB{?alG16m&E%TL +zd89l)7w9*-X>dB;ypH{-V+GggzQLvy%@>dII4w-x>HmO)*EeU?!P9bdjF0^ahR4Fd +zz)Dn4=;!eYA#?v +zMWg7c=#x0HrE`78f%XEq9lRCbk0z)tE3-5&N&b{|tV?9GT2fP2ugAsVodL6r>wgdB +zcTgDC=fS=fdOOTxxnX8xBsvCdINpUSoLEu#_3IY}E*p(lBc52@9dH)IPjrWtRq3{? +z;dg(3y?;Lp3v{*k@I~g3W(ZOJWO}-niqOy=gv~aXTgD(!fMpdx)1DoG=`{ekXg=PRKiUvZEWgfcr?Ck+#&|0u(u&t$rmef +zE5i^w31dDygP?V49ZfvMp>*J#ROIBI?uxUQ==Gyu>@!(}6s3`pr?U8t6V>%@v3=EJ +zNm6EHIk<*{!qEx>x__91zx+)W=<5@b&ATQoL1YClsoRL)7~cYsQ8f4b(W;qF}hZEu7oxbJKFazj+zaToY~@9T20;y;|qJ+5Bx5;g*oR6gXr^%5`*3^%z& +z6z-^eh830^HI|k(St&F~A<~S|O~K|g>xTj}iC-jG51;P>eYbf0Juw2TF#0lT +z(LH<9E{H!=O^(Wx>gd0Srr0-{P^K1b73D_jjFj1kaK8K*(6NZ1@n`m{8mlo}Wg%YD +z-+Wi#hfHU*;o;yYWYZv6-m}Rop-c>x8N4?jSAoKGWK`7U)fpi$-A+quHS}Y1Xp +zcD(RRBBU0^337uRi0oDzW`yV-$UOZEn3rpaO`HZL9UvJK#_bVb6tuKLAgB%zi5xm= +zY9yz>si#4dx`6?iK6Z>p^8;8a9!fl$tAc@_+Mk651p}>4{|X-w#bl6QtR8h9V2+@{ +zZAZ)%oFn=H56{<~SOg=(NWOhRK{&+BIpashX7JO^0%c_zqfW=%ZrH+$;oaD#%;nAm +zxR_ckzTHg0p2E(~KQ=~ej2*wOp1T-P^-INrLA!n~vjH_*;Xsv~8rc+16pq&Z)w%xA +zTXB1@y@JsdaI?1SfBVC&>E}Ef>*HBBp4;6L8Y_m3ca+01y`|S)$L$(J`ao0u#GHnn +zesXH+){Sr1V3&zfhDnESg_6nU5xzV>KR>Cc(EDk5I;Z)dbrd*p?masH6>re`qNIUV +zG16k2`OGAOX93z>2qGl4t+ch)erabpD8Fr9B`ly9XOC-ZB;`=R&I=C#3wy$BR@(KI +ztF(dw)OlrP_pSQGhm|N +zTlqR_vzC0EyfI4E4%AxCt&pN>Z6B}*jv#Pz6QV~CL)>cmn6&2aY4P`4Ik|b8&d?Kq}jVfB@ +zh_bJ3O +ztmBrczPTy86i+h=TurQ3MFXuOLp(usTIB2XvFYjqaLhCUDxtrjuV(AIhqO!7PwF`U +z8*7nI5Zfs-FKaemn9Ezp-T35T|Du$%(1jHOfg48uU%N)T*8w#(HD=kLs$%Xq9eP_e +zplBy>qT=Fxz2Jjl_DwnZ&kYvJyE|y|ABImC?>msgMD8yJvu;3xZGC$air!|}a~|Y9 +z=&KfV1K#IiQbai09zwpi@utVk>kAyIpvZw*Nc6L)w)S=v@QphqF4}^Ni@WQlV*C?k2?!nGpDw7YOJWDlqd2~t +z`p3KdljJ}4u0rChr(;5tE_7GQ)d+Nw~Mi64r2_(-QnbnHR*%kBCgCidLY2w{xdvGHV0FANm>n +z!u@48yHBVELIad&%iGoSn&{|UQUGNqq!&$||M4y)S#bE~tMC2J&WCJB8VieT!Tkd$ +z`7U$_tr4pESh6sAtnRE4Dm5$VZOxoL22{nkiW@|zYgrDK&dsS5#i%z}L>^yK+E`SCpVzPevj0GdCu?0>R +zhKUjzwCET48J;`#9oS|Nh^CN@*;|7}o$#;suGP+ke1*xDBdF!4*f^a_6tsYEFR%#y +z22kw)w)OgBJTGk09$7GSL{`?_&bA?$h&J!{>zy4kB!Pu(;jK36az#;T`F^KiiEPv%j5}}!y1b+YtP$J=_Ik6Dx_!`2?HOQ4w +zXMcdh_QS({g1CUg69DBNL+eKF?EJX1^Vr_OB}6@fP_W*)HQgTO^plb+DQNPa2@HTR +z%LWD`60@Gp_d_NSa5DtW!Y+bd%Mh%ua%fq*ECa3FB=uoZE&z@F)%Q%Izy&{R;N$ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ Spiralling screensaver ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.spiral/icon.png b/addons/screensaver.gles.spiral/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.stellar/addon.xml b/addons/screensaver.gles.stellar/addon.xml +new file mode 100644 +index 0000000..c345d87 +--- /dev/null ++++ b/addons/screensaver.gles.stellar/addon.xml +@@ -0,0 +1,121 @@ ++ ++ ++ ++ ++ ++ ++ ++ Seker die tweede mees psigedeliese sluimerskerm ooit ++ ربما شاشة التوقف الثانية الأكثر هدوء على الإطلاق ++ Напэўна, другі найбольш псіхадэлічны ахоўнік экрану ++ Вероятно вторият най-халюциногенен скрийнсейвър ++ Probablement el segon estalvi de pantalla més psicodèlic mai creat ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig ++ Formodentlig den anden mest psykedeliske pauseskærm nogensinde ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner überhaupt ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που έγινε ποτέ ++ An interstellar journey ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probably the second most psychedelic screensaver ever ++ Probablemente el segundo salvapantallas más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico jamás creado ++ Probablemente el segundo protector de pantalla más psicodélico ++ Arvatavasti teine kõige psühhedeelsem ekraanisäästja, mis iial tehtud ++ Ziurrenik inoizko bigarren pantaila-babesle psikodelikoena ++ Todennäköisesti toiseksi psykedeelisin näytönsäästäjä koskaan ++ Probablement le deuxième économiseur d'écran le plus psychédélique jamais créé ++ Probablement le deuxième économiseur d'écran le plus psychédélique ++ Probabelmente o segundo protector de pantalla máis psicodélico. ++ כנראה שומר המסך השני בדירוג הפסיכדליות ++ Vjerojatno drugi najveći psihodelični čuvar zaslona ikad ++ A második legpszihedelikusabb képernyővédő ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna ++ Probabilmente il secondo salvaschermo più psichedelico di sempre ++ 世界で2番目にサイケなスクリーンセーバー ++ 아마도 지금까지 두번째로 가장 환상적인 화면보호기 ++ Tikriausiai antra labiausiai psichodelinė ekrano užsklanda pasaulyje. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē ++ Можеби втора нај психоделична заштита на екран ++ Waarschijnlijk de op één na meest psychedelische schermbeveiliging ooit ++ Helt sikkert den nest mest psykedeliske skjermspareren som finnes ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie ++ Este é provavelmente o segundo melhor protector de ecrã psicadélico de sempre ++ Provavelmente a segunda mais psicodélica proteção de tela já vista ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată ++ Наверное, вторая из самых психоделических заставок в мире ++ Förmodligen den näst psykedeliska skärmsläckaren ++ පෙනෙන විදියට සදා දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky vôbec ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu ++ Troligen den näst mest psykedeliska skärmsläckaren någonsin. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu ++ Напевно, друга серед найбільш психоделічних заставок ++ Xứng đáng làm trình bảo vệ màn hình gây ảo giác mạnh thứ hai ++ 或许是排名第二的迷幻效果屏幕保护程序 ++ 可能是有史以來第二最夢幻的螢幕保護程式保護程式 ++ Seker die tweede mees psigedeliese sluimerskerm wat bestaan. Verbeel jou net al daai kleure wat rond beweeg. ++ ربما شاشة التوقف الثانية الأكثر هدوء في الوجود. فقط حاول تصوير هذه الألوان المتحركة . ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Вероятно вторият по сила халюциногенен скрийнсейвър създаван някога. Просто се опитайте да съзрете всички тези цветове. ++ Probablement el segon estalvi de pantalla més psicodèlic que existeix. Intenta imaginar tots aquests colors movent-se. ++ Pravděpodobně druhý nejdivočejší šetřič obrazovky všech dob. Zkuste si představit všechny ty poletující barvy. ++ Mwy na thebyg yr ail arbedwr sgrin mwyaf seicadelig sy'n bod. Ceisiwch ddychmygu'r holl liwiau na'n symud o gwmpas. ++ Formodentlig den anden mest psykedeliske pauseskærm, der eksisterer. Forestil dig alle de farver, der bevæger sig omkring. ++ Wahrscheinlich der zweit-psychodelischste Bildschirmschoner, den es gibt. Versuche doch alle diese Farben, die sich umher bewegen, festzuhalten. ++ Πιθανότατα η δεύτερη πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Απλά προσπαθήστε να φανταστείτε όλα αυτά τα χρώματα σε κίνηση. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colours moving around. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ Probablemente el segundo salvapantallas más psicodélico que existe. Intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantalla más psicodélico que existe. Solo intente imaginarse todos esos colores moviéndose. ++ Probablemente el segundo protector de pantallas más psicodélico. Solo trate de captar todos los colores moviéndose alrededor. ++ Arvatavasti ajaloo teine kõige psühhedeelsem ekraanisäästja. Püüa lihtsalt kujutleda kõiki neid värve, mis ringi liiguvad. ++ Ziurrenik existitzen den bigarren pantaila-babesle psikodelikoena. Saiatu kolore guzti horiek mugitzen irudikatzen. ++ Todennäköisesti toiseksi psykedeelisin olemassa oleva näytönsäästäjä. Kuvittelepa vain kaikki nuo värit lentelemässä ympäriinsä. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probablement le deuxième économiseur d'écran le plus psychédélique de l'histoire. Essayez seulement d'imaginer toutes ces couleurs en mouvement. ++ Probabelmente o segundo protector de pantalla máis psicodélico do mundo. Tan só probe a imaxinarse todas esas cores movéndose ó redor. ++ כנראה שומר המסך השני בדירוג הפסיכדליות שקיים כיום. פשוט נסו לדמיין את כל הצבעים האלו נעים ממקום למקום. ++ Vjerojatno drugi najveći psihodelični čuvar zaslona koji postoji. Samo pokušajte zamisliti sve te boje koje se gibaju okolo. ++ Valószínüleg a második legpszihedelikusabb képernyővédő ami létezik. Csak képzeld el mindezt a színkavalkádot mozogni. ++ Mungkin screensaver paling psikedelik nomor dua yang pernah ada. Coba bayangkan warna-warni itu bergerak ke sana kemari. ++ Líklega í öðru sæti yfir klikkuðustu skjáhvíluna sem til er. Reyndi bara að ímynda þér alla þessa liti á hreyfingu. ++ Probabilmente il secondo salvaschermo più psichedelico di sempre. Prova semplicemente a guardare tutti quei colori che si muovono. ++ Probably the second most psychedelic screensaver in existence. Just try to picture all those colors moving around. ++ 아마도 존재하는 두번째로 가장 환상적인 화면보호기. 모든 색깔들이 움직이는 것을 상상해보세요. ++ Turbūt antra labiausiai psichodelinė ekrano užsklanda pasaulyje. Išbandykite ją ir pamatysite judančių spalvų šventę. ++ Iespējams viens no vispsihodēliskākajiem ekrānsaudzētājiem pasaulē. Pamēģiniet, lai gūtu priekšstatu par krāsu kustību un plūsmu visapkārt. ++ Можеби втора нај психоделична заштита на екран. Само обидете се да ги согледате сите тие бои кои се движат. ++ Waarschlijnlijk de op één na meest psychedelische schermbeveliging ooit. Probeer u het voor te stellen: al die kleuren die door elkaar lopen. ++ Helt sikkert den nest mest psykadeliske skjermsparern i verden. Bare prøv å se for deg alle de fargene som beveger seg rundt. ++ Prawdopodobnie drugi, najbardziej psychodeliczny wygaszacz na świecie. Spróbuj i zobacz ferie poruszających się barw. ++ Provavelmente, o segundo melhor protector de ecrã psicadélico de sempre. Experimente visualizar todas as cores a moverem-se. ++ Provavelmente a segundo mais psicodélica proteção de tela existente. Experimente ver todas essas cores se movimentando ao redor da tela. ++ Probabil al doilea cel mai năucitor screensaver care a existat vreodată. Doar încercați să vă imaginați toate acele culori mișcându-se. ++ Просто попробуйте представить себе все цвета в движении. ++ Förmodligen den näst psykedeliska skärmsläckaren som finns. Försök bara att uppfatta alla färger som rör sig runt och runt. ++ පෙනෙන විදියට සදා පවතින දෙවන මහත් අධිචිත්ත වේගී තිරමෙහෙකරු.වටේ තිබෙන එම සියළු වර්ණ ඡායාරූප කිරීමට උත්සාහ කිරීම පමණයි. ++ Pravdepodobne druhý najviac hypnotizujúci šetrič obrazovky aký vôbec existuje. Iba si skúste predstaviť všetky tie farby pohybujúc sa okolo. ++ Gotovo drugi najbolj psihadelični ohranjevalnik zaslona na svetu. Samo predstavljajte si vse te barve, ki letijo naokrog. ++ Troligen den näst mest psykedeliska skärmsläckaren som existerar. Bara tänk dig alla färgerna som rör på sig. ++ Эҳтимол аст, ки имрӯз дар тамоми ҷаҳон ин пардаи экран ҷои дуюмро мегирад. Танҳо тасаввур кунед, ки чӣ қадар зебо ҳамаи рангҳояш бозӣ мекунанд. ++ Muhtemelen insanı hayallere sürükleyen en iyi ikinci ekran koruyucu. Ekranda dolaşan tüm renkleri seyretmeye çalışın. ++ Напевно, друга серед найбільш психоделічних заставок. Лише уявіть усі ці переливи кольорів. ++ Đây có thể là trình bảo vệ màn hình gây ảo giác mạnh thứ hai tại thời điểm này. Hãy thử xem các hình ảnh tạo nên từ các màu sắc di chuyển khắp nơi ++ 或许是排名第二的迷幻效果屏幕保护程序。你将看到所有颜色满处乱飞。 ++ 可能是現存第二最夢幻的螢幕保護程式。快來嘗試想像一下所有移動中的色彩變化。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.stellar/icon.png b/addons/screensaver.gles.stellar/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..a6784afc53d95a655742f9b7db247471fc52a105 +GIT binary patch +literal 5657 +zcmd5=%_yf)hI}rNdW+$&`^i!0RZ0Z5f2~+-G*^$ +zdC}XzSS?I;T#Z?V*$oLUxq6 +zE9lIcr+wgK*+sd{`L^(P-8a3lYQ&E}UA|67z<}ug9WVyQrWc4}FGAmYqBl>1bONzv +zC+?Ez!vf2~`U3PpH94L~S5!~e3>{ftnwqYDHkO#%!3Eds-f-vU<#x3ok^P!#c&&Mj +zzqU{)hEWAAwchi(#n$&f83OU#4u794xU3pF;=hiq3z=Iyzy>gw6Z9jc|#L>RDEfDP^{ +zw1VZPJzaiK3d}>fS&jI4kUS-TdMLJX#O%vmQUu7;ka*&oPz;Dus2GWytedNb0VVFo +z=kC>iea=I}ER0DJ)^vpcb6$-b?rJ8LX9^5>nJ}Xg6!55(@FZlJA9&Z2c +z!+;}TZ4V{di+qq?Xf=8;-O}LTGYj|nvT$g|IzXn0C-KCg_?NN3#>vI=#XWhw?Wi^+ +z^5c(n?^!b~o5{zi??H}^N`*^@ANh^k1$*V8eb%ysgxv^$Gs<9_i2oVtX{VnGo`hq+ +zylhDS*9eiVK!Mjpe5VF{IPTn9Mgq4AI)Ep>o|344+WxA@`KN8z(B22(wE%zr&1Wb(!JYd`bl)I`2oCbOeV)*7eJt@Rok8|jq%ZHWu5Ak2x( +z`UFt5tE>DaycfyOpHB3v>FWnYB4&^~-QE=wrbh62 +zn@A$`0LoZf#ctGs9~hCsirP#OM22xhr~DjQh$2s$IAh95$xVO& +zcI->QTatShXtbcLfgS3SfEPF^93rtz6YI-*0?-UuSjH{Z8 +z>at!RLM1%!4T?6mr+tW3;$0ZF^9h1MSU+qSkfN+qVan0pj3C9$(Z +zjg$p*`xnG=-UpXTg`QTr$bZ+KkmkjM7f<<(oJvf&LnN6o5O;~iCm}~b@LEPWSb~QN +zJvrf{&fR@?rCsTVW+tuPtR{j_|4_OdieB5wpOErln*d&^`xYqJB}54VP*d3 +z&)HR_0%}>q-`}5IKKOF?%tuz&P=uHyk2`%>v1o6vPOEdVi%Kw@Nh +zsjWuVK={$ASC{xw0)zYuzvdKk^U%<6W5MG3WD#Ejd`MLp9;CT{9CUmC2jO!ymsF@> +zEJt^3H~ZaVHI7i*i^D?A^p=+9^>{;x7xfK)b&!IRtzcI_RMEO>f}0;4fI<;(ly1&N$3` +z-lic`n(t!wdUcV5JB2Ggdf&nj!kCklV<1M7J})(5`kK99*4W%!E?~c>2~v?P3~@C^ +zlX#f*?4#Xl7f;*0*W9*Ap;Hk+8EhNdv&>DKEVtG>FH{2TPBet|=osjln*M%-LGu2z +zL6!@uFSC7y!qJ0oM~konMa2pq-U#1Mp!gd_SWhtcc~8c~oTsDdcMQ?2n~~swL^X!1 +zU11*XYJom55TMsw%_BXl>M{}2WD-1$=>I;lpg%S*dMmaX&mWYf)OX8wAK-SRl0BBP +zzA@l068Eb=Je9%tc+6~qLwaHz#^ta7gMzMGf#fH4fLLsE5pRxwC2(Mzkx5C +zw7vTiDbg1x93}BMYY{lp9EWlJymk`-D?Ba)BQ@35Zb40#md}y7xw&?h46NCd_GU-K +zGI~0z+h?G82a$RIW$drvbmGF!xHz=yk>lgp$C4bf5naT>bUzfw1ow%)-r>PKoE9&}$SiH|ip)kt +z;9-&()<{0ja4c^nGqS!$e$9FYSWnjAN}suVph5bo_MONsLq)<;i7%VV7Q}SCuAH%d +zLMNI{m@*=+WwbE;v7kzShVaF25xR7xjPwUtI0G~gn +z)vub}A?$;;u$@>@qWUID4EfMbSJ~S<9##^~>E0UgzwDtmQB>KgKoZAQcw_K(e7vcq +zAA7nD>s5sh!>rjK9pa~8^1;Z=yzbSpAbkkHfEcxOJG3z+EaTK?Zugxnoo=pt88IRB +zXqvOYzUEJJ`affS{VZyCta=bM;-fvk!OecIa2$I<`9PXsUL-1va +znVb_V!RY8z_|?}$RmTLdcr4+t_)jMmam~}=)=*0G5i;mb3z(sIDqT#g^%Ni&E%1^D +zxmd*BDX1hwOAMqQ53VV{l$S%))EB}$4@SA~I-!oT#l{MVq=`x0^J*IAm&Bj#lmoks +zsV3eYGvXiAJ>LhsR?z0xok{K}D)7F!cKRJEn;w2ma^s(W&8C&fUJ#wIu}K~9{;iJ` +zH7V+;&Y07SBe>e*SRwOfDaLdW{3^W~N-9ey+i^AYPtSZ%MR5$%^s!g*9}f92+4qdU +zez3N;p8D=)dq_%2<#NPf2#I<+J+C|eXf$>91vam*um4Wbhle2)I7PA;|LpHiEyS2+ +z=j4oqCV!Td)_@;X4_U4Oj#b?X%r!MNt5P24S5Hr-&PB2^I~EDQrzJ+LQ&5`Il-XqA +zuPV&m*P{AVpREo2^EpZEM`;L!95dy8$Mhr>ZR`JAw+l%=9y=oc`d5Sq#zg$6@4gW{ +z2J=(+Iw<&DyGE3XZv*u-;i2_K*ra6KfXziFGQ=tdW*-Hc?S!T +z(NpC~VI@4sDC&1sExFsz464|E@h0e$ua0-Dt!X(IIl9ep#S#4 +ziX_7C_Rwm6c+sOxLET(7w&Mi~12b1084)Wtt!@OS^rGpGU|KAwfC_4UJLiEX- +zP`(_BpzXDZiIo+7*@&FrpGQMaqM;1=LM!ADmdGOXw>T%bmFXZD(eQ@JJ|fnb5VLu5 +zb`{27Qz|WDnf1K0Rd@c|MnmaMfcVQ*h%NeMy||&xOt^)Gq&t%=ToEASU8UE@Lw({m +z4XkPQtA}WH?{uD +zu}%YCK0+eEf^RhsA38sOxh^Q36O9&O_Cq5^pCX91hLi|sfAi6d|0(@-?p7Gol(9%!s +zvY~TS4YaVaeOvM}tuHPtaoMo1d>ro9JuIGDBm`C*K@G{@^;9WeMbmm--&IwXc%;Q$ +zCfQs-`80gFaeusrHtBSLqpqfoERlkOa_VBcQcsNF&|l$_YZ`k9)Q7EWFEuUO?>RO8 +zZc#P#_4PHvz~AcWb!587$e10A4Am*-kP}$Z20e7PzEV4`&8RkGm)84!64;uwgc!_h$W6()k +z+XeP?;6rc!)b!Lki}m?P#=3eRH;9~%wr0n7NdmW7>EG|!)PRA-6JV?TPd&Z!P+q~_nc0`O(Gln;7?+~vWa +z9EAJ&$1D-bYbAvTRQDr-{^X$gl!lh&9{p#HlQ&zi> +z%d#}SnT(Bm+UwCf5|9O2kMo-~vY0D>&1azzOQK4JoWg7bqhL_-6O>^_qJ-&7T_GMj +z&{d}|SV4R#g$6OCj9Guk9IafN*Omq1tb70J6fDI@qR+Q5DJ(XTrAhV<9 +zS$!p$kqdI#O=pMB`T#}l9RoIvVqD6&1d2=@kM+LQ715}8Bn(JQkX0{`V9(zx1fvQ; +zLG|V1HwOHSWI;D)2(NeGt2)&jro$XR0{L1zP= +z(Vzk#3)E)mYu99*qIUeQ{2mxFoJ<6K!`!b51|E~bO{oc%jQ*Z=cD0+mi(C`MMT0y& +zDC-@3JN>5bmJk&HW~BF-+Jur!@-Eek-Yssfek=jz-{kztOH>tKV9wm-0h^W%l+UX#F1wq)~lB}t= +z?q*_bk5um3PfOJ!l*tAZcCqlvt&{XP5Vt*Dr5W_LD%_^7-s +zYA0b$eB?hfI~#Po8zht-#UVXAX*l`+i-JObQMW$o3SDZ)@RXJgyF8tlnI4wEi5^(n`yI&J!$OQ-?PPl&1onO?v7%w5DiNX?gHkZcFcyYdis#Jjc`uhBPF|)X_QRaG8pMk^SK6`ZccI4)=xw!1i +zgz-@$tZ{jd87k=-{S*C-SaKmZ^VjTRn9Nd6`EXgh;Hf}{FzM?g +zQ=$AGrF&jWLqkLJmzUVp0jp1^ai;^}eU!p4jI0J`f~*5HOc;F&IvYRsG4^m0jOL)A +zRzwL2I@pk)gCw~u#t2+~&tc|m;!H{Xgt0<{7d8$V3HA3}_jk8s!>{#C0KRMe=h{zV#)M?A0%Nm +zm&YzUE+WEh_9|U*&NO~Ke{@A2%}T>8i@f`pnt(gyG%PBKrhY_T+BHC6WcqEx{7A;z +z!JzAw{%qkFuVfj$UR0DNoQpDo@6guWeIeL7$5@_ViJ7L@QfuK_9?h7|m7Sum|1xw| +zSCZ@QKgM4sg>jwMZc%F86Au{a1L|LVn>HC*+q0CCx?6qOepVeaq2!F04`EgE@DOH= +ztoPuL5&g(SFdDs-{<=h^^5jAm+JafPKiMVei8_xQmkNmgH48Lsw>#-wc@0Jer +zmJP=mO)18Ia~P(_NLrvl{q-J=*5!rwdg<}h<>eh$R%X@^HdC(F{oR=Z*%>B3L3VE= +z*f^ymXhlBDyly0ag~=I<7}SRt|^E{(nylbLBVkn|D0 +zj%fwa9nNK)bt=O*@!_fHIRECsLEasi83=a>2*d&wwy@At#D6?cQct0p1dtrO6D)D& +ztMQTMk9MI>yywmJyhdg#D~fN|%#VmACR!=EVLDieC+0uZ5(H5CpM>|;SqpFnC>g0) +V_ay9mdAsWcG*q;qwMtfz{|8C@VfFw3 + +literal 0 +HcmV?d00001 + +diff --git a/addons/screensaver.gles.warp/addon.xml b/addons/screensaver.gles.warp/addon.xml +new file mode 100644 +index 0000000..b39c5f6 +--- /dev/null ++++ b/addons/screensaver.gles.warp/addon.xml +@@ -0,0 +1,119 @@ ++ ++ ++ ++ ++ ++ ++ ++ Omtrent so psigedelies soos sluimerskerm kan kom ++ حول الحصول على مهدء كشاشة التوقف ++ Падобны на псіхадэлічны ахоўнік экрану ++ Колкото халюциногенен може да бъде един скрийнсейвър ++ Quant al més psicodèlic dels estalvis de pantalla ++ Nejdivočejší šetřič obrazovky všech dob ++ Mor seicadelig ag y mae modd bod ++ Omtrent så psykedelisk som en pauseskærm kan blive. ++ So psychedelisch wie ein Bildschirmschoner nur sein kann ++ Όσο πιο ψυχεδελική μπορεί να είναι μία προφύλαξη οθόνης ++ Screenbending screensaver ++ About as psychedelic as screensavers get ++ About as psychedelic as screensavers get ++ About as psychedelic as screensavers get ++ El más psicodélico de los salvapantallas ++ Tan psicodélico como un protector de pantalla pueda serlo ++ Tan psicodélico como cualquier protector de pantalla debería ++ Nii psühhedeelne kui üks ekraanisäästja olla saab ++ Pantaila-babesleetatik psikodelikoena ++ Mahdollisesti kaikkein psykedeelisin näytönsäästäjä ++ Difficilement plus psychédélique comme économiseur d'écran ++ Il y a pas d'économiseur d'écran plus psychédélique ++ Máis ou menos tan psicodélico como o pode ser un protector de pantalla ++ זהו שומר המסך הפסיכדלי ביותר שיכול להיות ++ Psihodeličan koliko čuvar zaslona može biti ++ A legpszihedelikusabb képernyővédő ++ Sepsikedelik mungkin dari sebuah screensaver ++ Eins geggjuð og skjáhvíla getur orðið ++ Quanto di più psichedelico possa essere un salvaschermo ++ スクリーンセーバーはここまでサイケになれる ++ 싸이키델릭 화면보호기 ++ Psihodelinė užsklanda nunešanti stoga ++ Cik nu vien psihodēlisks ekrānsaudzētājs var būt ++ Најпсиходелична заштита на екран ++ Een meer psychedelische schermbeveiliging vindt u niet ++ Så psykadelisk som en skjermsparer kan bli ++ Tak psychodeliczny jak tylko się da ++ Um protector de ecrã mais psicadélico do que este? Impossível. ++ Protetor de Tela Psicodélico ++ Un protector ecran cât se poate de năucitor ++ Самая психоделическая в мире заставка ++ Ungefär så psykedelisk som en skärmsläckare kan bli ++ Tak psychodelický ako to len ide ++ Najbolj psihadelični ohranjevalnik zaslona ++ Ungefär så psykedelisk som en skärmsläckare kan bli ++ Дар тамоми ҷаҳон ин пардаи экран аз ҳама беҳтарин аст ++ İnsanı hayallere sürükleyen bir ekran koruyucu ++ Настільки психоделічна наскільки можливо для заставки ++ Tạo ra ảo giác mạnh nhất mà trình bảo vệ màn hình có thể có được ++ 最具迷幻效果的屏幕保护程序 ++ 最具夢幻效果的螢幕保護程式 ++ Die is omtrent so psigedelies soos sluimerskerm kan kom. mogumbo het gedink sy Plasma beskermer was heel voor in die koor, maar die een sal jou maag selfs meer laat draai. Jy beter een van daardie vlug siekte sakke kry voor jy te lank na hierdie een staar. ++ هذا حول الحصول على مهدء كشاشة التوقف. اعتقد موغمبو أن شاشة توقف البلازمة خاصته في قمة الجدول, لكن هذا مقرف أكثر. الأفضل أن تجد أحد أكياس الغثيان قبل أن تنظر لهذا لوقت طويل. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ Точно колкото може един скрийнсейвър. mogumbo смяташе, че неговият "Plasma saver" е върхът, но този е по-смущаващ. Препоръчвам Ви да вземете една торбичка/леген, преди да зазяпате в скрийнсейвъра по-дълго отколкото трябва. ++ Aquest és probablement el més psicodèlic dels estalvis de pantalla. mogumbo va pensar que el seu estalvi Plasma estava al capdamunt, però aquest és més nauseabund. Serà millor que agafis una bossa per als marejos si has d'estar molta estona mirant-lo. ++ Asi nejdivočejší šetřič obrazovky všech dob. Použití plazmového šetřiče bývalo vrcholem, ale tento spořič je ještě více zneklidňující. Připravte si pytlíky na zvracení pokud se jej rozhodnete sledovat příliš dlouho. ++ Mor seicadelig ag y mae modd bod. Roedd mogumbo'n meddwl fod ei arbedwr Plasma ar frig y rhestr, ond mae hwn hyd yn oed yn fwy troëdig. Gwell dod o hyd i fag salwch cyn edrych ar hwn yn rhy hir. ++ Dette er omtrent så psykedelisk som en pauseskærm kan blive. Mogumbo troede hans Plasma-pauseskærm var i toppen af skalaen, men denne er endnu mere kvalmende. Du må hellere finde en papirpose, inden du kigger alt for længe på denne. ++ In etwa so ​​psychedelisch wie ein Bildschirmschoner nur sein kann. mogumbo dachte, sein Plasma-Bildschirmschoner wäre bereits abstoßend, aber dieser hier ist noch verabscheuenswürdiger. Kram' besser schon mal eine Kotztüte hervor, bevor Du diesen Bildschirmschoner zu lange anstarrst. ++ Αυτή είναι η πιο ψυχεδελική προφύλαξη οθόνης που υπάρχει. Ο mogumbo νόμιζε ότι η Plasma προφ. οθόνης του ήταν η κορυφαία, αλλά αυτή είναι ακόμα πιο μπερδεμένη. Καλύτερα να βρείτε μία από εκείνες τις σακούλες για τη ναυτία προτού την κοιτάξετε για πολλή ώρα. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ Este es probablemente el más psicodélico de los salvapantallas. Mogumbo -el autor- pensó que su protector 'Plasma' estaba en lo más alto, pero éste es más repugnante. Será mejor que cojas una bolsa para los mareos si vas a estar mucho tiempo viéndolo. ++ Este es probablemente el más psicodélico de los protectores de pantalla. mogumbo pensó que su protector de Plasma estaba en lo mas alto, pero éste es más repugnante. Será mejor que busques una bolsa para los mareos si vas a estar mucho tiempo viéndolo. ++ Esto es tan psicodélico como un protector de pantalla debe ser, mogumbo pensó que su protector Plasma estaba en la cima del mundo, pero éste es aún más nauseabundo. Deberías conseguir una bolsa para mareos antes de quedarte observando por mucho tiempo. ++ See on nii psühhedeelne kui üks ekraanisäästja olla saab. mogumbo arvas, et tema Plasma säästja oli tippude tipp, aga see on isegi rohkem iiveldama ajav. Parem otsi endale üks neist lennuki oksekottidest enne kui liiga kauaks seda siin vaatama jääd. ++ Hau ziurrenik inoiz sortu den pantaila-babesle psikodelikoena da. Mogunbo sortzaileak bere Plasma babeslea garaiena zuela uste zuen baina hau oraindik nazkagarriago da. Ikusten denbora asko egon behar bazara hobe zorabiorako poltsa bat edukitzea. ++ Tämä on mahdollisesti niin psykedeelinen kuin vain näytönsäästäjä voi olla. mogumbo luuli, että hänen Plasma-näytönäästäjänsä oli asteikon huipulla, mutta tämä ohittaa senkin. Oksennuspussin hakeminen on suositeltavaa ennen pitkäaikaista tuijottamista. ++ En terme d'économiseur, on fait difficilement plus psychédélique. Mogumbo pensait son économiseur Plasma tout en haut de l'échelle mais, celui-ci donne encore plus la nausée. Mieux vaut se munir d'un de ces sachets pour le mal de l'air avant de le regarder trop longtemps. ++ On fait difficilement plus psychédélique comme économiseur d'écran. mogumbo pensait que son économiseur Plasma était tout en haut de l'échelle mais, celui-ci donne encore plus la nausée. Vous devriez trouver un de ces sacs pour le mal de l'air avant de le fixer trop longtemps. ++ Este é máis ou menos tan psicodélico como pode selo un protector de pantalla. mogumbo pensou que o seu protector de pantalla Plasma era do mello, pero este é aínda máis mareante. Será mellor que colla unha bolsa contra o mareo antes de quedar pampo mirando para el. ++ זהו שומר מסך הכי פסיכדלי שניתן להיות. mogumbo חשב ששומר מסך הפלזמה שלו הגיע לראש הטבלה, אך שומר זה יגרום לתחושת סחרחורת גדולה יותר. מוטב להצטייד במספר שקיות הקאה בטרם בהיה ממושכת. ++ Psihodeličan koliko čuvar zaslona može biti. Mogumbo kroz svoj plazma čuvar zaslona je bio vrh, ali od ovog vam je još više loše. Bilo bi vam bolje da pronađete jednu od onih vrećica za mučninu što dijele u avionima prije nego počnete zuriti u ovaj. ++ Ez a legpszihedelikusabb képernyővédő. mogumbo úgy gondolta, hogy a Plasma képernyővédő van a lista tetején,de ez még inkább kábító. Jobb ha keresel egy légibetegség zacskót mielőtt túl sokáig néznéd a képernyőt. ++ Ini adalah sepsikedelik mungkin dari sebuah screensaver. mogumbo mengira Plasma savernya berada di puncak, Tapi ini bahkan lebih memabukkan. Anda sebaiknya mencari kantung mabuk terlebih dahulu sebelum menatapnya terlalu lama. ++ Þetta er líklega eins geggjað og skjáhvílur geta orðið. mogumbo hélt að Plasma skjáhvílan væri á toppnum, en þessi gerir þig meira flökurt. Best fyrir þig að redda þér ælupoka áður en þú starir á þetta í einhvern tíma. ++ Questo è quanto di più psichedelico possa essere un salvaschermo. mogumbo pensava che il suo salvaschermo 'Plasma' fosse al massimo della psichedelicità, ma questo è anche più nauseante. Faresti meglio a cercare uno di quei sacchetti per il mal d'aria prima di fissarlo troppo a lungo. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ 싸이키델릭한 화면보호기입니다. 거의 토나올 정도의 화면보호기로 오래 쳐다보려면 봉투를 준비하는것이 좋을겁니다. ++ Tai stogą nunešanti psichodelinė užsklanda. Mogumbo galvojo, kad jo Plasma užsklandos niekas neperšoks, tačiau ši užsklanda tai kažkas tokio. Geriau susiraskite vieną iš tų lėktuvo maišelių, jei supykintų, prieš spoksant į tai per ilgai.. ++ Ekrānsaudzētājs nevarētu būt vēl vairāk psihodēlisks. mogumbo domāja, ka viņa "Plasma saver" bija saraksta augšgalā, bet šis ir vēl šķebinošāks. Labāk apsēdies un sameklē kādu maisņu nelabai dūšai pirms skaties šo pārāk ilgi. ++ This is about as psychedelic as screensavers get. mogumbo thought his Plasma saver was at the top of the scale, but this one is even more nauseating. You'd better find one of those air sickness bags before you stare at this one for too long. ++ Ongetwijfeld de meest psychedelische screensaver. mogumbo dacht dat zijn Plasmascreensaver al bovenaan deze lijst stond, maar deze is nóg meer misselijkmakend. Houd uw braakzakje bij de hand, mocht u hier te lang naar staren. ++ Dette er så psykadelisk som en skjermsparer kan bli. Mogumbo trodde hans Plasma skjermsparer var på toppen av skalaen, men denne er enda mer kvalmende. Du bør skaffe deg en sånn spypose som de deler ut på fly før du stirrer på denne for lenge. ++ Tak psychodeliczny wygaszacz jak tylko się da. Lepiej zaopatrz się w worki na chorobę lokomocyjną. ++ Provavelmente o protector de ecrã mais psicadélico de sempre. O autor, mogumbo, julgava que a sua proteção 'Plasma' estava no topo da escala, mas este é ainda mais repugnante. É melhor encontrar um desses sacos de enjoo antes de ficar pregado nele durante muito tempo. ++ Esta é provavelmente a proteção de tela mais psicodélica de todos os tempos. O mogumbo, pensou que a sua proteção de tela 'Plasma' estava no topo da escala de proteções nauseantes mas esta parece ainda pior. Procure um saco de enjoo e sente-se, se vai ficar muito tempo a olhar para a tela. ++ Acesta este un screensaver cât se poate de năucitor. mogumbo credea că screensaverul creat de el, Plasma este pe primul loc, dar acest screensaver este și mai amețitor. Ar trebui să căutați o pungă să nu vi se facă rău înainte de a vă uita la acesta prea mult. ++ Самая психоделическая в мире заставка. mogumbo считал, что никто не сможет достичь эффекта его заставки Plasma, но от этой заставки укачивает ещё сильнее. Если будете смотреть на эту заставку слишком долго, вам очень скоро понадобится гигиенический пакет. ++ Det här är ungefär så psykedelisk skärmsläckare kan bli. mogumbo trodde hans plasma-skärmsläckare var toppen på skalan, men denna är till och med ännu mer kväljande. Du gör bäst i att leta upp en åksjukepåse innan du stirrar på denna för länge. ++ Tento šetrič je tak psychodelický ako to len ide. Mogumbo myslel, že Plasma šetrič je na vrchole rebríčka, ale tento je ešte viac zvrátený. Radšej si nájdite hygienické vrecko skôr než naň budete civieť pridlho. ++ Težko bi si zamislili bolj psihadeličen ohranjevalnik zaslona. mogumbo je menil, da je njegov ohranjevalnik Plasma na vrhu, to da ta še bolj vzbuja slabost. Bolje, da najdete eno izmed tistih vrečk za bruhanje, preden predolgo strmite vanj. ++ Detta är ungefär så psykedelisk som en skärmsläckare kan bli. mogumbo trodde att hans Plasma Saver var toppen på skalan, men denna gör dig ännu mer illamående. Det är nog bäst att du letar upp en påse för flygsjuka innan du sätter dig ned och stirrar på denna för länge. ++ Дар тамоми ҷаҳон ин пардаи экран аз ҳама беҳтарин буда дар рейтинги пардаҳои экран ҷои якумро бо пардаи плазмаи худ гирифт. Вақте ки истифодаи ин пардаи экранро сар мекунед, аз истифодаи он ҳеҷ гоҳ рад намекунед. ++ Bu, insanı hayallere sürükleyen bir ekran koruyucudur. mogumbo kendisine ait bu Plazma ekran koruyucunun skalanın en üstünde olduğunu düşünüyor, ancak daha ziyade insanın içini kaldırıyor. Bu ekran koruyucuyu uzun süre seyretmeden önce mide bulantınız için gerekli önlemleri almanız iyi olur. ++ Сама психоделічна в світі заставка. mogumbo вважав, що ніхто не зможе досягти ефекту його заставки плазми, але від цієї заставки заколисує ще сильніше. Якщо будете дивитися на цю заставку занадто довго, вам дуже скоро знадобиться гігієнічний пакет. ++ Chú trọng để tạo ra ảo giác mạnh nhất mà trình bảo vệ màn hình có thể có được. Mogumbo từng nghĩ trình bảo vệ Plasma của mình đã đỉnh, nhưng trình này còn kinh khủng hơn. Tốt hơn hết là bạn nên chuẩn bị một túi chống nôn cho mình trước khi bắt đầu nhìn vào nó quá lâu ++ 这大概是最具迷幻效果的屏幕保护程序了。mogumbo 以为他的 Plasma 屏保已经是数一数二了,但这个更令人犯晕。如果你要长时间盯视它最好先准备一个晕机袋。 ++ 這大概是最具夢幻效果的屏幕保護程序了。 mogumbo以為他的電漿螢幕保護程式已經是數一數二了,但這個更令人頭昏腦脹。如果你要長時間盯視它最好先準備一個夠用的暈機嘔吐袋。 ++ all ++ ++ +diff --git a/addons/screensaver.gles.warp/icon.png b/addons/screensaver.gles.warp/icon.png +new file mode 100644 +index 0000000000000000000000000000000000000000..cc2beea958a46bf3d9ecec1a3205be641b1b4555 +GIT binary patch +literal 9424 +zcmdUVRajg>v+ZCL1`qBG5+EeN;6Voq9$bSvK?4MLCj@tw5Znd{gy8NLY;bpXhco|q +zyASui+?R8ndVhO&clB4jt7_G%`mU@fjg3K$0RRB7Wo0B)0RSY#BN6}|88J-aK{*fu +z*|(3{-_#r|zPTAYnFGYk98Ao?vUbLn=Bnn#W*&|M=0X4fgOjYJn7aG?p*~1keWx+o +z_$yNAn@?RVR-&Jhkd9k=Dag*%qvRy>ne7NwRlFwsuQd~DQW>rFem1b=axg|&C1)5- +z)s?J9AjQw`fbwOnope4$<_6N)m}#gOAA5~Loj;6XK~S)`+HVS}!knKka{MfoZyuIU +zpczvOmUY3Rq@}RDDt}RAFrEwm6&d6&3P!?1X8<4vpo)TH0qCgsfPnwWAOBzHhR7Jp +z8+HIfK37;c{8D}EL&4xLHhRvMyx~Ja4)%xz09iJ!=Gfm)=)8gH@zv +zQO^fKtc@hqXzMzx(@YJpPVkj176ZU0uQhe%{^X6&G!OgZd3!s6N0*_;FaGfnIeH{= +zhYEGJRN@z2kO}Fa92iME@&0qok8!rggZ=&e?QLRG!rkNEj-{-Jh69m|j0|}>xl=}V +z_O`}?#=2jGR$sov&CB%cDqu+{gH#=ICb~b$tG2bY=(}q)G>NQ}qoc01i9%YHT(xv` +zKpLW$Xm@vdmAiOBQNDqs*8dR}d5?U7G%HOF(gZ@O$oF@4ERQ)hx3;!Q)zR+I3R2|r +zkQ7mQLz5tcW}?V2@YTZUN#a{2$@hAsgoINs5~bzkswGYr=NDsHf<;xR)#NgOU=e0# +zmtv^%cI57^)y=W34-}9jK^&Xqb9Zho2BPvDPo4=<1u+0>YYmI-#XK$C%fs&P`PXFb +z<1!C3lXV+xZMo^jl@JpGL5G&z4jUyeyZNU01o-zIyEphbj(6au++2UHfT(C5as^H> +zQtIqAEOupP#=^m}!EC^Rj*iZAt~NhE|G87Q!QPm}=lQLioLn@e?AXA-Ys$DNgGL2p +zFlnXRoVQ5dQ++*0Oth?w45^LD>Z{qK!^6X)qcB{WXstAbnIpzepFRywHq_TIxB5_Y +z?h+U#CSR+#y5i(uaT_gL;U)Gn0G!i&X|KmJIZU?(iJTf2Q%5>nNJvPOX{t;ED0Gq{`VxwZ2$4Nb{)+dI<$>zZH^cypFiLW>*^5m#jxjr%gxL`RdIYoZn-g;J6 +z#T*MF!xCV7A0J`nAI!_9>vUg4U803@F=SrrPhad-8zMBWATK{OaHsb!07s2mlTgLYDJib2qGDosBcg0rG5{Y&K*!}m6lK~J)q}BoZzLHCacA=4AIJO@V2dR`(tHpp +zxNSLdt+u>;s-=V~B;b0yLsS-x)6$aUr-LDJtDRj{^LY`Qq8(t(+sCJ+xf$=O%Af^f +z`|3U52LI-GNuo2LsBbw>%FWG9(>He?Qj$~c>+8HT+A=xsnRgqw{dlOzHbaYqWpQm2 +z2sOM?%n@n%@#g_<8WTmyUsGOwIRD#*IIk6_{dRtSetUcSHN8}OJS|gQeSJDNWV3o8 +zf$3dR$H$%?=+k9F>a%LuEC7@n10TD93VHjQnVFGX2yOI61x@~OKQob+|DoZ72gy$A +zDPC%6X^F#zcbA|FdFJOoh1YPtmX^scUHLTLRuCB7t(XtaiHm +zbiJBdvX+jQ9Q^r!8F|Y|Lt6y}1yNB^DB|!{pHH8#dn4mEP|_2tVAGR%dGCqZ<*Pm6 +z)<<}tTy~6=>w2x{%c5%2KG$B~TMRh0&DTdpAJKlIZ0hCS>1m>P$d?G>5~F_`F(f2J +zE024HJPWk=qE*bDaHwiF4hK!OVDY)3AsaZ%n6Us^lL#!k{bZOu +zJ&#zx-q|+u_&D}r%VXuMd=*W~v3|Zaq-k>>)!pKCW53)CLi*Fxl<}De6%7py2;AJ> +z{#-=$(<|s&52+jwuK(KRRFY3xTKYrSJFQBrblfO)Wdj2?5#s@OZ12m7Fbuz!`iDgY +z$EIx@fVE9HW+IZOq;Fzd^PLJaVVhy&zxG*{guB~Yy}#eSxN +zg~ifJNJwDM(++JT;fpGDLHRD`vhipvPq*K+wzis^o8O$Q&?FiHC?~Q6-HgsY3EM`h +zuO2+?@~wDxEzp+mSRt;k?6i$r;B#A4QIVyoY5s4j{r!uR4)tp;Fo#pEL{AT&!!tu` +zetrSBD39pazM&bw1g@#?Jp%cCAWOwq23B!AMvX8N&Zq+c@SA +z2dC +z5FMn#%fqAp=d|Va@1XCsI0Hbf1=nq0h#vZK_k+E)cm?QU9K&8qo}Mb?QBzh{CRb3C +z2;4m$XS4y#d9HP$-P_Rk-mcBhf4)yvKx?w_+!@s;SF<;r%pnIOU5cU{0jr#)kL0(D +z8pva>8-V@DX@`E*wlWZg^U?+F7+uo8DIq3&9tkLzn7DSmeu_nv0WkK1waLm){C0;p +z5?+6<+2pf6`i5r?z^u)Y6@9S}JB-)4j~EUJ4@dX%^7@_j9|5~q@|g>1IA3J8EHfOLzf|!T#HLf-ZWQlFwGpvzG9#= +zyqJQ($LLdhVL%yx6a&(;pO_c}0JA+R!>y3Ky@q_(3?qCTH&*b2%&-S@BeotaD-&Gs#KL!Hbo#3EuqGb(Zk0ESmuS{i&{Dgz)M1bjmucIqD+<2%4E +zkOeG}04ggh5wGa_hla{ZD&wrh$l5tMbLj!e;`0G0sz>>|1IRi*0m^DfMjV^lrEs-B +zjeX-8N5~%dqAB>R>?pkML_!_qf7Dgu?MG3<&l-E=pI?~fIdc~gf}u^Ou-0a%qNCI3I9Z6W-a#`?;+K)Xf(uBJ +zZnfFOKSo1N{%$bh?O(^@;fub|va>r(7LMp0S{^oVINUZ!A(0APDP1H#nc|S`E`}+% +zKbEw#2xlQrIn?ju*VW}q$IQd~ZOu7Lj9$WIfOr=M3g0HmEHp!*{1py+>=TQre>Uzy +z4#^;=&<@EF-*!tKomc;Grlw~4&FXpS_HVi>UfWd!-iX~ +zCZo!?;{Q!^MfuV}aBwu|!dxjj9^eZ%CVz8`9; +zzlxRQdZoxD41e1p)0I%Bir95}YAW!ezP?`QOi)OvZHZcc|A=c|_0TW&BJ%b~txy4J +zBOJ(N*MD_M@PqUEZe5hMgFTGZ*p$y8?JVg +zW{1hd3`}A+^eiH4VKJ=&)w4F-n}tMuR*8BR7Pf!H;9&;GBGB2FP=e4L8n+Suj#pu? +zot$5vjcxDjXw9nED!+(MrO4cmTxc5rkRRr{>Jj*dIG8;=T-(a7FQcZWw$bB5ngY7w +zI*3^_ed_5_%}!rG3{rO!Biakr0K-!f6SIZO2FKXPsYj7d!eo13lvk{#0g{KW?iLVG +zpw_Vq_)ciHrl!Vv?%cedc}Nl&^1-s;W(TEK1E|rVpgx8{VI%dO7@-}Le>QER`ZMzH +zpHgq1M*(zWV-tS8YFzjP1mzbE>LpH%bLbTk)7TV0>48$E>xwouDvpkpjDsB=%VQ4Z +z!AsvNFwOjNcAQ^Y +z+d85AZwIXXR(E#`TwGi@brm6*&t}GEV{{}N7sZ%cT?&03 +zh&vf-AdZn}8XD8AtgKXeDMDWfLte&2{Ym`1G&{X8%>ZYaFR);( +zqbCf1yg{D8-j1jYp-t|auHn1}Hg=shu&81>>+DlgGEYIYI`4?H`|*Q{46W1b1cx=f +z(@YwWmgi+0I_R|X{n0QxEA9y8D<6OFO~>_DYD|PcA``>JenV2;?8O1FIGbw6rdfw7 +z($11AkQfdLYsYo+W)AJ0Yn-_gzWLnik{`-RllJ!Kr&x0&%}EV<`4b-#!$g^H%RR0) +zWIX>SLUC10Mh_s7W-($Omr|_4)C1tvzi-gS&la?wgk3rRaoOGv@EiiEN51!~z>`SmZVCA0_X3%@AwZx`jFZWK|7?f7DUdsr3H>F%kwOsW +z;VFX1NQBp0@Sg7y2u8dp0!7LT!&^~g0iVgfcH@usH~hIcJ3TEfF2)P-tGL(;ep*-4 +zrfIg%^J?ACxvgj$W?ueb;1XT#f@unr;_=ss!jrCQZuUNF?B3{$q2Vx*^ziV2LcfkK +zEHqVCMz>h5t;{615&lj%U2%kKdPNngWJf!Uke6H)qAGk1`KfPHX+*5w_nw0ro29is +zDoU(^k1KC7`!|^Y4(x>s;O6wn)wTWumY{$D4vh$9y!-81*n=GdoWzw?Mv>y#P5|?T +zYIdNZ!OO#=ljnEC?}06+<6rh8lR^t<;kaH6m=xAy$Wz%E{a545Y|Hxrc7l~S_($n> +zC1n0qZu7>l5IX|K$H1shlU4Pv99OJcxp?uFl$5ga5&***D1a1pLt;I=mnWNS9$|}N +zQWBDs=j!L%fjDP)jvv%1*zF}N)Q^LH%PH)zyqwSVC>>(lIcw;1by(#$lFDV=+5Me> +zado6OilVu>8P!!W?Y#TSW~(#jq~*pyZ;^&-^PHx&4Q4Z2SzrHPcXP5q@ikFUkC`pI +z{ieN`nq1&uQ71{87JTr4n15K?*6L9!!XzjU=UMm_b>cl+nML5sLCYlgaFXL2kylf3 +z`ZBIl%SK2dMx=laN0y(seY#oc62A<^-Rf_kQ8nmCCiBlS@?a3w*Vfk8XKfAxwkta8 +zzD(pxYiVdKwRmZD(%e7Yw)asbK(m_sVmJ22#~oUq|H5F(CF;IsJv&=l=1p#G)dx}f +z+8VJr&^PXbQ4t5&*x2Te{6gBPSy^awqp2JOCsb5hXO51>wU$hb3}(M*99>-}|1m#2R!IF9c|4P7)DS%-;i54Xwf!S4$Ulo2G<=WhdWpM_S^B`t +zdNgyStG^f`6&|h_eI6X_j;B>|b&>ntAS)~L!@7U~n?W7A-@Vf1?7!j`ST3GCF{{C5 +z@JAds5IGF9-JEicL +zzR#ybW#bkP(Nyp+fHwa7j(P&7ds8jA*XDYUoH;r$XzOBo4Ek*s5_-S(;_ENWZgBbD +z0GCRD+w1zUC6dHREWfN +zL_-EdyGeSd1AH%?ji>Zgw*2w^hiffuT^2t@@?+CJ6IA% +ziHcze1HZSuUjO(*g`K{&QnvxeJ1XjX$HRF|P03_ol}>GM-vUKerjU#Ea`Rn35qsNX +zO@6{;z1>1JhU5L_0734~_0dAL)~T1Y>OVvxH$e-hp=!C@;<15H+df|}I0Q5oDQ1at +zitX$&2?;Is^-(zZ-VK%XQ&%%K9{so8R>sRgWm +z%0D{Xf=Ta6)Y5EbD}o}3&o~RQjCvW`cK|wKVzlv`x&|sLjt4WW)zYujMml__TKk2> +zJ3TBNO52~0ah^(ND|BO4JrCg=5PVcSE2~WIy|c-*B7MC~vB{~aDRyV)7z;Chz*qF* +z8}HV;H-saogmf;>$=x%c<)4$v1Rlbm<;Y7!5&px&!@Z%QusP!u-v?IGm|_2A1c-~K +z5d?k?x?gCpb8~X-q^>4@)VzI2NlG!cm5#9hcZu>wVMocQuu5!H=+;w;c;6-{;izF7 +zJ*R=6<;oHh3AMl0-|kPB3Dk1Gm%d?rIP2o$;Q?*$3?>cn&SwyO;{&}7D7#(@Bg6yX +z{%oi73qkH^%4R5bO!8D!5rs +zgf{wi_n9f_FNk|M?2yIUUk{6-lBPvmt5Xk>!921>6bQudLo)|lWPr0>AS<%61GfB} +z{t(u#)&2c>ErR^WCq&E-oE4|Oz1@fr9FBQi1Z|gx0O@UMpuV<1`r6+gL$-bQox5Foh^ce8MfRgj`<~rGgTq2S_UNl1|k9lDlWtz06w-@x8(41NYmAJUWTPZf&NG^BgC7fl>8#Mev!n?QQ +z4~~wGN@1Z9X)N|wZETd4`*WGNft2@>t8MOQbh_bnwN6_nHV6CgPufka0J!oN4o(W& +z6SKi@Q)&EN^yL^TKAe%&+O>^@+`UagUtU?CvoM-JonUVyEl_u_?b2Tjcyfqc>aE-I +z+>cbB(~X!Aja4>oM(&^u1o!BA2v>m-T7QLnf;|AQV+3tQ;EA7$Tru +zp!&wqTPg1Rj2abrLWPXJTh6_!*7NFz)!mG)7oJTTrey{_g+h*qPe)(~99H}XeVtGf +z$q&I~_Xq|~zkZr4=KuR{nsQ@nvak*YlUYQuti!;-+qhfr4ILN-gNvfuqYIAM*dD|I6V(1N831HE3Ib9X&{cIVzu$4EF-$!^F!mdZK +z&W(@R2^}0<&j;ntK@|~K9%mm@g7CP_x&3ae-Gd$`OiWEbclfX|1?#jZ9 +zGQ{-Uw&n3jg(QdiK$7PGyFaDXU?Hcv-5-~CEwyCNJ>(l;g +z%P-aQ5BGsiSwEN2eJ9HeR@LNoLM`BJ)fI|;dd8%by(#2ltYU4=viKMQ*VYDCTF1+Y +zysXm<$jXj)MgRJR3w?y}^75Lji5s^Y`rd6FFEyPkH@(}!wF^3?mx^q62Q&1a819S- +z3JQLdloUm=`abBjP=A!$nvt;}=ymhcZ!Ou~EMV9^m=qT;rtNaz~O;(NJto#B$iQ_an{ZKnUJZU +z#^Gnx92`bM>qR%kDt_9((?5M+xdlKuwv7npysYfqp@?R6AX0|m8m;Y*WnR1G_l2$B*FFtq))fj(FW2dl +zQ3`oo+m8M)+z2PiRrWtKH`iKNmKRCxUdRpNf6xz}0R$gOF>IW~G3 +zA7{~J35keIg|Cy+JTN>Qju#u<5h0uKmo)#6r{3;f|KF>^W*|S8ie^f6V36O-%F9SJ +zWHgJ*a!l9DogyE&*Wo@zTb$})*zJQ1=d!<6OVZU-kF>oWmtfn{W5QPWr@E#C3L;N# +zV~CFvb-v+AGegi^w|we?Z`D;)0)!x*msV#W@z{Pb6 +zT_GD%rCmHQ@HV^&OliW3Yy(pT`JFw#I>~4MkRU! +z0)ZcL6oazz59n_?N)n2U>SkL1*4Ndc{uFI61#a +z<6A}L;t+)JA#j;kRJFs32o`Bjhw{t)fMJI(7Q=qy4h-{f_i}GiFZ!s;3mI#IT+|R{ +z-cvm=0uL)&$b(bY>twkF!TrI=$ak+PX}M9ZstnuM*oa~^lwa5X{*4)91eti0(c#}6 +z$#Db_1X}%t&>@RaY&ZS>eWmrft+b@#W6;IUn3q>f=R6sgMdr)wU4?Fgzw^ONm7n9) +zK7y?wCMJrZ5G2;tY^BO6c6&j!RQ%JA#zH>r-xH>TG!kE^XPVesKckTp-`aGzZ +z$(PxbO1S4%hUNL7!B++S*}@LK +zXE9vL=--;W?`npJCm(Lwe$WUzIWo+IhJ-}b)e5>DQv%iW)VWPI!>7wMiAYG2PH%iE +zFnIhm&{vVLPuWRYU!JAR&6SOEjhyhB5e(^B#9@r5;*M|DsxW>J4=lI&aWqS?^L%^T +zg0TD*F7+ms=GaJ#D@ILqb@L;6#8OeVC&nm+WY_`VHT2<-D^Kf>hccOzRc~a`pojn0 +zzG!M^7iUD4(S7I8_OV4*O}ERr(v-pNv+i1AcDjhq%k$HU&kYsva?8U0;pQ)O7DMm7 +zg3pSqs@?*m)C|O_!o@f)=$V5B`Pr$dx@9{mekZfu2~*3_ +z%#NEN4yAPNy)9^qo}S+OEmT)x^WlPc{70S7o@Dal2+p&-q(tONhj?K_8PC6mI(Fg; +ziPLp;FD~arh?cgs?}j*RFYHUB_ZG&Ow+?$w3%y=8r}-d3qv7_kud^Hc5SCVJ5s)&E +zB6T>?sh1IadrM+sa62}Tur`W7uNszPUnrNZY+{~FkZ)NEN#>O@KdjyDp;)A>`#x=xh +zBlQ;*)te+I`B;1%92`Cn4+L>fe_5HEv;Fy0158J;vF-w;p&HR*7k^A4onKfO$>irU +zF_vs-NR*g@#%GTfvkUnbRjsFuUOY0aXMlfvDC!cT`YHdhW}KEy>&q@yd<8yn1RExA +zyUNo@)9&DIKKFkgm(V`MGW_?0$UX%rDIO^ygWFf5nee6J*3wdps?*=FPE}_Sk3l2t +zqr)>q1_j<*k9bi0yT862rtemHae0y_b&T{LAZs}mJ0&8haRZLp)xnxM-F(|A8gR8t +zuHs#^{wn9qga&DSJd@IEL?!M$%F(xGl?FM+eFETjfWQDyqU9Ss7Aq3o5Xd4B+XwCc +zs~VqIwYIza$8jU{;^iLrA}_1ho3s8K!M^l$a=qLl+r-d7dF|%a-$%y8WbmDkJ>m|9 +zNUzKO5xi0q_;zYqH>G2*fHK2$Z;1_KfBZ5Go?uFbX}~qzv5uWpR321s_UpRwo5}e} +zpKz`4ZNKZHAXD(!lD@!iZ-avi3oTBS+{fRTLP?zw#ki;pUgL_QBI%E4Zc2B3y)mz< +z3qNIfK6Zci%Yw2O&bInIB&fOmH22n{BzD4e@rm`z;t|b>xtQw4Kg7K3X@@mkc)#dl +z;ZqniyPvJ*Nkm6G#S%58@7LwZ7=u?6vgD>4%t2u%uUi=ySJ3z{)LLZ#B +zbMT+3r`9zp3hOTf$GEyE%u-$bmo{LD_w@ACXff#& +zw^l%8kC}PMb)pB1dmhtgwpuUX8W~4D!eYOe%IlI22H@QfLth5&Ph27QG_k0V4*@Hr +zZ9Y9w7~}GkI7&&WY>OA2yCZr-rHN7xB~a= +zg@oAIZ&GL5u6^HNGBGh|7q>;$SRLsI3X7ysaDXczlS0CkWE5l-1N*EZY~$HOnIz0&Lf&SkY+6&g(1uSt}M;13QQCQt(-G5?Qg@ +z_Q;_p5@Z4jofu1%fD*N$L3pbe&VrLgp9m=8J;sK){z-FWOl$y!DK_1guhBtb(46+& +zd~9n_<=l4ypAV$??O-JOSMRvb?z?(uf;GZ$sCql$siaX2p^evm#UG4e?`A$wQ@;^W++}@ZUUY`oNoEt3lmg3PnJW{RIuQ56mO=(MDEK!;Ob+Br +zT}#;2GIdriG~_22$kZAoYcH3L+-)KERZy_Fa!tm(u>(*7(OOar{J*rt{O@Uy`9Irv +fB&c85+X3$}Uc> + + +@@ -47,7 +47,6 @@ + Komandos Kodi Web sąsaja.(Kodi numatytoji žiniatinklio sąsaja) + Team Kodi tīmekļa saskarne. (Kodi noklusētā tīmekļa saskarne) + Веб интерфејс на Kodi тимот. (Kodi's подразбирачки веб интерфејс) +- Kodi багийн вэб интерфэйс. (Kodi-ийн үндсэн вэб интерфэйс) + Antaramuka Sesawang Pasukan-Kodi (antaramuka sesawang lalai Kodi) + Web interface ta' Team Kodi. (Il-Web interface normali ta' Kodi) + Team Kodi ဝက်ဘ် အသွင်အပြင် (Kodi ၏ မူရင် ဝက်ဘ် အသွင်အပြင်) +@@ -55,7 +54,7 @@ + Team Kodi Webinterface. (Kodi's standaard webinterface) + Interfejs webowy Kodi. (Domyślny) + Interface Web da Equipe Kodi. (interface web padrão do Kodi) +- Interface da Web da Team Kodi. (Interface da Web predefinida do Kodi) ++ Interface web da Team Kodi. (Interface web padrão do Kodi) + Interfață web Kodi. (interfață web implicită pentru Kodi) + Веб-интерфейс от разработчиков Kodi (веб-интерфейс Kodi по умолчанию). + Webové rozhranie tímu Kodi. (predvolené webové rozhranie pre Kodi) +@@ -98,7 +97,7 @@ + رابط استاندارد وب برای Kodi. قابل استفاده برای همه دستگاه ها و همه رزولوشن ها + Oletus WWW-käyttöliittymä Kodi:lle. Suunniteltu käytettäväksi kaiken kokoisilla laitteilla. + Interface Web par défaut de Kodi - Conçue pour les appareils de toutes résolutions +- Interface Web d'origine de Kodi ; adaptée aux appareils de toutes résolutions ++ Interface Web par défaut de Kodi ; adaptée aux appareils de toutes résolutions + Interface web predefinida para Kodi, deseñada para dispositivos de todas as resolucións + ממשק דפדפן ברירת המחדל עבור Kodi; מותאם למכשירים בעלי אבחנות שונות + Uobičajeno web sučelje za Kodi; Dizajnirano za uređaje svih razlučivosti +@@ -112,7 +111,6 @@ + Numatytoji Kodi Web sąsaja skirta visų rezoliucijų prietaisams + Noklusētā Kodi tīmekļa sakarne; Piemērota visu izšķirtspēju iekārtām + Подразбирачки веб интерфејс за Kodi; Дизајниран за уреди со сите резолуции +- Kod-ийн үндсэн вэб интерфэйс; Бүх төрлийн нарийвчлалтай төхөөрөмжид зориулагдсан. + Antaramuka sesawang lalai untuk Kodi; Direka untuk peranti pelbagai resolusi + Il-Web interface in-normali ta' Kodi; Iddiżinjata għal apparat ta' kull reżoluzzjoni + Kodi အတွက် မူရင်း ဝက်ဘ် အသွင်ပြင် ၊ စက်များ အားလုံး၏ resolutions အတွက် ရေးဆွဲထားသည်။ +@@ -120,7 +118,7 @@ + Standaard Kodi-webinterface; geschikt voor alle resoluties + Domyślny interfejs webowy Kodi; Zaprojektowany dla urządzeń o ekranach w dowolnej rozdzielczości + Interface web padrão para Kodi; Concebida para dispositivos de todas as resoluções +- Interface da Web ppredefinida do Kodi; Criada para dispositivos de todas as resoluções. ++ Interface web padrão do Kodi. Criada para dispositivos de todas as resoluções. + Interfață web implicită pentru Kodi, realizată de echipa Kodi pentru dispozitive cu orice rezoluție. + Веб-интерфейс Kodi по умолчанию. Разработан для устройств с любыми разрешениями. + Kodi' සඳහා නියත වෙබ් අතුරුමුහුණත; සෑම විභේදනයකම උපකරණ සඳහා නිර්මාණය කර ඇත +diff --git a/addons/webinterface.default/js/MediaLibrary.js b/addons/webinterface.default/js/MediaLibrary.js +index a5bbe72..211460b 100755 +--- a/addons/webinterface.default/js/MediaLibrary.js ++++ b/addons/webinterface.default/js/MediaLibrary.js +@@ -228,12 +228,12 @@ MediaLibrary.prototype = { + {'playerid': player, 'to': 'previous'} + ); + case 'forward': +- return this.rpcCall('Player.SetSpeed', +- {'playerid': player, 'speed': 'increment'} ++ return this.rpcCall('Player.Seek', ++ {'playerid': player, 'speed': 'smallforward'} + ); + case 'rewind': +- return this.rpcCall('Player.SetSpeed', +- {'playerid': player, 'speed': 'decrement'} ++ return this.rpcCall('Player.Seek', ++ {'playerid': player, 'speed': 'smallbackward'} + ); + } + } +diff --git a/appveyor.yml b/appveyor.yml +index 82d69fd..af6b01d 100644 +--- a/appveyor.yml ++++ b/appveyor.yml +@@ -6,12 +6,12 @@ environment: + CONFIG: Release + matrix: + - BUILD: Kodi +- # - ADDONS: adsp +- # - ADDONS: audiodecoder +- # - ADDONS: audioencoder +- # - ADDONS: pvr +- # - ADDONS: screensaver +- # - ADDONS: visualization ++ - ADDONS: adsp ++ - ADDONS: audiodecoder ++ - ADDONS: audioencoder ++ - ADDONS: pvr ++ - ADDONS: screensaver ++ - ADDONS: visualization + + install: + - SET PATH=C:\Program Files (x86)\CMake\bin;C:\msys64\bin;C:\msys64\usr\bin;%PATH% +diff --git a/codegenerator.mk b/codegenerator.mk +index 5f8bdd9..c020794 100644 +--- a/codegenerator.mk ++++ b/codegenerator.mk +@@ -47,11 +47,6 @@ $(GENDIR)/%.xml: %.i $(SWIG) $(JAVA) $(GENERATE_DEPS) + + codegenerated: $(SWIG) $(JAVA) $(GENERATED) $(GENERATED_JSON) $(GENERATED_ADDON_JSON) + +-$(JAVA): +- @echo Java not found, it will be used if found after configure. +- @echo This is not necessarily an error. +- @false +- + $(SWIG): + @echo Swig not found, it will be used if found after configure. + @echo This is not necessarily an error. +diff --git a/configure.ac b/configure.ac +index 45145b3..33dede8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -172,6 +172,8 @@ missing_headers="Could not find some required headers. Please see the README for + missing_program="Could not find a required program. Please see the README for your platform." + alsa_disabled="== ALSA support disabled. ==" + dbus_disabled="== DBUS support disabled. ==" ++glesscreensavers_enabled="== GLES screensavers enabled. ==" ++glesscreensavers_disabled="== GLES screensavers disabled. ==" + x11_enabled="== X11 enabled. ==" + x11_disabled="== X11 disabled. ==" + pulse_not_found="== Could not find libpulse. PulseAudio support disabled. ==" +@@ -186,8 +188,12 @@ vaapi_not_found="== Could not find libva. VAAPI support disabled. ==" + vaapi_disabled="== VAAPI support manually disabled. ==" + openmax_disabled="== OpenMax support manually disabled. ==" + openmax_not_found="== Could not find OpenMax headers. OpenMax support disabled. ==" ++librtmp_not_found="== Could not find libRTMP. RTMP support disabled. ==" ++librtmp_disabled="== RTMP support disabled. ==" + libnfs_not_found="== Could not find libnfs. NFS client support disabled. ==" + libnfs_disabled="== NFS support disabled. ==" ++libafpclient_not_found="== Could not find libafpclient. AFP client support disabled. ==" ++libafpclient_disabled="== AFP support disabled. ==" + libshairplay_not_found="== Could not find libshairplay. ==" + samba_disabled="== SAMBA support disabled. ==" + libplist_not_found="== Could not find libplist. AirPlay support disabled. ==" +@@ -239,9 +245,9 @@ AC_ARG_WITH([platform], + + AC_ARG_ENABLE([optimizations], + [AS_HELP_STRING([--enable-optimizations], +- [enable optimization (default is yes)])], ++ [enable optimization (default is no)])], + [use_optimizations=$enableval], +- [use_optimizations=yes]) ++ [use_optimizations=no]) + + AC_ARG_ENABLE([gl], + [AS_HELP_STRING([--enable-gl], +@@ -285,6 +291,12 @@ AC_ARG_ENABLE([profiling], + [use_profiling=$enableval], + [use_profiling=no]) + ++AC_ARG_ENABLE([glesscreensavers], ++ [AS_HELP_STRING([--enable-glesscreensavers], ++ [enable GLES screensavers (default is yes)])], ++ [use_glesscreensavers=$enableval], ++ [use_glesscreensavers=yes]) ++ + AC_ARG_ENABLE([x11], + [AS_HELP_STRING([--enable-x11], + [enable x11 (default is yes) 'Linux Only'])], +@@ -321,6 +333,12 @@ AC_ARG_ENABLE([ssh], + [use_ssh=$enableval], + [use_ssh=yes]) + ++AC_ARG_ENABLE([rtmp], ++ [AS_HELP_STRING([--enable-rtmp], ++ [enable RTMP support via librtmp (default is auto)])], ++ [use_librtmp=$enableval], ++ [use_librtmp=auto]) ++ + AC_ARG_ENABLE([samba], + [AS_HELP_STRING([--disable-samba], + [disable SAMBA support (default is enabled)])], +@@ -333,6 +351,12 @@ AC_ARG_ENABLE([nfs], + [use_libnfs=$enableval], + [use_libnfs=auto]) + ++AC_ARG_ENABLE([afpclient], ++ [AS_HELP_STRING([--enable-afpclient], ++ [enable AFP support via libafpclient (default is auto)])], ++ [use_libafpclient=$enableval], ++ [use_libafpclient=auto]) ++ + AC_ARG_ENABLE([airplay], + [AS_HELP_STRING([--enable-airplay], + [enable AirPlay support(default is auto)])], +@@ -371,7 +395,7 @@ AC_ARG_ENABLE([avahi], + + AC_ARG_ENABLE([non-free], + [AS_HELP_STRING([--disable-non-free], +- [disable components with non-compliant licenses])], ++ [disable componentents with non-compliant licenses])], + [use_nonfree=$enableval], + [use_nonfree=yes]) + +@@ -399,12 +423,6 @@ AC_ARG_ENABLE([libbluray], + [use_libbluray=$enableval], + [use_libbluray=auto]) + +-AC_ARG_ENABLE([libxslt], +- [AS_HELP_STRING([--disable-libxslt], +- [enable libxslt (XSLT scrapers) support (default is enabled)])], +- [use_libxslt=$enableval], +- [use_libxslt=yes]) +- + AC_ARG_ENABLE([texturepacker], + [AS_HELP_STRING([--enable-texturepacker], + [enable texturepacker support (default is auto)])], +@@ -670,16 +688,38 @@ case $use_platform in + target_platform=target_raspberry_pi + use_neon=no + use_cpu=arm1176jzf-s ++ extrarpiflags=rpi1 ++ CFLAGS="$CFLAGS -pipe -O3 -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ CXXFLAGS="$CXXFLAGS -pipe -O3 -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ FFMPEG_EXTRACFLAGS="$FFMPEG_EXTRACFLAGS -pipe -O3 -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ use_arch="arm" ++ ;; ++ cubox-i) ++ use_arch=armv7-a ++ target_platform="cubox-i" ++ use_static_ffmpeg=yes ++ use_joystick=no ++ use_sdl=no ++ use_hardcoded_tables="yes" ++ CFLAGS="$CFLAGS -pipe -O3 -march=armv7-a -mtune=cortex-a9 -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=neon -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ CXXFLAGS="$CXXFLAGS -pipe -O3 -march=armv7-a -mtune=cortex-a9 -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=neon -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ use_cpu=cortex-a9 ++ use_x11=no ++ use_neon=yes ++ ARCH=arm + ;; + raspberry-pi2) ++ use_arch=armv7-a + target_platform=target_raspberry_pi + use_neon=yes + use_cpu=cortex-a7 ++ extrarpiflags=rpi2 ++ CFLAGS="$CFLAGS -pipe -O3 -march=armv7-a -mfloat-abi=hard -mfpu=neon -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " ++ CXXFLAGS="$CXXFLAGS -pipe -O3 -march=armv7-a -mfloat-abi=hard -mfpu=neon -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -Wno-deprecated-declarations " + ;; + esac + + if test "$target_platform" = "target_raspberry_pi" ; then +- use_arch="arm" + use_hardcoded_tables="yes" + use_openmax=no + CORE_SYSTEM_NAME=rbpi +@@ -783,10 +823,7 @@ if test "$host_vendor" = "apple" ; then + #arm/ios + LIBS="$LIBS -framework CoreFoundation" + fi +-elif test "$target_platform" = "target_raspberry_pi"; then +- ARCH="arm" +- use_arch="arm" +-elif test "$use_arch" = "arm"; then ++elif test "$use_arch" = "arm" || test "$ARCH" = "arm"; then + CFLAGS="$CFLAGS -mno-apcs-stack-check" + CXXFLAGS="$CXXFLAGS -mno-apcs-stack-check" + if test "$use_tegra" = "yes"; then +@@ -907,6 +944,17 @@ else + AC_MSG_NOTICE([Using Python $PYTHON_VERSION]) + fi + ++# i.MX6 ++if test "$target_platform" = "cubox-i"; then ++ AC_MSG_CHECKING([for i.MX framebuffer support]) ++ AC_CHECK_HEADER([linux/mxcfb.h], have_imxfb=yes,have_imxfb=no) ++ AC_MSG_RESULT($have_imxfb) ++ if test "x$have_imxfb" = "xyes"; then ++ AC_DEFINE([HAS_IMXFB], [1], [Whether i.MX framebuffer support is enabled.]) ++ AC_SUBST([USE_IMXFB], 1) ++ fi ++fi ++ + # Checks for platforms libraries. + if test "$use_gles" = "yes"; then + use_gl="no" +@@ -920,7 +968,12 @@ if test "$use_gles" = "yes"; then + AC_DEFINE([HAVE_LIBEGL],[1],["Define to 1 if you have the `EGL' library (-lEGL)."]) + AC_DEFINE([HAVE_LIBGLESV2],[1],["Define to 1 if you have the `GLESv2' library (-lGLESv2)."]) + AC_MSG_RESULT(== WARNING: OpenGLES support is assumed.) +- LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm -lmmal -lmmal_core -lmmal_util -lvcsm" ++ INCLUDES="-I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux/ -I/opt/vc/include/interface/vcos/pthreads $INCLUDES" ++ LIBS="$LIBS -L/opt/vc/lib -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm -lmmal -lmmal_core -lmmal_util -lvcsm" ++ elif test "$target_platform" = "cubox-i"; then ++ AC_DEFINE([HAVE_LIBEGL],[1],["Define to 1 if you have the `EGL' library (-lEGL)."]) ++ AC_DEFINE([HAVE_LIBGLESV2],[1],["Define to 1 if you have the `GLESv2' library (-lGLESv2)."]) ++ LIBS="$LIBS -lEGL -lGLESv2 -lGAL " + else + AC_CHECK_LIB([EGL], [main],, AC_MSG_ERROR($missing_library)) + AC_CHECK_LIB([GLESv2],[main],, AC_MSG_ERROR($missing_library)) +@@ -1027,7 +1080,8 @@ int main() { + )]) + AC_LANG_POP([C++]) + +-if test "${target_platform}" = "target_linux" || test "${target_platform}" = "target_raspberry_pi" || test "${target_platform}" = "target_android"; then ++if test "${target_platform}" = "target_linux" || test "${target_platform}" = "target_raspberry_pi" || test "${target_platform}" = "target_android" || \ ++ test "${target_platform}" = "cubox-i"; then + PKG_CHECK_MODULES([UUID], [uuid],, AC_MSG_ERROR(libuuid not found)) + fi + +@@ -1065,28 +1119,21 @@ if test "$target_platform" = "target_android" ; then + AC_CHECK_LIB([log], [__android_log_vprint],, AC_MSG_ERROR($missing_library)) + AC_CHECK_LIB([jnigraphics], [main],, AC_MSG_ERROR($missing_library)) + fi +- +-# check for libbxslt +-AS_CASE([x$use_libxslt], +- [xyes],[ +- PKG_CHECK_MODULES([LIBXML], [libxml-2.0], +- [INCLUDES="$INCLUDES $LIBXML_CFLAGS"; LIBS="$LIBS $LIBXML_LIBS"], +- AC_MSG_ERROR($missing_library)) +- PKG_CHECK_MODULES([LIBXSLT], [libxslt], +- [INCLUDES="$INCLUDES $LIBXSLT_CFLAGS"; LIBS="$LIBS $LIBXSLT_LIBS"], +- AC_MSG_ERROR($missing_library)) +- AC_DEFINE([HAVE_LIBXSLT], 1, [System has libxslt library]) +- AC_SUBST([HAVE_LIBXSLT], 1) +- ],[ +- AC_SUBST([HAVE_LIBXSLT], 0) +- ] +-) ++PKG_CHECK_MODULES([LIBXML], [libxml-2.0], ++ [INCLUDES="$INCLUDES $LIBXML_CFLAGS"; LIBS="$LIBS $LIBXML_LIBS"], ++ AC_MSG_ERROR($missing_library)) ++PKG_CHECK_MODULES([LIBXSLT], [libxslt], ++ [INCLUDES="$INCLUDES $LIBXSLT_CFLAGS"; LIBS="$LIBS $LIBXSLT_LIBS"], ++ AC_MSG_ERROR($missing_library)) + PKG_CHECK_MODULES([FRIBIDI], [fribidi], + [INCLUDES="$INCLUDES $FRIBIDI_CFLAGS"; LIBS="$LIBS $FRIBIDI_LIBS"], + AC_MSG_ERROR($missing_library)) + PKG_CHECK_MODULES([SQLITE3], [sqlite3], + [INCLUDES="$INCLUDES $SQLITE3_CFLAGS"; LIBS="$LIBS $SQLITE3_LIBS"], + AC_MSG_ERROR($missing_library)) ++PKG_CHECK_MODULES([PNG], [libpng], ++ [INCLUDES="$INCLUDES $PNG_CFLAGS"; LIBS="$LIBS $PNG_LIBS"], ++ AC_MSG_ERROR($missing_library)) + PKG_CHECK_MODULES([PCRECPP], [libpcrecpp], + [INCLUDES="$INCLUDES $PCRECPP_CFLAGS"; LIBS="$LIBS $PCRECPP_LIBS"]; \ + AC_DEFINE([HAVE_LIBPCRECPP],[1],["Define to 1 if libpcrecpp is installed"]), +@@ -1098,7 +1145,7 @@ PKG_CHECK_MODULES([PCRE], [libpcre], + PKG_CHECK_MODULES([FREETYPE2], [freetype2], + [INCLUDES="$INCLUDES $FREETYPE2_CFLAGS"; LIBS="$LIBS $FREETYPE2_LIBS"], + AC_MSG_ERROR($missing_library)) +-PKG_CHECK_MODULES([TAGLIB], [taglib >= 1.9], ++PKG_CHECK_MODULES([TAGLIB], [taglib >= 1.8], + [INCLUDES="$INCLUDES $TAGLIB_CFLAGS"; LIBS="$LIBS $TAGLIB_LIBS"], + AC_MSG_ERROR($missing_library)) + +@@ -1283,6 +1330,15 @@ else + AC_MSG_RESULT($x11_disabled) + fi + ++# GLES Screensavers ++if test "$use_glesscreensavers" = "no" || test "$use_gles" = "no"; then ++ AC_MSG_NOTICE($glesscreensavers_disabled) ++ DISABLE_GLESSCREENSAVERS=1 ++else ++ AC_MSG_NOTICE($glesscreensavers_enabled) ++ DISABLE_GLESSCREENSAVERS=0 ++fi ++ + # libssh + if test "x$use_ssh" = "xno"; then + AC_MSG_NOTICE(ssh support disabled by user) +@@ -1293,6 +1349,26 @@ else + AC_MSG_ERROR(libssh not found)) + fi + ++# libRTMP ++if test "$use_librtmp" != "no"; then ++ AC_CHECK_HEADERS([librtmp/log.h librtmp/amf.h librtmp/rtmp.h],, ++ [if test "$use_librtmp" = "yes"; then ++ AC_MSG_ERROR($librtmp_not_found) ++ elif test "$use_librtmp" != "no"; then ++ AC_MSG_NOTICE($librtmp_not_found) ++ use_librtmp="no" ++ fi ++ ]) ++ if test "$use_librtmp" != "no"; then ++ XB_FIND_SONAME([RTMP], [rtmp], [use_librtmp]) ++ fi ++ if test "$use_librtmp" != "no"; then ++ AC_DEFINE([HAS_LIBRTMP], [1], [Whether to use libRTMP library.]) ++ fi ++else ++ AC_MSG_NOTICE($librtmp_disabled) ++fi ++ + # samba + if test "x$use_samba" != "xno"; then + PKG_CHECK_MODULES([SAMBA], [smbclient], +@@ -1335,6 +1411,26 @@ else + AC_MSG_NOTICE($libnfs_disabled) + fi + ++# libafpclient ++USE_LIBAFPCLIENT=0 ++if test "x$use_libafpclient" != "xno"; then ++ AC_CHECK_HEADERS([afpfs-ng/libafpclient.h],, ++ [if test "x$use_libafpclient" = "xyes"; then ++ AC_MSG_ERROR($libafpclient_not_found) ++ elif test "x$use_libafpclient" != "xno"; then ++ AC_MSG_NOTICE($libafpclient_not_found) ++ use_libafpclient="no" ++ fi ++ ]) ++ if test "x$use_libafpclient" != "xno"; then ++ XB_FIND_SONAME([AFPCLIENT], [afpclient], [use_libafpclient]) ++ AC_DEFINE([HAVE_LIBAFPCLIENT], [1], [Whether to use libafpclient library.]) ++ USE_LIBAFPCLIENT=1 ++ fi ++else ++ AC_MSG_NOTICE($libafpclient_disabled) ++fi ++ + # libplist for airplay feature + USE_AIRPLAY=0 + if test "$use_airplay" != "no"; then +@@ -1520,6 +1616,8 @@ if test "${USE_STATIC_FFMPEG}" = "1"; then + FFMPEG_OPTS="${FFMPEG_OPTS} --disable-optimizations" + fi + ++ FFMPEG_OPTS="${FFMPEG_OPTS} --cpu=${use_cpu} --arch=${use_arch}" ++ + if test "$with_ffmpeg" = "auto" || test "$with_ffmpeg" = "yes"; then + SAVE_INCLUDES="$INCLUDES" + SAVE_LIBS="$LIBS" +@@ -1601,9 +1699,6 @@ final_message="$final_message\n SWIG Available:\tYes" + + echo "Checking for a jre installation" + AC_PATH_PROG(JAVA_EXE, java, "none") +-if test "$JAVA_EXE" = "none"; then +- AC_MSG_ERROR($missing_program) +-fi + final_message="$final_message\n JRE Available:\tYes" + + echo "Checking for doxygen installation" +@@ -1860,6 +1955,12 @@ else + final_message="$final_message\n OpenMax:\tNo" + fi + ++if test "$use_glesscreensavers" = "yes"; then ++ final_message="$final_message\n GLES Screensavers:\t\tYes" ++else ++ final_message="$final_message\n GLES Screensavers:\t\tNo" ++fi ++ + if test "$use_x11" = "yes"; then + USE_X11=1 + final_message="$final_message\n X11:\t\tYes" +@@ -1874,18 +1975,11 @@ else + final_message="$final_message\n Bluray:\tNo" + fi + +-if test "$use_libxslt" = "yes"; then +- final_message="$final_message\n XSLT scrapers:\tYes" +-else +- final_message="$final_message\n XSLT scrapers:\tNo" +-fi +- + if test "x$use_texturepacker" != "xno"; then +- AC_PATH_PROG([TEXTUREPACKER], [TexturePacker], ["none"], +- [$PATH$PATH_SEPARATOR${abs_top_srcdir}/tools/depends/native/TexturePacker/bin]) +- if test "$TEXTUREPACKER" = "none"; then ++ AC_CHECK_PROG(TEXTUREPACKER, ${abs_top_srcdir}/tools/depends/native/TexturePacker/bin/TexturePacker, "yes", "no",) ++ if test "$TEXTUREPACKER" = "no"; then + make -C ${abs_top_srcdir}/tools/depends/native/TexturePacker +- TEXTUREPACKER="${abs_top_srcdir}/tools/depends/native/TexturePacker/bin/TexturePacker" ++ TEXTUREPACKER="${abs_top_srcdir}/tools/depends/native/TexturePacker/bin/TexturePacker" + fi + if test -x "$TEXTUREPACKER"; then + final_message="$final_message\n TexturePacker:Yes" +@@ -2016,6 +2110,12 @@ else + final_message="$final_message\n libssh support:\tNo" + fi + ++if test "$use_librtmp" != "no"; then ++ final_message="$final_message\n libRTMP support:\tYes" ++else ++ final_message="$final_message\n libRTMP support:\tNo" ++fi ++ + if test "x$use_samba" != "xno"; then + final_message="$final_message\n libsmbclient support:\tYes" + else +@@ -2028,6 +2128,12 @@ else + final_message="$final_message\n libnfs client support:No" + fi + ++if test "x$use_libafpclient" != "xno"; then ++ final_message="$final_message\n libafpclient support:\tYes" ++else ++ final_message="$final_message\n libafpclient support:\tNo" ++fi ++ + if test "$use_airplay" != "no"; then + final_message="$final_message\n AirPlay support:\tYes" + else +@@ -2153,6 +2259,15 @@ OUTPUT_FILES="Makefile \ + xbmc/freebsd/Makefile \ + xbmc/linux/Makefile \ + xbmc/filesystem/Makefile \ ++ xbmc/screensavers/gles/Makefile \ ++ xbmc/screensavers/gles/solarwinds/Makefile \ ++ xbmc/screensavers/gles/plasma/Makefile \ ++ xbmc/screensavers/gles/plasma2/Makefile \ ++ xbmc/screensavers/gles/noise/Makefile \ ++ xbmc/screensavers/gles/warp/Makefile \ ++ xbmc/screensavers/gles/stellar/Makefile \ ++ xbmc/screensavers/gles/spiral/Makefile \ ++ xbmc/screensavers/gles/ball/Makefile \ + xbmc/windowing/Makefile \ + xbmc/windowing/egl/Makefile \ + lib/addons/library.xbmc.addon/Makefile \ +@@ -2248,6 +2363,7 @@ AC_SUBST(CFLAGS_FOR_BUILD) + AC_SUBST(CXXFLAGS_FOR_BUILD) + AC_SUBST(LDFLAGS_FOR_BUILD) + AC_SUBST(SDL_DEFINES) ++AC_SUBST(DISABLE_GLESSCREENSAVERS) + AC_SUBST(FFMPEG_LIBDIR) + AC_SUBST(USE_STATIC_FFMPEG) + AC_SUBST(GNUTLS_ALL_LIBS) +@@ -2265,6 +2381,7 @@ AC_SUBST(USE_VDPAU) + AC_SUBST(USE_VAAPI) + AC_SUBST(USE_LIBSMBCLIENT) + AC_SUBST(USE_LIBNFS) ++AC_SUBST(USE_LIBAFPCLIENT) + AC_SUBST(USE_AIRPLAY) + AC_SUBST(USE_OPENMAX) + AC_SUBST(USE_PULSE) +diff --git a/lib/libUPnP/CMakeLists.txt b/lib/libUPnP/CMakeLists.txt +index b565720..29476f5 100644 +--- a/lib/libUPnP/CMakeLists.txt ++++ b/lib/libUPnP/CMakeLists.txt +@@ -101,7 +101,7 @@ else() + include_directories(Neptune/Source/System/Win32) + endif() + +-if(APPLE) ++if(CORE_SYSTEM_NAME STREQUAL darwin OR CORE_SYSTEM_NAME STREQUAL ios) + list(APPEND SOURCES Neptune/Source/System/Apple/NptAppleAutoreleasePool.mm + Neptune/Source/System/Apple/NptAppleLogConfig.mm) + endif() +diff --git a/lib/libdvd/Makefile.in b/lib/libdvd/Makefile.in +index 00827cf..90cdf63 100644 +--- a/lib/libdvd/Makefile.in ++++ b/lib/libdvd/Makefile.in +@@ -3,16 +3,10 @@ ARCH=@ARCH@ + CC=@CC@ + CXX=@CXX@ + +-ifeq (@CROSS_COMPILING@,yes) +- DEPENDS_DIR = $(shell grep "^PREFIX=/" @abs_top_srcdir@/tools/depends/Makefile.include | sed 's/PREFIX=//g') +- DVDNAV_A = $(DEPENDS_DIR)/lib/libdvdnav.a +- DVDREAD_A = $(DEPENDS_DIR)/lib/libdvdread.a +- DVDCSS_A = $(DEPENDS_DIR)/lib/libdvdcss.a +-else +- DVDNAV_A = @abs_top_srcdir@/tools/depends/target/libdvdnav/dvdnav-install/lib/libdvdnav.a +- DVDREAD_A = @abs_top_srcdir@/tools/depends/target/libdvdread/dvdread-install/lib/libdvdread.a +- DVDCSS_A = @abs_top_srcdir@/tools/depends/target/libdvdcss/dvdcss-install/lib/libdvdcss.a +-endif ++DEPENDS_DIR = $(shell grep "^PREFIX=/" @abs_top_srcdir@/tools/depends/Makefile.include | sed 's/PREFIX=//g') ++DVDNAV_A = $(DEPENDS_DIR)/lib/libdvdnav.a ++DVDREAD_A = $(DEPENDS_DIR)/lib/libdvdread.a ++DVDCSS_A = $(DEPENDS_DIR)/lib/libdvdcss.a + + SYSDIR = @abs_top_srcdir@/system/players/VideoPlayer + SOS = libdvdnav-$(ARCH).so +diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list +index 71024bf..f7bc7b9 100644 +--- a/project/BuildDependencies/scripts/0_package.list ++++ b/project/BuildDependencies/scripts/0_package.list +@@ -13,7 +13,7 @@ dnssd-541-win32.zip + doxygen-1.8.2-win32.7z + fontconfig-2.8.0-win32.7z + freetype-2.4.6-win32-3.7z +-giflib-5.1.4-win32-vc140.7z ++giflib-5.1.1-win32.7z + jsonschemabuilder-1.0.0-win32-3.7z + libass-0.12.1-win32.7z + libbluray-0.8.1-win32-vc120.7z +@@ -22,11 +22,12 @@ libcec-3.0.0-win32-2.7z + libexpat_2.0.1-win32.7z + libfribidi-0.19.2-win32.7z + libiconv-1.14-win32-vc140-v2.7z +-libjpeg-turbo-1.4.90-win32-vc140.7z +-libmicrohttpd-0.9.50-win32-vc140.7z ++libjpeg-turbo-1.2.0-win32.7z ++liblzo-2.04-win32.7z ++libmicrohttpd-0.9.48-win32-vc140-v2.7z + libnfs-1.10.0-win32.7z + libplist-1.7-win32-3.7z +-libpng-1.6.21-win32-vc140.7z ++libpng-1.5.13-win32.7z + librtmp-20150114-git-a107ce-win32.7z + libshairplay-52fd9db-win32.7z + libssh-0.5.0-1-win32.zip +@@ -34,15 +35,14 @@ libxml2-2.7.8_1-win32.7z + libxslt-1.1.26_1-win32.7z + libyajl-2.0.1-win32.7z + libzlib-vc100-1.2.5-win32.7z +-lzo-2.09-win32-vc140-v3.7z + mysql-connector-c-6.1.6-win32-vc140.7z + openssl-1.0.2g-win32-vc140-v2.7z + pcre-8.37-win32-vc140-v3.7z + pillow-3.1.0-win32-vc140.7z + python-2.7.11-win32-vc140-v2.7z + sqlite-3.10.2-win32-vc140.7z +-swig-3.0.10-win32.7z ++swig-2.0.7-win32-1.7z + taglib-1.11-win32-vc140-v2.7z +-texturepacker-1.1.1-win32.7z ++texturepacker-1.1.0-win32.7z + tinyxmlstl-2.6.2-win32-vc140-v2.7z +-zlib-1.2.8-win32-vc140-v3.7z ++zlib-1.2.8-win32-vc140-v2.7z +diff --git a/project/VS2010Express/XBMC for Windows.sln b/project/VS2010Express/XBMC for Windows.sln +index a833f85..e2c0c65 100644 +--- a/project/VS2010Express/XBMC for Windows.sln ++++ b/project/VS2010Express/XBMC for Windows.sln +@@ -1,21 +1,11 @@ + Microsoft Visual Studio Solution File, Format Version 12.00 +-# Visual Studio 14 +-VisualStudioVersion = 14.0.25402.0 ++# Visual Studio 2013 ++VisualStudioVersion = 12.0.40629.0 + MinimumVisualStudioVersion = 10.0.40219.1 + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kodi", "XBMC.vcxproj", "{3A68081D-E8F9-4523-9436-530DE9E5530A}" + ProjectSection(ProjectDependencies) = postProject +- {F8F1290B-1188-4810-86C9-88178A31D2AF} = {F8F1290B-1188-4810-86C9-88178A31D2AF} +- {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7} = {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7} +- {FEA71D39-CB68-486B-A978-246E661A3F89} = {FEA71D39-CB68-486B-A978-246E661A3F89} +- {44F93C4D-85DD-4452-99BB-F1D196174024} = {44F93C4D-85DD-4452-99BB-F1D196174024} +- {88968763-3D6B-48A8-B495-CC8C187FAC02} = {88968763-3D6B-48A8-B495-CC8C187FAC02} + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} +- {6B96FD7D-26EE-415B-8858-27757A0B1273} = {6B96FD7D-26EE-415B-8858-27757A0B1273} + {DF460EAB-570D-4B50-9089-2E2FC801BF38} = {DF460EAB-570D-4B50-9089-2E2FC801BF38} +- {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} = {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} +- {8BC9CEB8-8B4A-11D0-8D11-00A0CFEBC942} = {8BC9CEB8-8B4A-11D0-8D11-00A0CFEBC942} +- {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE} = {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE} +- {6D8C91F8-992F-4C83-9DE3-485D64EF8420} = {6D8C91F8-992F-4C83-9DE3-485D64EF8420} + EndProjectSection + EndProject + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libPlatinum", "libPlatinum.vcxproj", "{B2975495-FBE4-4F94-AAC5-B21A9842BF50}" +@@ -84,6 +74,12 @@ Global + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug|Win32.Build.0 = Debug (DLL)|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release|Win32.ActiveCfg = Release (DLL)|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release|Win32.Build.0 = Release (DLL)|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug Testsuite|Win32.ActiveCfg = Debug|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug Testsuite|Win32.Build.0 = Debug|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug|Win32.ActiveCfg = Debug|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug|Win32.Build.0 = Debug|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release|Win32.ActiveCfg = Release|Win32 ++ {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release|Win32.Build.0 = Release|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug Testsuite|Win32.ActiveCfg = Debug|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug Testsuite|Win32.Build.0 = Debug|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug|Win32.ActiveCfg = Debug|Win32 +diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj +index 164b608..bb6a5e4 100644 +--- a/project/VS2010Express/XBMC.vcxproj ++++ b/project/VS2010Express/XBMC.vcxproj +@@ -245,19 +245,14 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- +- CompileAsCpp +- CompileAsCpp +- CompileAsCpp +- +- +- CompileAsCpp +- CompileAsCpp +- CompileAsCpp +- + + + ++ ++ ++ ++ ++ + + + +@@ -265,11 +260,6 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- +- +- +- +- + + + +@@ -371,6 +361,9 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ + + + +@@ -378,6 +371,8 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ + + + +@@ -391,6 +386,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + +@@ -413,9 +409,14 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ + + + ++ ++ + + + +@@ -596,7 +597,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- ++ + + + +@@ -740,12 +741,14 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + + + +- ++ ++ + + + +@@ -932,6 +935,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + true + true +@@ -1011,7 +1015,6 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- + + + +@@ -1021,11 +1024,11 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- +- +- +- +- ++ ++ ++ ++ ++ + + + +@@ -1353,12 +1356,8 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- +- + +- + +- + + + +@@ -1398,20 +1397,28 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ + + + + + ++ ++ + + + + ++ ++ + + + + + ++ + + + +@@ -1428,7 +1435,13 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ ++ + ++ ++ + + + +@@ -1454,6 +1467,9 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ + + + +@@ -1486,11 +1502,8 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- + +- + +- + + true + true +@@ -1499,10 +1512,6 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + true + true + +- +- true +- true +- + + true + true +@@ -1541,8 +1550,10 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + ++ + + + +@@ -1551,6 +1562,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + CompileAsCpp + + ++ + + + +@@ -1599,6 +1611,10 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + true + true + ++ ++ true ++ true ++ + + true + true +@@ -1846,6 +1862,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + +@@ -1863,6 +1880,11 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ ++ ++ + + + +@@ -1955,7 +1977,6 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- + + + +@@ -2119,6 +2140,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + +@@ -2174,10 +2196,15 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + ++ ++ + ++ ++ + + + +@@ -2289,6 +2316,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + true + true +@@ -2329,13 +2357,16 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + ++ + + + + + ++ + + + +@@ -2419,7 +2450,6 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- + + + +@@ -2476,6 +2506,7 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ + + + +@@ -2504,7 +2535,16 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + ++ ++ ++ ++ + ++ ++ ++ ++ ++ + + + +@@ -3141,4 +3181,4 @@ copy "..\Win32BuildSetup\dependencies\python27.dll" "$(TargetDir)" + + + +- +\ No newline at end of file ++ +diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters +index b3c5378..1385742 100644 +--- a/project/VS2010Express/XBMC.vcxproj.filters ++++ b/project/VS2010Express/XBMC.vcxproj.filters +@@ -1,4 +1,4 @@ +- ++ + + + +@@ -319,6 +319,9 @@ + + {43526341-7b96-462d-9f71-685e426251ec} + ++ ++ {2afb92ce-e9ac-4458-80e7-3384ccfffa3c} ++ + + {1bdb0045-3341-49b7-8d6f-30a53f812350} + +@@ -445,9 +448,6 @@ + + {9e3dd585-08e1-4dae-bc21-05e49697ef94} + +- +- {c6256fb3-a4b8-4114-95c1-eb601756759a} +- + + + +@@ -576,6 +576,9 @@ + + cores\VideoPlayer\DVDInputStreams + ++ ++ cores\VideoPlayer\DVDInputStreams ++ + + cores\VideoPlayer\DVDInputStreams + +@@ -609,6 +612,9 @@ + + cores\VideoPlayer\DVDSubtitles + ++ ++ cores\paplayer ++ + + cores\paplayer + +@@ -618,9 +624,36 @@ + + cores\paplayer + ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ + + cores\paplayer + ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ + + cores\DllLoader + +@@ -1134,6 +1167,9 @@ + + input + ++ ++ input ++ + + input + +@@ -1218,6 +1254,9 @@ + + music\tags + ++ ++ music\tags ++ + + music\tags + +@@ -1227,9 +1266,21 @@ + + music\tags + ++ ++ music\tags ++ ++ ++ music\tags ++ + + music\tags + ++ ++ music\tags ++ ++ ++ music\tags ++ + + network + +@@ -1398,6 +1449,9 @@ + + utils + ++ ++ utils ++ + + utils + +@@ -1407,6 +1461,9 @@ + + utils + ++ ++ utils ++ + + utils + +@@ -1845,6 +1902,9 @@ + + filesystem + ++ ++ filesystem ++ + + network\httprequesthandler + +@@ -1887,6 +1947,12 @@ + + network\httprequesthandler + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -1902,6 +1968,12 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -1926,6 +1998,9 @@ + + filesystem + ++ ++ filesystem ++ + + filesystem + +@@ -1971,12 +2046,30 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -2052,6 +2145,15 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -2192,6 +2294,7 @@ + + + ++ + + + +@@ -2317,6 +2420,12 @@ + + utils\test + ++ ++ utils\test ++ ++ ++ utils\test ++ + + utils\test + +@@ -2329,6 +2438,9 @@ + + utils\test + ++ ++ utils\test ++ + + utils\test + +@@ -2830,21 +2942,6 @@ + + network\httprequesthandler + +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- + + + +@@ -2917,6 +3014,21 @@ + + settings + ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ + + utils + +@@ -2965,9 +3077,6 @@ + + input + +- +- music\tags +- + + network\httprequesthandler\python + +@@ -3004,9 +3113,6 @@ + + addons + +- +- addons +- + + filesystem + +@@ -3613,6 +3719,9 @@ + + cores\VideoPlayer\DVDInputStreams + ++ ++ cores\VideoPlayer\DVDInputStreams ++ + + cores\VideoPlayer\DVDInputStreams + +@@ -3679,6 +3788,9 @@ + + cores\VideoPlayer\DVDSubtitles + ++ ++ cores\paplayer ++ + + cores\paplayer + +@@ -3691,9 +3803,36 @@ + + cores\paplayer + ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ + + cores\paplayer + ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ ++ ++ cores\paplayer ++ + + cores\DllLoader + +@@ -4245,6 +4384,9 @@ + + input + ++ ++ input ++ + + input + +@@ -4356,6 +4498,9 @@ + + music\tags + ++ ++ music\tags ++ + + music\tags + +@@ -4365,9 +4510,21 @@ + + music\tags + ++ ++ music\tags ++ ++ ++ music\tags ++ + + music\tags + ++ ++ music\tags ++ ++ ++ music\tags ++ + + network + +@@ -4542,12 +4699,18 @@ + + utils + ++ ++ utils ++ + + utils + + + utils + ++ ++ utils ++ + + utils + +@@ -4557,6 +4720,9 @@ + + utils + ++ ++ utils ++ + + utils + +@@ -5037,6 +5203,15 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -5049,6 +5224,12 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -5061,6 +5242,12 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -5076,6 +5263,9 @@ + + filesystem + ++ ++ filesystem ++ + + filesystem + +@@ -5124,9 +5314,27 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -5202,6 +5410,15 @@ + + filesystem + ++ ++ filesystem ++ ++ ++ filesystem ++ ++ ++ filesystem ++ + + filesystem + +@@ -5406,6 +5623,7 @@ + + + ++ + + + +@@ -6041,6 +6259,21 @@ + + settings + ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ ++ ++ cores\AudioEngine\DSPAddons ++ + + addons + +@@ -6071,15 +6304,9 @@ + + video\jobs + +- +- music\tags +- + + video\jobs + +- +- music +- + + utils + +@@ -6329,9 +6556,6 @@ + + input + +- +- utils +- + + music\tags + +@@ -6689,21 +6913,6 @@ + + network\httprequesthandler + +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- +- +- cores\AudioEngine\Engines\ActiveAE\AudioDSPAddons +- + + + +@@ -6790,4 +6999,4 @@ + shaders + + +- +\ No newline at end of file ++ +diff --git a/project/cmake/CMakeLists.txt b/project/cmake/CMakeLists.txt +index a5368ae..7800c0d 100644 +--- a/project/cmake/CMakeLists.txt ++++ b/project/cmake/CMakeLists.txt +@@ -18,8 +18,8 @@ option(ENABLE_NONFREE "Enable non-free components?" ON) + option(ENABLE_MICROHTTPD "Enable MicroHttpd webserver?" ON) + option(ENABLE_MYSQLCLIENT "Enable MySql support?" ON) + option(ENABLE_AVAHI "Enable Avahi support?" ON) ++option(ENABLE_RTMP "Enable RTMP support?" ON) + option(ENABLE_BLURAY "Enable BluRay support?" ON) +-option(ENABLE_XSLT "Enable XSLT scrapers support?" ON) + option(ENABLE_PLIST "Enable AirPlay support?" ON) + option(ENABLE_NFS "Enable NFS support?" ON) + option(ENABLE_AIRTUNES "Enable AirTunes support?" ON) +@@ -61,13 +61,13 @@ set(CORE_BUILD_DIR build) + message(STATUS "Source directory: ${CORE_SOURCE_DIR}") + message(STATUS "Build directory: ${CMAKE_BINARY_DIR}") + +-include(modules/extra/ECMEnableSanitizers.cmake) + include(scripts/common/GeneratorSetup.cmake) + include(scripts/common/AddOptions.cmake) + include(scripts/common/ArchSetup.cmake) + include(scripts/common/Macros.cmake) ++include(scripts/common/ManageString.cmake) + include(scripts/common/ProjectMacros.cmake) +-include(scripts/${CORE_SYSTEM_NAME}/PathSetup.cmake) ++include(scripts/common/PathSetup.cmake) + include(ExternalProject) + + core_find_git_rev() +@@ -95,7 +95,7 @@ list(APPEND DEPLIBS ${CMAKE_THREAD_LIBS_INIT}) + + # Required dependencies + set(required_deps Sqlite3 FreeType PCRE Cpluff LibDvd +- TinyXML Python Yajl ++ TinyXML Python Yajl Xslt + Lzo2 Fribidi TagLib FFMPEG CrossGUID) + if(NOT WIN32) + list(APPEND required_deps LibSmbClient ZLIB) +@@ -107,7 +107,7 @@ if(CORE_SYSTEM_NAME STREQUAL android) + endif() + + # Optional dependencies +-set(optional_deps MicroHttpd MySqlClient SSH Xslt ++set(optional_deps MicroHttpd MySqlClient SSH + Alsa UDev Dbus Avahi + PulseAudio VDPAU VAAPI) + +@@ -115,10 +115,10 @@ set(optional_deps MicroHttpd MySqlClient SSH Xslt + set(required_dyload Curl ASS) + + # Optional, dyloaded deps +-set(dyload_optional CEC Bluray Plist NFS) ++set(dyload_optional RTMP CEC Bluray Plist NFS) + + # Required by shared objects we link +-set(required_dep_libs EXPAT) ++set(required_dep_libs PNG EXPAT) + + # Required tools + find_package(TexturePacker REQUIRED) +@@ -203,10 +203,6 @@ if(ENABLE_CCACHE) + core_optional_dep(CCache) + endif() + +-if(CORE_SYSTEM_NAME STREQUAL android) +- core_optional_dep(Breakpad) +-endif() +- + # Compile Info + add_custom_command(OUTPUT ${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp + ${CMAKE_BINARY_DIR}/addons/xbmc.addon/addon.xml +@@ -316,23 +312,16 @@ add_subdirectory(${CORE_SOURCE_DIR}/xbmc/interfaces/swig build/swig) + set(OTHER_FILES README.md) + + # main binary +-if(NOT CORE_SYSTEM_NAME STREQUAL android) +- add_executable(${APP_NAME_LC} ${CORE_MAIN_SOURCE} $ "${RESOURCES}" ${OTHER_FILES}) +-else() +- add_library(${APP_NAME_LC} SHARED ${CORE_MAIN_SOURCE} $ "${RESOURCES}" ${OTHER_FILES}) +-endif() ++add_executable(${APP_NAME_LC} ${CORE_MAIN_SOURCE} $ "${RESOURCES}" ${OTHER_FILES}) + whole_archive(_MAIN_LIBRARIES ${core_DEPENDS}) + target_link_libraries(${APP_NAME_LC} ${SYSTEM_LDFLAGS} ${_MAIN_LIBRARIES} ${DEPLIBS} ${CMAKE_DL_LIBS}) + unset(_MAIN_LIBRARIES) + add_dependencies(${APP_NAME_LC} export-files) +- +-if(WIN32) ++if(NOT WIN32) ++ set_target_properties(${APP_NAME_LC} PROPERTIES SUFFIX ".bin") ++else() + set_target_properties(${APP_NAME_LC} PROPERTIES WIN32_EXECUTABLE ON) + copy_main_dlls_to_buildtree() +-elseif(CORE_SYSTEM_NAME STREQUAL android) +- # Nothing +-else() +- set_target_properties(${APP_NAME_LC} PROPERTIES SUFFIX ".bin") + endif() + + # testing +@@ -359,9 +348,6 @@ endif() + if(FFMPEG_LINK_EXECUTABLE) + set(CMAKE_CXX_LINK_EXECUTABLE "${FFMPEG_LINK_EXECUTABLE}") + endif() +-if(FFMPEG_CREATE_SHARED_LIBRARY) +- set(CMAKE_CXX_CREATE_SHARED_LIBRARY "${FFMPEG_CREATE_SHARED_LIBRARY}") +-endif() + + # randr + if(ENABLE_X11 AND XRANDR_FOUND) +@@ -370,7 +356,7 @@ if(ENABLE_X11 AND XRANDR_FOUND) + endif() + + # XBMCHelper +-if(CORE_SYSTEM_NAME STREQUAL osx) ++if(CORE_SYSTEM_NAME STREQUAL darwin) + add_subdirectory(${CORE_SOURCE_DIR}/tools/EventClients/Clients/OSXRemote build/XBMCHelper) + endif() + +@@ -387,7 +373,7 @@ set(APP_LIB_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/${APP_NAME_LC}) + set(APP_INCLUDE_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include/${APP_NAME_LC}) + set(CXX11_SWITCH "-std=c++11") + configure_file(${PROJECT_SOURCE_DIR}/KodiConfig.cmake.in +- ${CORE_BUILD_DIR}/lib/${APP_NAME_LC}/${APP_NAME}Config.cmake @ONLY) ++ ${CORE_BUILD_DIR}/lib/${APP_NAME_LC}/${APP_NAME_LC}Config.cmake @ONLY) + configure_file(${PROJECT_SOURCE_DIR}/scripts/common/AddonHelpers.cmake + ${CORE_BUILD_DIR}/lib/${APP_NAME_LC}/AddonHelpers.cmake COPYONLY) + configure_file(${PROJECT_SOURCE_DIR}/scripts/common/AddOptions.cmake +diff --git a/project/cmake/KodiConfig.cmake.in b/project/cmake/KodiConfig.cmake.in +index 839cba9..d6b60c2 100644 +--- a/project/cmake/KodiConfig.cmake.in ++++ b/project/cmake/KodiConfig.cmake.in +@@ -1,24 +1,24 @@ +-set(APP_NAME @APP_NAME@) +-set(APP_NAME_LC @APP_NAME_LC@) +-set(APP_NAME_UC @APP_NAME_UC@) +-set(APP_VERSION_MAJOR @APP_VERSION_MAJOR@) +-set(APP_VERSION_MINOR @APP_VERSION_MINOR@) +-if(NOT @APP_NAME_UC@_PREFIX) +- set(@APP_NAME_UC@_PREFIX @APP_PREFIX@) +-endif() +-if(NOT @APP_NAME_UC@_INCLUDE_DIR) +- set(@APP_NAME_UC@_INCLUDE_DIR @APP_INCLUDE_DIR@) +-endif() +-if(NOT @APP_NAME_UC@_LIB_DIR) +- set(@APP_NAME_UC@_LIB_DIR @APP_LIB_DIR@) +-endif() +-if(NOT WIN32) +- set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} @CXX11_SWITCH@") +-endif() +-list(APPEND CMAKE_MODULE_PATH @APP_LIB_DIR@) ++SET(APP_NAME @APP_NAME@) ++SET(APP_NAME_LC @APP_NAME_LC@) ++SET(APP_NAME_UC @APP_NAME_UC@) ++SET(APP_VERSION_MAJOR @APP_VERSION_MAJOR@) ++SET(APP_VERSION_MINOR @APP_VERSION_MINOR@) ++IF(NOT @APP_NAME_UC@_PREFIX) ++ SET(@APP_NAME_UC@_PREFIX @APP_PREFIX@) ++ENDIF() ++IF(NOT @APP_NAME_UC@_INCLUDE_DIR) ++ SET(@APP_NAME_UC@_INCLUDE_DIR @APP_INCLUDE_DIR@) ++ENDIF() ++IF(NOT @APP_NAME_UC@_LIB_DIR) ++ SET(@APP_NAME_UC@_LIB_DIR @APP_LIB_DIR@) ++ENDIF() ++IF(NOT WIN32) ++ SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} @CXX11_SWITCH@") ++ENDIF() ++LIST(APPEND CMAKE_MODULE_PATH @APP_LIB_DIR@) + +-string(REPLACE ";" " " ARCH_DEFINES "@ARCH_DEFINES@") +-add_definitions(${ARCH_DEFINES} -DBUILD_KODI_ADDON) ++STRING(REPLACE ";" " " ARCH_DEFINES "@ARCH_DEFINES@") ++ADD_DEFINITIONS(${ARCH_DEFINES} -DBUILD_KODI_ADDON) + + if(NOT CORE_SYSTEM_NAME) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") +diff --git a/project/cmake/README.md b/project/cmake/README.md +index fafd078..5eccc25 100644 +--- a/project/cmake/README.md ++++ b/project/cmake/README.md +@@ -152,16 +152,6 @@ When using the makefile builds a few extra targets are defined: + + - `make check` builds and executes the test suite. + +-## Sanitizers +- +-Clang and GCC support different kinds of Sanitizers. To enable a Sanitizer call CMake with the +-option `-DECM_ENABLE_SANITIZERS=’san1;san2;...'`. For more information about enabling the +-Sanitizers read the documentation in +-[modules/extra/ECMEnableSanitizers.cmake](https://github.com/xbmc/xbmc/tree/master/project/cmake/modules/extra/ECMEnableSanitizers.cmake). +- +-It is also recommended to read the sections about the Sanitizers in the [Clang +-documentation](http://clang.llvm.org/docs/). +- + ## Debugging the build + + This section covers some tips that can be useful for debugging a CMake +diff --git a/project/cmake/addons/CMakeLists.txt b/project/cmake/addons/CMakeLists.txt +index f35003f..f7c781a 100644 +--- a/project/cmake/addons/CMakeLists.txt ++++ b/project/cmake/addons/CMakeLists.txt +@@ -113,13 +113,13 @@ if(PACKAGE_ZIP) + endif() + list(APPEND BUILD_ARGS -DPACKAGE_DIR=${PACKAGE_DIR}) + +- message(STATUS "ZIP packaging enabled (destination: ${PACKAGE_DIR})") ++ MESSAGE(STATUS "ZIP packaging enabled (destination: ${PACKAGE_DIR})") + endif() + + if(CMAKE_TOOLCHAIN_FILE) + list(APPEND BUILD_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}) +- message(STATUS "Toolchain specified") +- message(STATUS ${BUILD_ARGS}) ++ MESSAGE(STATUS "Toolchain specified") ++ MESSAGE(STATUS ${BUILD_ARGS}) + endif() + + if(NOT ADDONS_TO_BUILD) +@@ -127,7 +127,6 @@ if(NOT ADDONS_TO_BUILD) + else() + string(STRIP "${ADDONS_TO_BUILD}" ADDONS_TO_BUILD) + message(STATUS "Building following addons: ${ADDONS_TO_BUILD}") +- separate_arguments(ADDONS_TO_BUILD) + endif() + + if(NOT ADDONS_DEFINITION_DIR) +@@ -206,7 +205,7 @@ if(NOT addons) + file(MAKE_DIRECTORY ${BOOTSTRAP_BUILD_DIR}) + endif() + +- string(REPLACE ";" " " ADDONS_TO_BUILD_STR "${ADDONS_TO_BUILD}") ++ string (REPLACE ";" " " ADDONS_TO_BUILD_STR "${ADDONS_TO_BUILD}") + # generate the bootstrap buildsystem + execute_process(COMMAND ${CMAKE_COMMAND} ${PROJECT_SOURCE_DIR}/bootstrap + -DCMAKE_INSTALL_PREFIX:PATH=${ADDONS_DEFINITION_DIR} +@@ -230,6 +229,8 @@ endif() + # error either in ADDONS_TO_BUILD or in the directory configuration. + set(SUPPORTED_ADDON_FOUND FALSE) + ++separate_arguments(ADDONS_TO_BUILD) ++ + foreach(addon ${addons}) + if(NOT (addon MATCHES platforms.txt)) + file(STRINGS ${addon} def) +@@ -257,7 +258,7 @@ foreach(addon ${addons}) + set(platform_found FALSE) + check_target_platform(${dir} ${CORE_SYSTEM_NAME} platform_found) + +- if(${platform_found}) ++ if (${platform_found}) + # make sure the output directory is clean + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${id}") + file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}/${id}/") +diff --git a/project/cmake/installdata/cmake-files.txt b/project/cmake/installdata/cmake-files.txt +index 7ae9a8d..5536056 100644 +--- a/project/cmake/installdata/cmake-files.txt ++++ b/project/cmake/installdata/cmake-files.txt +@@ -7,5 +7,7 @@ project/cmake/scripts/common/GenerateVersionedFiles.cmake + project/cmake/scripts/common/GeneratorSetup.cmake + project/cmake/scripts/common/HandleDepends.cmake + project/cmake/scripts/common/Macros.cmake ++project/cmake/scripts/common/ManageString.cmake ++project/cmake/scripts/common/PathSetup.cmake + project/cmake/scripts/common/PrepareEnv.cmake + project/cmake/scripts/common/ProjectMacros.cmake +diff --git a/project/cmake/installdata/darwin/packaging.txt b/project/cmake/installdata/darwin/packaging.txt +new file mode 100644 +index 0000000..8cb2245 +--- /dev/null ++++ b/project/cmake/installdata/darwin/packaging.txt +@@ -0,0 +1,3 @@ ++LICENSE.gpl ++xbmc/platform/darwin/Credits.html ++tools/darwin/packaging/media/osx/icon.iconset/* +diff --git a/project/cmake/installdata/darwin/runtime.txt b/project/cmake/installdata/darwin/runtime.txt +new file mode 100644 +index 0000000..3bb5467 +--- /dev/null ++++ b/project/cmake/installdata/darwin/runtime.txt +@@ -0,0 +1,2 @@ ++tools/darwin/runtime/preflight ++tools/darwin/runtime/org.xbmc.helper.plist +diff --git a/project/cmake/modules/FindCCache.cmake b/project/cmake/modules/FindCCache.cmake +index b872772..4ad7d07 100644 +--- a/project/cmake/modules/FindCCache.cmake ++++ b/project/cmake/modules/FindCCache.cmake +@@ -2,5 +2,5 @@ find_program(CCACHE_FOUND ccache) + if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) +-endif() ++endif(CCACHE_FOUND) + +diff --git a/project/cmake/modules/FindCXX11.cmake b/project/cmake/modules/FindCXX11.cmake +index c0b9a52..f1b7346 100644 +--- a/project/cmake/modules/FindCXX11.cmake ++++ b/project/cmake/modules/FindCXX11.cmake +@@ -11,8 +11,8 @@ else() + if(CXX_FLAG_CXX0X) + add_options (CXX ALL_BUILDS "-std=c++0x") + set(CXX_STD11_FLAGS "-std=c++0x") +- endif() +-endif() ++ endif(CXX_FLAG_CXX0X) ++endif(CXX_FLAG_CXX11) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(CXX11 DEFAULT_MSG CXX_STD11_FLAGS) +diff --git a/project/cmake/modules/FindCrossGUID.cmake b/project/cmake/modules/FindCrossGUID.cmake +index 05f2abc..df40c9e 100644 +--- a/project/cmake/modules/FindCrossGUID.cmake ++++ b/project/cmake/modules/FindCrossGUID.cmake +@@ -5,7 +5,6 @@ if(ENABLE_INTERNAL_CROSSGUID) + list(GET CGUID_VER 0 CGUID_VER) + string(SUBSTRING "${CGUID_VER}" 8 -1 CGUID_VER) + +- set(CROSSGUID_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/libcrossguid.a) + externalproject_add(crossguid + URL http://mirrors.kodi.tv/build-deps/sources/crossguid-${CGUID_VER}.tar.gz + PREFIX ${CORE_BUILD_DIR}/crossguid +@@ -19,11 +18,10 @@ if(ENABLE_INTERNAL_CROSSGUID) + && + ${CMAKE_COMMAND} -E copy + ${CORE_SOURCE_DIR}/tools/depends/target/crossguid/FindCXX11.cmake +- +- BUILD_BYPRODUCTS ${CROSSGUID_LIBRARY}) ++ ) + + set(CROSSGUID_FOUND 1) +- set(CROSSGUID_LIBRARIES ${CROSSGUID_LIBRARY}) ++ set(CROSSGUID_LIBRARIES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/libcrossguid.a) + set(CROSSGUID_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) + + include(FindPackageHandleStandardArgs) +diff --git a/project/cmake/modules/FindD3DX11Effects.cmake b/project/cmake/modules/FindD3DX11Effects.cmake +index 5a58993..9de8c2b 100644 +--- a/project/cmake/modules/FindD3DX11Effects.cmake ++++ b/project/cmake/modules/FindD3DX11Effects.cmake +@@ -6,20 +6,19 @@ + # D3DCOMPILER_DLL - Path to the Direct3D Compiler + + include(ExternalProject) +-set(D3DX11EFFECTS_LIBRARY_RELEASE ${CORE_SOURCE_DIR}/lib/win32/Effects11/libs/Effects11/Release/Effects11.lib) +-set(D3DX11EFFECTS_LIBRARY_DEBUG ${CORE_SOURCE_DIR}/lib/win32/Effects11/libs/Effects11/Debug/Effects11.lib) + ExternalProject_Add(d3dx11effects + SOURCE_DIR ${CORE_SOURCE_DIR}/lib/win32/Effects11 + PREFIX ${CORE_BUILD_DIR}/Effects11 + CONFIGURE_COMMAND "" + BUILD_COMMAND msbuild ${CORE_SOURCE_DIR}/lib/win32/Effects11/Effects11_2013.sln + /t:Effects11 /p:Configuration=${CORE_BUILD_CONFIG} +- INSTALL_COMMAND "" +- BUILD_BYPRODUCTS ${D3DX11EFFECTS_LIBRARY_RELEASE} ${D3DX11EFFECTS_LIBRARY_DEBUG}) ++ INSTALL_COMMAND "") + + set(D3DX11EFFECTS_FOUND 1) + set(D3DX11EFFECTS_INCLUDE_DIRS ${CORE_SOURCE_DIR}/lib/win32/Effects11/inc) + ++set(D3DX11EFFECTS_LIBRARY_RELEASE ${CORE_SOURCE_DIR}/lib/win32/Effects11/libs/Effects11/Release/Effects11.lib) ++set(D3DX11EFFECTS_LIBRARY_DEBUG ${CORE_SOURCE_DIR}/lib/win32/Effects11/libs/Effects11/Debug/Effects11.lib) + include(SelectLibraryConfigurations) + select_library_configurations(D3DX11EFFECTS) + +diff --git a/project/cmake/modules/FindEMBEDDED.cmake b/project/cmake/modules/FindEMBEDDED.cmake +index 856d601..bc1b456 100644 +--- a/project/cmake/modules/FindEMBEDDED.cmake ++++ b/project/cmake/modules/FindEMBEDDED.cmake +@@ -11,7 +11,7 @@ endif() + string(REGEX MATCH "^arm" TARGET_ARCH_ARM "${CMAKE_SYSTEM_PROCESSOR}") + if(NOT CMAKE_CROSSCOMPILING AND NOT TARGET_ARCH_ARM) + return() +-endif() ++endif(NOT CMAKE_CROSSCOMPILING AND NOT TARGET_ARCH_ARM) + + find_path(EMBEDDED_FOUND NAMES include/linux/imxfb.h include/bcm_host.h PATHS /opt/vc) + +diff --git a/project/cmake/modules/FindFFMPEG.cmake b/project/cmake/modules/FindFFMPEG.cmake +index 1c600cd..caa7053 100644 +--- a/project/cmake/modules/FindFFMPEG.cmake ++++ b/project/cmake/modules/FindFFMPEG.cmake +@@ -44,7 +44,7 @@ if(ENABLE_INTERNAL_FFMPEG) + + file(WRITE ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ffmpeg/ffmpeg-link-wrapper + "#!/bin/bash +-if [[ $@ == *${APP_NAME_LC}.bin* || $@ == *${APP_NAME_LC}.so* || $@ == *${APP_NAME_LC}-test* ]] ++if [[ $@ == *${APP_NAME_LC}.bin* || $@ == *${APP_NAME_LC}-test* ]] + then + avformat=`PKG_CONFIG_PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/pkgconfig ${PKG_CONFIG_EXECUTABLE} --libs --static libavcodec` + avcodec=`PKG_CONFIG_PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/pkgconfig ${PKG_CONFIG_EXECUTABLE} --libs --static libavformat` +@@ -61,7 +61,6 @@ fi") + DESTINATION ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) + set(FFMPEG_LINK_EXECUTABLE "${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ffmpeg-link-wrapper -o " PARENT_SCOPE) +- set(FFMPEG_CREATE_SHARED_LIBRARY "${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ffmpeg-link-wrapper -o " PARENT_SCOPE) + set(FFMPEG_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) + list(APPEND FFMPEG_DEFINITIONS -DFFMPEG_VER_SHA=\"${FFMPEG_VER}\" + -DUSE_STATIC_FFMPEG=1) +diff --git a/project/cmake/modules/FindLibDvd.cmake b/project/cmake/modules/FindLibDvd.cmake +index 834d436..5588e78 100644 +--- a/project/cmake/modules/FindLibDvd.cmake ++++ b/project/cmake/modules/FindLibDvd.cmake +@@ -21,25 +21,15 @@ if(NOT WIN32) + endif() + + if(APPLE) +- set(CMAKE_LD_FLAGS "-framework IOKit -framework CoreFoundation") +- endif() +- +- set(HOST_ARCH ${ARCH}) +- if(CORE_SYSTEM_NAME STREQUAL android) +- if(ARCH STREQUAL arm) +- set(HOST_ARCH arm-linux-androideabi) +- elseif(ARCH STREQUAL i486-linux) +- set(HOST_ARCH i686-linux-android) +- endif() ++ set(CMAKE_LD_FLAGS "-framework IOKit -framework CoreFoundation") + endif() + + if(ENABLE_DVDCSS) +- set(DVDCSS_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdcss.a) + ExternalProject_Add(dvdcss URL ${libdvdcss_BASE_URL}/archive/${libdvdcss_VER}.tar.gz + PREFIX ${CORE_BUILD_DIR}/libdvd + CONFIGURE_COMMAND ac_cv_path_GIT= /configure +- --target=${HOST_ARCH} +- --host=${HOST_ARCH} ++ --target=${ARCH} ++ --host=${ARCH} + --disable-doc + --enable-static + --disable-shared +@@ -47,36 +37,34 @@ if(NOT WIN32) + --prefix= + "${EXTRA_FLAGS}" + "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" +- "LDFLAGS=${CMAKE_LD_FLAGS}" +- BUILD_BYPRODUCTS ${DVDCSS_LIBRARY}) ++ "LDFLAGS=${CMAKE_LD_FLAGS}") + ExternalProject_Add_Step(dvdcss autoreconf + DEPENDEES download update patch + DEPENDERS configure + COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif + WORKING_DIRECTORY ) + +- core_link_library(${DVDCSS_LIBRARY} system/players/VideoPlayer/libdvdcss dvdcss) ++ core_link_library(${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdcss.a ++ system/players/VideoPlayer/libdvdcss dvdcss) + endif() + + set(DVDREAD_CFLAGS "-D_XBMC") + if(ENABLE_DVDCSS) + set(DVDREAD_CFLAGS "${DVDREAD_CFLAGS} -DHAVE_DVDCSS_DVDCSS_H -I${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/include") +- endif() ++ endif(ENABLE_DVDCSS) + +- set(DVDREAD_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.a) + ExternalProject_Add(dvdread URL ${libdvdread_BASE_URL}/archive/${libdvdread_VER}.tar.gz + PREFIX ${CORE_BUILD_DIR}/libdvd + CONFIGURE_COMMAND ac_cv_path_GIT= /configure +- --target=${HOST_ARCH} +- --host=${HOST_ARCH} ++ --target=${ARCH} ++ --host=${ARCH} + --enable-static + --disable-shared + --with-pic + --prefix= + "${EXTRA_FLAGS}" + "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" +- "LDFLAGS=${CMAKE_LD_FLAGS}" +- BUILD_BYPRODUCTS ${DVDREAD_LIBRARY}) ++ "LDFLAGS=${CMAKE_LD_FLAGS}") + ExternalProject_Add_Step(dvdread autoreconf + DEPENDEES download update patch + DEPENDERS configure +@@ -86,18 +74,18 @@ if(NOT WIN32) + add_dependencies(dvdread dvdcss) + endif() + +- core_link_library(${DVDREAD_LIBRARY} system/players/VideoPlayer/libdvdread dvdread) ++ core_link_library(${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.a ++ system/players/VideoPlayer/libdvdread dvdread) + + if(ENABLE_DVDCSS) + set(DVDNAV_LIBS -ldvdcss) +- endif() ++ endif(ENABLE_DVDCSS) + +- set(DVDNAV_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdnav.a) + ExternalProject_Add(dvdnav URL ${libdvdnav_BASE_URL}/archive/${libdvdnav_VER}.tar.gz + PREFIX ${CORE_BUILD_DIR}/libdvd + CONFIGURE_COMMAND ac_cv_path_GIT= /configure +- --target=${HOST_ARCH} +- --host=${HOST_ARCH} ++ --target=${ARCH} ++ --host=${ARCH} + --enable-static + --disable-shared + --with-pic +@@ -107,22 +95,23 @@ if(NOT WIN32) + "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" + "DVDREAD_CFLAGS=${DVDREAD_CFLAGS}" + "DVDREAD_LIBS=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.la" +- "LIBS=${DVDNAV_LIBS}" +- BUILD_BYPRODUCTS ${DVDNAV_LIBRARY}) ++ "LIBS=${DVDNAV_LIBS}") + ExternalProject_Add_Step(dvdnav autoreconf + DEPENDEES download update patch + DEPENDERS configure + COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif + WORKING_DIRECTORY ) + add_dependencies(dvdnav dvdread) +- core_link_library(${DVDNAV_LIBRARY} system/players/VideoPlayer/libdvdnav dvdnav) ++ core_link_library(${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdnav.a ++ system/players/VideoPlayer/libdvdnav dvdnav) + + set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE) + + set(LIBDVD_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/include) +- set(LIBDVD_LIBRARIES ${DVDNAV_LIBRARY} ${DVDREAD_LIBRARY}) ++ set(LIBDVD_LIBRARIES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdnav.a ++ ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.a) + if(ENABLE_DVDCSS) +- list(APPEND LIBDVD_LIBRARIES ${DVDCSS_LIBRARY}) ++ list(APPEND LIBDVD_LIBRARIES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdcss.a) + endif() + set(LIBDVD_LIBRARIES ${LIBDVD_LIBRARIES} CACHE STRING "libdvd libraries" FORCE) + set(LIBDVD_FOUND 1 CACHE BOOL "libdvd found" FORCE) +diff --git a/project/cmake/modules/FindLibSmbClient.cmake b/project/cmake/modules/FindLibSmbClient.cmake +index e61e4a9..897fa7b 100644 +--- a/project/cmake/modules/FindLibSmbClient.cmake ++++ b/project/cmake/modules/FindLibSmbClient.cmake +@@ -5,10 +5,10 @@ if(PKGCONFIG_FOUND) + set(LIBSMBCLIENT_DEFINITIONS -DHAVE_LIBSMBCLIENT=1) + endif() + +-if(LIBSMBCLIENT_LIBRARIES AND LIBSMBCLIENT_INCLUDE_DIRS) ++if (LIBSMBCLIENT_LIBRARIES AND LIBSMBCLIENT_INCLUDE_DIRS) + # in cache already + set(LIBSMBCLIENT_FOUND TRUE) +-else() ++else (LIBSMBCLIENT_LIBRARIES AND LIBSMBCLIENT_INCLUDE_DIRS) + find_path(LIBSMBCLIENT_INCLUDE_DIR + NAMES + libsmbclient.h +@@ -29,37 +29,37 @@ else() + /sw/lib + ) + +- if(SMBCLIENT_LIBRARY) ++ if (SMBCLIENT_LIBRARY) + set(SMBCLIENT_FOUND TRUE) +- endif() ++ endif (SMBCLIENT_LIBRARY) + + set(LIBSMBCLIENT_INCLUDE_DIRS + ${LIBSMBCLIENT_INCLUDE_DIR} + ) + +- if(SMBCLIENT_FOUND) ++ if (SMBCLIENT_FOUND) + set(LIBSMBCLIENT_LIBRARIES + ${LIBSMBCLIENT_LIBRARIES} + ${SMBCLIENT_LIBRARY} + ) +- endif() ++ endif (SMBCLIENT_FOUND) + +- if(LIBSMBCLIENT_INCLUDE_DIRS AND LIBSMBCLIENT_LIBRARIES) ++ if (LIBSMBCLIENT_INCLUDE_DIRS AND LIBSMBCLIENT_LIBRARIES) + set(LIBSMBCLIENT_FOUND TRUE) +- endif() ++ endif (LIBSMBCLIENT_INCLUDE_DIRS AND LIBSMBCLIENT_LIBRARIES) + +- if(LIBSMBCLIENT_FOUND) +- if(NOT Libsmbclient_FIND_QUIETLY) ++ if (LIBSMBCLIENT_FOUND) ++ if (NOT Libsmbclient_FIND_QUIETLY) + message(STATUS "Found Libsmbclient: ${LIBSMBCLIENT_LIBRARIES}") +- endif() +- else() +- if(Libsmbclient_FIND_REQUIRED) ++ endif (NOT Libsmbclient_FIND_QUIETLY) ++ else (LIBSMBCLIENT_FOUND) ++ if (Libsmbclient_FIND_REQUIRED) + message(FATAL_ERROR "Could not find Libsmbclient") +- endif() +- endif() ++ endif (Libsmbclient_FIND_REQUIRED) ++ endif (LIBSMBCLIENT_FOUND) + set(LIBSMBCLIENT_DEFINITIONS -DHAVE_LIBSMBCLIENT=1) + + # show the LIBSMBCLIENT_INCLUDE_DIRS and LIBSMBCLIENT_LIBRARIES variables only in the advanced view + mark_as_advanced(LIBSMBCLIENT_INCLUDE_DIRS LIBSMBCLIENT_LIBRARIES LIBSMBCLIENT_DEFINITIONS) + +-endif() ++endif (LIBSMBCLIENT_LIBRARIES AND LIBSMBCLIENT_INCLUDE_DIRS) +diff --git a/project/cmake/modules/FindLzo2.cmake b/project/cmake/modules/FindLzo2.cmake +index 2dbd308..33eee10 100644 +--- a/project/cmake/modules/FindLzo2.cmake ++++ b/project/cmake/modules/FindLzo2.cmake +@@ -12,11 +12,11 @@ + # For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +-find_path(LZO2_INCLUDE_DIRS lzo1x.h PATH_SUFFIXES lzo) ++FIND_PATH(LZO2_INCLUDE_DIRS lzo1x.h PATH_SUFFIXES lzo) + +-find_library(LZO2_LIBRARIES NAMES lzo2 liblzo2) ++FIND_LIBRARY(LZO2_LIBRARIES NAMES lzo2 liblzo2) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Lzo2 DEFAULT_MSG LZO2_INCLUDE_DIRS LZO2_LIBRARIES) + +-mark_as_advanced(LZO2_INCLUDE_DIRS LZO2_LIBRARIES) ++MARK_AS_ADVANCED(LZO2_INCLUDE_DIRS LZO2_LIBRARIES) +diff --git a/project/cmake/modules/FindMicroHttpd.cmake b/project/cmake/modules/FindMicroHttpd.cmake +index 0cab031..f73dc77 100644 +--- a/project/cmake/modules/FindMicroHttpd.cmake ++++ b/project/cmake/modules/FindMicroHttpd.cmake +@@ -1,24 +1,24 @@ +-if(NOT WIN32) ++IF (NOT WIN32) + include(FindPkgConfig) +- if( PKG_CONFIG_FOUND ) ++ if ( PKG_CONFIG_FOUND ) + + pkg_check_modules (MICROHTTPD libmicrohttpd>=0.4) + + set(MICROHTTPD_DEFINITIONS ${MICROHTTPD_CFLAGS_OTHER}) +- endif() +-endif() ++ endif(PKG_CONFIG_FOUND) ++endif (NOT WIN32) + + # + # set defaults + if(NOT MICROHTTPD_FOUND) +- set(_microhttpd_HOME "/usr/local") +- set(_microhttpd_INCLUDE_SEARCH_DIRS ++ SET(_microhttpd_HOME "/usr/local") ++ SET(_microhttpd_INCLUDE_SEARCH_DIRS + ${CMAKE_INCLUDE_PATH} + /usr/local/include + /usr/include + ) + +- set(_microhttpd_LIBRARIES_SEARCH_DIRS ++ SET(_microhttpd_LIBRARIES_SEARCH_DIRS + ${CMAKE_LIBRARY_PATH} + /usr/local/lib + /usr/lib +@@ -28,39 +28,39 @@ if(NOT MICROHTTPD_FOUND) + if( "${MICROHTTPD_HOME}" STREQUAL "") + if("" MATCHES "$ENV{MICROHTTPD_HOME}") + message(STATUS "MICROHTTPD_HOME env is not set, setting it to /usr/local") +- set(MICROHTTPD_HOME ${_microhttpd_HOME}) +- else() +- set(MICROHTTPD_HOME "$ENV{MICROHTTPD_HOME}") +- endif() +- else() ++ set (MICROHTTPD_HOME ${_microhttpd_HOME}) ++ else("" MATCHES "$ENV{MICROHTTPD_HOME}") ++ set (MICROHTTPD_HOME "$ENV{MICROHTTPD_HOME}") ++ endif("" MATCHES "$ENV{MICROHTTPD_HOME}") ++ else( "${MICROHTTPD_HOME}" STREQUAL "") + message(STATUS "MICROHTTPD_HOME is not empty: \"${MICROHTTPD_HOME}\"") +- endif() ++ endif( "${MICROHTTPD_HOME}" STREQUAL "") + ## + + message(STATUS "Looking for microhttpd in ${MICROHTTPD_HOME}") + +- if( NOT ${MICROHTTPD_HOME} STREQUAL "" ) +- set(_microhttpd_INCLUDE_SEARCH_DIRS ${MICROHTTPD_HOME}/include ${_microhttpd_INCLUDE_SEARCH_DIRS}) +- set(_microhttpd_LIBRARIES_SEARCH_DIRS ${MICROHTTPD_HOME}/lib ${_microhttpd_LIBRARIES_SEARCH_DIRS}) +- set(_microhttpd_HOME ${MICROHTTPD_HOME}) +- endif() ++ IF( NOT ${MICROHTTPD_HOME} STREQUAL "" ) ++ SET(_microhttpd_INCLUDE_SEARCH_DIRS ${MICROHTTPD_HOME}/include ${_microhttpd_INCLUDE_SEARCH_DIRS}) ++ SET(_microhttpd_LIBRARIES_SEARCH_DIRS ${MICROHTTPD_HOME}/lib ${_microhttpd_LIBRARIES_SEARCH_DIRS}) ++ SET(_microhttpd_HOME ${MICROHTTPD_HOME}) ++ ENDIF( NOT ${MICROHTTPD_HOME} STREQUAL "" ) + +- if( NOT $ENV{MICROHTTPD_INCLUDEDIR} STREQUAL "" ) +- set(_microhttpd_INCLUDE_SEARCH_DIRS $ENV{MICROHTTPD_INCLUDEDIR} ${_microhttpd_INCLUDE_SEARCH_DIRS}) +- endif() ++ IF( NOT $ENV{MICROHTTPD_INCLUDEDIR} STREQUAL "" ) ++ SET(_microhttpd_INCLUDE_SEARCH_DIRS $ENV{MICROHTTPD_INCLUDEDIR} ${_microhttpd_INCLUDE_SEARCH_DIRS}) ++ ENDIF( NOT $ENV{MICROHTTPD_INCLUDEDIR} STREQUAL "" ) + +- if( NOT $ENV{MICROHTTPD_LIBRARYDIR} STREQUAL "" ) +- set(_microhttpd_LIBRARIES_SEARCH_DIRS $ENV{MICROHTTPD_LIBRARYDIR} ${_microhttpd_LIBRARIES_SEARCH_DIRS}) +- endif() ++ IF( NOT $ENV{MICROHTTPD_LIBRARYDIR} STREQUAL "" ) ++ SET(_microhttpd_LIBRARIES_SEARCH_DIRS $ENV{MICROHTTPD_LIBRARYDIR} ${_microhttpd_LIBRARIES_SEARCH_DIRS}) ++ ENDIF( NOT $ENV{MICROHTTPD_LIBRARYDIR} STREQUAL "" ) + +- if( MICROHTTPD_HOME ) +- set(_microhttpd_INCLUDE_SEARCH_DIRS ${MICROHTTPD_HOME}/include ${_microhttpd_INCLUDE_SEARCH_DIRS}) +- set(_microhttpd_LIBRARIES_SEARCH_DIRS ${MICROHTTPD_HOME}/lib ${_microhttpd_LIBRARIES_SEARCH_DIRS}) +- set(_microhttpd_HOME ${MICROHTTPD_HOME}) +- endif() ++ IF( MICROHTTPD_HOME ) ++ SET(_microhttpd_INCLUDE_SEARCH_DIRS ${MICROHTTPD_HOME}/include ${_microhttpd_INCLUDE_SEARCH_DIRS}) ++ SET(_microhttpd_LIBRARIES_SEARCH_DIRS ${MICROHTTPD_HOME}/lib ${_microhttpd_LIBRARIES_SEARCH_DIRS}) ++ SET(_microhttpd_HOME ${MICROHTTPD_HOME}) ++ ENDIF( MICROHTTPD_HOME ) + + # find the include files +- find_path(MICROHTTPD_INCLUDE_DIRS microhttpd.h ++ FIND_PATH(MICROHTTPD_INCLUDE_DIRS microhttpd.h + HINTS + ${_microhttpd_INCLUDE_SEARCH_DIRS} + ${PC_MICROHTTPD_INCLUDEDIR} +@@ -69,12 +69,12 @@ if(NOT MICROHTTPD_FOUND) + ) + + # locate the library +- if(WIN32) +- set(MICROHTTPD_LIBRARY_NAMES ${MICROHTTPD_LIBRARY_NAMES} libmicrohttpd.lib) +- else() +- set(MICROHTTPD_LIBRARY_NAMES ${MICROHTTPD_LIBRARY_NAMES} libmicrohttpd.a) +- endif() +- find_library(MICROHTTPD_LIBRARIES NAMES ${MICROHTTPD_LIBRARY_NAMES} ++ IF(WIN32) ++ SET(MICROHTTPD_LIBRARY_NAMES ${MICROHTTPD_LIBRARY_NAMES} libmicrohttpd.lib) ++ ELSE(WIN32) ++ SET(MICROHTTPD_LIBRARY_NAMES ${MICROHTTPD_LIBRARY_NAMES} libmicrohttpd.a) ++ ENDIF(WIN32) ++ FIND_LIBRARY(MICROHTTPD_LIBRARIES NAMES ${MICROHTTPD_LIBRARY_NAMES} + HINTS + ${_microhttpd_LIBRARIES_SEARCH_DIRS} + ${PC_MICROHTTPD_LIBDIR} +@@ -82,9 +82,9 @@ if(NOT MICROHTTPD_FOUND) + ) + + # if the include and the program are found then we have it +- if(MICROHTTPD_INCLUDE_DIRS AND MICROHTTPD_LIBRARIES) +- set(MICROHTTPD_FOUND "YES") +- endif() ++ IF(MICROHTTPD_INCLUDE_DIRS AND MICROHTTPD_LIBRARIES) ++ SET(MICROHTTPD_FOUND "YES") ++ ENDIF(MICROHTTPD_INCLUDE_DIRS AND MICROHTTPD_LIBRARIES) + + if( NOT WIN32) + find_library(GCRYPT_LIBRARY gcrypt) +@@ -93,12 +93,12 @@ if(NOT MICROHTTPD_FOUND) + if(NOT APPLE AND NOT CORE_SYSTEM_NAME STREQUAL android) + list(APPEND MICROHTTPD_LIBRARIES "-lrt") + endif() +- endif() ++ endif( NOT WIN32) + endif() + + list(APPEND MICROHTTPD_DEFINITIONS -DHAVE_LIBMICROHTTPD=1) + +-mark_as_advanced( ++MARK_AS_ADVANCED( + MICROHTTPD_FOUND + MICROHTTPD_LIBRARIES + MICROHTTPD_DEFINITIONS +diff --git a/project/cmake/modules/FindOpenGl.cmake b/project/cmake/modules/FindOpenGl.cmake +index 139a821..9d6ec01 100644 +--- a/project/cmake/modules/FindOpenGl.cmake ++++ b/project/cmake/modules/FindOpenGl.cmake +@@ -14,7 +14,7 @@ if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_OPENGL gl glu) + endif() + +-if(NOT CORE_SYSTEM_NAME STREQUAL osx) ++if(NOT CORE_SYSTEM_NAME STREQUAL darwin) + find_path(OPENGL_INCLUDE_DIR GL/gl.h + PATHS ${PC_OPENGL_gl_INCLUDEDIR}) + find_library(OPENGL_gl_LIBRARY NAMES GL +diff --git a/project/cmake/modules/FindPulseAudio.cmake b/project/cmake/modules/FindPulseAudio.cmake +index f471f78..5b57364 100644 +--- a/project/cmake/modules/FindPulseAudio.cmake ++++ b/project/cmake/modules/FindPulseAudio.cmake +@@ -13,57 +13,57 @@ + # Redistribution and use is allowed according to the terms of the BSD license. + # For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +-if(NOT PULSEAUDIO_MINIMUM_VERSION) ++if (NOT PULSEAUDIO_MINIMUM_VERSION) + set(PULSEAUDIO_MINIMUM_VERSION "1.0.0") +-endif() ++endif (NOT PULSEAUDIO_MINIMUM_VERSION) + +-if(PULSEAUDIO_INCLUDE_DIRS AND PULSEAUDIO_LIBRARY AND PULSEAUDIO_MAINLOOP_LIBRARY) ++if (PULSEAUDIO_INCLUDE_DIRS AND PULSEAUDIO_LIBRARY AND PULSEAUDIO_MAINLOOP_LIBRARY) + # Already in cache, be silent + set(PULSEAUDIO_FIND_QUIETLY TRUE) +-endif() ++endif (PULSEAUDIO_INCLUDE_DIRS AND PULSEAUDIO_LIBRARY AND PULSEAUDIO_MAINLOOP_LIBRARY) + +-if(NOT WIN32) ++if (NOT WIN32) + include(FindPkgConfig) + pkg_check_modules(PC_PULSEAUDIO libpulse>=${PULSEAUDIO_MINIMUM_VERSION}) + pkg_check_modules(PC_PULSEAUDIO_MAINLOOP libpulse-mainloop-glib) +-endif() ++endif (NOT WIN32) + +-find_path(PULSEAUDIO_INCLUDE_DIRS pulse/pulseaudio.h ++FIND_PATH(PULSEAUDIO_INCLUDE_DIRS pulse/pulseaudio.h + HINTS + ${PC_PULSEAUDIO_INCLUDEDIR} + ${PC_PULSEAUDIO_INCLUDE_DIRS} + ) + +-find_library(PULSEAUDIO_LIBRARY NAMES pulse libpulse ++FIND_LIBRARY(PULSEAUDIO_LIBRARY NAMES pulse libpulse + HINTS + ${PC_PULSEAUDIO_LIBDIR} + ${PC_PULSEAUDIO_LIBRARY_DIRS} + ) + +-find_library(PULSEAUDIO_MAINLOOP_LIBRARY NAMES pulse-mainloop pulse-mainloop-glib libpulse-mainloop-glib ++FIND_LIBRARY(PULSEAUDIO_MAINLOOP_LIBRARY NAMES pulse-mainloop pulse-mainloop-glib libpulse-mainloop-glib + HINTS + ${PC_PULSEAUDIO_LIBDIR} + ${PC_PULSEAUDIO_LIBRARY_DIRS} + ) + +-if(NOT PULSEAUDIO_INCLUDE_DIRS OR NOT PULSEAUDIO_LIBRARY) ++if (NOT PULSEAUDIO_INCLUDE_DIRS OR NOT PULSEAUDIO_LIBRARY) + set(PULSEAUDIO_FOUND FALSE) + else() + set(PULSEAUDIO_FOUND TRUE) + endif() + +-if(PULSEAUDIO_FOUND) +- if(NOT PULSEAUDIO_FIND_QUIETLY) ++if (PULSEAUDIO_FOUND) ++ if (NOT PULSEAUDIO_FIND_QUIETLY) + message(STATUS "Found PulseAudio: ${PULSEAUDIO_LIBRARY}") +- if(PULSEAUDIO_MAINLOOP_LIBRARY) ++ if (PULSEAUDIO_MAINLOOP_LIBRARY) + message(STATUS "Found PulseAudio Mainloop: ${PULSEAUDIO_MAINLOOP_LIBRARY}") +- else() ++ else (PULSAUDIO_MAINLOOP_LIBRARY) + message(STATUS "Could NOT find PulseAudio Mainloop Library") +- endif() +- endif() +-else() ++ endif (PULSEAUDIO_MAINLOOP_LIBRARY) ++ endif (NOT PULSEAUDIO_FIND_QUIETLY) ++else (PULSEAUDIO_FOUND) + message(STATUS "Could NOT find PulseAudio") +-endif() ++endif (PULSEAUDIO_FOUND) + + set(PULSEAUDIO_LIBRARIES ${PULSEAUDIO_LIBRARY}) + +diff --git a/project/cmake/modules/FindRTMP.cmake b/project/cmake/modules/FindRTMP.cmake +new file mode 100644 +index 0000000..432b77d +--- /dev/null ++++ b/project/cmake/modules/FindRTMP.cmake +@@ -0,0 +1,21 @@ ++# - Try to find rtmp ++# Once done this will define ++# ++# RTMP_FOUND - system has librtmp ++# RTMP_INCLUDE_DIRS - the librtmp include directory ++# RTMP_LIBRARIES - The librtmp libraries ++ ++if(PKG_CONFIG_FOUND) ++ pkg_check_modules (RTMP librtmp) ++ list(APPEND RTMP_INCLUDE_DIRS ${RTMP_INCLUDEDIR}) ++else() ++ find_path(RTMP_INCLUDE_DIRS librtmp/rtmp.h) ++ find_library(RTMP_LIBRARIES rtmp) ++endif() ++ ++include(FindPackageHandleStandardArgs) ++find_package_handle_standard_args(RTMP DEFAULT_MSG RTMP_INCLUDE_DIRS RTMP_LIBRARIES) ++ ++list(APPEND RTMP_DEFINITIONS -DHAS_LIBRTMP=1) ++ ++mark_as_advanced(RTMP_INCLUDE_DIRS RTMP_LIBRARIES RTMP_DEFINITIONS) +diff --git a/project/cmake/modules/FindSSE.cmake b/project/cmake/modules/FindSSE.cmake +index 14009be..c76b811 100644 +--- a/project/cmake/modules/FindSSE.cmake ++++ b/project/cmake/modules/FindSSE.cmake +@@ -1,105 +1,105 @@ + # Check if SSE instructions are available on the machine where + # the project is compiled. + +-if(CMAKE_SYSTEM_NAME MATCHES "Linux") +- exec_program(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) ++IF(CMAKE_SYSTEM_NAME MATCHES "Linux") ++ EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) + +- string(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE) +- if(SSE2_TRUE) ++ STRING(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE) ++ IF (SSE2_TRUE) + set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") +- else() ++ ELSE (SSE2_TRUE) + set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") +- endif() ++ ENDIF (SSE2_TRUE) + + # /proc/cpuinfo apparently omits sse3 :( +- string(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE) +- if(NOT SSE3_TRUE) +- string(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE) +- endif() ++ STRING(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE) ++ IF (NOT SSE3_TRUE) ++ STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE) ++ ENDIF (NOT SSE3_TRUE) + +- string(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE) +- if(SSE3_TRUE OR SSSE3_TRUE) ++ STRING(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE) ++ IF (SSE3_TRUE OR SSSE3_TRUE) + set(SSE3_FOUND true CACHE BOOL "SSE3 available on host") +- else() ++ ELSE (SSE3_TRUE OR SSSE3_TRUE) + set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") +- endif() +- if(SSSE3_TRUE) ++ ENDIF (SSE3_TRUE OR SSSE3_TRUE) ++ IF (SSSE3_TRUE) + set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host") +- else() ++ ELSE (SSSE3_TRUE) + set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") +- endif() ++ ENDIF (SSSE3_TRUE) + +- string(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE) +- if(SSE41_TRUE) ++ STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE) ++ IF (SSE41_TRUE) + set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") +- else() ++ ELSE (SSE41_TRUE) + set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") +- endif() +-elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") +- exec_program("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE ++ ENDIF (SSE41_TRUE) ++ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") ++ EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE + CPUINFO) + +- string(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE) +- if(SSE2_TRUE) ++ STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE) ++ IF (SSE2_TRUE) + set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") +- else() ++ ELSE (SSE2_TRUE) + set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") +- endif() ++ ENDIF (SSE2_TRUE) + +- string(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE) +- if(SSE3_TRUE) ++ STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE) ++ IF (SSE3_TRUE) + set(SSE3_FOUND true CACHE BOOL "SSE3 available on host") +- else() ++ ELSE (SSE3_TRUE) + set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") +- endif() ++ ENDIF (SSE3_TRUE) + +- string(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE) +- if(SSSE3_TRUE) ++ STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE) ++ IF (SSSE3_TRUE) + set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host") +- else() ++ ELSE (SSSE3_TRUE) + set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") +- endif() ++ ENDIF (SSSE3_TRUE) + +- string(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO}) +- string(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE) +- if(SSE41_TRUE) ++ STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO}) ++ STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE) ++ IF (SSE41_TRUE) + set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") +- else() ++ ELSE (SSE41_TRUE) + set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") +- endif() +-elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") ++ ENDIF (SSE41_TRUE) ++ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows") + # TODO + set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") + set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") + set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") + set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") +-else() ++ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") + set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") + set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") + set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") +-endif() ++ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + + if(NOT SSE2_FOUND) +- message(STATUS "Could not find hardware support for SSE2 on this machine.") +-endif() ++ MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.") ++endif(NOT SSE2_FOUND) + if(NOT SSE3_FOUND) +- message(STATUS "Could not find hardware support for SSE3 on this machine.") +-endif() ++ MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.") ++endif(NOT SSE3_FOUND) + if(NOT SSSE3_FOUND) +- message(STATUS "Could not find hardware support for SSSE3 on this machine.") +-endif() ++ MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.") ++endif(NOT SSSE3_FOUND) + if(NOT SSE4_1_FOUND) +- message(STATUS "Could not find hardware support for SSE4.1 on this machine.") +-endif() ++ MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.") ++endif(NOT SSE4_1_FOUND) + + mark_as_advanced(SSE2_FOUND SSE3_FOUND SSSE3_FOUND SSE4_1_FOUND) + +diff --git a/project/cmake/modules/FindTagLib.cmake b/project/cmake/modules/FindTagLib.cmake +index 0a9c353..06b615d 100644 +--- a/project/cmake/modules/FindTagLib.cmake ++++ b/project/cmake/modules/FindTagLib.cmake +@@ -14,7 +14,7 @@ + # TagLib::TagLib - The TagLib library + + if(PKG_CONFIG_FOUND) +- pkg_check_modules(PC_TAGLIB taglib>=1.9.0 QUIET) ++ pkg_check_modules(PC_TAGLIB taglib>=1.8.0 QUIET) + endif() + + find_path(TAGLIB_INCLUDE_DIR taglib/tag.h +diff --git a/project/cmake/modules/FindXslt.cmake b/project/cmake/modules/FindXslt.cmake +index f03124d..442ba43 100644 +--- a/project/cmake/modules/FindXslt.cmake ++++ b/project/cmake/modules/FindXslt.cmake +@@ -15,8 +15,4 @@ endif() + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Xslt DEFAULT_MSG XSLT_INCLUDE_DIRS XSLT_LIBRARIES) + +-if(XSLT_FOUND) +- set(XSLT_DEFINITIONS -DHAVE_LIBXSLT=1) +-endif() +- + mark_as_advanced(XSLT_INCLUDE_DIRS XSLT_LIBRARIES) +diff --git a/project/cmake/modules/FindYajl.cmake b/project/cmake/modules/FindYajl.cmake +index ef5f3d9..c27b03a 100644 +--- a/project/cmake/modules/FindYajl.cmake ++++ b/project/cmake/modules/FindYajl.cmake +@@ -14,7 +14,7 @@ if(NOT YAJL_FOUND) + file(STRINGS ${YAJL_INCLUDE_DIRS}/yajl/yajl_version.h version_header) + string(REGEX MATCH "YAJL_MAJOR ([0-9]+)" YAJL_VERSION_MAJOR ${version_header}) + string(REGEX REPLACE "YAJL_MAJOR ([0-9]+)" "\\1" YAJL_VERSION_MAJOR "${YAJL_VERSION_MAJOR}") +- if(YAJL_VERSION_MINOR LESS 2) ++ if (YAJL_VERSION_MINOR LESS 2) + set(YAJL_INCLUDE_DIRS) + set(YALJ_LIBRARIES) + endif() +diff --git a/project/cmake/scripts/android/ArchSetup.cmake b/project/cmake/scripts/android/ArchSetup.cmake +index c2a4489..86c0f6a 100644 +--- a/project/cmake/scripts/android/ArchSetup.cmake ++++ b/project/cmake/scripts/android/ArchSetup.cmake +@@ -1,7 +1,5 @@ + if(NOT CMAKE_TOOLCHAIN_FILE) + message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE required for android. See ${PROJECT_SOURCE_DIR}/README.md") +-elseif(NOT SDK_PLATFORM) +- message(FATAL_ERROR "Toolchain did not define SDK_PLATFORM. Possibly outdated depends.") + endif() + + set(ARCH_DEFINES -DTARGET_POSIX -DTARGET_LINUX -D_LINUX -DTARGET_ANDROID) +@@ -12,9 +10,9 @@ if(WITH_ARCH) + set(ARCH ${WITH_ARCH}) + else() + if(CPU STREQUAL armeabi-v7a) +- set(ARCH arm) ++ set(ARCH arm-linux-androideabi) + elseif(CPU STREQUAL i686) +- set(ARCH i486-linux) ++ set(ARCH i686-linux-android) + else() + message(SEND_ERROR "Unknown CPU: ${CPU}") + endif() +@@ -28,6 +26,5 @@ set(ENABLE_X11 OFF) + set(ENABLE_EGL ON) + set(ENABLE_AML ON) + set(ENABLE_OPTICAL OFF) +-set(ENABLE_BREAKPAD ON) + + list(APPEND DEPLIBS android log jnigraphics) +diff --git a/project/cmake/scripts/android/Install.cmake b/project/cmake/scripts/android/Install.cmake +index f0fd566..e69de29 100644 +--- a/project/cmake/scripts/android/Install.cmake ++++ b/project/cmake/scripts/android/Install.cmake +@@ -1,118 +0,0 @@ +-# Android packaging +- +-find_program(AAPT_EXECUTABLE aapt PATHS ${SDK_BUILDTOOLS_PATH}) +-if(NOT AAPT_EXECUTABLE) +- message(FATAL_ERROR "Could NOT find aapt executable") +-endif() +-find_program(DX_EXECUTABLE dx PATHS ${SDK_BUILDTOOLS_PATH}) +-if(NOT DX_EXECUTABLE) +- message(FATAL_ERROR "Could NOT find dx executable") +-endif() +-find_program(ZIPALIGN_EXECUTABLE zipalign PATHS ${SDK_BUILDTOOLS_PATH}) +-if(NOT ZIPALIGN_EXECUTABLE) +- message(FATAL_ERROR "Could NOT find zipalign executable") +-endif() +- +-# Configure files into packaging environment. +-if(BREAKPAD_FOUND) +- set(USE_BREAKPAD 1) +-endif() +-configure_file(${CORE_SOURCE_DIR}/tools/android/packaging/Makefile.in +- ${CMAKE_BINARY_DIR}/tools/android/packaging/Makefile @ONLY) +-configure_file(${CORE_SOURCE_DIR}/tools/android/packaging/apksign +- ${CMAKE_BINARY_DIR}/tools/android/packaging/apksign COPYONLY) +-configure_file(${CORE_SOURCE_DIR}/tools/android/packaging/make_symbols.sh +- ${CMAKE_BINARY_DIR}/tools/android/packaging/make_symbols.sh COPYONLY) +-file(WRITE ${CMAKE_BINARY_DIR}/tools/depends/Makefile.include +- "$(PREFIX)/lib/${APP_NAME_LC}/lib${APP_NAME_LC}.so: ;\n") +- +-set(package_files strings.xml +- activity_main.xml +- AndroidManifest.xml +- src/org/xbmc/kodi/XBMCOnAudioFocusChangeListener.java +- src/org/xbmc/kodi/XBMCInputDeviceListener.java +- src/org/xbmc/kodi/Main.java +- src/org/xbmc/kodi/XBMCSettingsContentObserver.java +- src/org/xbmc/kodi/XBMCOnFrameAvailableListener.java +- src/org/xbmc/kodi/XBMCVideoView.java +- src/org/xbmc/kodi/Splash.java +- src/org/xbmc/kodi/XBMCBroadcastReceiver.java) +-foreach(file IN LISTS package_files) +- configure_file(${CORE_SOURCE_DIR}/tools/android/packaging/xbmc/${file}.in +- ${CMAKE_BINARY_DIR}/tools/android/packaging/xbmc/${file} @ONLY) +-endforeach() +- +-# Copy files to the location expected by the Android packaging scripts. +-add_custom_target(bundle +- COMMAND ${CMAKE_COMMAND} -E copy_directory ${CORE_SOURCE_DIR}/tools/android/packaging/media +- ${CMAKE_BINARY_DIR}/tools/android/packaging/media +- COMMAND ${CMAKE_COMMAND} -E copy_directory ${CORE_SOURCE_DIR}/tools/android/packaging/xbmc/res +- ${CMAKE_BINARY_DIR}/tools/android/packaging/xbmc/res +- COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDS_PATH}/lib/python2.7 ${libdir}/python2.7 +- COMMAND ${CMAKE_COMMAND} -E copy $ +- ${libdir}/${APP_NAME_LC}/$) +-add_dependencies(bundle ${APP_NAME_LC}) +- +-# This function is used to prepare a prefix expected by the Android packaging +-# scripts. It creates a bundle_files command that is added to the bundle target. +-function(add_bundle_file file destination relative) +- if(NOT TARGET bundle_files) +- file(REMOVE ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/BundleFiles.cmake) +- add_custom_target(bundle_files COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/BundleFiles.cmake) +- add_dependencies(bundle bundle_files) +- add_dependencies(bundle_files export-files pack-skins wrap-libraries generate_json_header) +- endif() +- +- string(REPLACE "${relative}/" "" outfile ${file}) +- get_filename_component(outdir ${outfile} DIRECTORY) +- file(APPEND ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/BundleFiles.cmake +- "file(COPY \"${file}\" DESTINATION \"${destination}/${outdir}\")\n") +-endfunction() +- +-# Copy files into prefix +-foreach(file IN LISTS XBT_FILES install_data) +- string(REPLACE "${CMAKE_BINARY_DIR}/" "" file ${file}) +- add_bundle_file(${CMAKE_BINARY_DIR}/${file} ${datarootdir}/${APP_NAME_LC} ${CMAKE_BINARY_DIR}) +-endforeach() +- +-foreach(file IN LISTS WRAP_FILES) +- add_bundle_file(${CMAKE_BINARY_DIR}/${file} ${libdir}/${APP_NAME_LC} ${CMAKE_BINARY_DIR}) +-endforeach() +- +-foreach(lib IN LISTS required_dyload dyload_optional ITEMS Shairplay) +- string(TOUPPER ${lib} lib_up) +- set(lib_so ${${lib_up}_SONAME}) +- if(lib_so AND EXISTS ${DEPENDS_PATH}/lib/${lib_so}) +- add_bundle_file(${DEPENDS_PATH}/lib/${lib_so} ${libdir} "") +- endif() +-endforeach() +-add_bundle_file(${SMBCLIENT_LIBRARY} ${libdir} "") +- +-# Main targets from Makefile.in +-if(CPU MATCHES i686) +- set(CPU x86) +- set(ARCH x86) +-endif() +-foreach(target apk obb apk-unsigned apk-obb apk-obb-unsigned apk-noobb apk-clean apk-sign) +- add_custom_target(${target} +- COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} ${CMAKE_MAKE_PROGRAM} +- -C ${CMAKE_BINARY_DIR}/tools/android/packaging +- XBMCROOT=${CORE_SOURCE_DIR} +- CC=${CMAKE_C_COMPILER} +- CPU=${CPU} +- ARCH=${ARCH} +- PREFIX=${prefix} +- NDKROOT=${NDKROOT} +- SDKROOT=${SDKROOT} +- SDK_PLATFORM=${SDK_PLATFORM} +- STRIP=${CMAKE_STRIP} +- AAPT=${AAPT_EXECUTABLE} +- DX=${DX_EXECUTABLE} +- ZIPALIGN=${ZIPALIGN_EXECUTABLE} +- ${target} +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tools/android/packaging +- ) +- if(NOT target STREQUAL apk-clean) +- add_dependencies(${target} bundle) +- endif() +-endforeach() +diff --git a/project/cmake/scripts/android/PathSetup.cmake b/project/cmake/scripts/android/PathSetup.cmake +deleted file mode 100644 +index 69de883..0000000 +--- a/project/cmake/scripts/android/PathSetup.cmake ++++ /dev/null +@@ -1,33 +0,0 @@ +-if(NOT prefix) +- set(prefix ${CMAKE_BINARY_DIR}/install) +-endif() +-set(CMAKE_INSTALL_PREFIX ${prefix}) +-if(NOT exec_prefix) +- set(exec_prefix ${prefix}) +-endif() +-if(NOT libdir) +- set(libdir ${prefix}/lib) +-endif() +-if(NOT bindir) +- set(bindir ${prefix}/bin) +-endif() +-if(NOT includedir) +- set(includedir ${prefix}/include) +-endif() +-if(NOT datarootdir) +- set(datarootdir ${prefix}/share) +-endif() +-if(NOT datadir) +- set(datadir ${datarootdir}) +-endif() +- +-list(APPEND final_message "-- PATH config --") +-list(APPEND final_message "Prefix: ${prefix}") +-list(APPEND final_message "Libdir: ${libdir}") +-list(APPEND final_message "Bindir: ${bindir}") +-list(APPEND final_message "Includedir: ${includedir}") +-list(APPEND final_message "Datarootdir: ${datarootdir}") +-list(APPEND final_message "Datadir: ${datadir}") +- +-set(PATH_DEFINES -DBIN_INSTALL_PATH=\"${libdir}/kodi\" +- -DINSTALL_PATH=\"${datarootdir}/kodi\") +diff --git a/project/cmake/scripts/android/PathSetup.cmake b/project/cmake/scripts/android/PathSetup.cmake +new file mode 120000 +index 0000000..6786c1c +--- /dev/null ++++ b/project/cmake/scripts/android/PathSetup.cmake +@@ -0,0 +1 @@ ++../linux/PathSetup.cmake +\ No newline at end of file +diff --git a/project/cmake/scripts/common/AddOptions.cmake b/project/cmake/scripts/common/AddOptions.cmake +index 96837c1..0ebb823 100644 +--- a/project/cmake/scripts/common/AddOptions.cmake ++++ b/project/cmake/scripts/common/AddOptions.cmake +@@ -23,56 +23,60 @@ + # + # add_options (CXX RELEASE "-O3" "-DNDEBUG" "-Wall") + +-function(add_options langs builds) ++function (add_options langs builds) + # special handling of empty language specification +- if("${langs}" STREQUAL "ALL_LANGUAGES") +- set(langs CXX C Fortran) +- endif() +- foreach(lang IN LISTS langs) ++ if ("${langs}" STREQUAL "ALL_LANGUAGES") ++ set (langs CXX C Fortran) ++ endif ("${langs}" STREQUAL "ALL_LANGUAGES") ++ foreach (lang IN LISTS langs) + # prepend underscore if necessary +- foreach(build IN LISTS builds) +- if(NOT ("${build}" STREQUAL "ALL_BUILDS")) +- set(_bld "_${build}") +- string(TOUPPER "${_bld}" _bld) +- else() +- set(_bld "") +- endif() +- foreach(_opt IN LISTS ARGN) +- set(_var "CMAKE_${lang}_FLAGS${_bld}") +- #message(STATUS "Adding \"${_opt}\" to \${${_var}}") ++ foreach (build IN LISTS builds) ++ if (NOT ("${build}" STREQUAL "ALL_BUILDS")) ++ set (_bld "_${build}") ++ string (TOUPPER "${_bld}" _bld) ++ else (NOT ("${build}" STREQUAL "ALL_BUILDS")) ++ set (_bld "") ++ endif (NOT ("${build}" STREQUAL "ALL_BUILDS")) ++ foreach (_opt IN LISTS ARGN) ++ set (_var "CMAKE_${lang}_FLAGS${_bld}") ++ #message (STATUS "Adding \"${_opt}\" to \${${_var}}") + # remove it first +- string(REPLACE "${_opt}" "" _without "${${_var}}") +- string(STRIP "${_without}" _without) ++ string (REPLACE "${_opt}" "" _without "${${_var}}") ++ string (STRIP "${_without}" _without) + # we need to strip this one as well, so they are comparable +- string(STRIP "${${_var}}" _stripped) ++ string (STRIP "${${_var}}" _stripped) + # if it wasn't there, then add it at the end +- if("${_without}" STREQUAL "${_stripped}") ++ if ("${_without}" STREQUAL "${_stripped}") + # don't add any extra spaces if no options yet are set +- if(NOT ${_stripped} STREQUAL "") +- set(${_var} "${_stripped} ${_opt}") +- else() +- set(${_var} "${_opt}") +- endif() +- set(${_var} "${${_var}}" PARENT_SCOPE) +- endif() +- endforeach() +- endforeach() +- endforeach() +-endfunction() ++ if (NOT ${_stripped} STREQUAL "") ++ set (${_var} "${_stripped} ${_opt}") ++ else (NOT ${_stripped} STREQUAL "") ++ set (${_var} "${_opt}") ++ endif (NOT ${_stripped} STREQUAL "") ++ set (${_var} "${${_var}}" PARENT_SCOPE) ++ endif ("${_without}" STREQUAL "${_stripped}") ++ endforeach (_opt) ++ endforeach (build) ++ endforeach (lang) ++endfunction (add_options lang build) + + # set varname to flag unless user has specified something that matches regex +-function(set_default_option varname flag regex) +- if(NOT "$ENV{CXXFLAGS}" MATCHES "${regex}" ++function (set_default_option varname flag regex) ++ if (NOT "$ENV{CXXFLAGS}" MATCHES "${regex}" + AND NOT "${CMAKE_CXX_FLAGS}" MATCHES "${regex}" + AND NOT "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}" MATCHES "${regex}") +- set(${varname} ${flag} PARENT_SCOPE) +- else() +- set(${varname} PARENT_SCOPE) +- endif() +-endfunction() ++ set (${varname} ${flag} PARENT_SCOPE) ++ else (NOT "$ENV{CXXFLAGS}" MATCHES "${regex}" ++ AND NOT "${CMAKE_CXX_FLAGS}" MATCHES "${regex}" ++ AND NOT "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}" MATCHES "${regex}") ++ set (${varname} PARENT_SCOPE) ++ endif (NOT "$ENV{CXXFLAGS}" MATCHES "${regex}" ++ AND NOT "${CMAKE_CXX_FLAGS}" MATCHES "${regex}" ++ AND NOT "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}" MATCHES "${regex}") ++endfunction (set_default_option) + + # note: this must be called before project() +-macro(no_default_options) ++macro (no_default_options) + # prevent the platform probe to set options +- set(CMAKE_NOT_USING_CONFIG_FLAGS TRUE) +-endmacro() ++ set (CMAKE_NOT_USING_CONFIG_FLAGS TRUE) ++endmacro (no_default_options) +diff --git a/project/cmake/scripts/common/AddonHelpers.cmake b/project/cmake/scripts/common/AddonHelpers.cmake +index b0709e7..e429716 100644 +--- a/project/cmake/scripts/common/AddonHelpers.cmake ++++ b/project/cmake/scripts/common/AddonHelpers.cmake +@@ -21,82 +21,70 @@ endmacro() + + # Grab the version from a given add-on's addon.xml + macro (addon_version dir prefix) +- if(EXISTS ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in) +- file(READ ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in ADDONXML) +- else() +- file(READ ${dir}/addon.xml ADDONXML) +- endif() +- +- string(REGEX MATCH "]*version.?=.?.[0-9\\.]+" VERSION_STRING ${ADDONXML}) +- string(REGEX REPLACE ".*version=.([0-9\\.]+).*" "\\1" ${prefix}_VERSION ${VERSION_STRING}) ++ IF(EXISTS ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in) ++ FILE(READ ${PROJECT_SOURCE_DIR}/${dir}/addon.xml.in ADDONXML) ++ ELSE() ++ FILE(READ ${dir}/addon.xml ADDONXML) ++ ENDIF() ++ ++ STRING(REGEX MATCH "]*version.?=.?.[0-9\\.]+" VERSION_STRING ${ADDONXML}) ++ STRING(REGEX REPLACE ".*version=.([0-9\\.]+).*" "\\1" ${prefix}_VERSION ${VERSION_STRING}) + message(STATUS ${prefix}_VERSION=${${prefix}_VERSION}) + endmacro() + + # Build, link and optionally package an add-on + macro (build_addon target prefix libs) ++ ADD_LIBRARY(${target} ${${prefix}_SOURCES}) ++ TARGET_LINK_LIBRARIES(${target} ${${libs}}) + addon_version(${target} ${prefix}) +- if(${prefix}_SOURCES) +- add_library(${target} ${${prefix}_SOURCES}) +- TARGET_link_libraries(${target} ${${libs}}) +- set_target_properties(${target} PROPERTIES VERSION ${${prefix}_VERSION} +- SOVERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR} +- PREFIX "") +- if(OS STREQUAL "android") +- set_target_properties(${target} PROPERTIES PREFIX "lib") +- endif() +- elseif(${prefix}_CUSTOM_BINARY) +- add_custom_target(${target} ALL) +- list(GET ${prefix}_CUSTOM_BINARY 2 dependency) +- add_dependencies(${target} ${dependency}) +- endif() ++ SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${${prefix}_VERSION} ++ SOVERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR} ++ PREFIX "") ++ IF(OS STREQUAL "android") ++ SET_TARGET_PROPERTIES(${target} PROPERTIES PREFIX "lib") ++ ENDIF(OS STREQUAL "android") + + # get the library's location +- if(${prefix}_CUSTOM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 0 LIBRARY_LOCATION) +- list(GET ${prefix}_CUSTOM_BINARY 1 LIBRARY_FILENAME) ++ SET(LIBRARY_LOCATION $) ++ # get the library's filename ++ if("${CORE_SYSTEM_NAME}" STREQUAL "android") ++ # for android we need the filename without any version numbers ++ set(LIBRARY_FILENAME $) + else() +- set(LIBRARY_LOCATION $) +- # get the library's filename +- if("${CORE_SYSTEM_NAME}" STREQUAL "android") +- # for android we need the filename without any version numbers +- set(LIBRARY_FILENAME $) +- else() +- set(LIBRARY_FILENAME $) +- endif() ++ SET(LIBRARY_FILENAME $) + endif() + + # if there's an addon.xml.in we need to generate the addon.xml +- if(EXISTS ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in) +- set(PLATFORM ${CORE_SYSTEM_NAME}) ++ IF(EXISTS ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in) ++ SET(PLATFORM ${CORE_SYSTEM_NAME}) + +- file(READ ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in addon_file) +- string(CONFIGURE "${addon_file}" addon_file_conf @ONLY) +- file(GENERATE OUTPUT ${PROJECT_SOURCE_DIR}/${target}/addon.xml CONTENT "${addon_file_conf}") ++ FILE(READ ${PROJECT_SOURCE_DIR}/${target}/addon.xml.in addon_file) ++ STRING(CONFIGURE "${addon_file}" addon_file_conf @ONLY) ++ FILE(GENERATE OUTPUT ${PROJECT_SOURCE_DIR}/${target}/addon.xml CONTENT "${addon_file_conf}") + if(${APP_NAME_UC}_BUILD_DIR) +- file(GENERATE OUTPUT ${${APP_NAME_UC}_BUILD_DIR}/addons/${target}/addon.xml CONTENT "${addon_file_conf}") ++ FILE(GENERATE OUTPUT ${${APP_NAME_UC}_BUILD_DIR}/addons/${target}/addon.xml CONTENT "${addon_file_conf}") + endif() +- endif() ++ ENDIF() + + # set zip as default if addon-package is called without PACKAGE_XXX +- set(CPACK_GENERATOR "ZIP") +- set(ext "zip") +- if(PACKAGE_ZIP OR PACKAGE_TGZ) +- if(PACKAGE_TGZ) +- set(CPACK_GENERATOR "TGZ") +- set(ext "tar.gz") +- endif() +- set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) ++ SET(CPACK_GENERATOR "ZIP") ++ SET(ext "zip") ++ IF(PACKAGE_ZIP OR PACKAGE_TGZ) ++ IF(PACKAGE_TGZ) ++ SET(CPACK_GENERATOR "TGZ") ++ SET(ext "tar.gz") ++ ENDIF(PACKAGE_TGZ) ++ SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) + set(CPACK_PACKAGE_FILE_NAME addon) +- if(CMAKE_BUILD_TYPE STREQUAL "Release") +- set(CPACK_STRIP_FILES TRUE) +- endif() ++ IF(CMAKE_BUILD_TYPE STREQUAL "Release") ++ SET(CPACK_STRIP_FILES TRUE) ++ ENDIF(CMAKE_BUILD_TYPE STREQUAL "Release") + set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + set(CPACK_COMPONENTS_IGNORE_GROUPS 1) + list(APPEND CPACK_COMPONENTS_ALL ${target}-${${prefix}_VERSION}) + # Pack files together to create an archive +- install(DIRECTORY ${target} DESTINATION ./ COMPONENT ${target}-${${prefix}_VERSION} PATTERN "addon.xml.in" EXCLUDE) +- if(WIN32) ++ INSTALL(DIRECTORY ${target} DESTINATION ./ COMPONENT ${target}-${${prefix}_VERSION} PATTERN "addon.xml.in" EXCLUDE) ++ IF(WIN32) + if(NOT CPACK_PACKAGE_DIRECTORY) + # determine the temporary path + file(TO_CMAKE_PATH "$ENV{TEMP}" WIN32_TEMP_PATH) +@@ -115,49 +103,25 @@ macro (build_addon target prefix libs) + # is changed within Visual Studio) + string(REPLACE "$(Configuration)" "${CMAKE_BUILD_TYPE}" LIBRARY_LOCATION "${LIBRARY_LOCATION}") + +- if(${prefix}_SOURCES) +- # install the generated DLL file +- install(PROGRAMS ${LIBRARY_LOCATION} DESTINATION ${target} +- COMPONENT ${target}-${${prefix}_VERSION}) ++ # install the generated DLL file ++ INSTALL(PROGRAMS ${LIBRARY_LOCATION} DESTINATION ${target} ++ COMPONENT ${target}-${${prefix}_VERSION}) + +- if(CMAKE_BUILD_TYPE MATCHES Debug) +- # for debug builds also install the PDB file +- get_filename_component(LIBRARY_DIR ${LIBRARY_LOCATION} DIRECTORY) +- install(FILES ${LIBRARY_DIR}/${target}.pdb DESTINATION ${target} +- COMPONENT ${target}-${${prefix}_VERSION}) +- endif() +- endif() +- if (${prefix}_CUSTOM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 0 FROM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 1 TO_BINARY) +- install(FILES ${FROM_BINARY} DESTINATION ${target} RENAME ${TO_BINARY}) +- endif() +- if(${prefix}_CUSTOM_DATA) +- install(DIRECTORY ${${prefix}_CUSTOM_DATA} DESTINATION ${target}/resources) +- endif() +- else() ++ IF(CMAKE_BUILD_TYPE MATCHES Debug) ++ # for debug builds also install the PDB file ++ get_filename_component(LIBRARY_DIR ${LIBRARY_LOCATION} DIRECTORY) ++ INSTALL(FILES ${LIBRARY_DIR}/${target}.pdb DESTINATION ${target} ++ COMPONENT ${target}-${${prefix}_VERSION}) ++ ENDIF() ++ ELSE(WIN32) + if(NOT CPACK_PACKAGE_DIRECTORY) + set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}) + endif() +- if(${prefix}_SOURCES) +- install(TARGETS ${target} DESTINATION ${target} +- COMPONENT ${target}-${${prefix}_VERSION}) +- endif() +- if (${prefix}_CUSTOM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 0 FROM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 1 TO_BINARY) +- if(OS STREQUAL "android") +- set(TO_BINARY "lib${TO_BINARY}") +- endif() +- install(FILES ${FROM_BINARY} DESTINATION ${target} RENAME ${TO_BINARY} +- COMPONENT ${target}-${${prefix}_VERSION}) +- endif() +- if(${prefix}_CUSTOM_DATA) +- install(DIRECTORY ${${prefix}_CUSTOM_DATA} DESTINATION ${target}/resources) +- endif() +- endif() ++ INSTALL(TARGETS ${target} DESTINATION ${target} ++ COMPONENT ${target}-${${prefix}_VERSION}) ++ ENDIF(WIN32) + add_cpack_workaround(${target} ${${prefix}_VERSION} ${ext}) +- else() ++ ELSE(PACKAGE_ZIP OR PACKAGE_TGZ) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR NOT CMAKE_INSTALL_PREFIX) + message(STATUS "setting install paths to match ${APP_NAME}: CMAKE_INSTALL_PREFIX: ${${APP_NAME_UC}_PREFIX}") +@@ -173,30 +137,11 @@ macro (build_addon target prefix libs) + else() + set(CMAKE_INSTALL_LIBDIR "lib/${APP_NAME_LC}") + endif() +- if(${prefix}_SOURCES) +- install(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}/addons/${target}) +- endif() +- if (${prefix}_CUSTOM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 0 FROM_BINARY) +- list(GET ${prefix}_CUSTOM_BINARY 1 TO_BINARY) +- if(OS STREQUAL "android") +- set(TO_BINARY "lib${TO_BINARY}") +- endif() +- install(FILES ${FROM_BINARY} DESTINATION ${CMAKE_INSTALL_LIBDIR}/addons/${target} RENAME ${TO_BINARY}) +- endif() +- install(DIRECTORY ${target} DESTINATION share/${APP_NAME_LC}/addons PATTERN "addon.xml.in" EXCLUDE) +- if(${prefix}_CUSTOM_DATA) +- install(DIRECTORY ${${prefix}_CUSTOM_DATA} DESTINATION share/${APP_NAME_LC}/addons/${target}/resources) +- endif() +- endif() ++ INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}/addons/${target}) ++ INSTALL(DIRECTORY ${target} DESTINATION share/${APP_NAME_LC}/addons PATTERN "addon.xml.in" EXCLUDE) ++ ENDIF(PACKAGE_ZIP OR PACKAGE_TGZ) + if(${APP_NAME_UC}_BUILD_DIR) + file(GLOB_RECURSE files ${CMAKE_CURRENT_SOURCE_DIR}/${target}/*) +- if(${prefix}_CUSTOM_DATA) +- add_custom_command(TARGET ${target} POST_BUILD +- COMMAND ${CMAKE_COMMAND} -E copy_directory +- ${${prefix}_CUSTOM_DATA} +- ${${APP_NAME_UC}_BUILD_DIR}/addons/${target}/resources) +- endif() + foreach(file ${files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/${target}/" "" name "${file}") + # A good way to deal with () in filenames +@@ -216,30 +161,30 @@ function (kodi_find_path var_name filename search_path strip_file) + file(GLOB_RECURSE PATH_TO_FILE ${search_path} ${filename}) + if(strip_file) + string(REPLACE ${filename} "" PATH_TO_FILE ${PATH_TO_FILE}) +- endif() ++ endif(strip_file) + set (${var_name} ${PATH_TO_FILE} PARENT_SCOPE) + endfunction() + + # Cmake build options + include(AddOptions) + include(TestCXXAcceptsFlag) +-option(PACKAGE_ZIP "Package Zip file?" OFF) +-option(PACKAGE_TGZ "Package TGZ file?" OFF) +-option(BUILD_SHARED_LIBS "Build shared libs?" ON) ++OPTION(PACKAGE_ZIP "Package Zip file?" OFF) ++OPTION(PACKAGE_TGZ "Package TGZ file?" OFF) ++OPTION(BUILD_SHARED_LIBS "Build shared libs?" ON) + + # LTO support? + CHECK_CXX_ACCEPTS_FLAG("-flto" HAVE_LTO) +-if(HAVE_LTO) +- option(USE_LTO "use link time optimization" OFF) +- if(USE_LTO) ++IF(HAVE_LTO) ++ OPTION(USE_LTO "use link time optimization" OFF) ++ IF(USE_LTO) + add_options(ALL_LANGUAGES ALL_BUILDS "-flto") +- endif() +-endif() ++ ENDIF(USE_LTO) ++ENDIF(HAVE_LTO) + + # set this to try linking dependencies as static as possible +-if(ADDONS_PREFER_STATIC_LIBS) +- set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) +-endif() ++IF(ADDONS_PREFER_STATIC_LIBS) ++ SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) ++ENDIF(ADDONS_PREFER_STATIC_LIBS) + + if(${APP_NAME_UC}_BUILD_DIR) + list(APPEND CMAKE_PREFIX_PATH ${${APP_NAME_UC}_BUILD_DIR}/build) +diff --git a/project/cmake/scripts/common/CheckTargetPlatform.cmake b/project/cmake/scripts/common/CheckTargetPlatform.cmake +index 199071d..fc8b403 100644 +--- a/project/cmake/scripts/common/CheckTargetPlatform.cmake ++++ b/project/cmake/scripts/common/CheckTargetPlatform.cmake +@@ -21,11 +21,11 @@ function(check_target_platform dir target_platform build) + if(${platform_first} STREQUAL "!") + # extract the platform + string(LENGTH ${platform} platform_length) +- math(EXPR platform_length "${platform_length} - 1") ++ MATH(EXPR platform_length "${platform_length} - 1") + string(SUBSTRING ${platform} 1 ${platform_length} platform) + + # check if the current platform does not match the extracted platform +- if(NOT ${platform} STREQUAL ${target_platform}) ++ if (NOT ${platform} STREQUAL ${target_platform}) + set(${build} TRUE) + endif() + endif() +diff --git a/project/cmake/scripts/common/GenerateVersionedFiles.cmake b/project/cmake/scripts/common/GenerateVersionedFiles.cmake +index e105b27..c4ac549 100644 +--- a/project/cmake/scripts/common/GenerateVersionedFiles.cmake ++++ b/project/cmake/scripts/common/GenerateVersionedFiles.cmake +@@ -3,16 +3,9 @@ include(${CORE_SOURCE_DIR}/project/cmake/scripts/common/Macros.cmake) + core_find_versions() + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/addons/xbmc.addon) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/addons/kodi.guilib) +- +-# configure_file without dependency tracking +-# configure_file would register additional file dependencies that interfere +-# with the ones from add_custom_command (and the generation would happen twice) +-function(generate_versioned_file _SRC _DEST) +- file(READ ${CORE_SOURCE_DIR}/${_SRC} file_content) +- string(CONFIGURE "${file_content}" file_content @ONLY) +- file(WRITE ${CMAKE_BINARY_DIR}/${_DEST} "${file_content}") +-endfunction() +- +-generate_versioned_file(addons/xbmc.addon/addon.xml.in addons/xbmc.addon/addon.xml) +-generate_versioned_file(addons/kodi.guilib/addon.xml.in addons/kodi.guilib/addon.xml) +-generate_versioned_file(xbmc/CompileInfo.cpp.in ${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp) ++configure_file(${CORE_SOURCE_DIR}/addons/xbmc.addon/addon.xml.in ++ ${CMAKE_BINARY_DIR}/addons/xbmc.addon/addon.xml @ONLY) ++configure_file(${CORE_SOURCE_DIR}/addons/kodi.guilib/addon.xml.in ++ ${CMAKE_BINARY_DIR}/addons/kodi.guilib/addon.xml @ONLY) ++configure_file(${CORE_SOURCE_DIR}/xbmc/CompileInfo.cpp.in ++ ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp @ONLY) +diff --git a/project/cmake/scripts/common/GeneratorSetup.cmake b/project/cmake/scripts/common/GeneratorSetup.cmake +index a19730a..75083ca 100644 +--- a/project/cmake/scripts/common/GeneratorSetup.cmake ++++ b/project/cmake/scripts/common/GeneratorSetup.cmake +@@ -22,8 +22,3 @@ else() + set(CORE_BUILD_CONFIG ${CMAKE_BUILD_TYPE}) + message(STATUS "Generator: Single-configuration: ${CMAKE_BUILD_TYPE} (${CMAKE_GENERATOR})") + endif() +- +-# Ninja needs CMake 3.2 due to ExternalProject BUILD_BYPRODUCTS usage +-if(CMAKE_GENERATOR STREQUAL Ninja AND CMAKE_VERSION VERSION_LESS 3.2) +- message(FATAL_ERROR "Generator: Ninja requires CMake 3.2 or later") +-endif() +diff --git a/project/cmake/scripts/common/HandleDepends.cmake b/project/cmake/scripts/common/HandleDepends.cmake +index 4aca6ba..f44c87a 100644 +--- a/project/cmake/scripts/common/HandleDepends.cmake ++++ b/project/cmake/scripts/common/HandleDepends.cmake +@@ -10,7 +10,6 @@ function(add_addon_depends addon searchpath) + list(APPEND cmake_input_files ${cmake_input_files2}) + + foreach(file ${cmake_input_files}) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${file}) + if(NOT (file MATCHES CMakeLists.txt OR + file MATCHES install.txt OR + file MATCHES noinstall.txt OR +@@ -46,7 +45,6 @@ function(add_addon_depends addon searchpath) + + # check if there are any library specific flags that need to be passed on + if(EXISTS ${dir}/flags.txt) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${dir}/flags.txt) + file(STRINGS ${dir}/flags.txt extraflags) + separate_arguments(extraflags) + message(STATUS "${id} extraflags: ${extraflags}") +@@ -72,17 +70,16 @@ function(add_addon_depends addon searchpath) + + if(CMAKE_TOOLCHAIN_FILE) + list(APPEND BUILD_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}) +- message("toolchain specified") +- message(${BUILD_ARGS}) ++ MESSAGE("toolchain specified") ++ MESSAGE(${BUILD_ARGS}) + endif() + + # if there's a CMakeLists.txt use it to prepare the build + set(PATCH_FILE ${BUILD_DIR}/${id}/tmp/patch.cmake) + if(EXISTS ${dir}/CMakeLists.txt) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${dir}/CMakeLists.txt) + file(APPEND ${PATCH_FILE} + "file(COPY ${dir}/CMakeLists.txt +- DESTINATION ${BUILD_DIR}/${id}/src/${id})\n") ++ DESTINATION ${BUILD_DIR}/${id}/src/${id})\n") + endif() + + # check if we have patches to apply +@@ -107,7 +104,6 @@ function(add_addon_depends addon searchpath) + endif() + endif() + +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${patch}) + file(APPEND ${PATCH_FILE} + "execute_process(COMMAND ${PATCH_PROGRAM} -p1 -i \"${patch}\")\n") + endforeach() +@@ -129,7 +125,6 @@ function(add_addon_depends addon searchpath) + + # check if there's a deps.txt containing dependencies on other libraries + if(EXISTS ${dir}/deps.txt) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${dir}/deps.txt) + file(STRINGS ${dir}/deps.txt deps) + message(STATUS "${id} depends: ${deps}") + else() +@@ -138,7 +133,6 @@ function(add_addon_depends addon searchpath) + + if(CROSS_AUTOCONF AND AUTOCONF_FILES) + foreach(afile ${AUTOCONF_FILES}) +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${afile}) + file(APPEND ${PATCH_FILE} + "message(STATUS \"AUTOCONF: copying ${afile} to ${BUILD_DIR}/${id}/src/${id}\")\n + file(COPY ${afile} DESTINATION ${BUILD_DIR}/${id}/src/${id})\n") +@@ -147,7 +141,7 @@ function(add_addon_depends addon searchpath) + + # if the patch file exists we need to set the PATCH_COMMAND + set(PATCH_COMMAND "") +- if(EXISTS ${PATCH_FILE}) ++ if (EXISTS ${PATCH_FILE}) + set(PATCH_COMMAND ${CMAKE_COMMAND} -P ${PATCH_FILE}) + endif() + +diff --git a/project/cmake/scripts/common/Macros.cmake b/project/cmake/scripts/common/Macros.cmake +index b8dd860..de2a77c 100644 +--- a/project/cmake/scripts/common/Macros.cmake ++++ b/project/cmake/scripts/common/Macros.cmake +@@ -176,7 +176,7 @@ endfunction() + # helper macro for optional deps + macro(setup_enable_switch) + string(TOUPPER ${dep} depup) +- if(ARGV1) ++ if (ARGV1) + set(enable_switch ${ARGV1}) + else() + set(enable_switch ENABLE_${depup}) +@@ -235,11 +235,10 @@ function(core_file_read_filtered result filepattern) + if(VERBOSE) + message(STATUS "core_file_read_filtered - filename: ${filename}") + endif() +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filename}) + file(STRINGS ${filename} fstrings REGEX "^[^#//]") + foreach(fstring ${fstrings}) + string(REGEX REPLACE "^(.*)#(.*)" "\\1" fstring ${fstring}) +- string(REGEX REPLACE "[ \n\r\t]//.*" "" fstring ${fstring}) ++ string(REGEX REPLACE "//.*" "" fstring ${fstring}) + string(STRIP ${fstring} fstring) + list(APPEND filename_strings ${fstring}) + endforeach() +@@ -261,7 +260,7 @@ function(core_add_subdirs_from_filelist files) + string(STRIP ${filename} filename) + core_file_read_filtered(fstrings ${filename}) + foreach(subdir ${fstrings}) +- string(REPLACE " " ";" subdir ${subdir}) ++ STRING_SPLIT(subdir " " ${subdir}) + list(GET subdir 0 subdir_src) + list(GET subdir -1 subdir_dest) + if(VERBOSE) +@@ -294,7 +293,6 @@ macro(core_add_optional_subdirs_from_filelist pattern) + if(VERBOSE) + message(STATUS "core_add_optional_subdirs_from_filelist - reading file: ${filename}") + endif() +- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filename}) + file(STRINGS ${filename} fstrings REGEX "^[^#//]") + foreach(line ${fstrings}) + string(REPLACE " " ";" line "${line}") +@@ -318,7 +316,7 @@ macro(core_add_optional_subdirs_from_filelist pattern) + endmacro() + + macro(today RESULT) +- if(WIN32) ++ if (WIN32) + execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT}) + string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}}) + elseif(UNIX) +@@ -338,12 +336,12 @@ function(core_find_git_rev) + execute_process(COMMAND ${GIT_EXECUTABLE} diff-files --ignore-submodules --quiet -- + RESULT_VARIABLE status_code + WORKING_DIRECTORY ${CORE_SOURCE_DIR}) +- if(NOT status_code) ++ if (NOT status_code) + execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --ignore-submodules --quiet HEAD -- + RESULT_VARIABLE status_code + WORKING_DIRECTORY ${CORE_SOURCE_DIR}) + endif() +- if(status_code) ++ if (status_code) + execute_process(COMMAND ${GIT_EXECUTABLE} log -n 1 --pretty=format:"%h-dirty" HEAD + OUTPUT_VARIABLE HASH + WORKING_DIRECTORY ${CORE_SOURCE_DIR}) +@@ -369,32 +367,13 @@ function(core_find_git_rev) + endif() + endfunction() + +-# Parses version.txt and libKODI_guilib.h and sets variables +-# used to construct dirs structure, file naming, API version, etc. +-# +-# The following variables are set from version.txt: +-# APP_NAME - app name +-# APP_NAME_LC - lowercased app name +-# APP_NAME_UC - uppercased app name +-# COMPANY_NAME - company name +-# APP_VERSION_MAJOR - the app version major +-# APP_VERSION_MINOR - the app version minor +-# APP_VERSION_TAG - the app version tag +-# APP_VERSION_TAG_LC - lowercased app version tag +-# APP_VERSION - the app version (${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}-${APP_VERSION_TAG}) +-# APP_ADDON_API - the addon API version in the form of 16.9.702 +-# FILE_VERSION - file version in the form of 16,9,702,0 - Windows only +-# +-# The following variables are set from libKODI_guilib.h: +-# guilib_version - current ADDONGUI API version +-# guilib_version_min - minimal ADDONGUI API version + macro(core_find_versions) + include(CMakeParseArguments) + core_file_read_filtered(version_list ${CORE_SOURCE_DIR}/version.txt) + string(REPLACE " " ";" version_list "${version_list}") +- cmake_parse_arguments(APP "" "APP_NAME;COMPANY_NAME;WEBSITE;VERSION_MAJOR;VERSION_MINOR;VERSION_TAG;VERSION_CODE;ADDON_API" "" ${version_list}) ++ cmake_parse_arguments(APP "" "VERSION_MAJOR;VERSION_MINOR;VERSION_TAG;VERSION_CODE;ADDON_API;APP_NAME;COMPANY_NAME" "" ${version_list}) + +- set(APP_NAME ${APP_APP_NAME}) # inconsistency but APP_APP_NAME looks weird ++ set(APP_NAME ${APP_APP_NAME}) # inconsistency in upstream + string(TOLOWER ${APP_APP_NAME} APP_NAME_LC) + string(TOUPPER ${APP_APP_NAME} APP_NAME_UC) + set(COMPANY_NAME ${APP_COMPANY_NAME}) +@@ -408,17 +387,4 @@ macro(core_find_versions) + string(REGEX REPLACE ".*\"(.*)\"" "\\1" guilib_version ${guilib_version}) + file(STRINGS ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h guilib_version_min REGEX "^.*GUILIB_MIN_API_VERSION (.*)$") + string(REGEX REPLACE ".*\"(.*)\"" "\\1" guilib_version_min ${guilib_version_min}) +- # unset variables not used anywhere else +- unset(version_list) +- unset(APP_APP_NAME) +- +- # bail if we can't parse version.txt +- if(NOT DEFINED APP_VERSION_MAJOR OR NOT DEFINED APP_VERSION_MINOR) +- message(FATAL_ERROR "Could not determine app version! Make sure that ${CORE_SOURCE_DIR}/version.txt exists") +- endif() +- +- # bail if we can't parse libKODI_guilib.h +- if(NOT DEFINED guilib_version OR NOT DEFINED guilib_version_min) +- message(FATAL_ERROR "Could not determine add-on API version! Make sure that ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h exists") +- endif() + endmacro() +diff --git a/project/cmake/scripts/common/ManageString.cmake b/project/cmake/scripts/common/ManageString.cmake +new file mode 100644 +index 0000000..7321f4c +--- /dev/null ++++ b/project/cmake/scripts/common/ManageString.cmake +@@ -0,0 +1,235 @@ ++# - Collection of String utility macros. ++# Defines the following macros: ++# STRING_TRIM(var str [NOUNQUOTE]) ++# - Trim a string by removing the leading and trailing spaces, ++# just like STRING(STRIP ...) in CMake 2.6 and later. ++# This macro is needed as CMake 2.4 does not support STRING(STRIP ..) ++# This macro also remove quote and double quote marks around the string, ++# unless NOUNQUOTE is defined. ++# * Parameters: ++# + var: A variable that stores the result. ++# + str: A string. ++# + NOUNQUOTE: (Optional) do not remove the double quote mark around the string. ++# ++# STRING_UNQUOTE(var str) ++# - Remove double quote marks and quote marks around a string. ++# If the string is not quoted, then it returns an empty string. ++# * Parameters: ++# + var: A variable that stores the result. ++# + str: A string. ++# ++# STRING_JOIN(var delimiter str_list [str...]) ++# - Concatenate strings, with delimiter inserted between strings. ++# * Parameters: ++# + var: A variable that stores the result. ++# + str_list: A list of string. ++# + str: (Optional) more string to be join. ++# ++# STRING_SPLIT(var delimiter str [NOESCAPE_SEMICOLON]) ++# - Split a string into a list using a delimiter, which can be in 1 or more ++# characters long. ++# * Parameters: ++# + var: A variable that stores the result. ++# + delimiter: To separate a string. ++# + str: A string. ++# + NOESCAPE_SEMICOLON: (Optional) Do not escape semicolons. ++# ++ ++IF(NOT DEFINED _MANAGE_STRING_CMAKE_) ++ SET(_MANAGE_STRING_CMAKE_ "DEFINED") ++ ++ MACRO(STRING_TRIM var str) ++ SET(${var} "") ++ IF (NOT "${ARGN}" STREQUAL "NOUNQUOTE") ++ # Need not trim a quoted string. ++ STRING_UNQUOTE(_var "${str}") ++ IF(NOT _var STREQUAL "") ++ # String is quoted ++ SET(${var} "${_var}") ++ ENDIF(NOT _var STREQUAL "") ++ ENDIF(NOT "${ARGN}" STREQUAL "NOUNQUOTE") ++ ++ IF(${var} STREQUAL "") ++ SET(_var_1 "${str}") ++ STRING(REGEX REPLACE "^[ \t\r\n]+" "" _var_2 "${str}" ) ++ STRING(REGEX REPLACE "[ \t\r\n]+$" "" _var_3 "${_var_2}" ) ++ SET(${var} "${_var_3}") ++ ENDIF(${var} STREQUAL "") ++ ENDMACRO(STRING_TRIM var str) ++ ++ # Internal macro ++ # Variable cannot be escaped here, as variable is already substituted ++ # at the time it passes to this macro. ++ MACRO(STRING_ESCAPE var str) ++ # ';' and '\' are tricky, need to be encoded. ++ # '#' => '#H' ++ # '\' => '#B' ++ # ';' => '#S' ++ SET(_NOESCAPE_SEMICOLON "") ++ SET(_NOESCAPE_HASH "") ++ ++ FOREACH(_arg ${ARGN}) ++ IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") ++ ELSEIF(${_arg} STREQUAL "NOESCAPE_HASH") ++ SET(_NOESCAPE_HASH "NOESCAPE_HASH") ++ ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ ENDFOREACH(_arg) ++ ++ IF(_NOESCAPE_HASH STREQUAL "") ++ STRING(REGEX REPLACE "#" "#H" _ret "${str}") ++ ELSE(_NOESCAPE_HASH STREQUAL "") ++ SET(_ret "${str}") ++ ENDIF(_NOESCAPE_HASH STREQUAL "") ++ ++ STRING(REGEX REPLACE "\\\\" "#B" _ret "${_ret}") ++ IF(_NOESCAPE_SEMICOLON STREQUAL "") ++ STRING(REGEX REPLACE ";" "#S" _ret "${_ret}") ++ ENDIF(_NOESCAPE_SEMICOLON STREQUAL "") ++ SET(${var} "${_ret}") ++ ENDMACRO(STRING_ESCAPE var str) ++ ++ MACRO(STRING_UNESCAPE var str) ++ # '#B' => '\' ++ # '#H' => '#' ++ # '#D' => '$' ++ # '#S' => ';' ++ SET(_ESCAPE_VARIABLE "") ++ SET(_NOESCAPE_SEMICOLON "") ++ SET(_ret "${str}") ++ FOREACH(_arg ${ARGN}) ++ IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") ++ ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE") ++ SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE") ++ STRING(REGEX REPLACE "#D" "$" _ret "${_ret}") ++ ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ ENDFOREACH(_arg) ++ ++ STRING(REGEX REPLACE "#B" "\\\\" _ret "${_ret}") ++ IF(_NOESCAPE_SEMICOLON STREQUAL "") ++ # ';' => '#S' ++ STRING(REGEX REPLACE "#S" "\\\\;" _ret "${_ret}") ++ ELSE(_NOESCAPE_SEMICOLON STREQUAL "") ++ STRING(REGEX REPLACE "#S" ";" _ret "${_ret}") ++ ENDIF(_NOESCAPE_SEMICOLON STREQUAL "") ++ ++ IF(NOT _ESCAPE_VARIABLE STREQUAL "") ++ # '#D' => '$' ++ STRING(REGEX REPLACE "#D" "$" _ret "${_ret}") ++ ENDIF(NOT _ESCAPE_VARIABLE STREQUAL "") ++ STRING(REGEX REPLACE "#H" "#" _ret "${_ret}") ++ SET(${var} "${_ret}") ++ ENDMACRO(STRING_UNESCAPE var str) ++ ++ ++ MACRO(STRING_UNQUOTE var str) ++ STRING_ESCAPE(_ret "${str}" ${ARGN}) ++ IF(_ret MATCHES "^[ \t\r\n]+") ++ STRING(REGEX REPLACE "^[ \t\r\n]+" "" _ret "${_ret}") ++ ENDIF(_ret MATCHES "^[ \t\r\n]+") ++ IF(_ret MATCHES "^\"") ++ # Double quote ++ STRING(REGEX REPLACE "\"\(.*\)\"[ \t\r\n]*$" "\\1" _ret "${_ret}") ++ ELSEIF(_ret MATCHES "^'") ++ # Single quote ++ STRING(REGEX REPLACE "'\(.*\)'[ \t\r\n]*$" "\\1" _ret "${_ret}") ++ ELSE(_ret MATCHES "^\"") ++ SET(_ret "") ++ ENDIF(_ret MATCHES "^\"") ++ ++ # Unencoding ++ STRING_UNESCAPE(${var} "${_ret}" ${ARGN}) ++ ENDMACRO(STRING_UNQUOTE var str) ++ ++ MACRO(STRING_JOIN var delimiter str_list) ++ SET(_ret "") ++ FOREACH(_str ${str_list}) ++ IF(_ret STREQUAL "") ++ SET(_ret "${_str}") ++ ELSE(_ret STREQUAL "") ++ SET(_ret "${_ret}${delimiter}${_str}") ++ ENDIF(_ret STREQUAL "") ++ ENDFOREACH(_str ${str_list}) ++ ++ FOREACH(_str ${ARGN}) ++ IF(_ret STREQUAL "") ++ SET(_ret "${_str}") ++ ELSE(_ret STREQUAL "") ++ SET(_ret "${_ret}${delimiter}${_str}") ++ ENDIF(_ret STREQUAL "") ++ ENDFOREACH(_str ${str_list}) ++ SET(${var} "${_ret}") ++ ENDMACRO(STRING_JOIN var delimiter str_list) ++ ++ MACRO(STRING_SPLIT var delimiter str) ++ SET(_max_tokens "") ++ SET(_NOESCAPE_SEMICOLON "") ++ SET(_ESCAPE_VARIABLE "") ++ FOREACH(_arg ${ARGN}) ++ IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") ++ ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE") ++ SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE") ++ ELSE(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ SET(_max_tokens ${_arg}) ++ ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") ++ ENDFOREACH(_arg) ++ ++ IF(NOT _max_tokens) ++ SET(_max_tokens -1) ++ ENDIF(NOT _max_tokens) ++ ++ STRING_ESCAPE(_str "${str}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) ++ STRING_ESCAPE(_delimiter "${delimiter}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) ++ ++ SET(_str_list "") ++ SET(_token_count 0) ++ STRING(LENGTH "${_delimiter}" _de_len) ++ ++ WHILE(NOT _token_count EQUAL _max_tokens) ++ MATH(EXPR _token_count ${_token_count}+1) ++ IF(_token_count EQUAL _max_tokens) ++ # Last token, no need splitting ++ SET(_str_list ${_str_list} "${_str}") ++ ELSE(_token_count EQUAL _max_tokens) ++ # in case encoded characters are delimiters ++ STRING(LENGTH "${_str}" _str_len) ++ SET(_index 0) ++ SET(_token "") ++ SET(_str_remain "") ++ MATH(EXPR _str_end ${_str_len}-${_de_len}+1) ++ SET(_bound "k") ++ WHILE(_index LESS _str_end) ++ STRING(SUBSTRING "${_str}" ${_index} ${_de_len} _str_cursor) ++ IF(_str_cursor STREQUAL _delimiter) ++ # Get the token ++ STRING(SUBSTRING "${_str}" 0 ${_index} _token) ++ # Get the rest ++ MATH(EXPR _rest_index ${_index}+${_de_len}) ++ MATH(EXPR _rest_len ${_str_len}-${_index}-${_de_len}) ++ STRING(SUBSTRING "${_str}" ${_rest_index} ${_rest_len} _str_remain) ++ SET(_index ${_str_end}) ++ ELSE(_str_cursor STREQUAL _delimiter) ++ MATH(EXPR _index ${_index}+1) ++ ENDIF(_str_cursor STREQUAL _delimiter) ++ ENDWHILE(_index LESS _str_end) ++ ++ IF(_str_remain STREQUAL "") ++ # Meaning: end of string ++ LIST(APPEND _str_list "${_str}") ++ SET(_max_tokens ${_token_count}) ++ ELSE(_str_remain STREQUAL "") ++ LIST(APPEND _str_list "${_token}") ++ SET(_str "${_str_remain}") ++ ENDIF(_str_remain STREQUAL "") ++ ENDIF(_token_count EQUAL _max_tokens) ++ ENDWHILE(NOT _token_count EQUAL _max_tokens) ++ ++ ++ # Unencoding ++ STRING_UNESCAPE(${var} "${_str_list}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) ++ ENDMACRO(STRING_SPLIT var delimiter str) ++ ++ENDIF(NOT DEFINED _MANAGE_STRING_CMAKE_) ++ +diff --git a/project/cmake/scripts/common/PathSetup.cmake b/project/cmake/scripts/common/PathSetup.cmake +new file mode 100644 +index 0000000..47b1a96 +--- /dev/null ++++ b/project/cmake/scripts/common/PathSetup.cmake +@@ -0,0 +1,3 @@ ++# This script configures installation paths ++ ++include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/PathSetup.cmake) +diff --git a/project/cmake/scripts/common/PrepareEnv.cmake b/project/cmake/scripts/common/PrepareEnv.cmake +index bf258d5..fadca48 100644 +--- a/project/cmake/scripts/common/PrepareEnv.cmake ++++ b/project/cmake/scripts/common/PrepareEnv.cmake +@@ -1,6 +1,25 @@ +-# parse version.txt and libKODI_guilib.h to get the version and API info +-include(${CORE_SOURCE_DIR}/project/cmake/scripts/common/Macros.cmake) +-core_find_versions() ++# parse version.txt to get the version info ++if(EXISTS "${CORE_SOURCE_DIR}/version.txt") ++ file(STRINGS "${CORE_SOURCE_DIR}/version.txt" versions) ++ foreach (version ${versions}) ++ if(version MATCHES "^VERSION_.*") ++ string(REGEX MATCH "^[^ ]+" version_name ${version}) ++ string(REPLACE "${version_name} " "" version_value ${version}) ++ set(APP_${version_name} "${version_value}") ++ else() ++ string(REGEX MATCH "^[^ ]+" name ${version}) ++ string(REPLACE "${name} " "" value ${version}) ++ set(${name} "${value}") ++ endif() ++ endforeach() ++ string(TOLOWER ${APP_NAME} APP_NAME_LC) ++ string(TOUPPER ${APP_NAME} APP_NAME_UC) ++endif() ++ ++# bail if we can't parse versions ++if(NOT DEFINED APP_VERSION_MAJOR OR NOT DEFINED APP_VERSION_MINOR) ++ message(FATAL_ERROR "Could not determine app version! make sure that ${CORE_SOURCE_DIR}/version.txt exists") ++endif() + + # in case we need to download something, set KODI_MIRROR to the default if not alread set + if(NOT DEFINED KODI_MIRROR) +@@ -62,7 +81,7 @@ foreach(binding ${bindings}) + # auto-generate header files for backwards compatibility to xbmc with deprecation warning + # but only do it if the file doesn't already exist + get_filename_component(headerfile ${header} NAME) +- if(NOT EXISTS "${XBMC_INCLUDE_DIR}/${headerfile}") ++ if (NOT EXISTS "${XBMC_INCLUDE_DIR}/${headerfile}") + file(WRITE ${XBMC_INCLUDE_DIR}/${headerfile} + "#pragma once + #define DEPRECATION_WARNING \"Including xbmc/${headerfile} has been deprecated, please use kodi/${headerfile}\" +diff --git a/project/cmake/scripts/darwin/ArchSetup.cmake b/project/cmake/scripts/darwin/ArchSetup.cmake +new file mode 100644 +index 0000000..d4d7f35 +--- /dev/null ++++ b/project/cmake/scripts/darwin/ArchSetup.cmake +@@ -0,0 +1,33 @@ ++if(NOT CMAKE_TOOLCHAIN_FILE) ++ message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE required for darwin. See ${PROJECT_SOURCE_DIR}/README.md") ++endif() ++ ++set(CORE_MAIN_SOURCE ${CORE_SOURCE_DIR}/xbmc/platform/posix/main.cpp ++ ${CORE_SOURCE_DIR}/xbmc/platform/darwin/osx/SDLMain.mm ++ ${CORE_SOURCE_DIR}/xbmc/platform/darwin/osx/SDLMain.h) ++ ++set(ARCH_DEFINES -D_LINUX -DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_OSX) ++set(SYSTEM_DEFINES -D_REENTRANT -D_FILE_DEFINED -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE ++ -D__STDC_CONSTANT_MACROS) ++set(PLATFORM_DIR linux) ++set(CMAKE_SYSTEM_NAME Darwin) ++if(WITH_ARCH) ++ set(ARCH ${WITH_ARCH}) ++else() ++ if(CPU STREQUAL x86_64 OR CPU STREQUAL i386) ++ set(ARCH x86-osx) ++ else() ++ message(SEND_ERROR "Unknown CPU: ${CPU}") ++ endif() ++endif() ++ ++find_package(CXX11 REQUIRED) ++ ++list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${NATIVEPREFIX}) ++ ++list(APPEND DEPLIBS "-framework DiskArbitration" "-framework IOKit" ++ "-framework IOSurface" "-framework SystemConfiguration" ++ "-framework ApplicationServices" "-framework AppKit" ++ "-framework CoreAudio" "-framework AudioToolbox" ++ "-framework CoreGraphics" "-framework CoreMedia" ++ "-framework VideoToolbox") +diff --git a/project/cmake/scripts/darwin/Install.cmake b/project/cmake/scripts/darwin/Install.cmake +new file mode 100644 +index 0000000..1f130d7 +--- /dev/null ++++ b/project/cmake/scripts/darwin/Install.cmake +@@ -0,0 +1,38 @@ ++# OSX packaging ++ ++set(PACKAGE_OUTPUT_DIR ${CMAKE_BINARY_DIR}/build/${CORE_BUILD_CONFIG}) ++ ++configure_file(${CORE_SOURCE_DIR}/xbmc/platform/darwin/osx/Info.plist.in ++ ${CMAKE_BINARY_DIR}/xbmc/platform/darwin/osx/Info.plist @ONLY) ++execute_process(COMMAND perl -p -i -e "s/r####/${APP_SCMID}/" ${CMAKE_BINARY_DIR}/xbmc/platform/darwin/osx/Info.plist) ++ ++add_custom_target(bundle ++ COMMAND ${CMAKE_COMMAND} -E copy $ ${PACKAGE_OUTPUT_DIR}/${APP_NAME} ++ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/DllPaths_generated.h ++ ${CMAKE_BINARY_DIR}/xbmc/DllPaths_generated.h ++ COMMAND "ACTION=build" ++ "TARGET_BUILD_DIR=${PACKAGE_OUTPUT_DIR}" ++ "TARGET_NAME=${APP_NAME}.app" ++ "APP_NAME=${APP_NAME}" ++ "SRCROOT=${CMAKE_BINARY_DIR}" ++ ${CORE_SOURCE_DIR}/tools/darwin/Support/CopyRootFiles-osx.command ++ COMMAND "XBMC_DEPENDS=${DEPENDS_PATH}" ++ "TARGET_BUILD_DIR=${PACKAGE_OUTPUT_DIR}" ++ "TARGET_NAME=${APP_NAME}.app" ++ "APP_NAME=${APP_NAME}" ++ "FULL_PRODUCT_NAME=${APP_NAME}.app" ++ "SRCROOT=${CMAKE_BINARY_DIR}" ++ ${CORE_SOURCE_DIR}/tools/darwin/Support/copyframeworks-osx.command) ++add_dependencies(bundle ${APP_NAME_LC} export-files pack-skins wrap-libraries generate_json_header XBMCHelper) ++ ++configure_file(${CORE_SOURCE_DIR}/tools/darwin/packaging/osx/mkdmg-osx.sh.in ++ ${CMAKE_BINARY_DIR}/tools/darwin/packaging/osx/mkdmg-osx.sh @ONLY) ++ ++add_custom_target(dmg ++ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CORE_SOURCE_DIR}/tools/darwin/packaging/osx/ ++ ${CMAKE_BINARY_DIR}/tools/darwin/packaging/osx/ ++ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CORE_SOURCE_DIR}/tools/darwin/packaging/media/osx/ ++ ${CMAKE_BINARY_DIR}/tools/darwin/packaging/media/osx/ ++ COMMAND ./mkdmg-osx.sh ${CORE_BUILD_CONFIG} ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tools/darwin/packaging/osx) ++add_dependencies(dmg bundle) +diff --git a/project/cmake/scripts/darwin/Macros.cmake b/project/cmake/scripts/darwin/Macros.cmake +new file mode 100644 +index 0000000..f4e1ce8 +--- /dev/null ++++ b/project/cmake/scripts/darwin/Macros.cmake +@@ -0,0 +1,110 @@ ++function(core_link_library lib wraplib) ++ if(CMAKE_GENERATOR MATCHES "Unix Makefiles") ++ set(wrapper_obj cores/dll-loader/exports/CMakeFiles/wrapper.dir/wrapper.c.o) ++ elseif(CMAKE_GENERATOR MATCHES "Xcode") ++ set(wrapper_obj cores/dll-loader/exports/kodi.build/$(CONFIGURATION)/wrapper.build/Objects-$(CURRENT_VARIANT)/$(CURRENT_ARCH)/wrapper.o) ++ else() ++ message(FATAL_ERROR "Unsupported generator in core_link_library") ++ endif() ++ ++ set(export -bundle -undefined dynamic_lookup -read_only_relocs suppress ++ -Wl,-alias_list,${CORE_BUILD_DIR}/cores/dll-loader/exports/wrapper.def ++ ${CORE_BUILD_DIR}/${wrapper_obj}) ++ set(extension ${CMAKE_SHARED_MODULE_SUFFIX}) ++ set(check_arg "") ++ if(TARGET ${lib}) ++ set(target ${lib}) ++ set(link_lib $) ++ set(check_arg ${ARGV2}) ++ set(data_arg ${ARGV3}) ++ else() ++ set(target ${ARGV2}) ++ set(link_lib ${lib}) ++ set(check_arg ${ARGV3}) ++ set(data_arg ${ARGV4}) ++ endif() ++ if(check_arg STREQUAL export) ++ set(export ${export} ++ -Wl,--version-script=${ARGV3}) ++ elseif(check_arg STREQUAL nowrap) ++ set(export -undefined dynamic_lookup -dynamiclib ${data_arg}) ++ set(extension ${CMAKE_SHARED_LIBRARY_SUFFIX}) ++ elseif(check_arg STREQUAL extras) ++ foreach(arg ${data_arg}) ++ list(APPEND export ${arg}) ++ endforeach() ++ endif() ++ get_filename_component(dir ${wraplib} PATH) ++ ++ # We can't simply pass the linker flags to the args section of the custom command ++ # because cmake will add quotes around it (and the linker will fail due to those). ++ # We need to do this handstand first ... ++ separate_arguments(CUSTOM_COMMAND_ARGS_LDFLAGS UNIX_COMMAND "${CMAKE_SHARED_LINKER_FLAGS}") ++ ++ add_custom_command(OUTPUT ${wraplib}-${ARCH}${extension} ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${dir} ++ COMMAND ${CMAKE_C_COMPILER} ++ ARGS ${CUSTOM_COMMAND_ARGS_LDFLAGS} ${export} -Wl,-force_load ${link_lib} ++ -o ${CMAKE_BINARY_DIR}/${wraplib}-${ARCH}${extension} ++ DEPENDS ${target} wrapper.def wrapper ++ VERBATIM) ++ ++ # Uncomment to create wrap_ targets for debugging ++ #get_filename_component(libname ${wraplib} NAME_WE) ++ #add_custom_target(wrap_${libname} ALL DEPENDS ${wraplib}-${ARCH}${extension}) ++ ++ list(APPEND WRAP_FILES ${wraplib}-${ARCH}${extension}) ++ set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE) ++endfunction() ++ ++function(find_soname lib) ++ cmake_parse_arguments(arg "REQUIRED" "" "" ${ARGN}) ++ ++ string(TOLOWER ${lib} liblow) ++ if(${lib}_LDFLAGS) ++ set(link_lib "${${lib}_LDFLAGS}") ++ else() ++ set(link_lib "${${lib}_LIBRARIES}") ++ endif() ++ ++ execute_process(COMMAND ${CMAKE_C_COMPILER} -print-search-dirs ++ COMMAND fgrep libraries: ++ COMMAND sed "s/[^=]*=\\(.*\\)/\\1/" ++ COMMAND sed "s/:/ /g" ++ ERROR_QUIET ++ OUTPUT_VARIABLE cc_lib_path ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ execute_process(COMMAND echo ${link_lib} ++ COMMAND sed "s/-L[ ]*//g" ++ COMMAND sed "s/-l[^ ]*//g" ++ ERROR_QUIET ++ OUTPUT_VARIABLE env_lib_path ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ ++ foreach(path ${cc_lib_path} ${env_lib_path}) ++ if(IS_DIRECTORY ${path}) ++ execute_process(COMMAND ls -- ${path}/lib${liblow}.dylib ++ ERROR_QUIET ++ OUTPUT_VARIABLE lib_file ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ else() ++ set(lib_file ${path}) ++ endif() ++ if(lib_file) ++ # we want the path/name that is embedded in the dylib ++ execute_process(COMMAND otool -L ${lib_file} ++ COMMAND grep -v lib${liblow}.dylib ++ COMMAND grep ${liblow} ++ COMMAND awk "{V=1; print $V}" ++ ERROR_QUIET ++ OUTPUT_VARIABLE filename ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ get_filename_component(${lib}_SONAME "${filename}" NAME) ++ message(STATUS "${lib} soname: ${${lib}_SONAME}") ++ endif() ++ endforeach() ++ if(arg_REQUIRED AND NOT ${lib}_SONAME) ++ message(FATAL_ERROR "Could not find dynamically loadable library ${lib}") ++ endif() ++ set(${lib}_SONAME ${${lib}_SONAME} PARENT_SCOPE) ++endfunction() +diff --git a/project/cmake/scripts/darwin/PathSetup.cmake b/project/cmake/scripts/darwin/PathSetup.cmake +new file mode 100644 +index 0000000..071dfd4 +--- /dev/null ++++ b/project/cmake/scripts/darwin/PathSetup.cmake +@@ -0,0 +1,32 @@ ++if(NOT prefix) ++ set(prefix ${DEPENDS_PATH}) ++endif() ++if(NOT exec_prefix) ++ set(exec_prefix ${prefix}) ++endif() ++if(NOT libdir) ++ set(libdir ${prefix}/lib) ++endif() ++if(NOT bindir) ++ set(bindir ${prefix}/bin) ++endif() ++if(NOT includedir) ++ set(includedir ${prefix}/include) ++endif() ++if(NOT datarootdir) ++ set(datarootdir ${prefix}/share) ++endif() ++if(NOT datadir) ++ set(datadir ${datarootdir}) ++endif() ++ ++list(APPEND final_message "-- PATH config --") ++list(APPEND final_message "Prefix: ${prefix}") ++list(APPEND final_message "Libdir: ${libdir}") ++list(APPEND final_message "Bindir: ${bindir}") ++list(APPEND final_message "Includedir: ${includedir}") ++list(APPEND final_message "Datarootdir: ${datarootdir}") ++list(APPEND final_message "Datadir: ${datadir}") ++ ++set(PATH_DEFINES -DBIN_INSTALL_PATH=\"${libdir}/kodi\" ++ -DINSTALL_PATH=\"${datarootdir}/kodi\") +diff --git a/project/cmake/scripts/ios/Macros.cmake b/project/cmake/scripts/ios/Macros.cmake +index 54c1b28..cc397fd 120000 +--- a/project/cmake/scripts/ios/Macros.cmake ++++ b/project/cmake/scripts/ios/Macros.cmake +@@ -1 +1 @@ +-../osx/Macros.cmake +\ No newline at end of file ++../darwin/Macros.cmake +\ No newline at end of file +diff --git a/project/cmake/scripts/ios/PathSetup.cmake b/project/cmake/scripts/ios/PathSetup.cmake +index d7f25b2..8303b28 120000 +--- a/project/cmake/scripts/ios/PathSetup.cmake ++++ b/project/cmake/scripts/ios/PathSetup.cmake +@@ -1 +1 @@ +-../osx/PathSetup.cmake +\ No newline at end of file ++../darwin/PathSetup.cmake +\ No newline at end of file +diff --git a/project/cmake/scripts/linux/Install.cmake b/project/cmake/scripts/linux/Install.cmake +index 67cb2ee..a326791 100644 +--- a/project/cmake/scripts/linux/Install.cmake ++++ b/project/cmake/scripts/linux/Install.cmake +@@ -14,11 +14,8 @@ else() + set(USE_OPENGLES 0) + endif() + +-# CMake config +-set(APP_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/${APP_NAME_LC}) +-set(APP_PREFIX ${CMAKE_INSTALL_PREFIX}) +-set(APP_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include/${APP_NAME_LC}) +-set(CXX11_SWITCH "-std=c++11") ++configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi.sh.in ++ ${CORE_BUILD_DIR}/scripts/${APP_NAME_LC} @ONLY) + + # Set XBMC_STANDALONE_SH_PULSE so we can insert PulseAudio block into kodi-standalone + if(EXISTS ${CORE_SOURCE_DIR}/tools/Linux/kodi-standalone.sh.pulse) +@@ -28,118 +25,86 @@ if(EXISTS ${CORE_SOURCE_DIR}/tools/Linux/kodi-standalone.sh.pulse) + endif() + endif() + +-# Configure startup scripts +-configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi.sh.in +- ${CORE_BUILD_DIR}/scripts/${APP_NAME_LC} @ONLY) + configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi-standalone.sh.in + ${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}-standalone @ONLY) + +- +-# Configure cmake files ++# cmake config ++set(APP_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/${APP_NAME_LC}) ++set(APP_PREFIX ${CMAKE_INSTALL_PREFIX}) ++set(APP_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include/${APP_NAME_LC}) ++set(CXX11_SWITCH "-std=c++11") + configure_file(${PROJECT_SOURCE_DIR}/KodiConfig.cmake.in +- ${CORE_BUILD_DIR}/scripts/${APP_NAME}Config.cmake @ONLY) +- +-# Configure xsession entry +-configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi-xsession.desktop.in +- ${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop @ONLY) +- +-# Install cmake files +-# TODO: revisit, refactor and nuke txt file globbing +-install(FILES ${cmake_files} DESTINATION lib/${APP_NAME_LC}) +-install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME}Config.cmake ++ ${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}Config.cmake @ONLY) ++install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}Config.cmake + ${PROJECT_SOURCE_DIR}/scripts/common/AddOptions.cmake + ${PROJECT_SOURCE_DIR}/scripts/common/AddonHelpers.cmake +- ${PROJECT_SOURCE_DIR}/scripts/linux/PathSetup.cmake + DESTINATION lib/${APP_NAME_LC}) ++install(FILES ${cmake_files} DESTINATION ${libdir}/${APP_NAME_LC}) + +-# Install app +-install(TARGETS ${APP_NAME_LC} DESTINATION lib/${APP_NAME_LC}) ++install(TARGETS ${APP_NAME_LC} DESTINATION ${libdir}/${APP_NAME_LC}) + if(ENABLE_X11 AND XRANDR_FOUND) +- install(TARGETS ${APP_NAME_LC}-xrandr DESTINATION lib/${APP_NAME_LC}) ++ install(TARGETS ${APP_NAME_LC}-xrandr DESTINATION ${libdir}/${APP_NAME_LC}) ++endif() ++ ++if(NOT EXISTS ${libdir}/xbmc) ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC}/ xbmc WORKING_DIRECTORY ${libdir})") ++endif() ++install(FILES ${addon_bindings} DESTINATION ${includedir}/${APP_NAME_LC}) ++if(NOT EXISTS ${includedir}/xbmc) ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC}/ xbmc WORKING_DIRECTORY ${includedir})") + endif() + +-# Install scripts + install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME_LC} + ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}-standalone +- DESTINATION bin) ++ DESTINATION ${bindir}) ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC} xbmc WORKING_DIRECTORY ${bindir})") ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC}-standalone xbmc-standalone WORKING_DIRECTORY ${bindir})") + +-# Install libraries +-foreach(wraplib ${WRAP_FILES}) +- get_filename_component(dir ${wraplib} PATH) +- install(PROGRAMS ${CMAKE_BINARY_DIR}/${wraplib} +- DESTINATION lib/${APP_NAME_LC}/${dir}) +-endforeach() +- +-# Install add-ons, fonts, icons, keyboard maps, keymaps, etc +-# (addons, media, system, userdata folders in share/kodi/) +-foreach(file ${install_data}) +- get_filename_component(dir ${file} PATH) +- install(FILES ${CMAKE_BINARY_DIR}/${file} +- DESTINATION share/${APP_NAME_LC}/${dir}) +-endforeach() +- +-# Install add-on bindings +-install(FILES ${addon_bindings} DESTINATION include/${APP_NAME_LC}) +- +-# Install xsession entry ++configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi-xsession.desktop.in ++ ${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop) + install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop +- DESTINATION share/xsessions) +- +-# Install desktop entry +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/kodi.desktop +- DESTINATION share/applications/${APP_NAME_LC}.desktop) ++ DESTINATION ${datarootdir}/xsessions) ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC}.desktop xbmc.desktop WORKING_DIRECTORY ${datarootdir}/xsessions/)") + +-# Install icons +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon16x16.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/16x16/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon22x22.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/22x22/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon24x24.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/24x24/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon32x32.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/32x32/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon48x48.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/48x48/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon64x64.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/64x64/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon128x128.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/128x128/apps) +-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon256x256.png +- RENAME ${APP_NAME_LC}.png +- DESTINATION share/icons/hicolor/256x256/apps) +-install(CODE "execute_process(COMMAND gtk-update-icon-cache -f -q -t +- $ENV{DESTDIR}${datarootdir}/icons/hicolor ERROR_QUIET)") ++if(NOT EXISTS ${datarootdir}/xbmc) ++install(CODE "execute_process (COMMAND ln -sf ${APP_NAME_LC}/ xbmc WORKING_DIRECTORY ${datarootdir})") ++endif() + +-# Install docs + install(FILES ${CORE_SOURCE_DIR}/copying.txt + ${CORE_SOURCE_DIR}/LICENSE.GPL + ${CORE_SOURCE_DIR}/version.txt + ${CORE_SOURCE_DIR}/docs/README.linux +- DESTINATION share/doc/${APP_NAME_LC}) ++ DESTINATION ${datarootdir}/doc/${APP_NAME_LC}) ++ ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/kodi.desktop ++ DESTINATION ${datarootdir}/applications/${APP_NAME_LC}.desktop) + +-# Install XBT skin files + foreach(texture ${XBT_FILES}) + string(REPLACE "${CMAKE_BINARY_DIR}/" "" dir ${texture}) + get_filename_component(dir ${dir} PATH) + install(FILES ${texture} +- DESTINATION share/${APP_NAME_LC}/${dir}) ++ DESTINATION ${datarootdir}/${APP_NAME_LC}/${dir}) ++endforeach() ++ ++foreach(wraplib ${WRAP_FILES}) ++ get_filename_component(dir ${wraplib} PATH) ++ install(PROGRAMS ${CMAKE_BINARY_DIR}/${wraplib} ++ DESTINATION ${libdir}/${APP_NAME_LC}/${dir}) ++endforeach() ++ ++foreach(file ${install_data}) ++ get_filename_component(dir ${file} PATH) ++ install(FILES ${CMAKE_BINARY_DIR}/${file} ++ DESTINATION ${datarootdir}/${APP_NAME_LC}/${dir}) + endforeach() + +-# Install extra stuff if it exists + if(EXISTS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/extra-installs) + install(CODE "file(STRINGS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/extra-installs dirs) + foreach(dir \${dirs}) + file(GLOB_RECURSE FILES RELATIVE ${CMAKE_BINARY_DIR} \${dir}/*) + foreach(file \${FILES}) + get_filename_component(dir \${file} PATH) +- file(INSTALL \${file} DESTINATION share/${APP_NAME_LC}/\${dir}) ++ file(INSTALL \${file} DESTINATION ${datarootdir}/${APP_NAME_LC}/\${dir}) + endforeach() + endforeach()") + endif() +@@ -155,29 +120,29 @@ foreach(subdir ${build_dirs}) + endif() + endforeach() + +-# Create xbmc -> kodi symlinks +-if(NOT EXISTS ${libdir}/xbmc) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc +- WORKING_DIRECTORY ${libdir})") +-endif() +-if(NOT EXISTS ${includedir}/xbmc) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc +- WORKING_DIRECTORY ${includedir})") +-endif() +-if(NOT EXISTS ${bindir}/xbmc) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC} xbmc +- WORKING_DIRECTORY ${bindir})") +-endif() +-if(NOT EXISTS ${bindir}/xbmc-standalone) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}-standalone xbmc-standalone +- WORKING_DIRECTORY ${bindir})") +-endif() +-if(NOT EXISTS ${datarootdir}/xsessions/xbmc.desktop) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}.desktop xbmc.desktop +- WORKING_DIRECTORY ${datarootdir}/xsessions/)") +-endif() +-if(NOT EXISTS ${datarootdir}/xbmc) +- install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc +- WORKING_DIRECTORY ${datarootdir})") +-endif() ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon16x16.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/16x16/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon22x22.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/22x22/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon24x24.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/24x24/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon32x32.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/32x32/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon48x48.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/48x48/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon64x64.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/64x64/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon128x128.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/128x128/apps) ++install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon256x256.png ++ RENAME ${APP_NAME_LC}.png ++ DESTINATION ${datarootdir}/icons/hicolor/256x256/apps) + ++install(CODE "execute_process(COMMAND gtk-update-icon-cache -f -q -t $ENV{DESTDIR}${datarootdir}/icons/hicolor ERROR_QUIET)") +diff --git a/project/cmake/scripts/windows/CFlagOverrides.cmake b/project/cmake/scripts/windows/CFlagOverrides.cmake +index 00f4e22..1d3c13b 100644 +--- a/project/cmake/scripts/windows/CFlagOverrides.cmake ++++ b/project/cmake/scripts/windows/CFlagOverrides.cmake +@@ -2,4 +2,4 @@ if(MSVC) + set(CMAKE_C_FLAGS "/MP /DWIN32 /D_WINDOWS /W3 /Zi /arch:SSE2") + set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MDd /Ob0 /Od /RTC1 /D_ITERATOR_DEBUG_LEVEL=0") + set(CMAKE_C_FLAGS_RELEASE "/MD /Ox /Ob2 /Oi /Ot /Oy /GL /DNDEBUG") +-endif() ++endif(MSVC) +diff --git a/project/cmake/scripts/windows/CXXFlagOverrides.cmake b/project/cmake/scripts/windows/CXXFlagOverrides.cmake +index 3c4d6c4..31295a7 100644 +--- a/project/cmake/scripts/windows/CXXFlagOverrides.cmake ++++ b/project/cmake/scripts/windows/CXXFlagOverrides.cmake +@@ -2,4 +2,4 @@ if(MSVC) + set(CMAKE_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /W3 /GR /Zi /EHsc /arch:SSE2") + set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob0 /Od /RTC1 /D_ITERATOR_DEBUG_LEVEL=0") + set(CMAKE_CXX_FLAGS_RELEASE "/MD /Ox /Ob2 /Oi /Ot /Oy /GL /DNDEBUG") +-endif() ++endif(MSVC) +diff --git a/project/cmake/treedata/darwin/subdirs.txt b/project/cmake/treedata/darwin/subdirs.txt +new file mode 100644 +index 0000000..f0fc5c5 +--- /dev/null ++++ b/project/cmake/treedata/darwin/subdirs.txt +@@ -0,0 +1,12 @@ ++xbmc/linux linuxsupport ++xbmc/network/linux network/linux ++xbmc/network/osx network/osx ++xbmc/peripherals/bus/osx peripherals/bus/osx ++xbmc/powermanagement/osx powermanagement/osx ++xbmc/storage/osx storage/osx ++xbmc/platform/posix posix ++xbmc/platform/darwin platform_darwin ++xbmc/platform/darwin/osx platform_osx ++xbmc/filesystem/posix filesystem/posix ++xbmc/utils/posix utils_posix ++xbmc/windowing/osx windowing/osx +diff --git a/system/keymaps/appcommand.xml b/system/keymaps/appcommand.xml +index c51ec72..2cbee66 100644 +--- a/system/keymaps/appcommand.xml ++++ b/system/keymaps/appcommand.xml +@@ -17,9 +17,9 @@ + Stop + PlayPause + +- ActivateWindow(Music) +- ActivateWindow(Programs) +- ActivateWindow(Programs) ++ ActivateWindow(MyMusic) ++ ActivateWindow(MyPrograms) ++ ActivateWindow(MyPrograms) + Play + Pause + FastForward +diff --git a/system/keymaps/customcontroller.AppleRemote.xml b/system/keymaps/customcontroller.AppleRemote.xml +index 4a47364..c20bb98 100644 +--- a/system/keymaps/customcontroller.AppleRemote.xml ++++ b/system/keymaps/customcontroller.AppleRemote.xml +@@ -8,18 +8,18 @@ + + + +- ++ + + + + + +- ++ + + +- ++ + + +@@ -177,11 +177,16 @@ + + +- ++ ++ ++ ++ ++ ++ + + + +diff --git a/system/keymaps/customcontroller.Harmony.xml b/system/keymaps/customcontroller.Harmony.xml +index 6666f11..728cb73 100644 +--- a/system/keymaps/customcontroller.Harmony.xml ++++ b/system/keymaps/customcontroller.Harmony.xml +@@ -15,11 +15,11 @@ + + + +- ++ + + +- ++ + + + +@@ -85,17 +85,17 @@ + + + +- +- ++ ++ + + + +- ++ + + + + +- ++ + + + +@@ -118,14 +118,14 @@ + + + +- ++ + + + + + + +- ++ + + + +@@ -133,8 +133,9 @@ + + + +- ++ + ++ + + + +@@ -145,7 +146,20 @@ + + + +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +@@ -195,7 +209,7 @@ + + + +- ++ + + + +@@ -204,11 +218,11 @@ + + + +- ++ + + + +- ++ + + + +@@ -240,13 +254,13 @@ + + + +- ++ + + + + + +- ++ + + + +@@ -274,7 +288,7 @@ + + + +- ++ + + + +@@ -288,7 +302,21 @@ + + + +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +@@ -315,11 +343,11 @@ + + + +- ++ + + + +- ++ + + + +diff --git a/system/keymaps/gamepad.xml b/system/keymaps/gamepad.xml +index ab298f0..1e839ca 100644 +--- a/system/keymaps/gamepad.xml ++++ b/system/keymaps/gamepad.xml +@@ -19,7 +19,7 @@ + + + +- ++ + + + +@@ -61,11 +61,16 @@ + VolumeDown + + +- ++ ++ ++ Skin.ToggleSetting(HomeViewToggle) ++ ++ ++ + + Highlight + +- ++ + + + Delete +@@ -77,12 +82,18 @@ + Queue + + +- ++ ++ ++ Queue ++ Playlist ++ ++ ++ + + Queue + Playlist + +- ++ + + + Pause +@@ -156,13 +167,13 @@ + AnalogFastForward + + +- ++ + + Back + AnalogRewind + AnalogFastForward + +- ++ + + + Back +@@ -197,13 +208,13 @@ + NextResolution + + +- ++ + + AnalogMove + NextCalibration + ResetCalibration + +- ++ + + + Back +@@ -255,11 +266,17 @@ + AnalogFastForward + + +- ++ + + Delete + +- ++ ++ ++ ++ Queue ++ Playlist ++ ++ + + + Delete +@@ -281,11 +298,11 @@ + Back + + +- ++ + + info + +- ++ + + + BackSpace +diff --git a/system/keymaps/joystick.xml b/system/keymaps/joystick.xml +index 516726d..976223e 100644 +--- a/system/keymaps/joystick.xml ++++ b/system/keymaps/joystick.xml +@@ -29,18 +29,25 @@ + VolumeDown + + +- ++ ++ ++ Skin.ToggleSetting(HomeViewToggle) ++ ++ ++ + + Highlight + +- ++ + + + Delete + + +- +- ++ ++ ++ ++ + + + Pause +@@ -108,7 +115,7 @@ + + Pause + Stop +- ActivateWindow(AddonSettings) ++ ActivateWindow(VisualisationSettings) + ActivateWindow(VisualisationPresetList) + Info + ActivateWindow(MusicOSD) +@@ -130,6 +137,11 @@ + Info + + ++ ++ ++ Close ++ ++ + + + Close +@@ -161,13 +173,13 @@ + NextCalibration + + +- ++ + + ResetCalibration + NextResolution + NextCalibration + +- ++ + + + Close +@@ -198,8 +210,10 @@ + Delete + + +- +- ++ ++ ++ ++ + + + Delete +@@ -220,11 +234,11 @@ + Close + + +- ++ + + ContextMenu + +- ++ + + + PreviousMenu +diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml +index b898242..004bc16 100644 +--- a/system/keymaps/keyboard.xml ++++ b/system/keymaps/keyboard.xml +@@ -12,7 +12,7 @@ + + + +- ++ + + + +@@ -88,7 +88,7 @@ + Number7 + Number8 + Number9 +- ToggleFullScreen ++ + FirstPage + LastPage + ActivateWindow(shutdownmenu) +@@ -102,9 +102,9 @@ + ActivateWindow(TVTimers) + + ActivateWindow(TVChannels) +- ActivateWindow(Videos) +- ActivateWindow(Music) +- ActivateWindow(Pictures) ++ ActivateWindow(MyVideos) ++ ActivateWindow(MyMusic) ++ ActivateWindow(MyPictures) + + Back + +@@ -127,9 +127,9 @@ + Rewind + + +- ActivateWindow(Music) +- ActivateWindow(Programs) +- ActivateWindow(Programs) ++ ActivateWindow(MyMusic) ++ ActivateWindow(MyPrograms) ++ ActivateWindow(MyPrograms) + + + +@@ -257,7 +257,7 @@ + ShowTimerRule + + +- ++ + + Highlight + Delete +@@ -266,7 +266,7 @@ + Highlight + ActivateWindow(Home) + +- ++ + + + Back +@@ -284,13 +284,21 @@ + ActivateWindow(Home) + + +- ++ + + Playlist + Queue ++ Delete + ActivateWindow(Home) + +- ++ ++ ++ ++ Playlist ++ Queue ++ ActivateWindow(Home) ++ ++ + + + FastForward +@@ -403,6 +411,21 @@ + ActivateWindow(MusicPlaylist) + + ++ ++ ++ FastForward ++ Rewind ++ SkipNext ++ SkipPrevious ++ Back ++ Info ++ CodecInfo ++

ActivateWindow(VisualisationPresetList)

++ Back ++ Back ++ ActivateWindow(MusicPlaylist) ++
++
+ + + FastForward +@@ -450,13 +473,13 @@ + NextResolution + + +- ++ + + NextCalibration + NextCalibration + ResetCalibration + +- ++ + + + Back +@@ -503,14 +526,22 @@ + Delete + + +- ++ + + Delete + Playlist + ToggleWatched + ActivateWindow(Home) + +- ++ ++ ++ ++ Playlist ++ Queue ++ ToggleWatched ++ ActivateWindow(Home) ++ ++ + + + Back +@@ -624,12 +655,12 @@ + Close + + +- ++ + + PreviousMenu + PreviousMenu + +- ++ + + + Highlight +diff --git a/system/keymaps/mouse.xml b/system/keymaps/mouse.xml +index c2b39f8..488de69 100644 +--- a/system/keymaps/mouse.xml ++++ b/system/keymaps/mouse.xml +@@ -7,6 +7,12 @@ + + + ++ ++ ++ wheeldown ++ wheelup ++ ++ + + + leftclick +@@ -15,8 +21,8 @@ + doubleclick + contextmenu + +- wheeldown +- wheelup ++ down ++ up + mousedrag + mousemove + +diff --git a/system/keymaps/remote.xml b/system/keymaps/remote.xml +index 2220ae4..a0c8edf 100644 +--- a/system/keymaps/remote.xml ++++ b/system/keymaps/remote.xml +@@ -19,7 +19,7 @@ + + + +- ++ + + + +@@ -73,9 +73,9 @@ + VolumeDown + Mute + ShutDown() +- ActivateWindow(Videos) +- ActivateWindow(Music) +- ActivateWindow(Pictures) ++ ActivateWindow(MyVideos) ++ ActivateWindow(MyMusic) ++ ActivateWindow(MyPictures) + ActivateWindow(Videos,TvShows) + ActivateWindow(TVGuide) + ActivateWindow(TVChannels) +@@ -83,9 +83,9 @@ + ActivateWindow(TVRecordings) + ActivateWindow(TVSearch) + ActivateWindow(TVChannels) +- ActivateWindow(Videos) +- ActivateWindow(Music) +- ActivateWindow(Pictures) ++ ActivateWindow(MyVideos) ++ ActivateWindow(MyMusic) ++ ActivateWindow(MyPictures) + Number0 + Number1 + JumpSMS2 +@@ -142,14 +142,14 @@ + Blue + + +- ++ + + Delete + Highlight + Move + Rename + +- ++ + + + Delete +@@ -161,12 +161,18 @@ + Queue + + +- ++ + + Queue + Queue + +- ++ ++ ++ ++ Queue ++ Queue ++ ++ + + + Delete +@@ -258,6 +264,13 @@ + CodecInfo + + ++ ++ ++ Back ++ Back ++ Back ++ ++ + + + Back +@@ -292,12 +305,12 @@ + NextResolution + + +- ++ + + + ResetCalibration + +- ++ + + + Back +@@ -353,12 +366,18 @@ + Delete + + +- ++ + + Queue + Delete + +- ++ ++ ++ ++ Queue ++ Queue ++ ++ + + + Delete +@@ -390,11 +409,11 @@ + Back + + +- ++ + + info + +- ++ + + + Number0 +@@ -455,11 +474,11 @@ + PreviousMenu + + +- ++ + + PreviousMenu + +- ++ + + + PreviousMenu +@@ -661,11 +680,16 @@ + number9 + + +- ++ + + PreviousMenu + +- ++ ++ ++ ++ Delete ++ ++ + + + Red +diff --git a/system/keymaps/touchscreen.xml b/system/keymaps/touchscreen.xml +index 5124cdf..4d16457 100644 +--- a/system/keymaps/touchscreen.xml ++++ b/system/keymaps/touchscreen.xml +@@ -15,13 +15,13 @@ + ActivateWindow(PlayerControls) + + +- ++ + + Select + Highlight + Highlight + +- ++ + + + StepBack +@@ -100,4 +100,4 @@ + ChannelDown + + +- ++ +\ No newline at end of file +diff --git a/system/peripherals.xml b/system/peripherals.xml +index 67f6b7a..ea2b245 100644 +--- a/system/peripherals.xml ++++ b/system/peripherals.xml +@@ -16,11 +16,11 @@ + + + +- +- +- ++ ++ ++ ++ + +- + + + +@@ -44,4 +44,9 @@ + + + ++ ++ ++ ++ ++ + +diff --git a/system/settings/imx6.xml b/system/settings/imx6.xml +index b8c90a5..52e60e3 100644 +--- a/system/settings/imx6.xml ++++ b/system/settings/imx6.xml +@@ -2,10 +2,34 @@ + +
+ +- ++ ++ ++ true ++ ++ ++ false ++ ++ ++ true ++ ++ ++ ++
++
++ ++ ++ ++ true ++ ++ ++ ++
++
++ ++ + + 2 +- 10 ++ 5 + + 0 + 5 +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 806eadf..eb5f26c 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -39,7 +39,7 @@ +
+
+ +- ++ + + false + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 53a4fe3..8ef5874 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -46,6 +46,67 @@ + + + ++ ++ 2 ++ 0 ++ ++ refreshchangedelays ++ ++ ++ 0 ++ ++ ++ ++ ++ 2 ++ false ++ true ++ ++ 0 ++ ++ ++ ++ ++ 2 ++ false ++ true ++ ++ true ++ ++ ++ ++ ++ 2 ++ false ++ true ++ ++ true ++ ++ ++ ++ ++ 2 ++ 720 ++ true ++ ++ true ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 2 ++ false ++ ++ + + 1 + false +@@ -100,7 +161,7 @@ + + + 2 +- 20 ++ 0 + + 0 + 10 +@@ -848,20 +909,18 @@ +
+
+ +- ++ + + 1 + true + + +- ++ + 1 + true + +- +- +- +- ++ ++ + 1 + true + +@@ -879,11 +938,6 @@ + + + +- +- 2 +- false +- +- + + 2 + false +@@ -897,10 +951,15 @@ + + + ++ ++ 2 ++ false ++ ++ + + + +- ++ + + 0 + 1 +@@ -914,23 +973,46 @@ + + + +- ++ + 2 +- true +- ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ + +- +- 4 ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ ++ ++ ++ ++ ++ ++ 2 + true + + +- ++ + 2 +- true ++ false + + +- +- + + 1 + false +@@ -941,16 +1023,14 @@ + true + + +- +- +- +- 2 +- true ++ ++ 1 ++ false + + +- +- 0 +- true ++ ++ 1 ++ false + + + +@@ -970,47 +1050,26 @@ + + + +- +- 2 +- false ++ ++ ++ ++ 0 ++ true + + +- +- 2 +- 0 +- +- +- +- +- +- +- +- +- +- ++ + 2 +- 0 +- +- +- +- +- +- +- +- +- +- 0 +- +- ++ true ++ + +- +- 1 +- false ++ ++ 4 ++ true + + +- +- 1 +- false ++ ++ 2 ++ true + + + +@@ -1021,7 +1080,17 @@ + + + +- ++ ++ ++ 2 ++ true ++ ++ ++ ++ 0 ++ true ++ ++ + + 3 + [%N. ]%A - %T +@@ -1049,35 +1118,23 @@ + 16016 + + +- +- 2 +- true +- +- +- +- ++ ++ + + 1 + true + +- +- +- +- +- 2 +- true +- +- +- +- 0 +- true +- + + + 1 + false + + ++ ++ 2 ++ true ++ ++ + + 2 + false +@@ -1107,6 +1164,10 @@ + + + ++ ++ 4 ++ 10501 ++ + + 4 + false +@@ -1121,7 +1182,7 @@ + + + +- ++ + + 0 + true +@@ -1478,18 +1539,6 @@ + + + +- +- 1 +- 0 +- +- +- +- +- +- +- +- +- + + 1 + 120 +@@ -1965,6 +2014,15 @@ + + + ++ ++ 1 ++ false ++ false ++ ++ ++ ++ ++ + + + +@@ -2047,6 +2105,13 @@ + + + ++ ++ ++ 2 ++ true ++ ++ ++ + + + +@@ -2464,7 +2529,7 @@ + + + 0 +- true ++ false + + + 0 +@@ -2977,10 +3042,10 @@ + + + +- ++ + HAS_EVENT_SERVER + HAS_JSONRPC +- ++ + + + 1 +@@ -3066,6 +3131,13 @@ + + + ++ ++ ++ 3 ++ false ++ ++ ++ + + + +diff --git a/tools/EventClients/Clients/WiiRemote/Makefile b/tools/EventClients/Clients/WiiRemote/Makefile +index eba0f1e..8bb41a5 100644 +--- a/tools/EventClients/Clients/WiiRemote/Makefile ++++ b/tools/EventClients/Clients/WiiRemote/Makefile +@@ -7,7 +7,7 @@ VERSION = v0.12 + + all: + @$(MAKE) -C wiiuse_$(VERSION)/src $@ +- $(CXX) $(CFLAGS) -I./wiiuse_$(VERSION)/src WiiUse_WiiRemote.cpp $(OBJS) -o $(BIN) ++ $(CXX) $(CFLAGS) -I./wiiuse_$(VERSION)/src WiiUse_WiiRemote.cpp $(OBJS) -o $(BIN) -l bluetooth + wiiuse: + @$(MAKE) -C wiiuse_$(VERSION)/src + clean: +diff --git a/tools/android/packaging/Makefile.in b/tools/android/packaging/Makefile.in +index 7dc1183..e934db1 100644 +--- a/tools/android/packaging/Makefile.in ++++ b/tools/android/packaging/Makefile.in +@@ -2,6 +2,7 @@ include ../../depends/Makefile.include + + OBJS = libcurl.so \ + librtmp.so \ ++ libafpclient.so \ + libplist.so libshairplay.so \ + libnfs.so libass.so \ + libbluray.so libsmbclient.so +diff --git a/tools/buildsteps/android/make-binary-addons b/tools/buildsteps/android/make-binary-addons +index 1c07b4c..a82e021 100644 +--- a/tools/buildsteps/android/make-binary-addons ++++ b/tools/buildsteps/android/make-binary-addons +@@ -15,14 +15,7 @@ then + do + echo "building $addon" + git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon +- +- if [ "$CMAKE_BUILD" = true ]; then +- # Must match prefix in android/PathSetup.cmake +- INSTALL_PREFIX="../../../../../build/install" +- else +- INSTALL_PREFIX="\$(PREFIX)" +- fi +- cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0" ++ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0" + done + fi + +diff --git a/tools/buildsteps/android/package b/tools/buildsteps/android/package +index ec32294..7721b9e 100644 +--- a/tools/buildsteps/android/package ++++ b/tools/buildsteps/android/package +@@ -2,20 +2,18 @@ WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} + XBMC_PLATFORM_DIR=android + . $WORKSPACE/tools/buildsteps/defaultenv + +-if [ "x$BUILD_OBB" == "xtrue" ]; then +- TARGET=apk-obb-unsigned +-else +- TARGET=apk-unsigned ++# Temporarily disabled because packaging not implement for CMake ++if [ "$CMAKE_BUILD" = true ]; then ++ exit 0 + fi + +-if [ "$CMAKE_BUILD" = true ]; then +- cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET ++if [ "x$BUILD_OBB" == "xtrue" ] ++then ++ cd $WORKSPACE;make apk-obb-unsigned + else +- cd $WORKSPACE;make -j$BUILDTHREADS $TARGET ++ cd $WORKSPACE;make apk-unsigned + fi + $RUN_SIGNSTEP +-mv tools/android/packaging/Kodi.symbols*.tar.bz2 $WORKSPACE/ +-cd $WORKSPACE + + #rename for upload + #e.x. xbmc-20130314-8c2fb31-Frodo-armeabi-v7a.apk +@@ -25,3 +23,4 @@ if [ -f *.obb ] + then + mv *.obb $UPLOAD_FILENAME.obb + fi ++mv tools/android/packaging/Kodi.symbols*.tar.bz2 $WORKSPACE/ +diff --git a/tools/buildsteps/androidx86/make-binary-addons b/tools/buildsteps/androidx86/make-binary-addons +index 0ef6c3d..e3e1899 100644 +--- a/tools/buildsteps/androidx86/make-binary-addons ++++ b/tools/buildsteps/androidx86/make-binary-addons +@@ -15,14 +15,7 @@ then + do + echo "building $addon" + git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon +- +- if [ "$CMAKE_BUILD" = true ]; then +- # Must match prefix in android/PathSetup.cmake +- INSTALL_PREFIX="../../../../../build/install" +- else +- INSTALL_PREFIX="\$(PREFIX)" +- fi +- cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0" ++ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0" + done + fi + +diff --git a/tools/buildsteps/androidx86/package b/tools/buildsteps/androidx86/package +index 19249c6..b7d4000 100644 +--- a/tools/buildsteps/androidx86/package ++++ b/tools/buildsteps/androidx86/package +@@ -2,26 +2,25 @@ WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} + XBMC_PLATFORM_DIR=android + . $WORKSPACE/tools/buildsteps/defaultenv + +-if [ "x$BUILD_OBB" == "xtrue" ]; then +- TARGET=apk-obb-unsigned +-else +- TARGET=apk-unsigned ++# Temporarily disabled because packaging not implement for CMake ++if [ "$CMAKE_BUILD" = true ]; then ++ exit 0 + fi + +-if [ "$CMAKE_BUILD" = true ]; then +- cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET ++if [ "x$BUILD_OBB" == "xtrue" ] ++then ++ cd $WORKSPACE;make apk-obb-unsigned + else +- cd $WORKSPACE;make -j$BUILDTHREADS $TARGET ++ cd $WORKSPACE;make apk-unsigned + fi + $RUN_SIGNSTEP +-mv tools/android/packaging/Kodi.symbols*.tar.bz2 $WORKSPACE/ +-cd $WORKSPACE + + #rename for upload + #e.x. xbmc-20130314-8c2fb31-Frodo-x86.apk + UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-x86" + mv kodiapp-x86-*.apk $UPLOAD_FILENAME.apk +-if [ -f *.obb ] ++if [ -f *.obb ] + then + mv *.obb $UPLOAD_FILENAME.obb + fi ++mv tools/android/packaging/Kodi.symbols*.tar.bz2 $WORKSPACE/ +diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac +index 11b60e2..7b25715 100644 +--- a/tools/depends/configure.ac ++++ b/tools/depends/configure.ac +@@ -456,7 +456,7 @@ if test "$platform_os" == "android"; then + AC_MSG_ERROR("NDK path is required for android") + fi + +- if ([! test -f "$use_ndk/source.properties"] && [! test -f "$use_ndk/RELEASE.TXT"]) ; then ++ if ! test -f "$use_ndk/RELEASE.TXT" ; then + AC_MSG_ERROR("$use_ndk is not an NDK directory") + fi + +@@ -543,7 +543,6 @@ echo -e + AC_SUBST(use_sdk_path) + AC_SUBST(use_ndk) + AC_SUBST(use_sdk) +- AC_SUBST(build_tools_path) + fi + + AC_SUBST(use_host) +@@ -575,7 +574,6 @@ echo -e "cpu:\t\t $use_cpu" + echo -e "host:\t\t $use_host" + if test "$platform_os" == "android"; then + echo -e "sdk-platform:\t $use_sdk" +- echo -e "build-tools:\t $build_tools_path" + fi + + if test "$platform_os" == "ios"; then +diff --git a/tools/depends/native/Makefile b/tools/depends/native/Makefile +index 1a179e2..b76dfcc 100644 +--- a/tools/depends/native/Makefile ++++ b/tools/depends/native/Makefile +@@ -34,7 +34,7 @@ libpng-native: zlib-native + swig-native: pcre-native + distribute-native: python27-native + distutilscross-native: python27-native distribute-native +-tar-native: xz-native automake-native ++tar-native: xz-native + python27-native: zlib-native + + #liblzo2 has stale packaged automake files that cause borked host/build detection +diff --git a/tools/depends/native/gettext-native/Makefile b/tools/depends/native/gettext-native/Makefile +index 8c75a28..cbde5f5 100644 +--- a/tools/depends/native/gettext-native/Makefile ++++ b/tools/depends/native/gettext-native/Makefile +@@ -5,7 +5,7 @@ DEPS= ../../Makefile.include.in Makefile + + # lib name, version + LIBNAME=gettext +-VERSION=0.19.8 ++VERSION=0.18.2 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/native/giflib-native/Makefile b/tools/depends/native/giflib-native/Makefile +index b556e67..0885272 100644 +--- a/tools/depends/native/giflib-native/Makefile ++++ b/tools/depends/native/giflib-native/Makefile +@@ -5,7 +5,7 @@ PLATFORM=$(NATIVEPLATFORM) + + # lib name, version + LIBNAME=giflib +-VERSION=5.1.4 ++VERSION=5.1.0 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.bz2 + +diff --git a/tools/depends/native/liblzo2-native/Makefile b/tools/depends/native/liblzo2-native/Makefile +index 927ffb5..41809ea 100644 +--- a/tools/depends/native/liblzo2-native/Makefile ++++ b/tools/depends/native/liblzo2-native/Makefile +@@ -5,7 +5,7 @@ DEPS= ../../Makefile.include.in Makefile + + # lib name, version + LIBNAME=lzo +-VERSION=2.09 ++VERSION=2.03 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/native/swig-native/Makefile b/tools/depends/native/swig-native/Makefile +index 6b255b2..9067b2a 100644 +--- a/tools/depends/native/swig-native/Makefile ++++ b/tools/depends/native/swig-native/Makefile +@@ -6,7 +6,7 @@ DEPS= ../../Makefile.include.in Makefile + + # lib name, version + LIBNAME=swig +-VERSION=3.0.10 ++VERSION=2.0.8 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile +index 2f0c831..4c69844 100644 +--- a/tools/depends/target/Makefile ++++ b/tools/depends/target/Makefile +@@ -9,8 +9,8 @@ DEPENDS = \ + libgcrypt bzip2 liblzo2 libzip freetype2 fontconfig \ + openssl gmp nettle gnutls curl \ + libjpeg-turbo libpng fribidi libass \ +- librtmp libxml2 yajl libmicrohttpd mysql libffi \ +- python27 libshairplay \ ++ libmodplug librtmp libxml2 yajl libmicrohttpd mysql libffi \ ++ python27 afpfs-ng libshairplay \ + libplist libcec libbluray tinyxml dummy-libxbmc \ + libamplayer libssh taglib libusb libnfs \ + pythonmodule-pil pythonmodule-setuptools \ +@@ -86,6 +86,7 @@ librtmp: openssl + libmicrohttpd: gnutls libgcrypt libgpg-error + python27: expat gettext libxml2 sqlite3 openssl libffi + libcdio: $(ICONV) ++afpfs-ng: libgcrypt $(ICONV) + libplist: libxml2 $(ZLIB) + libbluray: $(ICONV) libxml2 + libssh: libgcrypt openssl $(ZLIB) +diff --git a/tools/depends/target/Toolchain.cmake.in b/tools/depends/target/Toolchain.cmake.in +index 7b32712..b5c96fa 100644 +--- a/tools/depends/target/Toolchain.cmake.in ++++ b/tools/depends/target/Toolchain.cmake.in +@@ -1,71 +1,66 @@ +-set(DEPENDS_PATH "@prefix@/@deps_dir@") +-set(NATIVEPREFIX "@prefix@/@tool_dir@") ++SET(DEPENDS_PATH "@prefix@/@deps_dir@") ++SET(NATIVEPREFIX "@prefix@/@tool_dir@") + +-set(OS "@platform_os@") +-set(CPU "@use_cpu@") +-set(PLATFORM "@target_platform@") +-if("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") +- set(CMAKE_SYSTEM_NAME Linux) +-endif() ++SET(OS "@platform_os@") ++SET(CPU "@use_cpu@") ++SET(PLATFORM "@target_platform@") ++IF("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") ++SET(CMAKE_SYSTEM_NAME Linux) ++ENDIF() + + # set special CORE_SYSTEM_NAME +-if("${OS}" STREQUAL "android") +- set(CORE_SYSTEM_NAME android) +-elseif("${OS}" STREQUAL "osx") +- set(CORE_SYSTEM_NAME osx) +-elseif("${OS}" STREQUAL "ios") +- set(CORE_SYSTEM_NAME ios) +- set(CMAKE_SYSTEM_NAME Darwin) +-elseif("${PLATFORM}" STREQUAL "raspberry-pi") +- set(CORE_SYSTEM_NAME rbpi) +-endif() ++IF("${OS}" STREQUAL "android") ++SET(CORE_SYSTEM_NAME android) ++ELSEIF("${OS}" STREQUAL "ios") ++SET(CORE_SYSTEM_NAME ios) ++SET(CMAKE_SYSTEM_NAME Darwin) ++ELSEIF("${PLATFORM}" STREQUAL "raspberry-pi") ++SET(CORE_SYSTEM_NAME rbpi) ++ENDIF() + +-if("${OS}" STREQUAL "ios" OR "${OS}" STREQUAL "osx") +- set(CMAKE_OSX_SYSROOT @use_sdk_path@) +-endif() +-set(CMAKE_SYSTEM_VERSION 1) ++IF("${OS}" STREQUAL "ios" OR "${OS}" STREQUAL "osx") ++SET(CMAKE_OSX_SYSROOT @use_sdk_path@) ++ENDIF() ++SET(CMAKE_SYSTEM_VERSION 1) + + # specify the cross compiler +-set(CMAKE_C_COMPILER @CC@) +-set(CMAKE_CXX_COMPILER @CXX@) +-set(CMAKE_AR @AR@ CACHE FILEPATH "Archiver") +-set(CMAKE_LINKER @LD@ CACHE FILEPATH "Linker") ++SET(CMAKE_C_COMPILER @CC@) ++SET(CMAKE_CXX_COMPILER @CXX@) ++SET(CMAKE_AR @AR@ CACHE FILEPATH "Archiver") ++SET(CMAKE_LINKER @LD@ CACHE FILEPATH "Linker") + + # where is the target environment +-set(CMAKE_FIND_ROOT_PATH @prefix@/@deps_dir@ @use_toolchain@ @use_toolchain@/usr @use_sdk_path@ @use_sdk_path@/usr @use_toolchain@/sysroot/usr) +-set(CMAKE_LIBRARY_PATH @prefix@/@deps_dir@/lib:@use_toolchain@/usr/lib/@use_host@:@use_toolchain@/lib/@use_host@) ++SET(CMAKE_FIND_ROOT_PATH @prefix@/@deps_dir@ @use_toolchain@ @use_toolchain@/usr @use_sdk_path@ @use_sdk_path@/usr @use_toolchain@/sysroot/usr) ++SET(CMAKE_LIBRARY_PATH @prefix@/@deps_dir@/lib:@use_toolchain@/usr/lib/@use_host@:@use_toolchain@/lib/@use_host@) + + # add RBPI's firmware directories +-if("${CORE_SYSTEM_NAME}" STREQUAL "rbpi") +- list(APPEND CMAKE_FIND_ROOT_PATH @use_firmware@/opt/vc) +- list(APPEND CMAKE_LIBRARY_PATH @use_firmware@/opt/vc/lib) +- list(APPEND CMAKE_INCLUDE_PATH @use_firmware@/opt/vc/include) +-endif() ++IF("${CORE_SYSTEM_NAME}" STREQUAL "rbpi") ++ LIST(APPEND CMAKE_FIND_ROOT_PATH @use_firmware@/opt/vc) ++ LIST(APPEND CMAKE_LIBRARY_PATH @use_firmware@/opt/vc/lib) ++ LIST(APPEND CMAKE_INCLUDE_PATH @use_firmware@/opt/vc/include) ++ENDIF() + +-# add Android directories and tools +-if("${CORE_SYSTEM_NAME}" STREQUAL "android") +- set(NDKROOT @use_ndk@) +- set(SDKROOT @use_sdk_path@) +- set(SDK_PLATFORM @use_sdk@) +- string(REPLACE ":" ";" SDK_BUILDTOOLS_PATH "@build_tools_path@") +-endif() ++# add Android directories ++IF("${CORE_SYSTEM_NAME}" STREQUAL "android") ++ LIST(APPEND NDKROOT @use_ndk@) ++ENDIF() + +-set(CMAKE_C_FLAGS "@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") +-set(CMAKE_CXX_FLAGS "@platform_cxxflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") +-set(CMAKE_CPP_FLAGS "@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") +-set(CMAKE_EXE_LINKER_FLAGS "-L@prefix@/@deps_dir@/lib @platform_ldflags@") +-set(ENV{CFLAGS} ${CMAKE_C_FLAGS}) +-set(ENV{CXXFLAGS} ${CMAKE_CXX_FLAGS}) +-set(ENV{CPPFLAGS} ${CMAKE_CPP_FLAGS}) +-set(ENV{LDFLAGS} ${CMAKE_EXE_LINKER_FLAGS}) ++SET(CMAKE_C_FLAGS "@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") ++SET(CMAKE_CXX_FLAGS "@platform_cxxflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") ++SET(CMAKE_CPP_FLAGS "@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include") ++SET(CMAKE_EXE_LINKER_FLAGS "-L@prefix@/@deps_dir@/lib @platform_ldflags@") ++SET(ENV{CFLAGS} ${CMAKE_C_FLAGS}) ++SET(ENV{CXXFLAGS} ${CMAKE_CXX_FLAGS}) ++SET(ENV{CPPFLAGS} ${CMAKE_CPP_FLAGS}) ++SET(ENV{LDFLAGS} ${CMAKE_EXE_LINKER_FLAGS}) + # search for programs in the build host directories +-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) ++SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + # for libraries and headers in the target directories +-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +-set(ENV{PKG_CONFIG_LIBDIR} @prefix@/@deps_dir@/lib/pkgconfig) ++SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) ++SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) ++SET(ENV{PKG_CONFIG_LIBDIR} @prefix@/@deps_dir@/lib/pkgconfig) + + # Binary Addons +-if(NOT OS STREQUAL "linux") +- set(ADDONS_PREFER_STATIC_LIBS ON) +-endif() ++IF(NOT OS STREQUAL "linux") ++SET(ADDONS_PREFER_STATIC_LIBS ON) ++ENDIF() +diff --git a/tools/depends/target/config-binaddons.site.in b/tools/depends/target/config-binaddons.site.in +index 0753a4c..44d5959 100644 +--- a/tools/depends/target/config-binaddons.site.in ++++ b/tools/depends/target/config-binaddons.site.in +@@ -34,7 +34,7 @@ LD_LIBRARY_PATH=@prefix@/@tool_dir@/lib:$LD_LIBRARY_PATH + + NATIVE_ROOT=@prefix@/@tool_dir@ + +-#libomxil-bellagio ++#afps-ng and libomxil-bellagio + ac_cv_func_malloc_0_nonnull=yes + + #curl +diff --git a/tools/depends/target/config.site.in b/tools/depends/target/config.site.in +index a3a3bc2..15fa70d 100644 +--- a/tools/depends/target/config.site.in ++++ b/tools/depends/target/config.site.in +@@ -42,7 +42,7 @@ PYTHON_SITE_PKG=@prefix@/@deps_dir@/lib/python${PYTHON_VERSION}/site-packages + PYTHON_NOVERSIONCHECK=no-check + NATIVE_ROOT=@prefix@/@tool_dir@ + +-#libomxil-bellagio ++#afps-ng and libomxil-bellagio + ac_cv_func_malloc_0_nonnull=yes + + #curl +diff --git a/tools/depends/target/crossguid/CMakeLists.txt b/tools/depends/target/crossguid/CMakeLists.txt +index 73ad8f9..1c2b831 100644 +--- a/tools/depends/target/crossguid/CMakeLists.txt ++++ b/tools/depends/target/crossguid/CMakeLists.txt +@@ -16,7 +16,7 @@ elseif(APPLE) + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_CFUUID) + elseif(WIN32) + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_WINDOWS) +-endif() ++endif () + + install(TARGETS ${PROJECT_NAME} DESTINATION lib) + install(FILES guid.h DESTINATION include) +diff --git a/tools/depends/target/crossguid/FindCXX11.cmake b/tools/depends/target/crossguid/FindCXX11.cmake +index fb2a582..001dc8a 100644 +--- a/tools/depends/target/crossguid/FindCXX11.cmake ++++ b/tools/depends/target/crossguid/FindCXX11.cmake +@@ -11,8 +11,8 @@ else() + if(CXX_FLAG_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + set(CXX_STD11_FLAGS "-std=c++0x") +- endif() +-endif() ++ endif(CXX_FLAG_CXX0X) ++endif(CXX_FLAG_CXX11) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(CXX11 DEFAULT_MSG CXX_STD11_FLAGS) +diff --git a/tools/depends/target/crossguid/Makefile b/tools/depends/target/crossguid/Makefile +index 487ab2a..fe072c0 100644 +--- a/tools/depends/target/crossguid/Makefile ++++ b/tools/depends/target/crossguid/Makefile +@@ -37,9 +37,7 @@ LIBDYLIB=$(PLATFORM)/lib$(LIBNAME).a + + .PHONY: .installed-$(PLATFORM) + +-all: .installed-$(PLATFORM) $(PREFIX)/lib/lib$(LIBNAME).a +-$(PREFIX)/lib/lib$(LIBNAME).a: +- @make .installed-$(PLATFORM) ++all: .installed-$(PLATFORM) $(LIBDYLIB) + + $(TARBALLS_LOCATION)/$(ARCHIVE): + cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) +diff --git a/tools/depends/target/curl/Makefile b/tools/depends/target/curl/Makefile +index e641a9d..f82de26 100644 +--- a/tools/depends/target/curl/Makefile ++++ b/tools/depends/target/curl/Makefile +@@ -13,7 +13,7 @@ ARCHIVE=$(SOURCE).tar.bz2 + # configuration settings + CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) \ +- --without-libssh2 --disable-ntlm-wb --enable-ipv6 ++ --without-libssh2 --disable-ntlm-wb + + LIBDYLIB=$(PLATFORM)/lib/.libs/lib$(LIBNAME).a + +diff --git a/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +new file mode 100644 +index 0000000..eef7385 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +@@ -0,0 +1,69 @@ ++From ff289b3678b3b102f76c0fc0ffc802e3c8026fdb Mon Sep 17 00:00:00 2001 ++From: Deborah Crook ++Date: Thu, 5 Mar 2015 19:48:43 +0000 ++Subject: [PATCH] Discard data before VO/VOL in mpeg-4 over mpegts ++ ++--- ++ libavcodec/mpeg4video_parser.c | 26 ++++++++++++++++++++++---- ++ 1 file changed, 22 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c ++index aa5e87a..0d8b15a 100644 ++--- a/libavcodec/mpeg4video_parser.c +++++ b/libavcodec/mpeg4video_parser.c ++@@ -43,18 +43,32 @@ int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) ++ state = pc->state; ++ ++ i = 0; ++- if (!vop_found) { +++ if (vop_found < 0) { +++ for (i = 0; i < buf_size; i++) { +++ state = (state << 8) | buf[i]; +++ if (state >= 0x100 && state <= 0x12f) { +++ i++; +++ vop_found = 0; +++ break; +++ } +++ } +++ } +++ +++ if (vop_found == 0) +++ vop_found = 1; +++ +++ if (vop_found == 1) { ++ for (i = 0; i < buf_size; i++) { ++ state = (state << 8) | buf[i]; ++ if (state == 0x1B6) { ++ i++; ++- vop_found = 1; +++ vop_found = 2; ++ break; ++ } ++ } ++ } ++ ++- if (vop_found) { +++ if (vop_found == 2) { ++ /* EOF considered as end of frame */ ++ if (buf_size == 0) ++ return 0; ++@@ -133,12 +147,16 @@ static int mpeg4video_parse(AVCodecParserContext *s, ++ ParseContext *pc = s->priv_data; ++ int next; ++ +++ if (pc->frame_start_found == 0 && !avctx->extradata) +++ pc->frame_start_found = -1; +++ ++ if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { ++ next = buf_size; ++ } else { ++ next = ff_mpeg4_find_frame_end(pc, buf, buf_size); ++ ++- if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { +++ if (pc->frame_start_found < 0 || +++ ff_combine_frame(pc, next, &buf, &buf_size) < 0) { ++ *poutbuf = NULL; ++ *poutbuf_size = 0; ++ return buf_size; ++-- ++2.1.4 +diff --git a/tools/depends/target/ffmpeg/0001-Squashed-commit-of-the-following.patch b/tools/depends/target/ffmpeg/0001-Squashed-commit-of-the-following.patch +new file mode 100644 +index 0000000..88adfab +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-Squashed-commit-of-the-following.patch +@@ -0,0 +1,2180 @@ ++From ccb1eff2e6dd1259c6a8ca262076553875c5abe2 Mon Sep 17 00:00:00 2001 ++From: John Cox ++Date: Wed, 13 Jan 2016 16:13:33 +0000 ++Subject: [PATCH] H.265 residual decode rework (v2) ++ ++Rework the cabac decode functions ++Simplify the code flow and variable usage where possible ++ ++(Remove profiling and other spurious deltas that were in v1) ++--- ++ libavcodec/arm/cabac.h | 155 ++++- ++ libavcodec/arm/hevc_cabac.h | 491 +++++++++++++++ ++ libavcodec/arm/hevcdsp_deblock_neon.S | 13 +- ++ libavcodec/arm/hevcdsp_epel_neon.S | 9 +- ++ libavcodec/cabac.h | 9 +- ++ libavcodec/hevc_cabac.c | 1098 +++++++++++++++++++++++++-------- ++ 6 files changed, 1510 insertions(+), 265 deletions(-) ++ create mode 100644 libavcodec/arm/hevc_cabac.h ++ ++diff --git a/libavcodec/arm/cabac.h b/libavcodec/arm/cabac.h ++index fdbf86b..0a3980a 100644 ++--- a/libavcodec/arm/cabac.h +++++ b/libavcodec/arm/cabac.h ++@@ -26,13 +26,34 @@ ++ #include "libavutil/internal.h" ++ #include "libavcodec/cabac.h" ++ +++ +++#if UNCHECKED_BITSTREAM_READER +++#define LOAD_16BITS_BEHI\ +++ "ldrh %[tmp] , [%[ptr]] , #2 \n\t"\ +++ "rev %[tmp] , %[tmp] \n\t" +++#elif CONFIG_THUMB +++#define LOAD_16BITS_BEHI\ +++ "ldr %[tmp] , [%[c], %[end]] \n\t"\ +++ "cmp %[tmp] , %[ptr] \n\t"\ +++ "it cs \n\t"\ +++ "ldrhcs %[tmp] , [%[ptr]] , #2 \n\t"\ +++ "rev %[tmp] , %[tmp] \n\t" +++#else +++#define LOAD_16BITS_BEHI\ +++ "ldr %[tmp] , [%[c], %[end]] \n\t"\ +++ "cmp %[tmp] , %[ptr] \n\t"\ +++ "ldrcsh %[tmp] , [%[ptr]] , #2 \n\t"\ +++ "rev %[tmp] , %[tmp] \n\t" +++#endif +++ +++ ++ #define get_cabac_inline get_cabac_inline_arm ++ static av_always_inline int get_cabac_inline_arm(CABACContext *c, ++ uint8_t *const state) ++ { ++ int bit; +++#if 0 ++ void *reg_b, *reg_c, *tmp; ++- ++ __asm__ volatile( ++ "ldrb %[bit] , [%[state]] \n\t" ++ "add %[r_b] , %[tables] , %[lps_off] \n\t" ++@@ -100,9 +121,141 @@ static av_always_inline int get_cabac_inline_arm(CABACContext *c, ++ [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128) ++ : "memory", "cc" ++ ); +++#else +++ // *** Not thumb compatible yet +++ unsigned int reg_b, tmp; +++ __asm__ ( +++ "ldrb %[bit] , [%[state]] \n\t" +++ "sub %[r_b] , %[mlps_tables], %[lps_off] \n\t" +++ "and %[tmp] , %[range] , #0xC0 \n\t" +++ "add %[r_b] , %[r_b] , %[bit] \n\t" +++ "ldrb %[tmp] , [%[r_b] , %[tmp], lsl #1] \n\t" +++// %bit = *state +++// %range = range +++// %tmp = RangeLPS +++ "sub %[range] , %[range] , %[tmp] \n\t" +++ +++ "cmp %[low] , %[range] , lsl #17 \n\t" +++ "ittt ge \n\t" +++ "subge %[low] , %[low] , %[range], lsl #17 \n\t" +++ "mvnge %[bit] , %[bit] \n\t" +++ "movge %[range] , %[tmp] \n\t" +++ +++ "clz %[tmp] , %[range] \n\t" +++ "sub %[tmp] , #23 \n\t" +++ +++ "ldrb %[r_b] , [%[mlps_tables], %[bit]] \n\t" +++ "lsl %[low] , %[low] , %[tmp] \n\t" +++ "lsl %[range] , %[range] , %[tmp] \n\t" +++ +++ "strb %[r_b] , [%[state]] \n\t" +++ "lsls %[tmp] , %[low] , #16 \n\t" +++ +++ "bne 2f \n\t" +++ LOAD_16BITS_BEHI +++ "lsr %[tmp] , %[tmp] , #15 \n\t" +++ "movw %[r_b] , #0xFFFF \n\t" +++ "sub %[tmp] , %[tmp] , %[r_b] \n\t" +++ +++ "rbit %[r_b] , %[low] \n\t" +++ "clz %[r_b] , %[r_b] \n\t" +++ "sub %[r_b] , %[r_b] , #16 \n\t" +++#if CONFIG_THUMB +++ "lsl %[tmp] , %[tmp] , %[r_b] \n\t" +++ "add %[low] , %[low] , %[tmp] \n\t" +++#else +++ "add %[low] , %[low] , %[tmp], lsl %[r_b] \n\t" +++#endif +++ "2: \n\t" +++ : [bit]"=&r"(bit), +++ [low]"+&r"(c->low), +++ [range]"+&r"(c->range), +++ [r_b]"=&r"(reg_b), +++ [ptr]"+&r"(c->bytestream), +++ [tmp]"=&r"(tmp) +++ : [state]"r"(state), +++ [mlps_tables]"r"(ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128), +++ [byte]"M"(offsetof(CABACContext, bytestream)), +++#if !UNCHECKED_BITSTREAM_READER +++ [c]"r"(c), +++ [end]"M"(offsetof(CABACContext, bytestream_end)), +++#endif +++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) +++ : "memory", "cc" +++ ); +++#endif ++ ++ return bit & 1; ++ } +++ +++#define get_cabac_bypass get_cabac_bypass_arm +++static inline int get_cabac_bypass_arm(CABACContext * const c) +++{ +++ int rv = 0; +++ unsigned int tmp; +++ __asm ( +++ "lsl %[low] , #1 \n\t" +++ "cmp %[low] , %[range] , lsl #17 \n\t" +++ "adc %[rv] , %[rv] , #0 \n\t" +++ "it cs \n\t" +++ "subcs %[low] , %[low] , %[range], lsl #17 \n\t" +++ "lsls %[tmp] , %[low] , #16 \n\t" +++ "bne 1f \n\t" +++ LOAD_16BITS_BEHI +++ "add %[low] , %[low] , %[tmp], lsr #15 \n\t" +++ "movw %[tmp] , #0xFFFF \n\t" +++ "sub %[low] , %[low] , %[tmp] \n\t" +++ "1: \n\t" +++ : // Outputs +++ [rv]"+&r"(rv), +++ [low]"+&r"(c->low), +++ [tmp]"=&r"(tmp), +++ [ptr]"+&r"(c->bytestream) +++ : // Inputs +++#if !UNCHECKED_BITSTREAM_READER +++ [c]"r"(c), +++ [end]"M"(offsetof(CABACContext, bytestream_end)), +++#endif +++ [range]"r"(c->range) +++ : "cc" +++ ); +++ return rv; +++} +++ +++ +++#define get_cabac_bypass_sign get_cabac_bypass_sign_arm +++static inline int get_cabac_bypass_sign_arm(CABACContext * const c, int rv) +++{ +++ unsigned int tmp; +++ __asm ( +++ "lsl %[low] , #1 \n\t" +++ "cmp %[low] , %[range] , lsl #17 \n\t" +++ "ite cc \n\t" +++ "rsbcc %[rv] , %[rv] , #0 \n\t" +++ "subcs %[low] , %[low] , %[range], lsl #17 \n\t" +++ "lsls %[tmp] , %[low] , #16 \n\t" +++ "bne 1f \n\t" +++ LOAD_16BITS_BEHI +++ "add %[low] , %[low] , %[tmp], lsr #15 \n\t" +++ "movw %[tmp] , #0xFFFF \n\t" +++ "sub %[low] , %[low] , %[tmp] \n\t" +++ "1: \n\t" +++ : // Outputs +++ [rv]"+&r"(rv), +++ [low]"+&r"(c->low), +++ [tmp]"=&r"(tmp), +++ [ptr]"+&r"(c->bytestream) +++ : // Inputs +++#if !UNCHECKED_BITSTREAM_READER +++ [c]"r"(c), +++ [end]"M"(offsetof(CABACContext, bytestream_end)), +++#endif +++ [range]"r"(c->range) +++ : "cc" +++ ); +++ return rv; +++} +++ ++ #endif /* HAVE_ARMV6T2_INLINE */ ++ ++ #endif /* AVCODEC_ARM_CABAC_H */ ++diff --git a/libavcodec/arm/hevc_cabac.h b/libavcodec/arm/hevc_cabac.h ++new file mode 100644 ++index 0000000..31d3c59 ++--- /dev/null +++++ b/libavcodec/arm/hevc_cabac.h ++@@ -0,0 +1,491 @@ +++/* +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++#ifndef AVCODEC_ARM_HEVC_CABAC_H +++#define AVCODEC_ARM_HEVC_CABAC_H +++ +++#include "config.h" +++#if HAVE_ARMV6T2_INLINE +++ +++#define hevc_mem_bits32 hevc_mem_bits32_arm +++static inline uint32_t hevc_mem_bits32_arm(const void * p, const unsigned int bits) +++{ +++ unsigned int n; +++ __asm__ ( +++ "rev %[n], %[x] \n\t" +++ : [n]"=r"(n) +++ : [x]"r"(*(const uint32_t *)((const uint8_t *)p + (bits >> 3))) +++ : +++ ); +++ return n << (bits & 7); +++} +++ +++ +++// --------------------------------------------------------------------------- +++// +++// Helper fns - little bits of code where ARM has an instraction that the +++// compiler doesn't know about / use +++ +++#define trans_scale_sat trans_scale_sat_arm +++static inline int trans_scale_sat_arm(const int level, const unsigned int scale, const unsigned int scale_m, const unsigned int shift) +++{ +++ int rv; +++ int t = ((level * (int)(scale * scale_m)) >> shift) + 1; +++ +++ __asm__ ( +++ "ssat %[rv], #16, %[t], ASR #1 \n\t" +++ : [rv]"=r"(rv) +++ : [t]"r"(t) +++ : +++ ); +++ return rv; +++} +++ +++#define update_rice update_rice_arm +++static inline void update_rice_arm(uint8_t * const stat_coeff, +++ const unsigned int last_coeff_abs_level_remaining, +++ const unsigned int c_rice_param) +++{ +++ int t; +++ __asm__ ( +++ "lsl %[t], %[coeff], #1 \n\t" +++ "lsrs %[t], %[t], %[shift] \n\t" +++ "it eq \n\t" +++ "subeq %[stat], %[stat], #1 \n\t" +++ "cmp %[t], #6 \n\t" +++ "adc %[stat], %[stat], #0 \n\t" +++ "usat %[stat], #8, %[stat] \n\t" +++ : [stat]"+&r"(*stat_coeff), +++ [t]"=&r"(t) +++ : [coeff]"r"(last_coeff_abs_level_remaining), +++ [shift]"r"(c_rice_param) +++ : "cc" +++ ); +++} +++ +++// --------------------------------------------------------------------------- +++// +++// CABAC get loops +++// +++// Where the loop is simple enough we can normally do 10-30% better than the +++// compiler +++ +++// Get the residual greater than 1 bits +++ +++#define get_cabac_greater1_bits get_cabac_greater1_bits_arm +++static inline unsigned int get_cabac_greater1_bits_arm(CABACContext * const c, const unsigned int n, +++ uint8_t * const state0) +++{ +++ unsigned int i, reg_b, st, tmp, bit, rv; +++ __asm__ ( +++ "mov %[i] , #0 \n\t" +++ "mov %[rv] , #0 \n\t" +++ "1: \n\t" +++ "add %[i] , %[i] , #1 \n\t" +++ "cmp %[rv] , #0 \n\t" +++ "ite eq \n\t" +++ "usateq %[st] , #2 , %[i] \n\t" +++ "movne %[st] , #0 \n\t" +++ +++ "ldrb %[bit] , [%[state0], %[st]] \n\t" +++ "sub %[r_b] , %[mlps_tables], %[lps_off] \n\t" +++ "and %[tmp] , %[range] , #0xC0 \n\t" +++ "add %[r_b] , %[r_b] , %[bit] \n\t" +++ "ldrb %[tmp] , [%[r_b], %[tmp], lsl #1] \n\t" +++ "sub %[range] , %[range] , %[tmp] \n\t" +++ +++ "cmp %[low] , %[range], lsl #17 \n\t" +++ "ittt ge \n\t" +++ "subge %[low] , %[low] , %[range], lsl #17 \n\t" +++ "mvnge %[bit] , %[bit] \n\t" +++ "movge %[range] , %[tmp] \n\t" +++ +++ "ldrb %[r_b] , [%[mlps_tables], %[bit]] \n\t" +++ "and %[bit] , %[bit] , #1 \n\t" +++ "orr %[rv] , %[bit] , %[rv], lsl #1 \n\t" +++ +++ "clz %[tmp] , %[range] \n\t" +++ "sub %[tmp] , #23 \n\t" +++ +++ "lsl %[low] , %[low] , %[tmp] \n\t" +++ "lsl %[range] , %[range] , %[tmp] \n\t" +++ +++ "strb %[r_b] , [%[state0], %[st]] \n\t" +++// There is a small speed gain from combining both conditions, using a single +++// branch and then working out what that meant later +++ "lsls %[tmp] , %[low] , #16 \n\t" +++ "it ne \n\t" +++ "cmpne %[n] , %[i] \n\t" +++ "bne 1b \n\t" +++ +++// If reload is not required then we must have run out of flags to decode +++ "tst %[tmp] , %[tmp] \n\t" +++ "bne 2f \n\t" +++ +++// Do reload +++ "ldrh %[tmp] , [%[bptr]] , #2 \n\t" +++ "movw %[r_b] , #0xFFFF \n\t" +++ "rev %[tmp] , %[tmp] \n\t" +++ "rsb %[tmp] , %[r_b] , %[tmp], lsr #15 \n\t" +++ +++ "rbit %[r_b] , %[low] \n\t" +++ "clz %[r_b] , %[r_b] \n\t" +++ "sub %[r_b] , %[r_b] , #16 \n\t" +++ +++#if CONFIG_THUMB +++ "lsl %[tmp] , %[tmp] , %[r_b] \n\t" +++ "add %[low] , %[low] , %[tmp] \n\t" +++#else +++ "add %[low] , %[low] , %[tmp], lsl %[r_b] \n\t" +++#endif +++ +++ "cmp %[n] , %[i] \n\t" +++ "bne 1b \n\t" +++ "2: \n\t" +++ : [bit]"=&r"(bit), +++ [low]"+&r"(c->low), +++ [range]"+&r"(c->range), +++ [r_b]"=&r"(reg_b), +++ [bptr]"+&r"(c->bytestream), +++ [i]"=&r"(i), +++ [tmp]"=&r"(tmp), +++ [st]"=&r"(st), +++ [rv]"=&r"(rv) +++ : [state0]"r"(state0), +++ [n]"r"(n), +++ [mlps_tables]"r"(ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128), +++ [byte]"M"(offsetof(CABACContext, bytestream)), +++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) +++ : "memory", "cc" +++ ); +++ return rv; +++} +++ +++ +++// n must be > 0 on entry +++#define get_cabac_sig_coeff_flag_idxs get_cabac_sig_coeff_flag_idxs_arm +++static inline uint8_t * get_cabac_sig_coeff_flag_idxs_arm(CABACContext * const c, uint8_t * const state0, +++ unsigned int n, +++ const uint8_t const * ctx_map, +++ uint8_t * p) +++{ +++ unsigned int reg_b, tmp, st, bit; +++ __asm__ ( +++ "1: \n\t" +++// Get bin from map +++ "ldrb %[st] , [%[ctx_map], %[n]] \n\t" +++ +++// Load state & ranges +++ "sub %[r_b] , %[mlps_tables], %[lps_off] \n\t" +++ "ldrb %[bit] , [%[state0], %[st]] \n\t" +++ "and %[tmp] , %[range] , #0xC0 \n\t" +++ "add %[r_b] , %[r_b] , %[tmp], lsl #1 \n\t" +++ "ldrb %[tmp] , [%[r_b], %[bit]] \n\t" +++ "sub %[range] , %[range] , %[tmp] \n\t" +++ +++ "cmp %[low] , %[range], lsl #17 \n\t" +++ "ittt ge \n\t" +++ "subge %[low] , %[low] , %[range], lsl #17 \n\t" +++ "mvnge %[bit] , %[bit] \n\t" +++ "movge %[range] , %[tmp] \n\t" +++ +++ "ldrb %[r_b] , [%[mlps_tables], %[bit]] \n\t" +++ "tst %[bit] , #1 \n\t" +++// GCC asm seems to need strbne written differently for thumb and arm +++#if CONFIG_THUMB +++ "it ne \n\t" +++ "strbne %[n] , [%[idx]] , #1 \n\t" +++#else +++ "strneb %[n] , [%[idx]] , #1 \n\t" +++#endif +++ +++// Renorm +++ "clz %[tmp] , %[range] \n\t" +++ "sub %[tmp] , #23 \n\t" +++ "lsl %[low] , %[low] , %[tmp] \n\t" +++ "lsl %[range] , %[range] , %[tmp] \n\t" +++ +++ "strb %[r_b] , [%[state0], %[st]] \n\t" +++// There is a small speed gain from combining both conditions, using a single +++// branch and then working out what that meant later +++ "subs %[n] , %[n] , #1 \n\t" +++#if CONFIG_THUMB +++ "itt ne \n\t" +++ "lslsne %[tmp] , %[low] , #16 \n\t" +++ "bne 1b \n\t" +++#else +++ "lslnes %[tmp] , %[low] , #16 \n\t" +++ "bne 1b \n\t" +++#endif +++ +++// If we have bits left then n must be 0 so give up now +++ "lsls %[tmp] , %[low] , #16 \n\t" +++ "bne 2f \n\t" +++ +++// Do reload +++ "ldrh %[tmp] , [%[bptr]] , #2 \n\t" +++ "movw %[r_b] , #0xFFFF \n\t" +++ "rev %[tmp] , %[tmp] \n\t" +++ "rsb %[tmp] , %[r_b] , %[tmp], lsr #15 \n\t" +++ +++ "rbit %[r_b] , %[low] \n\t" +++ "clz %[r_b] , %[r_b] \n\t" +++ "sub %[r_b] , %[r_b] , #16 \n\t" +++ +++#if CONFIG_THUMB +++ "lsl %[tmp] , %[tmp] , %[r_b] \n\t" +++ "add %[low] , %[low] , %[tmp] \n\t" +++#else +++ "add %[low] , %[low] , %[tmp], lsl %[r_b] \n\t" +++#endif +++ +++// Check to see if we still have more to do +++ "cmp %[n] , #0 \n\t" +++ "bne 1b \n\t" +++ "2: \n\t" +++ : [bit]"=&r"(bit), +++ [low]"+&r"(c->low), +++ [range]"+&r"(c->range), +++ [r_b]"=&r"(reg_b), +++ [bptr]"+&r"(c->bytestream), +++ [idx]"+&r"(p), +++ [n]"+&r"(n), +++ [tmp]"=&r"(tmp), +++ [st]"=&r"(st) +++ : [state0]"r"(state0), +++ [ctx_map]"r"(ctx_map), +++ [mlps_tables]"r"(ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET + 128), +++ [byte]"M"(offsetof(CABACContext, bytestream)), +++ [lps_off]"I"((H264_MLPS_STATE_OFFSET + 128) - H264_LPS_RANGE_OFFSET) +++ : "memory", "cc" +++ ); +++ +++ return p; +++} +++ +++// --------------------------------------------------------------------------- +++// +++// CABAC_BY22 functions +++// +++// By and large these are (at best) no faster than their C equivalents - the +++// only one worth having is _peek where we do a slightly better job than the +++// compiler +++// +++// The others have been stashed here for reference in case larger scale asm +++// is attempted in which case they might be a useful base +++ +++ +++#define get_cabac_by22_peek get_cabac_by22_peek_arm +++static inline uint32_t get_cabac_by22_peek_arm(const CABACContext *const c) +++{ +++ uint32_t rv, tmp; +++ __asm__ ( +++ "bic %[rv] , %[low], #1 \n\t" +++ "cmp %[inv] , #0 \n\t" +++ "it ne \n\t" +++ "umullne %[tmp] , %[rv] , %[inv], %[rv] \n\t" +++ : // Outputs +++ [rv]"=&r"(rv), +++ [tmp]"=r"(tmp) +++ : // Inputs +++ [low]"r"(c->low), +++ [inv]"r"(c->range) +++ : // Clobbers +++ "cc" +++ ); +++ return rv << 1; +++} +++ +++#if 0 +++ +++// ***** Slower than the C :-( +++#define get_cabac_by22_flush get_cabac_by22_flush_arm +++static inline void get_cabac_by22_flush_arm(CABACContext *const c, const unsigned int n, const uint32_t val) +++{ +++ uint32_t m, tmp; +++ __asm__ ( +++ "add %[bits], %[bits], %[n] \n\t" +++ "ldr %[m], [%[ptr], %[bits], lsr #3] \n\t" +++ +++ "rsb %[tmp], %[n], #32 \n\t" +++ "lsr %[tmp], %[val], %[tmp] \n\t" +++ "mul %[tmp], %[range], %[tmp] \n\t" +++ +++ "rev %[m], %[m] \n\t" +++ +++ "lsl %[tmp], %[tmp], #23 \n\t" +++ "rsb %[low], %[tmp], %[low], lsl %[n] \n\t" +++ +++ "and %[tmp], %[bits], #7 \n\t" +++ "lsl %[m], %[m], %[tmp] \n\t" +++ +++ "orr %[low], %[low], %[m], lsr #9 \n\t" +++ : // Outputs +++ [m]"=&r"(m), +++ [tmp]"=&r"(tmp), +++ [bits]"+&r"(c->by22.bits), +++ [low]"+&r"(c->low) +++ : // Inputs +++ [n]"r"(n), +++ [val]"r"(val), +++ [inv]"r"(c->range), +++ [range]"r"(c->by22.range), +++ [ptr]"r"(c->bytestream) +++ : // Clobbers +++ ); +++} +++ +++ +++// Works but slower than C +++#define coeff_abs_level_remaining_decode_by22(c,r) coeff_abs_level_remaining_decode_by22_arm(c, r) +++static int coeff_abs_level_remaining_decode_by22_arm(CABACContext * const c, const unsigned int c_rice_param) +++{ +++ uint32_t n, val, tmp, level; +++ +++// PROFILE_START(); +++ +++ __asm__ ( +++ // Peek +++ "bic %[val], %[low], #1 \n\t" +++ "cmp %[inv], #0 \n\t" +++ "umullne %[tmp], %[val], %[inv], %[val] \n\t" +++ "lsl %[val], %[val], #1 \n\t" +++ +++ // Count bits (n = prefix) +++ "mvn %[n], %[val] \n\t" +++ "clz %[n], %[n] \n\t" +++ +++ "lsl %[level], %[val], %[n] \n\t" +++ "subs %[tmp], %[n], #3 \n\t" +++ "blo 2f \n\t" +++ +++ // prefix >= 3 +++ // < tmp = prefix - 3 +++ // > tmp = prefix + rice - 3 +++ "add %[tmp], %[tmp], %[rice] \n\t" +++ // > n = prefix * 2 + rice - 3 +++ "add %[n], %[tmp], %[n] \n\t" +++ "cmp %[n], #21 \n\t" +++ "bhi 3f \n\t" +++ +++ "orr %[level], %[level], #0x80000000 \n\t" +++ "rsb %[tmp], %[tmp], #31 \n\t" +++ "lsr %[level], %[level], %[tmp] \n\t" +++ +++ "mov %[tmp], #2 \n\t" +++ "add %[level], %[level], %[tmp], lsl %[rice] \n\t" +++ "b 1f \n\t" +++ +++ // > 22 bits used in total - need reload +++ "3: \n\t" +++ +++ // Stash prefix + rice - 3 in level (only spare reg) +++ "mov %[level], %[tmp] \n\t" +++ // Restore n to flush value (prefix) +++ "sub %[n], %[n], %[tmp] \n\t" +++ +++ // Flush + reload +++ +++// "rsb %[tmp], %[n], #32 \n\t" +++// "lsr %[tmp], %[val], %[tmp] \n\t" +++// "mul %[tmp], %[range], %[tmp] \n\t" +++ +++ // As it happens we know that all the bits we are flushing are 1 +++ // so we can cheat slightly +++ "rsb %[tmp], %[range], %[range], lsl %[n] \n\t" +++ "lsl %[tmp], %[tmp], #23 \n\t" +++ "rsb %[low], %[tmp], %[low], lsl %[n] \n\t" +++ +++ "add %[bits], %[bits], %[n] \n\t" +++ "ldr %[n], [%[ptr], %[bits], lsr #3] \n\t" +++ "rev %[n], %[n] \n\t" +++ "and %[tmp], %[bits], #7 \n\t" +++ "lsl %[n], %[n], %[tmp] \n\t" +++ +++ "orr %[low], %[low], %[n], lsr #9 \n\t" +++ +++ // (reload) +++ +++ "bic %[val], %[low], #1 \n\t" +++ "cmp %[inv], #0 \n\t" +++ "umullne %[tmp], %[val], %[inv], %[val] \n\t" +++ "lsl %[val], %[val], #1 \n\t" +++ +++ // Build value +++ +++ "mov %[n], %[level] \n\t" +++ +++ "orr %[tmp], %[val], #0x80000000 \n\t" +++ "rsb %[level], %[level], #31 \n\t" +++ "lsr %[level], %[tmp], %[level] \n\t" +++ +++ "mov %[tmp], #2 \n\t" +++ "add %[level], %[level], %[tmp], lsl %[rice] \n\t" +++ "b 1f \n\t" +++ +++ // prefix < 3 +++ "2: \n\t" +++ "rsb %[tmp], %[rice], #31 \n\t" +++ "lsr %[level], %[level], %[tmp] \n\t" +++ "orr %[level], %[level], %[n], lsl %[rice] \n\t" +++ "add %[n], %[n], %[rice] \n\t" +++ +++ "1: \n\t" +++ // Flush +++ "add %[n], %[n], #1 \n\t" +++ +++ "rsb %[tmp], %[n], #32 \n\t" +++ "lsr %[tmp], %[val], %[tmp] \n\t" +++ +++ "add %[bits], %[bits], %[n] \n\t" +++ "ldr %[val], [%[ptr], %[bits], lsr #3] \n\t" +++ +++ "mul %[tmp], %[range], %[tmp] \n\t" +++ "lsl %[tmp], %[tmp], #23 \n\t" +++ "rsb %[low], %[tmp], %[low], lsl %[n] \n\t" +++ +++ "rev %[val], %[val] \n\t" +++ "and %[tmp], %[bits], #7 \n\t" +++ "lsl %[val], %[val], %[tmp] \n\t" +++ +++ "orr %[low], %[low], %[val], lsr #9 \n\t" +++ : // Outputs +++ [level]"=&r"(level), +++ [n]"=&r"(n), +++ [val]"=&r"(val), +++ [tmp]"=&r"(tmp), +++ [bits]"+&r"(c->by22.bits), +++ [low]"+&r"(c->low) +++ : // Inputs +++ [rice]"r"(c_rice_param), +++ [inv]"r"(c->range), +++ [range]"r"(c->by22.range), +++ [ptr]"r"(c->bytestream) +++ : // Clobbers +++ "cc" +++ ); +++ +++// PROFILE_ACC(residual_abs); +++ +++ return level; +++} +++#endif +++ +++#endif /* HAVE_ARMV6T2_INLINE */ +++ +++#endif /* AVCODEC_ARM_HEVC_CABAC_H */ ++diff --git a/libavcodec/arm/hevcdsp_deblock_neon.S b/libavcodec/arm/hevcdsp_deblock_neon.S ++index bad4589..a088cc3 100644 ++--- a/libavcodec/arm/hevcdsp_deblock_neon.S +++++ b/libavcodec/arm/hevcdsp_deblock_neon.S ++@@ -409,10 +409,12 @@ function ff_hevc_deblocking_boundary_strengths_neon, export=1 ++ beq 90f ++ ++ tst a3, #1 +++ itee ne ++ ldrne a3, [v5, #0] @ curr->mv[0] ++ ldreq a3, [v5, #4] @ curr->mv[1] ++ moveq v1, v2 ++ tst v8, #1 +++ itee ne ++ ldrne v8, [v6, #0] @ neigh->mv[0] ++ ldreq v8, [v6, #4] @ neigh->mv[1] ++ moveq v3, v4 ++@@ -424,9 +426,14 @@ function ff_hevc_deblocking_boundary_strengths_neon, export=1 ++ sel a3, a3, ip ++ ands a3, a3, lr ++ @ drop through ++-10: movne a3, #1 +++10: it ne +++ movne a3, #1 ++ 11: subs a2, a2, #1 ++-12: strbhs a3, [v7], a4 +++12: +++A strbhs a3, [v7], a4 +++T itt hs +++T strbhs a3, [v7] +++T addhs v7, v7, a4 ++ subs a2, a2, #1 ++ bhs 12b ++ ++@@ -442,6 +449,7 @@ function ff_hevc_deblocking_boundary_strengths_neon, export=1 ++ bne 10b ++ ++ teq v1, v3 +++ it eq ++ teqeq v2, v4 ++ bne 40f ++ teq v1, v2 ++@@ -487,6 +495,7 @@ function ff_hevc_deblocking_boundary_strengths_neon, export=1 ++ b 10b ++ ++ 40: teq v1, v4 +++ ite eq ++ teqeq v2, v3 ++ bne 10b ++ ++diff --git a/libavcodec/arm/hevcdsp_epel_neon.S b/libavcodec/arm/hevcdsp_epel_neon.S ++index 516ae5b..00eab9e 100644 ++--- a/libavcodec/arm/hevcdsp_epel_neon.S +++++ b/libavcodec/arm/hevcdsp_epel_neon.S ++@@ -110,7 +110,9 @@ function ff_hevc_put_epel_h_neon_8, export=1 ++ sub r7, #1 ++ lsl r7, #2 ++ vpush {d8-d15} ++- adrl r12, epel_coeffs +++@ adr reaches if we are in thumb mode but not in arm +++T adr r12, epel_coeffs +++A adrl r12, epel_coeffs ++ add r7, r12 ++ sub r1, #1 ++ lsl r4, #1 ++@@ -170,7 +172,8 @@ function ff_hevc_put_epel_v_neon_8, export=1 ++ sub r7, #1 ++ lsl r7, #2 ++ vpush {d8-d15} ++- adrl r12, epel_coeffs +++T adr r12, epel_coeffs +++A adrl r12, epel_coeffs ++ add r7, r12 ++ load_coeffs_16b r7 ++ sub r1, r2 ++@@ -246,7 +249,7 @@ function ff_hevc_put_epel_hv_neon_8, export=1 ++ sub r7, #1 ++ lsl r7, #2 ++ vpush {d8-d15} ++- adrl r12, epel_coeffs +++ adr r12, epel_coeffs ++ sub r6, #1 ++ lsl r6, #2 ++ add r6, r12 // mx epel coeff offset ++diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h ++index 1bf1c62..ccfa991 100644 ++--- a/libavcodec/cabac.h +++++ b/libavcodec/cabac.h ++@@ -43,7 +43,14 @@ extern const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; ++ typedef struct CABACContext{ ++ int low; ++ int range; ++- int outstanding_count; +++ union +++ { +++ int outstanding_count; +++ struct { +++ uint16_t bits; +++ uint16_t range; +++ } by22; +++ }; ++ const uint8_t *bytestream_start; ++ const uint8_t *bytestream; ++ const uint8_t *bytestream_end; ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index 271e17a..4caf720 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -21,14 +21,72 @@ ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ +++#define UNCHECKED_BITSTREAM_READER 1 +++ ++ #include "libavutil/attributes.h" ++ #include "libavutil/common.h" ++ ++-#include "cabac_functions.h" ++ #include "hevc.h" +++#include "cabac_functions.h" +++ +++// BY22 is probably faster than simple bypass if the processor has +++// either a fast 32-bit divide or a fast 32x32->64[63:32] instruction +++// x86 has fast int divide +++// Arm doesn't have divide or general fast 64 bit, but does have the multiply +++// * Beware: ARCH_xxx isn't set if configure --disable-asm is used +++#define USE_BY22 (HAVE_FAST_64BIT || ARCH_ARM || ARCH_X86) +++// Use native divide if we have a fast one - otherwise use mpy 1/x +++// x86 has a fast integer divide - arm doesn't - unsure about other +++// architectures +++#define USE_BY22_DIV ARCH_X86 +++ +++// Special case blocks with a single significant ceoff +++// Decreases the complexity of the code for a common case but increases the +++// code size. +++#define USE_N_END_1 1 +++ +++#if ARCH_ARM +++#include "arm/hevc_cabac.h" +++#endif ++ ++ #define CABAC_MAX_BIN 31 ++ +++ +++#if USE_BY22 && !USE_BY22_DIV +++#define I(x) (uint32_t)((0x10000000000ULL / (uint64_t)(x)) + 1ULL) +++ +++static const uint32_t cabac_by22_inv_range[256] = { +++ 0, I(257), I(258), I(259), +++ I(260), I(261), I(262), I(263), I(264), I(265), I(266), I(267), I(268), I(269), +++ I(270), I(271), I(272), I(273), I(274), I(275), I(276), I(277), I(278), I(279), +++ I(280), I(281), I(282), I(283), I(284), I(285), I(286), I(287), I(288), I(289), +++ I(290), I(291), I(292), I(293), I(294), I(295), I(296), I(297), I(298), I(299), +++ I(300), I(301), I(302), I(303), I(304), I(305), I(306), I(307), I(308), I(309), +++ I(310), I(311), I(312), I(313), I(314), I(315), I(316), I(317), I(318), I(319), +++ I(320), I(321), I(322), I(323), I(324), I(325), I(326), I(327), I(328), I(329), +++ I(330), I(331), I(332), I(333), I(334), I(335), I(336), I(337), I(338), I(339), +++ I(340), I(341), I(342), I(343), I(344), I(345), I(346), I(347), I(348), I(349), +++ I(350), I(351), I(352), I(353), I(354), I(355), I(356), I(357), I(358), I(359), +++ I(360), I(361), I(362), I(363), I(364), I(365), I(366), I(367), I(368), I(369), +++ I(370), I(371), I(372), I(373), I(374), I(375), I(376), I(377), I(378), I(379), +++ I(380), I(381), I(382), I(383), I(384), I(385), I(386), I(387), I(388), I(389), +++ I(390), I(391), I(392), I(393), I(394), I(395), I(396), I(397), I(398), I(399), +++ I(400), I(401), I(402), I(403), I(404), I(405), I(406), I(407), I(408), I(409), +++ I(410), I(411), I(412), I(413), I(414), I(415), I(416), I(417), I(418), I(419), +++ I(420), I(421), I(422), I(423), I(424), I(425), I(426), I(427), I(428), I(429), +++ I(430), I(431), I(432), I(433), I(434), I(435), I(436), I(437), I(438), I(439), +++ I(440), I(441), I(442), I(443), I(444), I(445), I(446), I(447), I(448), I(449), +++ I(450), I(451), I(452), I(453), I(454), I(455), I(456), I(457), I(458), I(459), +++ I(460), I(461), I(462), I(463), I(464), I(465), I(466), I(467), I(468), I(469), +++ I(470), I(471), I(472), I(473), I(474), I(475), I(476), I(477), I(478), I(479), +++ I(480), I(481), I(482), I(483), I(484), I(485), I(486), I(487), I(488), I(489), +++ I(490), I(491), I(492), I(493), I(494), I(495), I(496), I(497), I(498), I(499), +++ I(500), I(501), I(502), I(503), I(504), I(505), I(506), I(507), I(508), I(509), +++ I(510), I(511) +++}; +++#undef I +++#endif // USE_BY22 +++ ++ /** ++ * number of bin by SyntaxElement. ++ */ ++@@ -445,6 +503,211 @@ static const uint8_t diag_scan8x8_inv[8][8] = { ++ { 28, 36, 43, 49, 54, 58, 61, 63, }, ++ }; ++ +++ +++typedef struct +++{ +++ uint16_t coeff; +++ uint16_t scale; +++} xy_off_t; +++ +++#define XYT_C(x,y,t) ((x) + ((y) << (t))) +++#define SCALE_TRAFO(t) ((t) > 3 ? 3 : (t)) +++#define SCALE_SHR(t) ((t) - SCALE_TRAFO(t)) +++#define XYT_S(x,y,t) (((x) >> SCALE_SHR(t)) + (((y) >> SCALE_SHR(t)) << SCALE_TRAFO(t))) +++ +++#define XYT(x,y,t) {XYT_C(x,y,t), XYT_S(x,y,t)} +++ +++#define OFF_DIAG(t) {\ +++ XYT(0,0,t), XYT(0,1,t), XYT(1,0,t), XYT(0,2,t),\ +++ XYT(1,1,t), XYT(2,0,t), XYT(0,3,t), XYT(1,2,t),\ +++ XYT(2,1,t), XYT(3,0,t), XYT(1,3,t), XYT(2,2,t),\ +++ XYT(3,1,t), XYT(2,3,t), XYT(3,2,t), XYT(3,3,t)\ +++} +++ +++#define OFF_HORIZ(t) {\ +++ XYT(0,0,t), XYT(1,0,t), XYT(2,0,t), XYT(3,0,t),\ +++ XYT(0,1,t), XYT(1,1,t), XYT(2,1,t), XYT(3,1,t),\ +++ XYT(0,2,t), XYT(1,2,t), XYT(2,2,t), XYT(3,2,t),\ +++ XYT(0,3,t), XYT(1,3,t), XYT(2,3,t), XYT(3,3,t)\ +++} +++ +++#define OFF_VERT(t) {\ +++ XYT(0,0,t), XYT(0,1,t), XYT(0,2,t), XYT(0,3,t),\ +++ XYT(1,0,t), XYT(1,1,t), XYT(1,2,t), XYT(1,3,t),\ +++ XYT(2,0,t), XYT(2,1,t), XYT(2,2,t), XYT(2,3,t),\ +++ XYT(3,0,t), XYT(3,1,t), XYT(3,2,t), XYT(3,3,t)\ +++} +++ +++static const xy_off_t off_xys[3][4][16] = +++{ +++ {OFF_DIAG(2), OFF_DIAG(3), OFF_DIAG(4), OFF_DIAG(5)}, +++ {OFF_HORIZ(2), OFF_HORIZ(3), OFF_HORIZ(4), OFF_HORIZ(5)}, +++ {OFF_VERT(2), OFF_VERT(3), OFF_VERT(4), OFF_VERT(5)} +++}; +++ +++ +++// Helper fns +++#ifndef hevc_mem_bits32 +++static av_always_inline uint32_t hevc_mem_bits32(const void * buf, const unsigned int offset) +++{ +++ return AV_RB32((const uint8_t *)buf + (offset >> 3)) << (offset & 7); +++} +++#endif +++ +++#if AV_GCC_VERSION_AT_LEAST(3,4) && !defined(hevc_clz32) +++#define hevc_clz32 hevc_clz32_builtin +++static av_always_inline unsigned int hevc_clz32_builtin(const uint32_t x) +++{ +++ // __builtin_clz says it works on ints - so adjust if int is >32 bits long +++ return __builtin_clz(x) - (sizeof(int) * 8 - 32); +++} +++#endif +++ +++// It is unlikely that we will ever need this but include for completeness +++#ifndef hevc_clz32 +++static inline unsigned int hevc_clz32(unsigned int x) +++{ +++ unsigned int n = 1; +++ if ((x & 0xffff0000) == 0) { +++ n += 16; +++ x <<= 16; +++ } +++ if ((x & 0xff000000) == 0) { +++ n += 8; +++ x <<= 8; +++ } +++ if ((x & 0xf0000000) == 0) { +++ n += 4; +++ x <<= 4; +++ } +++ if ((x & 0xc0000000) == 0) { +++ n += 2; +++ x <<= 2; +++ } +++ return n - ((x >> 31) & 1); +++} +++#endif +++ +++ +++#if !USE_BY22 +++// If no by22 then _by22 functions will revert to normal and so _peek/_flush +++// will no longer be called but the setup calls will still exist and we want +++// to null them out +++#define bypass_start(s) +++#define bypass_finish(s) +++#else +++// Use BY22 for residual bypass block +++ +++#define bypass_start(s) get_cabac_by22_start(&s->HEVClc->cc) +++#define bypass_finish(s) get_cabac_by22_finish(&s->HEVClc->cc) +++ +++// BY22 notes that bypass is simply a divide into the bitstream and so we +++// can peek out large quantities of bits at one and treat the result as if +++// it was VLC. In many cases this will lead to O(1) processing rather than +++// O(n) though the setup and teardown is sufficiently expensive that it is +++// only worth using if we expect to be dealing with more than a few bits +++// The definition of "a few bits" will vary from platform to platform but +++// tests on ARM show that it probably isn't worth it for a single coded +++// residual, but is for >1 - this is probaly reinforced that if there are +++// more residuals then they are likely to be bigger and this will make the +++// O(1) nature of the code more worthwhile. +++ +++ +++#if !USE_BY22_DIV +++// * 1/x @ 32 bits gets us 22 bits of accuracy +++#define CABAC_BY22_PEEK_BITS 22 +++#else +++// A real 32-bit divide gets us another bit +++// If we have a 64 bit int & a unit time divider then we should get a lot +++// of bits (55) but that is untested and it is unclear if it would give +++// us a large advantage +++#define CABAC_BY22_PEEK_BITS 23 +++#endif +++ +++// Bypass block start +++// Must be called before _by22_peek is used as it sets the CABAC environment +++// into the correct state. _by22_finish must be called to return to 'normal' +++// (i.e. non-bypass) cabac decoding +++static inline void get_cabac_by22_start(CABACContext * const c) +++{ +++ const unsigned int bits = __builtin_ctz(c->low); +++ const uint32_t m = hevc_mem_bits32(c->bytestream, 0); +++ uint32_t x = (c->low << (22 - CABAC_BITS)) ^ ((m ^ 0x80000000U) >> (9 + CABAC_BITS - bits)); +++#if !USE_BY22_DIV +++ const uint32_t inv = cabac_by22_inv_range[c->range & 0xff]; +++#endif +++ +++ c->bytestream -= (CABAC_BITS / 8); +++ c->by22.bits = bits; +++#if !USE_BY22_DIV +++ c->by22.range = c->range; +++ c->range = inv; +++#endif +++ c->low = x; +++} +++ +++// Bypass block finish +++// Must be called at the end of the bypass block to return to normal operation +++static inline void get_cabac_by22_finish(CABACContext * const c) +++{ +++ unsigned int used = c->by22.bits; +++ unsigned int bytes_used = (used / CABAC_BITS) * (CABAC_BITS / 8); +++ unsigned int bits_used = used & (CABAC_BITS == 16 ? 15 : 7); +++ +++ c->bytestream += bytes_used + (CABAC_BITS / 8); +++ c->low = (((uint32_t)c->low >> (22 - CABAC_BITS + bits_used)) | 1) << bits_used; +++#if !USE_BY22_DIV +++ c->range = c->by22.range; +++#endif +++} +++ +++// Peek bypass bits +++// _by22_start must be called before _by22_peek is called and _by22_flush +++// must be called afterwards to flush any used bits +++// The actual number of valid bits returned is +++// min(, CABAC_BY22_PEEK_BITS). CABAC_BY22_PEEK_BITS +++// will be at least 22 which should be long enough for any prefix or suffix +++// though probably not long enough for the worst case combination +++#ifndef get_cabac_by22_peek +++static inline uint32_t get_cabac_by22_peek(const CABACContext * const c) +++{ +++#if USE_BY22_DIV +++ return ((unsigned int)c->low / (unsigned int)c->range) << 9; +++#else +++ uint32_t x = c->low & ~1U; +++ const uint32_t inv = c->range; +++ +++ if (inv != 0) +++ x = (uint32_t)(((uint64_t)x * (uint64_t)inv) >> 32); +++ +++ return x << 1; +++#endif +++} +++#endif +++ +++// Flush bypass bits peeked by _by22_peek +++// Flush n bypass bits. n must be >= 1 to guarantee correct operation +++// val is an unmodified copy of whatever _by22_peek returned +++#ifndef get_cabac_by22_flush +++static inline void get_cabac_by22_flush(CABACContext * c, const unsigned int n, const uint32_t val) +++{ +++ // Subtract the bits used & reshift up to the top of the word +++#if USE_BY22_DIV +++ const uint32_t low = (((unsigned int)c->low << n) - (((val >> (32 - n)) * (unsigned int)c->range) << 23)); +++#else +++ const uint32_t low = (((uint32_t)c->low << n) - (((val >> (32 - n)) * c->by22.range) << 23)); +++#endif +++ +++ // and refill lower bits +++ // We will probably OR over some existing bits but that doesn't matter +++ c->by22.bits += n; +++ c->low = low | (hevc_mem_bits32(c->bytestream, c->by22.bits) >> 9); +++} +++#endif +++ +++#endif // USE_BY22 +++ +++ ++ void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts) ++ { ++ if (s->ps.pps->entropy_coding_sync_enabled_flag && ++@@ -863,19 +1126,19 @@ int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth) ++ return GET_CABAC(elem_offset[CBF_LUMA] + !trafo_depth); ++ } ++ ++-static int hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx) +++static int hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx_nz) ++ { ++- return GET_CABAC(elem_offset[TRANSFORM_SKIP_FLAG] + !!c_idx); +++ return GET_CABAC(elem_offset[TRANSFORM_SKIP_FLAG] + c_idx_nz); ++ } ++ ++-static int explicit_rdpcm_flag_decode(HEVCContext *s, int c_idx) +++static int explicit_rdpcm_flag_decode(HEVCContext *s, int c_idx_nz) ++ { ++- return GET_CABAC(elem_offset[EXPLICIT_RDPCM_FLAG] + !!c_idx); +++ return GET_CABAC(elem_offset[EXPLICIT_RDPCM_FLAG] + c_idx_nz); ++ } ++ ++-static int explicit_rdpcm_dir_flag_decode(HEVCContext *s, int c_idx) +++static int explicit_rdpcm_dir_flag_decode(HEVCContext *s, int c_idx_nz) ++ { ++- return GET_CABAC(elem_offset[EXPLICIT_RDPCM_DIR_FLAG] + !!c_idx); +++ return GET_CABAC(elem_offset[EXPLICIT_RDPCM_DIR_FLAG] + c_idx_nz); ++ } ++ ++ int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx) { ++@@ -891,14 +1154,14 @@ int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx) { ++ return GET_CABAC(elem_offset[RES_SCALE_SIGN_FLAG] + idx); ++ } ++ ++-static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCContext *s, int c_idx, +++static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCContext *s, int c_idx_nz, ++ int log2_size, int *last_scx_prefix, int *last_scy_prefix) ++ { ++ int i = 0; ++ int max = (log2_size << 1) - 1; ++ int ctx_offset, ctx_shift; ++ ++- if (!c_idx) { +++ if (!c_idx_nz) { ++ ctx_offset = 3 * (log2_size - 2) + ((log2_size - 1) >> 2); ++ ctx_shift = (log2_size + 1) >> 2; ++ } else { ++@@ -929,22 +1192,16 @@ static av_always_inline int last_significant_coeff_suffix_decode(HEVCContext *s, ++ return value; ++ } ++ ++-static av_always_inline int significant_coeff_group_flag_decode(HEVCContext *s, int c_idx, int ctx_cg) +++static av_always_inline int significant_coeff_group_flag_decode(HEVCContext *s, int c_idx_nz, int ctx_cg) ++ { ++ int inc; ++ ++- inc = FFMIN(ctx_cg, 1) + (c_idx>0 ? 2 : 0); +++ inc = (ctx_cg != 0) + (c_idx_nz << 1); ++ ++ return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_GROUP_FLAG] + inc); ++ } ++-static av_always_inline int significant_coeff_flag_decode(HEVCContext *s, int x_c, int y_c, ++- int offset, const uint8_t *ctx_idx_map) ++-{ ++- int inc = ctx_idx_map[(y_c << 2) + x_c] + offset; ++- return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + inc); ++-} ++ ++-static av_always_inline int significant_coeff_flag_decode_0(HEVCContext *s, int c_idx, int offset) +++static av_always_inline int significant_coeff_flag_decode_0(HEVCContext *s, int offset) ++ { ++ return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + offset); ++ } ++@@ -966,65 +1223,305 @@ static av_always_inline int coeff_abs_level_greater2_flag_decode(HEVCContext *s, ++ return GET_CABAC(elem_offset[COEFF_ABS_LEVEL_GREATER2_FLAG] + inc); ++ } ++ ++-static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int rc_rice_param) +++ +++#if !USE_BY22 +++#define coeff_abs_level_remaining_decode_bypass(s,r) coeff_abs_level_remaining_decode(s, r) +++#endif +++ +++ +++#ifndef coeff_abs_level_remaining_decode_bypass +++static int coeff_abs_level_remaining_decode_bypass(HEVCContext * const s, const unsigned int rice_param) +++{ +++ CABACContext * const c = &s->HEVClc->cc; +++ uint32_t y; +++ unsigned int prefix; +++ unsigned int last_coeff_abs_level_remaining; +++ unsigned int n; +++ +++ y = get_cabac_by22_peek(c); +++ prefix = hevc_clz32(~y); +++ // y << prefix will always have top bit 0 +++ +++ if (prefix < 3) { +++ const unsigned int suffix = (y << prefix) >> (31 - rice_param); +++ last_coeff_abs_level_remaining = (prefix << rice_param) + suffix; +++ n = prefix + 1 + rice_param; +++ } +++ else if (prefix * 2 + rice_param <= CABAC_BY22_PEEK_BITS + 2) +++ { +++ const uint32_t suffix = ((y << prefix) | 0x80000000) >> (34 - (prefix + rice_param)); +++ +++ last_coeff_abs_level_remaining = (2 << rice_param) + suffix; +++ n = prefix * 2 + rice_param - 2; +++ } +++ else { +++ unsigned int suffix; +++ +++ get_cabac_by22_flush(c, prefix, y); +++ y = get_cabac_by22_peek(c); +++ +++ suffix = (y | 0x80000000) >> (34 - (prefix + rice_param)); +++ last_coeff_abs_level_remaining = (2 << rice_param) + suffix; +++ n = prefix + rice_param - 2; +++ } +++ +++ get_cabac_by22_flush(c, n, y); +++ +++ return last_coeff_abs_level_remaining; +++} +++#endif +++ +++static int coeff_abs_level_remaining_decode(HEVCContext * const s, int rc_rice_param) ++ { +++ CABACContext * const c = &s->HEVClc->cc; ++ int prefix = 0; ++ int suffix = 0; ++ int last_coeff_abs_level_remaining; ++ int i; ++ ++- while (prefix < CABAC_MAX_BIN && get_cabac_bypass(&s->HEVClc->cc)) +++ while (prefix < CABAC_MAX_BIN && get_cabac_bypass(c)) ++ prefix++; ++ if (prefix == CABAC_MAX_BIN) { ++ av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); ++ return 0; ++ } +++ ++ if (prefix < 3) { ++ for (i = 0; i < rc_rice_param; i++) ++- suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc); +++ suffix = (suffix << 1) | get_cabac_bypass(c); ++ last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix; ++ } else { ++ int prefix_minus3 = prefix - 3; ++ for (i = 0; i < prefix_minus3 + rc_rice_param; i++) ++- suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc); +++ suffix = (suffix << 1) | get_cabac_bypass(c); ++ last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1) ++ << rc_rice_param) + suffix; ++ } +++ ++ return last_coeff_abs_level_remaining; ++ } ++ ++-static av_always_inline int coeff_sign_flag_decode(HEVCContext *s, uint8_t nb) +++#if !USE_BY22 +++#define coeff_sign_flag_decode_bypass coeff_sign_flag_decode +++static inline uint32_t coeff_sign_flag_decode(HEVCContext * const s, const unsigned int nb) ++ { ++- int i; ++- int ret = 0; +++ CABACContext * const c = &s->HEVClc->cc; +++ unsigned int i; +++ uint32_t ret = 0; ++ ++ for (i = 0; i < nb; i++) ++- ret = (ret << 1) | get_cabac_bypass(&s->HEVClc->cc); ++- return ret; +++ ret = (ret << 1) | get_cabac_bypass(c); +++ +++ return ret << (32 - nb); ++ } +++#endif +++ +++#ifndef coeff_sign_flag_decode_bypass +++static inline uint32_t coeff_sign_flag_decode_bypass(HEVCContext * const s, const unsigned int nb) +++{ +++ CABACContext * const c = &s->HEVClc->cc; +++ uint32_t y; +++ y = get_cabac_by22_peek(c); +++ get_cabac_by22_flush(c, nb, y); +++ return y & ~(0xffffffffU >> nb); +++} +++#endif +++ +++ +++#ifndef get_cabac_greater1_bits +++static inline unsigned int get_cabac_greater1_bits(CABACContext * const c, const unsigned int n, +++ uint8_t * const state0) +++{ +++ unsigned int i; +++ unsigned int rv = 0; +++ for (i = 0; i != n; ++i) { +++ const unsigned int idx = rv != 0 ? 0 : i < 3 ? i + 1 : 3; +++ const unsigned int b = get_cabac(c, state0 + idx); +++ rv = (rv << 1) | b; +++ } +++ return rv; +++} +++#endif +++ +++ +++// N.B. levels returned are the values assuming coeff_abs_level_remaining +++// is uncoded, so 1 must be added if it is coded. sum_abs also reflects +++// this version of events. +++static inline uint32_t get_greaterx_bits(HEVCContext * const s, const unsigned int n_end, int * const levels, +++ int * const pprev_subset_coded, int * const psum, +++ const unsigned int idx0_gt1, const unsigned int idx_gt2) +++{ +++ CABACContext * const c = &s->HEVClc->cc; +++ uint8_t * const state0 = s->HEVClc->cabac_state + idx0_gt1; +++ uint8_t * const state_gt2 = s->HEVClc->cabac_state + idx_gt2; +++ unsigned int rv; +++ unsigned int i; +++ const unsigned int n = FFMIN(n_end, 8); +++ +++ // Really this is i != n but the simple unconditional loop is cheaper +++ // and faster +++ for (i = 0; i != 8; ++i) +++ levels[i] = 1; +++ +++ rv = get_cabac_greater1_bits(c, n, state0); +++ +++ *pprev_subset_coded = 0; +++ *psum = n; +++ +++ rv <<= (32 - n); +++ if (rv != 0) +++ { +++ *pprev_subset_coded = 1; +++ *psum = n + 1; +++ i = hevc_clz32(rv); +++ levels[i] = 2; +++ if (get_cabac(c, state_gt2) == 0) +++ { +++ // Unset first coded bit +++ rv &= ~(0x80000000U >> i); +++ } +++ } +++ +++ if (n_end > 8) { +++ const unsigned int g8 = n_end - 8; +++ rv |= ((1 << g8) - 1) << (24 - g8); +++ for (i = 0; i != g8; ++i) { +++ levels[i + 8] = 0; +++ } +++ } +++ +++ return rv; +++} +++ +++// extended_precision_processing_flag must be false given we are +++// putting the result into a 16-bit array +++// So trans_coeff_level must fit in 16 bits too (7.4.9.1 definition of coeff_abs_level_remaining) +++// scale_m is uint8_t +++// +++// scale is [40 - 72] << [0..12] based on qp- worst case is (45 << 12) +++// or it can be 2 (if we have transquant_bypass) +++// shift is set to one less than we really want but would normally be +++// s->ps.sps->bit_depth (max 16, min 8) + log2_trafo_size (max 5, min 2?) - 5 = max 16 min 5? +++// however the scale shift is substracted from shift to a min 0 so scale_m worst = 45 << 6 +++// This can still theoretically lead to overflow but the coding would have to be very odd (& inefficient) +++// to achieve it +++ +++#ifndef trans_scale_sat +++static inline int trans_scale_sat(const int level, const unsigned int scale, const unsigned int scale_m, const unsigned int shift) +++{ +++ return av_clip_int16((((level * (int)(scale * scale_m)) >> shift) + 1) >> 1); +++} +++#endif +++ +++ +++#ifndef update_rice +++static inline void update_rice(uint8_t * const stat_coeff, +++ const unsigned int last_coeff_abs_level_remaining, +++ const unsigned int c_rice_param) +++{ +++ const unsigned int x = (last_coeff_abs_level_remaining << 1) >> c_rice_param; +++ if (x >= 6) +++ (*stat_coeff)++; +++ else if (x == 0 && *stat_coeff > 0) +++ (*stat_coeff)--; +++} +++#endif +++ +++ +++// n must be > 0 on entry +++#ifndef get_cabac_sig_coeff_flag_idxs +++static inline uint8_t * get_cabac_sig_coeff_flag_idxs(CABACContext * const c, uint8_t * const state0, +++ unsigned int n, +++ const uint8_t const * ctx_map, +++ uint8_t * p) +++{ +++ do { +++ if (get_cabac(c, state0 + ctx_map[n])) +++ *p++ = n; +++ } while (--n != 0); +++ return p; +++} +++#endif +++ +++ +++static int get_sig_coeff_flag_idxs(CABACContext * const c, uint8_t * const state0, +++ unsigned int n, +++ const uint8_t const * ctx_map, +++ uint8_t * const flag_idx) +++{ +++ int rv; +++ +++ rv = get_cabac_sig_coeff_flag_idxs(c, state0, n, ctx_map, flag_idx) - flag_idx; +++ +++ return rv; +++} +++ +++#define H4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ +++ x0, x1, x2, x3,\ +++ x4, x5, x6, x7,\ +++ x8, x9, x10, x11,\ +++ x12, x13, x14, x15} +++ +++#define V4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ +++ x0, x4, x8, x12,\ +++ x1, x5, x9, x13,\ +++ x2, x6, x10, x14,\ +++ x3, x7, x11, x15} +++ +++#define D4x4(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {\ +++ x0, x4, x1, x8,\ +++ x5, x2, x12, x9,\ +++ x6, x3, x13, x10,\ +++ x7, x14, x11, x15} +++ +++ +++static inline int next_subset(HEVCContext * const s, int i, const int c_idx_nz, +++ uint8_t * const significant_coeff_group_flag, +++ const uint8_t * const scan_x_cg, const uint8_t * const scan_y_cg, +++ int * const pPrev_sig) +++{ +++ while (--i >= 0) { +++ unsigned int x_cg = scan_x_cg[i]; +++ unsigned int y_cg = scan_y_cg[i]; +++ +++ // For the flag decode we only care about Z/NZ but +++ // we use the full Right + Down * 2 when calculating +++ // significant coeff flags so we obtain it here +++ //. +++ // The group flag array is one longer than it needs to +++ // be so we don't need to check for y_cg limits +++ unsigned int prev_sig = ((significant_coeff_group_flag[y_cg] >> (x_cg + 1)) & 1) | +++ (((significant_coeff_group_flag[y_cg + 1] >> x_cg) & 1) << 1); +++ +++ if (i == 0 || +++ significant_coeff_group_flag_decode(s, c_idx_nz, prev_sig)) +++ { +++ significant_coeff_group_flag[y_cg] |= (1 << x_cg); +++ *pPrev_sig = prev_sig; +++ break; +++ } +++ } +++ +++ return i; +++} +++ ++ ++ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ int log2_trafo_size, enum ScanType scan_idx, ++ int c_idx) ++ { ++-#define GET_COORD(offset, n) \ ++- do { \ ++- x_c = (x_cg << 2) + scan_x_off[n]; \ ++- y_c = (y_cg << 2) + scan_y_off[n]; \ ++- } while (0) ++- HEVCLocalContext *lc = s->HEVClc; ++- int transform_skip_flag = 0; +++ HEVCLocalContext * const lc = s->HEVClc; +++ int trans_skip_or_bypass = lc->cu.cu_transquant_bypass_flag; ++ ++ int last_significant_coeff_x, last_significant_coeff_y; ++- int last_scan_pos; ++- int n_end; ++ int num_coeff = 0; ++- int greater1_ctx = 1; +++ int prev_subset_coded = 0; ++ ++ int num_last_subset; ++ int x_cg_last_sig, y_cg_last_sig; ++ ++- const uint8_t *scan_x_cg, *scan_y_cg, *scan_x_off, *scan_y_off; +++ const uint8_t *scan_x_cg, *scan_y_cg; +++ const xy_off_t * scan_xy_off; ++ ++ ptrdiff_t stride = s->frame->linesize[c_idx]; ++ int hshift = s->ps.sps->hshift[c_idx]; ++@@ -1032,21 +1529,28 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride + ++ ((x0 >> hshift) << s->ps.sps->pixel_shift)]; ++ #ifdef RPI ++- int use_vpu = s->enable_rpi && !lc->cu.cu_transquant_bypass_flag && !transform_skip_flag && !lc->tu.cross_pf && log2_trafo_size>=4; +++ //***** transform_skip_flag decoded later! +++ int use_vpu = s->enable_rpi && !lc->cu.cu_transquant_bypass_flag /* && !transform_skip_flag*/ && !lc->tu.cross_pf && log2_trafo_size>=4; ++ #endif ++ int16_t *coeffs = (int16_t*)(c_idx ? lc->edge_emu_buffer2 : lc->edge_emu_buffer); ++- uint8_t significant_coeff_group_flag[8][8] = {{0}}; +++ uint8_t significant_coeff_group_flag[9] = {0}; // Allow 1 final byte that is always zero ++ int explicit_rdpcm_flag = 0; ++ int explicit_rdpcm_dir_flag; ++ ++ int trafo_size = 1 << log2_trafo_size; ++ int i; ++- int qp,shift,add,scale,scale_m; ++- const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 }; +++ int qp,shift,scale; +++ static const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 }; ++ const uint8_t *scale_matrix = NULL; ++ uint8_t dc_scale; ++ int pred_mode_intra = (c_idx == 0) ? lc->tu.intra_pred_mode : ++ lc->tu.intra_pred_mode_c; +++ +++ int prev_sig = 0; +++ const int c_idx_nz = (c_idx != 0); +++ +++ int may_hide_sign; +++ ++ #ifdef RPI ++ if (s->enable_rpi) { ++ int n = trafo_size * trafo_size; ++@@ -1078,7 +1582,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ ++ // Derive QP for dequant ++ if (!lc->cu.cu_transquant_bypass_flag) { ++- static const int qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37 }; +++ static const uint8_t qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37 }; ++ static const uint8_t rem6[51 + 4 * 6 + 1] = { ++ 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, ++ 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, ++@@ -1094,9 +1598,19 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ }; ++ int qp_y = lc->qp_y; ++ +++ may_hide_sign = s->ps.pps->sign_data_hiding_flag; +++ ++ if (s->ps.pps->transform_skip_enabled_flag && ++ log2_trafo_size <= s->ps.pps->log2_max_transform_skip_block_size) { ++- transform_skip_flag = hevc_transform_skip_flag_decode(s, c_idx); +++ int transform_skip_flag = hevc_transform_skip_flag_decode(s, c_idx_nz); +++ if (transform_skip_flag) { +++ trans_skip_or_bypass = 1; +++ if (lc->cu.pred_mode == MODE_INTRA && +++ s->ps.sps->implicit_rdpcm_enabled_flag && +++ (pred_mode_intra == 10 || pred_mode_intra == 26)) { +++ may_hide_sign = 0; +++ } +++ } ++ } ++ ++ if (c_idx == 0) { ++@@ -1129,39 +1643,73 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ qp += s->ps.sps->qp_bd_offset; ++ } ++ ++- shift = s->ps.sps->bit_depth + log2_trafo_size - 5; ++- add = 1 << (shift-1); ++- scale = level_scale[rem6[qp]] << (div6[qp]); ++- scale_m = 16; // default when no custom scaling lists. ++- dc_scale = 16; +++ // Shift is set to one less than will actually occur as the scale +++ // and saturate step adds 1 and then shifts right again +++ shift = s->ps.sps->bit_depth + log2_trafo_size - 6; +++ scale = level_scale[rem6[qp]]; +++ if (div6[qp] >= shift) { +++ scale <<= (div6[qp] - shift); +++ shift = 0; +++ } else { +++ shift -= div6[qp]; +++ } ++ ++- if (s->ps.sps->scaling_list_enable_flag && !(transform_skip_flag && log2_trafo_size > 2)) { +++ if (s->ps.sps->scaling_list_enable_flag && !(trans_skip_or_bypass && log2_trafo_size > 2)) { ++ const ScalingList *sl = s->ps.pps->scaling_list_data_present_flag ? ++- &s->ps.pps->scaling_list : &s->ps.sps->scaling_list; +++ &s->ps.pps->scaling_list : &s->ps.sps->scaling_list; ++ int matrix_id = lc->cu.pred_mode != MODE_INTRA; ++ ++ matrix_id = 3 * matrix_id + c_idx; ++ ++ scale_matrix = sl->sl[log2_trafo_size - 2][matrix_id]; +++ dc_scale = scale_matrix[0]; ++ if (log2_trafo_size >= 4) ++ dc_scale = sl->sl_dc[log2_trafo_size - 4][matrix_id]; ++ } +++ else +++ { +++ static const uint8_t sixteen_scale[64] = { +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16, +++ 16, 16, 16, 16, 16, 16, 16, 16 +++ }; +++ scale_matrix = sixteen_scale; +++ dc_scale = 16; +++ } ++ } else { +++ static const uint8_t unit_scale[64] = { +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ 1, 1, 1, 1, 1, 1, 1, 1, +++ }; +++ scale_matrix = unit_scale; ++ shift = 0; ++- add = 0; ++- scale = 0; ++- dc_scale = 0; +++ scale = 2; // We will shift right to kill this +++ dc_scale = 1; +++ +++ may_hide_sign = 0; ++ } ++ ++ if (lc->cu.pred_mode == MODE_INTER && s->ps.sps->explicit_rdpcm_enabled_flag && ++- (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { ++- explicit_rdpcm_flag = explicit_rdpcm_flag_decode(s, c_idx); +++ trans_skip_or_bypass) { +++ explicit_rdpcm_flag = explicit_rdpcm_flag_decode(s, c_idx_nz); ++ if (explicit_rdpcm_flag) { ++- explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(s, c_idx); +++ may_hide_sign = 0; +++ explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(s, c_idx_nz); ++ } ++ } ++ ++- last_significant_coeff_xy_prefix_decode(s, c_idx, log2_trafo_size, +++ last_significant_coeff_xy_prefix_decode(s, c_idx_nz, log2_trafo_size, ++ &last_significant_coeff_x, &last_significant_coeff_y); ++ ++ if (last_significant_coeff_x > 3) { ++@@ -1189,119 +1737,113 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ int last_x_c = last_significant_coeff_x & 3; ++ int last_y_c = last_significant_coeff_y & 3; ++ ++- scan_x_off = ff_hevc_diag_scan4x4_x; ++- scan_y_off = ff_hevc_diag_scan4x4_y; ++ num_coeff = diag_scan4x4_inv[last_y_c][last_x_c]; ++- if (trafo_size == 4) { +++ +++ switch (log2_trafo_size) { +++ case 2: ++ scan_x_cg = scan_1x1; ++ scan_y_cg = scan_1x1; ++- } else if (trafo_size == 8) { +++ break; +++ case 3: ++ num_coeff += diag_scan2x2_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = diag_scan2x2_x; ++ scan_y_cg = diag_scan2x2_y; ++- } else if (trafo_size == 16) { +++ break; +++ case 4: ++ num_coeff += diag_scan4x4_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = ff_hevc_diag_scan4x4_x; ++ scan_y_cg = ff_hevc_diag_scan4x4_y; ++- } else { // trafo_size == 32 +++ break; +++ case 5: +++ default: ++ num_coeff += diag_scan8x8_inv[y_cg_last_sig][x_cg_last_sig] << 4; ++ scan_x_cg = ff_hevc_diag_scan8x8_x; ++ scan_y_cg = ff_hevc_diag_scan8x8_y; +++ break; ++ } ++ break; ++ } ++ case SCAN_HORIZ: ++ scan_x_cg = horiz_scan2x2_x; ++ scan_y_cg = horiz_scan2x2_y; ++- scan_x_off = horiz_scan4x4_x; ++- scan_y_off = horiz_scan4x4_y; ++ num_coeff = horiz_scan8x8_inv[last_significant_coeff_y][last_significant_coeff_x]; ++ break; ++ default: //SCAN_VERT ++ scan_x_cg = horiz_scan2x2_y; ++ scan_y_cg = horiz_scan2x2_x; ++- scan_x_off = horiz_scan4x4_y; ++- scan_y_off = horiz_scan4x4_x; ++ num_coeff = horiz_scan8x8_inv[last_significant_coeff_x][last_significant_coeff_y]; ++ break; ++ } ++ num_coeff++; ++ num_last_subset = (num_coeff - 1) >> 4; ++ ++- for (i = num_last_subset; i >= 0; i--) { ++- int n, m; ++- int x_cg, y_cg, x_c, y_c, pos; ++- int implicit_non_zero_coeff = 0; ++- int64_t trans_coeff_level; ++- int prev_sig = 0; ++- int offset = i << 4; ++- int rice_init = 0; ++- ++- uint8_t significant_coeff_flag_idx[16]; ++- uint8_t nb_significant_coeff_flag = 0; +++ significant_coeff_group_flag[y_cg_last_sig] = 1 << x_cg_last_sig; // 1st subset always significant ++ ++- x_cg = scan_x_cg[i]; ++- y_cg = scan_y_cg[i]; +++ scan_xy_off = off_xys[scan_idx][log2_trafo_size - 2]; ++ ++- if ((i < num_last_subset) && (i > 0)) { ++- int ctx_cg = 0; ++- if (x_cg < (1 << (log2_trafo_size - 2)) - 1) ++- ctx_cg += significant_coeff_group_flag[x_cg + 1][y_cg]; ++- if (y_cg < (1 << (log2_trafo_size - 2)) - 1) ++- ctx_cg += significant_coeff_group_flag[x_cg][y_cg + 1]; ++- ++- significant_coeff_group_flag[x_cg][y_cg] = ++- significant_coeff_group_flag_decode(s, c_idx, ctx_cg); ++- implicit_non_zero_coeff = 1; ++- } else { ++- significant_coeff_group_flag[x_cg][y_cg] = ++- ((x_cg == x_cg_last_sig && y_cg == y_cg_last_sig) || ++- (x_cg == 0 && y_cg == 0)); ++- } +++ i = num_last_subset; +++ do { +++ int implicit_non_zero_coeff = 0; +++ int n_end; ++ ++- last_scan_pos = num_coeff - offset - 1; +++ uint8_t significant_coeff_flag_idx[16]; +++ unsigned int nb_significant_coeff_flag = 0; ++ ++ if (i == num_last_subset) { +++ // First time through +++ int last_scan_pos = num_coeff - (i << 4) - 1; ++ n_end = last_scan_pos - 1; ++ significant_coeff_flag_idx[0] = last_scan_pos; ++ nb_significant_coeff_flag = 1; ++ } else { ++ n_end = 15; +++ implicit_non_zero_coeff = (i != 0); ++ } ++ ++- if (x_cg < ((1 << log2_trafo_size) - 1) >> 2) ++- prev_sig = !!significant_coeff_group_flag[x_cg + 1][y_cg]; ++- if (y_cg < ((1 << log2_trafo_size) - 1) >> 2) ++- prev_sig += (!!significant_coeff_group_flag[x_cg][y_cg + 1] << 1); ++- ++- if (significant_coeff_group_flag[x_cg][y_cg] && n_end >= 0) { ++- static const uint8_t ctx_idx_map[] = { ++- 0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8, // log2_trafo_size == 2 ++- 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 0 ++- 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 1 ++- 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, // prev_sig == 2 ++- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // default +++ if (n_end >= 0) { +++ static const uint8_t ctx_idx_maps_ts2[3][16] = { +++ D4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8), // log2_trafo_size == 2 +++ H4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8), // log2_trafo_size == 2 +++ V4x4(0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8) // log2_trafo_size == 2 +++ }; +++ static const uint8_t ctx_idx_maps[3][4][16] = { +++ { +++ D4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 +++ D4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 1 +++ D4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 2 +++ D4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default +++ }, +++ { +++ H4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 +++ H4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 1 +++ H4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 2 +++ H4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default +++ }, +++ { +++ V4x4(1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 0 +++ V4x4(2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0), // prev_sig == 1 +++ V4x4(2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0), // prev_sig == 2 +++ V4x4(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) // prev_sig == 3, default +++ } ++ }; ++ const uint8_t *ctx_idx_map_p; ++ int scf_offset = 0; ++- if (s->ps.sps->transform_skip_context_enabled_flag && ++- (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { ++- ctx_idx_map_p = (uint8_t*) &ctx_idx_map[4 * 16]; ++- if (c_idx == 0) { ++- scf_offset = 40; ++- } else { ++- scf_offset = 14 + 27; ++- } +++ +++ if (s->ps.sps->transform_skip_context_enabled_flag && trans_skip_or_bypass) { +++ ctx_idx_map_p = ctx_idx_maps[0][3]; +++ scf_offset = 40 + c_idx_nz; ++ } else { ++- if (c_idx != 0) +++ if (c_idx_nz != 0) ++ scf_offset = 27; +++ ++ if (log2_trafo_size == 2) { ++- ctx_idx_map_p = (uint8_t*) &ctx_idx_map[0]; +++ ctx_idx_map_p = ctx_idx_maps_ts2[scan_idx]; ++ } else { ++- ctx_idx_map_p = (uint8_t*) &ctx_idx_map[(prev_sig + 1) << 4]; ++- if (c_idx == 0) { ++- if ((x_cg > 0 || y_cg > 0)) +++ ctx_idx_map_p = ctx_idx_maps[scan_idx][prev_sig]; +++ if (!c_idx_nz) { +++ if (i != 0) ++ scf_offset += 3; +++ ++ if (log2_trafo_size == 3) { ++ scf_offset += (scan_idx == SCAN_DIAG) ? 9 : 15; ++ } else { ++@@ -1315,34 +1857,30 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } ++ } ++ } ++- for (n = n_end; n > 0; n--) { ++- x_c = scan_x_off[n]; ++- y_c = scan_y_off[n]; ++- if (significant_coeff_flag_decode(s, x_c, y_c, scf_offset, ctx_idx_map_p)) { ++- significant_coeff_flag_idx[nb_significant_coeff_flag] = n; ++- nb_significant_coeff_flag++; +++ +++ if (n_end > 0) { +++ int cnt = get_sig_coeff_flag_idxs(&s->HEVClc->cc, +++ s->HEVClc->cabac_state + elem_offset[SIGNIFICANT_COEFF_FLAG] + scf_offset, +++ n_end, ctx_idx_map_p, +++ significant_coeff_flag_idx + nb_significant_coeff_flag); +++ +++ nb_significant_coeff_flag += cnt; +++ if (cnt != 0) { ++ implicit_non_zero_coeff = 0; ++ } ++ } +++ ++ if (implicit_non_zero_coeff == 0) { ++- if (s->ps.sps->transform_skip_context_enabled_flag && ++- (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { ++- if (c_idx == 0) { ++- scf_offset = 42; ++- } else { ++- scf_offset = 16 + 27; ++- } +++ if (s->ps.sps->transform_skip_context_enabled_flag && trans_skip_or_bypass) { +++ scf_offset = 42 + c_idx_nz; ++ } else { ++ if (i == 0) { ++- if (c_idx == 0) ++- scf_offset = 0; ++- else ++- scf_offset = 27; +++ scf_offset = c_idx_nz ? 27 : 0; ++ } else { ++ scf_offset = 2 + scf_offset; ++ } ++ } ++- if (significant_coeff_flag_decode_0(s, c_idx, scf_offset) == 1) { +++ if (significant_coeff_flag_decode_0(s, scf_offset) == 1) { ++ significant_coeff_flag_idx[nb_significant_coeff_flag] = 0; ++ nb_significant_coeff_flag++; ++ } ++@@ -1352,141 +1890,185 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } ++ } ++ ++- n_end = nb_significant_coeff_flag; ++- +++ if (nb_significant_coeff_flag != 0) { +++ const unsigned int gt1_idx_delta = (c_idx_nz << 2) | +++ ((i != 0 && !c_idx_nz) ? 2 : 0) | +++ prev_subset_coded; +++ const unsigned int idx0_gt1 = elem_offset[COEFF_ABS_LEVEL_GREATER1_FLAG] + +++ (gt1_idx_delta << 2); +++ const unsigned int idx_gt2 = elem_offset[COEFF_ABS_LEVEL_GREATER2_FLAG] + +++ gt1_idx_delta; +++ +++ const unsigned int x_cg = scan_x_cg[i]; +++ const unsigned int y_cg = scan_y_cg[i]; +++ int16_t * const blk_coeffs = coeffs + +++ ((x_cg + (y_cg << log2_trafo_size)) << 2); +++ // This calculation is 'wrong' for log2_traffo_size == 2 +++ // but that doesn't mattor as in this case x_cg & y_cg +++ // are always 0 so result is correct (0) anyway +++ const uint8_t * const blk_scale = scale_matrix + +++ (((x_cg + (y_cg << 3)) << (5 - log2_trafo_size))); +++ +++ // * THe following code block doesn't deal with these flags: +++ // (nor did the one it replaces) +++ // +++ // cabac_bypass_alignment_enabled_flag +++ // This should be easy but I can't find a test case +++ // extended_precision_processing_flag +++ // This can extend the required precision past 16bits +++ // so is probably tricky - also no example found yet +++ +++#if USE_N_END_1 +++ if (nb_significant_coeff_flag == 1) { +++ // There is a small gain to be had from special casing the single +++ // transform coefficient case. The reduction in complexity +++ // makes up for the code duplicatioon. +++ +++ int trans_coeff_level = 1; +++ int coeff_sign_flag; +++ int coded_val = 0; +++ +++ // initialize first elem of coeff_bas_level_greater1_flag +++ prev_subset_coded = 0; +++ +++ if (get_cabac(&s->HEVClc->cc, s->HEVClc->cabac_state + idx0_gt1 + 1)) { +++ trans_coeff_level = 2; +++ prev_subset_coded = 1; +++ coded_val = get_cabac(&s->HEVClc->cc, s->HEVClc->cabac_state + idx_gt2); +++ } ++ ++- if (n_end) { ++- int first_nz_pos_in_cg; ++- int last_nz_pos_in_cg; ++- int c_rice_param = 0; ++- int first_greater1_coeff_idx = -1; ++- uint8_t coeff_abs_level_greater1_flag[8]; ++- uint16_t coeff_sign_flag; ++- int sum_abs = 0; ++- int sign_hidden; ++- int sb_type; +++ // Probably not worth the overhead of starting by22 for just one value +++ coeff_sign_flag = get_cabac_bypass(&s->HEVClc->cc); ++ +++ if (coded_val) +++ { +++ if (!s->ps.sps->persistent_rice_adaptation_enabled_flag) { +++ trans_coeff_level = 3 + coeff_abs_level_remaining_decode(s, 0); +++ } else { +++ uint8_t * const stat_coeff = +++ lc->stat_coeff + trans_skip_or_bypass + 2 - ((c_idx_nz) << 1); +++ const unsigned int c_rice_param = *stat_coeff >> 2; +++ const int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param); ++ ++- // initialize first elem of coeff_bas_level_greater1_flag ++- int ctx_set = (i > 0 && c_idx == 0) ? 2 : 0; +++ trans_coeff_level = 3 + last_coeff_abs_level_remaining; +++ update_rice(stat_coeff, last_coeff_abs_level_remaining, c_rice_param); +++ } +++ } ++ ++- if (s->ps.sps->persistent_rice_adaptation_enabled_flag) { ++- if (!transform_skip_flag && !lc->cu.cu_transquant_bypass_flag) ++- sb_type = 2 * (c_idx == 0 ? 1 : 0); ++- else ++- sb_type = 2 * (c_idx == 0 ? 1 : 0) + 1; ++- c_rice_param = lc->stat_coeff[sb_type] / 4; ++- } +++ { +++ const xy_off_t * const xy_off = scan_xy_off + significant_coeff_flag_idx[0]; +++ const int k = (int32_t)(coeff_sign_flag << 31) >> 31; +++ const unsigned int scale_m = blk_scale[xy_off->scale]; ++ ++- if (!(i == num_last_subset) && greater1_ctx == 0) ++- ctx_set++; ++- greater1_ctx = 1; ++- last_nz_pos_in_cg = significant_coeff_flag_idx[0]; ++- ++- for (m = 0; m < (n_end > 8 ? 8 : n_end); m++) { ++- int inc = (ctx_set << 2) + greater1_ctx; ++- coeff_abs_level_greater1_flag[m] = ++- coeff_abs_level_greater1_flag_decode(s, c_idx, inc); ++- if (coeff_abs_level_greater1_flag[m]) { ++- greater1_ctx = 0; ++- if (first_greater1_coeff_idx == -1) ++- first_greater1_coeff_idx = m; ++- } else if (greater1_ctx > 0 && greater1_ctx < 3) { ++- greater1_ctx++; +++ blk_coeffs[xy_off->coeff] = trans_scale_sat( +++ (trans_coeff_level ^ k) - k, // Apply sign +++ scale, +++ i == 0 && xy_off->coeff == 0 ? dc_scale : scale_m, +++ shift); ++ } ++ } ++- first_nz_pos_in_cg = significant_coeff_flag_idx[n_end - 1]; ++- ++- if (lc->cu.cu_transquant_bypass_flag || ++- (lc->cu.pred_mode == MODE_INTRA && ++- s->ps.sps->implicit_rdpcm_enabled_flag && transform_skip_flag && ++- (pred_mode_intra == 10 || pred_mode_intra == 26 )) || ++- explicit_rdpcm_flag) ++- sign_hidden = 0; ++ else ++- sign_hidden = (last_nz_pos_in_cg - first_nz_pos_in_cg >= 4); +++#endif +++ { +++ int sign_hidden = may_hide_sign; +++ int levels[16]; // Should be able to get away with int16_t but that fails some tests +++ uint32_t coeff_sign_flags; +++ uint32_t coded_vals = 0; +++ // Sum(abs(level[])) +++ // In fact we only need the bottom bit and in some future +++ // version that may be all we calculate +++ unsigned int sum_abs; +++ +++ coded_vals = get_greaterx_bits(s, nb_significant_coeff_flag, levels, +++ &prev_subset_coded, &sum_abs, idx0_gt1, idx_gt2); +++ +++ if (significant_coeff_flag_idx[0] - significant_coeff_flag_idx[nb_significant_coeff_flag - 1] <= 3) +++ sign_hidden = 0; +++ +++ // -- Start bypass block +++ +++ bypass_start(s); +++ +++ coeff_sign_flags = coeff_sign_flag_decode_bypass(s, nb_significant_coeff_flag - sign_hidden); +++ +++ if (coded_vals != 0) +++ { +++ const int rice_adaptation_enabled = s->ps.sps->persistent_rice_adaptation_enabled_flag; +++ uint8_t * stat_coeff = !rice_adaptation_enabled ? NULL : +++ lc->stat_coeff + trans_skip_or_bypass + 2 - ((c_idx_nz) << 1); +++ int c_rice_param = !rice_adaptation_enabled ? 0 : *stat_coeff >> 2; +++ int * level = levels - 1; +++ +++ do { +++ { +++ const unsigned int z = hevc_clz32(coded_vals) + 1; +++ level += z; +++ coded_vals <<= z; +++ } ++ ++- if (first_greater1_coeff_idx != -1) { ++- coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set); ++- } ++- if (!s->ps.pps->sign_data_hiding_flag || !sign_hidden ) { ++- coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag); ++- } else { ++- coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1)); ++- } +++ { +++ const int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode_bypass(s, c_rice_param); +++ const int trans_coeff_level = *level + last_coeff_abs_level_remaining + 1; +++ +++ sum_abs += last_coeff_abs_level_remaining + 1; +++ *level = trans_coeff_level; ++ ++- for (m = 0; m < n_end; m++) { ++- n = significant_coeff_flag_idx[m]; ++- GET_COORD(offset, n); ++- if (m < 8) { ++- trans_coeff_level = 1 + coeff_abs_level_greater1_flag[m]; ++- if (trans_coeff_level == ((m == first_greater1_coeff_idx) ? 3 : 2)) { ++- int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param); ++- ++- trans_coeff_level += last_coeff_abs_level_remaining; ++- if (trans_coeff_level > (3 << c_rice_param)) ++- c_rice_param = s->ps.sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); ++- if (s->ps.sps->persistent_rice_adaptation_enabled_flag && !rice_init) { ++- int c_rice_p_init = lc->stat_coeff[sb_type] / 4; ++- if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) ++- lc->stat_coeff[sb_type]++; ++- else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) ++- if (lc->stat_coeff[sb_type] > 0) ++- lc->stat_coeff[sb_type]--; ++- rice_init = 1; +++ if (stat_coeff != NULL) +++ update_rice(stat_coeff, last_coeff_abs_level_remaining, c_rice_param); +++ stat_coeff = NULL; +++ +++ if (trans_coeff_level > (3 << c_rice_param) && +++ (c_rice_param < 4 || rice_adaptation_enabled)) +++ ++c_rice_param; ++ } ++- } ++- } else { ++- int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param); ++- ++- trans_coeff_level = 1 + last_coeff_abs_level_remaining; ++- if (trans_coeff_level > (3 << c_rice_param)) ++- c_rice_param = s->ps.sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4); ++- if (s->ps.sps->persistent_rice_adaptation_enabled_flag && !rice_init) { ++- int c_rice_p_init = lc->stat_coeff[sb_type] / 4; ++- if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init)) ++- lc->stat_coeff[sb_type]++; ++- else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init)) ++- if (lc->stat_coeff[sb_type] > 0) ++- lc->stat_coeff[sb_type]--; ++- rice_init = 1; ++- } +++ } while (coded_vals != 0); ++ } ++- if (s->ps.pps->sign_data_hiding_flag && sign_hidden) { ++- sum_abs += trans_coeff_level; ++- if (n == first_nz_pos_in_cg && (sum_abs&1)) ++- trans_coeff_level = -trans_coeff_level; +++ +++ // sign_hidden = 0 or 1 so we can combine the tests +++ if ((sign_hidden & sum_abs) != 0) { +++ levels[nb_significant_coeff_flag - 1] = -levels[nb_significant_coeff_flag - 1]; ++ } ++- if (coeff_sign_flag >> 15) ++- trans_coeff_level = -trans_coeff_level; ++- coeff_sign_flag <<= 1; ++- if(!lc->cu.cu_transquant_bypass_flag) { ++- if (s->ps.sps->scaling_list_enable_flag && !(transform_skip_flag && log2_trafo_size > 2)) { ++- if(y_c || x_c || log2_trafo_size < 4) { ++- switch(log2_trafo_size) { ++- case 3: pos = (y_c << 3) + x_c; break; ++- case 4: pos = ((y_c >> 1) << 3) + (x_c >> 1); break; ++- case 5: pos = ((y_c >> 2) << 3) + (x_c >> 2); break; ++- default: pos = (y_c << 2) + x_c; break; ++- } ++- scale_m = scale_matrix[pos]; ++- } else { ++- scale_m = dc_scale; ++- } +++ +++ bypass_finish(s); +++ +++ // -- Finish bypass block +++ +++ // Scale loop +++ { +++ int m = nb_significant_coeff_flag - 1; +++ +++ // Deal with DC component (if any) first +++ if (i == 0 && significant_coeff_flag_idx[m] == 0) +++ { +++ const int k = (int32_t)(coeff_sign_flags << m) >> 31; +++ blk_coeffs[0] = trans_scale_sat( +++ (levels[m] ^ k) - k, scale, dc_scale, shift); +++ --m; ++ } ++- trans_coeff_level = (trans_coeff_level * (int64_t)scale * (int64_t)scale_m + add) >> shift; ++- if(trans_coeff_level < 0) { ++- if((~trans_coeff_level) & 0xFffffffffff8000) ++- trans_coeff_level = -32768; ++- } else { ++- if(trans_coeff_level & 0xffffffffffff8000) ++- trans_coeff_level = 32767; +++ +++#if !USE_N_END_1 +++ // If N_END_! set then m was at least 1 initially +++ if (m >= 0) +++#endif +++ { +++ do { +++ const xy_off_t * const xy_off = scan_xy_off + +++ significant_coeff_flag_idx[m]; +++ const int k = (int32_t)(coeff_sign_flags << m) >> 31; +++ +++ blk_coeffs[xy_off->coeff] = trans_scale_sat( +++ (levels[m] ^ k) - k, +++ scale, +++ blk_scale[xy_off->scale], +++ shift); +++ } while (--m >= 0); ++ } ++ } ++- coeffs[y_c * trafo_size + x_c] = trans_coeff_level; +++ ++ } ++ } ++- } +++ } while ((i = next_subset(s, i, c_idx_nz, +++ significant_coeff_group_flag, scan_x_cg, scan_y_cg, &prev_sig)) >= 0); ++ ++ if (lc->cu.cu_transquant_bypass_flag) { ++ if (explicit_rdpcm_flag || (s->ps.sps->implicit_rdpcm_enabled_flag && ++@@ -1496,7 +2078,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); ++ } ++ } else { ++- if (transform_skip_flag) { +++ if (trans_skip_or_bypass) { // Must be trans_skip as we've already dealt with bypass ++ int rot = s->ps.sps->transform_skip_rotation_enabled_flag && ++ log2_trafo_size == 2 && ++ lc->cu.pred_mode == MODE_INTRA; ++-- ++2.5.0 ++ +diff --git a/tools/depends/target/ffmpeg/0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch b/tools/depends/target/ffmpeg/0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch +new file mode 100644 +index 0000000..c191dd1 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch +@@ -0,0 +1,67 @@ ++From f2e011c656b3579b6ede184bb5c56a7b97fad0f3 Mon Sep 17 00:00:00 2001 ++From: Hendrik Leppkes ++Date: Sat, 9 Jan 2016 15:34:09 +0100 ++Subject: [PATCH] avcodec: add h264_mvc codec id and profiles ++ ++avcodec: add h264_mvc codec id and profiles ++--- ++ libavcodec/avcodec.h | 5 +++++ ++ libavcodec/codec_desc.c | 7 +++++++ ++ libavcodec/profiles.c | 3 +++ ++ libavformat/mpegts.c | 2 +- ++ 4 files changed, 16 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h ++index f365775..8498921 100644 ++--- a/libavcodec/avcodec.h +++++ b/libavcodec/avcodec.h ++@@ -316,6 +316,8 @@ enum AVCodecID { ++ AV_CODEC_ID_APNG, ++ AV_CODEC_ID_DAALA, ++ +++ AV_CODEC_ID_H264_MVC, +++ ++ /* various PCM "codecs" */ ++ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs ++ AV_CODEC_ID_PCM_S16LE = 0x10000, ++@@ -3086,6 +3088,9 @@ typedef struct AVCodecContext { ++ #define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 ++ #define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) ++ #define FF_PROFILE_H264_CAVLC_444 44 +++#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +++#define FF_PROFILE_H264_STEREO_HIGH 128 +++#define FF_PROFILE_H264_MULTIVIEW_HIGH_DEPTH 138 ++ ++ #define FF_PROFILE_VC1_SIMPLE 0 ++ #define FF_PROFILE_VC1_MAIN 1 ++diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c ++index 5fbe624..9431bd8 100644 ++--- a/libavcodec/codec_desc.c +++++ b/libavcodec/codec_desc.c ++@@ -1521,6 +1521,13 @@ static const AVCodecDescriptor codec_descriptors[] = { ++ .props = AV_CODEC_PROP_LOSSLESS, ++ .mime_types= MT("image/png"), ++ }, +++ { +++ .id = AV_CODEC_ID_H264_MVC, +++ .type = AVMEDIA_TYPE_VIDEO, +++ .name = "h264_mvc", +++ .long_name = NULL_IF_CONFIG_SMALL("H264 MVC"), +++ .props = AV_CODEC_PROP_LOSSY, +++ }, ++ ++ /* various PCM "codecs" */ ++ { ++diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c ++index 22874e6..34b6987 100644 ++--- a/libavformat/mpegts.c +++++ b/libavformat/mpegts.c ++@@ -698,7 +698,7 @@ static const StreamType ISO_types[] = { ++ { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */ ++ #endif ++ { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, ++- { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, +++ { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264_MVC }, ++ { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 }, ++ { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, ++ { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, +diff --git a/tools/depends/target/ffmpeg/0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch b/tools/depends/target/ffmpeg/0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch +new file mode 100644 +index 0000000..06e4347 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch +@@ -0,0 +1,113 @@ ++From 0b857974bc3f2f48800526efbe02b9e72fdeb266 Mon Sep 17 00:00:00 2001 ++From: Hendrik Leppkes ++Date: Sat, 9 Jan 2016 16:34:40 +0100 ++Subject: [PATCH] h264_parser: add support for parsing h264 mvc NALUs ++ ++--- ++ libavcodec/allcodecs.c | 1 + ++ libavcodec/h264.h | 2 ++ ++ libavcodec/h264_parser.c | 34 ++++++++++++++++++++++++++++++---- ++ 3 files changed, 33 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c ++index 2097db0..66eb571 100644 ++--- a/libavcodec/allcodecs.c +++++ b/libavcodec/allcodecs.c ++@@ -633,6 +633,7 @@ void avcodec_register_all(void) ++ REGISTER_PARSER(H261, h261); ++ REGISTER_PARSER(H263, h263); ++ REGISTER_PARSER(H264, h264); +++ REGISTER_PARSER(H264_MVC, h264_mvc); ++ REGISTER_PARSER(HEVC, hevc); ++ REGISTER_PARSER(MJPEG, mjpeg); ++ REGISTER_PARSER(MLP, mlp); ++diff --git a/libavcodec/h264.h b/libavcodec/h264.h ++index 78f4eed..9e1d377 100644 ++--- a/libavcodec/h264.h +++++ b/libavcodec/h264.h ++@@ -123,7 +123,9 @@ enum { ++ NAL_END_STREAM = 11, ++ NAL_FILLER_DATA = 12, ++ NAL_SPS_EXT = 13, +++ NAL_SPS_SUBSET = 15, ++ NAL_AUXILIARY_SLICE = 19, +++ NAL_SLICE_EXT = 20, ++ NAL_FF_IGNORE = 0xff0f001, ++ }; ++ ++diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c ++index 12d6397..4337c8c 100644 ++--- a/libavcodec/h264_parser.c +++++ b/libavcodec/h264_parser.c ++@@ -38,6 +38,7 @@ typedef struct H264ParseContext { ++ H264Context h; ++ ParseContext pc; ++ int got_first; +++ int is_mvc; ++ } H264ParseContext; ++ ++ ++@@ -86,14 +87,18 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, ++ } else if (state <= 5) { ++ int nalu_type = buf[i] & 0x1F; ++ if (nalu_type == NAL_SEI || nalu_type == NAL_SPS || ++- nalu_type == NAL_PPS || nalu_type == NAL_AUD) { +++ nalu_type == NAL_PPS || nalu_type == NAL_AUD || +++ nalu_type == NAL_SPS_SUBSET) { ++ if (pc->frame_start_found) { ++ i++; ++ goto found; ++ } ++ } else if (nalu_type == NAL_SLICE || nalu_type == NAL_DPA || ++- nalu_type == NAL_IDR_SLICE) { +++ nalu_type == NAL_IDR_SLICE || (p->is_mvc && nalu_type == NAL_SLICE_EXT)) { ++ state += 8; +++ +++ if (nalu_type == NAL_SLICE_EXT) +++ i += 3; // skip mvc extension ++ continue; ++ } ++ state = 7; ++@@ -532,7 +537,8 @@ static int h264_parse(AVCodecParserContext *s, ++ } ++ } ++ ++- parse_nal_units(s, avctx, buf, buf_size); +++ if (!p->is_mvc) +++ parse_nal_units(s, avctx, buf, buf_size); ++ ++ if (avctx->framerate.num) ++ avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); ++@@ -569,7 +575,7 @@ static int h264_split(AVCodecContext *avctx, ++ if ((state & 0xFFFFFF00) != 0x100) ++ break; ++ nalu_type = state & 0x1F; ++- if (nalu_type == NAL_SPS) { +++ if (nalu_type == NAL_SPS || nalu_type == NAL_SPS_SUBSET) { ++ has_sps = 1; ++ } else if (nalu_type == NAL_PPS) ++ has_pps = 1; ++@@ -625,3 +631,23 @@ AVCodecParser ff_h264_parser = { ++ .parser_close = h264_close, ++ .split = h264_split, ++ }; +++ +++static av_cold int init_mvc(AVCodecParserContext *s) +++{ +++ H264ParseContext *p = s->priv_data; +++ int ret = init(s); +++ if (ret < 0) +++ return ret; +++ +++ p->is_mvc = 1; +++ return 0; +++} +++ +++AVCodecParser ff_h264_mvc_parser = { +++ .codec_ids = { AV_CODEC_ID_H264_MVC }, +++ .priv_data_size = sizeof(H264ParseContext), +++ .parser_init = init_mvc, +++ .parser_parse = h264_parse, +++ .parser_close = h264_close, +++ .split = h264_split, +++}; +diff --git a/tools/depends/target/ffmpeg/0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch b/tools/depends/target/ffmpeg/0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch +new file mode 100644 +index 0000000..4cb8dd8 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch +@@ -0,0 +1,48 @@ ++From 84e9a1784bbd3182b68cefa5e5feae8da8b9e184 Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Fri, 5 Jun 2015 22:48:33 +0100 ++Subject: [PATCH] mpeg4video: Signal unsupported GMC with more than one warp ++ point ++ ++--- ++ libavcodec/avcodec.h | 1 + ++ libavcodec/mpeg4videodec.c | 4 ++++ ++ 2 files changed, 5 insertions(+) ++ ++diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h ++index 8c7c420..e63dc2d 100644 ++--- a/libavcodec/avcodec.h +++++ b/libavcodec/avcodec.h ++@@ -2527,6 +2527,7 @@ typedef struct AVCodecContext { ++ #define FF_BUG_DC_CLIP 4096 ++ #define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. ++ #define FF_BUG_TRUNCATED 16384 +++#define FF_BUG_GMC_UNSUPPORTED 32768 ++ ++ /** ++ * strictly follow the standard (MPEG4, ...). ++diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c ++index 9bf33dd..0b5d3b9 100644 ++--- a/libavcodec/mpeg4videodec.c +++++ b/libavcodec/mpeg4videodec.c ++@@ -2179,6 +2179,9 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) ++ ++ if (ctx->divx_version >= 0) ++ s->workaround_bugs |= FF_BUG_HPEL_CHROMA; +++ +++ if (ctx->num_sprite_warping_points > 1) +++ s->workaround_bugs |= FF_BUG_GMC_UNSUPPORTED; ++ } ++ ++ if (s->workaround_bugs & FF_BUG_STD_QPEL) { ++@@ -2203,6 +2206,7 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) ++ s->workaround_bugs, ctx->lavc_build, ctx->xvid_build, ++ ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : ""); ++ +++ avctx->workaround_bugs = s->workaround_bugs; ++ if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 && ++ s->codec_id == AV_CODEC_ID_MPEG4 && ++ avctx->idct_algo == FF_IDCT_AUTO) { ++-- ++1.9.1 ++ +diff --git a/tools/depends/target/ffmpeg/73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch b/tools/depends/target/ffmpeg/73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch +new file mode 100644 +index 0000000..5240cf5 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch +@@ -0,0 +1,24 @@ ++From 73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105 Mon Sep 17 00:00:00 2001 ++From: Hendrik Leppkes ++Date: Mon, 1 Sep 2014 11:39:09 +0200 ++Subject: [PATCH] h264_parser: force grabing a new timestamp until a frame ++ start was found ++ ++--- ++ libavcodec/h264_parser.c | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c ++index 2fd3f2b..7165652 100644 ++--- a/libavcodec/h264_parser.c +++++ b/libavcodec/h264_parser.c ++@@ -525,6 +525,9 @@ static int h264_parse(AVCodecParserContext *s, ++ } else { ++ next = h264_find_frame_end(p, buf, buf_size); ++ +++ if (next == END_NOT_FOUND && pc->frame_start_found == 0) +++ s->fetch_timestamp = 1; +++ ++ if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { ++ *poutbuf = NULL; ++ *poutbuf_size = 0; +diff --git a/tools/depends/target/ffmpeg/CMakeLists.txt b/tools/depends/target/ffmpeg/CMakeLists.txt +index 41b0362..b42cd89 100644 +--- a/tools/depends/target/ffmpeg/CMakeLists.txt ++++ b/tools/depends/target/ffmpeg/CMakeLists.txt +@@ -16,7 +16,7 @@ if(CROSSCOMPILING) + endif() + + if(CORE_SYSTEM_NAME STREQUAL linux) +- list(APPEND ffmpeg_conf --enable-vdpau --enable-vaapi --enable-pic) ++ list(APPEND ffmpeg_conf --enable-vdpau --enable-vaapi) + elseif(CORE_SYSTEM_NAME STREQUAL android) + if(CPU MATCHES arm) + list(APPEND ffmpeg_conf --cpu=cortex-a9) +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index c3998be..5b2f19c 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,10 +1,24 @@ +-include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ++ ++PLATFORM = ffmpeg-$(VERSION) ++RETRIEVE_TOOL = curl ++TARBALLS_LOCATION = $(shell pwd) ++ARCHIVE_TOOL = tar ++ARCHIVE_TOOL_FLAGS = --strip-components=1 -xf ++ ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile \ ++ 0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch \ ++ hevcdsp_ARM_NEON_optimized_epel_functions.patch added_ARM_NEON_optimized_SAO_patches.patch \ ++ pfcd_hevc_optimisations.patch \ ++ 0001-Squashed-commit-of-the-following.patch \ ++ 0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch 0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch \ ++ h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch \ ++ 73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch \ ++ 0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +-APPLY_PATCHES=no ++APPLY_PATCHES=yes + + # configuration settings + ffmpg_config = --prefix=$(PREFIX) --extra-version="kodi-$(VERSION)" +@@ -12,12 +26,14 @@ ffmpg_config += --cc=$(CC) --cxx=$(CXX) --ar=$(AR) --ranlib=$(RANLIB) + ffmpg_config += --disable-devices --disable-doc + ffmpg_config += --disable-ffplay --disable-ffmpeg --disable-sdl + ffmpg_config += --disable-ffprobe --disable-ffserver +-ffmpg_config += --enable-gpl --enable-runtime-cpudetect ++ffmpg_config += --enable-gpl ++###--enable-runtime-cpudetect + ffmpg_config += --enable-postproc --enable-pthreads + ffmpg_config += --enable-muxer=spdif --enable-muxer=adts + ffmpg_config += --enable-muxer=asf --enable-muxer=ipod + ffmpg_config += --enable-encoder=ac3 --enable-encoder=aac + ffmpg_config += --enable-encoder=wmav2 --enable-protocol=http ++ffmpg_config += --pkg-config=/usr/bin/pkg-config + ffmpg_config += --enable-gnutls + ffmpg_config += --enable-encoder=png --enable-encoder=mjpeg + +@@ -26,7 +42,7 @@ ifeq ($(CROSS_COMPILING), yes) + endif + ifeq ($(OS), linux) + ffmpg_config += --target-os=$(OS) --cpu=$(CPU) +- ffmpg_config += --enable-vdpau --enable-vaapi --enable-pic ++ ffmpg_config += --enable-vdpau --enable-vaapi + endif + ifeq ($(OS), android) + ifeq ($(findstring arm, $(CPU)), arm) +@@ -48,7 +64,6 @@ ifeq ($(OS), osx) + ffmpg_config += --disable-outdev=sdl + ffmpg_config += --disable-decoder=mpeg_xvmc --disable-vda --disable-crystalhd --enable-videotoolbox + ffmpg_config += --target-os=darwin +- ffmpg_config += --disable-securetransport + endif + ifeq ($(findstring arm, $(CPU)), arm) + ffmpg_config += --enable-pic --disable-armv5te --disable-armv6t2 +@@ -60,10 +75,11 @@ ifeq ($(Configuration), Release) + ffmpg_config += --disable-debug + endif + ++ffmpg_config += $(CONFFLAGS) + + CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +-all: .installed-$(PLATFORM) ++all: .ffmpeg-installed + + $(TARBALLS_LOCATION)/$(ARCHIVE): + cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) -Ls --create-dirs -f -o $(TARBALLS_LOCATION)/$(ARCHIVE) $(BASE_URL)/$(VERSION).tar.gz +@@ -72,6 +88,16 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure ++ cd $(PLATFORM); patch -p1 < ../../0001-mpeg4video-Signal-unsupported-GMC-with-more-than-one.patch ++ cd $(PLATFORM); patch -p1 < ../../hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ cd $(PLATFORM); patch -p1 < ../../added_ARM_NEON_optimized_SAO_patches.patch ++ cd $(PLATFORM); patch -p1 < ../../pfcd_hevc_optimisations.patch ++ cd $(PLATFORM); patch -p1 < ../../0001-Squashed-commit-of-the-following.patch ++ cd $(PLATFORM); patch -p1 < ../../0001-avcodec-add-h264_mvc-codec-id-and-profiles.patch ++ cd $(PLATFORM); patch -p1 < ../../0001-h264_parser-add-support-for-parsing-h264-mvc-NALUs.patch ++ cd $(PLATFORM); patch -p1 < ../../h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch ++ cd $(PLATFORM); patch -p1 < ../../73fde6f9f3d01f7fc0f3ae4b66f6c725f9fb1105.patch ++ cd $(PLATFORM); patch -p1 < ../../0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) +@@ -79,13 +105,14 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + build: $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +-.installed-$(PLATFORM): build ++.ffmpeg-installed: build + $(MAKE) -C $(PLATFORM) install + touch $@ + + clean: + $(MAKE) -C $(PLATFORM) clean +- rm -f .installed-$(PLATFORM) ++ rm -f .ffmpeg-installed + + distclean:: +- rm -rf $(PLATFORM) .installed-$(PLATFORM) ++ rm -rf $(PLATFORM) .ffmpeg-installed ++ +diff --git a/tools/depends/target/ffmpeg/added_ARM_NEON_optimized_SAO_patches.patch b/tools/depends/target/ffmpeg/added_ARM_NEON_optimized_SAO_patches.patch +new file mode 100644 +index 0000000..792b5fe +--- /dev/null ++++ b/tools/depends/target/ffmpeg/added_ARM_NEON_optimized_SAO_patches.patch +@@ -0,0 +1,3328 @@ ++From b0cb307c253d2c9f4b94a54dfc74ddb83af984cc Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Mon, 8 Dec 2014 13:24:40 +0200 ++Subject: [PATCH 1/9] added ARM NEON optimized SAO band offset ++ ++--- ++ libavcodec/arm/Makefile | 3 +- ++ libavcodec/arm/hevcdsp_init_neon.c | 47 +++++++++ ++ libavcodec/arm/hevcdsp_sao_neon.S | 204 +++++++++++++++++++++++++++++++++++++ ++ 3 files changed, 253 insertions(+), 1 deletion(-) ++ create mode 100644 libavcodec/arm/hevcdsp_sao_neon.S ++ ++diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile ++index 6051ec8..093a2e8 100644 ++--- a/libavcodec/arm/Makefile +++++ b/libavcodec/arm/Makefile ++@@ -133,7 +133,8 @@ NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ ++ arm/hevcdsp_deblock_neon.o \ ++ arm/hevcdsp_epel_neon.o \ ++ arm/hevcdsp_idct_neon.o \ ++- arm/hevcdsp_qpel_neon.o +++ arm/hevcdsp_qpel_neon.o \ +++ arm/hevcdsp_sao_neon.o ++ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o ++ NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ ++ arm/rv40dsp_neon.o ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 733ff08..69e2b2c 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -22,6 +22,7 @@ ++ #include "libavutil/arm/cpu.h" ++ #include "libavcodec/hevcdsp.h" ++ #include "hevcdsp_arm.h" +++#include "../bit_depth_template.c" ++ ++ void ff_hevc_v_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++ void ff_hevc_h_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++@@ -43,6 +44,11 @@ void ff_hevc_transform_add_16x16_neon_8(uint8_t *_dst, int16_t *coeffs, ++ void ff_hevc_transform_add_32x32_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++ +++void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++ ++ #define PUT_PIXELS(name) \ ++ void name(int16_t *dst, uint8_t *src, \ ++ ptrdiff_t srcstride, int height, \ ++@@ -151,6 +157,44 @@ void ff_hevc_put_qpel_bi_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t ++ put_hevc_qpel_uw_neon[my][mx](dst, dststride, src, srcstride, width, height, src2, MAX_PB_SIZE); ++ } ++ +++static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, +++ int16_t *sao_offset_val, int sao_left_class, int width, int height) +++{ +++ pixel *dst = (pixel *)_dst; +++ pixel *src = (pixel *)_src; +++ int8_t offset_table[32] = { 0 }; +++ int k, y, x; +++ int shift = 3; // BIT_DEPTH - 5 +++ +++ stride_src /= sizeof(pixel); +++ stride_dst /= sizeof(pixel); +++ +++ for (k = 0; k < 4; k++) +++ offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; +++ +++ switch(width){ +++ case 8: +++ ff_hevc_sao_band_w8_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ break; +++ case 16: +++ ff_hevc_sao_band_w16_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ break; +++ case 32: +++ ff_hevc_sao_band_w32_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ break; +++ case 64: +++ ff_hevc_sao_band_w64_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ break; +++ default: +++ for (y = 0; y < height; y++) { +++ for (x = 0; x < width; x++) +++ dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); +++ dst += stride_dst; +++ src += stride_src; +++ } +++ } +++} +++ ++ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ { ++ if (bit_depth == 8) { ++@@ -170,6 +214,9 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->transform_add[2] = ff_hevc_transform_add_16x16_neon_8; ++ c->transform_add[3] = ff_hevc_transform_add_32x32_neon_8; ++ c->idct_4x4_luma = ff_hevc_transform_luma_4x4_neon_8; +++ for (x = 0; x < sizeof c->sao_band_filter / sizeof *c->sao_band_filter; x++) { +++ c->sao_band_filter[x] = ff_hevc_sao_band_neon_wrapper; +++ } ++ put_hevc_qpel_neon[1][0] = ff_hevc_put_qpel_v1_neon_8; ++ put_hevc_qpel_neon[2][0] = ff_hevc_put_qpel_v2_neon_8; ++ put_hevc_qpel_neon[3][0] = ff_hevc_put_qpel_v3_neon_8; ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++new file mode 100644 ++index 0000000..1f0ad64 ++--- /dev/null +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -0,0 +1,204 @@ +++/* +++ * Copyright (c) 2014 Seppo Tomperi +++ * +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++#include "libavutil/arm/asm.S" +++#include "neon.S" +++ +++function ff_hevc_sao_band_w8_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // offset_table +++ vpush {d8-d15} +++ vld1.8 {q0, q1}, [r5] // offset table +++ +++1: subs r4, #1 +++ vld1.8 {d24}, [r1], r3 +++ vshr.u8 d16, d24, #3 +++ vtbl.8 d16, {q0, q1}, d16 +++ vmovl.s8 q2, d16 +++ vmovl.u8 q6, d24 +++ vadd.s16 q2, q6 +++ vqmovun.s16 d4, q2 +++ vst1.8 {d4}, [r0], r2 +++ bne 1b +++ +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_band_w16_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // offset_table +++ vpush {d8-d15} +++ vld1.8 {q0, q1}, [r5] // offset table +++ +++1: subs r4, #1 +++ vld1.8 {q12}, [r1], r3 +++ +++ vshr.u8 q8, q12, #3 +++ +++ vtbl.8 d16, {q0, q1}, d16 +++ vtbl.8 d17, {q0, q1}, d17 +++ +++ vmovl.s8 q2, d16 +++ vmovl.s8 q3, d17 +++ +++ vmovl.u8 q6, d24 +++ vmovl.u8 q7, d25 +++ +++ vadd.s16 q2, q6 +++ vadd.s16 q3, q7 +++ +++ vqmovun.s16 d4, q2 +++ vqmovun.s16 d5, q3 +++ +++ vstm.8 r0, {q2} +++ add r0, r2 +++ bne 1b +++ +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_band_w32_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // offset_table +++ vpush {d8-d15} +++ vld1.8 {q0, q1}, [r5] // offset table +++ +++1: subs r4, #1 +++ vld1.8 {q12-q13}, [r1], r3 +++ +++ vshr.u8 q8, q12, #3 +++ vshr.u8 q9, q13, #3 +++ +++ vtbl.8 d16, {q0, q1}, d16 +++ vtbl.8 d17, {q0, q1}, d17 +++ vtbl.8 d18, {q0, q1}, d18 +++ vtbl.8 d19, {q0, q1}, d19 +++ +++ vmovl.s8 q2, d16 +++ vmovl.s8 q3, d17 // q8 free +++ vmovl.s8 q4, d18 +++ vmovl.s8 q5, d19 // q9 free +++ +++ vmovl.u8 q6, d24 +++ vmovl.u8 q7, d25 // q12 free +++ vmovl.u8 q8, d26 +++ vmovl.u8 q9, d27 // q13 free +++ +++ vadd.s16 q2, q6 +++ vadd.s16 q3, q7 +++ vadd.s16 q4, q8 +++ vadd.s16 q5, q9 +++ +++ vqmovun.s16 d4, q2 +++ vqmovun.s16 d5, q3 +++ vqmovun.s16 d6, q4 // q4 free +++ vqmovun.s16 d7, q5 // q5 free +++ +++ vst1.8 {q2-q3}, [r0], r2 +++ bne 1b +++ +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_band_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // offset_table +++ vpush {d8-d15} +++ vld1.8 {q0, q1}, [r5] // offset table +++ +++1: subs r4, #1 +++ vld1.8 {q12-q13}, [r1]! +++ vld1.8 {q14-q15}, [r1], r3 +++ sub r1, #32 +++ +++ vshr.u8 q8, q12, #3 +++ vshr.u8 q9, q13, #3 +++ vshr.u8 q10, q14, #3 +++ vshr.u8 q11, q15, #3 +++ +++ vtbl.8 d16, {q0, q1}, d16 +++ vtbl.8 d17, {q0, q1}, d17 +++ vtbl.8 d18, {q0, q1}, d18 +++ vtbl.8 d19, {q0, q1}, d19 +++ vtbl.8 d20, {q0, q1}, d20 +++ vtbl.8 d21, {q0, q1}, d21 +++ vtbl.8 d22, {q0, q1}, d22 +++ vtbl.8 d23, {q0, q1}, d23 +++ +++ vmovl.s8 q2, d16 +++ vmovl.s8 q3, d17 // q8 free +++ vmovl.s8 q4, d18 +++ vmovl.s8 q5, d19 // q9 free +++ +++ vmovl.u8 q6, d24 +++ vmovl.u8 q7, d25 // q12 free +++ vmovl.u8 q8, d26 +++ vmovl.u8 q9, d27 // q13 free +++ +++ vadd.s16 q2, q6 +++ vadd.s16 q3, q7 +++ vadd.s16 q4, q8 +++ vadd.s16 q5, q9 +++ +++ vqmovun.s16 d4, q2 +++ vqmovun.s16 d5, q3 +++ vqmovun.s16 d6, q4 // q4 free +++ vqmovun.s16 d7, q5 // q5 free +++ +++ // free q4 -q9, q12 - q13 +++ vmovl.s8 q4, d20 +++ vmovl.s8 q5, d21 // q10 free +++ vmovl.s8 q6, d22 +++ vmovl.s8 q7, d23 // q11 free +++ +++ vmovl.u8 q8, d28 +++ vmovl.u8 q9, d29 // q14 free +++ vmovl.u8 q10, d30 +++ vmovl.u8 q11, d31 // q15 free +++ +++ vadd.s16 q4, q8 +++ vadd.s16 q5, q9 +++ vadd.s16 q6, q10 +++ vadd.s16 q7, q11 +++ +++ vqmovun.s16 d8, q4 +++ vqmovun.s16 d9, q5 +++ vqmovun.s16 d10, q6 +++ vqmovun.s16 d11, q7 +++ +++ vstm.8 r0, {q2-q5} +++ add r0, r2 +++ bne 1b +++ +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ ++-- ++2.5.0 ++ ++ ++From 8429b1de64bb871d57651ecfe3b084e2dfe0af51 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Wed, 27 May 2015 18:10:20 +0100 ++Subject: [PATCH 2/9] added NEON optimized sao edge for eo1 width 64 ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 47 ++++++++++++ ++ libavcodec/arm/hevcdsp_sao_neon.S | 147 +++++++++++++++++++++++++++++++++++++ ++ 2 files changed, 194 insertions(+) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 69e2b2c..c7b5404 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -22,6 +22,7 @@ ++ #include "libavutil/arm/cpu.h" ++ #include "libavcodec/hevcdsp.h" ++ #include "hevcdsp_arm.h" +++#include "libavcodec/avcodec.h" ++ #include "../bit_depth_template.c" ++ ++ void ff_hevc_v_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++@@ -48,6 +49,7 @@ void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_d ++ void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++ void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++ void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++void ff_hevc_sao_edge_eo1_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++ ++ #define PUT_PIXELS(name) \ ++ void name(int16_t *dst, uint8_t *src, \ ++@@ -195,6 +197,50 @@ static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_ ++ } ++ } ++ +++#define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1)) +++static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t *_src /* align 32 */, ptrdiff_t stride_dst, +++ int16_t *_sao_offset_val, int eo, int width, int height) +++{ +++ static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; +++ static const int8_t pos[4][2][2] = { +++ { { -1, 0 }, { 1, 0 } }, // horizontal +++ { { 0, -1 }, { 0, 1 } }, // vertical +++ { { -1, -1 }, { 1, 1 } }, // 45 degree +++ { { 1, -1 }, { -1, 1 } }, // 135 degree +++ }; +++ int8_t sao_offset_val[8]; // padding of 3 for vld +++ ptrdiff_t stride_src = (2*MAX_PB_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); +++ pixel *dst = (pixel *)_dst; +++ pixel *src = (pixel *)_src; +++ int a_stride, b_stride; +++ int x, y; +++ +++ for (x = 0; x < 5; x++) { +++ sao_offset_val[x] = _sao_offset_val[x]; +++ } +++ +++ stride_src /= sizeof(pixel); +++ stride_dst /= sizeof(pixel); +++ +++ if (eo == 1 && width == 64) { +++ ff_hevc_sao_edge_eo1_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ } else { +++ a_stride = pos[eo][0][0] + pos[eo][0][1] * stride_src; +++ b_stride = pos[eo][1][0] + pos[eo][1][1] * stride_src; +++ for (y = 0; y < height; y++) { +++ for (x = 0; x < width; x++) { +++ int diff0 = CMP(src[x], src[x + a_stride]); +++ int diff1 = CMP(src[x], src[x + b_stride]); +++ int offset_val = edge_idx[2 + diff0 + diff1]; +++ dst[x] = av_clip_pixel(src[x] + sao_offset_val[offset_val]); +++ } +++ src += stride_src; +++ dst += stride_dst; +++ } +++ } +++} +++#undef CMP +++ ++ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ { ++ if (bit_depth == 8) { ++@@ -216,6 +262,7 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->idct_4x4_luma = ff_hevc_transform_luma_4x4_neon_8; ++ for (x = 0; x < sizeof c->sao_band_filter / sizeof *c->sao_band_filter; x++) { ++ c->sao_band_filter[x] = ff_hevc_sao_band_neon_wrapper; +++ c->sao_edge_filter[x] = ff_hevc_sao_edge_neon_wrapper; ++ } ++ put_hevc_qpel_neon[1][0] = ff_hevc_put_qpel_v1_neon_8; ++ put_hevc_qpel_neon[2][0] = ff_hevc_put_qpel_v2_neon_8; ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 1f0ad64..5ec2de9 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -202,3 +202,150 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ bx lr ++ endfunc ++ +++function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x02 +++ vpush {d8-d15} +++1: subs r4, #1 +++ // load a +++ sub r1, r3 +++ vld1.8 {q0-q1}, [r1]! +++ vld1.8 {q2-q3}, [r1], r3 +++ sub r1, #32 +++ // load c +++ vld1.8 {q4-q5}, [r1]! +++ vld1.8 {q6-q7}, [r1], r3 +++ sub r1, #32 +++ // load b +++ vld1.8 {q8-q9}, [r1]! +++ vld1.8 {q10-q11}, [r1], r3 +++ sub r1, #32 +++ +++ vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 +++ vcgt.u8 q13, q5, q1 +++ vcgt.u8 q1, q1, q5 +++ vcgt.u8 q14, q6, q2 +++ vcgt.u8 q2, q2, q6 +++ vcgt.u8 q15, q7, q3 +++ vcgt.u8 q3, q3, q7 +++ +++ vsub.s8 q12, q0, q12 // diff0 +++ vsub.s8 q13, q1, q13 +++ vsub.s8 q14, q2, q14 +++ vsub.s8 q15, q3, q15 +++ +++ vcgt.u8 q0, q4, q8 // c > b +++ vcgt.u8 q8, q8, q4 // b > c +++ vcgt.u8 q1, q5, q9 +++ vcgt.u8 q9, q9, q5 +++ vcgt.u8 q2, q6, q10 +++ vcgt.u8 q10, q10, q6 +++ vcgt.u8 q3, q7, q11 +++ vcgt.u8 q11, q11, q7 +++ +++ vsub.s8 q0, q8, q0 // diff1 +++ vsub.s8 q1, q9, q1 +++ vsub.s8 q2, q10, q2 +++ vsub.s8 q3, q11, q3 +++ +++ veor.u8 q8, q8 // zero register +++ vdup.s8 q9, r6 // 2 to all elements +++ add r6, #1 +++ vdup.s8 q10, r6 // 3 to all elements +++ sub r6, #1 +++ +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 +++ vadd.s8 q2, q14 +++ vadd.s8 q3, q15 +++ +++ vcgt.s8 q4, q0, q8 // diff0 + diff1 > 0 +++ vcgt.s8 q5, q1, q8 +++ vcgt.s8 q6, q2, q8 +++ vcgt.s8 q7, q3, q8 +++ +++ vclt.s8 q11, q0, q8 // diff0 + diff1 < 0 +++ vclt.s8 q12, q1, q8 +++ vclt.s8 q13, q2, q8 +++ vclt.s8 q14, q3, q8 +++ +++ vadd.s8 q8, q0, q9 // diff0 + diff1 + 2 +++ vand.8 q15, q8, q4 +++ vadd.s8 q8, q0, q10 // diff0 + diff1 + 3 +++ vand.8 q8, q8, q11 +++ vadd.s8 q0, q15, q8 // offset_idx +++ +++ vadd.s8 q8, q1, q9 // diff0 + diff1 + 2 +++ vand.8 q15, q8, q5 +++ vadd.s8 q8, q1, q10 // diff0 + diff1 + 3 +++ vand.8 q8, q8, q12 +++ vadd.s8 q1, q15, q8 // offset_idx +++ +++ vadd.s8 q8, q2, q9 // diff0 + diff1 + 2 + 2 +++ vand.8 q15, q8, q6 +++ vadd.s8 q8, q2, q10 // diff0 + diff1 + 2 + 3 +++ vand.8 q8, q8, q13 +++ vadd.s8 q2, q15, q8 // offset_idx +++ +++ vadd.s8 q8, q3, q9 // diff0 + diff1 + 2 + 2 +++ vand.8 q15, q8, q7 +++ vadd.s8 q8, q3, q10 // diff0 + diff1 + 2 + 3 +++ vand.8 q8, q8, q14 +++ vadd.s8 q3, q15, q8 // offset_idx +++ // TODO: load only once +++ vld1.8 d16, [r5] +++ +++ vtbl.8 d0, {d16}, d0 +++ vtbl.8 d1, {d16}, d1 +++ vtbl.8 d2, {d16}, d2 +++ vtbl.8 d3, {d16}, d3 +++ vtbl.8 d4, {d16}, d4 +++ vtbl.8 d5, {d16}, d5 +++ vtbl.8 d6, {d16}, d6 +++ vtbl.8 d7, {d16}, d7 +++ +++ // TODO: load only once +++ // load c again +++ sub r1, r3 +++ sub r1, r3 +++ vld1.8 {q4-q5}, [r1]! +++ vld1.8 {q6-q7}, [r1], r3 +++ sub r1, #32 +++ +++ vmovl.u8 q8, d8 +++ vmovl.u8 q9, d9 +++ vmovl.u8 q10, d10 +++ vmovl.u8 q11, d11 +++ vmovl.u8 q12, d12 +++ vmovl.u8 q13, d13 +++ vmovl.u8 q14, d14 +++ vmovl.u8 q15, d15 +++ +++ vaddw.s8 q8, d0 +++ vaddw.s8 q9, d1 +++ vaddw.s8 q10, d2 +++ vaddw.s8 q11, d3 +++ vaddw.s8 q12, d4 +++ vaddw.s8 q13, d5 +++ vaddw.s8 q14, d6 +++ vaddw.s8 q15, d7 +++ +++ vqmovun.s16 d0, q8 +++ vqmovun.s16 d1, q9 +++ vqmovun.s16 d2, q10 +++ vqmovun.s16 d3, q11 +++ vqmovun.s16 d4, q12 +++ vqmovun.s16 d5, q13 +++ vqmovun.s16 d6, q14 +++ vqmovun.s16 d7, q15 +++ +++ vstm r0, {q0-q3} +++ add r0, r2 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc ++-- ++2.5.0 ++ ++ ++From 402e2bd1c5ad659c757bf9734abe6331904fb9e2 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Tue, 16 Dec 2014 16:28:25 +0200 ++Subject: [PATCH 3/9] Added SAO edge offset for ARM NEON w32 and w64 ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 46 +++- ++ libavcodec/arm/hevcdsp_sao_neon.S | 510 +++++++++++++++++++++++++++++++------ ++ 2 files changed, 474 insertions(+), 82 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index c7b5404..c32940e 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -49,7 +49,16 @@ void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_d ++ void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++ void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++ void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++ +++void ff_hevc_sao_edge_eo0_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++void ff_hevc_sao_edge_eo1_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++void ff_hevc_sao_edge_eo2_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++void ff_hevc_sao_edge_eo3_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++ +++void ff_hevc_sao_edge_eo0_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++ void ff_hevc_sao_edge_eo1_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++void ff_hevc_sao_edge_eo2_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); +++void ff_hevc_sao_edge_eo3_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++ ++ #define PUT_PIXELS(name) \ ++ void name(int16_t *dst, uint8_t *src, \ ++@@ -222,9 +231,40 @@ static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t ++ stride_src /= sizeof(pixel); ++ stride_dst /= sizeof(pixel); ++ ++- if (eo == 1 && width == 64) { ++- ff_hevc_sao_edge_eo1_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); ++- } else { +++ switch (width) { +++ case 32: +++ switch(eo) { +++ case 0: +++ ff_hevc_sao_edge_eo0_w32_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 1: +++ ff_hevc_sao_edge_eo1_w32_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 2: +++ ff_hevc_sao_edge_eo2_w32_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 3: +++ ff_hevc_sao_edge_eo3_w32_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ } +++ break; +++ case 64: +++ switch(eo) { +++ case 0: +++ ff_hevc_sao_edge_eo0_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 1: +++ ff_hevc_sao_edge_eo1_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 2: +++ ff_hevc_sao_edge_eo2_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ case 3: +++ ff_hevc_sao_edge_eo3_w64_neon_8(dst, src, stride_dst, stride_src, height, sao_offset_val); +++ break; +++ } +++ break; +++ default: ++ a_stride = pos[eo][0][0] + pos[eo][0][1] * stride_src; ++ b_stride = pos[eo][1][0] + pos[eo][1][1] * stride_src; ++ for (y = 0; y < height; y++) { ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 5ec2de9..4687012 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -202,27 +202,7 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ bx lr ++ endfunc ++ ++-function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x02 ++- vpush {d8-d15} ++-1: subs r4, #1 ++- // load a ++- sub r1, r3 ++- vld1.8 {q0-q1}, [r1]! ++- vld1.8 {q2-q3}, [r1], r3 ++- sub r1, #32 ++- // load c ++- vld1.8 {q4-q5}, [r1]! ++- vld1.8 {q6-q7}, [r1], r3 ++- sub r1, #32 ++- // load b ++- vld1.8 {q8-q9}, [r1]! ++- vld1.8 {q10-q11}, [r1], r3 ++- sub r1, #32 ++- +++.macro edge_w64_body ++ vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 ++ vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 ++ vcgt.u8 q13, q5, q1 ++@@ -251,69 +231,61 @@ function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 ++ vsub.s8 q2, q10, q2 ++ vsub.s8 q3, q11, q3 ++ ++- veor.u8 q8, q8 // zero register ++- vdup.s8 q9, r6 // 2 to all elements ++- add r6, #1 ++- vdup.s8 q10, r6 // 3 to all elements ++- sub r6, #1 ++- ++ vadd.s8 q0, q12 //diff0 + diff1 ++ vadd.s8 q1, q13 ++ vadd.s8 q2, q14 ++ vadd.s8 q3, q15 ++ ++- vcgt.s8 q4, q0, q8 // diff0 + diff1 > 0 ++- vcgt.s8 q5, q1, q8 ++- vcgt.s8 q6, q2, q8 ++- vcgt.s8 q7, q3, q8 ++- ++- vclt.s8 q11, q0, q8 // diff0 + diff1 < 0 ++- vclt.s8 q12, q1, q8 ++- vclt.s8 q13, q2, q8 ++- vclt.s8 q14, q3, q8 ++- ++- vadd.s8 q8, q0, q9 // diff0 + diff1 + 2 ++- vand.8 q15, q8, q4 ++- vadd.s8 q8, q0, q10 // diff0 + diff1 + 3 ++- vand.8 q8, q8, q11 ++- vadd.s8 q0, q15, q8 // offset_idx ++- ++- vadd.s8 q8, q1, q9 // diff0 + diff1 + 2 ++- vand.8 q15, q8, q5 ++- vadd.s8 q8, q1, q10 // diff0 + diff1 + 3 ++- vand.8 q8, q8, q12 ++- vadd.s8 q1, q15, q8 // offset_idx ++- ++- vadd.s8 q8, q2, q9 // diff0 + diff1 + 2 + 2 ++- vand.8 q15, q8, q6 ++- vadd.s8 q8, q2, q10 // diff0 + diff1 + 2 + 3 ++- vand.8 q8, q8, q13 ++- vadd.s8 q2, q15, q8 // offset_idx ++- ++- vadd.s8 q8, q3, q9 // diff0 + diff1 + 2 + 2 ++- vand.8 q15, q8, q7 ++- vadd.s8 q8, q3, q10 // diff0 + diff1 + 2 + 3 ++- vand.8 q8, q8, q14 ++- vadd.s8 q3, q15, q8 // offset_idx ++- // TODO: load only once ++- vld1.8 d16, [r5] ++- ++- vtbl.8 d0, {d16}, d0 ++- vtbl.8 d1, {d16}, d1 ++- vtbl.8 d2, {d16}, d2 ++- vtbl.8 d3, {d16}, d3 ++- vtbl.8 d4, {d16}, d4 ++- vtbl.8 d5, {d16}, d5 ++- vtbl.8 d6, {d16}, d6 ++- vtbl.8 d7, {d16}, d7 ++- ++- // TODO: load only once ++- // load c again ++- sub r1, r3 ++- sub r1, r3 ++- vld1.8 {q4-q5}, [r1]! ++- vld1.8 {q6-q7}, [r1], r3 ++- sub r1, #32 +++ vdup.s8 q9, r6 // 3 to all elements +++ sub r6, #1 +++ +++ vclt.s8 q12, q0, #0 // diff0 + diff1 < 0 +++ vclt.s8 q13, q1, #0 +++ vclt.s8 q14, q2, #0 +++ vclt.s8 q15, q3, #0 +++ +++ vadd.s8 q8, q0, q9 // diff0 + diff1 + 3 +++ vadd.s8 q10, q1, q9 +++ vand.8 q12, q8, q12 // if (diff0 + diff1 < 0) then (diff0 + diff1 + 3) else 0 +++ vand.8 q13, q10, q13 +++ vadd.s8 q8, q2, q9 +++ vadd.s8 q10, q3, q9 +++ vand.8 q14, q8, q14 +++ vand.8 q15, q10, q15 +++ +++ vdup.s8 q9, r6 // 2 to all elements +++ add r6, #1 +++ +++ vcgt.s8 q10, q0, #0 // diff0 + diff1 > 0 +++ vadd.s8 q8, q0, q9 // diff0 + diff1 + 2 +++ vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vcgt.s8 q10, q1, #0 +++ vadd.s8 q0, q11, q12 // offset_idx +++ +++ vadd.s8 q8, q1, q9 // diff0 + diff1 + 2 +++ vcgt.s8 q12, q2, #0 +++ vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vadd.s8 q8, q2, q9 // diff0 + diff1 + 2 +++ vadd.s8 q1, q11, q13 +++ +++ vand.8 q11, q8, q12 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vcgt.s8 q10, q3, #0 +++ vadd.s8 q2, q11, q14 +++ +++ vadd.s8 q8, q3, q9 // diff0 + diff1 + 2 +++ vmov.32 d18[0], r7 // load offset table from general registers +++ vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vmov.32 d18[1], r5 // load rest of offset table +++ vadd.s8 q3, q11, q15 +++ +++ vtbl.8 d0, {d18}, d0 +++ vtbl.8 d1, {d18}, d1 +++ vtbl.8 d2, {d18}, d2 +++ vtbl.8 d3, {d18}, d3 +++ vtbl.8 d4, {d18}, d4 +++ vtbl.8 d5, {d18}, d5 +++ vtbl.8 d6, {d18}, d6 +++ vtbl.8 d7, {d18}, d7 ++ ++ vmovl.u8 q8, d8 ++ vmovl.u8 q9, d9 ++@@ -344,8 +316,388 @@ function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 ++ ++ vstm r0, {q0-q3} ++ add r0, r2 +++.endm +++ +++.macro edge_w32_body +++ vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 +++ vcgt.u8 q13, q5, q1 +++ vcgt.u8 q1, q1, q5 +++ +++ vsub.s8 q12, q0, q12 // diff0 +++ vcgt.u8 q0, q4, q8 // c > b +++ vsub.s8 q13, q1, q13 // diff0 part 2 +++ +++ vcgt.u8 q6, q8, q4 // b > c +++ vcgt.u8 q1, q5, q9 +++ vcgt.u8 q7, q9, q5 +++ +++ vsub.s8 q0, q6, q0 // diff1 +++ vsub.s8 q1, q7, q1 // diff1 part 2 +++ vadd.s8 q0, q12 //diff0 + diff1 +++ +++ vdup.s8 q7, r6 // 3 to all elements +++ sub r6, #1 +++ vadd.s8 q1, q13 +++ +++ vclt.s8 q12, q0, #0 // diff0 + diff1 < 0 +++ vclt.s8 q13, q1, #0 +++ +++ vadd.s8 q6, q0, q7 // diff0 + diff1 + 3 +++ vadd.s8 q10, q1, q7 +++ vdup.s8 q7, r6 // 2 to all elements +++ add r6, #1 +++ vand.8 q12, q6, q12 // if (diff0 + diff1 < 0) then (diff0 + diff1 + 3) else 0 +++ vand.8 q13, q10, q13 +++ +++ +++ vcgt.s8 q10, q0, #0 // diff0 + diff1 > 0 +++ vadd.s8 q6, q0, q7 // diff0 + diff1 + 2 +++ vand.8 q11, q6, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vcgt.s8 q10, q1, #0 +++ vadd.s8 q0, q11, q12 // offset_idx +++ +++ vadd.s8 q6, q1, q7 // diff0 + diff1 + 2 +++ vmov.32 d14[0], r7 // load offset table from general registers +++ vand.8 q11, q6, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 +++ vmov.32 d14[1], r5 // load rest of offset table +++ vadd.s8 q1, q11, q13 +++ +++ vtbl.8 d0, {d14}, d0 +++ vtbl.8 d1, {d14}, d1 +++ vtbl.8 d2, {d14}, d2 +++ vtbl.8 d3, {d14}, d3 +++ +++ vmovl.u8 q6, d8 +++ vmovl.u8 q7, d9 +++ vmovl.u8 q10, d10 +++ vmovl.u8 q11, d11 +++ +++ vaddw.s8 q6, d0 +++ vaddw.s8 q7, d1 +++ vaddw.s8 q10, d2 +++ vaddw.s8 q11, d3 +++ +++ vqmovun.s16 d0, q6 +++ vqmovun.s16 d1, q7 +++ vqmovun.s16 d2, q10 +++ vqmovun.s16 d3, q11 +++ +++ vstm r0, {q0-q1} +++ add r0, r2 +++.endm +++ +++function ff_hevc_sao_edge_eo0_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++ sub r1, #8 +++1: subs r4, #1 +++ vld1.64 {q10-q11}, [r1]! +++ vld1.64 {q12-q13}, [r1]! +++ vld1.64 {q14}, [r1], r3 +++ sub r1, #64 +++ // load a +++ vext.8 q0, q10, q11, #7 +++ vext.8 q1, q11, q12, #7 +++ vext.8 q2, q12, q13, #7 +++ vext.8 q3, q13, q14, #7 +++ // load c +++ vext.8 q4, q10, q11, #8 +++ vext.8 q5, q11, q12, #8 +++ vext.8 q6, q12, q13, #8 +++ vext.8 q7, q13, q14, #8 +++ // load b +++ vext.8 q8, q10, q11, #9 +++ vext.8 q9, q11, q12, #9 +++ vext.8 q10, q12, q13, #9 +++ vext.8 q11, q13, q14, #9 +++ edge_w64_body +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++ sub r1, r3 +++ // load a +++ vld1.8 {q0-q1}, [r1]! +++ vld1.8 {q2-q3}, [r1], r3 +++ sub r1, #32 +++1: subs r4, #1 +++ // load c +++ vld1.8 {q4-q5}, [r1]! +++ vld1.8 {q6-q7}, [r1], r3 +++ sub r1, #32 +++ // load b +++ vld1.8 {q8-q9}, [r1]! +++ vld1.8 {q10-q11}, [r1] +++ sub r1, #32 +++ edge_w64_body +++ // copy c to a +++ vmov.64 q0, q4 +++ vmov.64 q1, q5 +++ vmov.64 q2, q6 +++ vmov.64 q3, q7 ++ bne 1b ++ vpop {d8-d15} ++ pop {r4-r8} ++ bx lr ++ endfunc +++ +++function ff_hevc_sao_edge_eo2_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++1: sub r1, r3 +++ // load a +++ // TODO: fix unaligned load +++ // don't reload a like in eo1 +++ sub r1, #1 +++ vld1.8 {q0-q1}, [r1]! +++ vld1.8 {q2-q3}, [r1], r3 +++ sub r1, #31 +++ subs r4, #1 +++ // load c +++ vld1.8 {q4-q5}, [r1]! +++ vld1.8 {q6-q7}, [r1], r3 +++ sub r1, #32 +++ // load b +++ add r1, #1 +++ vld1.8 {q8-q9}, [r1]! +++ vld1.8 {q10-q11}, [r1] +++ sub r1, #33 +++ edge_w64_body +++ // copy c to a +++ vmov.64 q0, q4 +++ vmov.64 q1, q5 +++ vmov.64 q2, q6 +++ vmov.64 q3, q7 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo3_w64_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++1: sub r1, r3 +++ // load a +++ // TODO: fix unaligned load +++ // don't reload a like in eo1 +++ add r1, #1 +++ vld1.8 {q0-q1}, [r1]! +++ vld1.8 {q2-q3}, [r1], r3 +++ sub r1, #33 +++ subs r4, #1 +++ // load c +++ vld1.8 {q4-q5}, [r1]! +++ vld1.8 {q6-q7}, [r1], r3 +++ sub r1, #32 +++ // load b +++ sub r1, #1 +++ vld1.8 {q8-q9}, [r1]! +++ vld1.8 {q10-q11}, [r1] +++ sub r1, #31 +++ edge_w64_body +++ // copy c to a +++ vmov.64 q0, q4 +++ vmov.64 q1, q5 +++ vmov.64 q2, q6 +++ vmov.64 q3, q7 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo0_w32_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++ sub r1, #8 // load 8 extra bytes +++1: subs r4, #1 +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 // only first 9 bytes are used +++ sub r1, #32 +++ // a +++ vext.8 q0, q10, q11, #7 +++ vext.8 q1, q11, q12, #7 +++ // c +++ vext.8 q4, q10, q11, #8 +++ vext.8 q5, q11, q12, #8 +++ // b +++ vext.8 q8, q10, q11, #9 +++ vext.8 q9, q11, q12, #9 +++ edge_w32_body +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo1_w32_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++ // load a +++ sub r1, r3 +++ vld1.8 {q0-q1}, [r1], r3 +++ // load c +++ vld1.8 {q4-q5}, [r1], r3 +++1: subs r4, #1 +++ // load b +++ vld1.8 {q8-q9}, [r1], r3 +++ edge_w32_body +++ // inputs for next loop iteration +++ // a +++ vmov.64 q0, q4 +++ vmov.64 q1, q5 +++ // c +++ vmov.64 q4, q8 +++ vmov.64 q5, q9 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo2_w32_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ ldr r5, [r5] +++ vpush {d8-d15} +++ // load a +++ sub r1, r3 +++ sub r1, #8 +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q0, q10, q11, #7 +++ vext.8 q1, q11, q12, #7 +++ // load c +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q4, q10, q11, #8 +++ vext.8 q5, q11, q12, #8 +++ vext.8 q2, q10, q11, #7 +++1: subs r4, #1 +++ // load b +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q8, q10, q11, #9 +++ vext.8 q9, q11, q12, #9 +++ vext.8 q14, q10, q11, #8 +++ vext.8 q15, q11, q12, #8 +++ vext.8 q3, q10, q11, #7 +++ edge_w32_body +++ // inputs for next loop iteration +++ // a +++ vmov.8 q0, q2 +++ vext.8 q1, q4, q5, #15 +++ // c +++ vmov.8 q4, q14 +++ vmov.8 q5, q15 +++ vmov.8 q2, q3 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ +++function ff_hevc_sao_edge_eo3_w32_neon_8, export=1 +++ push {r4-r8} +++ ldr r4, [sp, #20] // height +++ ldr r5, [sp, #24] // sao_offset_val_table +++ ldr r6, =0x03 +++ ldr r7, [r5] +++ add r5, #4 +++ sub r1, r3 +++ ldr r5, [r5] +++ sub r1, #8 +++ vpush {d8-d15} +++ // load a +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q0, q10, q11, #9 +++ vext.8 q1, q11, q12, #9 +++ // load c +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q4, q10, q11, #8 +++ vext.8 q5, q11, q12, #8 +++ vext.8 q2, q12, q11, #8 +++1: subs r4, #1 +++ // load b +++ vld1.8 {q10-q11}, [r1] +++ add r1, #32 +++ vld1.8 {q12}, [r1], r3 +++ sub r1, #32 +++ vext.8 q8, q10, q11, #7 +++ vext.8 q9, q11, q12, #7 +++ vext.8 q3, q12, q10, #7 +++ edge_w32_body +++ // inputs for next loop iteration +++ // a +++ vext.8 q0, q4, q5, #1 +++ vext.8 q1, q5, q2, #1 +++ // c +++ vext.8 q4, q8, q9, #1 +++ vext.8 q5, q9, q3, #1 +++ vext.8 q2, q3, q1, #1 +++ bne 1b +++ vpop {d8-d15} +++ pop {r4-r8} +++ bx lr +++endfunc +++ ++-- ++2.5.0 ++ ++ ++From 1898d052a73370166d57e17cc7c52b7275887df3 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Fri, 19 Dec 2014 09:44:10 +0200 ++Subject: [PATCH 4/9] Improved SAO band NEON opimizations made SAO buffer 16 ++ byte aligned added alignment hints to loads and stores optimized register ++ usage in SAO band neon assembly ++ ++--- ++ libavcodec/arm/hevcdsp_sao_neon.S | 212 +++++++++++++++----------------------- ++ 1 file changed, 82 insertions(+), 130 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 4687012..ac21013 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -22,120 +22,84 @@ ++ #include "neon.S" ++ ++ function ff_hevc_sao_band_w8_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // offset_table ++- vpush {d8-d15} ++- vld1.8 {q0, q1}, [r5] // offset table +++ ldr r12, [sp, #4] // offset_table address +++ vld1.8 {q0, q1}, [r12] // offset table +++ ldr r12, [sp, #0] // height ++ ++-1: subs r4, #1 ++- vld1.8 {d24}, [r1], r3 +++1: subs r12, #1 +++ vld1.8 {d24}, [r1,:64], r3 ++ vshr.u8 d16, d24, #3 ++ vtbl.8 d16, {q0, q1}, d16 ++- vmovl.s8 q2, d16 ++ vmovl.u8 q6, d24 ++- vadd.s16 q2, q6 +++ vaddw.s8 q6, d16 ++ vqmovun.s16 d4, q2 ++- vst1.8 {d4}, [r0], r2 +++ vst1.8 {d4}, [r0,:64], r2 ++ bne 1b ++ ++- vpop {d8-d15} ++- pop {r4-r8} ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_band_w16_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // offset_table ++- vpush {d8-d15} ++- vld1.8 {q0, q1}, [r5] // offset table ++- ++-1: subs r4, #1 ++- vld1.8 {q12}, [r1], r3 +++ ldr r12, [sp, #4] // offset_table address +++ vld1.8 {q0, q1}, [r12] // offset table +++ ldr r12, [sp, #0] // height ++ +++1: subs r12, #1 +++ vld1.8 {q12}, [r1,:128], r3 ++ vshr.u8 q8, q12, #3 ++- ++ vtbl.8 d16, {q0, q1}, d16 ++ vtbl.8 d17, {q0, q1}, d17 ++- ++- vmovl.s8 q2, d16 ++- vmovl.s8 q3, d17 ++- ++- vmovl.u8 q6, d24 ++- vmovl.u8 q7, d25 ++- ++- vadd.s16 q2, q6 ++- vadd.s16 q3, q7 ++- ++- vqmovun.s16 d4, q2 ++- vqmovun.s16 d5, q3 ++- ++- vstm.8 r0, {q2} ++- add r0, r2 +++ vmovl.u8 q10, d24 +++ vmovl.u8 q11, d25 +++ vaddw.s8 q10, d16 +++ vaddw.s8 q11, d17 +++ vqmovun.s16 d4, q10 +++ vqmovun.s16 d5, q11 +++ vst1.8 {q2}, [r0,:128], r2 ++ bne 1b ++ ++- vpop {d8-d15} ++- pop {r4-r8} ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_band_w32_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // offset_table ++- vpush {d8-d15} ++- vld1.8 {q0, q1}, [r5] // offset table ++- ++-1: subs r4, #1 ++- vld1.8 {q12-q13}, [r1], r3 ++- ++- vshr.u8 q8, q12, #3 ++- vshr.u8 q9, q13, #3 ++- ++- vtbl.8 d16, {q0, q1}, d16 ++- vtbl.8 d17, {q0, q1}, d17 ++- vtbl.8 d18, {q0, q1}, d18 ++- vtbl.8 d19, {q0, q1}, d19 ++- ++- vmovl.s8 q2, d16 ++- vmovl.s8 q3, d17 // q8 free ++- vmovl.s8 q4, d18 ++- vmovl.s8 q5, d19 // q9 free ++- ++- vmovl.u8 q6, d24 ++- vmovl.u8 q7, d25 // q12 free ++- vmovl.u8 q8, d26 ++- vmovl.u8 q9, d27 // q13 free ++- ++- vadd.s16 q2, q6 ++- vadd.s16 q3, q7 ++- vadd.s16 q4, q8 ++- vadd.s16 q5, q9 ++- ++- vqmovun.s16 d4, q2 ++- vqmovun.s16 d5, q3 ++- vqmovun.s16 d6, q4 // q4 free ++- vqmovun.s16 d7, q5 // q5 free ++- ++- vst1.8 {q2-q3}, [r0], r2 ++- bne 1b ++- ++- vpop {d8-d15} ++- pop {r4-r8} ++- bx lr +++ ldr r12, [sp, #4] // offset_table address +++ vld1.8 {q0, q1}, [r12] // offset table +++ ldr r12, [sp, #0] // height +++ +++1: subs r12, #1 +++ vld1.8 {q2-q3}, [r1,:128], r3 +++ vshr.u8 q8, q2, #3 +++ vshr.u8 q9, q3, #3 +++ vtbl.8 d16, {q0, q1}, d16 +++ vtbl.8 d17, {q0, q1}, d17 +++ vtbl.8 d18, {q0, q1}, d18 +++ vtbl.8 d19, {q0, q1}, d19 +++ vmovl.u8 q12, d4 +++ vmovl.u8 q13, d5 +++ vmovl.u8 q14, d6 +++ vmovl.u8 q15, d7 +++ vaddw.s8 q12, d16 +++ vaddw.s8 q13, d17 +++ vaddw.s8 q14, d18 +++ vaddw.s8 q15, d19 +++ vqmovun.s16 d4, q12 +++ vqmovun.s16 d5, q13 +++ vqmovun.s16 d6, q14 +++ vqmovun.s16 d7, q15 +++ vst1.8 {q2-q3}, [r0,:128], r2 +++ bne 1b +++ +++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_band_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // offset_table ++- vpush {d8-d15} ++- vld1.8 {q0, q1}, [r5] // offset table +++ ldr r12, [sp, #4] // offset_table address +++ vld1.8 {q0, q1}, [r12] // offset table +++ ldr r12, [sp, #0] // height ++ ++-1: subs r4, #1 ++- vld1.8 {q12-q13}, [r1]! ++- vld1.8 {q14-q15}, [r1], r3 +++1: subs r12, #1 +++ vld1.8 {q12-q13}, [r1,:128]! +++ vld1.8 {q14-q15}, [r1,:128], r3 ++ sub r1, #32 ++ ++ vshr.u8 q8, q12, #3 ++@@ -152,53 +116,41 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ vtbl.8 d22, {q0, q1}, d22 ++ vtbl.8 d23, {q0, q1}, d23 ++ ++- vmovl.s8 q2, d16 ++- vmovl.s8 q3, d17 // q8 free ++- vmovl.s8 q4, d18 ++- vmovl.s8 q5, d19 // q9 free +++ vmovl.u8 q2, d24 +++ vmovl.u8 q3, d25 +++ vmovl.u8 q12, d26 +++ vmovl.u8 q13, d27 ++ ++- vmovl.u8 q6, d24 ++- vmovl.u8 q7, d25 // q12 free ++- vmovl.u8 q8, d26 ++- vmovl.u8 q9, d27 // q13 free ++- ++- vadd.s16 q2, q6 ++- vadd.s16 q3, q7 ++- vadd.s16 q4, q8 ++- vadd.s16 q5, q9 +++ vaddw.s8 q2, d16 +++ vaddw.s8 q3, d17 +++ vaddw.s8 q12, d18 +++ vaddw.s8 q13, d19 ++ ++ vqmovun.s16 d4, q2 ++ vqmovun.s16 d5, q3 ++- vqmovun.s16 d6, q4 // q4 free ++- vqmovun.s16 d7, q5 // q5 free ++- ++- // free q4 -q9, q12 - q13 ++- vmovl.s8 q4, d20 ++- vmovl.s8 q5, d21 // q10 free ++- vmovl.s8 q6, d22 ++- vmovl.s8 q7, d23 // q11 free ++- ++- vmovl.u8 q8, d28 ++- vmovl.u8 q9, d29 // q14 free ++- vmovl.u8 q10, d30 ++- vmovl.u8 q11, d31 // q15 free ++- ++- vadd.s16 q4, q8 ++- vadd.s16 q5, q9 ++- vadd.s16 q6, q10 ++- vadd.s16 q7, q11 ++- ++- vqmovun.s16 d8, q4 ++- vqmovun.s16 d9, q5 ++- vqmovun.s16 d10, q6 ++- vqmovun.s16 d11, q7 ++- ++- vstm.8 r0, {q2-q5} ++- add r0, r2 +++ vqmovun.s16 d6, q12 +++ vqmovun.s16 d7, q13 +++ +++ vmovl.u8 q12, d28 +++ vmovl.u8 q13, d29 +++ vmovl.u8 q14, d30 +++ vmovl.u8 q15, d31 +++ +++ vaddw.s8 q12, d20 +++ vaddw.s8 q13, d21 +++ vaddw.s8 q14, d22 +++ vaddw.s8 q15, d23 +++ +++ vqmovun.s16 d8, q12 +++ vqmovun.s16 d9, q13 +++ vqmovun.s16 d10, q14 +++ vqmovun.s16 d11, q15 +++ +++ vst1.8 {q2-q3}, [r0,:128]! +++ vst1.8 {q4-q5}, [r0,:128], r2 +++ sub r0, #32 ++ bne 1b ++ ++- vpop {d8-d15} ++- pop {r4-r8} ++ bx lr ++ endfunc ++ ++-- ++2.5.0 ++ ++ ++From 26bd536800db2f50ff6a021e1fda0d0394d1ea01 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Mon, 29 Dec 2014 15:00:49 +0200 ++Subject: [PATCH 5/9] better code reuse in NEON SAO band ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 16 ++-- ++ libavcodec/arm/hevcdsp_sao_neon.S | 155 +++++++++++++------------------------ ++ 2 files changed, 61 insertions(+), 110 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index c32940e..6379810 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -45,10 +45,10 @@ void ff_hevc_transform_add_16x16_neon_8(uint8_t *_dst, int16_t *coeffs, ++ void ff_hevc_transform_add_32x32_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++ ++-void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++-void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++-void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); ++-void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t * offset_table); +++void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); +++void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); +++void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); +++void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); ++ ++ void ff_hevc_sao_edge_eo0_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++ void ff_hevc_sao_edge_eo1_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++@@ -185,16 +185,16 @@ static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_ ++ ++ switch(width){ ++ case 8: ++- ff_hevc_sao_band_w8_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ ff_hevc_sao_band_w8_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); ++ break; ++ case 16: ++- ff_hevc_sao_band_w16_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ ff_hevc_sao_band_w16_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); ++ break; ++ case 32: ++- ff_hevc_sao_band_w32_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ ff_hevc_sao_band_w32_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); ++ break; ++ case 64: ++- ff_hevc_sao_band_w64_neon_8(_dst, _src, stride_dst, stride_src, height, offset_table); +++ ff_hevc_sao_band_w64_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); ++ break; ++ default: ++ for (y = 0; y < height; y++) { ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index ac21013..8852550 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -21,53 +21,13 @@ ++ #include "libavutil/arm/asm.S" ++ #include "neon.S" ++ ++-function ff_hevc_sao_band_w8_neon_8, export=1 ++- ldr r12, [sp, #4] // offset_table address +++.macro init_sao_band +++ ldr r12, [sp, #0] // offset_table address ++ vld1.8 {q0, q1}, [r12] // offset table ++- ldr r12, [sp, #0] // height ++- ++-1: subs r12, #1 ++- vld1.8 {d24}, [r1,:64], r3 ++- vshr.u8 d16, d24, #3 ++- vtbl.8 d16, {q0, q1}, d16 ++- vmovl.u8 q6, d24 ++- vaddw.s8 q6, d16 ++- vqmovun.s16 d4, q2 ++- vst1.8 {d4}, [r0,:64], r2 ++- bne 1b ++- ++- bx lr ++-endfunc ++- ++-function ff_hevc_sao_band_w16_neon_8, export=1 ++- ldr r12, [sp, #4] // offset_table address ++- vld1.8 {q0, q1}, [r12] // offset table ++- ldr r12, [sp, #0] // height ++- ++-1: subs r12, #1 ++- vld1.8 {q12}, [r1,:128], r3 ++- vshr.u8 q8, q12, #3 ++- vtbl.8 d16, {q0, q1}, d16 ++- vtbl.8 d17, {q0, q1}, d17 ++- vmovl.u8 q10, d24 ++- vmovl.u8 q11, d25 ++- vaddw.s8 q10, d16 ++- vaddw.s8 q11, d17 ++- vqmovun.s16 d4, q10 ++- vqmovun.s16 d5, q11 ++- vst1.8 {q2}, [r0,:128], r2 ++- bne 1b ++- ++- bx lr ++-endfunc ++- ++-function ff_hevc_sao_band_w32_neon_8, export=1 ++- ldr r12, [sp, #4] // offset_table address ++- vld1.8 {q0, q1}, [r12] // offset table ++- ldr r12, [sp, #0] // height +++ ldr r12, [sp, #4] // height +++.endm ++ ++-1: subs r12, #1 ++- vld1.8 {q2-q3}, [r1,:128], r3 +++.macro sao_band_32 ++ vshr.u8 q8, q2, #3 ++ vshr.u8 q9, q3, #3 ++ vtbl.8 d16, {q0, q1}, d16 ++@@ -86,6 +46,43 @@ function ff_hevc_sao_band_w32_neon_8, export=1 ++ vqmovun.s16 d5, q13 ++ vqmovun.s16 d6, q14 ++ vqmovun.s16 d7, q15 +++.endm +++ +++function ff_hevc_sao_band_w8_neon_8, export=1 +++ init_sao_band +++1: subs r12, #4 +++ vld1.8 {d4}, [r1,:64], r3 +++ vld1.8 {d5}, [r1,:64], r3 +++ vld1.8 {d6}, [r1,:64], r3 +++ vld1.8 {d7}, [r1,:64], r3 +++ sao_band_32 +++ vst1.8 {d4}, [r0,:64], r2 +++ vst1.8 {d5}, [r0,:64], r2 +++ vst1.8 {d6}, [r0,:64], r2 +++ vst1.8 {d7}, [r0,:64], r2 +++ bne 1b +++ +++ bx lr +++endfunc +++ +++function ff_hevc_sao_band_w16_neon_8, export=1 +++ init_sao_band +++1: subs r12, #2 +++ vld1.8 {q2}, [r1,:128], r3 +++ vld1.8 {q3}, [r1,:128], r3 +++ sao_band_32 +++ vst1.8 {q2}, [r0,:128], r2 +++ vst1.8 {q3}, [r0,:128], r2 +++ bne 1b +++ +++ bx lr +++endfunc +++ +++function ff_hevc_sao_band_w32_neon_8, export=1 +++ init_sao_band +++1: subs r12, #1 +++ vld1.8 {q2-q3}, [r1,:128], r3 +++ sao_band_32 ++ vst1.8 {q2-q3}, [r0,:128], r2 ++ bne 1b ++ ++@@ -93,63 +90,17 @@ function ff_hevc_sao_band_w32_neon_8, export=1 ++ endfunc ++ ++ function ff_hevc_sao_band_w64_neon_8, export=1 ++- ldr r12, [sp, #4] // offset_table address ++- vld1.8 {q0, q1}, [r12] // offset table ++- ldr r12, [sp, #0] // height ++- ++-1: subs r12, #1 ++- vld1.8 {q12-q13}, [r1,:128]! ++- vld1.8 {q14-q15}, [r1,:128], r3 ++- sub r1, #32 ++- ++- vshr.u8 q8, q12, #3 ++- vshr.u8 q9, q13, #3 ++- vshr.u8 q10, q14, #3 ++- vshr.u8 q11, q15, #3 ++- ++- vtbl.8 d16, {q0, q1}, d16 ++- vtbl.8 d17, {q0, q1}, d17 ++- vtbl.8 d18, {q0, q1}, d18 ++- vtbl.8 d19, {q0, q1}, d19 ++- vtbl.8 d20, {q0, q1}, d20 ++- vtbl.8 d21, {q0, q1}, d21 ++- vtbl.8 d22, {q0, q1}, d22 ++- vtbl.8 d23, {q0, q1}, d23 ++- ++- vmovl.u8 q2, d24 ++- vmovl.u8 q3, d25 ++- vmovl.u8 q12, d26 ++- vmovl.u8 q13, d27 ++- ++- vaddw.s8 q2, d16 ++- vaddw.s8 q3, d17 ++- vaddw.s8 q12, d18 ++- vaddw.s8 q13, d19 ++- ++- vqmovun.s16 d4, q2 ++- vqmovun.s16 d5, q3 ++- vqmovun.s16 d6, q12 ++- vqmovun.s16 d7, q13 ++- ++- vmovl.u8 q12, d28 ++- vmovl.u8 q13, d29 ++- vmovl.u8 q14, d30 ++- vmovl.u8 q15, d31 ++- ++- vaddw.s8 q12, d20 ++- vaddw.s8 q13, d21 ++- vaddw.s8 q14, d22 ++- vaddw.s8 q15, d23 ++- ++- vqmovun.s16 d8, q12 ++- vqmovun.s16 d9, q13 ++- vqmovun.s16 d10, q14 ++- vqmovun.s16 d11, q15 ++- ++- vst1.8 {q2-q3}, [r0,:128]! ++- vst1.8 {q4-q5}, [r0,:128], r2 ++- sub r0, #32 ++- bne 1b +++ init_sao_band +++1: subs r12, #1 +++ vld1.8 {q2-q3}, [r1,:128]! +++ sao_band_32 +++ vst1.8 {q2-q3}, [r0,:128]! +++ vld1.8 {q2-q3}, [r1,:128], r3 +++ sub r1, #32 +++ sao_band_32 +++ vst1.8 {q2-q3}, [r0,:128], r2 +++ sub r0, #32 +++ bne 1b ++ ++ bx lr ++ endfunc ++-- ++2.5.0 ++ ++ ++From f93646a97bc885b81759e774d04be3781916a3e7 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Wed, 7 Jan 2015 15:27:38 +0200 ++Subject: [PATCH 6/9] More SAO NEON optimizations Now uses only 8 bit integers ++ for SAO calculations ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 7 +- ++ libavcodec/arm/hevcdsp_sao_neon.S | 664 +++++++++++++++---------------------- ++ 2 files changed, 272 insertions(+), 399 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 6379810..8d6e863 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -225,7 +225,7 @@ static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t ++ int x, y; ++ ++ for (x = 0; x < 5; x++) { ++- sao_offset_val[x] = _sao_offset_val[x]; +++ sao_offset_val[x] = _sao_offset_val[edge_idx[x]]; ++ } ++ ++ stride_src /= sizeof(pixel); ++@@ -271,8 +271,9 @@ static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t ++ for (x = 0; x < width; x++) { ++ int diff0 = CMP(src[x], src[x + a_stride]); ++ int diff1 = CMP(src[x], src[x + b_stride]); ++- int offset_val = edge_idx[2 + diff0 + diff1]; ++- dst[x] = av_clip_pixel(src[x] + sao_offset_val[offset_val]); +++ int idx = diff0 + diff1; +++ if (idx) +++ dst[x] = av_clip_pixel(src[x] + sao_offset_val[idx+2]); ++ } ++ src += stride_src; ++ dst += stride_dst; ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 8852550..5fc482b 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -1,5 +1,5 @@ ++ /* ++- * Copyright (c) 2014 Seppo Tomperi +++ * Copyright (c) 2014 - 2015 Seppo Tomperi ++ * ++ * This file is part of FFmpeg. ++ * ++@@ -23,6 +23,7 @@ ++ ++ .macro init_sao_band ++ ldr r12, [sp, #0] // offset_table address +++ pld [r1] ++ vld1.8 {q0, q1}, [r12] // offset table ++ ldr r12, [sp, #4] // height ++ .endm ++@@ -30,36 +31,31 @@ ++ .macro sao_band_32 ++ vshr.u8 q8, q2, #3 ++ vshr.u8 q9, q3, #3 +++ vmov.u8 q14, #128 ++ vtbl.8 d16, {q0, q1}, d16 ++ vtbl.8 d17, {q0, q1}, d17 ++ vtbl.8 d18, {q0, q1}, d18 ++ vtbl.8 d19, {q0, q1}, d19 ++- vmovl.u8 q12, d4 ++- vmovl.u8 q13, d5 ++- vmovl.u8 q14, d6 ++- vmovl.u8 q15, d7 ++- vaddw.s8 q12, d16 ++- vaddw.s8 q13, d17 ++- vaddw.s8 q14, d18 ++- vaddw.s8 q15, d19 ++- vqmovun.s16 d4, q12 ++- vqmovun.s16 d5, q13 ++- vqmovun.s16 d6, q14 ++- vqmovun.s16 d7, q15 +++ vadd.s8 q2, q14 +++ vadd.s8 q3, q14 +++ vqadd.s8 q2, q8 +++ vqadd.s8 q3, q9 +++ vsub.s8 q2, q14 +++ vsub.s8 q3, q14 ++ .endm ++ ++ function ff_hevc_sao_band_w8_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #4 ++- vld1.8 {d4}, [r1,:64], r3 ++- vld1.8 {d5}, [r1,:64], r3 ++- vld1.8 {d6}, [r1,:64], r3 ++- vld1.8 {d7}, [r1,:64], r3 +++ vld1.8 {d4}, [r1, :64], r3 +++ vld1.8 {d5}, [r1, :64], r3 +++ vld1.8 {d6}, [r1, :64], r3 +++ vld1.8 {d7}, [r1, :64], r3 ++ sao_band_32 ++- vst1.8 {d4}, [r0,:64], r2 ++- vst1.8 {d5}, [r0,:64], r2 ++- vst1.8 {d6}, [r0,:64], r2 ++- vst1.8 {d7}, [r0,:64], r2 +++ vst1.8 {d4}, [r0, :64], r2 +++ vst1.8 {d5}, [r0, :64], r2 +++ vst1.8 {d6}, [r0, :64], r2 +++ vst1.8 {d7}, [r0, :64], r2 ++ bne 1b ++ ++ bx lr ++@@ -68,11 +64,11 @@ endfunc ++ function ff_hevc_sao_band_w16_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #2 ++- vld1.8 {q2}, [r1,:128], r3 ++- vld1.8 {q3}, [r1,:128], r3 +++ vld1.8 {q2}, [r1, :128], r3 +++ vld1.8 {q3}, [r1, :128], r3 ++ sao_band_32 ++- vst1.8 {q2}, [r0,:128], r2 ++- vst1.8 {q3}, [r0,:128], r2 +++ vst1.8 {q2}, [r0, :128], r2 +++ vst1.8 {q3}, [r0, :128], r2 ++ bne 1b ++ ++ bx lr ++@@ -81,9 +77,9 @@ endfunc ++ function ff_hevc_sao_band_w32_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #1 ++- vld1.8 {q2-q3}, [r1,:128], r3 +++ vld1.8 {q2-q3}, [r1, :128], r3 ++ sao_band_32 ++- vst1.8 {q2-q3}, [r0,:128], r2 +++ vst1.8 {q2-q3}, [r0, :128], r2 ++ bne 1b ++ ++ bx lr ++@@ -92,263 +88,153 @@ endfunc ++ function ff_hevc_sao_band_w64_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #1 ++- vld1.8 {q2-q3}, [r1,:128]! +++ pld [r1, r3] +++ vld1.8 {q2-q3}, [r1, :128]! ++ sao_band_32 ++- vst1.8 {q2-q3}, [r0,:128]! ++- vld1.8 {q2-q3}, [r1,:128], r3 +++ vst1.8 {q2-q3}, [r0, :128]! +++ vld1.8 {q2-q3}, [r1, :128], r3 ++ sub r1, #32 ++ sao_band_32 ++- vst1.8 {q2-q3}, [r0,:128], r2 +++ vst1.8 {q2-q3}, [r0, :128], r2 ++ sub r0, #32 ++ bne 1b ++ ++ bx lr ++ endfunc ++- +++// input +++// a in q0 - q3 +++// c in q4 - q7 +++// b in q8 - q11 +++// offset table in r7 and r5 +++// output in q0 - q3 +++// clobbers q12 - q15 ++ .macro edge_w64_body ++- vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 ++- vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 ++- vcgt.u8 q13, q5, q1 ++- vcgt.u8 q1, q1, q5 ++- vcgt.u8 q14, q6, q2 ++- vcgt.u8 q2, q2, q6 ++- vcgt.u8 q15, q7, q3 ++- vcgt.u8 q3, q3, q7 ++- ++- vsub.s8 q12, q0, q12 // diff0 ++- vsub.s8 q13, q1, q13 ++- vsub.s8 q14, q2, q14 ++- vsub.s8 q15, q3, q15 ++- +++ vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 +++ vcgt.u8 q13, q5, q1 +++ vcgt.u8 q1, q1, q5 +++ vsub.s8 q12, q0, q12 // diff0 ++ vcgt.u8 q0, q4, q8 // c > b ++- vcgt.u8 q8, q8, q4 // b > c +++ vsub.s8 q13, q1, q13 +++ +++ vcgt.u8 q14, q8, q4 // b > c ++ vcgt.u8 q1, q5, q9 ++- vcgt.u8 q9, q9, q5 ++- vcgt.u8 q2, q6, q10 ++- vcgt.u8 q10, q10, q6 ++- vcgt.u8 q3, q7, q11 ++- vcgt.u8 q11, q11, q7 +++ vcgt.u8 q15, q9, q5 +++ vsub.s8 q0, q14, q0 // diff1 ++ ++- vsub.s8 q0, q8, q0 // diff1 ++- vsub.s8 q1, q9, q1 ++- vsub.s8 q2, q10, q2 ++- vsub.s8 q3, q11, q3 +++ vsub.s8 q1, q15, q1 ++ ++- vadd.s8 q0, q12 //diff0 + diff1 ++- vadd.s8 q1, q13 ++- vadd.s8 q2, q14 ++- vadd.s8 q3, q15 ++- ++- vdup.s8 q9, r6 // 3 to all elements ++- sub r6, #1 ++- ++- vclt.s8 q12, q0, #0 // diff0 + diff1 < 0 ++- vclt.s8 q13, q1, #0 ++- vclt.s8 q14, q2, #0 ++- vclt.s8 q15, q3, #0 ++- ++- vadd.s8 q8, q0, q9 // diff0 + diff1 + 3 ++- vadd.s8 q10, q1, q9 ++- vand.8 q12, q8, q12 // if (diff0 + diff1 < 0) then (diff0 + diff1 + 3) else 0 ++- vand.8 q13, q10, q13 ++- vadd.s8 q8, q2, q9 ++- vadd.s8 q10, q3, q9 ++- vand.8 q14, q8, q14 ++- vand.8 q15, q10, q15 ++- ++- vdup.s8 q9, r6 // 2 to all elements ++- add r6, #1 ++- ++- vcgt.s8 q10, q0, #0 // diff0 + diff1 > 0 ++- vadd.s8 q8, q0, q9 // diff0 + diff1 + 2 ++- vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vcgt.s8 q10, q1, #0 ++- vadd.s8 q0, q11, q12 // offset_idx ++- ++- vadd.s8 q8, q1, q9 // diff0 + diff1 + 2 ++- vcgt.s8 q12, q2, #0 ++- vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vadd.s8 q8, q2, q9 // diff0 + diff1 + 2 ++- vadd.s8 q1, q11, q13 ++- ++- vand.8 q11, q8, q12 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vcgt.s8 q10, q3, #0 ++- vadd.s8 q2, q11, q14 ++- ++- vadd.s8 q8, q3, q9 // diff0 + diff1 + 2 ++- vmov.32 d18[0], r7 // load offset table from general registers ++- vand.8 q11, q8, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vmov.32 d18[1], r5 // load rest of offset table ++- vadd.s8 q3, q11, q15 ++- ++- vtbl.8 d0, {d18}, d0 ++- vtbl.8 d1, {d18}, d1 ++- vtbl.8 d2, {d18}, d2 ++- vtbl.8 d3, {d18}, d3 ++- vtbl.8 d4, {d18}, d4 ++- vtbl.8 d5, {d18}, d5 ++- vtbl.8 d6, {d18}, d6 ++- vtbl.8 d7, {d18}, d7 ++- ++- vmovl.u8 q8, d8 ++- vmovl.u8 q9, d9 ++- vmovl.u8 q10, d10 ++- vmovl.u8 q11, d11 ++- vmovl.u8 q12, d12 ++- vmovl.u8 q13, d13 ++- vmovl.u8 q14, d14 ++- vmovl.u8 q15, d15 ++- ++- vaddw.s8 q8, d0 ++- vaddw.s8 q9, d1 ++- vaddw.s8 q10, d2 ++- vaddw.s8 q11, d3 ++- vaddw.s8 q12, d4 ++- vaddw.s8 q13, d5 ++- vaddw.s8 q14, d6 ++- vaddw.s8 q15, d7 ++- ++- vqmovun.s16 d0, q8 ++- vqmovun.s16 d1, q9 ++- vqmovun.s16 d2, q10 ++- vqmovun.s16 d3, q11 ++- vqmovun.s16 d4, q12 ++- vqmovun.s16 d5, q13 ++- vqmovun.s16 d6, q14 ++- vqmovun.s16 d7, q15 ++- ++- vstm r0, {q0-q3} ++- add r0, r2 ++-.endm +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 ++ ++-.macro edge_w32_body ++- vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 ++- vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 ++- vcgt.u8 q13, q5, q1 ++- vcgt.u8 q1, q1, q5 +++ vcgt.u8 q14, q6, q2 +++ vcgt.u8 q2, q2, q6 +++ vcgt.u8 q15, q7, q3 +++ vcgt.u8 q3, q3, q7 ++ ++- vsub.s8 q12, q0, q12 // diff0 ++- vcgt.u8 q0, q4, q8 // c > b ++- vsub.s8 q13, q1, q13 // diff0 part 2 +++ vsub.s8 q14, q2, q14 +++ vcgt.u8 q2, q6, q10 +++ vsub.s8 q15, q3, q15 ++ ++- vcgt.u8 q6, q8, q4 // b > c ++- vcgt.u8 q1, q5, q9 ++- vcgt.u8 q7, q9, q5 +++ vcgt.u8 q12, q10, q6 +++ vcgt.u8 q3, q7, q11 +++ vcgt.u8 q13, q11, q7 +++ vsub.s8 q2, q12, q2 +++ vsub.s8 q3, q13, q3 ++ ++- vsub.s8 q0, q6, q0 // diff1 ++- vsub.s8 q1, q7, q1 // diff1 part 2 ++- vadd.s8 q0, q12 //diff0 + diff1 +++ vmov.s8 q13, #2 // 2 to all elements ++ ++- vdup.s8 q7, r6 // 3 to all elements ++- sub r6, #1 ++- vadd.s8 q1, q13 +++ vadd.s8 q2, q14 +++ vadd.s8 q3, q15 +++ +++ vmov.32 d24[0], r4 // load offset table from general registers +++ vmov.32 d24[1], r5 // load rest of offset table ++ ++- vclt.s8 q12, q0, #0 // diff0 + diff1 < 0 ++- vclt.s8 q13, q1, #0 ++- ++- vadd.s8 q6, q0, q7 // diff0 + diff1 + 3 ++- vadd.s8 q10, q1, q7 ++- vdup.s8 q7, r6 // 2 to all elements ++- add r6, #1 ++- vand.8 q12, q6, q12 // if (diff0 + diff1 < 0) then (diff0 + diff1 + 3) else 0 ++- vand.8 q13, q10, q13 ++- ++- ++- vcgt.s8 q10, q0, #0 // diff0 + diff1 > 0 ++- vadd.s8 q6, q0, q7 // diff0 + diff1 + 2 ++- vand.8 q11, q6, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vcgt.s8 q10, q1, #0 ++- vadd.s8 q0, q11, q12 // offset_idx ++- ++- vadd.s8 q6, q1, q7 // diff0 + diff1 + 2 ++- vmov.32 d14[0], r7 // load offset table from general registers ++- vand.8 q11, q6, q10 // if (diff0 + diff1 > 0) then (diff0 + diff1 + 2) else 0 ++- vmov.32 d14[1], r5 // load rest of offset table ++- vadd.s8 q1, q11, q13 ++- ++- vtbl.8 d0, {d14}, d0 ++- vtbl.8 d1, {d14}, d1 ++- vtbl.8 d2, {d14}, d2 ++- vtbl.8 d3, {d14}, d3 ++- ++- vmovl.u8 q6, d8 ++- vmovl.u8 q7, d9 ++- vmovl.u8 q10, d10 ++- vmovl.u8 q11, d11 ++- ++- vaddw.s8 q6, d0 ++- vaddw.s8 q7, d1 ++- vaddw.s8 q10, d2 ++- vaddw.s8 q11, d3 ++- ++- vqmovun.s16 d0, q6 ++- vqmovun.s16 d1, q7 ++- vqmovun.s16 d2, q10 ++- vqmovun.s16 d3, q11 ++- ++- vstm r0, {q0-q1} ++- add r0, r2 +++ vadd.s8 q0, q13 +++ vadd.s8 q1, q13 +++ vadd.s8 q2, q13 +++ vadd.s8 q3, q13 +++ +++ vmov.u8 q15, #128 // s8 #-128 +++ vtbl.8 d0, {d24}, d0 +++ vtbl.8 d1, {d24}, d1 +++ vtbl.8 d2, {d24}, d2 +++ vtbl.8 d3, {d24}, d3 +++ vtbl.8 d4, {d24}, d4 +++ vtbl.8 d5, {d24}, d5 +++ vtbl.8 d6, {d24}, d6 +++ vtbl.8 d7, {d24}, d7 +++ +++ vadd.s8 q12, q4, q15 +++ vadd.s8 q13, q5, q15 +++ vadd.s8 q14, q6, q15 +++ vadd.s8 q15, q7, q15 +++ vqadd.s8 q12, q0 +++ vqadd.s8 q15, q3 +++ vmov.u8 q3, #128 // s8 #-128 +++ vqadd.s8 q13, q1 +++ vqadd.s8 q14, q2 +++ vsub.s8 q0, q12, q3 +++ vsub.s8 q1, q13, q3 +++ vsub.s8 q2, q14, q3 +++ vsub.s8 q3, q15, q3 +++ vst1.8 {q0-q1}, [r0, :128]! +++ vst1.8 {q2-q3}, [r0, :128], r2 +++ sub r0, #32 ++ .endm ++ ++-function ff_hevc_sao_edge_eo0_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] +++.macro init_edge_64 +++ push {r4-r5} +++ ldr r12, [sp, #8] // height +++ ldr r5, [sp, #12] // sao_offset_val_table +++ ldr r4, [r5] ++ add r5, #4 ++ ldr r5, [r5] +++.endm +++ +++function ff_hevc_sao_edge_eo0_w64_neon_8, export=1 +++ init_edge_64 ++ vpush {d8-d15} ++ sub r1, #8 ++-1: subs r4, #1 ++- vld1.64 {q10-q11}, [r1]! ++- vld1.64 {q12-q13}, [r1]! ++- vld1.64 {q14}, [r1], r3 ++- sub r1, #64 +++1: subs r12, #1 +++ vld1.64 {d7}, [r1, :64]! +++ vld1.64 {q4-q5}, [r1, :128]! // load c +++ vld1.64 {q6-q7}, [r1, :128]! +++ vld1.64 {d24}, [r1, :64], r3 +++ sub r1, #72 ++ // load a ++- vext.8 q0, q10, q11, #7 ++- vext.8 q1, q11, q12, #7 ++- vext.8 q2, q12, q13, #7 ++- vext.8 q3, q13, q14, #7 ++- // load c ++- vext.8 q4, q10, q11, #8 ++- vext.8 q5, q11, q12, #8 ++- vext.8 q6, q12, q13, #8 ++- vext.8 q7, q13, q14, #8 +++ vext.8 q0, q3, q4, #15 +++ vext.8 q1, q4, q5, #15 +++ vext.8 q2, q5, q6, #15 +++ vext.8 q3, q6, q7, #15 ++ // load b ++- vext.8 q8, q10, q11, #9 ++- vext.8 q9, q11, q12, #9 ++- vext.8 q10, q12, q13, #9 ++- vext.8 q11, q13, q14, #9 +++ vext.8 q8, q4, q5, #1 +++ vext.8 q9, q5, q6, #1 +++ vext.8 q10, q6, q7, #1 +++ vext.8 q11, q7, q12, #1 ++ edge_w64_body ++ bne 1b ++ vpop {d8-d15} ++- pop {r4-r8} +++ pop {r4-r5} ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] +++ init_edge_64 ++ vpush {d8-d15} ++ sub r1, r3 ++ // load a ++- vld1.8 {q0-q1}, [r1]! ++- vld1.8 {q2-q3}, [r1], r3 +++ vld1.8 {q0-q1}, [r1, :128]! +++ vld1.8 {q2-q3}, [r1, :128], r3 ++ sub r1, #32 ++-1: subs r4, #1 ++ // load c ++- vld1.8 {q4-q5}, [r1]! ++- vld1.8 {q6-q7}, [r1], r3 +++ vld1.8 {q4-q5}, [r1, :128]! +++ vld1.8 {q6-q7}, [r1, :128], r3 ++ sub r1, #32 +++1: subs r12, #1 ++ // load b ++- vld1.8 {q8-q9}, [r1]! ++- vld1.8 {q10-q11}, [r1] +++ vld1.8 {q8-q9}, [r1, :128]! +++ vld1.8 {q10-q11}, [r1, :128], r3 ++ sub r1, #32 ++ edge_w64_body ++ // copy c to a ++@@ -356,20 +242,19 @@ function ff_hevc_sao_edge_eo1_w64_neon_8, export=1 ++ vmov.64 q1, q5 ++ vmov.64 q2, q6 ++ vmov.64 q3, q7 +++ // copy b to c +++ vmov.64 q4, q8 +++ vmov.64 q5, q9 +++ vmov.64 q6, q10 +++ vmov.64 q7, q11 ++ bne 1b ++ vpop {d8-d15} ++- pop {r4-r8} +++ pop {r4-r5} ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo2_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] +++ init_edge_64 ++ vpush {d8-d15} ++ 1: sub r1, r3 ++ // load a ++@@ -379,10 +264,10 @@ function ff_hevc_sao_edge_eo2_w64_neon_8, export=1 ++ vld1.8 {q0-q1}, [r1]! ++ vld1.8 {q2-q3}, [r1], r3 ++ sub r1, #31 ++- subs r4, #1 +++ subs r12, #1 ++ // load c ++- vld1.8 {q4-q5}, [r1]! ++- vld1.8 {q6-q7}, [r1], r3 +++ vld1.8 {q4-q5}, [r1, :128]! +++ vld1.8 {q6-q7}, [r1, :128], r3 ++ sub r1, #32 ++ // load b ++ add r1, #1 ++@@ -390,25 +275,14 @@ function ff_hevc_sao_edge_eo2_w64_neon_8, export=1 ++ vld1.8 {q10-q11}, [r1] ++ sub r1, #33 ++ edge_w64_body ++- // copy c to a ++- vmov.64 q0, q4 ++- vmov.64 q1, q5 ++- vmov.64 q2, q6 ++- vmov.64 q3, q7 ++ bne 1b ++ vpop {d8-d15} ++- pop {r4-r8} +++ pop {r4-r5} ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo3_w64_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] +++ init_edge_64 ++ vpush {d8-d15} ++ 1: sub r1, r3 ++ // load a ++@@ -418,10 +292,10 @@ function ff_hevc_sao_edge_eo3_w64_neon_8, export=1 ++ vld1.8 {q0-q1}, [r1]! ++ vld1.8 {q2-q3}, [r1], r3 ++ sub r1, #33 ++- subs r4, #1 +++ subs r12, #1 ++ // load c ++- vld1.8 {q4-q5}, [r1]! ++- vld1.8 {q6-q7}, [r1], r3 +++ vld1.8 {q4-q5}, [r1, :128]! +++ vld1.8 {q6-q7}, [r1, :128], r3 ++ sub r1, #32 ++ // load b ++ sub r1, #1 ++@@ -429,178 +303,176 @@ function ff_hevc_sao_edge_eo3_w64_neon_8, export=1 ++ vld1.8 {q10-q11}, [r1] ++ sub r1, #31 ++ edge_w64_body ++- // copy c to a ++- vmov.64 q0, q4 ++- vmov.64 q1, q5 ++- vmov.64 q2, q6 ++- vmov.64 q3, q7 ++ bne 1b ++ vpop {d8-d15} ++- pop {r4-r8} +++ pop {r4-r5} ++ bx lr ++ endfunc ++ +++// inputs: +++// a in q0, q1 +++// c in q2, q3 +++// b in q8, q9 +++// offset table in d31 +++// clobbered registers q0, q1, q10, q11, q12, q13 +++// output q0, q1 +++.macro edge_w32_body +++ vcgt.u8 q12, q2, q0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 q0, q0, q2 // a > c -> -1 , otherwise 0 +++ vcgt.u8 q13, q3, q1 +++ vcgt.u8 q1, q1, q3 +++ +++ vsub.s8 q12, q0, q12 // diff0 +++ vcgt.u8 q0, q2, q8 // c > b +++ vsub.s8 q13, q1, q13 // diff0 part 2 +++ +++ vcgt.u8 q10, q8, q2 // b > c +++ vcgt.u8 q1, q3, q9 +++ vcgt.u8 q11, q9, q3 +++ +++ vsub.s8 q0, q10, q0 // diff1 +++ +++ vmov.s8 q10, #2 // 2 to all elements +++ vsub.s8 q1, q11, q1 // diff1 part 2 +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 +++ +++ vadd.s8 q0, q10 +++ vadd.s8 q1, q10 +++ +++ vmov.u8 q10, #128 +++ vtbl.8 d0, {d31}, d0 +++ vtbl.8 d1, {d31}, d1 +++ vtbl.8 d2, {d31}, d2 +++ vtbl.8 d3, {d31}, d3 +++ +++ vadd.s8 q11, q2, q10 +++ vadd.s8 q12, q3, q10 +++ vqadd.s8 q11, q0 +++ vqadd.s8 q12, q1 +++ vsub.s8 q0, q11, q10 +++ vsub.s8 q1, q12, q10 +++ vst1.8 {q0-q1}, [r0, :128], r2 +++.endm +++ +++.macro init_edge_32 +++ ldr r12, [sp, #4] // sao_offset_val_table +++ vld1.32 {d31}, [r12] +++ ldr r12, [sp] // height +++.endm +++ ++ function ff_hevc_sao_edge_eo0_w32_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] ++- vpush {d8-d15} ++- sub r1, #8 // load 8 extra bytes ++-1: subs r4, #1 ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 // only first 9 bytes are used ++- sub r1, #32 +++ init_edge_32 +++ sub r1, #4 // load 4 extra bytes +++1: subs r12, #1 +++ vld1.32 d3[1], [r1]! +++ vld1.8 {q2-q3}, [r1, :128]! // c +++ vld1.32 d20[0], [r1], r3 +++ sub r1, #36 ++ // a ++- vext.8 q0, q10, q11, #7 ++- vext.8 q1, q11, q12, #7 ++- // c ++- vext.8 q4, q10, q11, #8 ++- vext.8 q5, q11, q12, #8 +++ vext.8 q0, q1, q2, #15 +++ vext.8 q1, q2, q3, #15 ++ // b ++- vext.8 q8, q10, q11, #9 ++- vext.8 q9, q11, q12, #9 +++ vext.8 q8, q2, q3, #1 +++ vext.8 q9, q3, q10, #1 ++ edge_w32_body ++- bne 1b ++- vpop {d8-d15} ++- pop {r4-r8} ++- bx lr +++ bne 1b +++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo1_w32_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] ++- vpush {d8-d15} +++ init_edge_32 ++ // load a ++ sub r1, r3 ++- vld1.8 {q0-q1}, [r1], r3 +++ vld1.8 {q0-q1}, [r1, :128], r3 ++ // load c ++- vld1.8 {q4-q5}, [r1], r3 ++-1: subs r4, #1 +++ vld1.8 {q2-q3}, [r1, :128], r3 +++1: subs r12, #1 ++ // load b ++- vld1.8 {q8-q9}, [r1], r3 +++ vld1.8 {q8-q9}, [r1, :128], r3 ++ edge_w32_body ++ // inputs for next loop iteration ++ // a ++- vmov.64 q0, q4 ++- vmov.64 q1, q5 +++ vmov.64 q0, q2 +++ vmov.64 q1, q3 ++ // c ++- vmov.64 q4, q8 ++- vmov.64 q5, q9 ++- bne 1b ++- vpop {d8-d15} ++- pop {r4-r8} ++- bx lr +++ vmov.64 q2, q8 +++ vmov.64 q3, q9 +++ bne 1b +++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo2_w32_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- ldr r5, [r5] ++- vpush {d8-d15} +++ init_edge_32 +++ vpush {d8-d15} ++ // load a ++ sub r1, r3 ++- sub r1, #8 ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 +++ sub r1, #8 +++ vld1.8 {q10-q11}, [r1, :64]! +++ vld1.8 {d24}, [r1, :64], r3 +++ sub r1, #32 ++ vext.8 q0, q10, q11, #7 ++ vext.8 q1, q11, q12, #7 ++ // load c ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 ++- vext.8 q4, q10, q11, #8 ++- vext.8 q5, q11, q12, #8 ++- vext.8 q2, q10, q11, #7 ++-1: subs r4, #1 +++ vld1.8 {d9}, [r1, :64]! +++ vld1.8 {q2-q3}, [r1, :64], r3 +++ sub r1, #8 +++ vext.8 q4, q4, q2, #15 +++1: subs r12, #1 ++ // load b ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 +++ vld1.8 {q10-q11}, [r1, :64]! +++ vld1.8 {q12}, [r1, :64], r3 +++ sub r1, #32 ++ vext.8 q8, q10, q11, #9 ++ vext.8 q9, q11, q12, #9 ++- vext.8 q14, q10, q11, #8 ++- vext.8 q15, q11, q12, #8 ++- vext.8 q3, q10, q11, #7 +++ vext.8 q6, q10, q11, #8 +++ vext.8 q7, q11, q12, #8 +++ vext.8 q5, q10, q11, #7 ++ edge_w32_body ++ // inputs for next loop iteration ++ // a ++- vmov.8 q0, q2 ++- vext.8 q1, q4, q5, #15 +++ vmov.8 q0, q4 +++ vext.8 q1, q2, q3, #15 ++ // c ++- vmov.8 q4, q14 ++- vmov.8 q5, q15 ++- vmov.8 q2, q3 ++- bne 1b ++- vpop {d8-d15} ++- pop {r4-r8} ++- bx lr +++ vmov.8 q2, q6 +++ vmov.8 q3, q7 +++ vmov.8 q4, q5 +++ bne 1b +++ vpop {d8-d15} +++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo3_w32_neon_8, export=1 ++- push {r4-r8} ++- ldr r4, [sp, #20] // height ++- ldr r5, [sp, #24] // sao_offset_val_table ++- ldr r6, =0x03 ++- ldr r7, [r5] ++- add r5, #4 ++- sub r1, r3 ++- ldr r5, [r5] ++- sub r1, #8 ++- vpush {d8-d15} +++ init_edge_32 +++ sub r1, r3 ++ // load a ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 ++- vext.8 q0, q10, q11, #9 ++- vext.8 q1, q11, q12, #9 +++ vld1.8 {q10-q11}, [r1, :64]! +++ vld1.8 {d24}, [r1, :64], r3 +++ sub r1, #32 +++ vext.8 q0, q10, q11, #1 +++ vext.8 q1, q11, q12, #1 ++ // load c ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 ++- vext.8 q4, q10, q11, #8 ++- vext.8 q5, q11, q12, #8 ++- vext.8 q2, q12, q11, #8 ++-1: subs r4, #1 +++ vld1.8 {q2-q3}, [r1, :64]! +++ vld1.8 {d30}, [r1, :64], r3 +++ sub r1, #40 +++1: subs r12, #1 ++ // load b ++- vld1.8 {q10-q11}, [r1] ++- add r1, #32 ++- vld1.8 {q12}, [r1], r3 ++- sub r1, #32 +++ vld1.8 {q10-q11}, [r1, :64]! +++ vld1.8 {q12}, [r1, :64], r3 +++ sub r1, #32 ++ vext.8 q8, q10, q11, #7 ++ vext.8 q9, q11, q12, #7 ++- vext.8 q3, q12, q10, #7 +++ vext.8 q14, q12, q10, #7 ++ edge_w32_body ++ // inputs for next loop iteration ++ // a ++- vext.8 q0, q4, q5, #1 ++- vext.8 q1, q5, q2, #1 +++ vext.8 q0, q2, q3, #1 +++ vext.8 q1, q3, q15, #1 ++ // c ++- vext.8 q4, q8, q9, #1 ++- vext.8 q5, q9, q3, #1 ++- vext.8 q2, q3, q1, #1 ++- bne 1b ++- vpop {d8-d15} ++- pop {r4-r8} ++- bx lr +++ vext.8 q2, q8, q9, #1 +++ vext.8 q3, q9, q14, #1 +++ vext.8 d30, d28, d2, #1 +++ bne 1b +++ bx lr ++ endfunc ++ ++-- ++2.5.0 ++ ++ ++From 016c39d46b86830204a4519590332d2a38f7ee51 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Thu, 8 Jan 2015 09:58:55 +0200 ++Subject: [PATCH 7/9] small optimization to SAO BAND. correct path for ++ bit_depth_template.c ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 2 +- ++ libavcodec/arm/hevcdsp_sao_neon.S | 2 +- ++ 2 files changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 8d6e863..385c35d 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -23,7 +23,7 @@ ++ #include "libavcodec/hevcdsp.h" ++ #include "hevcdsp_arm.h" ++ #include "libavcodec/avcodec.h" ++-#include "../bit_depth_template.c" +++#include "libavcodec/bit_depth_template.c" ++ ++ void ff_hevc_v_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++ void ff_hevc_h_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 5fc482b..710b32b 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -26,12 +26,12 @@ ++ pld [r1] ++ vld1.8 {q0, q1}, [r12] // offset table ++ ldr r12, [sp, #4] // height +++ vmov.u8 q14, #128 ++ .endm ++ ++ .macro sao_band_32 ++ vshr.u8 q8, q2, #3 ++ vshr.u8 q9, q3, #3 ++- vmov.u8 q14, #128 ++ vtbl.8 d16, {q0, q1}, d16 ++ vtbl.8 d17, {q0, q1}, d17 ++ vtbl.8 d18, {q0, q1}, d18 ++-- ++2.5.0 ++ ++ ++From 579f1584d688e1ac24fb7d22697e2a7b64f62e8e Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Fri, 9 Jan 2015 10:28:52 +0200 ++Subject: [PATCH 8/9] Added height check for SAO NEON optimizations. Faster SAO ++ band NEON Some reordering to use NEON pipelines more efficiently ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 12 +++- ++ libavcodec/arm/hevcdsp_sao_neon.S | 142 ++++++++++++++++++++++--------------- ++ 2 files changed, 93 insertions(+), 61 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 385c35d..6d0689c 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -176,6 +176,7 @@ static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_ ++ int8_t offset_table[32] = { 0 }; ++ int k, y, x; ++ int shift = 3; // BIT_DEPTH - 5 +++ int cwidth = 0; ++ ++ stride_src /= sizeof(pixel); ++ stride_dst /= sizeof(pixel); ++@@ -183,7 +184,10 @@ static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_ ++ for (k = 0; k < 4; k++) ++ offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; ++ ++- switch(width){ +++ if (height % 8 == 0) +++ cwidth = width; +++ +++ switch(cwidth){ ++ case 8: ++ ff_hevc_sao_band_w8_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); ++ break; ++@@ -223,15 +227,19 @@ static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t ++ pixel *src = (pixel *)_src; ++ int a_stride, b_stride; ++ int x, y; +++ int cwidth = 0; ++ ++ for (x = 0; x < 5; x++) { ++ sao_offset_val[x] = _sao_offset_val[edge_idx[x]]; ++ } ++ +++ if (height % 8 == 0) +++ cwidth = width; +++ ++ stride_src /= sizeof(pixel); ++ stride_dst /= sizeof(pixel); ++ ++- switch (width) { +++ switch (cwidth) { ++ case 32: ++ switch(eo) { ++ case 0: ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 710b32b..08f50b8 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -26,36 +26,59 @@ ++ pld [r1] ++ vld1.8 {q0, q1}, [r12] // offset table ++ ldr r12, [sp, #4] // height ++- vmov.u8 q14, #128 +++ vmov.u8 q3, #128 ++ .endm ++ ++-.macro sao_band_32 ++- vshr.u8 q8, q2, #3 ++- vshr.u8 q9, q3, #3 ++- vtbl.8 d16, {q0, q1}, d16 ++- vtbl.8 d17, {q0, q1}, d17 ++- vtbl.8 d18, {q0, q1}, d18 ++- vtbl.8 d19, {q0, q1}, d19 ++- vadd.s8 q2, q14 ++- vadd.s8 q3, q14 ++- vqadd.s8 q2, q8 ++- vqadd.s8 q3, q9 ++- vsub.s8 q2, q14 ++- vsub.s8 q3, q14 +++// 128 in q3 +++// input q8 - q11 +++// 32 cycles +++.macro sao_band_64 +++ vshr.u8 q12, q8, #3 +++ vshr.u8 q13, q9, #3 +++ vshr.u8 q14, q10, #3 +++ vshr.u8 q15, q11, #3 +++ vtbl.8 d24, {d0, d1, d2, d3}, d24 +++ vadd.s8 q8, q3 +++ vtbl.8 d25, {d0, d1, d2, d3}, d25 +++ vadd.s8 q9, q3 +++ vtbl.8 d26, {d0, d1, d2, d3}, d26 +++ vadd.s8 q10, q3 +++ vtbl.8 d27, {d0, d1, d2, d3}, d27 +++ vadd.s8 q11, q3 +++ vtbl.8 d28, {d0, d1, d2, d3}, d28 +++ vqadd.s8 q8, q12 +++ vtbl.8 d29, {d0, d1, d2, d3}, d29 +++ vqadd.s8 q9, q13 +++ vtbl.8 d30, {d0, d1, d2, d3}, d30 +++ vqadd.s8 q10, q14 +++ vtbl.8 d31, {d0, d1, d2, d3}, d31 +++ vqadd.s8 q11, q15 +++ vsub.s8 q8, q3 +++ vsub.s8 q9, q3 +++ vsub.s8 q10, q3 +++ vsub.s8 q11, q3 ++ .endm ++ ++ function ff_hevc_sao_band_w8_neon_8, export=1 ++ init_sao_band ++-1: subs r12, #4 ++- vld1.8 {d4}, [r1, :64], r3 ++- vld1.8 {d5}, [r1, :64], r3 ++- vld1.8 {d6}, [r1, :64], r3 ++- vld1.8 {d7}, [r1, :64], r3 ++- sao_band_32 ++- vst1.8 {d4}, [r0, :64], r2 ++- vst1.8 {d5}, [r0, :64], r2 ++- vst1.8 {d6}, [r0, :64], r2 ++- vst1.8 {d7}, [r0, :64], r2 +++1: subs r12, #8 +++ vld1.8 {d16}, [r1, :64], r3 +++ vld1.8 {d17}, [r1, :64], r3 +++ vld1.8 {d18}, [r1, :64], r3 +++ vld1.8 {d19}, [r1, :64], r3 +++ vld1.8 {d20}, [r1, :64], r3 +++ vld1.8 {d21}, [r1, :64], r3 +++ vld1.8 {d22}, [r1, :64], r3 +++ vld1.8 {d23}, [r1, :64], r3 +++ sao_band_64 +++ vst1.8 {d16}, [r0, :64], r2 +++ vst1.8 {d17}, [r0, :64], r2 +++ vst1.8 {d18}, [r0, :64], r2 +++ vst1.8 {d19}, [r0, :64], r2 +++ vst1.8 {d20}, [r0, :64], r2 +++ vst1.8 {d21}, [r0, :64], r2 +++ vst1.8 {d22}, [r0, :64], r2 +++ vst1.8 {d23}, [r0, :64], r2 ++ bne 1b ++ ++ bx lr ++@@ -63,12 +86,16 @@ endfunc ++ ++ function ff_hevc_sao_band_w16_neon_8, export=1 ++ init_sao_band ++-1: subs r12, #2 ++- vld1.8 {q2}, [r1, :128], r3 ++- vld1.8 {q3}, [r1, :128], r3 ++- sao_band_32 ++- vst1.8 {q2}, [r0, :128], r2 ++- vst1.8 {q3}, [r0, :128], r2 +++1: subs r12, #4 +++ vld1.8 {q8}, [r1, :128], r3 +++ vld1.8 {q9}, [r1, :128], r3 +++ vld1.8 {q10}, [r1, :128], r3 +++ vld1.8 {q11}, [r1, :128], r3 +++ sao_band_64 +++ vst1.8 {q8}, [r0, :128], r2 +++ vst1.8 {q9}, [r0, :128], r2 +++ vst1.8 {q10}, [r0, :128], r2 +++ vst1.8 {q11}, [r0, :128], r2 ++ bne 1b ++ ++ bx lr ++@@ -76,10 +103,12 @@ endfunc ++ ++ function ff_hevc_sao_band_w32_neon_8, export=1 ++ init_sao_band ++-1: subs r12, #1 ++- vld1.8 {q2-q3}, [r1, :128], r3 ++- sao_band_32 ++- vst1.8 {q2-q3}, [r0, :128], r2 +++1: subs r12, #2 +++ vld1.8 {q8-q9}, [r1, :128], r3 +++ vld1.8 {q10-q11}, [r1, :128], r3 +++ sao_band_64 +++ vst1.8 {q8-q9}, [r0, :128], r2 +++ vst1.8 {q10-q11}, [r0, :128], r2 ++ bne 1b ++ ++ bx lr ++@@ -89,13 +118,12 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #1 ++ pld [r1, r3] ++- vld1.8 {q2-q3}, [r1, :128]! ++- sao_band_32 ++- vst1.8 {q2-q3}, [r0, :128]! ++- vld1.8 {q2-q3}, [r1, :128], r3 +++ vld1.8 {q8-q9}, [r1, :128]! +++ vld1.8 {q10-q11}, [r1, :128], r3 ++ sub r1, #32 ++- sao_band_32 ++- vst1.8 {q2-q3}, [r0, :128], r2 +++ sao_band_64 +++ vst1.8 {q8-q9}, [r0, :128]! +++ vst1.8 {q10-q11}, [r0, :128], r2 ++ sub r0, #32 ++ bne 1b ++ ++@@ -121,7 +149,6 @@ endfunc ++ vcgt.u8 q1, q5, q9 ++ vcgt.u8 q15, q9, q5 ++ vsub.s8 q0, q14, q0 // diff1 ++- ++ vsub.s8 q1, q15, q1 ++ ++ vadd.s8 q0, q12 //diff0 + diff1 ++@@ -157,27 +184,25 @@ endfunc ++ ++ vmov.u8 q15, #128 // s8 #-128 ++ vtbl.8 d0, {d24}, d0 +++ vadd.s8 q13, q4, q15 ++ vtbl.8 d1, {d24}, d1 +++ vadd.s8 q14, q5, q15 ++ vtbl.8 d2, {d24}, d2 +++ vqadd.s8 q0, q13 ++ vtbl.8 d3, {d24}, d3 +++ vqadd.s8 q1, q14 ++ vtbl.8 d4, {d24}, d4 +++ vadd.s8 q13, q6, q15 ++ vtbl.8 d5, {d24}, d5 +++ vadd.s8 q14, q7, q15 ++ vtbl.8 d6, {d24}, d6 +++ vqadd.s8 q2, q13 ++ vtbl.8 d7, {d24}, d7 ++- ++- vadd.s8 q12, q4, q15 ++- vadd.s8 q13, q5, q15 ++- vadd.s8 q14, q6, q15 ++- vadd.s8 q15, q7, q15 ++- vqadd.s8 q12, q0 ++- vqadd.s8 q15, q3 ++- vmov.u8 q3, #128 // s8 #-128 ++- vqadd.s8 q13, q1 ++- vqadd.s8 q14, q2 ++- vsub.s8 q0, q12, q3 ++- vsub.s8 q1, q13, q3 ++- vsub.s8 q2, q14, q3 ++- vsub.s8 q3, q15, q3 +++ vqadd.s8 q3, q14 +++ vsub.s8 q0, q15 +++ vsub.s8 q1, q15 +++ vsub.s8 q2, q15 +++ vsub.s8 q3, q15 ++ vst1.8 {q0-q1}, [r0, :128]! ++ vst1.8 {q2-q3}, [r0, :128], r2 ++ sub r0, #32 ++@@ -342,13 +367,12 @@ endfunc ++ ++ vmov.u8 q10, #128 ++ vtbl.8 d0, {d31}, d0 +++ vadd.s8 q11, q2, q10 ++ vtbl.8 d1, {d31}, d1 +++ vadd.s8 q12, q3, q10 ++ vtbl.8 d2, {d31}, d2 +++ vqadd.s8 q11, q0 ++ vtbl.8 d3, {d31}, d3 ++- ++- vadd.s8 q11, q2, q10 ++- vadd.s8 q12, q3, q10 ++- vqadd.s8 q11, q0 ++ vqadd.s8 q12, q1 ++ vsub.s8 q0, q11, q10 ++ vsub.s8 q1, q12, q10 ++-- ++2.5.0 ++ ++ ++From 026bac1824e4936e948e6b1efec82868c520ea66 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Mon, 2 Feb 2015 16:08:27 +0200 ++Subject: [PATCH 9/9] Further SAO NEON optimisations ++ ++--- ++ libavcodec/arm/hevcdsp_init_neon.c | 16 +-- ++ libavcodec/arm/hevcdsp_sao_neon.S | 224 +++++++++++++++++++------------------ ++ 2 files changed, 124 insertions(+), 116 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 6d0689c..e5da7e9 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -45,10 +45,10 @@ void ff_hevc_transform_add_16x16_neon_8(uint8_t *_dst, int16_t *coeffs, ++ void ff_hevc_transform_add_32x32_neon_8(uint8_t *_dst, int16_t *coeffs, ++ ptrdiff_t stride); ++ ++-void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); ++-void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); ++-void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); ++-void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int8_t * offset_table, int height); +++void ff_hevc_sao_band_w8_neon_8(uint8_t *_dst, uint8_t *_src, int8_t * offset_table, ptrdiff_t stride_src, ptrdiff_t stride_dst, int height); +++void ff_hevc_sao_band_w16_neon_8(uint8_t *_dst, uint8_t *_src, int8_t * offset_table, ptrdiff_t stride_src, ptrdiff_t stride_dst, int height); +++void ff_hevc_sao_band_w32_neon_8(uint8_t *_dst, uint8_t *_src, int8_t * offset_table, ptrdiff_t stride_src, ptrdiff_t stride_dst, int height); +++void ff_hevc_sao_band_w64_neon_8(uint8_t *_dst, uint8_t *_src, int8_t * offset_table, ptrdiff_t stride_src, ptrdiff_t stride_dst, int height); ++ ++ void ff_hevc_sao_edge_eo0_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++ void ff_hevc_sao_edge_eo1_w32_neon_8(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int height, int8_t *sao_offset_table); ++@@ -189,16 +189,16 @@ static void ff_hevc_sao_band_neon_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_ ++ ++ switch(cwidth){ ++ case 8: ++- ff_hevc_sao_band_w8_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); +++ ff_hevc_sao_band_w8_neon_8(_dst, _src, offset_table, stride_src, stride_dst, height); ++ break; ++ case 16: ++- ff_hevc_sao_band_w16_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); +++ ff_hevc_sao_band_w16_neon_8(_dst, _src, offset_table, stride_src, stride_dst, height); ++ break; ++ case 32: ++- ff_hevc_sao_band_w32_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); +++ ff_hevc_sao_band_w32_neon_8(_dst, _src, offset_table, stride_src, stride_dst, height); ++ break; ++ case 64: ++- ff_hevc_sao_band_w64_neon_8(_dst, _src, stride_dst, stride_src, offset_table, height); +++ ff_hevc_sao_band_w64_neon_8(_dst, _src, offset_table, stride_src, stride_dst, height); ++ break; ++ default: ++ for (y = 0; y < height; y++) { ++diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S ++index 08f50b8..9c7808d 100644 ++--- a/libavcodec/arm/hevcdsp_sao_neon.S +++++ b/libavcodec/arm/hevcdsp_sao_neon.S ++@@ -22,21 +22,16 @@ ++ #include "neon.S" ++ ++ .macro init_sao_band ++- ldr r12, [sp, #0] // offset_table address ++ pld [r1] ++- vld1.8 {q0, q1}, [r12] // offset table ++- ldr r12, [sp, #4] // height +++ vld1.8 {q0, q1}, [r2] // offset table +++ ldr r2, [sp, #0] // stride_dst +++ ldr r12, [sp, #4] // height ++ vmov.u8 q3, #128 ++ .endm ++ ++ // 128 in q3 ++ // input q8 - q11 ++-// 32 cycles ++ .macro sao_band_64 ++- vshr.u8 q12, q8, #3 ++- vshr.u8 q13, q9, #3 ++- vshr.u8 q14, q10, #3 ++- vshr.u8 q15, q11, #3 ++ vtbl.8 d24, {d0, d1, d2, d3}, d24 ++ vadd.s8 q8, q3 ++ vtbl.8 d25, {d0, d1, d2, d3}, d25 ++@@ -52,8 +47,8 @@ ++ vtbl.8 d30, {d0, d1, d2, d3}, d30 ++ vqadd.s8 q10, q14 ++ vtbl.8 d31, {d0, d1, d2, d3}, d31 ++- vqadd.s8 q11, q15 ++ vsub.s8 q8, q3 +++ vqadd.s8 q11, q15 ++ vsub.s8 q9, q3 ++ vsub.s8 q10, q3 ++ vsub.s8 q11, q3 ++@@ -64,12 +59,16 @@ function ff_hevc_sao_band_w8_neon_8, export=1 ++ 1: subs r12, #8 ++ vld1.8 {d16}, [r1, :64], r3 ++ vld1.8 {d17}, [r1, :64], r3 +++ vshr.u8 q12, q8, #3 ++ vld1.8 {d18}, [r1, :64], r3 ++ vld1.8 {d19}, [r1, :64], r3 +++ vshr.u8 q13, q9, #3 ++ vld1.8 {d20}, [r1, :64], r3 ++ vld1.8 {d21}, [r1, :64], r3 +++ vshr.u8 q14, q10, #3 ++ vld1.8 {d22}, [r1, :64], r3 ++ vld1.8 {d23}, [r1, :64], r3 +++ vshr.u8 q15, q11, #3 ++ sao_band_64 ++ vst1.8 {d16}, [r0, :64], r2 ++ vst1.8 {d17}, [r0, :64], r2 ++@@ -88,9 +87,13 @@ function ff_hevc_sao_band_w16_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #4 ++ vld1.8 {q8}, [r1, :128], r3 +++ vshr.u8 q12, q8, #3 ++ vld1.8 {q9}, [r1, :128], r3 +++ vshr.u8 q13, q9, #3 ++ vld1.8 {q10}, [r1, :128], r3 +++ vshr.u8 q14, q10, #3 ++ vld1.8 {q11}, [r1, :128], r3 +++ vshr.u8 q15, q11, #3 ++ sao_band_64 ++ vst1.8 {q8}, [r0, :128], r2 ++ vst1.8 {q9}, [r0, :128], r2 ++@@ -105,7 +108,11 @@ function ff_hevc_sao_band_w32_neon_8, export=1 ++ init_sao_band ++ 1: subs r12, #2 ++ vld1.8 {q8-q9}, [r1, :128], r3 +++ vshr.u8 q12, q8, #3 +++ vshr.u8 q13, q9, #3 ++ vld1.8 {q10-q11}, [r1, :128], r3 +++ vshr.u8 q14, q10, #3 +++ vshr.u8 q15, q11, #3 ++ sao_band_64 ++ vst1.8 {q8-q9}, [r0, :128], r2 ++ vst1.8 {q10-q11}, [r0, :128], r2 ++@@ -119,7 +126,11 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ 1: subs r12, #1 ++ pld [r1, r3] ++ vld1.8 {q8-q9}, [r1, :128]! +++ vshr.u8 q12, q8, #3 +++ vshr.u8 q13, q9, #3 ++ vld1.8 {q10-q11}, [r1, :128], r3 +++ vshr.u8 q14, q10, #3 +++ vshr.u8 q15, q11, #3 ++ sub r1, #32 ++ sao_band_64 ++ vst1.8 {q8-q9}, [r0, :128]! ++@@ -129,51 +140,18 @@ function ff_hevc_sao_band_w64_neon_8, export=1 ++ ++ bx lr ++ endfunc ++-// input ++-// a in q0 - q3 ++-// c in q4 - q7 ++-// b in q8 - q11 ++-// offset table in r7 and r5 ++-// output in q0 - q3 ++-// clobbers q12 - q15 ++-.macro edge_w64_body ++- vcgt.u8 q12, q4, q0 // c > a -> -1 , otherwise 0 ++- vcgt.u8 q0, q0, q4 // a > c -> -1 , otherwise 0 ++- vcgt.u8 q13, q5, q1 ++- vcgt.u8 q1, q1, q5 ++- vsub.s8 q12, q0, q12 // diff0 ++- vcgt.u8 q0, q4, q8 // c > b ++- vsub.s8 q13, q1, q13 ++- ++- vcgt.u8 q14, q8, q4 // b > c ++- vcgt.u8 q1, q5, q9 ++- vcgt.u8 q15, q9, q5 ++- vsub.s8 q0, q14, q0 // diff1 ++- vsub.s8 q1, q15, q1 ++ ++- vadd.s8 q0, q12 //diff0 + diff1 ++- vadd.s8 q1, q13 ++- ++- vcgt.u8 q14, q6, q2 ++- vcgt.u8 q2, q2, q6 ++- vcgt.u8 q15, q7, q3 ++- vcgt.u8 q3, q3, q7 ++- ++- vsub.s8 q14, q2, q14 ++- vcgt.u8 q2, q6, q10 ++- vsub.s8 q15, q3, q15 ++- ++- vcgt.u8 q12, q10, q6 ++- vcgt.u8 q3, q7, q11 ++- vcgt.u8 q13, q11, q7 ++- vsub.s8 q2, q12, q2 ++- vsub.s8 q3, q13, q3 +++.macro diff32 out0, out1, tmp0, tmp1, in0, in1, in2, in3 +++ vcgt.u8 \out0, \in2, \in0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 \tmp0, \in0, \in2 // a > c -> -1 , otherwise 0 +++ vcgt.u8 \out1, \in3, \in1 // c > a -> -1 , otherwise 0 part 2 +++ vcgt.u8 \tmp1, \in1, \in3 // a > c -> -1 , otherwise 0 part 2 +++ vsub.s8 \out0, \tmp0, \out0 // diff0 +++ vsub.s8 \out1, \tmp1, \out1 // diff0 part 2 +++.endm ++ +++.macro table64 ++ vmov.s8 q13, #2 // 2 to all elements ++- ++- vadd.s8 q2, q14 ++- vadd.s8 q3, q15 ++- ++ vmov.32 d24[0], r4 // load offset table from general registers ++ vmov.32 d24[1], r5 // load rest of offset table ++ ++@@ -208,6 +186,28 @@ endfunc ++ sub r0, #32 ++ .endm ++ +++// input +++// a in q0 - q3 +++// c in q4 - q7 +++// b in q8 - q11 +++// offset table in r7 and r5 +++// output in q0 - q3 +++// clobbers q12 - q15 +++.macro edge_w64_body +++ diff32 q12, q13, q0, q1, q0, q1, q4, q5 +++ diff32 q0, q1, q14, q15, q8, q9, q4, q5 +++ +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 +++ +++ diff32 q14, q15, q2, q3, q2, q3, q6, q7 +++ diff32 q2, q3, q12, q13, q10, q11, q6, q7 +++ +++ vadd.s8 q2, q14 +++ vadd.s8 q3, q15 +++ table64 +++.endm +++ ++ .macro init_edge_64 ++ push {r4-r5} ++ ldr r12, [sp, #8] // height ++@@ -334,38 +334,23 @@ function ff_hevc_sao_edge_eo3_w64_neon_8, export=1 ++ bx lr ++ endfunc ++ ++-// inputs: ++-// a in q0, q1 ++-// c in q2, q3 ++-// b in q8, q9 ++-// offset table in d31 ++-// clobbered registers q0, q1, q10, q11, q12, q13 ++-// output q0, q1 ++-.macro edge_w32_body ++- vcgt.u8 q12, q2, q0 // c > a -> -1 , otherwise 0 ++- vcgt.u8 q0, q0, q2 // a > c -> -1 , otherwise 0 ++- vcgt.u8 q13, q3, q1 ++- vcgt.u8 q1, q1, q3 ++- ++- vsub.s8 q12, q0, q12 // diff0 ++- vcgt.u8 q0, q2, q8 // c > b ++- vsub.s8 q13, q1, q13 // diff0 part 2 ++- ++- vcgt.u8 q10, q8, q2 // b > c ++- vcgt.u8 q1, q3, q9 ++- vcgt.u8 q11, q9, q3 ++- ++- vsub.s8 q0, q10, q0 // diff1 ++- ++- vmov.s8 q10, #2 // 2 to all elements ++- vsub.s8 q1, q11, q1 // diff1 part 2 ++- vadd.s8 q0, q12 //diff0 + diff1 ++- vadd.s8 q1, q13 +++.macro init_edge_32 +++ ldr r12, [sp, #4] // sao_offset_val_table +++ vld1.32 {d31}, [r12] +++ ldr r12, [sp] // height +++.endm ++ ++- vadd.s8 q0, q10 ++- vadd.s8 q1, q10 +++.macro diff out0, tmp0, in0, in1 +++ vcgt.u8 \out0, \in1, \in0 // c > a -> -1 , otherwise 0 +++ vcgt.u8 \tmp0, \in0, \in1 // a > c -> -1 , otherwise 0 +++ vsub.s8 \out0, \tmp0, \out0 // diff0 +++.endm ++ ++- vmov.u8 q10, #128 +++.macro table32 +++ vmov.s8 q10, #2 +++ vadd.s8 q0, q10 +++ vadd.s8 q1, q10 +++ vmov.s8 q10, #128 ++ vtbl.8 d0, {d31}, d0 ++ vadd.s8 q11, q2, q10 ++ vtbl.8 d1, {d31}, d1 ++@@ -373,56 +358,68 @@ endfunc ++ vtbl.8 d2, {d31}, d2 ++ vqadd.s8 q11, q0 ++ vtbl.8 d3, {d31}, d3 ++- vqadd.s8 q12, q1 ++- vsub.s8 q0, q11, q10 ++- vsub.s8 q1, q12, q10 +++ vqadd.s8 q12, q1 +++ vsub.s8 q0, q11, q10 +++ vsub.s8 q1, q12, q10 ++ vst1.8 {q0-q1}, [r0, :128], r2 ++ .endm ++ ++-.macro init_edge_32 ++- ldr r12, [sp, #4] // sao_offset_val_table ++- vld1.32 {d31}, [r12] ++- ldr r12, [sp] // height ++-.endm ++- ++ function ff_hevc_sao_edge_eo0_w32_neon_8, export=1 ++ init_edge_32 ++- sub r1, #4 // load 4 extra bytes +++ vpush {q4-q7} +++ sub r1, #4 ++ 1: subs r12, #1 ++- vld1.32 d3[1], [r1]! ++- vld1.8 {q2-q3}, [r1, :128]! // c ++- vld1.32 d20[0], [r1], r3 ++- sub r1, #36 +++ vld1.8 {q13-q14}, [r1]! +++ vld1.32 d30, [r1], r3 +++ sub r1, #32 ++ // a ++- vext.8 q0, q1, q2, #15 ++- vext.8 q1, q2, q3, #15 ++- // b ++- vext.8 q8, q2, q3, #1 ++- vext.8 q9, q3, q10, #1 ++- edge_w32_body +++ vext.8 q0, q13, q14, #3 +++ vext.8 q1, q14, q15, #3 +++ vshr.u64 d24, d30, #24 +++ // c +++ vext.8 q2, q13, q14, #4 +++ vext.8 q3, q14, q15, #4 +++ vshr.u64 d16, d30, #32 +++ // diff0 +++ diff32 q13, q14, q4, q5, q0, q1, q2, q3 +++ diff d18, d25, d24, d16 +++ // -diff1 +++ vext.s8 q0, q13, q14, #1 +++ vext.s8 q1, q14, q9, #1 +++ +++ vsub.s8 q0, q13, q0 //diff0 + diff1 +++ vsub.s8 q1, q14, q1 +++ table32 ++ bne 1b +++ vpop {q4-q7} +++ ++ bx lr ++ endfunc ++ ++ function ff_hevc_sao_edge_eo1_w32_neon_8, export=1 ++ init_edge_32 +++ vpush {q4-q7} ++ // load a ++ sub r1, r3 ++ vld1.8 {q0-q1}, [r1, :128], r3 ++ // load c ++ vld1.8 {q2-q3}, [r1, :128], r3 +++ diff32 q12, q13, q0, q1, q0, q1, q2, q3 // CMP ( c, a ) ++ 1: subs r12, #1 ++ // load b ++ vld1.8 {q8-q9}, [r1, :128], r3 ++- edge_w32_body ++- // inputs for next loop iteration ++- // a ++- vmov.64 q0, q2 ++- vmov.64 q1, q3 +++ diff32 q4, q5, q10, q11, q8, q9, q2, q3 // CMP ( c, b ) +++ vadd.s8 q0, q4, q12 //diff0 + diff1 +++ vadd.s8 q1, q5, q13 +++ table32 +++ // CMP ( c, a ) +++ vneg.s8 q12, q4 +++ vneg.s8 q13, q5 ++ // c ++ vmov.64 q2, q8 ++ vmov.64 q3, q9 ++ bne 1b +++ vpop {q4-q7} ++ bx lr ++ endfunc ++ ++@@ -452,7 +449,11 @@ function ff_hevc_sao_edge_eo2_w32_neon_8, export=1 ++ vext.8 q6, q10, q11, #8 ++ vext.8 q7, q11, q12, #8 ++ vext.8 q5, q10, q11, #7 ++- edge_w32_body +++ diff32 q12, q13, q0, q1, q0, q1, q2, q3 +++ diff32 q0, q1, q10, q11, q8, q9, q2, q3 +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 +++ table32 ++ // inputs for next loop iteration ++ // a ++ vmov.8 q0, q4 ++@@ -487,7 +488,14 @@ function ff_hevc_sao_edge_eo3_w32_neon_8, export=1 ++ vext.8 q8, q10, q11, #7 ++ vext.8 q9, q11, q12, #7 ++ vext.8 q14, q12, q10, #7 ++- edge_w32_body +++ +++ diff32 q12, q13, q0, q1, q0, q1, q2, q3 +++ diff32 q0, q1, q10, q11, q8, q9, q2, q3 +++ +++ vadd.s8 q0, q12 //diff0 + diff1 +++ vadd.s8 q1, q13 +++ table32 +++ ++ // inputs for next loop iteration ++ // a ++ vext.8 q0, q2, q3, #1 ++-- ++2.5.0 ++ +diff --git a/tools/depends/target/ffmpeg/autobuild.sh b/tools/depends/target/ffmpeg/autobuild.sh +index 6bbebfc..7ef281d 100755 +--- a/tools/depends/target/ffmpeg/autobuild.sh ++++ b/tools/depends/target/ffmpeg/autobuild.sh +@@ -72,6 +72,7 @@ do + ;; + --arch=*) + FLAGS="$FLAGS --arch=${1#*=}" ++ ARCH=${1#*=} + shift + ;; + --extra-cflags=*) +@@ -100,6 +101,9 @@ do + esac + done + ++[ -n ${ARCH} ] || ARCH=$(dpkg-architecture -qDEB_BUILD_GNU_CPU) ++[ ${ARCH} = $(dpkg-architecture -qDEB_BUILD_GNU_CPU) ] || FLAGS="$FLAGS --enable-cross-compile" ++ + BUILDTHREADS=${BUILDTHREADS:-$(grep -c "^processor" /proc/cpuinfo)} + [ ${BUILDTHREADS} -eq 0 ] && BUILDTHREADS=1 + +@@ -107,9 +111,12 @@ BUILDTHREADS=${BUILDTHREADS:-$(grep -c "^processor" /proc/cpuinfo)} + if [ -f ${FFMPEG_PREFIX}/lib/pkgconfig/libavcodec.pc ] && [ -f .ffmpeg-installed ] + then + CURVER=$(cat .ffmpeg-installed) +- [ "$VERSION" == "$CURVER" ] && exit 0 ++ [ "$VERSION" == "$CURVER" ] && exit 0 || rm -fr .ffmpeg-installed + fi + ++CFLAG="$CFLAGS" CPPFLAGS="$CFLAGS" ARCH=$ARCH CXXFLAGS="$CXXFLAGS" LDFLAGS="$LDFLAGS" PLATFORM=ffmpeg-${VERSION} CONFFLAGS=${FLAGS} PREFIX=${FFMPEG_PREFIX} make -j ${BUILDTHREADS} ++exit $? ++ + [ -f ${ARCHIVE} ] || + curl -Ls --create-dirs -f -o ${ARCHIVE} ${BASE_URL}/${VERSION}.tar.gz || + { echo "error fetching ${BASE_URL}/${VERSION}.tar.gz" ; exit 3; } +@@ -156,7 +163,6 @@ CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS" LDFLAGS="$LDFLAGS" \ + --enable-encoder=mjpeg \ + --enable-nonfree \ + --enable-pthreads \ +- --enable-pic \ + --enable-zlib \ + --disable-mipsdsp \ + --disable-mipsdspr2 \ +diff --git a/tools/depends/target/ffmpeg/h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch b/tools/depends/target/ffmpeg/h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch +new file mode 100644 +index 0000000..648f64f +--- /dev/null ++++ b/tools/depends/target/ffmpeg/h264_parser_fix_parsing_of_mvc_slices_in_some_corner_cases.patch +@@ -0,0 +1,66 @@ ++From fd627f6435db524f3e1fd8df6f64a17dcda5c8b9 Mon Sep 17 00:00:00 2001 ++From: Hendrik Leppkes ++Date: Fri, 26 Feb 2016 00:23:53 +0100 ++Subject: [PATCH] h264_parser: fix parsing of mvc slices in some corner cases ++ ++--- ++ libavcodec/h264.h | 2 +- ++ libavcodec/h264_parser.c | 10 +++++----- ++ 2 files changed, 6 insertions(+), 6 deletions(-) ++ ++diff --git a/libavcodec/h264.h b/libavcodec/h264.h ++index 9e1d377..846e4dc 100644 ++--- a/libavcodec/h264.h +++++ b/libavcodec/h264.h ++@@ -828,7 +828,7 @@ typedef struct H264Context { ++ int cur_bit_depth_luma; ++ int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low ++ ++- uint8_t parse_history[6]; +++ uint8_t parse_history[9]; ++ int parse_history_count; ++ int parse_last_mb; ++ ++diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c ++index 4337c8c..2fd3f2b 100644 ++--- a/libavcodec/h264_parser.c +++++ b/libavcodec/h264_parser.c ++@@ -39,6 +39,7 @@ typedef struct H264ParseContext { ++ ParseContext pc; ++ int got_first; ++ int is_mvc; +++ int slice_ext; ++ } H264ParseContext; ++ ++ ++@@ -97,18 +98,17 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, ++ nalu_type == NAL_IDR_SLICE || (p->is_mvc && nalu_type == NAL_SLICE_EXT)) { ++ state += 8; ++ ++- if (nalu_type == NAL_SLICE_EXT) ++- i += 3; // skip mvc extension +++ p->slice_ext = (nalu_type == NAL_SLICE_EXT); ++ continue; ++ } ++ state = 7; ++ } else { ++ h->parse_history[h->parse_history_count++]= buf[i]; ++- if (h->parse_history_count>5) { +++ if (h->parse_history_count>8) { ++ unsigned int mb, last_mb= h->parse_last_mb; ++ GetBitContext gb; ++ ++- init_get_bits(&gb, h->parse_history, 8*h->parse_history_count); +++ init_get_bits8(&gb, h->parse_history + 3*p->slice_ext, h->parse_history_count - 3*p->slice_ext); ++ h->parse_history_count=0; ++ mb= get_ue_golomb_long(&gb); ++ h->parse_last_mb= mb; ++@@ -131,7 +131,7 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, ++ pc->frame_start_found = 0; ++ if (h->is_avc) ++ return next_avc; ++- return i - (state & 5) - 5 * (state > 7); +++ return i - (state & 5) - 8 * (state > 7); ++ } ++ ++ static int scan_mmco_reset(AVCodecParserContext *s) +diff --git a/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +new file mode 100644 +index 0000000..5e8e07d +--- /dev/null ++++ b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +@@ -0,0 +1,409 @@ ++From 29c3327a0d72a7e872ff170363cfe5ed13bca5d0 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Tue, 22 Dec 2015 18:10:24 +0000 ++Subject: [PATCH] hevcdsp: ARM NEON optimized epel functions ++ ++--- ++ libavcodec/arm/Makefile | 1 + ++ libavcodec/arm/hevcdsp_epel_neon.S | 334 +++++++++++++++++++++++++++++++++++++ ++ libavcodec/arm/hevcdsp_init_neon.c | 23 +++ ++ 3 files changed, 358 insertions(+) ++ create mode 100644 libavcodec/arm/hevcdsp_epel_neon.S ++ ++diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile ++index cdd35b0..6051ec8 100644 ++--- a/libavcodec/arm/Makefile +++++ b/libavcodec/arm/Makefile ++@@ -131,6 +131,7 @@ NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ ++ arm/synth_filter_neon.o ++ NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ ++ arm/hevcdsp_deblock_neon.o \ +++ arm/hevcdsp_epel_neon.o \ ++ arm/hevcdsp_idct_neon.o \ ++ arm/hevcdsp_qpel_neon.o ++ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o ++diff --git a/libavcodec/arm/hevcdsp_epel_neon.S b/libavcodec/arm/hevcdsp_epel_neon.S ++new file mode 100644 ++index 0000000..516ae5b ++--- /dev/null +++++ b/libavcodec/arm/hevcdsp_epel_neon.S ++@@ -0,0 +1,334 @@ +++/* +++ * Copyright (c) 2014 - 2015 Seppo Tomperi +++ * +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++#include "libavutil/arm/asm.S" +++#include "neon.S" +++ +++#define MAX_PB_SIZE #64 +++ +++.macro vextin_d4 +++ vld1.8 {q10}, [r1], r2 +++ vmov d16, d20 +++ vext.8 d17, d20, d21, #1 +++ vext.8 d18, d20, d21, #2 +++ vext.8 d19, d20, d21, #3 +++.endm +++ +++.macro vextin_d4_8 +++ vld1.8 d16, [r1], r2 +++ vext.8 d17, d16, d16, #1 +++ vext.8 d18, d16, d16, #2 +++ vext.8 d19, d16, d16, #3 +++.endm +++ +++.macro load_coeffs_16b coeffs +++ ldr \coeffs, [\coeffs] +++ vdup.i8 d0, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d1, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d2, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d3, \coeffs +++.endm +++ +++.macro epel_filter_16b out=q12 +++ vmull.u8 q3, d16, d0 +++ vmull.u8 q11, d19, d3 +++ vmull.u8 \out, d17, d1 +++ vmull.u8 q10, d18, d2 +++ vadd.s16 q3, q11 +++ vadd.s16 \out, q10 +++ vsub.s16 \out, q3 +++.endm +++ +++.macro load_coeffs_32b coeffs +++ ldr \coeffs, [\coeffs] +++ vmov.i64 d4, #0 +++ vmov.8 d4[0], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[2], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[4], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[6], \coeffs +++.endm +++ +++.macro epel_filter_32b +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q4, d25, d4[0] +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q6, d31, d4[3] +++ +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q8, d27, d4[1] +++ vmull.s16 q9, d28, d4[2] // q14 +++ vmull.s16 q10, d29, d4[2] +++ vadd.s32 q3, q5 +++ vadd.s32 q4, q6 +++ vadd.s32 q7, q9 +++ vadd.s32 q8, q10 +++ vsub.s32 q7, q3 +++ vsub.s32 q8, q4 +++ vqshrn.s32 d6, q7, #6 +++ vqshrn.s32 d7, q8, #6 +++.endm +++ +++.macro epel_filter_32b_4 +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q9, d28, d4[2] // q14 +++ vadd.s32 q3, q5 +++ vadd.s32 q7, q9 +++ vsub.s32 q7, q3 +++ vqshrn.s32 d6, q7, #6 +++.endm +++ +++function ff_hevc_put_epel_h_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #16] // mx +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ sub r1, #1 +++ lsl r4, #1 +++ load_coeffs_16b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: subs r3, #1 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ cmp r5, #4 +++ bgt 8b +++4: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++2: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_v_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ load_coeffs_16b r7 +++ sub r1, r2 +++ lsl r4, #1 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vld1.8 {d16}, [r1], r2 +++ pld [r1] +++ vld1.8 {d17}, [r1], r2 +++ pld [r1] +++ vld1.8 {d18}, [r1], r2 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_hv_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r6, [sp, #16] // mx +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ sub r6, #1 +++ lsl r6, #2 +++ add r6, r12 // mx epel coeff offset +++ add r7, r12 +++ sub r1, #1 +++ sub r1, r2 +++ lsl r4, #1 +++ load_coeffs_16b r6 +++ load_coeffs_32b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vextin_d4 +++ epel_filter_16b q12 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q13 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q14 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vextin_d4 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b +++ vst1.16 {q3}, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.16 d6, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.32 d6[0], [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++epel_coeffs: +++ .byte 2, 58, 10, 2 +++ .byte 4, 54, 16, 2 +++ .byte 6, 46, 28, 4 +++ .byte 4, 36, 36, 4 +++ .byte 4, 28, 46, 6 +++ .byte 2, 16, 54, 4 +++ .byte 2, 10, 58, 2 ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 5591807..733ff08 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -58,6 +58,15 @@ PUT_PIXELS(ff_hevc_put_pixels_w32_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w48_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w64_neon_8); ++ #undef PUT_PIXELS +++void ff_hevc_put_epel_h_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_v_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_hv_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); ++ ++ static void (*put_hevc_qpel_neon[4][4])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, ++ int height, int width); ++@@ -201,7 +210,21 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->put_hevc_qpel_bi[x][1][0] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][0][1] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][1][1] = ff_hevc_put_qpel_bi_neon_wrapper; +++ c->put_hevc_epel[x][1][0] = ff_hevc_put_epel_v_neon_8; +++ c->put_hevc_epel[x][0][1] = ff_hevc_put_epel_h_neon_8; +++ c->put_hevc_epel[x][1][1] = ff_hevc_put_epel_hv_neon_8; ++ } +++ c->put_hevc_epel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; +++ c->put_hevc_epel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; +++ c->put_hevc_epel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; +++ c->put_hevc_epel[3][0][0] = ff_hevc_put_pixels_w8_neon_8; +++ c->put_hevc_epel[4][0][0] = ff_hevc_put_pixels_w12_neon_8; +++ c->put_hevc_epel[5][0][0] = ff_hevc_put_pixels_w16_neon_8; +++ c->put_hevc_epel[6][0][0] = ff_hevc_put_pixels_w24_neon_8; +++ c->put_hevc_epel[7][0][0] = ff_hevc_put_pixels_w32_neon_8; +++ c->put_hevc_epel[8][0][0] = ff_hevc_put_pixels_w48_neon_8; +++ c->put_hevc_epel[9][0][0] = ff_hevc_put_pixels_w64_neon_8; +++ ++ c->put_hevc_qpel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; ++ c->put_hevc_qpel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; ++ c->put_hevc_qpel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; ++-- ++2.5.0 ++ +diff --git a/tools/depends/target/ffmpeg/pfcd_hevc_optimisations.patch b/tools/depends/target/ffmpeg/pfcd_hevc_optimisations.patch +new file mode 100644 +index 0000000..bb3be3f +--- /dev/null ++++ b/tools/depends/target/ffmpeg/pfcd_hevc_optimisations.patch +@@ -0,0 +1,38136 @@ ++From 4c05fa1631b5e8839a7763417c5220291308c707 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 28 Apr 2015 16:18:40 +0100 ++Subject: [PATCH 01/68] Added display output ++ ++--- ++ ffmpeg.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 159 insertions(+) ++ ++diff --git a/ffmpeg.c b/ffmpeg.c ++index a5ec3c3..8828f48 100644 ++--- a/ffmpeg.c +++++ b/ffmpeg.c ++@@ -23,6 +23,11 @@ ++ * multimedia converter based on the FFmpeg libraries ++ */ ++ +++#ifdef RPI +++#define RPI_DISPLAY +++//#define RPI_ZERO_COPY +++#endif +++ ++ #include "config.h" ++ #include ++ #include ++@@ -66,6 +71,20 @@ ++ # include "libavfilter/buffersrc.h" ++ # include "libavfilter/buffersink.h" ++ +++#ifdef RPI_DISPLAY +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#ifdef RPI_ZERO_COPY +++#include "libavcodec/rpi_qpu.h" +++#endif +++#endif +++ ++ #if HAVE_SYS_RESOURCE_H ++ #include ++ #include ++@@ -158,6 +177,134 @@ static int restore_tty; ++ static void free_input_threads(void); ++ #endif ++ +++#ifdef RPI_DISPLAY +++ +++#define NUM_BUFFERS 4 +++ +++static MMAL_COMPONENT_T* rpi_display = NULL; +++static MMAL_POOL_T *rpi_pool = NULL; +++ +++#ifdef RPI_ZERO_COPY +++static uint8_t *get_vc_handle(AVBufferRef *bref) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); +++ return (uint8_t *)p->vc_handle; +++} +++#endif +++ +++static MMAL_POOL_T* display_alloc_pool(MMAL_PORT_T* port, size_t w, size_t h) +++{ +++ MMAL_POOL_T* pool; +++ size_t i; +++ size_t size = (w*h*3)/2; +++#ifdef RPI_ZERO_COPY +++ mmal_port_parameter_set_boolean(port, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); // Does this mark that the buffer contains a vc_handle? Would have expected a vc_image? +++ pool = mmal_port_pool_create(port, NUM_BUFFERS, 0); +++ assert(pool); +++#else +++ pool = mmal_port_pool_create(port, NUM_BUFFERS, size); +++ +++ for (i = 0; i < NUM_BUFFERS; ++i) +++ { +++ MMAL_BUFFER_HEADER_T* buffer = pool->header[i]; +++ void* bufPtr = buffer->data; +++ memset(bufPtr, i*30, w*h); +++ memset(bufPtr+w*h, 128, (w*h)/2); +++ } +++#endif +++ +++ return pool; +++} +++ +++static void display_cb_input(MMAL_PORT_T *port,MMAL_BUFFER_HEADER_T *buffer) { +++ mmal_buffer_header_release(buffer); +++} +++ +++static MMAL_COMPONENT_T* display_init(size_t x, size_t y, size_t w, size_t h) +++{ +++ MMAL_COMPONENT_T* display; +++ int w2 = (w+31)&~31; +++ int h2 = (h+15)&~15; +++ MMAL_DISPLAYREGION_T region = +++ { +++ {MMAL_PARAMETER_DISPLAYREGION, sizeof(region)}, +++ .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_FULLSCREEN | MMAL_DISPLAY_SET_DEST_RECT, +++ .layer = 2, +++ .fullscreen = 0, +++ .dest_rect = {x, y, w, h} +++ }; +++ bcm_host_init(); // TODO is this needed? +++ mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &display); +++ assert(display); +++ +++ mmal_port_parameter_set(display->input[0], ®ion.hdr); +++ +++ MMAL_ES_FORMAT_T* format = display->input[0]->format; +++ format->encoding = MMAL_ENCODING_I420; +++ format->es->video.width = w2; +++ format->es->video.height = h2; +++ format->es->video.crop.x = 0; +++ format->es->video.crop.y = 0; +++ format->es->video.crop.width = w; +++ format->es->video.crop.height = h; +++ mmal_port_format_commit(display->input[0]); +++ +++ mmal_component_enable(display); +++ +++ rpi_pool = display_alloc_pool(display->input[0], w2, h2); +++ +++ mmal_port_enable(display->input[0],display_cb_input); +++ mmal_port_enable(display->control,display_cb_input); +++ +++ printf("Allocated display %d %d\n",w,h); +++ +++ return display; +++} +++ +++static void display_frame(MMAL_COMPONENT_T* display,AVFrame* fr) +++{ +++ int w = fr->width; +++ int h = fr->height; +++ int w2 = (w+31)&~31; +++ int h2 = (h+15)&~15; +++ if (!display || !rpi_pool) +++ return; +++ MMAL_BUFFER_HEADER_T* buf = mmal_queue_get(rpi_pool->queue); +++ if (!buf) { +++ // Running too fast so drop the frame +++ return; +++ } +++ assert(buf); +++ buf->cmd = 0; +++ buf->length = (w2 * h2 * 3)/2; +++ buf->offset = 0; // Offset to valid data +++ buf->flags = 0; +++#ifdef RPI_ZERO_COPY +++ buf->data = get_vc_handle(fr->buf[0]); +++ buf->alloc_size = (w2*h2*3)/2; +++#else +++ //mmal_buffer_header_mem_lock(buf); +++ memcpy(buf->data, fr->data[0], w2 * h); +++ memcpy(buf->data+w2*h2, fr->data[1], w2 * h / 4); +++ memcpy(buf->data+w2*h2*5/4, fr->data[2], w2 * h / 4); +++ //mmal_buffer_header_mem_unlock(buf); +++#endif +++ +++ mmal_port_send_buffer(display->input[0], buf); // I assume this will automatically get released +++} +++ +++static void display_exit(MMAL_COMPONENT_T* display) +++{ +++ if (display) { +++ mmal_component_destroy(display); +++ } +++ if (rpi_pool) { +++ mmal_port_pool_destroy(display->input[0], rpi_pool); +++ } +++} +++ +++#endif +++ +++ ++ /* sub2video hack: ++ Convert subtitles to video with alpha to insert them in filter graphs. ++ This is a temporary solution until libavfilter gets real subtitles support. ++@@ -581,6 +728,10 @@ static void ffmpeg_cleanup(int ret) ++ } ++ term_exit(); ++ ffmpeg_exited = 1; +++ +++#ifdef RPI_DISPLAY +++ display_exit(rpi_display); +++#endif ++ } ++ ++ void remove_avoptions(AVDictionary **a, AVDictionary *b) ++@@ -928,6 +1079,14 @@ static void do_video_out(AVFormatContext *s, ++ int frame_size = 0; ++ InputStream *ist = NULL; ++ AVFilterContext *filter = ost->filter->filter; +++#ifdef RPI_DISPLAY +++ if (next_picture) +++ { +++ if (!rpi_display) +++ rpi_display = display_init(0,0,next_picture->width,next_picture->height); +++ display_frame(rpi_display,next_picture); +++ } +++#endif ++ ++ if (ost->source_index >= 0) ++ ist = input_streams[ost->source_index]; ++-- ++2.5.0 ++ ++ ++From 90f7867ad638d03e8d1a9902990dfd7edd13fe0d Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 29 Apr 2015 16:49:43 +0100 ++Subject: [PATCH 02/68] Split transform and intra prediction into commands ++ ++--- ++ libavcodec/hevc.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++- ++ libavcodec/hevc.h | 58 +++++++++++++++++++++++ ++ libavcodec/hevc_cabac.c | 15 ++++++ ++ 3 files changed, 191 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 203f90a..2eebd31 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -920,6 +920,25 @@ static int hls_cross_component_pred(HEVCContext *s, int idx) { ++ return 0; ++ } ++ +++#ifdef RPI +++static void rpi_intra_pred(HEVCContext *s, int log2_trafo_size, int x0, int y0, int c_idx) +++{ +++ if (s->enable_rpi) { +++ HEVCLocalContext *lc = s->HEVClc; +++ HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; +++ cmd->type = RPI_PRED_INTRA; +++ cmd->size = log2_trafo_size; +++ cmd->c_idx = c_idx; +++ cmd->x = x0; +++ cmd->y = y0; +++ cmd->na = (lc->na.cand_bottom_left<<4) + (lc->na.cand_left<<3) + (lc->na.cand_up_left<<2) + (lc->na.cand_up<<1) + lc->na.cand_up_right; +++ cmd->mode = c_idx ? lc->tu.intra_pred_mode_c : lc->tu.intra_pred_mode; +++ } else { +++ s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, c_idx); +++ } +++} +++#endif +++ ++ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ int xBase, int yBase, int cb_xBase, int cb_yBase, ++ int log2_cb_size, int log2_trafo_size, ++@@ -932,8 +951,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ int trafo_size = 1 << log2_trafo_size; ++ ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); ++- +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size, x0, y0, 0); +++#else ++ s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); +++#endif ++ } ++ ++ if (cbf_luma || cbf_cb[0] || cbf_cr[0] || ++@@ -1019,7 +1041,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0 + (i << log2_trafo_size_c), 1); +++#else ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1); +++#endif ++ } ++ if (cbf_cb[i]) ++ ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), ++@@ -1048,7 +1074,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0 + (i << log2_trafo_size_c), 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2); +++#endif ++ } ++ if (cbf_cr[i]) ++ ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), ++@@ -1077,7 +1107,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), ++ trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase + (i << log2_trafo_size), 1); +++#else ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1); +++#endif ++ } ++ if (cbf_cb[i]) ++ ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), ++@@ -1087,7 +1121,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), ++ trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase + (i << log2_trafo_size), 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2); +++#endif ++ } ++ if (cbf_cr[i]) ++ ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), ++@@ -1099,26 +1137,46 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]); ++ int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]); ++ ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0, 1); +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0, 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2); +++#endif ++ if (s->ps.sps->chroma_format_idc == 2) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c), ++ trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0 + (1 << log2_trafo_size_c), 1); +++ rpi_intra_pred(s, log2_trafo_size_c, x0, y0 + (1 << log2_trafo_size_c), 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2); +++#endif ++ } ++ } else if (blk_idx == 3) { ++ int trafo_size_h = 1 << (log2_trafo_size + 1); ++ int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]); ++ ff_hevc_set_neighbour_available(s, xBase, yBase, ++ trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase, 1); +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase, 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); +++#endif ++ if (s->ps.sps->chroma_format_idc == 2) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)), ++ trafo_size_h, trafo_size_v); +++#ifdef RPI +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase + (1 << (log2_trafo_size)), 1); +++ rpi_intra_pred(s, log2_trafo_size, xBase, yBase + (1 << (log2_trafo_size)), 2); +++#else ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2); +++#endif ++ } ++ } ++ } ++@@ -2293,6 +2351,31 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]])); ++ } ++ +++#ifdef RPI +++static void rpi_execute_pred_cmds(HEVCContext *s) +++{ +++ int i; +++ HEVCPredCmd *cmd = s->univ_pred_cmds; +++ HEVCLocalContext *lc = s->HEVClc; +++ +++ for(i = s->num_pred_cmds; i > 0; i--, cmd++) { +++ if (cmd->type == RPI_PRED_INTRA) { +++ lc->tu.intra_pred_mode_c = lc->tu.intra_pred_mode = cmd->mode; +++ lc->na.cand_bottom_left = (cmd->na >> 4) & 1; +++ lc->na.cand_left = (cmd->na >> 3) & 1; +++ lc->na.cand_up_left = (cmd->na >> 2) & 1; +++ lc->na.cand_up = (cmd->na >> 1) & 1; +++ lc->na.cand_up_right = (cmd->na >> 0) & 1; +++ s->hpc.intra_pred[cmd->size - 2](s, cmd->x, cmd->y, cmd->c_idx); +++ } else { +++ s->hevcdsp.transform_add[cmd->size-2](cmd->dst, cmd->buf, cmd->stride); +++ } +++ } +++ s->num_pred_cmds = 0; +++ s->num_coeffs = 0; +++} +++#endif +++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ { ++ HEVCContext *s = avctxt->priv_data; ++@@ -2302,6 +2385,10 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ int y_ctb = 0; ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ +++#ifdef RPI +++ s->enable_rpi = 1; // TODO this should depend on cross component and frame width etc. +++#endif +++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++ return AVERROR_INVALIDDATA; ++@@ -2331,6 +2418,9 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); +++#ifdef RPI +++ rpi_execute_pred_cmds(s); +++#endif ++ if (more_data < 0) { ++ s->tab_slice_address[ctb_addr_rs] = -1; ++ return more_data; ++@@ -2376,6 +2466,10 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int ++ s = s1->sList[self_id]; ++ lc = s->HEVClc; ++ +++#ifdef RPI +++ s->enable_rpi = 0; +++#endif +++ ++ if(ctb_row) { ++ ret = init_get_bits8(&lc->gb, s->data + s->sh.offset[ctb_row - 1], s->sh.size[ctb_row - 1]); ++ ++@@ -3064,6 +3158,13 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ ++ av_freep(&s->cabac_state); ++ +++#ifdef RPI +++ av_freep(&s->unif_mv_cmds); +++ av_freep(&s->unif_xfm_cmds); +++ av_freep(&s->univ_pred_cmds); +++ av_freep(&s->coeffs_buf); +++#endif +++ ++ for (i = 0; i < 3; i++) { ++ av_freep(&s->sao_pixel_buffer_h[i]); ++ av_freep(&s->sao_pixel_buffer_v[i]); ++@@ -3123,6 +3224,22 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->HEVClcList[0] = s->HEVClc; ++ s->sList[0] = s; ++ +++#ifdef RPI +++ s->unif_mv_cmds = av_mallocz(sizeof(HEVCMvCmd)*RPI_MAX_MV_CMDS); +++ if (!s->unif_mv_cmds) +++ goto fail; +++ s->unif_xfm_cmds = av_mallocz(sizeof(HEVCXfmCmd)*RPI_MAX_XFM_CMDS); +++ if (!s->unif_xfm_cmds) +++ goto fail; +++ s->univ_pred_cmds = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); +++ if (!s->univ_pred_cmds) +++ goto fail; +++ s->coeffs_buf = av_mallocz(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16); +++ if (!s->coeffs_buf) +++ goto fail; +++ s->enable_rpi = 0; +++#endif +++ ++ s->cabac_state = av_malloc(HEVC_CONTEXTS); ++ if (!s->cabac_state) ++ goto fail; ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index c91f815..71174af 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -23,6 +23,9 @@ ++ #ifndef AVCODEC_HEVC_H ++ #define AVCODEC_HEVC_H ++ +++// define RPI to split the CABAC/prediction/transform into separate stages +++#include "config.h" +++ ++ #include "libavutil/buffer.h" ++ #include "libavutil/md5.h" ++ ++@@ -816,6 +819,49 @@ typedef struct HEVCLocalContext { ++ int boundary_flags; ++ } HEVCLocalContext; ++ +++#ifdef RPI +++ +++// RPI_MAX_WIDTH is maximum width in pixels supported by the accelerated code +++#define RPI_MAX_WIDTH 2048 +++ +++// Worst case is for 4:4:4 4x4 blocks with 64 high coding tree blocks, so 16 MV cmds per 4 pixels across for each colour plane +++#define RPI_MAX_MV_CMDS (16*3*(RPI_MAX_WIDTH/4)) +++#define RPI_MAX_XFM_CMDS (16*3*(RPI_MAX_WIDTH/4)) +++// Each block can have an intra prediction and a transform_add command +++#define RPI_MAX_PRED_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) +++ +++// Command for inter prediction +++typedef struct HEVCMvCmd { +++} HEVCMvCmd; +++ +++// Command for transform to process a block of coefficients +++typedef struct HEVCXfmCmd { +++} HEVCXfmCmd; +++ +++// Command for intra prediction and transform_add of predictions to coefficients +++#define RPI_PRED_TRANSFORM_ADD 0 +++#define RPI_PRED_INTRA 1 +++typedef struct HEVCPredCmd { +++ uint8_t size; +++ uint8_t type; +++ uint8_t na; +++ uint8_t c_idx; +++ union { +++ uint8_t *dst; // RPI_PRED_TRANSFORM_ADD +++ uint32_t x; // RPI_PRED_INTRA +++ }; +++ union { +++ int16_t *buf; // RPI_PRED_TRANSFORM_ADD +++ uint32_t y; // RPI_PRED_INTRA +++ }; +++ union { +++ enum IntraPredMode mode; // RPI_PRED_TRANSFORM_ADD +++ uint32_t stride; // RPI_PRED_INTRA +++ }; +++} HEVCPredCmd; +++ +++#endif +++ ++ typedef struct HEVCContext { ++ const AVClass *c; // needed by private avoptions ++ AVCodecContext *avctx; ++@@ -831,6 +877,18 @@ typedef struct HEVCContext { ++ int width; ++ int height; ++ +++#ifdef RPI +++ int enable_rpi; +++ HEVCMvCmd *unif_mv_cmds; +++ HEVCXfmCmd *unif_xfm_cmds; +++ HEVCPredCmd *univ_pred_cmds; +++ int16_t *coeffs_buf; +++ int num_mv_cmds; +++ int num_xfm_cmds; +++ int num_pred_cmds; +++ int num_coeffs; +++#endif +++ ++ uint8_t *cabac_state; ++ ++ /** 1 if the independent slice segment header was successfully parsed */ ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index d1bef83..c0fdfad 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1510,6 +1510,21 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ coeffs[i] = coeffs[i] + ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++ } +++#ifdef RPI +++ if (s->enable_rpi) { +++ int16_t *c = s->coeffs_buf + s->num_coeffs; +++ int n = trafo_size * trafo_size; +++ HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; +++ memcpy(c, coeffs, n * sizeof(int16_t)); // TODO change pointer earlier and we can avoid this copy +++ s->num_coeffs += n; +++ cmd->type = RPI_PRED_TRANSFORM_ADD; +++ cmd->size = log2_trafo_size; +++ cmd->buf = c; +++ cmd->dst = dst; +++ cmd->stride = stride; +++ return; +++ } +++#endif ++ s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride); ++ } ++ ++-- ++2.5.0 ++ ++ ++From 18fe64824d85a2ac9832bd5b600db8e52b5581fe Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 30 Apr 2015 15:23:22 +0100 ++Subject: [PATCH 03/68] Added simple VPU test code ++ ++--- ++ libavcodec/Makefile | 7 + ++ libavcodec/hevc.c | 33 +- ++ libavcodec/rpi_hevc_transform.h | 212 ++++++ ++ libavcodec/rpi_hevc_transform.s | 147 ++++ ++ libavcodec/rpi_mailbox.c | 293 ++++++++ ++ libavcodec/rpi_mailbox.h | 20 + ++ libavcodec/rpi_qpu.c | 652 ++++++++++++++++++ ++ libavcodec/rpi_qpu.h | 45 ++ ++ libavcodec/rpi_shader.c | 818 ++++++++++++++++++++++ ++ libavcodec/rpi_shader.h | 20 + ++ libavcodec/rpi_shader.qasm | 1413 +++++++++++++++++++++++++++++++++++++++ ++ libavcodec/rpi_user_vcsm.h | 425 ++++++++++++ ++ 12 files changed, 4084 insertions(+), 1 deletion(-) ++ create mode 100644 libavcodec/rpi_hevc_transform.h ++ create mode 100644 libavcodec/rpi_hevc_transform.s ++ create mode 100644 libavcodec/rpi_mailbox.c ++ create mode 100644 libavcodec/rpi_mailbox.h ++ create mode 100644 libavcodec/rpi_qpu.c ++ create mode 100644 libavcodec/rpi_qpu.h ++ create mode 100644 libavcodec/rpi_shader.c ++ create mode 100644 libavcodec/rpi_shader.h ++ create mode 100644 libavcodec/rpi_shader.qasm ++ create mode 100644 libavcodec/rpi_user_vcsm.h ++ ++diff --git a/libavcodec/Makefile b/libavcodec/Makefile ++index f6a4fbb..0fd6767 100644 ++--- a/libavcodec/Makefile +++++ b/libavcodec/Makefile ++@@ -5,6 +5,10 @@ NAME = avcodec ++ HEADERS = avcodec.h \ ++ avdct.h \ ++ avfft.h \ +++ rpi_qpu.h \ +++ rpi_shader.h \ +++ rpi_mailbox.h \ +++ rpi_hevc_transform.h \ ++ dv_profile.h \ ++ d3d11va.h \ ++ dirac.h \ ++@@ -39,6 +43,9 @@ OBJS = allcodecs.o \ ++ resample.o \ ++ resample2.o \ ++ utils.o \ +++ rpi_qpu.o \ +++ rpi_shader.o \ +++ rpi_mailbox.o \ ++ vorbis_parser.o \ ++ xiph.o \ ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 2eebd31..681e9fd 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -41,6 +41,10 @@ ++ #include "hevc.h" ++ #include "profiles.h" ++ +++#ifdef RPI +++#include "rpi_qpu.h" +++#endif +++ ++ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ ++ /** ++@@ -2419,7 +2423,9 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ #ifdef RPI ++- rpi_execute_pred_cmds(s); +++ if (x_ctb + ctb_size >= s->ps.sps->width) { +++ rpi_execute_pred_cmds(s); +++ } ++ #endif ++ if (more_data < 0) { ++ s->tab_slice_address[ctb_addr_rs] = -1; ++@@ -3238,6 +3244,31 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ if (!s->coeffs_buf) ++ goto fail; ++ s->enable_rpi = 0; +++ +++ // A little test program +++ { +++ GPU_MEM_PTR_T p; +++ int err = gpu_malloc_cached(16, &p); +++ short *q = (short *)p.arm; +++ int i; +++ int r; +++ printf("Allocated memory %d ARM 0x%x, VC 0x%x, Code 0x%x\n",err,(int)p.arm,p.vc,(int)vpu_get_fn()); +++ printf("Allocated memory %d ARM 0x%x, VC 0x%x\n",err,(int)p.arm,p.vc); +++ printf("Preparing data %p\n",q); +++ for(i=0;i<16;i++) +++ q[i] = i; +++ printf("Flush cache\n"); +++ gpu_cache_flush(&p); +++ printf("Executing code\n"); +++ r = vpu_execute_code( vpu_get_fn(), p.vc, 0, 0, 0, 0, 0); +++ printf("Return value %d (",r); +++ for(i=0;i<16;i++) +++ printf("%d ",q[i]); +++ printf(")\n"); +++ gpu_free(&p); +++ goto fail; // Early out +++ } +++ ++ #endif ++ ++ s->cabac_state = av_malloc(HEVC_CONTEXTS); ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++new file mode 100644 ++index 0000000..85a9102 ++--- /dev/null +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -0,0 +1,212 @@ +++unsigned char rpi_hevc_transform [] = { +++169, +++3, +++3, +++232, +++128, +++0, +++0, +++0, +++20, +++248, +++0, +++136, +++0, +++0, +++192, +++248, +++0, +++0, +++0, +++96, +++3, +++232, +++32, +++0, +++0, +++0, +++7, +++232, +++0, +++2, +++0, +++0, +++8, +++232, +++0, +++4, +++0, +++0, +++12, +++248, +++0, +++128, +++0, +++0, +++192, +++8, +++4, +++0, +++4, +++232, +++64, +++0, +++0, +++0, +++5, +++232, +++0, +++0, +++8, +++0, +++128, +++69, +++113, +++66, +++12, +++248, +++0, +++128, +++0, +++0, +++192, +++8, +++4, +++0, +++128, +++69, +++113, +++70, +++128, +++144, +++39, +++0, +++4, +++255, +++48, +++192, +++128, +++3, +++32, +++8, +++16, +++0, +++76, +++254, +++48, +++192, +++9, +++4, +++32, +++8, +++0, +++0, +++4, +++254, +++0, +++144, +++128, +++2, +++0, +++248, +++62, +++0, +++128, +++144, +++22, +++0, +++4, +++255, +++48, +++192, +++128, +++3, +++32, +++8, +++16, +++0, +++76, +++254, +++48, +++192, +++9, +++4, +++32, +++8, +++0, +++0, +++140, +++248, +++44, +++0, +++0, +++0, +++32, +++48, +++4, +++0, +++128, +++69, +++113, +++66, +++242, +++140, +++211, +++192, +++41, +++3, +++68, +++192, +++80, +++7, +++164, +++255, +++36, +++220, +++96, +++2, +++0, +++248, +++62, +++0, +++3, +++255, +++55, +++208, +++120, +++3, +++224, +++3, +++190, +++11, +++16, +++139, +++246, +++83, +++0, +++103, +++90, +++0, +++8, +++240, +++0, +++128, +++128, +++3, +++0, +++247, +++32, +++128, +++10, +++4, +++136, +++240, +++32, +++0, +++128, +++3, +++112, +++96, +++90, +++0, +++}; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++new file mode 100644 ++index 0000000..5e2728d ++--- /dev/null +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -0,0 +1,147 @@ +++# ****************************************************************************** +++# Argon Design Ltd. +++# (c) Copyright 2015 Argon Design Ltd. All rights reserved. +++# +++# Module : HEVC +++# Author : Peter de Rivaz +++# ****************************************************************************** +++ +++# HEVC VPU Transform +++# +++# Transform matrix can be thought of as +++# output row vector = input row vector * transMatrix2 +++# +++# The even rows of the matrix are symmetric +++# The odd rows of the matrix are antisymmetric +++# +++# So only need to compute the first half of the results, then can compute the remainder with a butterfly +++# +++# EXAMPLE +++# (a b c d) (1 2 2 1) +++# (3 4 -4 -3) +++# (5 6 6 5) +++# (7 8 -8 -7) +++# +++# x=(a c)(1 2) = 1a+5c 2a+6c +++# (5 6) +++# +++# y=(b d)(3 4) = 3b+7d 4b+8d +++# (7 8) +++# +++# u=x+y = 1a+5c+3b+7d 2a+4b+6c+8d +++# v=x-y = 1a+5c-3b-7d 2a+6c-4b-8d +++# +++# Final results are (u , v[::-1]) +++# +++# +++# For 32x1 input, load even rows into HX(0++,0), odd rows into HX(16++,0) +++# Apply the even matrix first and stop before rounding +++# Then apply the odd matrix in a full manner: +++# +++# First step is to compute partial products with the first input (16 cycles) +++# 1a 3b 5c 7d 16x1 input coefficients produce 16x16 output +++# 2a 4b 6c 8d +++# 2a -4b 6c -8d +++# 1a -3b 5c -7d +++# +++# Second step is to sum partial products into final position (8 cycles) +++# 1a+3b+5c+7d +++# 2a+4b+6c+8d +++# 2a-4b+6c-8d +++# 1a-3b+5c-7d +++# +++# Then can apply butterfly to combine even results and odd results + rounding to produce 16 rows of output at a time (need to save in transposed format) +++# +++# For 16x16 no butterfly is required and can store final results in original location (Could do 2 16x16s in parallel to make use of the trick - saves on the adds) +++# +++# For 8x8 we could compute two in parallel. +++# +++# +++ +++test_add: +++ vldh HX(0,0),(r0) +++ vadd HX(0,0),HX(0,0),10 +++ vsth HX(0,0),(r0) +++ mov r0,7 # return value +++ b lr +++ +++# Columns are transformed first +++# +++# Store top left half of transMatrix2 in +++# Store bottom left half of transMatrix2 in HX(32,32) +++# +++# For 16x16 +++# HX(0:15,0) contains input data before transform +++# HY(0:15,0) contains 32bit output data after transform +++# HX(32,0) contains even rows of left half of transMatrix2 +++# HX(32,32) contains odd rows of left half of transMatrix2 +++# HY(48,0) contains partial products ready for summing +++# +++ +++ +++# hevc_trans_16x16(short *transMatrix2, short *coeffs, int num) +++# transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) +++# coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) +++# num: number of 16x16 transforms to be done +++# +++hevc_trans_16x16: +++ push r6-r15, lr # TODO cut down number of used registers +++ +++ mov r3, 2*32*2 # Twice Stride of transMatrix2 in bytes +++ vld HX(32++,0),(r0 += r3) REP 16 # This is the 16x16 matrix, a transform is equivalent to multiplying input row vector * matrix +++ # Now use r0 to describe which matrix we are working on. +++ # Allows us to prefetch the next block of coefficients for efficiency. +++ mov r0,0 # This describes the location where we read our coefficients from +++ mov r3,16*2 # Stride of coefficients in bytes +++ mov r7,16*16*2 # Total block size +++ mov r8,64*16 # Value used to swap from current to next VRF location +++ vldh HX(0++,0)+r0,(r1 += r3) REP 16 +++ mov r4,64 # Constant used for rounding first pass +++ mov r5,1<<19 # Constant used for rounding second pass +++ +++ # At start of block r0,r1 point to the current block (that has already been loaded) +++block_loop: +++ eor r0,r8 +++ add r1,r7 +++ # Prefetch the next block +++ vldh HX(0++,0)+r0,(r1 += r3) REP 16 +++ eor r0,r8 +++ sub r1,r7 +++ +++ # Transform the current block +++ bl col_trans_16 +++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r4 REP 16 # Now add on rounding, shift down by 7, and saturate +++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # 9+7=16 so this ends up with the output saturated and in the top half of the word. +++ vasl HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # This should be saturating, but the instruction above does not assemble? +++ vmov VX(0,0++), HX(0++,32) REP 16 # For simplicity transpose this back to the original position +++ +++ bl col_trans_16 +++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r4 REP 16 # Now add on rounding, shift down by 7, and saturate +++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # 9+7=16 so this ends up with the output saturated and in the top half of the word. +++ vasl HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # This should be saturating, but the instruction above does not assemble? +++ +++ # Save results - note there has been a transposition during the processing so we save columns +++ vsth VX(0,32++)+r0, (r1 += r3) REP 16 +++ +++ # Move onto next block +++ eor r0,r8 +++ add r1,r7 +++ +++ addcmpbgt r2,-1,0,block_loop +++ pop r6-r15, pc +++ +++# r1,r2,r3 r7,r8 should be preserved +++# HX(0++,0)+r0 is the block to be transformed +++# HX(32++,0) is the 16x16 matrix of transform coefficients +++# Use HY(48,0) for intermediate results +++# r0 can be used, but should be returned to its original value at the end +++col_trans_16: +++ add r4,r0,16 # Final value for this loop +++col_trans_16_loop: +++ # First compute partial products for a single column +++ vmul32s VY(48,0++), VX(0,0)+r0, VX(32,0++) REP 16 +++ # Then sum up the results and place back +++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC +++ addcmpblt r0,1,r4,col_trans_16_loop +++ sub r0,16 # but r0 back to its original value +++ b lr ++diff --git a/libavcodec/rpi_mailbox.c b/libavcodec/rpi_mailbox.c ++new file mode 100644 ++index 0000000..536896f ++--- /dev/null +++++ b/libavcodec/rpi_mailbox.c ++@@ -0,0 +1,293 @@ +++/* +++Copyright (c) 2012, Broadcom Europe Ltd. +++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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE +++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#include +++ +++#define MAJOR_NUM 100 +++#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) +++#define DEVICE_FILE_NAME "/dev/char_dev" +++ +++#include "rpi_mailbox.h" +++ +++#define PAGE_SIZE (4*1024) +++ +++// Shared memory will not be cached in ARM cache +++void *mapmem_shared(unsigned base, unsigned size) +++{ +++ int mem_fd; +++ unsigned offset = base % PAGE_SIZE; +++ base = base - offset; +++ /* open /dev/mem */ +++ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { +++ printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); +++ return NULL; +++ } +++ void *mem = mmap( +++ 0, +++ size, +++ PROT_READ|PROT_WRITE, +++ MAP_SHARED/*|MAP_FIXED*/, +++ mem_fd, +++ base); +++#ifdef DEBUG +++ printf("base=0x%x, mem=%p\n", base, mem); +++#endif +++ if (mem == MAP_FAILED) { +++ printf("mmap error %d\n", (int)mem); +++ return NULL; +++ } +++ close(mem_fd); +++ return (char *)mem + offset; +++} +++ +++// Unshared memory will be faster as lives in ARM cache, but requires cache flushing +++void *mapmem_private(unsigned base, unsigned size) +++{ +++ int mem_fd; +++ unsigned offset = base % PAGE_SIZE; +++ base = base - offset; +++ /* open /dev/mem */ +++ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { +++ printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); +++ return NULL; +++ } +++ void *mem = mmap( +++ 0, +++ size, +++ PROT_READ|PROT_WRITE, +++ MAP_PRIVATE/*|MAP_FIXED*/, +++ mem_fd, +++ base); +++#ifdef DEBUG +++ printf("base=0x%x, mem=%p\n", base, mem); +++#endif +++ if (mem == MAP_FAILED) { +++ printf("mmap error %d\n", (int)mem); +++ return NULL; +++ } +++ close(mem_fd); +++ return (char *)mem + offset; +++} +++ +++void unmapmem(void *addr, unsigned size) +++{ +++ int s = munmap(addr, size); +++ if (s != 0) { +++ printf("munmap error %d\n", s); +++ exit (-1); +++ } +++} +++ +++/* +++ * use ioctl to send mbox property message +++ */ +++ +++static int mbox_property(int file_desc, void *buf) +++{ +++ int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); +++ +++ if (ret_val < 0) { +++ printf("ioctl_set_msg failed:%d\n", ret_val); +++ } +++ +++#ifdef DEBUG +++ unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; +++ for (i=0; i +++#include +++#include +++#include +++#include +++ +++#include "config.h" +++ +++#include +++#include +++ +++#include "rpi_mailbox.h" +++#include "rpi_qpu.h" +++#include "rpi_shader.h" +++#include "rpi_hevc_transform.h" +++ +++#ifdef RPI_USE_VCSM +++#include "rpi_user_vcsm.h" +++#endif +++ +++// On Pi2 there is no way to access the VPU L2 cache +++// GPU_MEM_FLG should be 4 for uncached memory. +++// However, if using VCSM allocated buffers, need to use C at the moment because VCSM does not allocate uncached memory correctly +++// The QPU crashes if we mix L2 cached and L2 uncached accesses due to a HW bug. +++#define GPU_MEM_FLG 0xC +++#define GPU_MEM_MAP 0x0 +++ +++#define vcos_verify(x) ((x)>=0) +++ +++typedef unsigned char uint8_t; +++typedef signed char int8_t; +++typedef unsigned short uint16_t; +++typedef unsigned int uint32_t; +++typedef int int32_t; +++ +++/*static const unsigned code[] = +++{ +++ #include "rpi_shader.hex" +++};*/ +++ +++// Size in 32bit words +++#define QPU_CODE_SIZE 2048 +++#define VPU_CODE_SIZE 2048 +++ +++struct GPU +++{ +++ unsigned int qpu_code[QPU_CODE_SIZE]; +++ unsigned int vpu_code[VPU_CODE_SIZE]; +++ int open_count; // Number of allocated video buffers +++ unsigned int vc_handle; // Handle of this memory +++ int mb; // Mailbox handle +++ int vc; // Address in GPU memory +++ int mail[12]; // These are used to pass pairs of code/unifs to the QPUs +++}; +++ +++// Stop more than one thread trying to allocate memory or use the processing resources at once +++static pthread_mutex_t gpu_mutex = PTHREAD_MUTEX_INITIALIZER; +++static volatile struct GPU* gpu = NULL; +++ +++#ifdef RPI_TIME_TOTAL_QPU +++static unsigned int Microseconds(void) { +++ struct timespec ts; +++ unsigned int x; +++ static unsigned int base = 0; +++ clock_gettime(CLOCK_REALTIME, &ts); +++ x = ts.tv_sec*1000000 + ts.tv_nsec/1000; +++ if (base==0) base=x; +++ return x-base; +++} +++#endif +++ +++// Connect to QPU, returns 0 on success. +++static int gpu_init(volatile struct GPU **gpu) { +++ int mb = mbox_open(); +++ int vc; +++ int handle; +++ volatile struct GPU* ptr; +++ if (mb < 0) +++ return -1; +++ +++ if (qpu_enable(mb, 1)) return -2; +++ +++#ifdef RPI_USE_VCSM +++ vcsm_init(); +++#endif +++ +++ handle = mem_alloc(mb, sizeof(struct GPU), 4096, GPU_MEM_FLG); +++ if (!handle) +++ { +++ qpu_enable(mb, 0); +++ return -3; +++ } +++ vc = mem_lock(mb, handle); +++ ptr = mapmem_shared((vc+GPU_MEM_MAP)&~0xc0000000, sizeof(struct GPU)); +++ if (ptr == NULL) +++ { mem_free(mb, handle); +++ mem_unlock(mb, handle); +++ qpu_enable(mb, 0); +++ return -4; +++ } +++ +++ ptr->mb = mb; +++ ptr->vc_handle = handle; +++ ptr->vc = vc; +++ +++ *gpu = ptr; +++ +++ // Now copy over the QPU code into GPU memory +++ { +++ int num_bytes = qpu_get_fn(QPU_MC_END) - qpu_get_fn(QPU_MC_SETUP); +++ assert(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); +++ memcpy((void*)ptr->qpu_code, rpi_shader, num_bytes); +++ } +++ // And the VPU code +++ { +++ int num_bytes = sizeof(rpi_hevc_transform); +++ assert(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); +++ memcpy((void*)ptr->vpu_code, rpi_hevc_transform, num_bytes); +++ } +++ +++ return 0; +++} +++ +++// Make sure we have exclusive access to the mailbox, and enable qpu if necessary. +++static void gpu_lock(void) { +++ pthread_mutex_lock(&gpu_mutex); +++ if (gpu==NULL) { +++ gpu_init(&gpu); +++ } +++} +++ +++static void gpu_unlock(void) { +++ pthread_mutex_unlock(&gpu_mutex); +++} +++ +++// Allocate memory on GPU +++// Fills in structure

containing ARM pointer, videocore handle, videocore memory address, numbytes +++// Returns 0 on success. +++// This allocates memory that will not be cached in ARM's data cache. +++// Therefore safe to use without data cache flushing. +++int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) { +++ gpu_lock(); +++ p->vc_handle = mem_alloc(gpu->mb, numbytes, 4096, GPU_MEM_FLG); +++ p->vcsm_handle = 0; +++ if (!p->vc_handle) +++ { +++ qpu_enable(gpu->mb, 0); +++ return -3; +++ } +++ p->vc = mem_lock(gpu->mb, p->vc_handle); +++ p->arm = mapmem_shared((p->vc+GPU_MEM_MAP)&~0xc0000000,numbytes); +++ p->numbytes = numbytes; +++ if (p->arm == NULL) +++ { +++ mem_free(gpu->mb, p->vc_handle); +++ mem_unlock(gpu->mb, p->vc_handle); +++ gpu_unlock(); +++ qpu_enable(gpu->mb, 0); +++ return -4; +++ } +++ gpu->open_count++; +++ gpu_unlock(); +++ return 0; +++} +++ +++void gpu_cache_flush(GPU_MEM_PTR_T *p) +++{ +++ // This only works when using RPI_USE_VCSM +++ void *tmp = vcsm_lock(p->vcsm_handle); +++ vcsm_unlock_ptr(tmp); +++} +++ +++// This allocates data that will be +++// Cached in ARM L2 +++// Uncached in VPU L2 +++int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p) { +++ gpu_lock(); +++#ifdef RPI_USE_VCSM +++ { +++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST, (char *)"Video Frame" ); // f....... locks up for VP9 - retest this? +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC, (char *)"Video Frame" ); // 3b...... works +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); //fb...... locks up +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST_AND_VC, (char *)"Video Frame" ); // 3b works (but corrupted due to caching) +++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); +++ p->arm = vcsm_lock(p->vcsm_handle); +++ p->vc = mem_lock(gpu->mb, p->vc_handle); +++ } +++#else +++ p->vc_handle = mem_alloc(gpu->mb, numbytes, 4096, GPU_MEM_FLG); +++ p->vcsm_handle = 0; +++ if (!p->handle) +++ { +++ qpu_enable(gpu->mb, 0); +++ return -3; +++ } +++ p->vc = mem_lock(gpu->mb, p->vc_handle); +++ printf("This mapmem_private does not seem to work\n"); +++ exit(-1); +++ p->arm = mapmem_private((p->vc+GPU_MEM_MAP)&~0xc0000000,numbytes); +++ p->numbytes = numbytes; +++ if (p->arm == NULL) +++ { +++ mem_free(gpu->mb, p->handle); +++ mem_unlock(gpu->mb, p->handle); +++ gpu_unlock(); +++ qpu_enable(gpu->mb, 0); +++ return -4; +++ } +++#endif +++ gpu->open_count++; +++ gpu_unlock(); +++ return 0; +++} +++ +++static void gpu_term(void) +++{ +++ int mb = gpu->mb; +++ unsigned handle = gpu->vc_handle; +++ if (gpu==NULL) +++ return; +++ unmapmem((void*)gpu, sizeof(struct GPU)); +++ mem_unlock(mb, handle); +++ mem_free(mb, handle); +++ qpu_enable(mb, 0); +++#ifdef RPI_USE_VCSM +++ vcsm_exit(); +++#endif +++ mbox_close(mb); +++ gpu = NULL; +++} +++ +++void gpu_free(GPU_MEM_PTR_T *p) { +++ int mb = gpu->mb; +++ unsigned handle = p->vc_handle; +++ gpu_lock(); +++#ifdef RPI_USE_VCSM +++ if (p->vcsm_handle) { +++ mem_unlock(mb,p->vc_handle); +++ vcsm_unlock_ptr(p->arm); +++ vcsm_free(p->vcsm_handle); +++ } else { +++ unmapmem((void*)p->arm, sizeof(struct GPU)); +++ mem_unlock(mb, handle); +++ mem_free(mb, handle); +++ } +++#else +++ unmapmem((void*)p->arm, sizeof(struct GPU)); +++ mem_unlock(mb, handle); +++ mem_free(mb, handle); +++#endif +++ +++ gpu->open_count--; +++ if (gpu->open_count==0) { +++ printf("Closing GPU\n"); +++ gpu_term(); +++ gpu = NULL; +++ } +++ gpu_unlock(); +++} +++ +++unsigned int vpu_get_fn(void) { +++ // Make sure that the gpu is initialized +++ if (gpu==NULL) { +++ printf("Preparing gpu\n"); +++ gpu_lock(); +++ gpu_unlock(); +++ } +++ return gpu->vc + offsetof(struct GPU,vpu_code); +++} +++ +++unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5) +++{ +++ unsigned r; +++ gpu_lock(); +++ r = execute_code(gpu->mb, code, r0, r1, r2, r3, r4, r5); +++ gpu_unlock(); +++ return r; +++} +++ +++// Run a program on a QPU with the given code and uniform stream (given in GPU addresses) +++// The first num QPUs will start at code, the next num2 QPUs will start at code2 +++void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, int unifs9, int unifs10, int unifs11, int unifs12) +++{ +++ int i; +++#ifdef RPI_TIME_TOTAL_QPU +++ static int last_time=0; +++ static long long on_time=0; +++ static long long off_time=0; +++ int start_time; +++ int end_time; +++ static int count=0; +++#endif +++ +++ gpu_lock(); +++#ifdef RPI_TIME_TOTAL_QPU +++ start_time = Microseconds(); +++ if (last_time==0) +++ last_time = start_time; +++ off_time += start_time-last_time; +++#endif +++ for(i=0;imail[i*2 + 1] = code; +++ } +++ for(;imail[i*2 + 1] = code2; +++ } +++ gpu->mail[0 ] = unifs1; +++ gpu->mail[2 ] = unifs2; +++ gpu->mail[4 ] = unifs3; +++ gpu->mail[6 ] = unifs4; +++ gpu->mail[8 ] = unifs5; +++ gpu->mail[10] = unifs6; +++ gpu->mail[12] = unifs7; +++ gpu->mail[14] = unifs8; +++ gpu->mail[16] = unifs9; +++ gpu->mail[18] = unifs10; +++ gpu->mail[20] = unifs11; +++ gpu->mail[22] = unifs12; +++ execute_qpu( +++ gpu->mb, +++ 12 /* Number of QPUs */, +++ gpu->vc + offsetof(struct GPU, mail), +++ 1 /* no flush */, // Don't flush VPU L1 cache +++ 5000 /* timeout ms */); +++#ifdef RPI_TIME_TOTAL_QPU +++ end_time = Microseconds(); +++ last_time = end_time; +++ on_time += end_time - start_time; +++ count++; +++ if ((count&0x7f)==0) +++ printf("On=%dms, Off=%dms\n",(int)(on_time/1000),(int)(off_time/1000)); +++#endif +++ gpu_unlock(); +++} +++ +++unsigned int qpu_get_fn(int num) { +++ // Make sure that the gpu is initialized +++ unsigned int *fn; +++ if (gpu==NULL) { +++ printf("Preparing gpu\n"); +++ gpu_lock(); +++ gpu_unlock(); +++ } +++ switch(num) { +++ case QPU_MC_SETUP: +++ fn = mc_setup; +++ break; +++ case QPU_MC_FILTER: +++ fn = mc_filter; +++ break; +++ case QPU_MC_EXIT: +++ fn = mc_exit; +++ break; +++ case QPU_MC_INTERRUPT_EXIT: +++ fn = mc_interrupt_exit; +++ break; +++ case QPU_MC_FILTER_B: +++ fn = mc_filter_b; +++ break; +++ case QPU_MC_FILTER_HONLY: +++ fn = mc_filter_honly; +++ break; +++ case QPU_MC_SETUP_UV: +++ fn = mc_setup_uv; +++ break; +++ case QPU_MC_FILTER_UV: +++ fn = mc_filter_uv; +++ break; +++ case QPU_MC_FILTER_UV_B: +++ fn = mc_filter_uv_b; +++ break; +++ case QPU_MC_END: +++ fn = mc_end; +++ break; +++ default: +++ printf("Unknown function\n"); +++ exit(-1); +++ } +++ return gpu->vc + 4*(int)(fn-rpi_shader); +++ //return code[num] + gpu->vc; +++} +++ +++#if 0 +++ +++int32_t hcoeffs[] = {-4, 10, -21, 70, 90, -24, 11, -4}; +++//int32_t hcoeffs[] = {1, 1, 1, 1, 1, 1, 1, 1}; +++int32_t vcoeffs[] = {-2, 6, -13, 37, 115, -20, 9, -4}; +++//int32_t vcoeffs[] = {1, 1, 1, 1, 1, 1, 1, 1}; +++ +++#define ENCODE_COEFFS(c0, c1, c2, c3) (((c0-1) & 0xff) | ((c1-1) & 0xff) << 8 | ((c2-1) & 0xff) << 16 | ((c3-1) & 0xff) << 24); +++ +++static uint8_t av_clip_uint8(int32_t a) +++{ +++ if (a&(~255)) return (-a)>>31; +++ else return a; +++} +++ +++static int32_t filter8(const uint8_t *data, int pitch) +++{ +++ int32_t vsum = 0; +++ int x, y; +++ +++ for (y = 0; y < 8; y++) { +++ int32_t hsum = 0; +++ +++ for (x = 0; x < 8; x++) +++ hsum += hcoeffs[x]*data[x + y * pitch]; +++ +++ vsum += vcoeffs[y]*av_clip_uint8( (hsum + 64) >> 7); // Added brackets to stop compiler warning +++ } +++ +++ return av_clip_uint8( (vsum + 64) >> 7); +++} +++ +++// Note regression changes coefficients so is not thread safe +++//#define REGRESSION +++#ifdef REGRESSION +++#define CMAX 100 +++#else +++#define CMAX 2 +++#endif +++#define YMAX 16 +++ +++int rpi_test_shader(void) +++{ +++ int i, c; +++ +++ uint32_t *unifs; +++ +++ uint8_t *in_buffer; +++ uint8_t *out_buffer[2]; +++ +++ GPU_MEM_PTR_T unifs_ptr; +++ GPU_MEM_PTR_T in_buffer_ptr; +++ GPU_MEM_PTR_T out_buffer_ptr[2]; +++ +++ // Addresses in GPU memory of filter programs +++ uint32_t mc_setup = 0; +++ uint32_t mc_filter = 0; +++ uint32_t mc_exit = 0; +++ +++ int pitch = 0x500; +++ +++ if (gpu==NULL) { +++ gpu_lock(); +++ gpu_unlock(); +++ } +++ +++ printf("This needs to change to reflect new assembler\n"); +++ // Use table to compute locations of program start points +++ mc_setup = code[0] + gpu->vc; +++ mc_filter = code[1] + gpu->vc; +++ mc_exit = code[2] + gpu->vc; +++ +++ if (!vcos_verify(gpu_malloc_uncached(4*64,&unifs_ptr))) { +++ return -2; +++ } +++ unifs = (uint32_t*)unifs_ptr.arm; +++ +++ if (!vcos_verify(gpu_malloc_uncached(64*23,&in_buffer_ptr))) { +++ return -3; +++ } +++ in_buffer = (uint8_t*)in_buffer_ptr.arm; +++ +++ if (!vcos_verify(gpu_malloc_uncached(16*pitch,&out_buffer_ptr[0])) || !vcos_verify(gpu_malloc_uncached(16*pitch,&out_buffer_ptr[1]))) { +++ return -4; +++ } +++ out_buffer[0] = (uint8_t*)out_buffer_ptr[0].arm; +++ out_buffer[1] = (uint8_t*)out_buffer_ptr[1].arm; +++ +++ for (c = 0; c < CMAX; c++) { +++ int xo[] = {rand()&31, rand()&31}; +++ +++#ifdef REGRESSION +++ for (i = 0; i < 8; i++) { +++ hcoeffs[i] = (int8_t)rand(); +++ vcoeffs[i] = (int8_t)rand(); +++ if (hcoeffs[i]==-128) +++ hcoeffs[i]++; +++ if (vcoeffs[i]==-128) +++ vcoeffs[i]++; +++ } +++#endif +++ +++ for (i = 0; i < 64*23; i++) { +++ //printf("%d %d %p\n",i,gpu->mb,&in_buffer[i]); +++ in_buffer[i] = rand(); +++ } +++ +++ // Clear output array +++ { +++ int b; +++ for(b=0;b<2;b++) { +++ for(i=0;i<16*16;i++) { +++ out_buffer[b][i] = 3; +++ } +++ } +++ } +++ +++ unifs[0] = mc_filter; +++ unifs[1] = in_buffer_ptr.vc+xo[0]+16; +++ unifs[2] = 64; // src pitch +++ unifs[3] = pitch; // dst pitch +++ unifs[4] = 0; // Padding +++ unifs[5] = 0; +++ unifs[6] = 0; +++ unifs[7 ] = mc_filter; +++ unifs[8 ] = in_buffer_ptr.vc+xo[1]+16; +++ unifs[9 ] = ENCODE_COEFFS(hcoeffs[0], hcoeffs[1], hcoeffs[2], hcoeffs[3]); +++ unifs[10] = ENCODE_COEFFS(hcoeffs[4], hcoeffs[5], hcoeffs[6], hcoeffs[7]); +++ unifs[11] = ENCODE_COEFFS(vcoeffs[0], vcoeffs[1], vcoeffs[2], vcoeffs[3]); +++ unifs[12] = ENCODE_COEFFS(vcoeffs[4], vcoeffs[5], vcoeffs[6], vcoeffs[7]); +++ unifs[13] = out_buffer_ptr[0].vc; +++ unifs[14] = mc_exit; +++ unifs[15] = in_buffer_ptr.vc+xo[1]+16; // dummy +++ unifs[16] = ENCODE_COEFFS(hcoeffs[0], hcoeffs[1], hcoeffs[2], hcoeffs[3]); +++ unifs[17] = ENCODE_COEFFS(hcoeffs[4], hcoeffs[5], hcoeffs[6], hcoeffs[7]); +++ unifs[18] = ENCODE_COEFFS(vcoeffs[0], vcoeffs[1], vcoeffs[2], vcoeffs[3]); +++ unifs[19] = ENCODE_COEFFS(vcoeffs[4], vcoeffs[5], vcoeffs[6], vcoeffs[7]); +++ unifs[20] = out_buffer_ptr[1].vc; +++ +++ printf("Gpu->vc=%x Code=%x dst=%x\n",gpu->vc, mc_filter,out_buffer_ptr[1].vc); +++ +++ // flush_dcache(); TODO is this needed on ARM side? - tried to use the direct alias to avoid this problem +++ +++ //qpu_run_shader(mc_setup, unifs_ptr.vc); +++ //qpu_run_shader(gpu, gpu->vc, unifs_ptr.vc); +++ rpi_do_block(in_buffer_ptr.vc+xo[0]+16, 64, out_buffer_ptr[0].vc, pitch,out_buffer[0]); +++ rpi_do_block(in_buffer_ptr.vc+xo[1]+16, 64, out_buffer_ptr[1].vc, pitch,out_buffer[1]); +++ +++ if (1) +++ { +++ int x, y, b; +++ int bad = 0; +++ +++ for (b=0; b<2; ++b) +++ for (y=0; yvc; +++ mc_filter = code[1] + gpu->vc; +++ mc_exit = code[2] + gpu->vc; +++ +++ if (!vcos_verify(gpu_malloc_uncached(4*64,&unifs_ptr))) { +++ return; +++ } +++ //gpu_malloc_uncached(16*dst_pitch,&out_buffer_ptr); +++ //out_buffer = (uint8_t*)out_buffer_ptr.arm; +++ +++ /*for (y=0; y<16; ++y) { +++ for (x=0; x<16; ++x) { +++ out_buffer[x+y*dst_pitch] = 7; +++ } +++ }*/ +++ +++ unifs = (uint32_t*)unifs_ptr.arm; +++ +++ unifs[0] = mc_filter; +++ unifs[1] = (int)in_buffer_vc; +++ unifs[2] = src_pitch; // src pitch +++ unifs[3] = dst_pitch; // dst pitch +++ unifs[4] = 0; // Padding +++ unifs[5] = 0; +++ unifs[6] = 0; +++ unifs[7 ] = mc_exit; +++ unifs[8 ] = (int)in_buffer_vc; +++ unifs[9 ] = ENCODE_COEFFS(hcoeffs[0], hcoeffs[1], hcoeffs[2], hcoeffs[3]); +++ unifs[10] = ENCODE_COEFFS(hcoeffs[4], hcoeffs[5], hcoeffs[6], hcoeffs[7]); +++ unifs[11] = ENCODE_COEFFS(vcoeffs[0], vcoeffs[1], vcoeffs[2], vcoeffs[3]); +++ unifs[12] = ENCODE_COEFFS(vcoeffs[4], vcoeffs[5], vcoeffs[6], vcoeffs[7]); +++ unifs[13] = (int)dst_vc; +++ //unifs[13] = (int)out_buffer_ptr.vc; +++ +++ //printf("Gpu->vc=%x Code=%x dst=%x\n",gpu->vc, mc_filter,out_buffer_ptr[1].vc); +++ +++ qpu_run_shader(mc_setup, unifs_ptr.vc); +++ +++ /*for (y=0; y<16; ++y) { +++ for (x=0; x<16; ++x) { +++ dst[x+y*dst_pitch] = out_buffer[x+y*dst_pitch]; +++ } +++ }*/ +++ +++ gpu_free(&unifs_ptr); +++ //gpu_free(&out_buffer_ptr); +++} +++ +++ +++#endif +++ +++#endif // RPI ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++new file mode 100644 ++index 0000000..4e3c35c ++--- /dev/null +++++ b/libavcodec/rpi_qpu.h ++@@ -0,0 +1,45 @@ +++#ifndef RPI_QPU_H +++#define RPI_QPU_H +++ +++typedef struct gpu_mem_ptr_s { +++ unsigned char *arm; // Pointer to memory mapped on ARM side +++ int vc_handle; // Videocore handle of relocatable memory +++ int vcsm_handle; // Handle for use by VCSM +++ int vc; // Address for use in GPU code +++ int numbytes; // Size of memory block +++} GPU_MEM_PTR_T; +++ +++// General GPU functions +++extern int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p); +++extern int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p); +++extern void gpu_free(GPU_MEM_PTR_T *p); +++extern void gpu_cache_flush(GPU_MEM_PTR_T *p); +++ +++// QPU specific functions +++extern void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, int unifs9, int unifs10, int unifs11, int unifs12); +++ +++enum { +++ QPU_MC_SETUP, +++ QPU_MC_FILTER, +++ QPU_MC_EXIT, +++ QPU_MC_INTERRUPT_EXIT, +++ QPU_MC_FILTER_B, +++ QPU_MC_FILTER_HONLY, +++ QPU_MC_SETUP_UV, +++ QPU_MC_FILTER_UV, +++ QPU_MC_FILTER_UV_B, +++ QPU_MC_END +++ }; +++extern unsigned int qpu_get_fn(int num); +++ +++// VPU specific functions +++extern unsigned int vpu_get_fn(void); +++extern unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); +++ +++// Simple test of shader code +++extern int rpi_test_shader(void); +++ +++extern void rpi_do_block(const unsigned char *in_buffer_vc, int src_pitch, unsigned char *dst_vc, int dst_pitch, unsigned char *dst); +++extern void rpi_do_block_arm(const unsigned char *in_buffer, int src_pitch, unsigned char *dst, int dst_pitch); +++ +++#endif ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++new file mode 100644 ++index 0000000..41cc2e1 ++--- /dev/null +++++ b/libavcodec/rpi_shader.c ++@@ -0,0 +1,818 @@ +++#include "rpi_shader.h" +++ +++#ifdef _MSC_VER +++ #include +++ /* cast through uintptr_t to avoid warnings */ +++ #define POINTER_TO_UINT(X) ((unsigned int)(uintptr_t)(X)) +++#else +++ #define POINTER_TO_UINT(X) ((unsigned int)(X)) +++#endif +++ +++#ifdef __cplusplus +++extern "C" { /* the types are probably wrong... */ +++#endif +++#ifdef __cplusplus +++} +++#endif +++ +++#ifdef _MSC_VER +++__declspec(align(8)) +++#elif defined(__GNUC__) +++__attribute__((aligned(8))) +++#endif +++unsigned int rpi_shader[] = { +++// ::mc_setup +++/* [0x00000000] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000008] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num +++/* [0x00000010] */ 0x15827d80, 0x10020767, // mov ra_y, unif +++/* [0x00000018] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif +++/* [0x00000020] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00000028] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x00000030] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x00000038] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000040] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x00000048] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x00000050] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x00000058] */ 0x00000040, 0xe0020567, // mov ra21, 64 +++/* [0x00000060] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000068] */ 0x00000008, 0xe00205e7, // mov ra23, 8 +++/* [0x00000070] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000078] */ 0x00000040, 0xe0021567, // mov rb21, 64 +++/* [0x00000080] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000088] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000090] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00000098] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x000000a0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x000000a8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x000000b0] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x000000b8] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x000000c0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x000000c8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x000000d0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000000d8] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x000000e0] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x000000e8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x000000f0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x000000f8] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000100] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000108] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000110] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000118] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000120] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000128] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000130] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000138] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000140] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000148] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000150] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000158] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000160] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000168] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000170] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000178] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x00000180] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x00000188] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x00000190] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x00000198] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000001a0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x000001a8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000001b0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x000001b8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x000001c0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000001c8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x000001d0] */ 0x4c9d00cf, 0x10024821, // add r0, r0, r3; mul24 r1, r1, rb_pitch +++/* [0x000001d8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x000001e0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001e8] */ 0x949dc5c0, 0xd0025890, // and r2, r2, ~3; mov ra_x_base, r0 +++/* [0x000001f0] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x000001f8] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x00000200] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000208] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000210] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000218] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000220] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000228] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000230] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000238] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000240] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++// ::mc_filter_uv +++/* [0x00000248] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000250] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000258] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000260] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000268] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000270] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000278] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000280] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000288] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000290] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000298] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000002a0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002b0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002d0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000002d8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000002e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002e8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002f0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000002f8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000300] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000330] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000340] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000350] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000360] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000368] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000370] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000378] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000380] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000388] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000390] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000398] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003a0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :uvloop +++/* [0x000003a8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003b0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000003b8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003c0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003c8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003d0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003d8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003e0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000400] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000408] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++/* [0x00000410] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000420] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000428] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000430] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000438] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000440] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000448] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000450] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000458] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000460] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000468] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000470] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000478] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000480] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000488] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000490] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000498] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x000004a0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x000004a8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000004b0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000004b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000004c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000004c8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004d0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x000004d8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x000004e0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x000004e8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x000004f0] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x000004f8] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000500] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000508] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000510] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000518] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000520] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000528] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000530] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000538] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000540] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x00000548] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000550] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000558] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000560] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000568] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000570] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000578] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000580] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000588] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000590] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000598] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter +++/* [0x000005a0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000005a8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000005b0] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x000005b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000005c0] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x000005c8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000005d0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x000005d8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000005e0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x000005e8] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x000005f0] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x000005f8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000600] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000608] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000610] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000618] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000620] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000628] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000630] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000638] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000640] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000648] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000650] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000658] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000660] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000668] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000670] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000678] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000680] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000688] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000690] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000698] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000006b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000006d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000006f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000700] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000708] */ 0x000001d0, 0xf07809e7, // brr.anynn -, r:fast_path +++/* [0x00000710] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000718] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000720] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000728] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :loop +++/* [0x00000730] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000738] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000740] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000748] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000750] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000758] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000760] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000768] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000770] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000778] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000780] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000788] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000790] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000798] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000007a0] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000007a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000007b0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000007b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000007c0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000007c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000007d0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000007d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000007e0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000007e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000007f0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000007f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000800] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000808] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000810] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000818] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000820] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000828] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000830] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000838] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000840] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000848] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:loop +++/* [0x00000850] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00000858] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00000860] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00000868] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000870] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000878] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000880] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000888] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000890] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000898] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x000008a0] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000008a8] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x000008b0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000008b8] */ 0xfffffe58, 0xf06809e7, // brr.anyn -, r:loop +++/* [0x000008c0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x000008c8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000008d0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000008d8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000008e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000008e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000008f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// :fast_path +++/* [0x000008f8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :fast_loop +++/* [0x00000900] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000908] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000910] */ 0x95727d9b, 0x1004475f, // mov.ifz ra_y, ra_y_next ; mov rb31, r3 +++/* [0x00000918] */ 0x95690dbf, 0x10044623, // mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch +++/* [0x00000920] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000928] */ 0x929de5e4, 0x100248a1, // min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 +++/* [0x00000930] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000938] */ 0xec414c87, 0x10024e20, // add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 +++/* [0x00000940] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000948] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000950] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000958] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000960] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000968] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000970] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000978] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000980] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000988] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 +++/* [0x00000990] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000998] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x000009a0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x000009a8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000009b0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000009b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000009c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000009c8] */ 0xffffff18, 0xf06809e7, // brr.anyn -, r:fast_loop +++/* [0x000009d0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x000009d8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x000009e0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x000009e8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x000009f0] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x000009f8] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000a00] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000a08] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000a10] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000a18] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000a20] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000a28] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000a30] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000a38] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:fast_loop +++/* [0x00000a40] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x00000a48] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a50] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a60] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter_b +++/* [0x00000a78] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000a80] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000a88] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x00000a90] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000a98] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x00000aa0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000aa8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x00000ab0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000ab8] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x00000ac0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x00000ac8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x00000ad0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000ad8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000ae0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000ae8] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000af0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000af8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000b00] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000b08] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000b10] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000b18] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000b20] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000b28] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000b30] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000b38] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000b40] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000b48] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000b50] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000b58] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000b60] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000b68] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000b70] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00000b78] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000b80] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000b88] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000b90] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000b98] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000ba0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ba8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bb0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bb8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000bc0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bc8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bd0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bd8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000be0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000be8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bf0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bf8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000c00] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000c08] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000c10] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :bloop +++/* [0x00000c18] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000c20] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000c28] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000c30] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000c38] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000c40] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000c48] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000c50] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000c58] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000c60] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000c68] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000c70] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000c78] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000c80] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000c88] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000c90] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000c98] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000ca0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000ca8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000cb0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000cb8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000cc0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000cc8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000cd0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000cd8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000ce0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000ce8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000cf0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000cf8] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000d00] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000d08] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000d10] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000d18] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000d20] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000d28] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000d30] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:bloop +++/* [0x00000d38] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00000d40] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00000d48] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00000d50] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000d58] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000d60] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000d68] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000d70] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000d78] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000d80] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000d88] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000d90] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000d98] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000da0] */ 0x8fc8f3f6, 0xd0020867, // asr r1, r1, 15 ; mov -, vr_wait +++/* [0x00000da8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000db0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x00000db8] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:bloop +++/* [0x00000dc0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000dc8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00000dd0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x00000dd8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000de0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000de8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000df0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter_honly +++/* [0x00000df8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000e00] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000e08] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x00000e10] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000e18] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x00000e20] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000e28] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x00000e30] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000e38] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x00000e40] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x00000e48] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x00000e50] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000e58] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000e60] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000e68] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000e70] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000e78] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000e80] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000e88] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e90] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000e98] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000ea0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000ea8] */ 0x0c9de1c0, 0xd0021467, // add rb17, r0, -2 +++/* [0x00000eb0] */ 0x919c71c0, 0xd0024812, // shl r0, r0, 7 ; mov rb18,r0 +++/* [0x00000eb8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000ec0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000ec8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000ed0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000ed8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ee0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ee8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ef0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000ef8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f00] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f08] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f10] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000f18] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000f20] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000f28] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000f30] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :loop_honly +++/* [0x00000f38] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000f40] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000f48] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000f50] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000f58] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000f60] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000f68] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000f70] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000f78] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000f80] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000f88] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000f90] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000f98] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000fa0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000fa8] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000fb0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000fb8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000fc0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000fc8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000fd0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000fd8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000fe0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000fe8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000ff0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000ff8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001000] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001008] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 +++/* [0x00001010] */ 0x8d5927f6, 0x100269e1, // sub.setf -, r3, rb18 ; mov r1, ra22 +++/* [0x00001018] */ 0x559f2fc1, 0x100049e0, // mov -, vw_wait ; mul24 r0, r0, r1 +++/* [0x00001020] */ 0xfffffef8, 0xf06809e7, // brr.anyn -, r:loop_honly +++/* [0x00001028] */ 0x0f9cf1c0, 0xd0020827, // asr r0, r0, 15 +++/* [0x00001030] */ 0x129d61c0, 0x10020827, // min r0, r0, rb22 +++/* [0x00001038] */ 0x139c01c0, 0xd0020c27, // max vpm, r0, 0 +++/* [0x00001040] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001048] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001050] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001058] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_exit +++/* [0x00001060] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001068] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00001070] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001078] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001080] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001088] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001090] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001098] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000010a0] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_exit1 +++/* [0x000010a8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000010b0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010b8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010c0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010c8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000010d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000010e0] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_interrupt_exit +++/* [0x000010e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000010f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001100] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001108] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001110] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001118] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001120] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001128] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001130] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001138] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001140] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001148] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001150] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001158] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001160] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001168] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001170] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00001178] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_interrupt_exit4 +++/* [0x00001180] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001188] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001190] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001198] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011a0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011c0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000011c8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000011d0] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_interrupt_exit8 +++/* [0x000011d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000011e0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011e8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001200] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001208] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001210] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001218] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001220] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001228] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001230] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001238] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001240] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00001248] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_setup_uv +++/* [0x00001250] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00001258] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num +++/* [0x00001260] */ 0x15827d80, 0x10020767, // mov ra_y, unif +++/* [0x00001268] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif +++/* [0x00001270] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00001278] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base +++/* [0x00001280] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00001288] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x00001290] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x00001298] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000012a0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x000012a8] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x000012b0] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x000012b8] */ 0x00000040, 0xe0020567, // mov ra21, 64 +++/* [0x000012c0] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x000012c8] */ 0x00000008, 0xe00205e7, // mov ra23, 8 +++/* [0x000012d0] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x000012d8] */ 0x00000040, 0xe0021567, // mov rb21, 64 +++/* [0x000012e0] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x000012e8] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x000012f0] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x000012f8] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x00001300] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x00001308] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x00001310] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x00001318] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x00001320] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x00001328] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x00001330] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00001338] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00001340] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00001348] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00001350] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00001358] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00001360] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00001368] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001370] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00001378] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00001380] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00001388] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00001390] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00001398] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x000013a0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x000013a8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x000013b0] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x000013b8] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x000013c0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000013c8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x000013d0] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x000013d8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x000013e0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000013e8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x000013f0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000013f8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x00001400] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00001408] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00001410] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 +++/* [0x00001418] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00001420] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x00001428] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x00001430] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x00001438] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001440] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001448] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001450] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00001458] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00001460] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00001468] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001470] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00001478] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00001480] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++// ::mc_filter_uv_b +++/* [0x00001488] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00001490] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00001498] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000014a0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000014a8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000014b0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000014b8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000014c0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000014c8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000014d0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000014d8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000014e0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000014e8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000014f0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000014f8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00001500] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00001508] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00001510] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00001518] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00001520] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00001528] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00001530] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00001538] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00001540] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001548] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001550] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00001558] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00001560] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00001568] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001570] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001578] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001580] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001588] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00001590] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001598] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015a0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015a8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000015b0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015b8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015c0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015c8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000015d0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015d8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015e0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015e8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x000015f0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000015f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001600] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :uvloop_b +++/* [0x00001608] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001610] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00001618] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00001620] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001628] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00001630] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001638] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00001640] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00001648] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00001650] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00001658] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001660] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00001668] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++/* [0x00001670] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00001678] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00001680] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00001688] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00001690] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00001698] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000016a0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000016a8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000016b0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000016b8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000016c0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000016c8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000016d0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000016d8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x000016e0] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x000016e8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x000016f0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x000016f8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001700] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001708] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001710] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001718] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001720] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00001728] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00001730] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00001738] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00001740] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00001748] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00001750] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00001758] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00001760] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00001768] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00001770] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00001778] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00001780] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00001788] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00001790] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00001798] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x000017a0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000017a8] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x000017b0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000017b8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000017c0] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x000017c8] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x000017d0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000017d8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000017e0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000017e8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000017f0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000017f8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001800] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00001808] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001810] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_end +++}; +++#ifdef __HIGHC__ +++#pragma Align_to(8, rpi_shader) +++#endif ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++new file mode 100644 ++index 0000000..db971f4 ++--- /dev/null +++++ b/libavcodec/rpi_shader.h ++@@ -0,0 +1,20 @@ +++#ifndef rpi_shader_H +++#define rpi_shader_H +++ +++extern unsigned int rpi_shader[]; +++ +++#define mc_setup (rpi_shader + 0) +++#define mc_filter_uv (rpi_shader + 146) +++#define mc_filter (rpi_shader + 360) +++#define mc_filter_b (rpi_shader + 670) +++#define mc_filter_honly (rpi_shader + 894) +++#define mc_exit (rpi_shader + 1048) +++#define mc_exit1 (rpi_shader + 1066) +++#define mc_interrupt_exit (rpi_shader + 1082) +++#define mc_interrupt_exit4 (rpi_shader + 1120) +++#define mc_interrupt_exit8 (rpi_shader + 1142) +++#define mc_setup_uv (rpi_shader + 1172) +++#define mc_filter_uv_b (rpi_shader + 1314) +++#define mc_end (rpi_shader + 1542) +++ +++#endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++new file mode 100644 ++index 0000000..6851e83 ++--- /dev/null +++++ b/libavcodec/rpi_shader.qasm ++@@ -0,0 +1,1413 @@ +++# register allocation +++# +++# ra0...ra7 eight horizontal filter coefficients +++# +++# rb1...rb7 seven shifted copies of the current unfiltered row +++# +++# ra8...ra15 eight filtered rows of context (rb15 == most recent) +++# +++# (ra15 isn't clamped to zero - this happens during the +++# copy to ra14, and during its use in the vertical filter) +++# +++# rb8...rb15 eight vertical filter coefficients +++# +++# ra16 clipped(row start address+elem_num)&~3 +++# ra17 per-channel shifts +++# ra19 next ra17 +++# +++# rb16 pitch +++# rb17 height + 5 +++# rb18 height + 7 +++# rb19 next ra16 +++# +++# ra20 1 +++# ra21 64 +++# ra22 256 +++# ra23 8 +++# +++# rb20 0xffffff00 +++# rb21 64 +++# rb22 255 +++# rb23 24 +++# +++# rb24 vdw_setup_1(dst_pitch) +++# rb25 frame width-1 +++# rb26 height<<23 + width<<16 + vdw_setup_0 +++# rb27 vdw_setup_0 (depends on QPU number) +++# rb28 vpm_setup (depends on QPU number) +++# rb29 vdw_setup_1(dst_pitch-width) +++# rb30 frame height-1 +++# rb31 used as temp to count loop iterations +++# +++# ra24...ra30 15, 14, 13, 12, 11, 10, 9 +++# ra24 clipped(row start address+8+elem_num)&~3 +++# ra25 per-channel shifts 2 +++# ra26 next ra24 +++# ra27 next ra25 +++# ra28 next y +++# ra29 y for next texture access +++# +++# ra31 next kernel address +++ +++.set rb_frame_width_minus_1, rb25 +++.set rb_frame_height_minus_1, rb30 +++.set rb_pitch, rb16 +++.set ra_x_base, ra16 +++.set rb_x_base_next, rb19 +++.set ra_x2_base, ra24 +++.set ra_x2_base_next, ra26 +++.set ra_xshift, ra17 +++ +++.set ra_x2shift, ra25 +++.set ra_u2v_ref_offset, ra25 +++ +++.set ra_xshift_next, ra19 +++ +++.set ra_x2shift_next, ra27 +++.set ra_u2v_dst_offset, ra27 +++ +++.set ra_y_next, ra28 +++.set ra_y, ra29 +++ +++.set rb_const_64, rb21 +++ +++# mc_setup(next_kernel, x, y, ref_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1) +++::mc_setup +++ +++# Read starting kernel +++mov ra31, unif +++ +++# Load first request location +++add ra_x_base, unif, elem_num # Store x +++mov ra_y, unif # Store y +++mov ra_x2_base, unif # Store frame base +++ +++# Read image dimensions +++sub rb25,unif,1 +++sub rb30,unif,1 +++ +++# get source pitch +++mov rb16, unif +++ +++# get destination pitch +++mov r0, unif +++mov r1, vdw_setup_1(0) +++add rb24, r1, r0 +++ +++# load constants +++ +++mov ra20, 1 +++mov ra21, 64 +++mov ra22, 256 +++mov ra23, 8 +++ +++mov rb20, 0xffffff00 +++mov rb21, 64 +++mov rb22, 255 +++mov rb23, 24 +++ +++# touch vertical context to keep simulator happy +++ +++mov ra8, 0 +++mov ra9, 0 +++mov ra10, 0 +++mov ra11, 0 +++mov ra12, 0 +++mov ra13, 0 +++mov ra14, 0 +++mov ra15, 0 +++ +++# Compute part of VPM to use for DMA output +++mov r2, qpu_num +++and r2, r2, 15 +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later +++shl r0, r0, 5 +++add rb27, r0, r1 +++ +++# Compute part of VPM to save data into +++mov r2, qpu_num +++and r2, r2, 15 +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vpm_setup(0, 4, h8p(0, 0)) +++add rb28, r0, r1 +++ +++# Compute base address for first and second access +++#add r0, unif, elem_num # x +++mov r0, ra_x_base # Load x +++add r2, r0, 8 # x+8 +++max r0, r0, 0; mov r1, ra_y # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base # Load the frame base +++shl ra_xshift_next, r0, 3 +++max r2, r2, 0 +++add ra_y, r1, 1 +++min r2, r2, rb_frame_width_minus_1 +++shl ra_x2shift_next, r2, 3 +++max r1, r1, 0 # y +++min r1, r1, rb_frame_height_minus_1 +++add r0, r0, r3; mul24 r1, r1, rb_pitch +++add r2, r2, r3 +++and r0, r0, ~3 +++and r2, r2, ~3; mov ra_x_base, r0 +++# submit texture requests for first line +++add t0s, r0, r1 ; mov ra_x2_base, r2 +++add t0s, r2, r1 +++ +++# Dump padding words +++mov r0, unif +++mov r0, unif +++ +++# submit texture requests for second line +++max r1, ra_y, 0 +++min r1, r1, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 +++bra -, ra31 +++nop ; mul24 r1, r1, rb_pitch +++add t0s, r1, ra_x_base +++add t0s, r1, ra_x2_base +++ +++################################################################################ +++ +++# mc_filter_uv(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) +++ +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x_base, ra_x16_base point to the current coordinates for this block +++::mc_filter_uv +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base +++shl ra_xshift_next, r0, 3 +++sub r2, unif, r3 # compute offset from frame base u to frame base v +++add r0, r0, r3 +++and rb_x_base_next, r0, ~3 +++mov ra_y_next, r1 +++add ra_x2_base_next, rb_x_base_next, r2 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++asr rb15, r0, rb23; mul24 r0, r0, ra22 +++asr rb14, r0, rb23; mul24 r0, r0, ra22 +++asr rb13, r0, rb23; mul24 r0, r0, ra22 +++asr rb12, r0, rb23 +++ +++# r2 is elem_num +++# r3 is loop counter +++ +++mov r5rep, -8 +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++mov r3, 0 +++ +++:uvloop +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++sub r0, r2, r3 +++ +++mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++brr.anyn -, r:uvloop +++max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr r0, r0, 15 ; mov r1, ra21 +++min.setf ra15, r0, rb22 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r0, ra14, rb14 +++sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++sub.ifnn r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++brr.anyn -, r:uvloop +++asr r1, r1, 15 +++min r1, r1, rb22 +++max vpm, r1, 0 +++ +++# DMA out for U +++ +++mov vw_setup, rb26 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++# DMA out for V +++# We need to wait for the U to complete first, but have nothing useful to compute while we wait. +++# Could potentially push this write into the start of the next pipeline stage. +++mov r0, 16 +++mov -, vw_wait +++ +++bra -, ra31 +++add vw_setup, rb26, r0 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++################################################################################ +++ +++ +++# mc_filter(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) +++ +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x_base, ra_x16_base point to the current coordinates for this block +++::mc_filter +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++mov ra_x2shift, ra_x2shift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++add r2, r0, 8 # x+8 +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base +++shl ra_xshift_next, r0, 3 +++max r2, r2, 0 +++min r2, r2, rb_frame_width_minus_1 +++shl ra_x2shift_next, r2, 3 +++add r0, r0, r3 +++add r2, r2, r3 +++and rb_x_base_next, r0, ~3 +++and ra_x2_base_next, r2, ~3 +++mov ra_y_next, r1 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++asr rb15, r0, rb23; mul24 r0, r0, ra22 +++asr rb14, r0, rb23; mul24 r0, r0, ra22 +++asr rb13, r0, rb23; mul24 r0, r0, ra22 +++brr.anynn -, r:fast_path +++asr rb12, r0, rb23 # delay slot 1 +++ +++# r2 is elem_num +++# r3 is loop counter +++ +++mov r5rep, -8 # delay slot 2 +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] # delay slot 3 +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++## nop ; ldtmu0 # loop counter increment +++## shr r0, r4, ra17 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 ; mul24 r3, r0, ra0 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++## sub r2, r2, r3 ; ldtmu0 +++## +++## mov r0, ra22 +++## shr r0, r4, ra17 ; mul24 r2, r2, r0 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # apply horizontal filter +++## +++## asr r2, r2, 15 ; mul24 r3, r0, ra0 +++## min r2, r2, rb22 +++## max ra13, r2, 0 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++## sub r0, r2, r3 +++## +++## # apply horizontal filter +++## +++## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero +++## asr r0, r0, 15 +++## min r0, r0, rb22 +++## max ra14, r0, 0 +++## +++## +++## +++## +++## nop ; ldtmu0 # loop counter increment +++## shr r0, r4, ra17 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 ; mul24 r3, r0, ra0 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++## sub r0, r2, r3 +++## +++## # apply horizontal filter +++## +++## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero +++## asr r0, r0, 15 +++## min r0, r0, rb22 +++## max ra15, r0, 0 +++ +++ +++ +++ +++mov r3, 0 +++ +++:loop +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++sub r0, r2, r3 +++ +++mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++brr.anyn -, r:loop +++max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr r0, r0, 15 ; mov r1, ra21 +++min.setf ra15, r0, rb22 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r0, ra14, rb14 +++sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++sub.ifnn r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++brr.anyn -, r:loop +++asr r1, r1, 15 +++min r1, r1, rb22 +++max vpm, r1, 0 +++ +++# DMA out +++ +++bra -, ra31 +++mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long +++mov vw_setup, rb29 +++mov vw_addr, unif # start the VDW +++ +++#################################################### +++ +++:fast_path +++## nop ; ldtmu0 # loop counter increment +++## shr r0, r4, ra17 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 ; mul24 r3, r0, ra0 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## sub r2, r2, r3 ; ldtmu0 +++## +++## mov r0, ra22 +++## shr r0, r4, ra17 ; mul24 r2, r2, r0 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # apply horizontal filter +++## +++## asr r2, r2, 15 ; mul24 r3, r0, ra0 +++## min r2, r2, rb22 +++## max ra13, r2, 0 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## sub r0, r2, r3 +++## +++## # apply horizontal filter +++## +++## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero +++## asr r0, r0, 15 +++## min r0, r0, rb22 +++## max ra14, r0, 0 +++## +++## +++## +++## +++## nop ; ldtmu0 # loop counter increment +++## shr r0, r4, ra17 ; ldtmu0 +++## shr r1, r4, ra17 ; v8subs r0, r0, rb20 +++## add t0s, ra16, r5 ; v8subs r1, r1, rb20 +++## add ra16, ra16, rb16 ; mov t0s, ra16 +++## +++## # generate seven shifted versions +++## # interleave with scroll of vertical context +++## +++## mov r2, rb21 ; mul24 r3, r0, ra0 +++## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++## sub r0, r2, r3 +++## +++## # apply horizontal filter +++## +++## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero +++## asr r0, r0, 15 +++## min r0, r0, rb22 +++## max ra15, r0, 0 +++ +++ +++mov r3, 0 # This signifies the amount of unrolling +++ +++:fast_loop +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++# Due to pipelining we can only skip second pipeline instructions related to the fetched pixels +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_y, ra_y_next ; mov rb31, r3 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch +++ +++max r2, ra_y, 0 +++min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 # discard texture read +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++sub r0, r2, r3 ; mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++ +++brr.anyn -, r:fast_loop +++max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr r0, r0, 15 ; mov r1, ra21 +++min.setf ra15, r0, rb22 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r0, ra14, rb14 +++sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++sub.ifnn r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++brr.anyn -, r:fast_loop +++asr r1, r1, 15 +++min r1, r1, rb22 +++max vpm, r1, 0 +++ +++# DMA out +++ +++bra -, ra31 +++mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long +++mov vw_setup, rb29 +++mov vw_addr, unif # start the VDW +++ +++################################################################################ +++ +++# mc_filter_b(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) +++ +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x_base, ra_x16_base point to the current coordinates for this block +++::mc_filter_b +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++mov ra_x2shift, ra_x2shift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++add r2, r0, 8 # x+8 +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base +++shl ra_xshift_next, r0, 3 +++max r2, r2, 0 +++min r2, r2, rb_frame_width_minus_1 +++shl ra_x2shift_next, r2, 3 +++add r0, r0, r3 +++add r2, r2, r3 +++and rb_x_base_next, r0, ~3 +++and ra_x2_base_next, r2, ~3 +++mov ra_y_next, r1 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++# r0 is currently height<<7 +++# For vr_setup we want height<<20 (so 20-7=13 additional bits) +++shl r3, r0, 13 +++shl r3, r3, 8 # Mask off top 8 bits +++shr r3, r3, 8 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++# In a B frame, so also set up VPM read +++add vr_setup, r3, rb28 +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++asr rb15, r0, rb23; mul24 r0, r0, ra22 +++asr rb14, r0, rb23; mul24 r0, r0, ra22 +++asr rb13, r0, rb23; mul24 r0, r0, ra22 +++asr rb12, r0, rb23 +++ +++# r2 is elem_num +++# r3 is loop counter +++ +++mov r5rep, -8 +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++mov r3, 0 +++ +++:bloop +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++sub r0, r2, r3 +++ +++mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++brr.anyn -, r:bloop +++max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr r0, r0, 15 ; mov r1, ra21 +++min.setf ra15, r0, rb22 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r0, ra14, rb14 +++sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++sub.ifnn r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++asr r1, r1, 15 ; mov -, vr_wait +++min r1, r1, rb22 +++add r0, vpm, 1 # Blend in previous VPM contents at this location +++brr.anyn -, r:bloop +++max r1, r1, 0 +++add r1, r1, r0 +++shr vpm, r1, 1 +++ +++# DMA out +++ +++bra -, ra31 +++mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long +++mov vw_setup, rb29 +++mov vw_addr, unif # start the VDW +++ +++################################################################################ +++ +++# mc_filter_honly(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) +++# This filter only does horizontal filtering. +++# It is assumed that the region to fetch does not include extra rows above. +++ +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x_base, ra_x16_base point to the current coordinates for this block +++::mc_filter_honly +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++mov ra_x2shift, ra_x2shift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++add r2, r0, 8 # x+8 +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base +++shl ra_xshift_next, r0, 3 +++max r2, r2, 0 +++min r2, r2, rb_frame_width_minus_1 +++shl ra_x2shift_next, r2, 3 +++add r0, r0, r3 +++add r2, r2, r3 +++and rb_x_base_next, r0, ~3 +++and ra_x2_base_next, r2, ~3 +++mov ra_y_next, r1 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, -2 # Pipelining means we move data across 2 iterations early +++shl r0, r0, 7 ; mov rb18,r0 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++mov r0, unif +++ +++# r2 is elem_num +++# r3 is loop counter +++mov r5rep, -8 +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] # delay slot 3 +++mov r3, 0 +++ +++:loop_honly +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++sub r0, r2, r3 ; mov r3, rb31 +++ +++sub.setf -, r3, rb18 ; mov r1, ra22 +++ +++mov -, vw_wait ; mul24 r0, r0, r1 +++brr.anyn -, r:loop_honly +++asr r0, r0, 15 # delay 1 +++min r0, r0, rb22 # delay 2 +++max vpm, r0, 0 # delay 3 +++ +++# DMA out +++bra -, ra31 +++mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long +++mov vw_setup, rb29 +++mov vw_addr, unif # start the VDW +++ +++ +++################################################################################ +++ +++# mc_exit() +++ +++::mc_exit +++mov -, vw_wait # wait on the VDW +++ +++mov -,srel(0) +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++nop ; nop ; thrend +++nop ; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++::mc_exit1 +++mov -, vw_wait # wait on the VDW +++ +++#mov -,srel(1) +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++nop ; nop ; thrend +++mov interrupt, 1; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++# mc_interrupt_exit() +++::mc_interrupt_exit +++mov -, vw_wait # wait on the VDW +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++mov -,sacq(0) # 1 +++mov -,sacq(0) # 2 +++mov -,sacq(0) # 3 +++mov -,sacq(0) # 4 +++mov -,sacq(0) # 5 +++mov -,sacq(0) # 6 +++mov -,sacq(0) # 7 +++mov -,sacq(0) # 8 +++mov -,sacq(0) # 9 +++mov -,sacq(0) # 10 +++mov -,sacq(0) # 11 +++ +++nop ; nop ; thrend +++mov interrupt, 1; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++# mc_interrupt_exit4() +++::mc_interrupt_exit4 +++mov -, vw_wait # wait on the VDW +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++mov -,sacq(0) # 1 +++mov -,sacq(0) # 2 +++mov -,sacq(0) # 3 +++ +++nop ; nop ; thrend +++mov interrupt, 1; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++# mc_interrupt_exit8() +++::mc_interrupt_exit8 +++mov -, vw_wait # wait on the VDW +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++mov -,sacq(0) # 1 +++mov -,sacq(0) # 2 +++mov -,sacq(0) # 3 +++mov -,sacq(0) # 4 +++mov -,sacq(0) # 5 +++mov -,sacq(0) # 6 +++mov -,sacq(0) # 7 +++ +++nop ; nop ; thrend +++mov interrupt, 1; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++################################################################################ +++# mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1, pad2) +++::mc_setup_uv +++ +++# Read starting kernel +++mov ra31, unif +++ +++# Load first request location +++add ra_x_base, unif, elem_num # Store x +++mov ra_y, unif # Store y +++mov ra_x2_base, unif # Store frame u base +++nop +++sub ra_u2v_ref_offset, unif, ra_x2_base # Store offset to add to move from u to v in reference frame +++ +++# Read image dimensions +++sub rb25,unif,1 +++sub rb30,unif,1 +++ +++# get source pitch +++mov rb16, unif +++ +++# get destination pitch +++mov r0, unif +++mov r1, vdw_setup_1(0) +++add rb24, r1, r0 +++ +++# load constants +++ +++mov ra20, 1 +++mov ra21, 64 +++mov ra22, 256 +++mov ra23, 8 +++ +++mov rb20, 0xffffff00 +++mov rb21, 64 +++mov rb22, 255 +++mov rb23, 24 +++ +++# touch vertical context to keep simulator happy +++ +++mov ra8, 0 +++mov ra9, 0 +++mov ra10, 0 +++mov ra11, 0 +++mov ra12, 0 +++mov ra13, 0 +++mov ra14, 0 +++mov ra15, 0 +++ +++# Compute part of VPM to use for DMA output +++mov r2, qpu_num +++and r2, r2, 15 +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later +++shl r0, r0, 5 +++add rb27, r0, r1 +++ +++# Compute part of VPM to save data into +++mov r2, qpu_num +++and r2, r2, 15 +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vpm_setup(0, 4, h8p(0, 0)) +++add rb28, r0, r1 +++ +++# Compute base address for first and second access +++mov r0, ra_x_base # Load x +++max r0, r0, 0; mov r1, ra_y # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base # Load the frame base +++shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++add ra_y, r1, 1 +++add r0, r0, r3 +++and r0, r0, ~3 +++max r1, r1, 0 ; mov ra_x_base, r0 # y +++min r1, r1, rb_frame_height_minus_1 +++# submit texture requests for first line +++add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++add t0s, r0, r1 ; mov ra_x2_base, r2 +++add t0s, r2, r1 +++ +++# Dump padding words +++mov r0, unif +++mov r0, unif +++mov r0, unif +++ +++# submit texture requests for second line +++max r1, ra_y, 0 +++min r1, r1, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 +++bra -, ra31 +++nop ; mul24 r1, r1, rb_pitch +++add t0s, r1, ra_x_base +++add t0s, r1, ra_x2_base +++ +++ +++ +++################################################################################ +++ +++::mc_filter_uv_b +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base +++shl ra_xshift_next, r0, 3 +++sub r2, unif, r3 # compute offset from frame base u to frame base v +++add r0, r0, r3 +++and rb_x_base_next, r0, ~3 +++mov ra_y_next, r1 +++add ra_x2_base_next, rb_x_base_next, r2 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++ +++# r0 is currently height<<7 +++# For vr_setup we want height<<20 (so 20-7=13 additional bits) +++shl r3, r0, 13 +++shl r3, r3, 8 # Mask off top 8 bits +++shr r3, r3, 8 +++ +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++# In a B frame, so also set up VPM read +++add vr_setup, r3, rb28 +++ +++sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++asr rb15, r0, rb23; mul24 r0, r0, ra22 +++asr rb14, r0, rb23; mul24 r0, r0, ra22 +++asr rb13, r0, rb23; mul24 r0, r0, ra22 +++asr rb12, r0, rb23 +++ +++# r2 is elem_num +++# r3 is loop counter +++ +++mov r5rep, -8 +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++mov r3, 0 +++ +++:uvloop_b +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r2, rb21 ; mul24 r3, r0, ra0 +++nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++sub r0, r2, r3 +++ +++mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++brr.anyn -, r:uvloop_b +++max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr r0, r0, 15 ; mov r1, ra21 +++min.setf ra15, r0, rb22 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r0, ra14, rb14 +++sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++sub.ifnn r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++asr r1, r1, 15 +++min r1, r1, rb22 +++add r0, vpm, 1 # Blend in previous VPM contents at this location +++brr.anyn -, r:uvloop_b +++max r1, r1, 0 +++add r1, r1, r0 +++shr vpm, r1, 1 +++ +++ +++# DMA out for U +++ +++mov vw_setup, rb26 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++# DMA out for V +++# We need to wait for the U to complete first, but have nothing useful to compute while we wait. +++# Could potentially push this write into the start of the next pipeline stage. +++mov r0, 16 +++mov -, vw_wait +++ +++bra -, ra31 +++add vw_setup, rb26, r0 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++::mc_end ++diff --git a/libavcodec/rpi_user_vcsm.h b/libavcodec/rpi_user_vcsm.h ++new file mode 100644 ++index 0000000..fbebbbe ++--- /dev/null +++++ b/libavcodec/rpi_user_vcsm.h ++@@ -0,0 +1,425 @@ +++/* +++Copyright (c) 2012, Broadcom Europe Ltd +++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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE +++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 __USER_VCSM__H__INCLUDED__ +++#define __USER_VCSM__H__INCLUDED__ +++ +++/* VideoCore Shared Memory - user interface library. +++** +++** This library provides all the necessary abstraction for any application to +++** make use of the shared memory service which is distributed accross a kernel +++** driver and a videocore service. +++** +++** It is an application design decision to choose or not to use this service. +++** +++** The logical flow of operations that a user application needs to follow when +++** using this service is: +++** +++** 1) Initialize the service. +++** 2) Allocate shared memory blocks. +++** 3) Start using the allocated blocks. +++** - In order to gain ownership on a block, lock the allocated block, +++** locking a block returns a valid address that the user application +++** can access. +++** - When finished with using the block for the current execution cycle +++** or function, and so when giving up the ownership, unlock the block. +++** 4) A block can be locked/unlocked as many times required - within or outside +++** of - a specific execution context. +++** 5) To completely release an allocated block, free it. +++** 6) If the service is no longer required, terminate it. +++** +++** +++** Some generic considerations: +++ +++** Allocating memory blocks. +++** +++** Memory blocks can be allocated in different manners depending on the cache +++** behavior desired. A given block can either be: +++ +++** - Allocated in a non cached fashion all the way through host and videocore. +++** - Allocated in a cached fashion on host OR videocore. +++** - Allocated in a cached fashion on host AND videocore. +++** +++** It is an application decision to determine how to allocate a block. Evidently +++** if the application will be doing substantial read/write accesses to a given block, +++** it is recommended to allocate the block at least in a 'host cached' fashion for +++** better results. +++** +++** +++** Locking memory blocks. +++** +++** When the memory block has been allocated in a host cached fashion, locking the +++** memory block (and so taking ownership of it) will trigger a cache invalidation. +++** +++** For the above reason and when using host cached allocation, it is important that +++** an application properly implements the lock/unlock mechanism to ensure cache will +++** stay coherent, otherwise there is no guarantee it will at all be. +++** +++** It is possible to dynamically change the host cache behavior (ie cached or non +++** cached) of a given allocation without needing to free and re-allocate the block. +++** This feature can be useful for such application which requires access to the block +++** only at certain times and not otherwise. By changing the cache behavior dynamically +++** the application can optimize performances for a given duration of use. +++** Such dynamic cache behavior remapping only applies to host cache and not videocore +++** cache. If one requires to change the videocore cache behavior, then a new block +++** must be created to replace the old one. +++** +++** On successful locking, a valid pointer is returned that the application can use +++** to access to data inside the block. There is no guarantee that the pointer will +++** stay valid following the unlock action corresponding to this lock. +++** +++** +++** Unocking memory blocks. +++** +++** When the memory block has been allocated in a host cached fashion, unlocking the +++** memory block (and so forgiving its ownership) will trigger a cache flush unless +++** explicitely asked not to flush the cache for performances reasons. +++** +++** For the above reason and when using host cached allocation, it is important that +++** an application properly implements the lock/unlock mechanism to ensure cache will +++** stay coherent, otherwise there is no guarantee it will at all be. +++** +++** +++** A complete API is defined below. +++*/ +++ +++#ifdef __cplusplus +++extern "C" +++{ +++#endif +++ +++/* Different status that can be dumped. +++*/ +++typedef enum +++{ +++ VCSM_STATUS_VC_WALK_ALLOC = 0, // Walks *all* the allocation on videocore. +++ // Result of the walk is seen in the videocore +++ // log. +++ VCSM_STATUS_HOST_WALK_MAP, // Walks the *full* mapping allocation on host +++ // driver (ie for all processes). Result of +++ // the walk is seen in the kernel log. +++ VCSM_STATUS_HOST_WALK_PID_MAP, // Walks the per process mapping allocation on host +++ // driver (for current process). Result of +++ // the walk is seen in the kernel log. +++ VCSM_STATUS_HOST_WALK_PID_ALLOC, // Walks the per process host allocation on host +++ // driver (for current process). Result of +++ // the walk is seen in the kernel log. +++ VCSM_STATUS_VC_MAP_ALL, // Equivalent to both VCSM_STATUS_VC_WALK_ALLOC and +++ // VCSM_STATUS_HOST_WALK_MAP. +++ // +++ VCSM_STATUS_NONE, // Must be last - invalid. +++ +++} VCSM_STATUS_T; +++ +++/* Different kind of cache behavior. +++*/ +++typedef enum +++{ +++ VCSM_CACHE_TYPE_NONE = 0, // No caching applies. +++ VCSM_CACHE_TYPE_HOST, // Allocation is cached on host (user space). +++ VCSM_CACHE_TYPE_VC, // Allocation is cached on videocore. +++ VCSM_CACHE_TYPE_HOST_AND_VC, // Allocation is cached on both host and videocore. +++ +++} VCSM_CACHE_TYPE_T; +++ +++/* Initialize the vcsm processing. +++** +++** Must be called once before attempting to do anything else. +++** +++** Returns 0 on success, -1 on error. +++*/ +++int vcsm_init( void ); +++ +++ +++/* Terminates the vcsm processing. +++** +++** Must be called vcsm services are no longer needed, it will +++** take care of removing any allocation under the current process +++** control if deemed necessary. +++*/ +++void vcsm_exit( void ); +++ +++ +++/* Queries the status of the the vcsm. +++** +++** Triggers dump of various kind of information, see the +++** different variants specified in VCSM_STATUS_T. +++** +++** Pid is optional. +++*/ +++void vcsm_status( VCSM_STATUS_T status, int pid ); +++ +++ +++/* Allocates a non-cached block of memory of size 'size' via the vcsm memory +++** allocator. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++** +++** On success, the user must invoke vcsm_lock with the returned opaque +++** handle to gain access to the memory associated with the opaque handle. +++** When finished using the memory, the user calls vcsm_unlock_xx (see those +++** function definition for more details on the one that can be used). +++** +++** A well behaved application should make every attempt to lock/unlock +++** only for the duration it needs to access the memory data associated with +++** the opaque handle. +++*/ +++unsigned int vcsm_malloc( unsigned int size, char *name ); +++ +++ +++/* Allocates a cached block of memory of size 'size' via the vcsm memory +++** allocator, the type of caching requested is passed as argument of the +++** function call. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++** +++** On success, the user must invoke vcsm_lock with the returned opaque +++** handle to gain access to the memory associated with the opaque handle. +++** When finished using the memory, the user calls vcsm_unlock_xx (see those +++** function definition for more details on the one that can be used). +++** +++** A well behaved application should make every attempt to lock/unlock +++** only for the duration it needs to access the memory data associated with +++** the opaque handle. +++*/ +++unsigned int vcsm_malloc_cache( unsigned int size, VCSM_CACHE_TYPE_T cache, char *name ); +++ +++ +++/* Shares an allocated block of memory via the vcsm memory allocator. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++** +++** On success, the user must invoke vcsm_lock with the returned opaque +++** handle to gain access to the memory associated with the opaque handle. +++** When finished using the memory, the user calls vcsm_unlock_xx (see those +++** function definition for more details on the one that can be used). +++** +++** A well behaved application should make every attempt to lock/unlock +++** only for the duration it needs to access the memory data associated with +++** the opaque handle. +++*/ +++unsigned int vcsm_malloc_share( unsigned int handle ); +++ +++ +++/* Resizes a block of memory allocated previously by vcsm_alloc. +++** +++** Returns: 0 on success +++** -errno on error. +++** +++** The handle must be unlocked by user prior to attempting any +++** resize action. +++** +++** On error, the original size allocated against the handle +++** remains available the same way it would be following a +++** successful vcsm_malloc. +++*/ +++int vcsm_resize( unsigned int handle, unsigned int new_size ); +++ +++ +++/* Frees a block of memory that was successfully allocated by +++** a prior call the vcms_alloc. +++** +++** The handle should be considered invalid upon return from this +++** call. +++** +++** Whether any memory is actually freed up or not as the result of +++** this call will depends on many factors, if all goes well it will +++** be freed. If something goes wrong, the memory will likely end up +++** being freed up as part of the vcsm_exit process. In the end the +++** memory is guaranteed to be freed one way or another. +++*/ +++void vcsm_free( unsigned int handle ); +++ +++ +++/* Retrieves a videocore opaque handle from a mapped user address +++** pointer. The videocore handle will correspond to the actual +++** memory mapped in videocore. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++** +++** Note: the videocore opaque handle is distinct from the user +++** opaque handle (allocated via vcsm_malloc) and it is only +++** significant for such application which knows what to do +++** with it, for the others it is just a number with little +++** use since nothing can be done with it (in particular +++** for safety reason it cannot be used to map anything). +++*/ +++unsigned int vcsm_vc_hdl_from_ptr( void *usr_ptr ); +++ +++ +++/* Retrieves a videocore opaque handle from a opaque handle +++** pointer. The videocore handle will correspond to the actual +++** memory mapped in videocore. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++** +++** Note: the videocore opaque handle is distinct from the user +++** opaque handle (allocated via vcsm_malloc) and it is only +++** significant for such application which knows what to do +++** with it, for the others it is just a number with little +++** use since nothing can be done with it (in particular +++** for safety reason it cannot be used to map anything). +++*/ +++unsigned int vcsm_vc_hdl_from_hdl( unsigned int handle ); +++ +++ +++/* Retrieves a user opaque handle from a mapped user address +++** pointer. +++** +++** Returns: 0 on error +++** a non-zero opaque handle on success. +++*/ +++unsigned int vcsm_usr_handle( void *usr_ptr ); +++ +++ +++/* Retrieves a mapped user address from an opaque user +++** handle. +++** +++** Returns: 0 on error +++** a non-zero address on success. +++** +++** On success, the address corresponds to the pointer +++** which can access the data allocated via the vcsm_malloc +++** call. +++*/ +++void *vcsm_usr_address( unsigned int handle ); +++ +++ +++/* Locks the memory associated with this opaque handle. +++** +++** Returns: NULL on error +++** a valid pointer on success. +++** +++** A user MUST lock the handle received from vcsm_malloc +++** in order to be able to use the memory associated with it. +++** +++** On success, the pointer returned is only valid within +++** the lock content (ie until a corresponding vcsm_unlock_xx +++** is invoked). +++*/ +++void *vcsm_lock( unsigned int handle ); +++ +++ +++/* Locks the memory associated with this opaque handle. The lock +++** also gives a chance to update the *host* cache behavior of the +++** allocated buffer if so desired. The *videocore* cache behavior +++** of the allocated buffer cannot be changed by this call and such +++** attempt will be ignored. +++** +++** The system will attempt to honour the cache_update mode request, +++** the cache_result mode will provide the final answer on which cache +++** mode is really in use. Failing to change the cache mode will not +++** result in a failure to lock the buffer as it is an application +++** decision to choose what to do if (cache_result != cache_update) +++** +++** The value returned in cache_result can only be considered valid if +++** the returned pointer is non NULL. The cache_result pointer may be +++** NULL if the application does not care about the actual outcome of +++** its action with regards to the cache behavior change. +++** +++** Returns: NULL on error +++** a valid pointer on success. +++** +++** A user MUST lock the handle received from vcsm_malloc +++** in order to be able to use the memory associated with it. +++** +++** On success, the pointer returned is only valid within +++** the lock content (ie until a corresponding vcsm_unlock_xx +++** is invoked). +++*/ +++void *vcsm_lock_cache( unsigned int handle, +++ VCSM_CACHE_TYPE_T cache_update, +++ VCSM_CACHE_TYPE_T *cache_result ); +++ +++ +++/* Unlocks the memory associated with this user mapped address. +++** +++** Returns: 0 on success +++** -errno on error. +++** +++** After unlocking a mapped address, the user should no longer +++** attempt to reference it. +++*/ +++int vcsm_unlock_ptr( void *usr_ptr ); +++ +++ +++/* Unlocks the memory associated with this user mapped address. +++** Apply special processing that would override the otherwise +++** default behavior. +++** +++** If 'cache_no_flush' is specified: +++** Do not flush cache as the result of the unlock (if cache +++** flush was otherwise applicable in this case). +++** +++** Returns: 0 on success +++** -errno on error. +++** +++** After unlocking a mapped address, the user should no longer +++** attempt to reference it. +++*/ +++int vcsm_unlock_ptr_sp( void *usr_ptr, int cache_no_flush ); +++ +++ +++/* Unlocks the memory associated with this user opaque handle. +++** +++** Returns: 0 on success +++** -errno on error. +++** +++** After unlocking an opaque handle, the user should no longer +++** attempt to reference the mapped addressed once associated +++** with it. +++*/ +++int vcsm_unlock_hdl( unsigned int handle ); +++ +++ +++/* Unlocks the memory associated with this user opaque handle. +++** Apply special processing that would override the otherwise +++** default behavior. +++** +++** If 'cache_no_flush' is specified: +++** Do not flush cache as the result of the unlock (if cache +++** flush was otherwise applicable in this case). +++** +++** Returns: 0 on success +++** -errno on error. +++** +++** After unlocking an opaque handle, the user should no longer +++** attempt to reference the mapped addressed once associated +++** with it. +++*/ +++int vcsm_unlock_hdl_sp( unsigned int handle, int cache_no_flush ); +++ +++#ifdef __cplusplus +++} +++#endif +++ +++#endif /* __USER_VCSM__H__INCLUDED__ */ ++-- ++2.5.0 ++ ++ ++From 9018000735949ecb6640187dd2571753881edcfa Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Sat, 2 May 2015 21:15:37 +0100 ++Subject: [PATCH 04/68] First working version with uncached memory ++ ++--- ++ libavcodec/hevc.c | 61 +++++- ++ libavcodec/hevc.h | 12 +- ++ libavcodec/hevc_cabac.c | 39 +++- ++ libavcodec/hevc_filter.c | 16 ++ ++ libavcodec/hevcpred_template.c | 6 + ++ libavcodec/rpi_hevc_transform.h | 422 +++++++++++++++++++++++++++++++++++++++- ++ libavcodec/rpi_hevc_transform.s | 153 +++++++++++++-- ++ libavcodec/rpi_qpu.c | 72 +++++++ ++ libavcodec/rpi_qpu.h | 1 + ++ 9 files changed, 736 insertions(+), 46 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 681e9fd..79678ea 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -45,6 +45,8 @@ ++ #include "rpi_qpu.h" ++ #endif ++ +++// #define DISABLE_MC +++ ++ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ ++ /** ++@@ -1068,11 +1070,15 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } +++ printf("Cross component not supported\n"); // TODO +++ exit(-1); ++ s->hevcdsp.transform_add[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++ ++ if (lc->tu.cross_pf) { +++ printf("Cross component not supported\n"); // TODO +++ exit(-1); ++ hls_cross_component_pred(s, 1); ++ } ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++@@ -1101,6 +1107,8 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } +++ printf("Cross component not supported\n"); // TODO +++ exit(-1); ++ s->hevcdsp.transform_add[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++@@ -1398,6 +1406,10 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ int idx = ff_hevc_pel_weight[block_w]; ++ +++#ifdef DISABLE_MC +++ return; +++#endif +++ ++ x_off += mv->x >> 2; ++ y_off += mv->y >> 2; ++ src += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift)); ++@@ -1468,6 +1480,10 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ uint8_t *src0 = ref0->data[0] + y_off0 * src0stride + (int)((unsigned)x_off0 << s->ps.sps->pixel_shift); ++ uint8_t *src1 = ref1->data[0] + y_off1 * src1stride + (int)((unsigned)x_off1 << s->ps.sps->pixel_shift); ++ +++#ifdef DISABLE_MC +++ return; +++#endif +++ ++ if (x_off0 < QPEL_EXTRA_BEFORE || y_off0 < QPEL_EXTRA_AFTER || ++ x_off0 >= pic_width - block_w - QPEL_EXTRA_AFTER || ++ y_off0 >= pic_height - block_h - QPEL_EXTRA_AFTER) { ++@@ -1553,6 +1569,10 @@ static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ intptr_t _mx = mx << (1 - hshift); ++ intptr_t _my = my << (1 - vshift); ++ +++#ifdef DISABLE_MC +++ return; +++#endif +++ ++ x_off += mv->x >> (2 + hshift); ++ y_off += mv->y >> (2 + vshift); ++ src0 += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift)); ++@@ -1617,6 +1637,10 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF ++ int hshift = s->ps.sps->hshift[1]; ++ int vshift = s->ps.sps->vshift[1]; ++ +++#ifdef DISABLE_MC +++ return; +++#endif +++ ++ intptr_t mx0 = av_mod_uintp2(mv0->x, 2 + hshift); ++ intptr_t my0 = av_mod_uintp2(mv0->y, 2 + vshift); ++ intptr_t mx1 = av_mod_uintp2(mv1->x, 2 + hshift); ++@@ -2356,6 +2380,22 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ } ++ ++ #ifdef RPI +++static void rpi_execute_transform(HEVCContext *s) +++{ +++ int i=2; +++ //int j; +++ //int16_t *coeffs = s->coeffs_buf_arm[i]; +++ //for(j=s->num_coeffs[i]; j > 0; j-= 16*16, coeffs+=16*16) { +++ // s->hevcdsp.idct[4-2](coeffs, 16); +++ //} +++ +++ //gpu_cache_flush(&s->coeffs_buf[i]); +++ vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf[i].vc, s->num_coeffs[i] >> 8, 0, 0, 0); +++ +++ for(i=0;i<4;i++) +++ s->num_coeffs[i] = 0; +++} +++ ++ static void rpi_execute_pred_cmds(HEVCContext *s) ++ { ++ int i; ++@@ -2376,7 +2416,6 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ } ++ } ++ s->num_pred_cmds = 0; ++- s->num_coeffs = 0; ++ } ++ #endif ++ ++@@ -2423,7 +2462,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ #ifdef RPI ++- if (x_ctb + ctb_size >= s->ps.sps->width) { +++ if (1 || x_ctb + ctb_size >= s->ps.sps->width) { // TODO watch out for deblocking! +++ rpi_execute_transform(s); ++ rpi_execute_pred_cmds(s); ++ } ++ #endif ++@@ -3168,7 +3208,9 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ av_freep(&s->unif_mv_cmds); ++ av_freep(&s->unif_xfm_cmds); ++ av_freep(&s->univ_pred_cmds); ++- av_freep(&s->coeffs_buf); +++ for(i = 0; i < 4; i++) { +++ gpu_free(&s->coeffs_buf[i]); +++ } ++ #endif ++ ++ for (i = 0; i < 3; i++) { ++@@ -3240,13 +3282,16 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->univ_pred_cmds = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); ++ if (!s->univ_pred_cmds) ++ goto fail; ++- s->coeffs_buf = av_mallocz(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16); ++- if (!s->coeffs_buf) ++- goto fail; +++ for(i = 0; i < 4; i++) { +++ gpu_malloc_uncached(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16, &s->coeffs_buf[i]); // TODO slim this down and share across sizes +++ s->coeffs_buf_arm[i] = (int16_t*) s->coeffs_buf[i].arm; +++ if (!s->coeffs_buf_arm[i]) +++ goto fail; +++ } ++ s->enable_rpi = 0; ++ ++ // A little test program ++- { +++ /*{ ++ GPU_MEM_PTR_T p; ++ int err = gpu_malloc_cached(16, &p); ++ short *q = (short *)p.arm; ++@@ -3267,7 +3312,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ printf(")\n"); ++ gpu_free(&p); ++ goto fail; // Early out ++- } +++ }*/ ++ ++ #endif ++ ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 71174af..1e4c34c 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -39,6 +39,11 @@ ++ #include "thread.h" ++ #include "videodsp.h" ++ +++// define RPI to split the CABAC/prediction/transform into separate stages +++#ifdef RPI +++#include "rpi_qpu.h" +++#endif +++ ++ #define MAX_DPB_SIZE 16 // A.4.1 ++ #define MAX_REFS 16 ++ ++@@ -882,11 +887,12 @@ typedef struct HEVCContext { ++ HEVCMvCmd *unif_mv_cmds; ++ HEVCXfmCmd *unif_xfm_cmds; ++ HEVCPredCmd *univ_pred_cmds; ++- int16_t *coeffs_buf; ++- int num_mv_cmds; +++ GPU_MEM_PTR_T coeffs_buf[4]; +++ int16_t *coeffs_buf_arm[4]; +++ int num_coeffs[4]; ++ int num_xfm_cmds; +++ int num_mv_cmds; ++ int num_pred_cmds; ++- int num_coeffs; ++ #endif ++ ++ uint8_t *cabac_state; ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index c0fdfad..a7561bd 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1031,6 +1031,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ int vshift = s->ps.sps->vshift[c_idx]; ++ uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride + ++ ((x0 >> hshift) << s->ps.sps->pixel_shift)]; +++ int use_vpu = s->enable_rpi && !lc->cu.cu_transquant_bypass_flag && !transform_skip_flag && !lc->tu.cross_pf && log2_trafo_size==4; ++ int16_t *coeffs = (int16_t*)(c_idx ? lc->edge_emu_buffer2 : lc->edge_emu_buffer); ++ uint8_t significant_coeff_group_flag[8][8] = {{0}}; ++ int explicit_rdpcm_flag = 0; ++@@ -1044,6 +1045,18 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ uint8_t dc_scale; ++ int pred_mode_intra = (c_idx == 0) ? lc->tu.intra_pred_mode : ++ lc->tu.intra_pred_mode_c; +++#ifdef RPI +++ if (s->enable_rpi) { +++ int n = trafo_size * trafo_size; +++ if (use_vpu) { +++ coeffs = s->coeffs_buf_arm[log2_trafo_size - 2] + s->num_coeffs[log2_trafo_size - 2]; +++ s->num_coeffs[log2_trafo_size - 2] += n; +++ } else { +++ coeffs = s->coeffs_buf_arm[0] + s->num_coeffs[0]; +++ s->num_coeffs[0] += n; +++ } +++ } +++#endif ++ ++ memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); ++ ++@@ -1488,6 +1501,24 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) { ++ s->hevcdsp.idct_4x4_luma(coeffs); ++ } else { +++#ifdef RPI +++ if (!use_vpu) { +++ int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y); +++ if (max_xy == 0) +++ s->hevcdsp.idct_dc[log2_trafo_size-2](coeffs); +++ else { +++ int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4; +++ if (max_xy < 4) +++ col_limit = FFMIN(4, col_limit); +++ else if (max_xy < 8) +++ col_limit = FFMIN(8, col_limit); +++ else if (max_xy < 12) +++ col_limit = FFMIN(24, col_limit); +++ +++ s->hevcdsp.idct[log2_trafo_size-2](coeffs, col_limit); +++ } +++ } +++#else ++ int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y); ++ if (max_xy == 0) ++ s->hevcdsp.idct_dc[log2_trafo_size-2](coeffs); ++@@ -1501,6 +1532,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ col_limit = FFMIN(24, col_limit); ++ s->hevcdsp.idct[log2_trafo_size-2](coeffs, col_limit); ++ } +++#endif ++ } ++ } ++ if (lc->tu.cross_pf) { ++@@ -1512,14 +1544,11 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } ++ #ifdef RPI ++ if (s->enable_rpi) { ++- int16_t *c = s->coeffs_buf + s->num_coeffs; ++- int n = trafo_size * trafo_size; ++ HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; ++- memcpy(c, coeffs, n * sizeof(int16_t)); // TODO change pointer earlier and we can avoid this copy ++- s->num_coeffs += n; +++ //memcpy(coeffs2, coeffs, sizeof(int16_t) * trafo_size * trafo_size); // TODO ++ cmd->type = RPI_PRED_TRANSFORM_ADD; ++ cmd->size = log2_trafo_size; ++- cmd->buf = c; +++ cmd->buf = coeffs; ++ cmd->dst = dst; ++ cmd->stride = stride; ++ return; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 1f33b0c..e4c3da7 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -22,6 +22,10 @@ ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ +++//#define DISABLE_SAO +++//#define DISABLE_DEBLOCK +++//#define DISABLE_STRENGTHS +++ ++ #include "libavutil/common.h" ++ #include "libavutil/internal.h" ++ ++@@ -273,6 +277,10 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) ++ edges[2] = x_ctb == s->ps.sps->ctb_width - 1; ++ edges[3] = y_ctb == s->ps.sps->ctb_height - 1; ++ +++#ifdef DISABLE_SAO +++ return; +++#endif +++ ++ if (restore) { ++ if (!edges[0]) { ++ left_tile_edge = no_tile_filter && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1]]; ++@@ -496,6 +504,10 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->ps.sps->pcm.loop_filter_disable_flag) || ++ s->ps.pps->transquant_bypass_enable_flag; ++ +++#ifdef DISABLE_DEBLOCK +++ return; +++#endif +++ ++ if (x0) { ++ left_tc_offset = s->deblock[ctb - 1].tc_offset; ++ left_beta_offset = s->deblock[ctb - 1].beta_offset; ++@@ -726,6 +738,10 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ int boundary_upper, boundary_left; ++ int i, j, bs; ++ +++#ifdef DISABLE_STRENGTHS +++ return; +++#endif +++ ++ boundary_upper = y0 > 0 && !(y0 & 7); ++ if (boundary_upper && ++ ((!s->sh.slice_loop_filter_across_slices_enabled_flag && ++diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c ++index 6ae87cc..71c6d52 100644 ++--- a/libavcodec/hevcpred_template.c +++++ b/libavcodec/hevcpred_template.c ++@@ -20,6 +20,8 @@ ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ +++//#define DISABLE_INTRA +++ ++ #include "libavutil/pixdesc.h" ++ ++ #include "bit_depth_template.c" ++@@ -114,6 +116,10 @@ do { \ ++ int top_right_size = (FFMIN(x0 + 2 * size_in_luma_h, s->ps.sps->width) - ++ (x0 + size_in_luma_h)) >> hshift; ++ +++#ifdef DISABLE_INTRA +++ return; +++#endif +++ ++ if (s->ps.pps->constrained_intra_pred_flag == 1) { ++ int size_in_luma_pu_v = PU(size_in_luma_v); ++ int size_in_luma_pu_h = PU(size_in_luma_h); ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++index 85a9102..c0c279f 100644 ++--- a/libavcodec/rpi_hevc_transform.h +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -3,11 +3,11 @@ unsigned char rpi_hevc_transform [] = { ++ 3, ++ 3, ++ 232, ++-128, +++32, ++ 0, ++ 0, ++ 0, ++-20, +++12, ++ 248, ++ 0, ++ 136, ++@@ -56,9 +56,9 @@ unsigned char rpi_hevc_transform [] = { ++ 5, ++ 232, ++ 0, ++-0, ++ 8, ++ 0, +++0, ++ 128, ++ 69, ++ 113, ++@@ -108,8 +108,8 @@ unsigned char rpi_hevc_transform [] = { ++ 128, ++ 2, ++ 0, ++-248, ++-62, +++8, +++2, ++ 0, ++ 128, ++ 144, ++@@ -123,13 +123,13 @@ unsigned char rpi_hevc_transform [] = { ++ 3, ++ 32, ++ 8, ++-16, +++20, ++ 0, ++ 76, ++ 254, ++ 48, ++ 192, ++-9, +++4, ++ 4, ++ 32, ++ 8, ++@@ -155,14 +155,46 @@ unsigned char rpi_hevc_transform [] = { ++ 192, ++ 41, ++ 3, ++-68, +++70, +++192, +++80, +++7, +++164, +++255, +++36, +++204, +++96, +++2, +++0, +++248, +++62, +++0, +++3, +++255, +++55, +++208, +++120, +++3, +++224, +++3, +++190, +++11, +++16, +++139, +++246, +++91, +++0, +++103, +++90, +++0, +++70, ++ 192, ++ 80, ++ 7, ++ 164, ++ 255, ++ 36, ++-220, +++204, ++ 96, ++ 2, ++ 0, ++@@ -182,7 +214,7 @@ unsigned char rpi_hevc_transform [] = { ++ 16, ++ 139, ++ 246, ++-83, +++91, ++ 0, ++ 103, ++ 90, ++@@ -209,4 +241,374 @@ unsigned char rpi_hevc_transform [] = { ++ 96, ++ 90, ++ 0, +++169, +++3, +++3, +++232, +++32, +++0, +++0, +++0, +++12, +++248, +++0, +++136, +++0, +++0, +++192, +++248, +++0, +++0, +++64, +++232, +++0, +++2, +++0, +++0, +++12, +++248, +++0, +++168, +++0, +++0, +++192, +++248, +++0, +++0, +++3, +++232, +++128, +++0, +++0, +++0, +++7, +++232, +++0, +++2, +++0, +++0, +++4, +++232, +++64, +++0, +++0, +++0, +++5, +++232, +++0, +++8, +++0, +++0, +++57, +++239, +++224, +++247, +++255, +++255, +++72, +++192, +++95, +++207, +++88, +++122, +++88, +++124, +++137, +++64, +++26, +++64, +++161, +++64, +++152, +++64, +++128, +++144, +++31, +++0, +++72, +++232, +++32, +++0, +++0, +++0, +++65, +++232, +++32, +++0, +++0, +++0, +++128, +++144, +++23, +++0, +++145, +++64, +++168, +++64, +++128, +++144, +++19, +++0, +++72, +++232, +++32, +++0, +++0, +++0, +++65, +++232, +++32, +++0, +++0, +++0, +++128, +++144, +++11, +++0, +++74, +++232, +++0, +++8, +++0, +++0, +++242, +++140, +++229, +++192, +++57, +++239, +++32, +++8, +++0, +++0, +++41, +++3, +++12, +++248, +++0, +++128, +++0, +++0, +++192, +++8, +++4, +++0, +++12, +++248, +++0, +++132, +++64, +++0, +++192, +++8, +++4, +++0, +++0, +++96, +++255, +++159, +++131, +++255, +++0, +++232, +++0, +++4, +++0, +++0, +++255, +++159, +++142, +++255, +++4, +++255, +++48, +++204, +++16, +++3, +++224, +++251, +++62, +++0, +++5, +++255, +++51, +++204, +++128, +++3, +++224, +++251, +++16, +++0, +++77, +++254, +++51, +++204, +++9, +++4, +++224, +++251, +++0, +++0, +++128, +++64, +++6, +++232, +++64, +++0, +++0, +++0, +++140, +++248, +++47, +++0, +++0, +++0, +++224, +++99, +++0, +++0, +++4, +++254, +++0, +++144, +++128, +++2, +++0, +++8, +++2, +++0, +++32, +++247, +++240, +++207, +++16, +++3, +++32, +++247, +++176, +++207, +++17, +++3, +++32, +++247, +++112, +++207, +++18, +++3, +++32, +++247, +++48, +++207, +++19, +++3, +++32, +++247, +++240, +++206, +++20, +++3, +++32, +++247, +++176, +++206, +++21, +++3, +++32, +++247, +++112, +++206, +++22, +++3, +++32, +++247, +++48, +++206, +++23, +++3, +++32, +++247, +++240, +++205, +++24, +++3, +++32, +++247, +++176, +++205, +++25, +++3, +++32, +++247, +++112, +++205, +++26, +++3, +++32, +++247, +++48, +++205, +++27, +++3, +++32, +++247, +++240, +++204, +++28, +++3, +++32, +++247, +++176, +++204, +++29, +++3, +++32, +++247, +++112, +++204, +++30, +++3, +++32, +++247, +++48, +++204, +++31, +++3, +++5, +++255, +++51, +++204, +++128, +++3, +++224, +++251, +++16, +++0, +++77, +++254, +++51, +++204, +++9, +++4, +++224, +++251, +++0, +++0, +++0, +++237, +++0, +++4, +++0, +++0, +++140, +++248, +++47, +++0, +++0, +++0, +++224, +++99, +++0, +++0, +++90, +++0, ++ }; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++index 5e2728d..1e389c7 100644 ++--- a/libavcodec/rpi_hevc_transform.s +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -58,13 +58,6 @@ ++ # ++ # ++ ++-test_add: ++- vldh HX(0,0),(r0) ++- vadd HX(0,0),HX(0,0),10 ++- vsth HX(0,0),(r0) ++- mov r0,7 # return value ++- b lr ++- ++ # Columns are transformed first ++ # ++ # Store top left half of transMatrix2 in ++@@ -79,7 +72,7 @@ test_add: ++ # ++ ++ ++-# hevc_trans_16x16(short *transMatrix2, short *coeffs, int num) +++# hevc_trans_16x16(short *transMatrix2, short *coeffs, int num) # TODO add size so we can branch to correct implementation (or perhaps have coeffs32 and num32 as secondary inputs!) ++ # transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) ++ # coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) ++ # num: number of 16x16 transforms to be done ++@@ -87,17 +80,17 @@ test_add: ++ hevc_trans_16x16: ++ push r6-r15, lr # TODO cut down number of used registers ++ ++- mov r3, 2*32*2 # Twice Stride of transMatrix2 in bytes ++- vld HX(32++,0),(r0 += r3) REP 16 # This is the 16x16 matrix, a transform is equivalent to multiplying input row vector * matrix +++ mov r3, 16*2 # Stride of transMatrix2 in bytes +++ vldh HX(32++,0),(r0 += r3) REP 16 # This is the 16x16 matrix, a transform is equivalent to multiplying input row vector * matrix ++ # Now use r0 to describe which matrix we are working on. ++ # Allows us to prefetch the next block of coefficients for efficiency. ++ mov r0,0 # This describes the location where we read our coefficients from ++- mov r3,16*2 # Stride of coefficients in bytes +++ mov r3,16*2 # Stride of coefficients in bytes (TODO remove) ++ mov r7,16*16*2 # Total block size ++ mov r8,64*16 # Value used to swap from current to next VRF location ++ vldh HX(0++,0)+r0,(r1 += r3) REP 16 ++ mov r4,64 # Constant used for rounding first pass ++- mov r5,1<<19 # Constant used for rounding second pass +++ mov r5,1<<11 # Constant used for rounding second pass ++ ++ # At start of block r0,r1 point to the current block (that has already been loaded) ++ block_loop: ++@@ -113,12 +106,12 @@ block_loop: ++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r4 REP 16 # Now add on rounding, shift down by 7, and saturate ++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # 9+7=16 so this ends up with the output saturated and in the top half of the word. ++ vasl HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # This should be saturating, but the instruction above does not assemble? ++- vmov VX(0,0++), HX(0++,32) REP 16 # For simplicity transpose this back to the original position +++ vmov VX(0,0++)+r0, HX(0++,32)+r0 REP 16 # For simplicity transpose this back to the original position ++ ++ bl col_trans_16 ++- vadd HY(0++,0)+r0,HY(0++,0)+r0,r4 REP 16 # Now add on rounding, shift down by 7, and saturate ++- #vsasls HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # 9+7=16 so this ends up with the output saturated and in the top half of the word. ++- vasl HY(0++,0)+r0,HY(0++,0)+r0,9 REP 16 # This should be saturating, but the instruction above does not assemble? +++ vadd HY(0++,0)+r0,HY(0++,0)+r0,r5 REP 16 # Now add on rounding, shift down by 7, and saturate +++ #vsasls HY(0++,0)+r0,HY(0++,0)+r0,4 REP 16 # 4+12=16 so this ends up with the output saturated and in the top half of the word. +++ vasl HY(0++,0)+r0,HY(0++,0)+r0,4 REP 16 # This should be saturating, but the instruction above does not assemble? (Probably because it ends with ls which is interpreted as a condition flag) ++ ++ # Save results - note there has been a transposition during the processing so we save columns ++ vsth VX(0,32++)+r0, (r1 += r3) REP 16 ++@@ -132,16 +125,136 @@ block_loop: ++ ++ # r1,r2,r3 r7,r8 should be preserved ++ # HX(0++,0)+r0 is the block to be transformed ++-# HX(32++,0) is the 16x16 matrix of transform coefficients +++# HX(32++,0)+r6 is the 16x16 matrix of transform coefficients ++ # Use HY(48,0) for intermediate results ++ # r0 can be used, but should be returned to its original value at the end ++ col_trans_16: ++- add r4,r0,16 # Final value for this loop +++ add r6,r0,16 # Final value for this loop ++ col_trans_16_loop: ++ # First compute partial products for a single column ++- vmul32s VY(48,0++), VX(0,0)+r0, VX(32,0++) REP 16 +++ vmul32s HY(48++,0), VX(0,0)+r0, VX(32,0++) REP 16 ++ # Then sum up the results and place back ++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC ++- addcmpblt r0,1,r4,col_trans_16_loop +++ addcmpblt r0,1,r6,col_trans_16_loop ++ sub r0,16 # but r0 back to its original value ++ b lr +++ +++col_trans_odd_16: +++ add r6,r0,16 # Final value for this loop +++col_trans_odd_16_loop: +++ # First compute partial products for a single column +++ vmul32s HY(48++,0), VX(0,0)+r0, VX(32,0++) REP 16 +++ # Then sum up the results and place back +++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC +++ addcmpblt r0,1,r6,col_trans_odd_16_loop +++ sub r0,16 # but r0 back to its original value +++ b lr +++ +++ +++test_add: +++ vldh HX(0,0),(r0) +++ vadd HX(0,0),HX(0,0),10 +++ vsth HX(0,0),(r0) +++ mov r0,7 # return value +++ b lr +++ +++# hevc_trans_32x32(short *transMatrix2, short *coeffs, int num) +++# transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) Even followed by odd +++# coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) +++# num: number of 16x16 transforms to be done +++# +++hevc_trans_32x32: +++ push r6-r15, lr # TODO cut down number of used registers +++ +++ # Fetch transform matrices +++ mov r3, 16*2 # Stride of transMatrix2 in bytes (and of coefficients) +++ vldh HX(32++,0),(r0 += r3) REP 16 # This is the even 16x16 matrix +++ add r0, 16*16*2 +++ vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix +++ +++ mov r3, 32*2*2 # Stride used to fetch alternate rows of our input coefficient buffer +++ mov r7, 16*16*2 # Total block size +++ mov r4, 64 # Constant used for rounding first pass +++ mov r5, 1<<11 # Constant used for rounding second pass +++ sub sp,sp,32*32*2+32 # Allocate some space on the stack for us to store 32*32 shorts as temporary results (needs to be aligned) +++ # set r8 to 32byte aligned stack pointer +++ add r8,sp,31 +++ lsr r8,5 +++ lsl r8,5 +++ mov r9,r8 # Backup of the temporary storage +++ mov r10,r1 # Backup of the coefficient buffer +++block_loop32: +++ +++ # COLUMN TRANSFORM +++ # Transform the first 16 columns +++ mov r1,r10 # Input Coefficient buffer +++ mov r8,r9 # Output temporary storage +++ bl trans32 +++ # Transform the second 16 columns +++ add r8,32 +++ add r1,32 +++ bl trans32 +++ +++ # ROW TRANSFORM +++ mov r1,r9 # Input temporary storage +++ mov r8,r10 # Output Coefficient buffer +++ bl trans32 +++ # Transform the second 16 columns +++ add r8,32 +++ add r1,32 +++ bl trans32 +++ +++ add r10, 32*32*2 # move onto next block of coefficients +++ addcmpbgt r2,-1,0,block_loop32 +++ +++ add sp,sp,32*32*2+32 # Restore stack +++ +++ pop r6-r15, pc +++ +++trans32: +++ # We can no longer afford the VRF space to do prefetching when doing 32x32 +++ # Fetch the even rows +++ vldh HX(0++,0)+r0,(r1 += r3) REP 16 +++ # Fetch the odd rows +++ vldh HX(16++,0)+r0,64(r1 += r3) REP 16 # First odd row is 32 shorts ahead of r1 +++ +++ # Transform the even rows using even matrix +++ mov r0, 0 # Even rows +++ bl col_trans_16 +++ +++ # Now transform the odd rows using odd matrix +++ mov r0, 64*16 # Odd rows +++ bl col_trans_odd_16 +++ +++ # Now apply butterfly to compute the first 16 results +++ vadd HY(48++,0),HY(0++,0),HY(16++,0) REP 16 +++ vadd HY(48++,0),HY(48++,0),r4 REP 32 # add on rounding, +++ vasl HY(48++,0),HY(48++,0),9 REP 32 # shift down by 7, and saturate +++ # 16bit results now in HX(48,32) +++ mov r0,r8 +++ mov r6,32*2 +++ vsth VX(48,32++),(r0+=r6) REP 16 +++ vmov VX(0,0++)+r0, HX(0++,32)+r0 REP 16 # Store transposed +++ +++ # Now apply butterfly to compute the second 16 results (in reverse order) +++ vsub HY(63,0),HY(0,0),HY(16,0) +++ vsub HY(62,0),HY(0,0),HY(17,0) +++ vsub HY(61,0),HY(0,0),HY(18,0) +++ vsub HY(60,0),HY(0,0),HY(19,0) +++ vsub HY(59,0),HY(0,0),HY(20,0) +++ vsub HY(58,0),HY(0,0),HY(21,0) +++ vsub HY(57,0),HY(0,0),HY(22,0) +++ vsub HY(56,0),HY(0,0),HY(23,0) +++ vsub HY(55,0),HY(0,0),HY(24,0) +++ vsub HY(54,0),HY(0,0),HY(25,0) +++ vsub HY(53,0),HY(0,0),HY(26,0) +++ vsub HY(52,0),HY(0,0),HY(27,0) +++ vsub HY(51,0),HY(0,0),HY(28,0) +++ vsub HY(50,0),HY(0,0),HY(29,0) +++ vsub HY(49,0),HY(0,0),HY(30,0) +++ vsub HY(48,0),HY(0,0),HY(31,0) +++ vadd HY(48++,0),HY(48++,0),r4 REP 32 # add on rounding, +++ vasl HY(48++,0),HY(48++,0),9 REP 32 # shift down by 7, and saturate +++ add r0,r8,16*32*2 # Move to 16th row +++ vsth VX(48,32++),(r0+=r6) REP 16 +++ b lr ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index b1f50ee..d720546 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -3,6 +3,7 @@ ++ // This works better than the mmap in that the memory can be cached, but requires a kernel modification to enable the device. ++ #define RPI_USE_VCSM ++ #define RPI_TIME_TOTAL_QPU +++#define RPI_TIME_TOTAL_VPU ++ ++ #include ++ #include ++@@ -48,10 +49,47 @@ typedef int int32_t; ++ #define QPU_CODE_SIZE 2048 ++ #define VPU_CODE_SIZE 2048 ++ +++const short rpi_transMatrix2even[32][16] = { // Even rows first +++{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, +++{90, 87, 80, 70, 57, 43, 25, 9, -9, -25, -43, -57, -70, -80, -87, -90}, +++{89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89}, +++{87, 57, 9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87}, +++{83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83}, +++{80, 9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80}, +++{75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75}, +++{70, -43, -87, 9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70}, +++{64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64}, +++{57, -80, -25, 90, -9, -87, 43, 70, -70, -43, 87, 9, -90, 25, 80, -57}, +++{50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50}, +++{43, -90, 57, 25, -87, 70, 9, -80, 80, -9, -70, 87, -25, -57, 90, -43}, +++{36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36}, +++{25, -70, 90, -80, 43, 9, -57, 87, -87, 57, -9, -43, 80, -90, 70, -25}, +++{18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18}, +++{ 9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9}, +++// Odd rows +++{90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4}, +++{90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13}, +++{88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22}, +++{85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31}, +++{82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67, 4, 73, 88, 38}, +++{78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46}, +++{73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54}, +++{67, -54, -78, 38, 85, -22, -90, 4, 90, 13, -88, -31, 82, 46, -73, -61}, +++{61, -73, -46, 82, 31, -88, -13, 90, -4, -90, 22, 85, -38, -78, 54, 67}, +++{54, -85, -4, 88, -46, -61, 82, 13, -90, 38, 67, -78, -22, 90, -31, -73}, +++{46, -90, 38, 54, -90, 31, 61, -88, 22, 67, -85, 13, 73, -82, 4, 78}, +++{38, -88, 73, -4, -67, 90, -46, -31, 85, -78, 13, 61, -90, 54, 22, -82}, +++{31, -78, 90, -61, 4, 54, -88, 82, -38, -22, 73, -90, 67, -13, -46, 85}, +++{22, -61, 85, -90, 73, -38, -4, 46, -78, 90, -82, 54, -13, -31, 67, -88}, +++{13, -38, 61, -78, 88, -90, 85, -73, 54, -31, 4, 22, -46, 67, -82, 90}, +++{ 4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90} +++}; +++ ++ struct GPU ++ { ++ unsigned int qpu_code[QPU_CODE_SIZE]; ++ unsigned int vpu_code[VPU_CODE_SIZE]; +++ short transMatrix2even[16*16]; ++ int open_count; // Number of allocated video buffers ++ unsigned int vc_handle; // Handle of this memory ++ int mb; // Mailbox handle ++@@ -123,6 +161,8 @@ static int gpu_init(volatile struct GPU **gpu) { ++ assert(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->vpu_code, rpi_hevc_transform, num_bytes); ++ } +++ // And the transform coefficients +++ memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, 16*16*sizeof(short)); ++ ++ return 0; ++ } ++@@ -274,11 +314,43 @@ unsigned int vpu_get_fn(void) { ++ return gpu->vc + offsetof(struct GPU,vpu_code); ++ } ++ +++unsigned int vpu_get_constants(void) { +++ if (gpu==NULL) { +++ gpu_lock(); +++ gpu_unlock(); +++ } +++ return gpu->vc + offsetof(struct GPU,transMatrix2even); +++} +++ ++ unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5) ++ { ++ unsigned r; +++#ifdef RPI_TIME_TOTAL_VPU +++ static int last_time=0; +++ static long long on_time=0; +++ static long long off_time=0; +++ int start_time; +++ int end_time; +++ static int count=0; +++ static long long countr2=0; +++#endif ++ gpu_lock(); +++#ifdef RPI_TIME_TOTAL_VPU +++ start_time = Microseconds(); +++ if (last_time==0) +++ last_time = start_time; +++ off_time += start_time-last_time; +++#endif ++ r = execute_code(gpu->mb, code, r0, r1, r2, r3, r4, r5); +++#ifdef RPI_TIME_TOTAL_VPU +++ end_time = Microseconds(); +++ last_time = end_time; +++ on_time += end_time - start_time; +++ count++; +++ countr2 += r2; +++ if ((count&0x7f)==0) +++ printf("VPU %d %lld On=%dms, Off=%dms\n",count,countr2,(int)(on_time/1000),(int)(off_time/1000)); +++#endif ++ gpu_unlock(); ++ return r; ++ } ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 4e3c35c..814fc3c 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -34,6 +34,7 @@ extern unsigned int qpu_get_fn(int num); ++ ++ // VPU specific functions ++ extern unsigned int vpu_get_fn(void); +++extern unsigned int vpu_get_constants(void); ++ extern unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); ++ ++ // Simple test of shader code ++-- ++2.5.0 ++ ++ ++From 4732d45788d56c44bda51c0cb12be912df89dab7 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 5 May 2015 09:41:23 +0100 ++Subject: [PATCH 05/68] Fixed deblocking ++ ++--- ++ libavcodec/hevc.c | 20 +++++++++++++++++--- ++ 1 file changed, 17 insertions(+), 3 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 79678ea..862f915 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2389,8 +2389,9 @@ static void rpi_execute_transform(HEVCContext *s) ++ // s->hevcdsp.idct[4-2](coeffs, 16); ++ //} ++ ++- //gpu_cache_flush(&s->coeffs_buf[i]); +++ gpu_cache_flush(&s->coeffs_buf[i]); ++ vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf[i].vc, s->num_coeffs[i] >> 8, 0, 0, 0); +++ gpu_cache_flush(&s->coeffs_buf[i]); ++ ++ for(i=0;i<4;i++) ++ s->num_coeffs[i] = 0; ++@@ -2429,6 +2430,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ ++ #ifdef RPI +++ int start_ctb_x = (s->sh.slice_ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; ++ s->enable_rpi = 1; // TODO this should depend on cross component and frame width etc. ++ #endif ++ ++@@ -2462,9 +2464,17 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ #ifdef RPI ++- if (1 || x_ctb + ctb_size >= s->ps.sps->width) { // TODO watch out for deblocking! +++ if (s->enable_rpi && x_ctb + ctb_size >= s->ps.sps->width) { +++ int x; +++ // Transform all blocks ++ rpi_execute_transform(s); +++ // Perform intra prediction and residual reconstruction ++ rpi_execute_pred_cmds(s); +++ // Perform deblocking for CTBs in this row +++ for(x = start_ctb_x; x <= x_ctb; x += ctb_size) { // TODO this will fail for tiles +++ ff_hevc_hls_filters(s, x, y_ctb, ctb_size); +++ } +++ start_ctb_x = 0; ++ } ++ #endif ++ if (more_data < 0) { ++@@ -2475,6 +2485,10 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ ctb_addr_ts++; ++ ff_hevc_save_states(s, ctb_addr_ts); +++#ifdef RPI +++ if (s->enable_rpi) +++ continue; +++#endif ++ ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size); ++ } ++ ++@@ -3283,7 +3297,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ if (!s->univ_pred_cmds) ++ goto fail; ++ for(i = 0; i < 4; i++) { ++- gpu_malloc_uncached(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16, &s->coeffs_buf[i]); // TODO slim this down and share across sizes +++ gpu_malloc_cached(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16, &s->coeffs_buf[i]); // TODO slim this down and share across sizes ++ s->coeffs_buf_arm[i] = (int16_t*) s->coeffs_buf[i].arm; ++ if (!s->coeffs_buf_arm[i]) ++ goto fail; ++-- ++2.5.0 ++ ++ ++From ddb4cf90d99f2e213de85244cd8e751570d794a8 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 5 May 2015 11:32:30 +0100 ++Subject: [PATCH 06/68] Added 32x32 transform ++ ++--- ++ libavcodec/hevc.c | 8 +- ++ libavcodec/hevc_cabac.c | 4 +- ++ libavcodec/rpi_hevc_transform.h | 200 +++++++++++++++++----------------------- ++ libavcodec/rpi_hevc_transform.s | 102 ++++++++++---------- ++ libavcodec/rpi_qpu.c | 4 +- ++ 5 files changed, 148 insertions(+), 170 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 862f915..fe71e03 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2389,9 +2389,11 @@ static void rpi_execute_transform(HEVCContext *s) ++ // s->hevcdsp.idct[4-2](coeffs, 16); ++ //} ++ ++- gpu_cache_flush(&s->coeffs_buf[i]); ++- vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf[i].vc, s->num_coeffs[i] >> 8, 0, 0, 0); ++- gpu_cache_flush(&s->coeffs_buf[i]); +++ gpu_cache_flush(&s->coeffs_buf[2]); +++ gpu_cache_flush(&s->coeffs_buf[3]); +++ vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf[2].vc, s->num_coeffs[2] >> 8, s->coeffs_buf[3].vc, s->num_coeffs[3] >> 10, 0); +++ gpu_cache_flush(&s->coeffs_buf[2]); +++ gpu_cache_flush(&s->coeffs_buf[3]); ++ ++ for(i=0;i<4;i++) ++ s->num_coeffs[i] = 0; ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index a7561bd..3e6dabf 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1031,7 +1031,9 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ int vshift = s->ps.sps->vshift[c_idx]; ++ uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride + ++ ((x0 >> hshift) << s->ps.sps->pixel_shift)]; ++- int use_vpu = s->enable_rpi && !lc->cu.cu_transquant_bypass_flag && !transform_skip_flag && !lc->tu.cross_pf && log2_trafo_size==4; +++#ifdef RPI +++ int use_vpu = s->enable_rpi && !lc->cu.cu_transquant_bypass_flag && !transform_skip_flag && !lc->tu.cross_pf && log2_trafo_size>=4; +++#endif ++ int16_t *coeffs = (int16_t*)(c_idx ? lc->edge_emu_buffer2 : lc->edge_emu_buffer); ++ uint8_t significant_coeff_group_flag[8][8] = {{0}}; ++ int explicit_rdpcm_flag = 0; ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++index c0c279f..6d772d7 100644 ++--- a/libavcodec/rpi_hevc_transform.h +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -1,6 +1,10 @@ ++ unsigned char rpi_hevc_transform [] = { ++ 169, ++ 3, +++62, +++64, +++79, +++64, ++ 3, ++ 232, ++ 32, ++@@ -17,6 +21,22 @@ unsigned char rpi_hevc_transform [] = { ++ 248, ++ 0, ++ 0, +++64, +++232, +++0, +++2, +++0, +++0, +++12, +++248, +++0, +++168, +++0, +++0, +++192, +++248, +++0, +++0, ++ 0, ++ 96, ++ 3, ++@@ -79,7 +99,7 @@ unsigned char rpi_hevc_transform [] = { ++ 70, ++ 128, ++ 144, ++-39, +++40, ++ 0, ++ 4, ++ 255, ++@@ -113,7 +133,7 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 128, ++ 144, ++-22, +++23, ++ 0, ++ 4, ++ 255, ++@@ -153,6 +173,8 @@ unsigned char rpi_hevc_transform [] = { ++ 140, ++ 211, ++ 192, +++34, +++31, ++ 41, ++ 3, ++ 70, ++@@ -195,7 +217,7 @@ unsigned char rpi_hevc_transform [] = { ++ 255, ++ 36, ++ 204, ++-96, +++224, ++ 2, ++ 0, ++ 248, ++@@ -219,62 +241,10 @@ unsigned char rpi_hevc_transform [] = { ++ 103, ++ 90, ++ 0, ++-8, ++-240, ++-0, ++-128, ++-128, ++-3, ++-0, ++-247, ++-32, ++-128, ++-10, ++-4, ++-136, ++-240, ++-32, ++-0, ++-128, ++-3, ++-112, ++-96, ++-90, ++-0, ++-169, ++-3, ++-3, ++-232, ++-32, ++-0, ++-0, ++-0, ++-12, ++-248, ++-0, ++-136, ++-0, ++-0, ++-192, ++-248, ++-0, ++-0, +++225, +++64, +++242, ++ 64, ++-232, ++-0, ++-2, ++-0, ++-0, ++-12, ++-248, ++-0, ++-168, ++-0, ++-0, ++-192, ++-248, ++-0, ++-0, ++ 3, ++ 232, ++ 128, ++@@ -287,18 +257,6 @@ unsigned char rpi_hevc_transform [] = { ++ 2, ++ 0, ++ 0, ++-4, ++-232, ++-64, ++-0, ++-0, ++-0, ++-5, ++-232, ++-0, ++-8, ++-0, ++-0, ++ 57, ++ 239, ++ 224, ++@@ -317,18 +275,26 @@ unsigned char rpi_hevc_transform [] = { ++ 64, ++ 26, ++ 64, +++4, +++232, +++64, +++0, +++0, +++0, +++149, +++96, ++ 161, ++ 64, ++ 152, ++ 64, ++ 128, ++ 144, ++-31, +++35, ++ 0, ++ 72, ++ 232, ++-32, ++ 0, +++4, ++ 0, ++ 0, ++ 65, ++@@ -339,8 +305,16 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 128, ++ 144, ++-23, +++27, +++0, +++4, +++232, +++0, +++8, ++ 0, +++0, +++69, +++96, ++ 145, ++ 64, ++ 168, ++@@ -351,8 +325,8 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 72, ++ 232, ++-32, ++ 0, +++4, ++ 0, ++ 0, ++ 65, ++@@ -373,7 +347,7 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 242, ++ 140, ++-229, +++221, ++ 192, ++ 57, ++ 239, ++@@ -383,6 +357,8 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 41, ++ 3, +++239, +++3, ++ 12, ++ 248, ++ 0, ++@@ -390,7 +366,7 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 0, ++ 192, ++-8, +++248, ++ 4, ++ 0, ++ 12, ++@@ -400,14 +376,14 @@ unsigned char rpi_hevc_transform [] = { ++ 64, ++ 0, ++ 192, ++-8, +++248, ++ 4, ++ 0, ++ 0, ++ 96, ++ 255, ++ 159, ++-131, +++154, ++ 255, ++ 0, ++ 232, ++@@ -417,7 +393,7 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 255, ++ 159, ++-142, +++165, ++ 255, ++ 4, ++ 255, ++@@ -429,7 +405,7 @@ unsigned char rpi_hevc_transform [] = { ++ 251, ++ 62, ++ 0, ++-5, +++4, ++ 255, ++ 51, ++ 204, ++@@ -439,15 +415,15 @@ unsigned char rpi_hevc_transform [] = { ++ 251, ++ 16, ++ 0, ++-77, +++76, ++ 254, ++ 51, ++ 204, ++-9, ++-4, +++128, +++3, ++ 224, ++ 251, ++-0, +++20, ++ 0, ++ 128, ++ 64, ++@@ -467,16 +443,6 @@ unsigned char rpi_hevc_transform [] = { ++ 99, ++ 0, ++ 0, ++-4, ++-254, ++-0, ++-144, ++-128, ++-2, ++-0, ++-8, ++-2, ++-0, ++ 32, ++ 247, ++ 240, ++@@ -488,92 +454,92 @@ unsigned char rpi_hevc_transform [] = { ++ 176, ++ 207, ++ 17, ++-3, +++19, ++ 32, ++ 247, ++ 112, ++ 207, ++ 18, ++-3, +++35, ++ 32, ++ 247, ++ 48, ++ 207, ++ 19, ++-3, +++51, ++ 32, ++ 247, ++ 240, ++ 206, ++ 20, ++-3, +++67, ++ 32, ++ 247, ++ 176, ++ 206, ++ 21, ++-3, +++83, ++ 32, ++ 247, ++ 112, ++ 206, ++ 22, ++-3, +++99, ++ 32, ++ 247, ++ 48, ++ 206, ++ 23, ++-3, +++115, ++ 32, ++ 247, ++ 240, ++ 205, ++ 24, ++-3, +++131, ++ 32, ++ 247, ++ 176, ++ 205, ++ 25, ++-3, +++147, ++ 32, ++ 247, ++ 112, ++ 205, ++ 26, ++-3, +++163, ++ 32, ++ 247, ++ 48, ++ 205, ++ 27, ++-3, +++179, ++ 32, ++ 247, ++ 240, ++ 204, ++ 28, ++-3, +++195, ++ 32, ++ 247, ++ 176, ++ 204, ++ 29, ++-3, +++211, ++ 32, ++ 247, ++ 112, ++ 204, ++ 30, ++-3, +++227, ++ 32, ++ 247, ++ 48, ++ 204, ++ 31, ++-3, ++-5, +++243, +++4, ++ 255, ++ 51, ++ 204, ++@@ -583,20 +549,20 @@ unsigned char rpi_hevc_transform [] = { ++ 251, ++ 16, ++ 0, ++-77, +++76, ++ 254, ++ 51, ++ 204, ++-9, ++-4, +++128, +++3, ++ 224, ++ 251, ++-0, +++20, ++ 0, ++ 0, ++ 237, +++32, ++ 0, ++-4, ++ 0, ++ 0, ++ 140, ++@@ -609,6 +575,6 @@ unsigned char rpi_hevc_transform [] = { ++ 99, ++ 0, ++ 0, ++-90, ++-0, +++111, +++3, ++ }; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++index 1e389c7..afdb32a 100644 ++--- a/libavcodec/rpi_hevc_transform.s +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -76,12 +76,19 @@ ++ # transMatrix2: address of the constant matrix (must be at 32 byte aligned address in Videocore memory) ++ # coeffs: address of the transform coefficients (must be at 32 byte aligned address in Videocore memory) ++ # num: number of 16x16 transforms to be done +++# coeffs32 +++# num32: number of 32x32 transforms ++ # ++ hevc_trans_16x16: ++ push r6-r15, lr # TODO cut down number of used registers ++- +++ mov r14,r3 # coeffs32 +++ mov r15,r4 # num32 ++ mov r3, 16*2 # Stride of transMatrix2 in bytes ++ vldh HX(32++,0),(r0 += r3) REP 16 # This is the 16x16 matrix, a transform is equivalent to multiplying input row vector * matrix +++ +++ add r0, 16*16*2 # For 32x32 transforms we also need this matrix +++ vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix +++ ++ # Now use r0 to describe which matrix we are working on. ++ # Allows us to prefetch the next block of coefficients for efficiency. ++ mov r0,0 # This describes the location where we read our coefficients from ++@@ -121,6 +128,10 @@ block_loop: ++ add r1,r7 ++ ++ addcmpbgt r2,-1,0,block_loop +++ +++ # Now go and do any 32x32 transforms +++ b hevc_trans_32x32 +++ ++ pop r6-r15, pc ++ ++ # r1,r2,r3 r7,r8 should be preserved ++@@ -136,26 +147,18 @@ col_trans_16_loop: ++ # Then sum up the results and place back ++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC ++ addcmpblt r0,1,r6,col_trans_16_loop ++- sub r0,16 # but r0 back to its original value +++ sub r0,16 # put r0 back to its original value ++ b lr ++ ++ col_trans_odd_16: ++ add r6,r0,16 # Final value for this loop ++ col_trans_odd_16_loop: ++ # First compute partial products for a single column ++- vmul32s HY(48++,0), VX(0,0)+r0, VX(32,0++) REP 16 +++ vmul32s HY(48++,0), VX(0,0)+r0, VX(32,32++) REP 16 ++ # Then sum up the results and place back ++ vadd VY(0,0)+r0, VY(48,0++), VY(48,8++) REP 8 CLRA SACC ++ addcmpblt r0,1,r6,col_trans_odd_16_loop ++- sub r0,16 # but r0 back to its original value ++- b lr ++- ++- ++-test_add: ++- vldh HX(0,0),(r0) ++- vadd HX(0,0),HX(0,0),10 ++- vsth HX(0,0),(r0) ++- mov r0,7 # return value +++ sub r0,16 # put r0 back to its original value ++ b lr ++ ++ # hevc_trans_32x32(short *transMatrix2, short *coeffs, int num) ++@@ -164,18 +167,17 @@ test_add: ++ # num: number of 16x16 transforms to be done ++ # ++ hevc_trans_32x32: ++- push r6-r15, lr # TODO cut down number of used registers +++ mov r1,r14 # coeffs +++ mov r2,r15 # num ++ ++- # Fetch transform matrices ++- mov r3, 16*2 # Stride of transMatrix2 in bytes (and of coefficients) ++- vldh HX(32++,0),(r0 += r3) REP 16 # This is the even 16x16 matrix ++- add r0, 16*16*2 ++- vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix +++ # Fetch odd transform matrix +++ #mov r3, 16*2 # Stride of transMatrix2 in bytes (and of coefficients) +++ #vldh HX(32++,0),(r0 += r3) REP 16 # This is the even 16x16 matrix +++ #add r0, 16*16*2 +++ #vldh HX(32++,32),(r0 += r3) REP 16 # This is the odd 16x16 matrix ++ ++ mov r3, 32*2*2 # Stride used to fetch alternate rows of our input coefficient buffer ++ mov r7, 16*16*2 # Total block size ++- mov r4, 64 # Constant used for rounding first pass ++- mov r5, 1<<11 # Constant used for rounding second pass ++ sub sp,sp,32*32*2+32 # Allocate some space on the stack for us to store 32*32 shorts as temporary results (needs to be aligned) ++ # set r8 to 32byte aligned stack pointer ++ add r8,sp,31 ++@@ -186,21 +188,27 @@ hevc_trans_32x32: ++ block_loop32: ++ ++ # COLUMN TRANSFORM +++ mov r4, 64 # Constant used for rounding first pass +++ mov r5, 9 # left shift used for rounding first pass +++ ++ # Transform the first 16 columns ++ mov r1,r10 # Input Coefficient buffer ++ mov r8,r9 # Output temporary storage ++ bl trans32 ++ # Transform the second 16 columns ++- add r8,32 +++ add r8,32*16*2 ++ add r1,32 ++ bl trans32 ++ ++ # ROW TRANSFORM +++ mov r4, 1<<11 # Constant used for rounding second pass +++ mov r5, 4 # left shift used for rounding second pass +++ ++ mov r1,r9 # Input temporary storage ++ mov r8,r10 # Output Coefficient buffer ++ bl trans32 ++ # Transform the second 16 columns ++- add r8,32 +++ add r8,32*16*2 ++ add r1,32 ++ bl trans32 ++ ++@@ -212,11 +220,12 @@ block_loop32: ++ pop r6-r15, pc ++ ++ trans32: +++ push lr ++ # We can no longer afford the VRF space to do prefetching when doing 32x32 ++ # Fetch the even rows ++- vldh HX(0++,0)+r0,(r1 += r3) REP 16 +++ vldh HX(0++,0),(r1 += r3) REP 16 ++ # Fetch the odd rows ++- vldh HX(16++,0)+r0,64(r1 += r3) REP 16 # First odd row is 32 shorts ahead of r1 +++ vldh HX(16++,0),64(r1 += r3) REP 16 # First odd row is 32 shorts ahead of r1 ++ ++ # Transform the even rows using even matrix ++ mov r0, 0 # Even rows ++@@ -228,33 +237,32 @@ trans32: ++ ++ # Now apply butterfly to compute the first 16 results ++ vadd HY(48++,0),HY(0++,0),HY(16++,0) REP 16 ++- vadd HY(48++,0),HY(48++,0),r4 REP 32 # add on rounding, ++- vasl HY(48++,0),HY(48++,0),9 REP 32 # shift down by 7, and saturate +++ vadd HY(48++,0),HY(48++,0),r4 REP 16 # add on rounding, +++ vasl HY(48++,0),HY(48++,0),r5 REP 16 # shift down by 7, and saturate ++ # 16bit results now in HX(48,32) ++ mov r0,r8 ++ mov r6,32*2 ++ vsth VX(48,32++),(r0+=r6) REP 16 ++- vmov VX(0,0++)+r0, HX(0++,32)+r0 REP 16 # Store transposed ++ ++ # Now apply butterfly to compute the second 16 results (in reverse order) ++- vsub HY(63,0),HY(0,0),HY(16,0) ++- vsub HY(62,0),HY(0,0),HY(17,0) ++- vsub HY(61,0),HY(0,0),HY(18,0) ++- vsub HY(60,0),HY(0,0),HY(19,0) ++- vsub HY(59,0),HY(0,0),HY(20,0) ++- vsub HY(58,0),HY(0,0),HY(21,0) ++- vsub HY(57,0),HY(0,0),HY(22,0) ++- vsub HY(56,0),HY(0,0),HY(23,0) ++- vsub HY(55,0),HY(0,0),HY(24,0) ++- vsub HY(54,0),HY(0,0),HY(25,0) ++- vsub HY(53,0),HY(0,0),HY(26,0) ++- vsub HY(52,0),HY(0,0),HY(27,0) ++- vsub HY(51,0),HY(0,0),HY(28,0) ++- vsub HY(50,0),HY(0,0),HY(29,0) ++- vsub HY(49,0),HY(0,0),HY(30,0) ++- vsub HY(48,0),HY(0,0),HY(31,0) ++- vadd HY(48++,0),HY(48++,0),r4 REP 32 # add on rounding, ++- vasl HY(48++,0),HY(48++,0),9 REP 32 # shift down by 7, and saturate ++- add r0,r8,16*32*2 # Move to 16th row +++ vsub HY(63,0),HY(0 ,0),HY(16,0) +++ vsub HY(62,0),HY(1 ,0),HY(17,0) +++ vsub HY(61,0),HY(2 ,0),HY(18,0) +++ vsub HY(60,0),HY(3 ,0),HY(19,0) +++ vsub HY(59,0),HY(4 ,0),HY(20,0) +++ vsub HY(58,0),HY(5 ,0),HY(21,0) +++ vsub HY(57,0),HY(6 ,0),HY(22,0) +++ vsub HY(56,0),HY(7 ,0),HY(23,0) +++ vsub HY(55,0),HY(8 ,0),HY(24,0) +++ vsub HY(54,0),HY(9 ,0),HY(25,0) +++ vsub HY(53,0),HY(10,0),HY(26,0) +++ vsub HY(52,0),HY(11,0),HY(27,0) +++ vsub HY(51,0),HY(12,0),HY(28,0) +++ vsub HY(50,0),HY(13,0),HY(29,0) +++ vsub HY(49,0),HY(14,0),HY(30,0) +++ vsub HY(48,0),HY(15,0),HY(31,0) +++ vadd HY(48++,0),HY(48++,0),r4 REP 16 # add on rounding, +++ vasl HY(48++,0),HY(48++,0),r5 REP 16 # shift down by 7, and saturate +++ add r0,r8,32 ++ vsth VX(48,32++),(r0+=r6) REP 16 ++- b lr +++ pop pc ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index d720546..12ad5fb 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -89,7 +89,7 @@ struct GPU ++ { ++ unsigned int qpu_code[QPU_CODE_SIZE]; ++ unsigned int vpu_code[VPU_CODE_SIZE]; ++- short transMatrix2even[16*16]; +++ short transMatrix2even[16*16*2]; ++ int open_count; // Number of allocated video buffers ++ unsigned int vc_handle; // Handle of this memory ++ int mb; // Mailbox handle ++@@ -162,7 +162,7 @@ static int gpu_init(volatile struct GPU **gpu) { ++ memcpy((void*)ptr->vpu_code, rpi_hevc_transform, num_bytes); ++ } ++ // And the transform coefficients ++- memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, 16*16*sizeof(short)); +++ memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, sizeof(rpi_transMatrix2even)); ++ ++ return 0; ++ } ++-- ++2.5.0 ++ ++ ++From cb4444b27d7e1d38d42375f52cd3741c2ebbe4ec Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 5 May 2015 16:57:03 +0100 ++Subject: [PATCH 07/68] Clear coefficients in advance ++ ++--- ++ libavcodec/hevc.c | 129 ++++++++++++++++++++++++++++------------ ++ libavcodec/hevc.h | 6 +- ++ libavcodec/hevc_cabac.c | 7 ++- ++ libavcodec/rpi_hevc_transform.h | 50 ++++++++++++++++ ++ libavcodec/rpi_hevc_transform.s | 16 +++++ ++ 5 files changed, 168 insertions(+), 40 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index fe71e03..8b93ca2 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -43,6 +43,8 @@ ++ ++ #ifdef RPI ++ #include "rpi_qpu.h" +++// For some unknown reason, the code seems to crash if I do a late malloc +++#define EARLY_MALLOC ++ #endif ++ ++ // #define DISABLE_MC ++@@ -61,6 +63,20 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ /* free everything allocated by pic_arrays_init() */ ++ static void pic_arrays_free(HEVCContext *s) ++ { +++#ifdef RPI +++#ifdef EARLY_MALLOC +++#else +++ printf("pic_arrays_free\n"); +++ if (s->coeffs_buf_arm[0]) { +++ gpu_free(&s->coeffs_buf_default); +++ s->coeffs_buf_arm[0] = 0; +++ } +++ if (s->coeffs_buf_arm[2]) { +++ gpu_free(&s->coeffs_buf_accelerated); +++ s->coeffs_buf_arm[2] = 0; +++ } +++#endif +++#endif ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++ ++@@ -97,6 +113,28 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ int ctb_count = sps->ctb_width * sps->ctb_height; ++ int min_pu_size = sps->min_pu_width * sps->min_pu_height; ++ +++#ifdef RPI +++#ifdef EARLY_MALLOC +++#else +++ int coeffs_in_ctb = (1 << s->ps.sps->log2_ctb_size) * (1 << s->ps.sps->log2_ctb_size); +++ int coefs_per_row = sps->ctb_width * coeffs_in_ctb * 3; // Allow space for chroma +++ printf("pic_arrays_init\n"); +++ printf("Allocated %d\n",coefs_per_row); +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); +++ s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; +++ if (!s->coeffs_buf_arm[0]) +++ goto fail; +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); +++ s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; +++ s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; +++ if (!s->coeffs_buf_arm[2]) +++ goto fail; +++ s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; +++ s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; +++ printf("Done\n"); +++#endif +++#endif +++ ++ s->bs_width = (width >> 2) + 1; ++ s->bs_height = (height >> 2) + 1; ++ ++@@ -2389,11 +2427,10 @@ static void rpi_execute_transform(HEVCContext *s) ++ // s->hevcdsp.idct[4-2](coeffs, 16); ++ //} ++ ++- gpu_cache_flush(&s->coeffs_buf[2]); ++- gpu_cache_flush(&s->coeffs_buf[3]); ++- vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf[2].vc, s->num_coeffs[2] >> 8, s->coeffs_buf[3].vc, s->num_coeffs[3] >> 10, 0); ++- gpu_cache_flush(&s->coeffs_buf[2]); ++- gpu_cache_flush(&s->coeffs_buf[3]); +++ +++ gpu_cache_flush(&s->coeffs_buf_accelerated); +++ vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); +++ //gpu_cache_flush(&s->coeffs_buf_accelerated); ++ ++ for(i=0;i<4;i++) ++ s->num_coeffs[i] = 0; ++@@ -2415,7 +2452,9 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ lc->na.cand_up_right = (cmd->na >> 0) & 1; ++ s->hpc.intra_pred[cmd->size - 2](s, cmd->x, cmd->y, cmd->c_idx); ++ } else { +++ int trafo_size = 1 << cmd->size; ++ s->hevcdsp.transform_add[cmd->size-2](cmd->dst, cmd->buf, cmd->stride); +++ memset(cmd->buf, 0, trafo_size * trafo_size * sizeof(int16_t)); // Clear coefficients here while they are in the cache ++ } ++ } ++ s->num_pred_cmds = 0; ++@@ -3224,10 +3263,18 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ av_freep(&s->unif_mv_cmds); ++ av_freep(&s->unif_xfm_cmds); ++ av_freep(&s->univ_pred_cmds); ++- for(i = 0; i < 4; i++) { ++- gpu_free(&s->coeffs_buf[i]); +++ +++#ifdef EARLY_MALLOC +++ if (s->coeffs_buf_arm[0]) { +++ gpu_free(&s->coeffs_buf_default); +++ s->coeffs_buf_arm[0] = 0; +++ } +++ if (s->coeffs_buf_arm[2]) { +++ gpu_free(&s->coeffs_buf_accelerated); +++ s->coeffs_buf_arm[2] = 0; ++ } ++ #endif +++#endif ++ ++ for (i = 0; i < 3; i++) { ++ av_freep(&s->sao_pixel_buffer_h[i]); ++@@ -3275,6 +3322,16 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ return 0; ++ } ++ +++#ifdef RPI +++static av_cold void memclear16(int16_t *p, int n) +++{ +++ vpu_execute_code( vpu_get_fn(), p, n, 0, 0, 0, 1); +++ //int i; +++ //for(i=0;ipriv_data; ++@@ -3298,37 +3355,35 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->univ_pred_cmds = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); ++ if (!s->univ_pred_cmds) ++ goto fail; ++- for(i = 0; i < 4; i++) { ++- gpu_malloc_cached(sizeof(int16_t)*RPI_MAX_XFM_CMDS*16, &s->coeffs_buf[i]); // TODO slim this down and share across sizes ++- s->coeffs_buf_arm[i] = (int16_t*) s->coeffs_buf[i].arm; ++- if (!s->coeffs_buf_arm[i]) ++- goto fail; ++- } ++- s->enable_rpi = 0; ++ ++- // A little test program ++- /*{ ++- GPU_MEM_PTR_T p; ++- int err = gpu_malloc_cached(16, &p); ++- short *q = (short *)p.arm; ++- int i; ++- int r; ++- printf("Allocated memory %d ARM 0x%x, VC 0x%x, Code 0x%x\n",err,(int)p.arm,p.vc,(int)vpu_get_fn()); ++- printf("Allocated memory %d ARM 0x%x, VC 0x%x\n",err,(int)p.arm,p.vc); ++- printf("Preparing data %p\n",q); ++- for(i=0;i<16;i++) ++- q[i] = i; ++- printf("Flush cache\n"); ++- gpu_cache_flush(&p); ++- printf("Executing code\n"); ++- r = vpu_execute_code( vpu_get_fn(), p.vc, 0, 0, 0, 0, 0); ++- printf("Return value %d (",r); ++- for(i=0;i<16;i++) ++- printf("%d ",q[i]); ++- printf(")\n"); ++- gpu_free(&p); ++- goto fail; // Early out ++- }*/ +++ s->coeffs_buf_arm[0] = 0; +++ s->coeffs_buf_arm[2] = 0; +++ +++#ifdef EARLY_MALLOC +++ int coeffs_in_ctb = 64*64; +++ int coefs_per_row = (2048/64) * coeffs_in_ctb * 3; // Allow space for chroma +++ printf("Allocated %d\n",coefs_per_row); +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); +++ s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; +++ if (!s->coeffs_buf_arm[0]) +++ goto fail; +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); +++ s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; +++ s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; +++ if (!s->coeffs_buf_arm[2]) +++ goto fail; +++ s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; +++ s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; +++ printf("Done\n"); +++ //memset(s->coeffs_buf_arm[0],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[0], coefs_per_row); +++ //memset(s->coeffs_buf_arm[2],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[2], coefs_per_row); +++ //memset(s->coeffs_buf_arm[3],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[3], coefs_per_row); +++#endif +++ +++ s->enable_rpi = 0; ++ ++ #endif ++ ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 1e4c34c..e240b5c 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -887,8 +887,12 @@ typedef struct HEVCContext { ++ HEVCMvCmd *unif_mv_cmds; ++ HEVCXfmCmd *unif_xfm_cmds; ++ HEVCPredCmd *univ_pred_cmds; ++- GPU_MEM_PTR_T coeffs_buf[4]; +++ int buf_width; +++ GPU_MEM_PTR_T coeffs_buf_default; +++ GPU_MEM_PTR_T coeffs_buf_accelerated; ++ int16_t *coeffs_buf_arm[4]; +++ unsigned int coeffs_buf_vc[4]; +++ ++ int num_coeffs[4]; ++ int num_xfm_cmds; ++ int num_mv_cmds; ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index 3e6dabf..a295d3e 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1058,9 +1058,13 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ s->num_coeffs[0] += n; ++ } ++ } +++ // We now do the memset after transform_add while we know the data is cached. +++ //memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); +++#else +++ memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); ++ #endif ++ ++- memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); +++ ++ ++ // Derive QP for dequant ++ if (!lc->cu.cu_transquant_bypass_flag) { ++@@ -1547,7 +1551,6 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ #ifdef RPI ++ if (s->enable_rpi) { ++ HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; ++- //memcpy(coeffs2, coeffs, sizeof(int16_t) * trafo_size * trafo_size); // TODO ++ cmd->type = RPI_PRED_TRANSFORM_ADD; ++ cmd->size = log2_trafo_size; ++ cmd->buf = coeffs; ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++index 6d772d7..4f13622 100644 ++--- a/libavcodec/rpi_hevc_transform.h +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -1,4 +1,10 @@ ++ unsigned char rpi_hevc_transform [] = { +++21, +++106, +++0, +++144, +++35, +++1, ++ 169, ++ 3, ++ 62, ++@@ -577,4 +583,48 @@ unsigned char rpi_hevc_transform [] = { ++ 0, ++ 111, ++ 3, +++4, +++254, +++0, +++128, +++0, +++4, +++0, +++248, +++0, +++0, +++2, +++232, +++32, +++0, +++0, +++0, +++140, +++248, +++32, +++0, +++0, +++0, +++224, +++35, +++0, +++0, +++64, +++232, +++0, +++2, +++0, +++0, +++193, +++232, +++0, +++1, +++0, +++0, +++1, +++106, +++116, +++30, +++90, +++0, ++ }; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++index afdb32a..fd159bc 100644 ++--- a/libavcodec/rpi_hevc_transform.s +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -78,8 +78,11 @@ ++ # num: number of 16x16 transforms to be done ++ # coeffs32 ++ # num32: number of 32x32 transforms +++# command 0 for transform, 1 for memclear16(int16_t *dst,num16) ++ # ++ hevc_trans_16x16: +++ cmp r5,1 +++ beq memclear16 ++ push r6-r15, lr # TODO cut down number of used registers ++ mov r14,r3 # coeffs32 ++ mov r15,r4 # num32 ++@@ -266,3 +269,16 @@ trans32: ++ add r0,r8,32 ++ vsth VX(48,32++),(r0+=r6) REP 16 ++ pop pc +++ +++memclear16: +++ # r0 is address +++ # r1 is number of 16bits values to set to 0 (may overrun past end and clear more than specified) +++ vmov HX(0++,0),0 REP 16 +++ mov r2,32 +++loop: +++ vsth HX(0++,0),(r0+=r2) REP 16 +++ add r0,16*16*2 +++ sub r1,16*16 +++ cmp r1,0 +++ bgt loop +++ b lr ++-- ++2.5.0 ++ ++ ++From 3328a46c648542e5281088576dffac413de7a19d Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 6 May 2015 09:56:43 +0100 ++Subject: [PATCH 08/68] Prepared inter offload ++ ++--- ++ libavcodec/hevc.c | 116 +++++++++++++++++++++++++++++++++++++++++++----- ++ libavcodec/hevc.h | 29 +++++++++++- ++ libavcodec/hevc_cabac.c | 5 ++- ++ 3 files changed, 137 insertions(+), 13 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 8b93ca2..59f5d15 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -45,6 +45,8 @@ ++ #include "rpi_qpu.h" ++ // For some unknown reason, the code seems to crash if I do a late malloc ++ #define EARLY_MALLOC +++// Move Inter prediction into separate pass +++//#define RPI_INTER ++ #endif ++ ++ // #define DISABLE_MC ++@@ -1429,6 +1431,95 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) ++ * @param luma_offset additive offset applied to the luma prediction value ++ */ ++ +++#ifdef RPI_INTER +++#define RPI_REDIRECT(fn) rpi_ ## fn +++static void rpi_luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, +++ AVFrame *ref, const Mv *mv, int x_off, int y_off, +++ int block_w, int block_h, int luma_weight, int luma_offset) +++{ +++ HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ cmd->cmd = RPI_CMD_LUMA_UNI; +++ cmd->dst = dst; +++ cmd->dststride = dststride; +++ cmd->src = ref->data[0]; +++ cmd->srcstride = ref->linesize[0]; +++ cmd->mv = *mv; +++ cmd->x_off = x_off; +++ cmd->y_off = y_off; +++ cmd->block_w = block_w; +++ cmd->block_h = block_h; +++ cmd->weight = luma_weight; +++ cmd->offset = luma_offset; +++} +++ +++static void rpi_luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, +++ AVFrame *ref0, const Mv *mv0, int x_off, int y_off, +++ int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) +++{ +++ HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ cmd->cmd = RPI_CMD_LUMA_BI; +++ cmd->dst = dst; +++ cmd->dststride = dststride; +++ cmd->src = ref->data[0]; +++ cmd->srcstride = ref->linesize[0]; +++ cmd->mv = *mv; +++ cmd->x_off = x_off; +++ cmd->y_off = y_off; +++ cmd->block_w = block_w; +++ cmd->block_h = block_h; +++ cmd->weight = luma_weight; +++ cmd->offset = luma_offset; +++ cmd->src1 = ref1->data[]; +++ cmd->srcstride1 = ref1->linesize[0]; +++ cmd->mv1 = *mv1; +++ cmd->ref_idx[0] = current_mv->ref_idx[0]; +++ cmd->ref_idx[1] = current_mv->ref_idx[1]; +++} +++ +++static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, +++ ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist, +++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset) +++{ +++ HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ cmd->cmd = RPI_CMD_CHROMA_UNI; +++ cmd->dst = dst0; +++ cmd->dststride = dststride; +++ cmd->src = src0; +++ cmd->srcstride = srcstride; +++ cmd->mv = current_mv->mv[reflist]; +++ cmd->x_off = x_off; +++ cmd->y_off = y_off; +++ cmd->block_w = block_w; +++ cmd->block_h = block_h; +++ cmd->weight = chroma_weight; +++ cmd->offset = chroma_offset; +++} +++ +++static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, +++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx) +++{ +++ HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ cmd->cmd = RPI_CMD_CHROMA_BI+cidx; +++ cmd->dst = dst0; +++ cmd->dststride = dststride; +++ cmd->src = ref0->data[cidx+1]; +++ cmd->srcstride = ref0->linesize[cidx+1]; +++ cmd->mv = current_mv->mv[reflist]; +++ cmd->x_off = x_off; +++ cmd->y_off = y_off; +++ cmd->block_w = block_w; +++ cmd->block_h = block_h; +++ cmd->weight = chroma_weight; +++ cmd->offset = chroma_offset; +++ cmd->src = ref1->data[cidx+1]; +++ cmd->srcstride1 = ref1->linesize[cidx+1]; +++ cmd->ref_idx[0] = current_mv->ref_idx[0]; +++ cmd->ref_idx[1] = current_mv->ref_idx[1]; +++} +++#else +++#define RPI_REDIRECT(fn) fn +++#endif +++ ++ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref, const Mv *mv, int x_off, int y_off, ++ int block_w, int block_h, int luma_weight, int luma_offset) ++@@ -1494,7 +1585,7 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ * @param mv1 motion vector1 (relative to block position) to get pixel data from ++ * @param current_mv current motion vector structure ++ */ ++- static void luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, +++static void luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref0, const Mv *mv0, int x_off, int y_off, ++ int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) ++ { ++@@ -1876,16 +1967,16 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- luma_mc_uni(s, dst0, s->frame->linesize[0], ref0->frame, +++ RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l0[current_mv.ref_idx[0]], ++ s->sh.luma_offset_l0[current_mv.ref_idx[0]]); ++ ++ if (s->ps.sps->chroma_format_idc) { ++- chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1], +++ RPI_REDIRECT(chroma_mc_uni)(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1], ++ 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]); ++- chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2], +++ RPI_REDIRECT(chroma_mc_uni)(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2], ++ 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]); ++ } ++@@ -1895,17 +1986,17 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- luma_mc_uni(s, dst0, s->frame->linesize[0], ref1->frame, +++ RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref1->frame, ++ ¤t_mv.mv[1], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l1[current_mv.ref_idx[1]], ++ s->sh.luma_offset_l1[current_mv.ref_idx[1]]); ++ ++ if (s->ps.sps->chroma_format_idc) { ++- chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1], +++ RPI_REDIRECT(chroma_mc_uni)(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1], ++ 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]); ++ ++- chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2], +++ RPI_REDIRECT(chroma_mc_uni)(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2], ++ 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]); ++ } ++@@ -1915,15 +2006,15 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- luma_mc_bi(s, dst0, s->frame->linesize[0], ref0->frame, +++ RPI_REDIRECT(luma_mc_bi)(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ ref1->frame, ¤t_mv.mv[1], ¤t_mv); ++ ++ if (s->ps.sps->chroma_format_idc) { ++- chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame, +++ RPI_REDIRECT(chroma_mc_bi)(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame, ++ x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 0); ++ ++- chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame, +++ RPI_REDIRECT(chroma_mc_bi)(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame, ++ x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 1); ++ } ++ } ++@@ -2454,7 +2545,9 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ } else { ++ int trafo_size = 1 << cmd->size; ++ s->hevcdsp.transform_add[cmd->size-2](cmd->dst, cmd->buf, cmd->stride); +++#ifdef RPI_PRECLEAR ++ memset(cmd->buf, 0, trafo_size * trafo_size * sizeof(int16_t)); // Clear coefficients here while they are in the cache +++#endif ++ } ++ } ++ s->num_pred_cmds = 0; ++@@ -3375,6 +3468,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; ++ s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; ++ printf("Done\n"); +++#ifdef RPI_PRECLEAR ++ //memset(s->coeffs_buf_arm[0],0, sizeof(int16_t) * coefs_per_row); ++ memclear16(s->coeffs_buf_arm[0], coefs_per_row); ++ //memset(s->coeffs_buf_arm[2],0, sizeof(int16_t) * coefs_per_row); ++@@ -3383,6 +3477,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ memclear16(s->coeffs_buf_arm[3], coefs_per_row); ++ #endif ++ +++#endif +++ ++ s->enable_rpi = 0; ++ ++ #endif ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index e240b5c..a35ee4a 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -829,14 +829,39 @@ typedef struct HEVCLocalContext { ++ // RPI_MAX_WIDTH is maximum width in pixels supported by the accelerated code ++ #define RPI_MAX_WIDTH 2048 ++ ++-// Worst case is for 4:4:4 4x4 blocks with 64 high coding tree blocks, so 16 MV cmds per 4 pixels across for each colour plane ++-#define RPI_MAX_MV_CMDS (16*3*(RPI_MAX_WIDTH/4)) +++// Worst case is for 4:4:4 4x4 blocks with 64 high coding tree blocks, so 16 MV cmds per 4 pixels across for each colour plane, * 2 for bi +++#define RPI_MAX_MV_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) ++ #define RPI_MAX_XFM_CMDS (16*3*(RPI_MAX_WIDTH/4)) ++ // Each block can have an intra prediction and a transform_add command ++ #define RPI_MAX_PRED_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) ++ +++#define RPI_CMD_LUMA_UNI 0 +++#define RPI_CMD_CHROMA_UNI 1 +++#define RPI_CMD_LUMA_BI 2 +++#define RPI_CMD_U_BI 3 +++#define RPI_CMD_V_BI 4 +++ +++// RPI_PRECLEAR is not working yet - perhaps clearing on VPUs is flawed? +++// #define RPI_PRECLEAR +++ ++ // Command for inter prediction ++ typedef struct HEVCMvCmd { +++ int cmd; +++ uint8_t *dst; +++ ptrdiff_t dststride; +++ uint8_t *src; +++ ptrdiff_t srcstride; +++ Mv mv; +++ int x_off; +++ int y_off; +++ int block_w; +++ int block_h; +++ int weight; +++ int offset; +++ uint8_t *src1; +++ ptrdiff_t srcstride1; +++ Mv mv1; +++ int8_t ref_idx[2]; ++ } HEVCMvCmd; ++ ++ // Command for transform to process a block of coefficients ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index a295d3e..f28759b 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1059,7 +1059,10 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } ++ } ++ // We now do the memset after transform_add while we know the data is cached. ++- //memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); +++ #ifdef RPI_PRECLEAR +++ #else +++ memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); +++ #endif ++ #else ++ memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t)); ++ #endif ++-- ++2.5.0 ++ ++ ++From 191028358f7153c8598981673e6bd165acaa699d Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 6 May 2015 11:08:50 +0100 ++Subject: [PATCH 09/68] Inter prediction in separate pass ++ ++--- ++ libavcodec/hevc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++---------- ++ libavcodec/hevc.h | 2 +- ++ 2 files changed, 77 insertions(+), 18 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 59f5d15..f60709e 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -46,7 +46,7 @@ ++ // For some unknown reason, the code seems to crash if I do a late malloc ++ #define EARLY_MALLOC ++ // Move Inter prediction into separate pass ++-//#define RPI_INTER +++#define RPI_INTER ++ #endif ++ ++ // #define DISABLE_MC ++@@ -1437,7 +1437,7 @@ static void rpi_luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref, const Mv *mv, int x_off, int y_off, ++ int block_w, int block_h, int luma_weight, int luma_offset) ++ { ++- HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; ++ cmd->cmd = RPI_CMD_LUMA_UNI; ++ cmd->dst = dst; ++ cmd->dststride = dststride; ++@@ -1456,31 +1456,29 @@ static void rpi_luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref0, const Mv *mv0, int x_off, int y_off, ++ int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) ++ { ++- HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; ++ cmd->cmd = RPI_CMD_LUMA_BI; ++ cmd->dst = dst; ++ cmd->dststride = dststride; ++- cmd->src = ref->data[0]; ++- cmd->srcstride = ref->linesize[0]; ++- cmd->mv = *mv; +++ cmd->src = ref0->data[0]; +++ cmd->srcstride = ref0->linesize[0]; +++ cmd->mv = *mv0; ++ cmd->x_off = x_off; ++ cmd->y_off = y_off; ++ cmd->block_w = block_w; ++ cmd->block_h = block_h; ++- cmd->weight = luma_weight; ++- cmd->offset = luma_offset; ++- cmd->src1 = ref1->data[]; +++ cmd->src1 = ref1->data[0]; ++ cmd->srcstride1 = ref1->linesize[0]; ++ cmd->mv1 = *mv1; ++ cmd->ref_idx[0] = current_mv->ref_idx[0]; ++ cmd->ref_idx[1] = current_mv->ref_idx[1]; ++ } ++ ++-static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, +++static void rpi_chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset) ++ { ++- HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; ++ cmd->cmd = RPI_CMD_CHROMA_UNI; ++ cmd->dst = dst0; ++ cmd->dststride = dststride; ++@@ -1495,27 +1493,27 @@ static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ cmd->offset = chroma_offset; ++ } ++ ++-static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, +++static void rpi_chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx) ++ { ++- HEVCMvCmd *cmd = unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; ++ cmd->cmd = RPI_CMD_CHROMA_BI+cidx; ++ cmd->dst = dst0; ++ cmd->dststride = dststride; ++ cmd->src = ref0->data[cidx+1]; ++ cmd->srcstride = ref0->linesize[cidx+1]; ++- cmd->mv = current_mv->mv[reflist]; +++ cmd->mv = current_mv->mv[0]; +++ cmd->mv1 = current_mv->mv[1]; ++ cmd->x_off = x_off; ++ cmd->y_off = y_off; ++ cmd->block_w = block_w; ++ cmd->block_h = block_h; ++- cmd->weight = chroma_weight; ++- cmd->offset = chroma_offset; ++- cmd->src = ref1->data[cidx+1]; +++ cmd->src1 = ref1->data[cidx+1]; ++ cmd->srcstride1 = ref1->linesize[cidx+1]; ++ cmd->ref_idx[0] = current_mv->ref_idx[0]; ++ cmd->ref_idx[1] = current_mv->ref_idx[1]; ++ } +++ ++ #else ++ #define RPI_REDIRECT(fn) fn ++ #endif ++@@ -2543,7 +2541,9 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ lc->na.cand_up_right = (cmd->na >> 0) & 1; ++ s->hpc.intra_pred[cmd->size - 2](s, cmd->x, cmd->y, cmd->c_idx); ++ } else { +++#ifdef RPI_PRECLEAR ++ int trafo_size = 1 << cmd->size; +++#endif ++ s->hevcdsp.transform_add[cmd->size-2](cmd->dst, cmd->buf, cmd->stride); ++ #ifdef RPI_PRECLEAR ++ memset(cmd->buf, 0, trafo_size * trafo_size * sizeof(int16_t)); // Clear coefficients here while they are in the cache ++@@ -2552,6 +2552,61 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ } ++ s->num_pred_cmds = 0; ++ } +++ +++static void rpi_execute_inter_cmds(HEVCContext *s) +++{ +++ HEVCMvCmd *cmd = s->unif_mv_cmds; +++ int n,cidx; +++ AVFrame myref; +++ AVFrame myref1; +++ struct MvField mymv; +++ if (s->num_mv_cmds > RPI_MAX_MV_CMDS) { +++ printf("Overflow inter_cmds\n"); +++ exit(-1); +++ } +++ for(n = s->num_mv_cmds; n>0 ; n--, cmd++) { +++ switch(cmd->cmd) { +++ case RPI_CMD_LUMA_UNI: +++ myref.data[0] = cmd->src; +++ myref.linesize[0] = cmd->srcstride; +++ luma_mc_uni(s, cmd->dst, cmd->dststride, &myref, &cmd->mv, cmd->x_off, cmd->y_off, cmd->block_w, cmd->block_h, cmd->weight, cmd->offset); +++ break; +++ case RPI_CMD_LUMA_BI: +++ myref.data[0] = cmd->src; +++ myref.linesize[0] = cmd->srcstride; +++ myref1.data[0] = cmd->src1; +++ myref1.linesize[0] = cmd->srcstride1; +++ mymv.ref_idx[0] = cmd->ref_idx[0]; +++ mymv.ref_idx[1] = cmd->ref_idx[1]; +++ luma_mc_bi(s, cmd->dst, cmd->dststride, +++ &myref, &cmd->mv, cmd->x_off, cmd->y_off, cmd->block_w, cmd->block_h, +++ &myref1, &cmd->mv1, &mymv); +++ break; +++ case RPI_CMD_CHROMA_UNI: +++ mymv.mv[0] = cmd->mv; +++ chroma_mc_uni(s, cmd->dst, +++ cmd->dststride, cmd->src, cmd->srcstride, 0, +++ cmd->x_off, cmd->y_off, cmd->block_w, cmd->block_h, &mymv, cmd->weight, cmd->offset); +++ break; +++ case RPI_CMD_CHROMA_BI: +++ case RPI_CMD_CHROMA_BI+1: +++ cidx = cmd->cmd - RPI_CMD_CHROMA_BI; +++ myref.data[cidx+1] = cmd->src; +++ myref.linesize[cidx+1] = cmd->srcstride; +++ myref1.data[cidx+1] = cmd->src1; +++ myref1.linesize[cidx+1] = cmd->srcstride1; +++ mymv.ref_idx[0] = cmd->ref_idx[0]; +++ mymv.ref_idx[1] = cmd->ref_idx[1]; +++ mymv.mv[0] = cmd->mv; +++ mymv.mv[1] = cmd->mv1; +++ chroma_mc_bi(s, cmd->dst, cmd->dststride, &myref, &myref1, +++ cmd->x_off, cmd->y_off, cmd->block_w, cmd->block_h, &mymv, cidx); +++ break; +++ } +++ } +++ s->num_mv_cmds = 0; +++} +++ ++ #endif ++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++@@ -2600,6 +2655,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI ++ if (s->enable_rpi && x_ctb + ctb_size >= s->ps.sps->width) { ++ int x; +++ // Perform inter prediction +++ rpi_execute_inter_cmds(s); ++ // Transform all blocks ++ rpi_execute_transform(s); ++ // Perform intra prediction and residual reconstruction ++@@ -3416,6 +3473,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ } ++ ++ #ifdef RPI +++#ifdef RPI_PRECLEAR ++ static av_cold void memclear16(int16_t *p, int n) ++ { ++ vpu_execute_code( vpu_get_fn(), p, n, 0, 0, 0, 1); ++@@ -3424,6 +3482,7 @@ static av_cold void memclear16(int16_t *p, int n) ++ // p[i] = 0; ++ } ++ #endif +++#endif ++ ++ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ { ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index a35ee4a..e3046a2 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -838,7 +838,7 @@ typedef struct HEVCLocalContext { ++ #define RPI_CMD_LUMA_UNI 0 ++ #define RPI_CMD_CHROMA_UNI 1 ++ #define RPI_CMD_LUMA_BI 2 ++-#define RPI_CMD_U_BI 3 +++#define RPI_CMD_CHROMA_BI 3 ++ #define RPI_CMD_V_BI 4 ++ ++ // RPI_PRECLEAR is not working yet - perhaps clearing on VPUs is flawed? ++-- ++2.5.0 ++ ++ ++From cf8758aad96c2c71abd5f2feb8ff85b5ac191b60 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 6 May 2015 13:03:50 +0100 ++Subject: [PATCH 10/68] Added VPU thread ++ ++--- ++ libavcodec/hevc.c | 11 +++-- ++ libavcodec/hevc.h | 1 + ++ libavcodec/rpi_qpu.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++-- ++ libavcodec/rpi_qpu.h | 2 + ++ 4 files changed, 133 insertions(+), 6 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index f60709e..7b0d951 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2518,8 +2518,10 @@ static void rpi_execute_transform(HEVCContext *s) ++ ++ ++ gpu_cache_flush(&s->coeffs_buf_accelerated); ++- vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); +++ s->vpu_id = vpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, &s->coeffs_buf_accelerated); +++ //vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); ++ //gpu_cache_flush(&s->coeffs_buf_accelerated); +++ //vpu_wait(s->vpu_id); ++ ++ for(i=0;i<4;i++) ++ s->num_coeffs[i] = 0; ++@@ -2655,10 +2657,12 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI ++ if (s->enable_rpi && x_ctb + ctb_size >= s->ps.sps->width) { ++ int x; ++- // Perform inter prediction ++- rpi_execute_inter_cmds(s); ++ // Transform all blocks ++ rpi_execute_transform(s); +++ // Perform inter prediction +++ rpi_execute_inter_cmds(s); +++ // Wait for transform completion +++ vpu_wait(s->vpu_id); ++ // Perform intra prediction and residual reconstruction ++ rpi_execute_pred_cmds(s); ++ // Perform deblocking for CTBs in this row ++@@ -3415,6 +3419,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ av_freep(&s->univ_pred_cmds); ++ ++ #ifdef EARLY_MALLOC +++ printf("hevc_decode_free\n"); ++ if (s->coeffs_buf_arm[0]) { ++ gpu_free(&s->coeffs_buf_default); ++ s->coeffs_buf_arm[0] = 0; ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index e3046a2..89636e4 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -922,6 +922,7 @@ typedef struct HEVCContext { ++ int num_xfm_cmds; ++ int num_mv_cmds; ++ int num_pred_cmds; +++ int vpu_id; ++ #endif ++ ++ uint8_t *cabac_state; ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 12ad5fb..378dd74 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -1,9 +1,13 @@ ++ #ifdef RPI ++-// Use the vcsm device for shared memory +++// define RPI_USE_VCSM to use the vcsm device for shared memory ++ // This works better than the mmap in that the memory can be cached, but requires a kernel modification to enable the device. ++ #define RPI_USE_VCSM ++-#define RPI_TIME_TOTAL_QPU ++-#define RPI_TIME_TOTAL_VPU +++// define RPI_TIME_TOTAL_QPU to print out how much time is spent in the QPU code +++//#define RPI_TIME_TOTAL_QPU +++// define RPI_TIME_TOTAL_VPU to print out how much time is spent in the VPI code +++//#define RPI_TIME_TOTAL_VPU +++// define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion +++#define RPI_ASYNC ++ ++ #include ++ #include ++@@ -113,6 +117,19 @@ static unsigned int Microseconds(void) { ++ } ++ #endif ++ +++#ifdef RPI_ASYNC +++pthread_t vpu_thread; +++static void *vpu_start(void *arg); +++ +++#define MAXCMDS 128 +++static pthread_cond_t post_cond = PTHREAD_COND_INITIALIZER; +++static pthread_mutex_t post_mutex = PTHREAD_MUTEX_INITIALIZER; +++ +++static int vpu_cmds[MAXCMDS][8]; +++static volatile int vpu_async_tail=0; // Contains the number of posted jobs +++static volatile int vpu_async_head=0; +++#endif +++ ++ // Connect to QPU, returns 0 on success. ++ static int gpu_init(volatile struct GPU **gpu) { ++ int mb = mbox_open(); ++@@ -164,12 +181,27 @@ static int gpu_init(volatile struct GPU **gpu) { ++ // And the transform coefficients ++ memcpy((void*)ptr->transMatrix2even, rpi_transMatrix2even, sizeof(rpi_transMatrix2even)); ++ +++#ifdef RPI_ASYNC +++ { +++ int err; +++ vpu_async_tail = 0; +++ vpu_async_head = 0; +++ err = pthread_create(&vpu_thread, NULL, vpu_start, NULL); +++ //printf("Created thread\n"); +++ if (err) { +++ printf("Failed to create vpu thread\n"); +++ return -4; +++ } +++ } +++#endif +++ ++ return 0; ++ } ++ ++ // Make sure we have exclusive access to the mailbox, and enable qpu if necessary. ++ static void gpu_lock(void) { ++ pthread_mutex_lock(&gpu_mutex); +++ ++ if (gpu==NULL) { ++ gpu_init(&gpu); ++ } ++@@ -264,6 +296,16 @@ static void gpu_term(void) ++ unsigned handle = gpu->vc_handle; ++ if (gpu==NULL) ++ return; +++ +++#ifdef RPI_ASYNC +++ { +++ void *res; +++ vpu_post_code(0, 0, 0, 0, 0, 0, -1, NULL); +++ pthread_join(vpu_thread, &res); +++ } +++#endif +++ +++ ++ unmapmem((void*)gpu, sizeof(struct GPU)); ++ mem_unlock(mb, handle); ++ mem_free(mb, handle); ++@@ -322,6 +364,79 @@ unsigned int vpu_get_constants(void) { ++ return gpu->vc + offsetof(struct GPU,transMatrix2even); ++ } ++ +++#ifdef RPI_ASYNC +++ +++static void *vpu_start(void *arg) { +++ while(1) { +++ pthread_mutex_lock(&post_mutex); +++ while( vpu_async_tail - vpu_async_head <= 0) +++ { +++ //printf("Checking number %d %d\n",vpu_async_head,vpu_async_tail); +++ pthread_cond_wait(&post_cond, &post_mutex); +++ } +++ int *p = vpu_cmds[vpu_async_head%MAXCMDS]; +++ pthread_mutex_unlock(&post_mutex); +++ +++ if (p[6] == -1) { +++ break; // Last job +++ } +++ if (p[7]) { +++ GPU_MEM_PTR_T *buf = (GPU_MEM_PTR_T *)p[7]; +++ //gpu_cache_flush(buf); +++ } +++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); +++ +++ pthread_mutex_lock(&post_mutex); +++ vpu_async_head++; +++ pthread_cond_broadcast(&post_cond); +++ pthread_mutex_unlock(&post_mutex); +++ } +++ +++ return NULL; +++} +++ +++// Post a command to the queue +++// Returns an id which we can use to wait for completion +++int vpu_post_code(unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, GPU_MEM_PTR_T *buf) +++{ +++ pthread_mutex_lock(&post_mutex); +++ { +++ int id = vpu_async_tail++; +++ int *p = vpu_cmds[id%MAXCMDS]; +++ int num = vpu_async_tail - vpu_async_head; +++ if (num>MAXCMDS) { +++ printf("Too many commands submitted\n"); +++ exit(-1); +++ } +++ p[0] = code; +++ p[1] = r0; +++ p[2] = r1; +++ p[3] = r2; +++ p[4] = r3; +++ p[5] = r4; +++ p[6] = r5; +++ p[7] = (int) buf; +++ if (num<=1) +++ pthread_cond_broadcast(&post_cond); // Otherwise the vpu thread must already be awake +++ pthread_mutex_unlock(&post_mutex); +++ return id; +++ } +++} +++ +++// Wait for completion of the given command +++void vpu_wait(int id) +++{ +++ pthread_mutex_lock(&post_mutex); +++ while( id + 1 - vpu_async_head > 0) +++ { +++ pthread_cond_wait(&post_cond, &post_mutex); +++ } +++ pthread_mutex_unlock(&post_mutex); +++} +++ +++#endif +++ +++ ++ unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5) ++ { ++ unsigned r; ++@@ -334,7 +449,9 @@ unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, ++ static int count=0; ++ static long long countr2=0; ++ #endif +++#ifndef RPI_ASYNC ++ gpu_lock(); +++#endif ++ #ifdef RPI_TIME_TOTAL_VPU ++ start_time = Microseconds(); ++ if (last_time==0) ++@@ -351,7 +468,9 @@ unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, ++ if ((count&0x7f)==0) ++ printf("VPU %d %lld On=%dms, Off=%dms\n",count,countr2,(int)(on_time/1000),(int)(off_time/1000)); ++ #endif +++#ifndef RPI_ASYNC ++ gpu_unlock(); +++#endif ++ return r; ++ } ++ ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 814fc3c..3526fce 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -36,6 +36,8 @@ extern unsigned int qpu_get_fn(int num); ++ extern unsigned int vpu_get_fn(void); ++ extern unsigned int vpu_get_constants(void); ++ extern unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); +++extern int vpu_post_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, GPU_MEM_PTR_T *buf); +++extern void vpu_wait( int id); ++ ++ // Simple test of shader code ++ extern int rpi_test_shader(void); ++-- ++2.5.0 ++ ++ ++From 6914dc93330c6d8494712589cdaeb0927ce9118d Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 6 May 2015 15:03:37 +0100 ++Subject: [PATCH 11/68] Added different signal when tail moves ++ ++--- ++ libavcodec/rpi_qpu.c | 11 ++++++----- ++ 1 file changed, 6 insertions(+), 5 deletions(-) ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 378dd74..d1c3e20 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -122,7 +122,8 @@ pthread_t vpu_thread; ++ static void *vpu_start(void *arg); ++ ++ #define MAXCMDS 128 ++-static pthread_cond_t post_cond = PTHREAD_COND_INITIALIZER; +++static pthread_cond_t post_cond_head = PTHREAD_COND_INITIALIZER; +++static pthread_cond_t post_cond_tail = PTHREAD_COND_INITIALIZER; ++ static pthread_mutex_t post_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++ static int vpu_cmds[MAXCMDS][8]; ++@@ -372,7 +373,7 @@ static void *vpu_start(void *arg) { ++ while( vpu_async_tail - vpu_async_head <= 0) ++ { ++ //printf("Checking number %d %d\n",vpu_async_head,vpu_async_tail); ++- pthread_cond_wait(&post_cond, &post_mutex); +++ pthread_cond_wait(&post_cond_tail, &post_mutex); ++ } ++ int *p = vpu_cmds[vpu_async_head%MAXCMDS]; ++ pthread_mutex_unlock(&post_mutex); ++@@ -388,7 +389,7 @@ static void *vpu_start(void *arg) { ++ ++ pthread_mutex_lock(&post_mutex); ++ vpu_async_head++; ++- pthread_cond_broadcast(&post_cond); +++ pthread_cond_broadcast(&post_cond_head); ++ pthread_mutex_unlock(&post_mutex); ++ } ++ ++@@ -417,7 +418,7 @@ int vpu_post_code(unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned ++ p[6] = r5; ++ p[7] = (int) buf; ++ if (num<=1) ++- pthread_cond_broadcast(&post_cond); // Otherwise the vpu thread must already be awake +++ pthread_cond_broadcast(&post_cond_tail); // Otherwise the vpu thread must already be awake ++ pthread_mutex_unlock(&post_mutex); ++ return id; ++ } ++@@ -429,7 +430,7 @@ void vpu_wait(int id) ++ pthread_mutex_lock(&post_mutex); ++ while( id + 1 - vpu_async_head > 0) ++ { ++- pthread_cond_wait(&post_cond, &post_mutex); +++ pthread_cond_wait(&post_cond_head, &post_mutex); ++ } ++ pthread_mutex_unlock(&post_mutex); ++ } ++-- ++2.5.0 ++ ++ ++From 0f997c095dc4aa3ddc5818c8188803ade60c8c72 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 7 May 2015 08:57:11 +0100 ++Subject: [PATCH 12/68] Add option to test for gpu_idle ++ ++--- ++ libavcodec/hevc.c | 3 ++- ++ libavcodec/rpi_qpu.c | 18 ++++++++++++++++++ ++ 2 files changed, 20 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 7b0d951..b703200 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2516,7 +2516,6 @@ static void rpi_execute_transform(HEVCContext *s) ++ // s->hevcdsp.idct[4-2](coeffs, 16); ++ //} ++ ++- ++ gpu_cache_flush(&s->coeffs_buf_accelerated); ++ s->vpu_id = vpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, &s->coeffs_buf_accelerated); ++ //vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); ++@@ -2658,6 +2657,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ if (s->enable_rpi && x_ctb + ctb_size >= s->ps.sps->width) { ++ int x; ++ // Transform all blocks +++ //printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); +++ ++ rpi_execute_transform(s); ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index d1c3e20..85f49db 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -199,6 +199,17 @@ static int gpu_init(volatile struct GPU **gpu) { ++ return 0; ++ } ++ +++// Returns 1 if the gpu is currently idle +++static int gpu_idle(void) +++{ +++ int ret = pthread_mutex_trylock(&gpu_mutex); +++ if (ret==0) { +++ pthread_mutex_unlock(&gpu_mutex); +++ return 1; +++ } +++ return 0; +++} +++ ++ // Make sure we have exclusive access to the mailbox, and enable qpu if necessary. ++ static void gpu_lock(void) { ++ pthread_mutex_lock(&gpu_mutex); ++@@ -400,6 +411,13 @@ static void *vpu_start(void *arg) { ++ // Returns an id which we can use to wait for completion ++ int vpu_post_code(unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, GPU_MEM_PTR_T *buf) ++ { +++ // If the gpu is idle then just run the command immediately +++ // This works, but doesn't seem to give any benefit +++ // if (gpu_idle()) { +++ // vpu_execute_code( code, r0, r1, r2, r3, r4, r5); +++ // return -1; // TODO perhaps a wraparound bug here? +++ // } +++ ++ pthread_mutex_lock(&post_mutex); ++ { ++ int id = vpu_async_tail++; ++-- ++2.5.0 ++ ++ ++From 3b7183a57c0936f10db7ae806db01ff6c977e095 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 7 May 2015 11:01:35 +0100 ++Subject: [PATCH 13/68] Added deblocking pass ++ ++--- ++ libavcodec/hevc.c | 33 +++++++++++++++++++++++++++------ ++ libavcodec/hevc.h | 7 ++++++- ++ libavcodec/hevc_filter.c | 6 +++++- ++ libavcodec/rpi_qpu.c | 2 +- ++ 4 files changed, 39 insertions(+), 9 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index b703200..c12693b 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2507,6 +2507,17 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ } ++ ++ #ifdef RPI +++static void rpi_execute_dblk_cmds(HEVCContext *s) +++{ +++ int n; +++ int ctb_size = 1 << s->ps.sps->log2_ctb_size; +++ int (*p)[2] = s->dblk_cmds; +++ for(n = s->num_dblk_cmds; n>0 ;n--,p++) { +++ ff_hevc_hls_filters(s, (*p)[0], (*p)[1], ctb_size); +++ } +++ s->num_dblk_cmds = 0; +++} +++ ++ static void rpi_execute_transform(HEVCContext *s) ++ { ++ int i=2; ++@@ -2620,7 +2631,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ ++ #ifdef RPI ++- int start_ctb_x = (s->sh.slice_ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; ++ s->enable_rpi = 1; // TODO this should depend on cross component and frame width etc. ++ #endif ++ ++@@ -2654,7 +2664,10 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ #ifdef RPI ++- if (s->enable_rpi && x_ctb + ctb_size >= s->ps.sps->width) { +++ if (s->enable_rpi) { +++ s->dblk_cmds[s->num_dblk_cmds][0] = x_ctb; +++ s->dblk_cmds[s->num_dblk_cmds++][1] = y_ctb; +++ if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { ++ int x; ++ // Transform all blocks ++ //printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++@@ -2667,10 +2680,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ // Perform intra prediction and residual reconstruction ++ rpi_execute_pred_cmds(s); ++ // Perform deblocking for CTBs in this row ++- for(x = start_ctb_x; x <= x_ctb; x += ctb_size) { // TODO this will fail for tiles ++- ff_hevc_hls_filters(s, x, y_ctb, ctb_size); ++- } ++- start_ctb_x = 0; +++ rpi_execute_dblk_cmds(s); +++ } ++ } ++ #endif ++ if (more_data < 0) { ++@@ -2688,6 +2699,16 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size); ++ } ++ +++#ifdef RPI +++ if (s->enable_rpi && s->num_dblk_cmds) { +++ rpi_execute_transform(s); +++ rpi_execute_inter_cmds(s); +++ vpu_wait(s->vpu_id); +++ rpi_execute_pred_cmds(s); +++ rpi_execute_dblk_cmds(s); +++ } +++#endif +++ ++ if (x_ctb + ctb_size >= s->ps.sps->width && ++ y_ctb + ctb_size >= s->ps.sps->height) ++ ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size); ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 89636e4..1fcf8b9 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -834,6 +834,8 @@ typedef struct HEVCLocalContext { ++ #define RPI_MAX_XFM_CMDS (16*3*(RPI_MAX_WIDTH/4)) ++ // Each block can have an intra prediction and a transform_add command ++ #define RPI_MAX_PRED_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) +++// Worst case is 16x16 CTUs +++#define RPI_MAX_DEBLOCK_CMDS (RPI_MAX_WIDTH*4/16) ++ ++ #define RPI_CMD_LUMA_UNI 0 ++ #define RPI_CMD_CHROMA_UNI 1 ++@@ -893,6 +895,9 @@ typedef struct HEVCPredCmd { ++ #endif ++ ++ typedef struct HEVCContext { +++#ifdef RPI +++ int dblk_cmds[RPI_MAX_DEBLOCK_CMDS][2]; +++#endif ++ const AVClass *c; // needed by private avoptions ++ AVCodecContext *avctx; ++ ++@@ -917,11 +922,11 @@ typedef struct HEVCContext { ++ GPU_MEM_PTR_T coeffs_buf_accelerated; ++ int16_t *coeffs_buf_arm[4]; ++ unsigned int coeffs_buf_vc[4]; ++- ++ int num_coeffs[4]; ++ int num_xfm_cmds; ++ int num_mv_cmds; ++ int num_pred_cmds; +++ int num_dblk_cmds; ++ int vpu_id; ++ #endif ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index e4c3da7..ea0af91 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -877,8 +877,12 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ if (s->threads_type & FF_THREAD_FRAME ) ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0); ++ } ++- } else if (s->threads_type & FF_THREAD_FRAME && x_end) +++ } else if (s->threads_type & FF_THREAD_FRAME && x_end) { +++ int newh = y + ctb_size - 4; +++ //int currh = s->ref->tf.progress->data[0]; +++ //if (((y + ctb_size)&63)==0) ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); +++ } ++ } ++ ++ void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size) ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 85f49db..3b6dae7 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -105,7 +105,7 @@ struct GPU ++ static pthread_mutex_t gpu_mutex = PTHREAD_MUTEX_INITIALIZER; ++ static volatile struct GPU* gpu = NULL; ++ ++-#ifdef RPI_TIME_TOTAL_QPU +++#if defined(RPI_TIME_TOTAL_QPU) || defined(RPI_TIME_TOTAL_VPU) ++ static unsigned int Microseconds(void) { ++ struct timespec ts; ++ unsigned int x; ++-- ++2.5.0 ++ ++ ++From 2e30016cc84d7b30f26bdeb1fbed69c3f495cded Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 7 May 2015 16:47:47 +0100 ++Subject: [PATCH 14/68] Added option to disable deblocking for non-ref frames ++ ++--- ++ libavcodec/hevc_filter.c | 10 ++++++++++ ++ 1 file changed, 10 insertions(+) ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index ea0af91..2cdd621 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -25,6 +25,8 @@ ++ //#define DISABLE_SAO ++ //#define DISABLE_DEBLOCK ++ //#define DISABLE_STRENGTHS +++// define DISABLE_DEBLOCK_NONREF for a 6% speed boost (by skipping deblocking on unimportant frames) +++//#define DISABLE_DEBLOCK_NONREF ++ ++ #include "libavutil/common.h" ++ #include "libavutil/internal.h" ++@@ -504,6 +506,14 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->ps.sps->pcm.loop_filter_disable_flag) || ++ s->ps.pps->transquant_bypass_enable_flag; ++ +++#ifdef DISABLE_DEBLOCK_NONREF +++ if ( s->nal_unit_type == NAL_TRAIL_N || +++ s->nal_unit_type == NAL_TSA_N || +++ s->nal_unit_type == NAL_STSA_N || +++ s->nal_unit_type == NAL_RADL_N || +++ s->nal_unit_type == NAL_RASL_N ) +++ return; // Don't deblock non-reference frames +++#endif ++ #ifdef DISABLE_DEBLOCK ++ return; ++ #endif ++-- ++2.5.0 ++ ++ ++From f5895e368e97fbd1ec04501b4be89a20f5cc5f29 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 11 May 2015 10:00:27 +0100 ++Subject: [PATCH 15/68] Moved buffers to VPU memory ++ ++--- ++ libavcodec/hevc_filter.c | 17 +++++++++++++- ++ libavcodec/utils.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ ++ libavutil/buffer.c | 6 +++++ ++ libavutil/buffer.h | 3 +++ ++ 4 files changed, 84 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 2cdd621..e1b32d4 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -866,6 +866,13 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ #undef CB ++ #undef CR ++ +++#ifdef RPI_INTER_QPU +++static void flush_buffer(AVBufferRef *bref) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); +++ gpu_cache_flush(p); +++} +++#endif +++ ++ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ { ++ int x_end = x >= s->ps.sps->width - ctb_size; ++@@ -888,9 +895,17 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0); ++ } ++ } else if (s->threads_type & FF_THREAD_FRAME && x_end) { ++- int newh = y + ctb_size - 4; +++ //int newh = y + ctb_size - 4; ++ //int currh = s->ref->tf.progress->data[0]; ++ //if (((y + ctb_size)&63)==0) +++ if (!( s->nal_unit_type == NAL_TRAIL_N || +++ s->nal_unit_type == NAL_TSA_N || +++ s->nal_unit_type == NAL_STSA_N || +++ s->nal_unit_type == NAL_RADL_N || +++ s->nal_unit_type == NAL_RASL_N )) { +++ flush_buffer(s->frame->buf[1]); +++ flush_buffer(s->frame->buf[2]); +++ } ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++ } ++diff --git a/libavcodec/utils.c b/libavcodec/utils.c ++index f532824..b32047a 100644 ++--- a/libavcodec/utils.c +++++ b/libavcodec/utils.c ++@@ -26,6 +26,12 @@ ++ */ ++ ++ #include "config.h" +++ +++#ifdef RPI +++// Move video buffers to GPU memory +++#define RPI_GPU_BUFFERS +++#endif +++ ++ #include "libavutil/atomic.h" ++ #include "libavutil/attributes.h" ++ #include "libavutil/avassert.h" ++@@ -63,6 +69,10 @@ ++ #include "libavutil/ffversion.h" ++ const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; ++ +++#ifdef RPI_GPU_BUFFERS +++#include "rpi_qpu.h" +++#endif +++ ++ #if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS ++ static int default_lockmgr_cb(void **arg, enum AVLockOp op) ++ { ++@@ -500,6 +510,47 @@ int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, ++ return ret; ++ } ++ +++#ifdef RPI_GPU_BUFFERS +++static void rpi_buffer_default_free(void *opaque, uint8_t *data) +++{ +++ GPU_MEM_PTR_T *p = opaque; +++ gpu_free(p); +++ av_free(p); +++} +++ +++static AVBufferRef *rpi_buffer_alloc(int size) +++{ +++ AVBufferRef *ret = NULL; +++ uint8_t *data = NULL; +++ GPU_MEM_PTR_T *p; +++ +++ static int total=0; +++ total+=size; +++ +++ p = av_malloc(sizeof *p); +++ if (!p) +++ return NULL; +++ +++ if (gpu_malloc_cached(size,p)<0) // Change this line to choose cached or uncached memory. The caching here refers to the ARM data cache. +++ return NULL; +++ +++ data = p->arm; +++ printf("Rpi alloc %d/%d ARM=%p VC=%x->%x\n",size,total,p->arm,p->vc,p->vc+size); +++ //memset(data, 64, size); +++ +++ if (!data) +++ return NULL; +++ +++ ret = av_buffer_create(data, size, rpi_buffer_default_free, p, 0); +++ if (!ret) { +++ gpu_free(p); +++ av_freep(&p); +++ } +++ +++ return ret; +++} +++#endif +++ ++ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) ++ { ++ FramePool *pool = avctx->internal->pool; ++@@ -547,6 +598,14 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) ++ av_buffer_pool_uninit(&pool->pools[i]); ++ pool->linesize[i] = linesize[i]; ++ if (size[i]) { +++#ifdef RPI_GPU_BUFFERS +++ if (avctx->codec_id == AV_CODEC_ID_HEVC) +++ pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, +++ CONFIG_MEMORY_POISONING ? +++ NULL : +++ rpi_buffer_alloc); +++ else +++#endif ++ pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, ++ CONFIG_MEMORY_POISONING ? ++ NULL : ++diff --git a/libavutil/buffer.c b/libavutil/buffer.c ++index bb112c2..7f8bfab 100644 ++--- a/libavutil/buffer.c +++++ b/libavutil/buffer.c ++@@ -400,3 +400,9 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) ++ ++ return ret; ++ } +++ +++// Return the opaque for the underlying frame (gives us a GPU_MEM_PTR_T) +++void *av_buffer_pool_opaque(AVBufferRef *ref) { +++ BufferPoolEntry *buf = av_buffer_get_opaque(ref); +++ return buf->opaque; +++} ++diff --git a/libavutil/buffer.h b/libavutil/buffer.h ++index b4399fd..0489002 100644 ++--- a/libavutil/buffer.h +++++ b/libavutil/buffer.h ++@@ -267,6 +267,9 @@ void av_buffer_pool_uninit(AVBufferPool **pool); ++ */ ++ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); ++ +++// Return the opaque for the underlying frame +++void *av_buffer_pool_opaque(AVBufferRef *ref); +++ ++ /** ++ * @} ++ */ ++-- ++2.5.0 ++ ++ ++From 969972796afe03290f6c2dd3251bce367b4c6847 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 11 May 2015 14:04:37 +0100 ++Subject: [PATCH 16/68] Prepared QPU execute code ++ ++--- ++ libavcodec/hevc.c | 227 ++++++++++++++++++++++++++++++++++++++++------- ++ libavcodec/hevc.h | 22 ++++- ++ libavcodec/hevc_filter.c | 7 +- ++ libavcodec/rpi_qpu.c | 55 +++++++++++- ++ libavcodec/rpi_qpu.h | 2 + ++ 5 files changed, 276 insertions(+), 37 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index c12693b..3b10ea0 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -42,17 +42,45 @@ ++ #include "profiles.h" ++ ++ #ifdef RPI ++-#include "rpi_qpu.h" ++-// For some unknown reason, the code seems to crash if I do a late malloc ++-#define EARLY_MALLOC ++-// Move Inter prediction into separate pass ++-#define RPI_INTER +++ #include "rpi_qpu.h" +++ // For some unknown reason, the code seems to crash if I do a late malloc +++ #define EARLY_MALLOC +++ // Move Inter prediction into separate pass +++ #define RPI_INTER ++ #endif ++ ++ // #define DISABLE_MC ++ ++ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ +++ +++#ifdef RPI_INTER_QPU +++ +++#define RPI_CHROMA_COMMAND_WORDS 12 +++// The QPU code for UV blocks only works up to a block width of 8 +++#define RPI_CHROMA_BLOCK_WIDTH 8 +++ +++#define ENCODE_COEFFS(c0, c1, c2, c3) (((-c0) & 0xff) | ((-c1) & 0xff) << 8 | ((-c2) & 0xff) << 16 | ((-c3) & 0xff) << 24) +++ +++// TODO Chroma only needs 4 taps +++static uint32_t rpi_filter_coefs[8][2] = { +++ { ENCODE_COEFFS( 0, 0, 0, 128), ENCODE_COEFFS( 0, 0, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -2, 58), ENCODE_COEFFS( 10, -2, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -4, 54), ENCODE_COEFFS( 16, -2, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -6, 46), ENCODE_COEFFS( 28, -4, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -4, 36), ENCODE_COEFFS( 36, -4, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -4, 28), ENCODE_COEFFS( 46, -6, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -2, 16), ENCODE_COEFFS( 54, -4, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, -2, 10), ENCODE_COEFFS( 58, -2, 0, 0 ) } +++}; +++ +++static uint32_t get_vc_address(AVBufferRef *bref) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); +++ return p->vc; +++} +++ +++#endif +++ ++ /** ++ * NOTE: Each function hls_foo correspond to the function foo in the ++ * specification (HLS stands for High Level Syntax). ++@@ -66,6 +94,7 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ static void pic_arrays_free(HEVCContext *s) ++ { ++ #ifdef RPI +++ ++ #ifdef EARLY_MALLOC ++ #else ++ printf("pic_arrays_free\n"); ++@@ -1971,6 +2000,43 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ s->sh.luma_offset_l0[current_mv.ref_idx[0]]); ++ ++ if (s->ps.sps->chroma_format_idc) { +++#ifdef RPI_INTER_QPU +++ if (s->enable_rpi) { +++ int reflist = 0; +++ int hshift = s->ps.sps->hshift[1]; +++ int vshift = s->ps.sps->vshift[1]; +++ const Mv *mv = ¤t_mv.mv[reflist]; +++ intptr_t mx = av_mod_uintp2(mv->x, 2 + hshift); +++ intptr_t my = av_mod_uintp2(mv->y, 2 + vshift); +++ intptr_t _mx = mx << (1 - hshift); +++ intptr_t _my = my << (1 - vshift); // Fractional part of motion vector +++ +++ int x1_c = x0_c + (mv->x >> (2 + hshift)); +++ int y1_c = y0_c + (mv->y >> (2 + hshift)); +++ int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width +++ +++ uint32_t *u = s->u_mvs[chan & 7]; +++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { +++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); +++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] +++ *u++ = rpi_filter_coefs[_mx][0]; +++ *u++ = rpi_filter_coefs[_mx][1]; +++ *u++ = rpi_filter_coefs[_my][0]; +++ *u++ = rpi_filter_coefs[_my][1]; +++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ } +++ } +++ s->u_mvs[chan & 7] = u; +++ return; +++ } +++#endif ++ RPI_REDIRECT(chroma_mc_uni)(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1], ++ 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]); ++@@ -2621,6 +2687,54 @@ static void rpi_execute_inter_cmds(HEVCContext *s) ++ ++ #endif ++ +++#ifdef RPI_INTER_QPU +++static void rpi_inter_clear(HEVCContext *s) +++{ +++ int i; +++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; +++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; +++ for(i=0;i<8;i++) { +++ s->u_mvs[i] = s->mvs_base[i]; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = pic_width; +++ *s->u_mvs[i]++ = pic_height; +++ *s->u_mvs[i]++ = s->frame->linesize[1]; +++ *s->u_mvs[i]++ = s->frame->linesize[2]; +++ s->u_mvs[i] += 3; // Padding words +++ } +++} +++ +++static void rpi_execute_inter_qpu(HEVCContext *s) +++{ +++ int k; +++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr.vc; +++ +++ if (s->sh.slice_type == I_SLICE) +++ return; +++ for(k=0;k<8;k++) { +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ } +++ +++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore +++ +++ qpu_run_shader8(qpu_get_fn(QPU_MC_SETUP_UV), +++ (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[2 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[3 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) +++ ); +++} +++#endif +++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ { ++ HEVCContext *s = avctxt->priv_data; ++@@ -2647,6 +2761,10 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ } ++ } ++ +++#ifdef RPI_INTER_QPU +++ rpi_inter_clear(s); +++#endif +++ ++ while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) { ++ int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ ++@@ -2668,19 +2786,30 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->dblk_cmds[s->num_dblk_cmds][0] = x_ctb; ++ s->dblk_cmds[s->num_dblk_cmds++][1] = y_ctb; ++ if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { ++- int x; +++#ifdef RPI_INTER_QPU +++ // Kick off inter prediction on QPUs +++ rpi_execute_inter_qpu(s); +++#endif ++ // Transform all blocks ++ //printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++- ++ rpi_execute_transform(s); ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); ++ // Wait for transform completion ++ vpu_wait(s->vpu_id); +++ +++ // Copy back reconstructed data +++ //memcpy(s->frame->data[0],s->dummy.arm,2048*64); +++ //memcpy(s->frame->data[1],s->dummy.arm,1024*32); +++ //memcpy(s->frame->data[2],s->dummy.arm,1024*32); +++ ++ // Perform intra prediction and residual reconstruction ++ rpi_execute_pred_cmds(s); ++ // Perform deblocking for CTBs in this row ++ rpi_execute_dblk_cmds(s); +++#ifdef RPI_INTER_QPU +++ rpi_inter_clear(s); +++#endif ++ } ++ } ++ #endif ++@@ -2701,6 +2830,9 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ ++ #ifdef RPI ++ if (s->enable_rpi && s->num_dblk_cmds) { +++#ifdef RPI_INTER_QPU +++ rpi_execute_inter_qpu(s); +++#endif ++ rpi_execute_transform(s); ++ rpi_execute_inter_cmds(s); ++ vpu_wait(s->vpu_id); ++@@ -3440,6 +3572,14 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ av_freep(&s->unif_xfm_cmds); ++ av_freep(&s->univ_pred_cmds); ++ +++#ifdef RPI_INTER_QPU +++ if (s->unif_mvs) { +++ gpu_free( &s->unif_mvs_ptr ); +++ s->unif_mvs = 0; +++ } +++#endif +++ //gpu_free(&s->dummy); +++ ++ #ifdef EARLY_MALLOC ++ printf("hevc_decode_free\n"); ++ if (s->coeffs_buf_arm[0]) { ++@@ -3535,34 +3675,59 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ if (!s->univ_pred_cmds) ++ goto fail; ++ ++- s->coeffs_buf_arm[0] = 0; ++- s->coeffs_buf_arm[2] = 0; +++#ifdef RPI_INTER_QPU +++ // We divide the image into blocks 256 wide and 64 high +++ // We support up to 2048 widths +++ // We compute the number of chroma motion vector commands for 4:4:4 format and 4x4 chroma blocks - assuming all blocks are B predicted +++ // Also add space for the startup command for each stream. +++ +++ { +++ int uv_commands_per_qpu = (1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS; +++ uint32_t *p; +++ gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); +++ s->unif_mvs = (uint32_t *) s->unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC +++ +++ // Set up initial locations for uniform streams +++ p = s->unif_mvs; +++ for(i = 0; i < 8; i++) { +++ s->mvs_base[i] = p; +++ p += uv_commands_per_qpu; +++ } +++ s->mc_filter_uv = qpu_get_fn(QPU_MC_FILTER_UV); +++ s->mc_filter_uv_b = qpu_get_fn(QPU_MC_FILTER_UV_B); +++ +++ } +++#endif +++ //gpu_malloc_uncached(2048*64,&s->dummy); ++ ++ #ifdef EARLY_MALLOC ++- int coeffs_in_ctb = 64*64; ++- int coefs_per_row = (2048/64) * coeffs_in_ctb * 3; // Allow space for chroma ++- printf("Allocated %d\n",coefs_per_row); ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); ++- s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; ++- if (!s->coeffs_buf_arm[0]) ++- goto fail; ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); ++- s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; ++- s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; ++- if (!s->coeffs_buf_arm[2]) ++- goto fail; ++- s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; ++- s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; ++- printf("Done\n"); +++ { +++ int coeffs_in_ctb = 64*64; +++ int coefs_per_row = (2048/64) * coeffs_in_ctb * 3; // Allow space for chroma +++ s->coeffs_buf_arm[0] = 0; +++ s->coeffs_buf_arm[2] = 0; +++ printf("Allocated %d\n",coefs_per_row); +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); +++ s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; +++ if (!s->coeffs_buf_arm[0]) +++ goto fail; +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); +++ s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; +++ s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; +++ if (!s->coeffs_buf_arm[2]) +++ goto fail; +++ s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; +++ s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; +++ printf("Done\n"); ++ #ifdef RPI_PRECLEAR ++- //memset(s->coeffs_buf_arm[0],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[0], coefs_per_row); ++- //memset(s->coeffs_buf_arm[2],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[2], coefs_per_row); ++- //memset(s->coeffs_buf_arm[3],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[3], coefs_per_row); +++ //memset(s->coeffs_buf_arm[0],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[0], coefs_per_row); +++ //memset(s->coeffs_buf_arm[2],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[2], coefs_per_row); +++ //memset(s->coeffs_buf_arm[3],0, sizeof(int16_t) * coefs_per_row); +++ memclear16(s->coeffs_buf_arm[3], coefs_per_row); ++ #endif ++- +++ } ++ #endif ++ ++ s->enable_rpi = 0; ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 1fcf8b9..a19d3ab 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -41,7 +41,11 @@ ++ ++ // define RPI to split the CABAC/prediction/transform into separate stages ++ #ifdef RPI ++-#include "rpi_qpu.h" +++ +++ #include "rpi_qpu.h" +++ // Use QPU for inter prediction +++ //#define RPI_INTER_QPU +++ ++ #endif ++ ++ #define MAX_DPB_SIZE 16 // A.4.1 ++@@ -914,7 +918,7 @@ typedef struct HEVCContext { ++ ++ #ifdef RPI ++ int enable_rpi; ++- HEVCMvCmd *unif_mv_cmds; +++ HEVCMvCmd *unif_mv_cmds; // TODO rename ++ HEVCXfmCmd *unif_xfm_cmds; ++ HEVCPredCmd *univ_pred_cmds; ++ int buf_width; ++@@ -928,6 +932,20 @@ typedef struct HEVCContext { ++ int num_pred_cmds; ++ int num_dblk_cmds; ++ int vpu_id; +++ //GPU_MEM_PTR_T dummy; +++#ifdef RPI_INTER_QPU +++ GPU_MEM_PTR_T unif_mvs_ptr; +++ uint32_t *unif_mvs; // Base of memory for motion vector commands +++ +++ // _base pointers are to the start of the row +++ uint32_t *mvs_base[8]; +++ // these pointers are to the next free space +++ uint32_t *u_mvs[8]; +++ // Function pointers +++ uint32_t mc_filter_uv; +++ uint32_t mc_filter_uv_b; +++#endif +++ ++ #endif ++ ++ uint8_t *cabac_state; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index e1b32d4..5b3d759 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -903,8 +903,11 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ s->nal_unit_type == NAL_STSA_N || ++ s->nal_unit_type == NAL_RADL_N || ++ s->nal_unit_type == NAL_RASL_N )) { ++- flush_buffer(s->frame->buf[1]); ++- flush_buffer(s->frame->buf[2]); +++ //flush_buffer(s->frame->buf[1]); +++ //flush_buffer(s->frame->buf[2]); +++ //memcpy(s->dummy.arm,s->frame->data[0],2048*64); +++ //memcpy(s->dummy.arm,s->frame->data[1],1024*32); +++ //memcpy(s->dummy.arm,s->frame->data[2],1024*32); ++ } ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 3b6dae7..e4dd58a 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -3,7 +3,7 @@ ++ // This works better than the mmap in that the memory can be cached, but requires a kernel modification to enable the device. ++ #define RPI_USE_VCSM ++ // define RPI_TIME_TOTAL_QPU to print out how much time is spent in the QPU code ++-//#define RPI_TIME_TOTAL_QPU +++#define RPI_TIME_TOTAL_QPU ++ // define RPI_TIME_TOTAL_VPU to print out how much time is spent in the VPI code ++ //#define RPI_TIME_TOTAL_VPU ++ // define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion ++@@ -30,7 +30,7 @@ ++ #endif ++ ++ // On Pi2 there is no way to access the VPU L2 cache ++-// GPU_MEM_FLG should be 4 for uncached memory. +++// GPU_MEM_FLG should be 4 for uncached memory. (Or C for alias to allocate in the VPU L2 cache) ++ // However, if using VCSM allocated buffers, need to use C at the moment because VCSM does not allocate uncached memory correctly ++ // The QPU crashes if we mix L2 cached and L2 uncached accesses due to a HW bug. ++ #define GPU_MEM_FLG 0xC ++@@ -549,6 +549,54 @@ void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int un ++ gpu_unlock(); ++ } ++ +++// Run a program on 8 QPUs with the given code and uniform stream (given in GPU addresses) +++void qpu_run_shader8(int code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8) +++{ +++ int i; +++#ifdef RPI_TIME_TOTAL_QPU +++ static int last_time=0; +++ static long long on_time=0; +++ static long long off_time=0; +++ int start_time; +++ int end_time; +++ static int count=0; +++#endif +++ +++ gpu_lock(); +++#ifdef RPI_TIME_TOTAL_QPU +++ start_time = Microseconds(); +++ if (last_time==0) +++ last_time = start_time; +++ off_time += start_time-last_time; +++#endif +++ for(i=0;i<8;i++) { +++ gpu->mail[i*2 + 1] = code; +++ } +++ gpu->mail[0 ] = unifs1; +++ gpu->mail[2 ] = unifs2; +++ gpu->mail[4 ] = unifs3; +++ gpu->mail[6 ] = unifs4; +++ gpu->mail[8 ] = unifs5; +++ gpu->mail[10] = unifs6; +++ gpu->mail[12] = unifs7; +++ gpu->mail[14] = unifs8; +++ execute_qpu( +++ gpu->mb, +++ 8 /* Number of QPUs */, +++ gpu->vc + offsetof(struct GPU, mail), +++ 1 /* no flush */, // Don't flush VPU L1 cache +++ 5000 /* timeout ms */); +++#ifdef RPI_TIME_TOTAL_QPU +++ end_time = Microseconds(); +++ last_time = end_time; +++ on_time += end_time - start_time; +++ count++; +++ if ((count&0x7f)==0) +++ printf("On=%dms, Off=%dms\n",(int)(on_time/1000),(int)(off_time/1000)); +++#endif +++ gpu_unlock(); +++} +++ ++ unsigned int qpu_get_fn(int num) { ++ // Make sure that the gpu is initialized ++ unsigned int *fn; ++@@ -585,6 +633,9 @@ unsigned int qpu_get_fn(int num) { ++ case QPU_MC_FILTER_UV_B: ++ fn = mc_filter_uv_b; ++ break; +++ case QPU_MC_INTERRUPT_EXIT8: +++ fn = mc_interrupt_exit8; +++ break; ++ case QPU_MC_END: ++ fn = mc_end; ++ break; ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 3526fce..2b22d98 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -16,6 +16,7 @@ extern void gpu_free(GPU_MEM_PTR_T *p); ++ extern void gpu_cache_flush(GPU_MEM_PTR_T *p); ++ ++ // QPU specific functions +++extern void qpu_run_shader8(int code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); ++ extern void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, int unifs9, int unifs10, int unifs11, int unifs12); ++ ++ enum { ++@@ -28,6 +29,7 @@ enum { ++ QPU_MC_SETUP_UV, ++ QPU_MC_FILTER_UV, ++ QPU_MC_FILTER_UV_B, +++ QPU_MC_INTERRUPT_EXIT8, ++ QPU_MC_END ++ }; ++ extern unsigned int qpu_get_fn(int num); ++-- ++2.5.0 ++ ++ ++From 90df0cacf3bed37328d465a925e446c7d3e9583b Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 13 May 2015 11:47:23 +0100 ++Subject: [PATCH 17/68] Drafted chroma interpolation on QPUs ++ ++--- ++ libavcodec/hevc.c | 5 ++- ++ libavcodec/hevc.h | 2 +- ++ libavcodec/hevc_filter.c | 6 ++- ++ libavcodec/rpi_qpu.c | 101 +++++++++++++++++++++++++++++++++++++++++++-- ++ libavcodec/rpi_qpu.h | 1 + ++ libavcodec/rpi_shader.c | 42 +++++++++---------- ++ libavcodec/rpi_shader.qasm | 42 +++++++++---------- ++ 7 files changed, 149 insertions(+), 50 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 3b10ea0..a5e1524 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -60,11 +60,11 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++ ++-#define ENCODE_COEFFS(c0, c1, c2, c3) (((-c0) & 0xff) | ((-c1) & 0xff) << 8 | ((-c2) & 0xff) << 16 | ((-c3) & 0xff) << 24) +++#define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++ // TODO Chroma only needs 4 taps ++ static uint32_t rpi_filter_coefs[8][2] = { ++- { ENCODE_COEFFS( 0, 0, 0, 128), ENCODE_COEFFS( 0, 0, 0, 0 ) }, +++ { ENCODE_COEFFS( 0, 0, 0, 64), ENCODE_COEFFS( 0, 0, 0, 0 ) }, ++ { ENCODE_COEFFS( 0, 0, -2, 58), ENCODE_COEFFS( 10, -2, 0, 0 ) }, ++ { ENCODE_COEFFS( 0, 0, -4, 54), ENCODE_COEFFS( 16, -2, 0, 0 ) }, ++ { ENCODE_COEFFS( 0, 0, -6, 46), ENCODE_COEFFS( 28, -4, 0, 0 ) }, ++@@ -2718,6 +2718,7 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ for(k=0;k<8;k++) { ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP); // Also need a dummy for V ++ } ++ ++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index a19d3ab..40470f5 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -44,7 +44,7 @@ ++ ++ #include "rpi_qpu.h" ++ // Use QPU for inter prediction ++- //#define RPI_INTER_QPU +++ // #define RPI_INTER_QPU ++ ++ #endif ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 5b3d759..9b6e26d 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -903,8 +903,10 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ s->nal_unit_type == NAL_STSA_N || ++ s->nal_unit_type == NAL_RADL_N || ++ s->nal_unit_type == NAL_RASL_N )) { ++- //flush_buffer(s->frame->buf[1]); ++- //flush_buffer(s->frame->buf[2]); +++#ifdef RPI_INTER_QPU +++ flush_buffer(s->frame->buf[1]); +++ flush_buffer(s->frame->buf[2]); +++#endif ++ //memcpy(s->dummy.arm,s->frame->data[0],2048*64); ++ //memcpy(s->dummy.arm,s->frame->data[1],1024*32); ++ //memcpy(s->dummy.arm,s->frame->data[2],1024*32); ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index e4dd58a..4d9eda8 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -33,7 +33,8 @@ ++ // GPU_MEM_FLG should be 4 for uncached memory. (Or C for alias to allocate in the VPU L2 cache) ++ // However, if using VCSM allocated buffers, need to use C at the moment because VCSM does not allocate uncached memory correctly ++ // The QPU crashes if we mix L2 cached and L2 uncached accesses due to a HW bug. ++-#define GPU_MEM_FLG 0xC +++#define GPU_MEM_FLG 0x4 +++// GPU_MEM_MAP is meaningless on the Pi2 and should be left at 0 (On Pi1 it allows ARM to access VPU L2 cache) ++ #define GPU_MEM_MAP 0x0 ++ ++ #define vcos_verify(x) ((x)>=0) ++@@ -165,6 +166,8 @@ static int gpu_init(volatile struct GPU **gpu) { ++ ptr->vc_handle = handle; ++ ptr->vc = vc; ++ +++ printf("GPU allocated at 0x%x\n",vc); +++ ++ *gpu = ptr; ++ ++ // Now copy over the QPU code into GPU memory ++@@ -304,10 +307,13 @@ int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p) { ++ ++ static void gpu_term(void) ++ { ++- int mb = gpu->mb; ++- unsigned handle = gpu->vc_handle; +++ int mb; +++ unsigned handle; +++ ++ if (gpu==NULL) ++ return; +++ mb = gpu->mb; +++ handle = gpu->vc_handle; ++ ++ #ifdef RPI_ASYNC ++ { ++@@ -648,6 +654,95 @@ unsigned int qpu_get_fn(int num) { ++ } ++ ++ #if 0 +++typedef unsigned int uint32_t; +++ +++typedef struct mvs_s { +++ GPU_MEM_PTR_T unif_mvs_ptr; +++ uint32_t *unif_mvs; // Base of memory for motion vector commands +++ +++ // _base pointers are to the start of the row +++ uint32_t *mvs_base[8]; +++ // these pointers are to the next free space +++ uint32_t *u_mvs[8]; +++ +++} HEVCContext; +++ +++#define RPI_CHROMA_COMMAND_WORDS 12 +++ +++static void rpi_inter_clear(HEVCContext *s) +++{ +++ int i; +++ for(i=0;i<8;i++) { +++ s->u_mvs[i] = s->mvs_base[i]; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 0; +++ *s->u_mvs[i]++ = 128; // w +++ *s->u_mvs[i]++ = 128; // h +++ *s->u_mvs[i]++ = 128; // stride u +++ *s->u_mvs[i]++ = 128; // stride v +++ s->u_mvs[i] += 3; // Padding words +++ } +++} +++ +++static void rpi_execute_inter_qpu(HEVCContext *s) +++{ +++ int k; +++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr.vc; +++ +++ for(k=0;k<8;k++) { +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP); // dummy location for V +++ } +++ +++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore +++ +++ qpu_run_shader8(qpu_get_fn(QPU_MC_SETUP_UV), +++ (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[2 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[3 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) +++ ); +++} +++ +++void rpi_test_qpu(void) +++{ +++ HEVCContext mvs; +++ HEVCContext *s = &mvs; +++ int i; +++ int uv_commands_per_qpu = (1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS; +++ uint32_t *p; +++ printf("Allocate memory\n"); +++ gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); +++ s->unif_mvs = (uint32_t *) s->unif_mvs_ptr.arm; +++ +++ // Set up initial locations for uniform streams +++ p = s->unif_mvs; +++ for(i = 0; i < 8; i++) { +++ s->mvs_base[i] = p; +++ p += uv_commands_per_qpu; +++ } +++ // Now run a simple program that should just quit immediately after a single texture fetch +++ rpi_inter_clear(s); +++ for(i=0;i<4;i++) { +++ printf("Launch QPUs\n"); +++ rpi_execute_inter_qpu(s); +++ printf("Done\n"); +++ } +++ printf("Free memory\n"); +++ gpu_free(&s->unif_mvs_ptr); +++ return; +++} +++#endif +++ +++#if 0 ++ ++ int32_t hcoeffs[] = {-4, 10, -21, 70, 90, -24, 11, -4}; ++ //int32_t hcoeffs[] = {1, 1, 1, 1, 1, 1, 1, 1}; ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 2b22d98..f9ad333 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -18,6 +18,7 @@ extern void gpu_cache_flush(GPU_MEM_PTR_T *p); ++ // QPU specific functions ++ extern void qpu_run_shader8(int code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); ++ extern void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, int unifs9, int unifs10, int unifs11, int unifs12); +++extern void rpi_test_qpu(void); ++ ++ enum { ++ QPU_MC_SETUP, ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 41cc2e1..d7ed297 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -152,23 +152,23 @@ unsigned int rpi_shader[] = { ++ /* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++ /* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++ /* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000400] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000408] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-/* [0x00000410] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000400] */ 0x55015fc6, 0x100248a2, // mov r2, rb21 ; mul24 r2, r0, ra0 +++/* [0x00000408] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000410] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++ /* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000420] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000420] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ /* [0x00000428] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000430] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000430] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ /* [0x00000438] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000440] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000440] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++ /* [0x00000448] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000450] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000450] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++ /* [0x00000458] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000460] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000460] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++ /* [0x00000468] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000470] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000470] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++ /* [0x00000478] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000480] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000480] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++ /* [0x00000488] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++ /* [0x00000490] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++ /* [0x00000498] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++@@ -179,20 +179,20 @@ unsigned int rpi_shader[] = { ++ /* [0x000004c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++ /* [0x000004c8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++ /* [0x000004d0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x000004d8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x000004d8] */ 0x8f54e1f6, 0xd0024821, // asr r0, r0, 14 ; mov r1, ra21 ++ /* [0x000004e0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x000004e8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x000004f0] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x000004f8] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000500] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000508] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000510] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000518] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000520] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000528] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x000004e8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x000004f0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x000004f8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000500] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000508] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000510] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000518] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000520] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000528] */ 0x8c9f223f, 0x100a0867, // add.ifnn r1, r1, r0 ; mov -, vw_wait ++ /* [0x00000530] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ /* [0x00000538] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000540] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x00000540] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++ /* [0x00000548] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++ /* [0x00000550] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++ /* [0x00000558] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 6851e83..02fdcb2 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -270,23 +270,23 @@ add t0s, ra_x2_base, r2 ++ ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++mov r2, rb21 ; mul24 r2, r0, ra0 +++nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++nop ; mul24 r3, ra1 << 1, r0 << 1 ++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++ nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++ nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++ nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++ nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-sub r0, r2, r3 +++add r0, r2, r3 ++ ++ mov r3, rb31 ++ ++@@ -302,23 +302,23 @@ sub.setf -, r3, 8 ; mov r1, ra22 ++ # apply horizontal filter ++ brr.anyn -, r:uvloop ++ max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 15 ; mov r1, ra21 +++asr r0, r0, 14 ; mov r1, ra21 ++ min.setf ra15, r0, rb22 ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r0, ra14, rb14 ++-sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-sub.ifnn r1, r1, r0 ; mov -, vw_wait +++nop ; mul24 r1, ra14, rb14 +++nop ; mul24 r0, ra13, rb13 +++add r1, r1, r0 ; mul24 r0, ra12, rb12 +++add r1, r1, r0 ; mul24 r0, ra11, rb11 +++add r1, r1, r0 ; mul24 r0, ra10, rb10 +++add r1, r1, r0 ; mul24 r0, ra9, rb9 +++add r1, r1, r0 ; mul24 r0, ra8, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb15 +++add.ifnn r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ brr.anyn -, r:uvloop ++-asr r1, r1, 15 +++asr r1, r1, 14 ++ min r1, r1, rb22 ++ max vpm, r1, 0 ++ ++-- ++2.5.0 ++ ++ ++From 552770488305e7574028fe760aa16d00c1020afa Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 13 May 2015 13:54:11 +0100 ++Subject: [PATCH 18/68] Fixed chroma inter prediction ++ ++--- ++ libavcodec/hevc.c | 8 +- ++ libavcodec/hevc.h | 2 +- ++ libavcodec/rpi_shader.c | 1170 ++++++++++++++++++++++---------------------- ++ libavcodec/rpi_shader.h | 22 +- ++ libavcodec/rpi_shader.qasm | 24 +- ++ 5 files changed, 617 insertions(+), 609 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index a5e1524..d4d272a 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -57,9 +57,11 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ #ifdef RPI_INTER_QPU ++ ++ #define RPI_CHROMA_COMMAND_WORDS 12 +++#define UV_COMMANDS_PER_QPU ((1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS) ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++ +++ ++ #define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++ // TODO Chroma only needs 4 taps ++@@ -2013,7 +2015,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ ++ int x1_c = x0_c + (mv->x >> (2 + hshift)); ++ int y1_c = y0_c + (mv->y >> (2 + hshift)); ++- int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width +++ //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width +++ int chan = x0>>8; ++ ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++@@ -2719,6 +2722,7 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP); // Also need a dummy for V +++ assert(s->u_mvs[k] - s->mvs_base[k] < UV_COMMANDS_PER_QPU); ++ } ++ ++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++@@ -3683,7 +3687,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ // Also add space for the startup command for each stream. ++ ++ { ++- int uv_commands_per_qpu = (1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS; +++ int uv_commands_per_qpu = UV_COMMANDS_PER_QPU; ++ uint32_t *p; ++ gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); ++ s->unif_mvs = (uint32_t *) s->unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 40470f5..442516d 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -44,7 +44,7 @@ ++ ++ #include "rpi_qpu.h" ++ // Use QPU for inter prediction ++- // #define RPI_INTER_QPU +++ #define RPI_INTER_QPU ++ ++ #endif ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index d7ed297..831633b 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -33,7 +33,7 @@ unsigned int rpi_shader[] = { ++ /* [0x00000040] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++ /* [0x00000048] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++ /* [0x00000050] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x00000058] */ 0x00000040, 0xe0020567, // mov ra21, 64 +++/* [0x00000058] */ 0x00000020, 0xe0020567, // mov ra21, 32 ++ /* [0x00000060] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++ /* [0x00000068] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++ /* [0x00000070] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++@@ -152,7 +152,7 @@ unsigned int rpi_shader[] = { ++ /* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++ /* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++ /* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000400] */ 0x55015fc6, 0x100248a2, // mov r2, rb21 ; mul24 r2, r0, ra0 +++/* [0x00000400] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++ /* [0x00000408] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++ /* [0x00000410] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++ /* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++@@ -178,9 +178,9 @@ unsigned int rpi_shader[] = { ++ /* [0x000004b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++ /* [0x000004c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++ /* [0x000004c8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004d0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x000004d8] */ 0x8f54e1f6, 0xd0024821, // asr r0, r0, 14 ; mov r1, ra21 ++-/* [0x000004e0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x000004d0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000004d8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000004e0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ /* [0x000004e8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++ /* [0x000004f0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++ /* [0x000004f8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++@@ -189,400 +189,400 @@ unsigned int rpi_shader[] = { ++ /* [0x00000510] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++ /* [0x00000518] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ /* [0x00000520] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000528] */ 0x8c9f223f, 0x100a0867, // add.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000528] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++ /* [0x00000530] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000538] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000540] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000548] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000550] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000558] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000560] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000568] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000570] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000578] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000580] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000588] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000590] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000598] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000538] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000540] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000548] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000550] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000558] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000560] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000568] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000570] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000578] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000580] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000588] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000590] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000598] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000005a0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000005a8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter ++-/* [0x000005a0] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000005a8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000005b0] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x000005b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000005c0] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x000005c8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000005d0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x000005d8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000005e0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x000005e8] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x000005f0] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x000005f8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000600] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000608] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000610] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000618] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000620] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000628] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000630] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000638] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000640] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000648] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000650] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000658] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000660] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000668] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000670] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000678] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000680] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000688] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000690] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000698] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000006b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000006d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000006f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000700] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000708] */ 0x000001d0, 0xf07809e7, // brr.anynn -, r:fast_path ++-/* [0x00000710] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000718] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000720] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000728] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000005b0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000005b8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000005c0] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x000005c8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000005d0] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x000005d8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000005e0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x000005e8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000005f0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x000005f8] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x00000600] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x00000608] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000610] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000618] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000620] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000628] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000630] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000638] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000640] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000648] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000650] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000658] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000660] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000668] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000670] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000678] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000680] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000688] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000690] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000698] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000006a0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000006c0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000006e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000700] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000708] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000710] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000718] */ 0x000001d0, 0xf07809e7, // brr.anynn -, r:fast_path +++/* [0x00000720] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000728] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000730] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000738] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :loop ++-/* [0x00000730] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000738] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000740] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000748] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000750] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000758] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000760] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000768] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000770] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000778] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000780] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000788] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000790] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000798] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000007a0] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000007a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000007b0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000007b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000007c0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000007c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000007d0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000007d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000007e0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000007e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000007f0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000007f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000800] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x00000808] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000810] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000818] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000820] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000828] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000830] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000838] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000840] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000848] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:loop ++-/* [0x00000850] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00000858] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00000860] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00000868] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000870] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000878] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000880] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000888] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000890] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000898] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x000008a0] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000008a8] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x000008b0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000008b8] */ 0xfffffe58, 0xf06809e7, // brr.anyn -, r:loop ++-/* [0x000008c0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x000008c8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000008d0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000008d8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000008e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000008e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000008f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000740] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000748] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000750] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000758] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000760] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000768] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000770] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000778] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000780] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000788] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000790] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000798] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x000007a0] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000007a8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000007b0] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000007b8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000007c0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000007c8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000007d0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000007d8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000007e0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000007e8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000007f0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000007f8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000800] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000808] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000810] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000818] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000820] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000828] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000830] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000838] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000840] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000848] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000850] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000858] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:loop +++/* [0x00000860] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00000868] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00000870] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00000878] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000880] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000888] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000890] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000898] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x000008a0] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x000008a8] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x000008b0] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000008b8] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x000008c0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000008c8] */ 0xfffffe58, 0xf06809e7, // brr.anyn -, r:loop +++/* [0x000008d0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x000008d8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000008e0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000008e8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000008f0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000008f8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000900] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // :fast_path ++-/* [0x000008f8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000908] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :fast_loop ++-/* [0x00000900] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000908] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000910] */ 0x95727d9b, 0x1004475f, // mov.ifz ra_y, ra_y_next ; mov rb31, r3 ++-/* [0x00000918] */ 0x95690dbf, 0x10044623, // mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch ++-/* [0x00000920] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000928] */ 0x929de5e4, 0x100248a1, // min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 ++-/* [0x00000930] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000938] */ 0xec414c87, 0x10024e20, // add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000940] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000948] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000950] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000958] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000960] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000968] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000970] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000978] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000980] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000988] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000990] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000998] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x000009a0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x000009a8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000009b0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000009b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000009c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000009c8] */ 0xffffff18, 0xf06809e7, // brr.anyn -, r:fast_loop ++-/* [0x000009d0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x000009d8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x000009e0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x000009e8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x000009f0] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x000009f8] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000a00] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000a08] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000a10] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000a18] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000a20] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000a28] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000a30] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000a38] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:fast_loop ++-/* [0x00000a40] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x00000a48] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a50] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a60] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000910] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000918] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000920] */ 0x95727d9b, 0x1004475f, // mov.ifz ra_y, ra_y_next ; mov rb31, r3 +++/* [0x00000928] */ 0x95690dbf, 0x10044623, // mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch +++/* [0x00000930] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000938] */ 0x929de5e4, 0x100248a1, // min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 +++/* [0x00000940] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000948] */ 0xec414c87, 0x10024e20, // add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 +++/* [0x00000950] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000958] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000960] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000968] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000970] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000978] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000980] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000988] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000990] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000998] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 +++/* [0x000009a0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x000009a8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x000009b0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x000009b8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000009c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000009c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000009d0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000009d8] */ 0xffffff18, 0xf06809e7, // brr.anyn -, r:fast_loop +++/* [0x000009e0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x000009e8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x000009f0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x000009f8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000a00] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000a08] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000a10] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000a18] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000a20] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000a28] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000a30] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000a38] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000a40] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000a48] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:fast_loop +++/* [0x00000a50] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x00000a58] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a60] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a68] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a70] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a78] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a80] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_b ++-/* [0x00000a78] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000a80] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000a88] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x00000a90] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000a98] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x00000aa0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000aa8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x00000ab0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000ab8] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x00000ac0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x00000ac8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x00000ad0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000ad8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000ae0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000ae8] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000af0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000af8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000b00] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000b08] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000b10] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000b18] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000b20] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000b28] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000b30] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000b38] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000b40] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000b48] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000b50] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000b58] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000b60] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000b68] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000b70] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 ++-/* [0x00000b78] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000b80] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000b88] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000b90] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000b98] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000ba0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ba8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bb0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bb8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000bc0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bc8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bd0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bd8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000be0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000be8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bf0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bf8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000c00] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000c08] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000c10] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000a88] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000a90] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000a98] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x00000aa0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000aa8] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x00000ab0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000ab8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x00000ac0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000ac8] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x00000ad0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x00000ad8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x00000ae0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000ae8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000af0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000af8] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000b00] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000b08] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000b10] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000b18] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000b20] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000b28] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000b30] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000b38] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000b40] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000b48] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000b50] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000b58] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000b60] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000b68] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000b70] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000b78] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000b80] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00000b88] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000b90] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000b98] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ba0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ba8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000bb0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bb8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bc0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bc8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000bd0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bd8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000be0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000be8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000bf0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000bf8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000c00] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000c08] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000c10] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000c18] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000c20] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :bloop ++-/* [0x00000c18] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000c20] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000c28] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000c30] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000c38] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000c40] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000c48] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000c50] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000c58] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000c60] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000c68] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000c70] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000c78] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000c80] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000c88] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000c90] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000c98] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000ca0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000ca8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000cb0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000cb8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000cc0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000cc8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000cd0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000cd8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000ce0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000ce8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x00000cf0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000cf8] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000d00] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000d08] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000d10] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000d18] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000d20] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000d28] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000d30] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:bloop ++-/* [0x00000d38] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00000d40] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00000d48] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00000d50] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000d58] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000d60] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000d68] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000d70] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000d78] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000d80] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000d88] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000d90] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000d98] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000da0] */ 0x8fc8f3f6, 0xd0020867, // asr r1, r1, 15 ; mov -, vr_wait ++-/* [0x00000da8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000db0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x00000db8] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:bloop ++-/* [0x00000dc0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000dc8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x00000dd0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x00000dd8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000de0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000de8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000df0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000c28] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000c30] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000c38] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000c40] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000c48] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000c50] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000c58] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000c60] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000c68] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000c70] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000c78] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000c80] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000c88] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000c90] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000c98] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000ca0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000ca8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000cb0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000cb8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000cc0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000cc8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000cd0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000cd8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000ce0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000ce8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000cf0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000cf8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000d00] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000d08] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000d10] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000d18] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000d20] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000d28] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000d30] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000d38] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000d40] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:bloop +++/* [0x00000d48] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00000d50] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00000d58] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00000d60] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000d68] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000d70] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000d78] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000d80] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000d88] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000d90] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000d98] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000da0] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000da8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000db0] */ 0x8fc8f3f6, 0xd0020867, // asr r1, r1, 15 ; mov -, vr_wait +++/* [0x00000db8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000dc0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x00000dc8] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:bloop +++/* [0x00000dd0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000dd8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00000de0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x00000de8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000df0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000df8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000e00] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_honly ++-/* [0x00000df8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000e00] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000e08] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x00000e10] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000e18] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x00000e20] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000e28] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x00000e30] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000e38] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x00000e40] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x00000e48] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x00000e50] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000e58] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000e60] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000e68] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000e70] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000e78] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000e80] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000e88] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000e90] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000e98] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000ea0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000ea8] */ 0x0c9de1c0, 0xd0021467, // add rb17, r0, -2 ++-/* [0x00000eb0] */ 0x919c71c0, 0xd0024812, // shl r0, r0, 7 ; mov rb18,r0 ++-/* [0x00000eb8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000ec0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000ec8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000ed0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000ed8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ee0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ee8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ef0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000ef8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f00] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f08] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f10] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000f18] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000f20] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000f28] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000f30] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000e08] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000e10] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000e18] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next +++/* [0x00000e20] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000e28] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 +++/* [0x00000e30] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000e38] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif +++/* [0x00000e40] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000e48] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x00000e50] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 +++/* [0x00000e58] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 +++/* [0x00000e60] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000e68] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 +++/* [0x00000e70] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000e78] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 +++/* [0x00000e80] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000e88] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000e90] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000e98] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000ea0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000ea8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000eb0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000eb8] */ 0x0c9de1c0, 0xd0021467, // add rb17, r0, -2 +++/* [0x00000ec0] */ 0x919c71c0, 0xd0024812, // shl r0, r0, 7 ; mov rb18,r0 +++/* [0x00000ec8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000ed0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000ed8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000ee0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000ee8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ef0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ef8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f00] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000f08] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f10] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f18] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f20] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000f28] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000f30] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000f38] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000f40] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :loop_honly ++-/* [0x00000f38] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000f40] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000f48] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000f50] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000f58] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000f60] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000f68] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000f70] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000f78] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000f80] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000f88] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000f90] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000f98] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000fa0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000fa8] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000fb0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000fb8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000fc0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000fc8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000fd0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000fd8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000fe0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000fe8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000ff0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000ff8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001000] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001008] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001010] */ 0x8d5927f6, 0x100269e1, // sub.setf -, r3, rb18 ; mov r1, ra22 ++-/* [0x00001018] */ 0x559f2fc1, 0x100049e0, // mov -, vw_wait ; mul24 r0, r0, r1 ++-/* [0x00001020] */ 0xfffffef8, 0xf06809e7, // brr.anyn -, r:loop_honly ++-/* [0x00001028] */ 0x0f9cf1c0, 0xd0020827, // asr r0, r0, 15 ++-/* [0x00001030] */ 0x129d61c0, 0x10020827, // min r0, r0, rb22 ++-/* [0x00001038] */ 0x139c01c0, 0xd0020c27, // max vpm, r0, 0 ++-/* [0x00001040] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001048] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001050] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001058] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000f48] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000f50] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000f58] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000f60] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000f68] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 +++/* [0x00000f70] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000f78] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000f80] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000f88] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000f90] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000f98] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000fa0] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000fa8] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000fb0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000fb8] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000fc0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000fc8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000fd0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000fd8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000fe0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000fe8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000ff0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000ff8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001000] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001008] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001010] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001018] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 +++/* [0x00001020] */ 0x8d5927f6, 0x100269e1, // sub.setf -, r3, rb18 ; mov r1, ra22 +++/* [0x00001028] */ 0x559f2fc1, 0x100049e0, // mov -, vw_wait ; mul24 r0, r0, r1 +++/* [0x00001030] */ 0xfffffef8, 0xf06809e7, // brr.anyn -, r:loop_honly +++/* [0x00001038] */ 0x0f9cf1c0, 0xd0020827, // asr r0, r0, 15 +++/* [0x00001040] */ 0x129d61c0, 0x10020827, // min r0, r0, rb22 +++/* [0x00001048] */ 0x139c01c0, 0xd0020c27, // max vpm, r0, 0 +++/* [0x00001050] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001058] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001060] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001068] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00001060] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001068] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00001070] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001078] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001070] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001078] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++ /* [0x00001080] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001088] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001090] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00001098] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000010a0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00001090] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001098] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010a0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000010a8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000010b0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_exit1 ++-/* [0x000010a8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000010b0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010b8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010b8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x000010c0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x000010c8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000010d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000010e0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000010d0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010d8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010e0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000010e8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000010f0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit ++-/* [0x000010e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000010f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000010f8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x00001100] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001108] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001110] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001118] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001110] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001118] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001120] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001128] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001130] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++@@ -592,225 +592,227 @@ unsigned int rpi_shader[] = { ++ /* [0x00001150] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001158] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001160] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001168] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00001170] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00001178] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00001168] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001170] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001178] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001180] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00001188] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit4 ++-/* [0x00001180] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001188] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001190] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001190] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x00001198] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x000011a0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000011b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011a8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011b0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x000011b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000011c0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000011c8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000011d0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000011c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000011d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000011d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000011e0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x000011d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000011e0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011e8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000011e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x000011f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x000011f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001200] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001208] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001200] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001208] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001210] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001218] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001220] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001228] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001230] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001238] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00001240] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00001248] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00001238] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001240] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001248] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001250] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00001258] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_setup_uv ++-/* [0x00001250] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00001258] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num ++-/* [0x00001260] */ 0x15827d80, 0x10020767, // mov ra_y, unif ++-/* [0x00001268] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif ++-/* [0x00001270] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00001278] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base ++-/* [0x00001280] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++-/* [0x00001288] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++-/* [0x00001290] */ 0x15827d80, 0x10021427, // mov rb16, unif ++-/* [0x00001298] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000012a0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++-/* [0x000012a8] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++-/* [0x000012b0] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x000012b8] */ 0x00000040, 0xe0020567, // mov ra21, 64 ++-/* [0x000012c0] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x000012c8] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++-/* [0x000012d0] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x000012d8] */ 0x00000040, 0xe0021567, // mov rb21, 64 ++-/* [0x000012e0] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x000012e8] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x000012f0] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x000012f8] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x00001300] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x00001308] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x00001310] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x00001318] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x00001320] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x00001328] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x00001330] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00001338] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00001340] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00001348] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00001350] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00001358] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00001360] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00001368] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001370] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00001378] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00001380] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00001388] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00001390] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00001398] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x000013a0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x000013a8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x000013b0] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x000013b8] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x000013c0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000013c8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x000013d0] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x000013d8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x000013e0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000013e8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x000013f0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000013f8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x00001400] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00001408] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00001410] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++-/* [0x00001418] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00001420] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x00001428] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x00001430] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00001438] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001440] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001260] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00001268] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num +++/* [0x00001270] */ 0x15827d80, 0x10020767, // mov ra_y, unif +++/* [0x00001278] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif +++/* [0x00001280] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00001288] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base +++/* [0x00001290] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00001298] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x000012a0] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x000012a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000012b0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x000012b8] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x000012c0] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x000012c8] */ 0x00000020, 0xe0020567, // mov ra21, 32 +++/* [0x000012d0] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x000012d8] */ 0x00000008, 0xe00205e7, // mov ra23, 8 +++/* [0x000012e0] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x000012e8] */ 0x00000040, 0xe0021567, // mov rb21, 64 +++/* [0x000012f0] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x000012f8] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00001300] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00001308] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x00001310] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x00001318] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x00001320] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x00001328] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x00001330] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x00001338] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x00001340] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00001348] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00001350] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00001358] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00001360] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00001368] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00001370] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00001378] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001380] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00001388] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00001390] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00001398] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000013a0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x000013a8] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x000013b0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x000013b8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x000013c0] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x000013c8] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x000013d0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000013d8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x000013e0] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x000013e8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x000013f0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000013f8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x00001400] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x00001408] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x00001410] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00001418] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00001420] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 +++/* [0x00001428] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00001430] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x00001438] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x00001440] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++ /* [0x00001448] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001450] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00001458] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00001460] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00001468] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001470] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00001478] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00001480] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00001450] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001458] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001460] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00001468] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00001470] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00001478] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001480] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00001488] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00001490] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv_b ++-/* [0x00001488] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00001490] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00001498] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000014a0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000014a8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000014b0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000014b8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000014c0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000014c8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000014d0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000014d8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000014e0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000014e8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000014f0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000014f8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00001500] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00001508] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00001510] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00001518] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00001520] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00001528] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00001530] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00001538] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00001540] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001548] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001550] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00001558] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 ++-/* [0x00001560] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00001568] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001570] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001578] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001580] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001588] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00001590] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001598] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015a0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015a8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000015b0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015b8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015c0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015c8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000015d0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015d8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015e0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015e8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x000015f0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000015f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001600] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00001498] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000014a0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000014a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000014b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000014b8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000014c0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000014c8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000014d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000014d8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000014e0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000014e8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000014f0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000014f8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00001500] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001508] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00001510] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00001518] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00001520] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00001528] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00001530] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00001538] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00001540] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00001548] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00001550] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001558] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001560] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00001568] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00001570] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00001578] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001580] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001588] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001590] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001598] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000015a0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015a8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015b0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015b8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000015c0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015c8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015d0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015d8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000015e0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015e8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015f0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000015f8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00001600] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00001608] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001610] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00001608] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00001610] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00001618] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00001620] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00001628] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00001630] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00001638] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00001640] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00001648] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00001650] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00001658] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001660] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00001668] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-/* [0x00001670] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00001678] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00001680] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00001688] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00001690] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00001698] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000016a0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000016a8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000016b0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000016b8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000016c0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000016c8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000016d0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000016d8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x000016e0] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x000016e8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x000016f0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x000016f8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001700] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001708] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001710] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001718] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001720] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00001728] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00001730] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00001738] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00001740] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00001748] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00001750] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00001758] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00001760] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00001768] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00001770] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00001778] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00001780] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00001788] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x00001790] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00001798] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x000017a0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000017a8] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x000017b0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000017b8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x000017c0] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x000017c8] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x000017d0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000017d8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000017e0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000017e8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000017f0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000017f8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001800] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00001808] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001810] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00001618] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001620] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00001628] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00001630] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001638] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00001640] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001648] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00001650] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00001658] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00001660] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00001668] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001670] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00001678] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++/* [0x00001680] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00001688] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00001690] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00001698] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000016a0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000016a8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000016b0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000016b8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000016c0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000016c8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000016d0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000016d8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000016e0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000016e8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x000016f0] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x000016f8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00001700] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00001708] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001710] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001718] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001720] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001728] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001730] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00001738] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00001740] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00001748] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00001750] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00001758] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00001760] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00001768] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00001770] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00001778] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00001780] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00001788] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00001790] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00001798] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x000017a0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000017a8] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x000017b0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000017b8] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x000017c0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000017c8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000017d0] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x000017d8] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x000017e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000017e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000017f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000017f8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00001800] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001808] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001810] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00001818] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001820] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index db971f4..3464cdb 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -5,16 +5,16 @@ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 146) ++-#define mc_filter (rpi_shader + 360) ++-#define mc_filter_b (rpi_shader + 670) ++-#define mc_filter_honly (rpi_shader + 894) ++-#define mc_exit (rpi_shader + 1048) ++-#define mc_exit1 (rpi_shader + 1066) ++-#define mc_interrupt_exit (rpi_shader + 1082) ++-#define mc_interrupt_exit4 (rpi_shader + 1120) ++-#define mc_interrupt_exit8 (rpi_shader + 1142) ++-#define mc_setup_uv (rpi_shader + 1172) ++-#define mc_filter_uv_b (rpi_shader + 1314) ++-#define mc_end (rpi_shader + 1542) +++#define mc_filter (rpi_shader + 364) +++#define mc_filter_b (rpi_shader + 674) +++#define mc_filter_honly (rpi_shader + 898) +++#define mc_exit (rpi_shader + 1052) +++#define mc_exit1 (rpi_shader + 1070) +++#define mc_interrupt_exit (rpi_shader + 1086) +++#define mc_interrupt_exit4 (rpi_shader + 1124) +++#define mc_interrupt_exit8 (rpi_shader + 1146) +++#define mc_setup_uv (rpi_shader + 1176) +++#define mc_filter_uv_b (rpi_shader + 1318) +++#define mc_end (rpi_shader + 1546) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 02fdcb2..4809e1d 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -21,7 +21,7 @@ ++ # rb19 next ra16 ++ # ++ # ra20 1 ++-# ra21 64 +++# ra21 32 ++ # ra22 256 ++ # ra23 8 ++ # ++@@ -97,7 +97,7 @@ add rb24, r1, r0 ++ # load constants ++ ++ mov ra20, 1 ++-mov ra21, 64 +++mov ra21, 32 ++ mov ra22, 256 ++ mov ra23, 8 ++ ++@@ -270,7 +270,7 @@ add t0s, ra_x2_base, r2 ++ ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++-mov r2, rb21 ; mul24 r2, r0, ra0 +++nop ; mul24 r2, r0, ra0 ++ nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++ nop ; mul24 r3, ra1 << 1, r0 << 1 ++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++@@ -301,9 +301,9 @@ sub.setf -, r3, 8 ; mov r1, ra22 ++ ++ # apply horizontal filter ++ brr.anyn -, r:uvloop ++-max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 14 ; mov r1, ra21 ++-min.setf ra15, r0, rb22 +++mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll +++asr ra15, r0, 8 ; nop +++nop ; nop # Delay slot 3 (TODO move more of the context scroll into here) ++ ++ # apply vertical filter and write to VPM ++ ++@@ -315,12 +315,14 @@ add r1, r1, r0 ; mul24 r0, ra10, rb10 ++ add r1, r1, r0 ; mul24 r0, ra9, rb9 ++ add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-add.ifnn r1, r1, r0 ; mov -, vw_wait +++add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-brr.anyn -, r:uvloop ++ asr r1, r1, 14 ++-min r1, r1, rb22 ++-max vpm, r1, 0 +++add r1, r1, ra21 +++brr.anyn -, r:uvloop +++asr r1, r1, 6 # Delay 1 +++min r1, r1, rb22 # Delay 2 +++max vpm, r1, 0 # Delay 3 ++ ++ # DMA out for U ++ ++@@ -1161,7 +1163,7 @@ add rb24, r1, r0 ++ # load constants ++ ++ mov ra20, 1 ++-mov ra21, 64 +++mov ra21, 32 ++ mov ra22, 256 ++ mov ra23, 8 ++ ++-- ++2.5.0 ++ ++ ++From 436c31805d8a53ace0fea63976a464c0e2d2a93c Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 13 May 2015 14:37:32 +0100 ++Subject: [PATCH 19/68] Removed unused luma functions ++ ++--- ++ libavcodec/hevc.c | 4 +- ++ libavcodec/rpi_qpu.c | 32 +- ++ libavcodec/rpi_shader.c | 1097 +++++++++++++------------------------------- ++ libavcodec/rpi_shader.h | 19 +- ++ libavcodec/rpi_shader.qasm | 970 +++------------------------------------ ++ 5 files changed, 396 insertions(+), 1726 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index d4d272a..b4a3707 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2720,8 +2720,8 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ return; ++ for(k=0;k<8;k++) { ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++- s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++- s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP); // Also need a dummy for V +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for V ++ assert(s->u_mvs[k] - s->mvs_base[k] < UV_COMMANDS_PER_QPU); ++ } ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 4d9eda8..4e90cc1 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -172,7 +172,7 @@ static int gpu_init(volatile struct GPU **gpu) { ++ ++ // Now copy over the QPU code into GPU memory ++ { ++- int num_bytes = qpu_get_fn(QPU_MC_END) - qpu_get_fn(QPU_MC_SETUP); +++ int num_bytes = qpu_get_fn(QPU_MC_END) - qpu_get_fn(QPU_MC_SETUP_UV); ++ assert(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->qpu_code, rpi_shader, num_bytes); ++ } ++@@ -612,24 +612,24 @@ unsigned int qpu_get_fn(int num) { ++ gpu_unlock(); ++ } ++ switch(num) { ++- case QPU_MC_SETUP: ++- fn = mc_setup; ++- break; ++- case QPU_MC_FILTER: ++- fn = mc_filter; ++- break; +++ //case QPU_MC_SETUP: +++ // fn = mc_setup; +++ // break; +++ //case QPU_MC_FILTER: +++ // fn = mc_filter; +++ // break; ++ case QPU_MC_EXIT: ++ fn = mc_exit; ++ break; ++- case QPU_MC_INTERRUPT_EXIT: ++- fn = mc_interrupt_exit; ++- break; ++- case QPU_MC_FILTER_B: ++- fn = mc_filter_b; ++- break; ++- case QPU_MC_FILTER_HONLY: ++- fn = mc_filter_honly; ++- break; +++ //case QPU_MC_INTERRUPT_EXIT: +++ // fn = mc_interrupt_exit; +++ // break; +++ //case QPU_MC_FILTER_B: +++ // fn = mc_filter_b; +++ // break; +++ //case QPU_MC_FILTER_HONLY: +++ // fn = mc_filter_honly; +++ // break; ++ case QPU_MC_SETUP_UV: ++ fn = mc_setup_uv; ++ break; ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 831633b..170e8ac 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -21,798 +21,331 @@ __declspec(align(8)) ++ __attribute__((aligned(8))) ++ #endif ++ unsigned int rpi_shader[] = { ++-// ::mc_setup +++// ::mc_setup_uv ++ /* [0x00000000] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++ /* [0x00000008] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num ++ /* [0x00000010] */ 0x15827d80, 0x10020767, // mov ra_y, unif ++ /* [0x00000018] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif ++-/* [0x00000020] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++-/* [0x00000028] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++-/* [0x00000030] */ 0x15827d80, 0x10021427, // mov rb16, unif ++-/* [0x00000038] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000040] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++-/* [0x00000048] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++-/* [0x00000050] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x00000058] */ 0x00000020, 0xe0020567, // mov ra21, 32 ++-/* [0x00000060] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x00000068] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++-/* [0x00000070] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000078] */ 0x00000040, 0xe0021567, // mov rb21, 64 ++-/* [0x00000080] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000088] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x00000090] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x00000098] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x000000a0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x000000a8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x000000b0] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x000000b8] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x000000c0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x000000c8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000d0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x000000d8] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x000000e0] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x000000e8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x000000f0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x000000f8] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000100] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000108] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000110] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000118] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000120] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000128] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000130] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000138] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000140] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000148] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000150] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000158] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000160] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000168] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000170] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000178] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x00000180] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x00000188] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x00000190] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x00000198] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000001a0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 +++/* [0x00000020] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000028] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base +++/* [0x00000030] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00000038] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x00000040] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x00000048] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000050] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x00000058] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x00000060] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x00000068] */ 0x00000020, 0xe0020567, // mov ra21, 32 +++/* [0x00000070] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000078] */ 0x00000008, 0xe00205e7, // mov ra23, 8 +++/* [0x00000080] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000088] */ 0x00000040, 0xe0021567, // mov rb21, 64 +++/* [0x00000090] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000098] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x000000a0] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x000000a8] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x000000b0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x000000b8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x000000c0] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x000000c8] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x000000d0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x000000d8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x000000e0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000000e8] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x000000f0] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x000000f8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000100] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000108] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000110] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000118] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000120] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000128] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000130] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000138] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000140] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000148] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000150] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000158] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000160] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000168] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000170] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000178] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000180] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000188] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x00000190] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x00000198] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x000001a0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++ /* [0x000001a8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001b0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x000001b8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x000001c0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000001b0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000001b8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001c0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++ /* [0x000001c8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001d0] */ 0x4c9d00cf, 0x10024821, // add r0, r0, r3; mul24 r1, r1, rb_pitch ++-/* [0x000001d8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x000001e0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001e8] */ 0x949dc5c0, 0xd0025890, // and r2, r2, ~3; mov ra_x_base, r0 ++-/* [0x000001f0] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x000001f8] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00000200] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000208] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000210] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000218] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000220] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000228] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000230] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000238] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000240] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x000001d0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x000001d8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x000001e0] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x000001e8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000001f0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000001f8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000200] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000208] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000210] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000218] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000220] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000228] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000230] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv ++-/* [0x00000248] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000250] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000258] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000260] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000268] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000270] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000278] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000280] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000288] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000290] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000298] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000002a0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002b0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002d0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000002d8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x000002e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002e8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000002f0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000002f8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000300] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000330] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000340] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000350] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000360] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000368] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000370] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000378] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000380] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000388] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000390] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000398] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003a0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000238] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000240] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000248] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000250] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000258] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000260] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000268] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000270] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000278] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000280] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000288] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000290] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000298] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002a0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002a8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002b0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002b8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002c0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000002c8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000002d0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000002e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000002f0] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x000002f8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000300] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000308] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000310] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000318] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000320] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000340] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000350] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000360] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000368] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000370] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000378] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000380] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000388] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000390] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x000003a8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003b0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000003b8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003c0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003c8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003d0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003d8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003e0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000400] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000408] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000410] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000420] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000428] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000430] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000438] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000440] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000448] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000450] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000458] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000460] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000468] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000470] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000478] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000480] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000488] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000490] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000498] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x000004a0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x000004a8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000004b0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000004b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000004c0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000004c8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004d0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000004d8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000004e0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000004e8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x000004f0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x000004f8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000500] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000508] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000510] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000518] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000520] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000528] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000530] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000538] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000540] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000548] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000550] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000558] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000560] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000568] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000570] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000578] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000580] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000588] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000590] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000598] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000005a0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000005a8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// ::mc_filter ++-/* [0x000005b0] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000005b8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000005c0] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x000005c8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000005d0] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x000005d8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000005e0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x000005e8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000005f0] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x000005f8] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x00000600] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x00000608] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000610] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000618] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000620] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000628] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000630] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000638] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000640] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000648] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000650] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000658] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000660] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000668] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000670] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000678] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000680] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000688] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000690] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000698] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000006a0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000006c0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000006e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000700] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000708] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000710] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000718] */ 0x000001d0, 0xf07809e7, // brr.anynn -, r:fast_path ++-/* [0x00000720] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000728] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000730] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000738] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++-// :loop ++-/* [0x00000740] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000748] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000750] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000758] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000760] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000768] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000770] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000778] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000780] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000788] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000790] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000798] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x000007a0] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000007a8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000007b0] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000007b8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000007c0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000007c8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000007d0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000007d8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000007e0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000007e8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000007f0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000007f8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000800] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000808] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000810] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x00000818] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000820] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000828] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000830] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000838] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000840] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000848] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000850] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000858] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:loop ++-/* [0x00000860] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00000868] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00000870] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00000878] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000880] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000888] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000890] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000898] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x000008a0] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x000008a8] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x000008b0] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000008b8] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x000008c0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000008c8] */ 0xfffffe58, 0xf06809e7, // brr.anyn -, r:loop ++-/* [0x000008d0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x000008d8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000008e0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000008e8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000008f0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000008f8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000900] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// :fast_path ++-/* [0x00000908] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++-// :fast_loop ++-/* [0x00000910] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000918] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000920] */ 0x95727d9b, 0x1004475f, // mov.ifz ra_y, ra_y_next ; mov rb31, r3 ++-/* [0x00000928] */ 0x95690dbf, 0x10044623, // mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch ++-/* [0x00000930] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000938] */ 0x929de5e4, 0x100248a1, // min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 ++-/* [0x00000940] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000948] */ 0xec414c87, 0x10024e20, // add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000950] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000958] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000960] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000968] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000970] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000978] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000980] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000988] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000990] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000998] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 ++-/* [0x000009a0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x000009a8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x000009b0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x000009b8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000009c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000009c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000009d0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000009d8] */ 0xffffff18, 0xf06809e7, // brr.anyn -, r:fast_loop ++-/* [0x000009e0] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x000009e8] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x000009f0] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x000009f8] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000a00] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000a08] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000a10] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000a18] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000a20] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000a28] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000a30] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000a38] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000a40] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000a48] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:fast_loop ++-/* [0x00000a50] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x00000a58] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a60] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a68] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a70] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a78] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a80] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// ::mc_filter_b ++-/* [0x00000a88] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000a90] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000a98] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x00000aa0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000aa8] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x00000ab0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000ab8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x00000ac0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000ac8] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x00000ad0] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x00000ad8] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x00000ae0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000ae8] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000af0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000af8] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000b00] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000b08] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000b10] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000b18] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000b20] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000b28] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000b30] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000b38] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000b40] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000b48] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000b50] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000b58] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000b60] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000b68] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000b70] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000b78] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000b80] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 ++-/* [0x00000b88] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000b90] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000b98] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ba0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ba8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000bb0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bb8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bc0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bc8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000bd0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bd8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000be0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000be8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000bf0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000bf8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000c00] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000c08] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000c10] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000c18] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000c20] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++-// :bloop ++-/* [0x00000c28] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000c30] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000c38] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000c40] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000c48] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000c50] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000c58] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000c60] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000c68] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000c70] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000c78] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000c80] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000c88] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000c90] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000c98] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000ca0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000ca8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000cb0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000cb8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000cc0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000cc8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000cd0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000cd8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000ce0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000ce8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000cf0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000cf8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x00000d00] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000d08] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000d10] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000d18] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000d20] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000d28] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000d30] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000d38] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000d40] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:bloop ++-/* [0x00000d48] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00000d50] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00000d58] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00000d60] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000d68] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000d70] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000d78] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000d80] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000d88] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000d90] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000d98] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000da0] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000da8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000db0] */ 0x8fc8f3f6, 0xd0020867, // asr r1, r1, 15 ; mov -, vr_wait ++-/* [0x00000db8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000dc0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x00000dc8] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:bloop ++-/* [0x00000dd0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000dd8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x00000de0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x00000de8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000df0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000df8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000e00] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// ::mc_filter_honly ++-/* [0x00000e08] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000e10] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000e18] */ 0x156e7d80, 0x10020667, // mov ra_x2shift, ra_x2shift_next ++-/* [0x00000e20] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000e28] */ 0x0c9c81c0, 0xd00208a7, // add r2, r0, 8 ++-/* [0x00000e30] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000e38] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3,unif ++-/* [0x00000e40] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000e48] */ 0x139c05c0, 0xd00208a7, // max r2, r2, 0 ++-/* [0x00000e50] */ 0x129d95c0, 0x100208a7, // min r2, r2, rb_frame_width_minus_1 ++-/* [0x00000e58] */ 0x119c35c0, 0xd00206e7, // shl ra_x2shift_next, r2, 3 ++-/* [0x00000e60] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000e68] */ 0x0c9e74c0, 0x100208a7, // add r2, r2, r3 ++-/* [0x00000e70] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000e78] */ 0x149dc5c0, 0xd00206a7, // and ra_x2_base_next, r2, ~3 ++-/* [0x00000e80] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000e88] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000e90] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000e98] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000ea0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000ea8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000eb0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000eb8] */ 0x0c9de1c0, 0xd0021467, // add rb17, r0, -2 ++-/* [0x00000ec0] */ 0x919c71c0, 0xd0024812, // shl r0, r0, 7 ; mov rb18,r0 ++-/* [0x00000ec8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000ed0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000ed8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000ee0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000ee8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ef0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ef8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f00] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000f08] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f10] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f18] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f20] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000f28] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000f30] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000f38] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000f40] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++-// :loop_honly ++-/* [0x00000f48] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000f50] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000f58] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000f60] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000f68] */ 0xee654987, 0x10024860, // shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 ++-/* [0x00000f70] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000f78] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000f80] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000f88] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000f90] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000f98] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000fa0] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000fa8] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000fb0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000fb8] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000fc0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000fc8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000fd0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000fd8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000fe0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000fe8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000ff0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000ff8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00001000] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00001008] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001010] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001018] */ 0x8d9df4ff, 0x10024823, // sub r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001020] */ 0x8d5927f6, 0x100269e1, // sub.setf -, r3, rb18 ; mov r1, ra22 ++-/* [0x00001028] */ 0x559f2fc1, 0x100049e0, // mov -, vw_wait ; mul24 r0, r0, r1 ++-/* [0x00001030] */ 0xfffffef8, 0xf06809e7, // brr.anyn -, r:loop_honly ++-/* [0x00001038] */ 0x0f9cf1c0, 0xd0020827, // asr r0, r0, 15 ++-/* [0x00001040] */ 0x129d61c0, 0x10020827, // min r0, r0, rb22 ++-/* [0x00001048] */ 0x139c01c0, 0xd0020c27, // max vpm, r0, 0 ++-/* [0x00001050] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001058] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001060] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001068] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// ::mc_exit ++-/* [0x00001070] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001078] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00001080] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001088] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001090] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001098] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010a0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000010a8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000010b0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_exit1 ++-/* [0x000010b8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000010c0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010c8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010d0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010d8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000010e0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000010e8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000010f0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_interrupt_exit ++-/* [0x000010f8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001100] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001108] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001110] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001118] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001120] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001128] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001130] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001138] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001140] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001148] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001150] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001158] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001160] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001168] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001170] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001178] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00001180] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00001188] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_interrupt_exit4 ++-/* [0x00001190] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001198] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011a0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011a8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011b0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000011c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000011c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000011d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000011d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000011e0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_interrupt_exit8 ++-/* [0x000011e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000011f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000011f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001200] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001208] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001210] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001218] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001220] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001228] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001230] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001238] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001240] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001248] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00001250] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00001258] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_setup_uv ++-/* [0x00001260] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00001268] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num ++-/* [0x00001270] */ 0x15827d80, 0x10020767, // mov ra_y, unif ++-/* [0x00001278] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif ++-/* [0x00001280] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00001288] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base ++-/* [0x00001290] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++-/* [0x00001298] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++-/* [0x000012a0] */ 0x15827d80, 0x10021427, // mov rb16, unif ++-/* [0x000012a8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000012b0] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++-/* [0x000012b8] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++-/* [0x000012c0] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x000012c8] */ 0x00000020, 0xe0020567, // mov ra21, 32 ++-/* [0x000012d0] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x000012d8] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++-/* [0x000012e0] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x000012e8] */ 0x00000040, 0xe0021567, // mov rb21, 64 ++-/* [0x000012f0] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x000012f8] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x00001300] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x00001308] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x00001310] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x00001318] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x00001320] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x00001328] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x00001330] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x00001338] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x00001340] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00001348] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00001350] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00001358] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00001360] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00001368] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00001370] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00001378] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001380] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00001388] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00001390] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00001398] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x000013a0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x000013a8] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x000013b0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x000013b8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x000013c0] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x000013c8] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x000013d0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000013d8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x000013e0] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x000013e8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x000013f0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000013f8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x00001400] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x00001408] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x00001410] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00001418] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00001420] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++-/* [0x00001428] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00001430] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x00001438] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x00001440] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00001448] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001450] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001458] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001460] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00001468] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00001470] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00001478] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001480] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00001488] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00001490] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000398] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003a0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000003a8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003b0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003b8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003c0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003c8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003d0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003d8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000003e0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000003e8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003f0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003f8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000400] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000408] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000410] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000418] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000420] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000428] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000430] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000438] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000440] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000448] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000450] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000458] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000460] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000468] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000470] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000478] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000480] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000488] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000490] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000498] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000004a0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000004a8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000004b0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000004b8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004c0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000004c8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000004d0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000004d8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x000004e0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x000004e8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x000004f0] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x000004f8] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000500] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000508] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000510] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000518] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000520] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000528] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000530] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000538] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000540] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000548] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000550] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000558] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000560] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000568] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000570] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000578] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000580] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000588] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000590] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000598] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x00001498] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000014a0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000014a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000014b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000014b8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000014c0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000014c8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000014d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000014d8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000014e0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000014e8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000014f0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000014f8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00001500] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001508] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00001510] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00001518] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00001520] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00001528] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00001530] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00001538] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00001540] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00001548] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00001550] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001558] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001560] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00001568] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 ++-/* [0x00001570] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00001578] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001580] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001588] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001590] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001598] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000015a0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015a8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015b0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015b8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000015c0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015c8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015d0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015d8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000015e0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015e8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015f0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000015f8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00001600] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00001608] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001610] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000005a0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000005a8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000005b0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000005b8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000005c0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000005c8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000005d0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000005d8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000005e0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000005e8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000005f0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000005f8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000600] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000608] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000610] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000618] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000620] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000628] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000630] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000638] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000640] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000648] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000650] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000658] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000660] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000668] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000670] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00000678] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000680] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000688] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000690] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000698] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000006a8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000006c8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000006e8] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f0] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f8] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000700] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000708] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000710] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000718] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00001618] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00001620] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00001628] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00001630] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00001638] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00001640] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00001648] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00001650] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00001658] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00001660] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00001668] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001670] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00001678] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-/* [0x00001680] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00001688] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00001690] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00001698] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000016a0] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000016a8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000016b0] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000016b8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000016c0] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000016c8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000016d0] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000016d8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000016e0] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000016e8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x000016f0] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 ++-/* [0x000016f8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00001700] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00001708] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001710] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001718] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001720] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001728] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001730] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00001738] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00001740] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00001748] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00001750] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00001758] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00001760] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00001768] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00001770] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00001778] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00001780] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00001788] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00001790] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00001798] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-/* [0x000017a0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000017a8] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x000017b0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000017b8] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x000017c0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000017c8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x000017d0] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x000017d8] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x000017e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000017e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000017f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000017f8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00001800] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001808] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001810] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00001818] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001820] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000720] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000728] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000730] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000738] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000740] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000748] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000750] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000758] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000760] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000768] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000770] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000778] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 +++/* [0x00000780] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 +++/* [0x00000788] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000790] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000798] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000007a0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000007a8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000007b0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000007b8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000007c0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000007c8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000007d0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000007d8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000007e0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000007e8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000007f0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x000007f8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x00000800] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000808] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000810] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000818] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000820] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000828] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000830] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000838] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000840] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000848] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 +++/* [0x00000850] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 +++/* [0x00000858] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 +++/* [0x00000860] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 +++/* [0x00000868] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 +++/* [0x00000870] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000878] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000880] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000888] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000890] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000898] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000008a0] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x000008a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000008b0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x000008b8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000008c0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x000008c8] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000008d0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000008d8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x000008e0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x000008e8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000008f0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000008f8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000900] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000908] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000910] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000918] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000920] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000928] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_exit +++/* [0x00000930] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000938] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000940] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000948] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000950] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000958] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000960] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000968] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000970] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_interrupt_exit8 +++/* [0x00000978] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000980] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000988] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000990] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000998] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000009a0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009d0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009d8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000009e0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000009e8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 3464cdb..9de4535 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -3,18 +3,11 @@ ++ ++ extern unsigned int rpi_shader[]; ++ ++-#define mc_setup (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 146) ++-#define mc_filter (rpi_shader + 364) ++-#define mc_filter_b (rpi_shader + 674) ++-#define mc_filter_honly (rpi_shader + 898) ++-#define mc_exit (rpi_shader + 1052) ++-#define mc_exit1 (rpi_shader + 1070) ++-#define mc_interrupt_exit (rpi_shader + 1086) ++-#define mc_interrupt_exit4 (rpi_shader + 1124) ++-#define mc_interrupt_exit8 (rpi_shader + 1146) ++-#define mc_setup_uv (rpi_shader + 1176) ++-#define mc_filter_uv_b (rpi_shader + 1318) ++-#define mc_end (rpi_shader + 1546) +++#define mc_setup_uv (rpi_shader + 0) +++#define mc_filter_uv (rpi_shader + 142) +++#define mc_filter_uv_b (rpi_shader + 360) +++#define mc_exit (rpi_shader + 588) +++#define mc_interrupt_exit8 (rpi_shader + 606) +++#define mc_end (rpi_shader + 636) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 4809e1d..cd7346d 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -71,8 +71,10 @@ ++ ++ .set rb_const_64, rb21 ++ ++-# mc_setup(next_kernel, x, y, ref_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1) ++-::mc_setup +++ +++################################################################################ +++# mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1, pad2) +++::mc_setup_uv ++ ++ # Read starting kernel ++ mov ra31, unif ++@@ -80,7 +82,9 @@ mov ra31, unif ++ # Load first request location ++ add ra_x_base, unif, elem_num # Store x ++ mov ra_y, unif # Store y ++-mov ra_x2_base, unif # Store frame base +++mov ra_x2_base, unif # Store frame u base +++nop +++sub ra_u2v_ref_offset, unif, ra_x2_base # Store offset to add to move from u to v in reference frame ++ ++ # Read image dimensions ++ sub rb25,unif,1 ++@@ -143,29 +147,24 @@ mov r1, vpm_setup(0, 4, h8p(0, 0)) ++ add rb28, r0, r1 ++ ++ # Compute base address for first and second access ++-#add r0, unif, elem_num # x ++ mov r0, ra_x_base # Load x ++-add r2, r0, 8 # x+8 ++ max r0, r0, 0; mov r1, ra_y # Load y ++ min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base # Load the frame base ++-shl ra_xshift_next, r0, 3 ++-max r2, r2, 0 +++shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++ add ra_y, r1, 1 ++-min r2, r2, rb_frame_width_minus_1 ++-shl ra_x2shift_next, r2, 3 ++-max r1, r1, 0 # y ++-min r1, r1, rb_frame_height_minus_1 ++-add r0, r0, r3; mul24 r1, r1, rb_pitch ++-add r2, r2, r3 +++add r0, r0, r3 ++ and r0, r0, ~3 ++-and r2, r2, ~3; mov ra_x_base, r0 +++max r1, r1, 0 ; mov ra_x_base, r0 # y +++min r1, r1, rb_frame_height_minus_1 ++ # submit texture requests for first line +++add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++ add t0s, r0, r1 ; mov ra_x2_base, r2 ++ add t0s, r2, r1 ++ ++ # Dump padding words ++ mov r0, unif ++ mov r0, unif +++mov r0, unif ++ ++ # submit texture requests for second line ++ max r1, ra_y, 0 ++@@ -176,6 +175,8 @@ nop ; mul24 r1, r1, rb_pitch ++ add t0s, r1, ra_x_base ++ add t0s, r1, ra_x2_base ++ +++ +++ ++ ################################################################################ ++ ++ # mc_filter_uv(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) ++@@ -341,453 +342,26 @@ add vw_setup, rb26, r0 # VDW setup 0 ++ mov vw_setup, rb29 # Stride ++ mov vw_addr, unif # start the VDW ++ ++-################################################################################ ++- ++- ++-# mc_filter(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) ++- ++-# At this point we have already issued two pairs of texture requests for the current block ++-# ra_x_base, ra_x16_base point to the current coordinates for this block ++-::mc_filter ++-mov ra31, unif ++- ++-# per-channel shifts were calculated on the *previous* invocation ++- ++-mov ra_xshift, ra_xshift_next ++-mov ra_x2shift, ra_x2shift_next ++- ++-# get base addresses and per-channel shifts for *next* invocation ++-add r0, unif, elem_num # x ++-add r2, r0, 8 # x+8 ++-max r0, r0, 0; mov r1, unif # y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base ++-shl ra_xshift_next, r0, 3 ++-max r2, r2, 0 ++-min r2, r2, rb_frame_width_minus_1 ++-shl ra_x2shift_next, r2, 3 ++-add r0, r0, r3 ++-add r2, r2, r3 ++-and rb_x_base_next, r0, ~3 ++-and ra_x2_base_next, r2, ~3 ++-mov ra_y_next, r1 ++- ++-# set up VPM write ++-mov vw_setup, rb28 ++- ++-# get width,height of block ++-mov r2, 16 ++-mov r0, unif ++-shr r1, r0, r2 # Extract width ++-sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++-and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 ++-shl r0, r0, 7 ++-add r0, r0, r1 # Combine width and height of destination area ++-shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++-add rb26, r0, rb27 ++- ++-sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++- ++-# get filter coefficients ++- ++-mov r0, unif ++-asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif ++-asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif ++-asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-brr.anynn -, r:fast_path ++-asr rb12, r0, rb23 # delay slot 1 ++- ++-# r2 is elem_num ++-# r3 is loop counter ++- ++-mov r5rep, -8 # delay slot 2 ++- ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] # delay slot 3 ++- ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-## nop ; ldtmu0 # loop counter increment ++-## shr r0, r4, ra17 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ; mul24 r3, r0, ra0 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-## sub r2, r2, r3 ; ldtmu0 ++-## ++-## mov r0, ra22 ++-## shr r0, r4, ra17 ; mul24 r2, r2, r0 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # apply horizontal filter ++-## ++-## asr r2, r2, 15 ; mul24 r3, r0, ra0 ++-## min r2, r2, rb22 ++-## max ra13, r2, 0 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-## sub r0, r2, r3 ++-## ++-## # apply horizontal filter ++-## ++-## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero ++-## asr r0, r0, 15 ++-## min r0, r0, rb22 ++-## max ra14, r0, 0 ++-## ++-## ++-## ++-## ++-## nop ; ldtmu0 # loop counter increment ++-## shr r0, r4, ra17 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ; mul24 r3, r0, ra0 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-## sub r0, r2, r3 ++-## ++-## # apply horizontal filter ++-## ++-## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero ++-## asr r0, r0, 15 ++-## min r0, r0, rb22 ++-## max ra15, r0, 0 ++- ++- ++- ++- ++-mov r3, 0 ++- ++-:loop ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++- ++-max r2, ra_y, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 ++- ++-# generate seven shifted versions ++-# interleave with scroll of vertical context ++- ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++- ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-sub r0, r2, r3 ++- ++-mov r3, rb31 ++- ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 8 ; mov r1, ra22 ++- ++-# apply horizontal filter ++-brr.anyn -, r:loop ++-max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 15 ; mov r1, ra21 ++-min.setf ra15, r0, rb22 ++- ++-# apply vertical filter and write to VPM ++- ++-nop ; mul24 r0, ra14, rb14 ++-sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-brr.anyn -, r:loop ++-asr r1, r1, 15 ++-min r1, r1, rb22 ++-max vpm, r1, 0 ++- ++-# DMA out ++- ++-bra -, ra31 ++-mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long ++-mov vw_setup, rb29 ++-mov vw_addr, unif # start the VDW ++- ++-#################################################### ++- ++-:fast_path ++-## nop ; ldtmu0 # loop counter increment ++-## shr r0, r4, ra17 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ; mul24 r3, r0, ra0 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## sub r2, r2, r3 ; ldtmu0 ++-## ++-## mov r0, ra22 ++-## shr r0, r4, ra17 ; mul24 r2, r2, r0 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # apply horizontal filter ++-## ++-## asr r2, r2, 15 ; mul24 r3, r0, ra0 ++-## min r2, r2, rb22 ++-## max ra13, r2, 0 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## sub r0, r2, r3 ++-## ++-## # apply horizontal filter ++-## ++-## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero ++-## asr r0, r0, 15 ++-## min r0, r0, rb22 ++-## max ra14, r0, 0 ++-## ++-## ++-## ++-## ++-## nop ; ldtmu0 # loop counter increment ++-## shr r0, r4, ra17 ; ldtmu0 ++-## shr r1, r4, ra17 ; v8subs r0, r0, rb20 ++-## add t0s, ra16, r5 ; v8subs r1, r1, rb20 ++-## add ra16, ra16, rb16 ; mov t0s, ra16 ++-## ++-## # generate seven shifted versions ++-## # interleave with scroll of vertical context ++-## ++-## mov r2, rb21 ; mul24 r3, r0, ra0 ++-## sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-## sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-## sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-## sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-## sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-## sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-## sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-## sub r0, r2, r3 ++-## ++-## # apply horizontal filter ++-## ++-## nop ; mul24 r0, r0, ra22 # last bit of context scroll, including clamp to zero ++-## asr r0, r0, 15 ++-## min r0, r0, rb22 ++-## max ra15, r0, 0 ++- ++- ++-mov r3, 0 # This signifies the amount of unrolling ++- ++-:fast_loop ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-# Due to pipelining we can only skip second pipeline instructions related to the fetched pixels ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_y, ra_y_next ; mov rb31, r3 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov r3, rb_pitch ++- ++-max r2, ra_y, 0 ++-min r2, r2, rb_frame_height_minus_1 ; mov r1, r4 # discard texture read ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r0, r0, rb20 ++-add t0s, ra_x2_base, r2 ++- ++-# generate seven shifted versions ++-# interleave with scroll of vertical context ++- ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-sub r0, r2, r3 ; mov r3, rb31 ++- ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 8 ; mov r1, ra22 ++- ++-# apply horizontal filter ++- ++-brr.anyn -, r:fast_loop ++-max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 15 ; mov r1, ra21 ++-min.setf ra15, r0, rb22 ++- ++-# apply vertical filter and write to VPM ++- ++-nop ; mul24 r0, ra14, rb14 ++-sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-brr.anyn -, r:fast_loop ++-asr r1, r1, 15 ++-min r1, r1, rb22 ++-max vpm, r1, 0 ++- ++-# DMA out ++- ++-bra -, ra31 ++-mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long ++-mov vw_setup, rb29 ++-mov vw_addr, unif # start the VDW ++ ++ ################################################################################ ++ ++-# mc_filter_b(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) ++- ++-# At this point we have already issued two pairs of texture requests for the current block ++-# ra_x_base, ra_x16_base point to the current coordinates for this block ++-::mc_filter_b +++::mc_filter_uv_b ++ mov ra31, unif ++ ++ # per-channel shifts were calculated on the *previous* invocation ++ ++ mov ra_xshift, ra_xshift_next ++-mov ra_x2shift, ra_x2shift_next ++ ++ # get base addresses and per-channel shifts for *next* invocation ++ add r0, unif, elem_num # x ++-add r2, r0, 8 # x+8 ++ max r0, r0, 0; mov r1, unif # y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base +++min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base ++ shl ra_xshift_next, r0, 3 ++-max r2, r2, 0 ++-min r2, r2, rb_frame_width_minus_1 ++-shl ra_x2shift_next, r2, 3 +++sub r2, unif, r3 # compute offset from frame base u to frame base v ++ add r0, r0, r3 ++-add r2, r2, r3 ++ and rb_x_base_next, r0, ~3 ++-and ra_x2_base_next, r2, ~3 ++ mov ra_y_next, r1 +++add ra_x2_base_next, rb_x_base_next, r2 ++ ++ # set up VPM write ++ mov vw_setup, rb28 ++@@ -801,17 +375,22 @@ and r0, r0, rb22 # Extract height ++ add rb17, r0, 5 ++ add rb18, r0, 7 ++ shl r0, r0, 7 +++ ++ # r0 is currently height<<7 ++ # For vr_setup we want height<<20 (so 20-7=13 additional bits) ++ shl r3, r0, 13 ++ shl r3, r3, 8 # Mask off top 8 bits ++ shr r3, r3, 8 +++ ++ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++ add rb26, r0, rb27 +++ ++ # In a B frame, so also set up VPM read ++ add vr_setup, r3, rb28 ++ +++sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code +++ ++ # get filter coefficients ++ ++ mov r0, unif ++@@ -837,9 +416,13 @@ asr rb12, r0, rb23 ++ ++ mov r5rep, -8 ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ ++ mov r3, 0 ++ ++-:bloop +++:uvloop_b ++ # retrieve texture results and pick out bytes ++ # then submit two more texture requests ++ ++@@ -847,7 +430,7 @@ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++ shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++ mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++@@ -861,6 +444,7 @@ add t0s, ra_x2_base, r2 ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++ mov r2, rb21 ; mul24 r3, r0, ra0 +++nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++ sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++ sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++@@ -889,7 +473,7 @@ mov ra13, ra14 ++ sub.setf -, r3, 8 ; mov r1, ra22 ++ ++ # apply horizontal filter ++-brr.anyn -, r:bloop +++brr.anyn -, r:uvloop_b ++ max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++ asr r0, r0, 15 ; mov r1, ra21 ++ min.setf ra15, r0, rb22 ++@@ -906,213 +490,50 @@ sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++ sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++ sub.ifnn r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 15 ; mov -, vr_wait +++asr r1, r1, 15 ++ min r1, r1, rb22 ++ add r0, vpm, 1 # Blend in previous VPM contents at this location ++-brr.anyn -, r:bloop +++brr.anyn -, r:uvloop_b ++ max r1, r1, 0 ++ add r1, r1, r0 ++ shr vpm, r1, 1 ++ ++-# DMA out +++ +++# DMA out for U +++ +++mov vw_setup, rb26 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++# DMA out for V +++# We need to wait for the U to complete first, but have nothing useful to compute while we wait. +++# Could potentially push this write into the start of the next pipeline stage. +++mov r0, 16 +++mov -, vw_wait ++ ++ bra -, ra31 ++-mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long ++-mov vw_setup, rb29 +++add vw_setup, rb26, r0 # VDW setup 0 +++mov vw_setup, rb29 # Stride ++ mov vw_addr, unif # start the VDW ++ ++ ################################################################################ ++ ++-# mc_filter_honly(next_kernel, x, y, frame_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_dst) ++-# This filter only does horizontal filtering. ++-# It is assumed that the region to fetch does not include extra rows above. +++# mc_exit() ++ ++-# At this point we have already issued two pairs of texture requests for the current block ++-# ra_x_base, ra_x16_base point to the current coordinates for this block ++-::mc_filter_honly ++-mov ra31, unif +++::mc_exit +++mov -, vw_wait # wait on the VDW ++ ++-# per-channel shifts were calculated on the *previous* invocation +++mov -,srel(0) ++ ++-mov ra_xshift, ra_xshift_next ++-mov ra_x2shift, ra_x2shift_next ++- ++-# get base addresses and per-channel shifts for *next* invocation ++-add r0, unif, elem_num # x ++-add r2, r0, 8 # x+8 ++-max r0, r0, 0; mov r1, unif # y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3,unif # frame_base ++-shl ra_xshift_next, r0, 3 ++-max r2, r2, 0 ++-min r2, r2, rb_frame_width_minus_1 ++-shl ra_x2shift_next, r2, 3 ++-add r0, r0, r3 ++-add r2, r2, r3 ++-and rb_x_base_next, r0, ~3 ++-and ra_x2_base_next, r2, ~3 ++-mov ra_y_next, r1 ++- ++-# set up VPM write ++-mov vw_setup, rb28 ++- ++-# get width,height of block ++-mov r2, 16 ++-mov r0, unif ++-shr r1, r0, r2 # Extract width ++-sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++-and r0, r0, rb22 # Extract height ++-add rb17, r0, -2 # Pipelining means we move data across 2 iterations early ++-shl r0, r0, 7 ; mov rb18,r0 ++-add r0, r0, r1 # Combine width and height of destination area ++-shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++-add rb26, r0, rb27 ++- ++-# get filter coefficients ++- ++-mov r0, unif ++-asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif ++-mov r0, unif ++- ++-# r2 is elem_num ++-# r3 is loop counter ++-mov r5rep, -8 ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] # delay slot 3 ++-mov r3, 0 ++- ++-:loop_honly ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, ra_x2shift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++- ++-max r2, ra_y, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 ++- ++-# generate seven shifted versions ++-# interleave with scroll of vertical context ++- ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++- ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-sub r0, r2, r3 ; mov r3, rb31 ++- ++-sub.setf -, r3, rb18 ; mov r1, ra22 ++- ++-mov -, vw_wait ; mul24 r0, r0, r1 ++-brr.anyn -, r:loop_honly ++-asr r0, r0, 15 # delay 1 ++-min r0, r0, rb22 # delay 2 ++-max vpm, r0, 0 # delay 3 ++- ++-# DMA out ++-bra -, ra31 ++-mov vw_setup, rb26 # VDW: height rows, 16 8-bit units long ++-mov vw_setup, rb29 ++-mov vw_addr, unif # start the VDW ++- ++- ++-################################################################################ ++- ++-# mc_exit() ++- ++-::mc_exit ++-mov -, vw_wait # wait on the VDW ++- ++-mov -,srel(0) ++- ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 ++ ++ nop ; nop ; thrend ++ nop ; nop # delay slot 1 ++ nop ; nop # delay slot 2 ++ ++-::mc_exit1 ++-mov -, vw_wait # wait on the VDW ++- ++-#mov -,srel(1) ++- ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++- ++-nop ; nop ; thrend ++-mov interrupt, 1; nop # delay slot 1 ++-nop ; nop # delay slot 2 ++- ++-# mc_interrupt_exit() ++-::mc_interrupt_exit ++-mov -, vw_wait # wait on the VDW ++- ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++- ++-mov -,sacq(0) # 1 ++-mov -,sacq(0) # 2 ++-mov -,sacq(0) # 3 ++-mov -,sacq(0) # 4 ++-mov -,sacq(0) # 5 ++-mov -,sacq(0) # 6 ++-mov -,sacq(0) # 7 ++-mov -,sacq(0) # 8 ++-mov -,sacq(0) # 9 ++-mov -,sacq(0) # 10 ++-mov -,sacq(0) # 11 ++- ++-nop ; nop ; thrend ++-mov interrupt, 1; nop # delay slot 1 ++-nop ; nop # delay slot 2 ++- ++-# mc_interrupt_exit4() ++-::mc_interrupt_exit4 ++-mov -, vw_wait # wait on the VDW ++- ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++- ++-mov -,sacq(0) # 1 ++-mov -,sacq(0) # 2 ++-mov -,sacq(0) # 3 ++- ++-nop ; nop ; thrend ++-mov interrupt, 1; nop # delay slot 1 ++-nop ; nop # delay slot 2 ++- ++ # mc_interrupt_exit8() ++ ::mc_interrupt_exit8 ++ mov -, vw_wait # wait on the VDW ++@@ -1134,282 +555,5 @@ nop ; nop ; thrend ++ mov interrupt, 1; nop # delay slot 1 ++ nop ; nop # delay slot 2 ++ ++-################################################################################ ++-# mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1, pad2) ++-::mc_setup_uv ++- ++-# Read starting kernel ++-mov ra31, unif ++- ++-# Load first request location ++-add ra_x_base, unif, elem_num # Store x ++-mov ra_y, unif # Store y ++-mov ra_x2_base, unif # Store frame u base ++-nop ++-sub ra_u2v_ref_offset, unif, ra_x2_base # Store offset to add to move from u to v in reference frame ++- ++-# Read image dimensions ++-sub rb25,unif,1 ++-sub rb30,unif,1 ++- ++-# get source pitch ++-mov rb16, unif ++- ++-# get destination pitch ++-mov r0, unif ++-mov r1, vdw_setup_1(0) ++-add rb24, r1, r0 ++- ++-# load constants ++- ++-mov ra20, 1 ++-mov ra21, 32 ++-mov ra22, 256 ++-mov ra23, 8 ++- ++-mov rb20, 0xffffff00 ++-mov rb21, 64 ++-mov rb22, 255 ++-mov rb23, 24 ++- ++-# touch vertical context to keep simulator happy ++- ++-mov ra8, 0 ++-mov ra9, 0 ++-mov ra10, 0 ++-mov ra11, 0 ++-mov ra12, 0 ++-mov ra13, 0 ++-mov ra14, 0 ++-mov ra15, 0 ++- ++-# Compute part of VPM to use for DMA output ++-mov r2, qpu_num ++-and r2, r2, 15 ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later ++-shl r0, r0, 5 ++-add rb27, r0, r1 ++- ++-# Compute part of VPM to save data into ++-mov r2, qpu_num ++-and r2, r2, 15 ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-add rb28, r0, r1 ++- ++-# Compute base address for first and second access ++-mov r0, ra_x_base # Load x ++-max r0, r0, 0; mov r1, ra_y # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base # Load the frame base ++-shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-add ra_y, r1, 1 ++-add r0, r0, r3 ++-and r0, r0, ~3 ++-max r1, r1, 0 ; mov ra_x_base, r0 # y ++-min r1, r1, rb_frame_height_minus_1 ++-# submit texture requests for first line ++-add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-add t0s, r0, r1 ; mov ra_x2_base, r2 ++-add t0s, r2, r1 ++- ++-# Dump padding words ++-mov r0, unif ++-mov r0, unif ++-mov r0, unif ++- ++-# submit texture requests for second line ++-max r1, ra_y, 0 ++-min r1, r1, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ++-bra -, ra31 ++-nop ; mul24 r1, r1, rb_pitch ++-add t0s, r1, ra_x_base ++-add t0s, r1, ra_x2_base ++- ++- ++- ++-################################################################################ ++- ++-::mc_filter_uv_b ++-mov ra31, unif ++- ++-# per-channel shifts were calculated on the *previous* invocation ++- ++-mov ra_xshift, ra_xshift_next ++- ++-# get base addresses and per-channel shifts for *next* invocation ++-add r0, unif, elem_num # x ++-max r0, r0, 0; mov r1, unif # y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base ++-shl ra_xshift_next, r0, 3 ++-sub r2, unif, r3 # compute offset from frame base u to frame base v ++-add r0, r0, r3 ++-and rb_x_base_next, r0, ~3 ++-mov ra_y_next, r1 ++-add ra_x2_base_next, rb_x_base_next, r2 ++- ++-# set up VPM write ++-mov vw_setup, rb28 ++- ++-# get width,height of block ++-mov r2, 16 ++-mov r0, unif ++-shr r1, r0, r2 # Extract width ++-sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++-and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 ++-shl r0, r0, 7 ++- ++-# r0 is currently height<<7 ++-# For vr_setup we want height<<20 (so 20-7=13 additional bits) ++-shl r3, r0, 13 ++-shl r3, r3, 8 # Mask off top 8 bits ++-shr r3, r3, 8 ++- ++-add r0, r0, r1 # Combine width and height of destination area ++-shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++-add rb26, r0, rb27 ++- ++-# In a B frame, so also set up VPM read ++-add vr_setup, r3, rb28 ++- ++-sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++- ++-# get filter coefficients ++- ++-mov r0, unif ++-asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif ++-asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif ++-asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-asr rb12, r0, rb23 ++- ++-# r2 is elem_num ++-# r3 is loop counter ++- ++-mov r5rep, -8 ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++- ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-mov r3, 0 ++- ++-:uvloop_b ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++- ++-max r2, ra_y, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 ++- ++-# generate seven shifted versions ++-# interleave with scroll of vertical context ++- ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++- ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 ++-nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-sub r0, r2, r3 ++- ++-mov r3, rb31 ++- ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 8 ; mov r1, ra22 ++- ++-# apply horizontal filter ++-brr.anyn -, r:uvloop_b ++-max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 15 ; mov r1, ra21 ++-min.setf ra15, r0, rb22 ++- ++-# apply vertical filter and write to VPM ++- ++-nop ; mul24 r0, ra14, rb14 ++-sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-sub.ifnn r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 15 ++-min r1, r1, rb22 ++-add r0, vpm, 1 # Blend in previous VPM contents at this location ++-brr.anyn -, r:uvloop_b ++-max r1, r1, 0 ++-add r1, r1, r0 ++-shr vpm, r1, 1 ++- ++- ++-# DMA out for U ++- ++-mov vw_setup, rb26 # VDW setup 0 ++-mov vw_setup, rb29 # Stride ++-mov vw_addr, unif # start the VDW ++- ++-# DMA out for V ++-# We need to wait for the U to complete first, but have nothing useful to compute while we wait. ++-# Could potentially push this write into the start of the next pipeline stage. ++-mov r0, 16 ++-mov -, vw_wait ++- ++-bra -, ra31 ++-add vw_setup, rb26, r0 # VDW setup 0 ++-mov vw_setup, rb29 # Stride ++-mov vw_addr, unif # start the VDW ++- ++ ::mc_end +++# Do not add code here because mc_end must appear after all other code. ++-- ++2.5.0 ++ ++ ++From b0d344c931394c7f734b12ab63b7067857f1a2b3 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 13 May 2015 14:54:25 +0100 ++Subject: [PATCH 20/68] Moved chroma P1 to QPUs ++ ++--- ++ libavcodec/hevc.c | 38 ++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 38 insertions(+) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index b4a3707..4e9ac54 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2059,6 +2059,44 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ s->sh.luma_offset_l1[current_mv.ref_idx[1]]); ++ ++ if (s->ps.sps->chroma_format_idc) { +++#ifdef RPI_INTER_QPU +++ if (s->enable_rpi) { +++ int reflist = 1; +++ int hshift = s->ps.sps->hshift[1]; +++ int vshift = s->ps.sps->vshift[1]; +++ const Mv *mv = ¤t_mv.mv[reflist]; +++ intptr_t mx = av_mod_uintp2(mv->x, 2 + hshift); +++ intptr_t my = av_mod_uintp2(mv->y, 2 + vshift); +++ intptr_t _mx = mx << (1 - hshift); +++ intptr_t _my = my << (1 - vshift); // Fractional part of motion vector +++ +++ int x1_c = x0_c + (mv->x >> (2 + hshift)); +++ int y1_c = y0_c + (mv->y >> (2 + hshift)); +++ //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width +++ int chan = x0>>8; +++ +++ uint32_t *u = s->u_mvs[chan & 7]; +++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { +++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); +++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] +++ *u++ = rpi_filter_coefs[_mx][0]; +++ *u++ = rpi_filter_coefs[_mx][1]; +++ *u++ = rpi_filter_coefs[_my][0]; +++ *u++ = rpi_filter_coefs[_my][1]; +++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ } +++ } +++ s->u_mvs[chan & 7] = u; +++ return; +++ } +++#endif ++ RPI_REDIRECT(chroma_mc_uni)(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1], ++ 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]); ++-- ++2.5.0 ++ ++ ++From 9e0a56b87c843033556835e00b562a76fa806f6e Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 13 May 2015 15:13:47 +0100 ++Subject: [PATCH 21/68] Added B prediction - not quite right ++ ++--- ++ libavcodec/hevc.c | 58 ++++++++++++++++++++++++ ++ libavcodec/rpi_shader.c | 108 +++++++++++++++++++++++---------------------- ++ libavcodec/rpi_shader.h | 6 +-- ++ libavcodec/rpi_shader.qasm | 48 ++++++++++---------- ++ 4 files changed, 141 insertions(+), 79 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 4e9ac54..9a13fd4 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2116,6 +2116,64 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ ref1->frame, ¤t_mv.mv[1], ¤t_mv); ++ ++ if (s->ps.sps->chroma_format_idc) { +++#ifdef RPI_INTER_QPU +++ if (s->enable_rpi) { +++ int hshift = s->ps.sps->hshift[1]; +++ int vshift = s->ps.sps->vshift[1]; +++ const Mv *mv = ¤t_mv.mv[0]; +++ intptr_t mx = av_mod_uintp2(mv->x, 2 + hshift); +++ intptr_t my = av_mod_uintp2(mv->y, 2 + vshift); +++ intptr_t _mx = mx << (1 - hshift); +++ intptr_t _my = my << (1 - vshift); // Fractional part of motion vector +++ int x1_c = x0_c + (mv->x >> (2 + hshift)); +++ int y1_c = y0_c + (mv->y >> (2 + hshift)); +++ +++ const Mv *mv2 = ¤t_mv.mv[1]; +++ intptr_t mx2 = av_mod_uintp2(mv2->x, 2 + hshift); +++ intptr_t my2 = av_mod_uintp2(mv2->y, 2 + vshift); +++ intptr_t _mx2 = mx2 << (1 - hshift); +++ intptr_t _my2 = my2 << (1 - vshift); // Fractional part of motion vector +++ +++ int x2_c = x0_c + (mv2->x >> (2 + hshift)); +++ int y2_c = y0_c + (mv2->y >> (2 + hshift)); +++ +++ int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width +++ +++ uint32_t *u = s->u_mvs[chan & 7]; +++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { +++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); +++ *u++ = ( (nPbW_cframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); // TODO this will become unused once we have a dedicated pass0 filter +++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ +++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x2_c - 3 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y2_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); +++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] +++ *u++ = rpi_filter_coefs[_mx2][0]; +++ *u++ = rpi_filter_coefs[_mx2][1]; +++ *u++ = rpi_filter_coefs[_my2][0]; +++ *u++ = rpi_filter_coefs[_my2][1]; +++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ } +++ } +++ s->u_mvs[chan & 7] = u; +++ return; +++ } +++#endif ++ RPI_REDIRECT(chroma_mc_bi)(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame, ++ x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 0); ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 170e8ac..5d00cb2 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -265,23 +265,23 @@ unsigned int rpi_shader[] = { ++ /* [0x00000760] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++ /* [0x00000768] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++ /* [0x00000770] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000778] */ 0x55015fc6, 0x100248a3, // mov r2, rb21 ; mul24 r3, r0, ra0 ++-/* [0x00000780] */ 0x40038031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-/* [0x00000788] */ 0x4d07f4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000778] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000780] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000788] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++ /* [0x00000790] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000798] */ 0x4d0be4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000798] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ /* [0x000007a0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000007a8] */ 0x4d0fd4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000007a8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ /* [0x000007b0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000007b8] */ 0x4d13c4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000007b8] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++ /* [0x000007c0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000007c8] */ 0x4d17b4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000007c8] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++ /* [0x000007d0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000007d8] */ 0x4d1ba4f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000007d8] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++ /* [0x000007e0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000007e8] */ 0x4d1f94f0, 0xd00248a3, // sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000007e8] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++ /* [0x000007f0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x000007f8] */ 0x0d9e74c0, 0x10020827, // sub r0, r2, r3 +++/* [0x000007f8] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++ /* [0x00000800] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++ /* [0x00000808] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++ /* [0x00000810] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++@@ -291,61 +291,63 @@ unsigned int rpi_shader[] = { ++ /* [0x00000830] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++ /* [0x00000838] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++ /* [0x00000840] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000848] */ 0x533c0dc1, 0xd00243a0, // max ra14, ra15, 0 ; mul24 r0, r0, r1 ++-/* [0x00000850] */ 0x8f54f1f6, 0xd0024821, // asr r0, r0, 15 ; mov r1, ra21 ++-/* [0x00000858] */ 0x129d61c0, 0x100223e7, // min.setf ra15, r0, rb22 ++-/* [0x00000860] */ 0x4038e037, 0x100049e0, // nop ; mul24 r0, ra14, rb14 ++-/* [0x00000868] */ 0x4d34d237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-/* [0x00000870] */ 0x4d30c237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000878] */ 0x4d2cb237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000880] */ 0x4d28a237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000888] */ 0x4d249237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000890] */ 0x4d208237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000898] */ 0x4d3cf237, 0x10024860, // sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000008a0] */ 0x8d9f223f, 0x100a0867, // sub.ifnn r1, r1, r0 ; mov -, vw_wait +++/* [0x00000848] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000850] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000858] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000860] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000868] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000870] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000878] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000880] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000888] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000890] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000898] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000008a0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++ /* [0x000008a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000008b0] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 ++-/* [0x000008b8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000008c0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x000008c8] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000008d0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x000008d8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x000008e0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x000008e8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000008f0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000008f8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000900] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000908] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000910] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000918] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000920] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000928] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008b0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000008b8] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x000008c0] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x000008c8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000008d0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x000008d8] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000008e0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x000008e8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x000008f0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x000008f8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000900] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000908] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000910] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000918] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000920] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000928] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000930] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000938] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000930] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000938] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000940] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000948] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000940] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000948] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++ /* [0x00000950] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000958] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000960] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000968] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000970] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000960] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000968] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000970] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000978] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000980] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000978] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000980] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000988] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000988] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x00000990] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000998] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009a0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009a0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000009a8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x000009b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000009b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000009c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000009c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000009d0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009d8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000009e0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000009e8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000009d8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009e0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000009e8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000009f0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000009f8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 9de4535..e36c4ae 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -6,8 +6,8 @@ extern unsigned int rpi_shader[]; ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 142) ++ #define mc_filter_uv_b (rpi_shader + 360) ++-#define mc_exit (rpi_shader + 588) ++-#define mc_interrupt_exit8 (rpi_shader + 606) ++-#define mc_end (rpi_shader + 636) +++#define mc_exit (rpi_shader + 592) +++#define mc_interrupt_exit8 (rpi_shader + 610) +++#define mc_end (rpi_shader + 640) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index cd7346d..870437d2 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -443,23 +443,23 @@ add t0s, ra_x2_base, r2 ++ ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++-mov r2, rb21 ; mul24 r3, r0, ra0 ++-nop ; mul24.ifnz r3, ra0 << 8, r1 << 8 ++-sub r2, r2, r3 ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24 r2, r0, ra0 +++nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++nop ; mul24 r3, ra1 << 1, r0 << 1 ++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-sub r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-sub r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-sub r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++ nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-sub r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++ nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-sub r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++ nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-sub r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++ nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-sub r0, r2, r3 +++add r0, r2, r3 ++ ++ mov r3, rb31 ++ ++@@ -474,23 +474,25 @@ sub.setf -, r3, 8 ; mov r1, ra22 ++ ++ # apply horizontal filter ++ brr.anyn -, r:uvloop_b ++-max ra14, ra15, 0 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr r0, r0, 15 ; mov r1, ra21 ++-min.setf ra15, r0, rb22 +++mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero +++asr ra15, r0, 8 ; nop +++nop ; nop ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r0, ra14, rb14 ++-sub r1, r1, r0 ; mul24 r0, ra13, rb13 ++-sub r1, r1, r0 ; mul24 r0, ra12, rb12 ++-sub r1, r1, r0 ; mul24 r0, ra11, rb11 ++-sub r1, r1, r0 ; mul24 r0, ra10, rb10 ++-sub r1, r1, r0 ; mul24 r0, ra9, rb9 ++-sub r1, r1, r0 ; mul24 r0, ra8, rb8 ++-sub r1, r1, r0 ; mul24 r0, ra15, rb15 ++-sub.ifnn r1, r1, r0 ; mov -, vw_wait +++nop ; mul24 r1, ra14, rb14 +++nop ; mul24 r0, ra13, rb13 +++add r1, r1, r0 ; mul24 r0, ra12, rb12 +++add r1, r1, r0 ; mul24 r0, ra11, rb11 +++add r1, r1, r0 ; mul24 r0, ra10, rb10 +++add r1, r1, r0 ; mul24 r0, ra9, rb9 +++add r1, r1, r0 ; mul24 r0, ra8, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb15 +++add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 15 +++asr r1, r1, 14 +++add r1, r1, ra21 +++asr r1, r1, 6 ++ min r1, r1, rb22 ++ add r0, vpm, 1 # Blend in previous VPM contents at this location ++ brr.anyn -, r:uvloop_b ++-- ++2.5.0 ++ ++ ++From 9bd4040dfa0e8146dd0a9d7ca191f98078e0d400 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 08:15:55 +0100 ++Subject: [PATCH 22/68] Added flush for SAO ++ ++--- ++ libavcodec/hevc.c | 2 +- ++ libavcodec/hevc_filter.c | 39 ++++++++++++++++++++++++++------------- ++ 2 files changed, 27 insertions(+), 14 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 9a13fd4..96b3568 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2892,7 +2892,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ rpi_execute_inter_qpu(s); ++ #endif ++ // Transform all blocks ++- //printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); +++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++ rpi_execute_transform(s); ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 9b6e26d..92a8271 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -871,6 +871,21 @@ static void flush_buffer(AVBufferRef *bref) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++ gpu_cache_flush(p); ++ } +++ +++static void ff_hevc_flush_chroma(HEVCContext *s) +++{ +++ if (s->enable_rpi && !( s->nal_unit_type == NAL_TRAIL_N || +++ s->nal_unit_type == NAL_TSA_N || +++ s->nal_unit_type == NAL_STSA_N || +++ s->nal_unit_type == NAL_RADL_N || +++ s->nal_unit_type == NAL_RASL_N )) { +++ flush_buffer(s->frame->buf[1]); +++ flush_buffer(s->frame->buf[2]); +++ //memcpy(s->dummy.arm,s->frame->data[0],2048*64); +++ //memcpy(s->dummy.arm,s->frame->data[1],1024*32); +++ //memcpy(s->dummy.arm,s->frame->data[2],1024*32); +++ } +++} ++ #endif ++ ++ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++@@ -886,31 +901,29 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ sao_filter_CTB(s, x - ctb_size, y); ++ if (y && x_end) { ++ sao_filter_CTB(s, x, y - ctb_size); ++- if (s->threads_type & FF_THREAD_FRAME ) +++ if (s->threads_type & FF_THREAD_FRAME ) { +++#ifdef RPI_INTER_QPU +++ ff_hevc_flush_chroma(s); +++#endif ++ ff_thread_report_progress(&s->ref->tf, y, 0); +++ } ++ } ++ if (x_end && y_end) { ++ sao_filter_CTB(s, x , y); ++- if (s->threads_type & FF_THREAD_FRAME ) +++ if (s->threads_type & FF_THREAD_FRAME ) { +++#ifdef RPI_INTER_QPU +++ ff_hevc_flush_chroma(s); +++#endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0); +++ } ++ } ++ } else if (s->threads_type & FF_THREAD_FRAME && x_end) { ++ //int newh = y + ctb_size - 4; ++ //int currh = s->ref->tf.progress->data[0]; ++ //if (((y + ctb_size)&63)==0) ++- if (!( s->nal_unit_type == NAL_TRAIL_N || ++- s->nal_unit_type == NAL_TSA_N || ++- s->nal_unit_type == NAL_STSA_N || ++- s->nal_unit_type == NAL_RADL_N || ++- s->nal_unit_type == NAL_RASL_N )) { ++ #ifdef RPI_INTER_QPU ++- flush_buffer(s->frame->buf[1]); ++- flush_buffer(s->frame->buf[2]); +++ ff_hevc_flush_chroma(s); ++ #endif ++- //memcpy(s->dummy.arm,s->frame->data[0],2048*64); ++- //memcpy(s->dummy.arm,s->frame->data[1],1024*32); ++- //memcpy(s->dummy.arm,s->frame->data[2],1024*32); ++- } ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++ } ++-- ++2.5.0 ++ ++ ++From d9e8153a94d637578cd0cdb6a0b737957abb8b8f Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 09:17:28 +0100 ++Subject: [PATCH 23/68] Stopped using acceleration in unsupported cases ++ ++--- ++ libavcodec/hevc.c | 14 +++++++------- ++ libavcodec/hevc_cabac.c | 4 ++-- ++ 2 files changed, 9 insertions(+), 9 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 96b3568..b9ae06a 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -1141,15 +1141,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++- printf("Cross component not supported\n"); // TODO ++- exit(-1); ++ s->hevcdsp.transform_add[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++ ++ if (lc->tu.cross_pf) { ++- printf("Cross component not supported\n"); // TODO ++- exit(-1); ++ hls_cross_component_pred(s, 1); ++ } ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++@@ -1178,8 +1174,6 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++- printf("Cross component not supported\n"); // TODO ++- exit(-1); ++ s->hevcdsp.transform_add[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++@@ -2846,7 +2840,13 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ ++ #ifdef RPI ++- s->enable_rpi = 1; // TODO this should depend on cross component and frame width etc. +++ s->enable_rpi = s->ps.sps->bit_depth == 8 +++ && s->ps.sps->width <= RPI_MAX_WIDTH +++ && !s->ps.pps->cross_component_prediction_enabled_flag +++ && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1 +++ && !(s->ps.pps->weighted_pred_flag && s->sh.slice_type == P_SLICE) +++ && !(s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE); +++ ++ #endif ++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index f28759b..ca76cb0 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1513,9 +1513,9 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ #ifdef RPI ++ if (!use_vpu) { ++ int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y); ++- if (max_xy == 0) +++ if (max_xy == 0) { ++ s->hevcdsp.idct_dc[log2_trafo_size-2](coeffs); ++- else { +++ } else { ++ int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4; ++ if (max_xy < 4) ++ col_limit = FFMIN(4, col_limit); ++-- ++2.5.0 ++ ++ ++From 0e326aaea2fd684025bfbd676bb7fa6f08acca22 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 09:42:16 +0100 ++Subject: [PATCH 24/68] Split B prediction into two passes ++ ++--- ++ libavcodec/hevc.c | 1 + ++ libavcodec/hevc.h | 1 + ++ libavcodec/rpi_qpu.c | 3 + ++ libavcodec/rpi_qpu.h | 1 + ++ libavcodec/rpi_shader.c | 559 +++++++++++++++++++++++++++------------------ ++ libavcodec/rpi_shader.h | 11 +- ++ libavcodec/rpi_shader.qasm | 196 ++++++++++++++-- ++ 7 files changed, 531 insertions(+), 241 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index b9ae06a..3994f2e 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3795,6 +3795,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ p += uv_commands_per_qpu; ++ } ++ s->mc_filter_uv = qpu_get_fn(QPU_MC_FILTER_UV); +++ s->mc_filter_uv_b0 = qpu_get_fn(QPU_MC_FILTER_UV_B0); ++ s->mc_filter_uv_b = qpu_get_fn(QPU_MC_FILTER_UV_B); ++ ++ } ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 442516d..d33ab74 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -943,6 +943,7 @@ typedef struct HEVCContext { ++ uint32_t *u_mvs[8]; ++ // Function pointers ++ uint32_t mc_filter_uv; +++ uint32_t mc_filter_uv_b0; ++ uint32_t mc_filter_uv_b; ++ #endif ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 4e90cc1..60bf079 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -636,6 +636,9 @@ unsigned int qpu_get_fn(int num) { ++ case QPU_MC_FILTER_UV: ++ fn = mc_filter_uv; ++ break; +++ case QPU_MC_FILTER_UV_B0: +++ fn = mc_filter_uv_b0; +++ break; ++ case QPU_MC_FILTER_UV_B: ++ fn = mc_filter_uv_b; ++ break; ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index f9ad333..543c84b 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -29,6 +29,7 @@ enum { ++ QPU_MC_FILTER_HONLY, ++ QPU_MC_SETUP_UV, ++ QPU_MC_FILTER_UV, +++ QPU_MC_FILTER_UV_B0, ++ QPU_MC_FILTER_UV_B, ++ QPU_MC_INTERRUPT_EXIT8, ++ QPU_MC_END ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 5d00cb2..88ad20b 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -39,18 +39,18 @@ unsigned int rpi_shader[] = { ++ /* [0x00000070] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++ /* [0x00000078] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++ /* [0x00000080] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000088] */ 0x00000040, 0xe0021567, // mov rb21, 64 ++-/* [0x00000090] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000098] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x000000a0] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x000000a8] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x000000b0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x000000b8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x000000c0] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x000000c8] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x000000d0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x000000d8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000e0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000088] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000090] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000098] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x000000a0] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x000000a8] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x000000b0] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x000000b8] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x000000c0] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x000000c8] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x000000d0] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x000000d8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000000e0] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++ /* [0x000000e8] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++ /* [0x000000f0] */ 0x159e7480, 0x10020867, // mov r1, r2 ++ /* [0x000000f8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++@@ -62,176 +62,176 @@ unsigned int rpi_shader[] = { ++ /* [0x00000128] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++ /* [0x00000130] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++ /* [0x00000138] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000140] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000148] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000150] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000158] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000160] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000168] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000170] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000178] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000180] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000188] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x00000190] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x00000198] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x000001a0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000001a8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001b0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000001b8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001c0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++-/* [0x000001c8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001d0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x000001d8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x000001e0] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x000001e8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000001f0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000001f8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000200] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000208] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000210] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000218] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000220] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000228] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000230] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000140] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x00000148] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000150] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000158] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000160] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000168] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000170] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000178] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000180] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000188] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000190] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 +++/* [0x00000198] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) +++/* [0x000001a0] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 +++/* [0x000001a8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x000001b0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000001b8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x000001c0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000001c8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000001d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000001d8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001e0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 +++/* [0x000001e8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x000001f0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x000001f8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x00000200] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x00000208] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000218] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000220] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000228] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000230] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000238] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000240] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000248] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000250] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv ++-/* [0x00000238] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000240] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000248] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000250] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000258] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000260] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000268] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000270] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000278] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000280] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000288] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000290] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000298] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002a0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002a8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002b0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002b8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002c0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000002c8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x000002d0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000002e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000002e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000002f0] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x000002f8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000300] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000308] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000310] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000318] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000320] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000340] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000350] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000360] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000368] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000370] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000378] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000380] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000388] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000390] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000258] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000260] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000268] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000270] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000278] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000280] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000288] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000290] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000298] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000002a0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000002a8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000002b0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002b8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002c0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002c8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002d0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002d8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002e0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000002e8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000002f0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002f8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000300] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000308] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000310] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000340] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000350] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000360] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000368] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000370] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000378] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000380] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000388] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000390] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000398] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x000003a0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000003a8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003b0] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x00000398] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003a0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000003a8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003b0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003b8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003c0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003c8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003d0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003d8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003e0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000003e8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003f0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000003f8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000400] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000408] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000410] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000418] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000420] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000428] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000430] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000438] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000440] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000448] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000450] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000458] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000460] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000468] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000470] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000478] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000480] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000488] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000490] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000498] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000004a0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000004a8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000004b0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000004b8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004c0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000004c8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000004d0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000004d8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x000004e0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x000004e8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x000004f0] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x000004f8] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000500] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000508] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000510] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000518] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000520] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000528] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000530] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000538] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000540] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000548] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000550] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000558] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000560] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000568] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000570] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000578] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000580] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000588] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000590] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000598] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-// ::mc_filter_uv_b ++-/* [0x000005a0] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000005a8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000005b0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000005b8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000005c0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000005c8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000005d0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000005d8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000005e0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000005e8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000005f0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000005f8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000600] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000608] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000610] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000618] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000620] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000628] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000630] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000638] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000640] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000648] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000650] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000658] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000660] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000668] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000670] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x000003b8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003c0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000003c8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003d0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003d8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003e0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003e8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003f0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003f8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000400] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000408] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000410] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000418] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000420] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000428] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000430] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000438] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000440] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000448] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000450] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000458] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000460] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000468] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000470] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000478] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000480] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000488] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000490] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000498] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x000004a0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x000004a8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x000004b0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x000004b8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000004c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000004c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000004d0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000004d8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004e0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000004e8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000004f0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000004f8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000500] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000508] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000510] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000518] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000520] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000528] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000530] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000538] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000540] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000548] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000550] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000558] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000560] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000568] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000570] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000578] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000580] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000588] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000590] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000598] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000005a0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000005a8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000005b0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000005b8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter_uv_b0 +++/* [0x000005c0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000005c8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000005d0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000005d8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000005e0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000005e8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000005f0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000005f8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000600] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000608] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000610] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000618] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000620] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000628] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000630] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000638] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000640] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000648] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000650] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000658] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000660] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000668] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000670] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++ /* [0x00000678] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++ /* [0x00000680] */ 0x15827d80, 0x10020827, // mov r0, unif ++ /* [0x00000688] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++@@ -253,7 +253,7 @@ unsigned int rpi_shader[] = { ++ /* [0x00000708] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++ /* [0x00000710] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ /* [0x00000718] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++-// :uvloop_b +++// :uvloop_b0 ++ /* [0x00000720] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++ /* [0x00000728] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++ /* [0x00000730] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++@@ -290,7 +290,7 @@ unsigned int rpi_shader[] = { ++ /* [0x00000828] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++ /* [0x00000830] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++ /* [0x00000838] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000840] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000840] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++ /* [0x00000848] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++ /* [0x00000850] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++ /* [0x00000858] */ 0x009e7000, 0x100009e7, // nop ; nop ++@@ -306,48 +306,163 @@ unsigned int rpi_shader[] = { ++ /* [0x000008a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ /* [0x000008b0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++ /* [0x000008b8] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x000008c0] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x000008c8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000008d0] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x000008d8] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000008e0] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x000008e8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x000008f0] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x000008f8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000900] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000908] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000910] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000918] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000920] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000928] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000930] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000938] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008c0] */ 0xfffffad8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000008c8] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x000008d0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000008d8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000008e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000008e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000008f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008f8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000900] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000908] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000910] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000918] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000920] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter_uv_b +++/* [0x00000928] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000930] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000938] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000940] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000948] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000950] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000958] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000960] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000968] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000970] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000978] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000980] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000988] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000990] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000998] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000009a0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000009a8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000009b0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000009b8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000009c0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000009c8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x000009d0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x000009d8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x000009e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000009e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000009f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000009f8] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x00000a00] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000a08] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000a10] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a18] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a20] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a28] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000a30] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a38] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a40] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a48] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000a50] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a58] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a60] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a68] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000a70] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a78] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a80] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a88] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000a90] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000a98] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000aa0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :uvloop_b +++/* [0x00000aa8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000ab0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000ab8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000ac0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000ac8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000ad0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000ad8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000ae0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000ae8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000af0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000af8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000b00] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000b08] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000b10] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000b18] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000b20] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000b28] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000b30] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000b38] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000b40] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000b48] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000b50] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000b58] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000b60] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000b68] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000b70] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000b78] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000b80] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000b88] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000b90] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000b98] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000ba0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000ba8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000bb0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000bb8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000bc0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000bc8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000bd0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000bd8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000be0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000be8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000bf0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000bf8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000c00] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000c08] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000c10] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000c18] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000c20] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000c28] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000c30] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000c38] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000c40] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000c48] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000c50] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000c58] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 +++/* [0x00000c60] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000c68] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000c70] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00000c78] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 +++/* [0x00000c80] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000c88] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000c90] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000c98] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000ca0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ca8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000cb0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000cb8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000cc0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000940] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000948] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000950] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000958] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000960] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000968] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000970] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000978] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000980] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000cc8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000cd0] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000cd8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ce0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ce8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000cf0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000cf8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000d00] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000d08] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000988] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000990] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000998] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009a0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009a8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009d0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009d8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009e0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000009e8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000009f0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000009f8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000d10] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000d18] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d20] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d28] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d30] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d38] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d40] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d48] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d50] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d58] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d60] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d70] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000d78] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000d80] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index e36c4ae..809e582 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,10 +4,11 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 142) ++-#define mc_filter_uv_b (rpi_shader + 360) ++-#define mc_exit (rpi_shader + 592) ++-#define mc_interrupt_exit8 (rpi_shader + 610) ++-#define mc_end (rpi_shader + 640) +++#define mc_filter_uv (rpi_shader + 150) +++#define mc_filter_uv_b0 (rpi_shader + 368) +++#define mc_filter_uv_b (rpi_shader + 586) +++#define mc_exit (rpi_shader + 818) +++#define mc_interrupt_exit8 (rpi_shader + 836) +++#define mc_end (rpi_shader + 866) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 870437d2..635b894 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -26,7 +26,7 @@ ++ # ra23 8 ++ # ++ # rb20 0xffffff00 ++-# rb21 64 +++# rb21 vpm_setup for writing 16bit results into VPM ++ # rb22 255 ++ # rb23 24 ++ # ++@@ -34,7 +34,7 @@ ++ # rb25 frame width-1 ++ # rb26 height<<23 + width<<16 + vdw_setup_0 ++ # rb27 vdw_setup_0 (depends on QPU number) ++-# rb28 vpm_setup (depends on QPU number) +++# rb28 vpm_setup (depends on QPU number) for writing 8bit results into VPM ++ # rb29 vdw_setup_1(dst_pitch-width) ++ # rb30 frame height-1 ++ # rb31 used as temp to count loop iterations ++@@ -69,8 +69,6 @@ ++ .set ra_y_next, ra28 ++ .set ra_y, ra29 ++ ++-.set rb_const_64, rb21 ++- ++ ++ ################################################################################ ++ # mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1, pad2) ++@@ -106,7 +104,6 @@ mov ra22, 256 ++ mov ra23, 8 ++ ++ mov rb20, 0xffffff00 ++-mov rb21, 64 ++ mov rb22, 255 ++ mov rb23, 24 ++ ++@@ -123,6 +120,7 @@ mov ra15, 0 ++ ++ # Compute part of VPM to use for DMA output ++ mov r2, qpu_num +++shl r2, r2, 1 # Convert QPU numbers to be even (this means we can only use 8 QPUs, but is necessary as we need to save 16bit intermediate results) ++ and r2, r2, 15 ++ mov r1, r2 ++ asr r1, r1, 2 ++@@ -135,16 +133,21 @@ shl r0, r0, 5 ++ add rb27, r0, r1 ++ ++ # Compute part of VPM to save data into ++-mov r2, qpu_num ++-and r2, r2, 15 ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vpm_setup(0, 4, h8p(0, 0)) +++mov r2, qpu_num # qpu_num = abcd +++shl r2, r2, 1 +++and r2, r2, 15 # r2 = bcd0 +++mov r1, r2 # r1 = bcd0 +++asr r1, r1, 2 # r1 = bc +++shl r1, r1, 6 # r1 = bc000000 +++mov r0, r2 # r0 = bcd0 +++and r0, r0, 3 # r0 = d0 +++add r0, r0, r1 # r0 = bc0000d0 +++mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit ++ add rb28, r0, r1 +++asr r0, r0, 1 # r0 = bc0000d +++# Prepare VPM command for 16bit intermediates +++mov r1, vpm_setup(0, 2, h16p(0, 0)) # 2 is stride - stride acts on ADDR which is Y[5:0],H[0] for 16 bit +++add rb21, r0, r1 ++ ++ # Compute base address for first and second access ++ mov r0, ra_x_base # Load x ++@@ -345,6 +348,171 @@ mov vw_addr, unif # start the VDW ++ ++ ################################################################################ ++ +++# mc_filter_uv_b0(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) +++ +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x_base, ra_x16_base point to the current coordinates for this block +++::mc_filter_uv_b0 +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # x +++max r0, r0, 0; mov r1, unif # y +++min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base +++shl ra_xshift_next, r0, 3 +++sub r2, unif, r3 # compute offset from frame base u to frame base v +++add r0, r0, r3 +++and rb_x_base_next, r0, ~3 +++mov ra_y_next, r1 +++add ra_x2_base_next, rb_x_base_next, r2 +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code +++ +++# get filter coefficients +++ +++mov r0, unif +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++asr rb15, r0, rb23; mul24 r0, r0, ra22 +++asr rb14, r0, rb23; mul24 r0, r0, ra22 +++asr rb13, r0, rb23; mul24 r0, r0, ra22 +++asr rb12, r0, rb23 +++ +++# r2 is elem_num +++# r3 is loop counter +++ +++mov r5rep, -8 +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++mov r3, 0 +++ +++:uvloop_b0 +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment +++shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_x2_base, r2 +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++nop ; mul24 r2, r0, ra0 +++nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++nop ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++add r0, r2, r3 +++ +++mov r3, rb31 +++ +++mov ra8, ra9 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++mov ra13, ra14 +++ +++sub.setf -, r3, 8 ; mov r1, ra22 +++ +++# apply horizontal filter +++brr.anyn -, r:uvloop_b0 +++mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll +++asr ra15, r0, 8 ; nop +++nop ; nop # Delay slot 3 (TODO move more of the context scroll into here) +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r1, ra14, rb14 +++nop ; mul24 r0, ra13, rb13 +++add r1, r1, r0 ; mul24 r0, ra12, rb12 +++add r1, r1, r0 ; mul24 r0, ra11, rb11 +++add r1, r1, r0 ; mul24 r0, ra10, rb10 +++add r1, r1, r0 ; mul24 r0, ra9, rb9 +++add r1, r1, r0 ; mul24 r0, ra8, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb15 +++add r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++asr r1, r1, 14 +++add r1, r1, ra21 +++brr.anyn -, r:uvloop +++asr r1, r1, 6 # Delay 1 +++min r1, r1, rb22 # Delay 2 +++max vpm, r1, 0 # Delay 3 +++ +++# DMA out for U +++ +++mov vw_setup, rb26 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++# DMA out for V +++# We need to wait for the U to complete first, but have nothing useful to compute while we wait. +++# Could potentially push this write into the start of the next pipeline stage. +++mov r0, 16 +++mov -, vw_wait +++ +++bra -, ra31 +++add vw_setup, rb26, r0 # VDW setup 0 +++mov vw_setup, rb29 # Stride +++mov vw_addr, unif # start the VDW +++ +++################################################################################ +++ ++ ::mc_filter_uv_b ++ mov ra31, unif ++ ++-- ++2.5.0 ++ ++ ++From 2949df95e5f5008ac156336d9089e7b3e9e67841 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 10:04:55 +0100 ++Subject: [PATCH 25/68] Switch to using 16bit temp buffers ++ ++--- ++ libavcodec/hevc.c | 2 +- ++ libavcodec/rpi_shader.c | 4 ++-- ++ libavcodec/rpi_shader.qasm | 10 +++++----- ++ 3 files changed, 8 insertions(+), 8 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 3994f2e..68cd237 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2136,7 +2136,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++- u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b0; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 88ad20b..ffd3a07 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -220,7 +220,7 @@ unsigned int rpi_shader[] = { ++ /* [0x00000600] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++ /* [0x00000608] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++ /* [0x00000610] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000618] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000618] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++ /* [0x00000620] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++ /* [0x00000628] */ 0x15827d80, 0x10020827, // mov r0, unif ++ /* [0x00000630] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++@@ -346,7 +346,7 @@ unsigned int rpi_shader[] = { ++ /* [0x000009e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++ /* [0x000009e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++ /* [0x000009f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000009f8] */ 0x0c9dc7c0, 0x10020c67, // add vr_setup, r3, rb28 +++/* [0x000009f8] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++ /* [0x00000a00] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++ /* [0x00000a08] */ 0x15827d80, 0x10020827, // mov r0, unif ++ /* [0x00000a10] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 635b894..9577121 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -26,7 +26,7 @@ ++ # ra23 8 ++ # ++ # rb20 0xffffff00 ++-# rb21 vpm_setup for writing 16bit results into VPM +++# rb21 vpm_setup for reading/writing 16bit results into VPM ++ # rb22 255 ++ # rb23 24 ++ # ++@@ -370,8 +370,8 @@ and rb_x_base_next, r0, ~3 ++ mov ra_y_next, r1 ++ add ra_x2_base_next, rb_x_base_next, r2 ++ ++-# set up VPM write ++-mov vw_setup, rb28 +++# set up VPM write, we need to save 16bit precision +++mov vw_setup, rb21 ++ ++ # get width,height of block ++ mov r2, 16 ++@@ -554,8 +554,8 @@ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++ add rb26, r0, rb27 ++ ++-# In a B frame, so also set up VPM read ++-add vr_setup, r3, rb28 +++# In a B frame, so also set up VPM read (reading back 16bit precision) +++add vr_setup, r3, rb21 ++ ++ sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++ ++-- ++2.5.0 ++ ++ ++From 7a3732950264ea60ac26aeca55d3ac269798d0c3 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 10:30:44 +0100 ++Subject: [PATCH 26/68] Corrected B prediction: matching md5 sum for hobbit50 ++ ++--- ++ libavcodec/rpi_shader.c | 815 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 12 +- ++ libavcodec/rpi_shader.qasm | 36 +- ++ 3 files changed, 429 insertions(+), 434 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index ffd3a07..77cca46 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -38,431 +38,428 @@ unsigned int rpi_shader[] = { ++ /* [0x00000068] */ 0x00000020, 0xe0020567, // mov ra21, 32 ++ /* [0x00000070] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++ /* [0x00000078] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++-/* [0x00000080] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000088] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000090] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x00000098] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x000000a0] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x000000a8] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x000000b0] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x000000b8] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x000000c0] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x000000c8] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x000000d0] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000d8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x000000e0] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-/* [0x000000e8] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x000000f0] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x000000f8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000100] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000108] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000110] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000118] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000120] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000128] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000130] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000138] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000140] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-/* [0x00000148] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000150] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000158] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000160] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000168] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000170] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000178] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000180] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000188] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000190] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 ++-/* [0x00000198] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++-/* [0x000001a0] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 ++-/* [0x000001a8] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x000001b0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000001b8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x000001c0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000001c8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000001d8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001e0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++-/* [0x000001e8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001f0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x000001f8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x00000200] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00000208] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000080] */ 0x00000040, 0xe00207a7, // mov ra30, 64 +++/* [0x00000088] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000090] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000098] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x000000a0] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x000000a8] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x000000b0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x000000b8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x000000c0] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x000000c8] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x000000d0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x000000d8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x000000e0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000000e8] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x000000f0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x000000f8] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000100] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000108] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000110] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000118] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000120] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000128] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000130] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000138] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000140] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000148] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x00000150] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000158] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000160] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000168] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000170] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000178] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000180] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000188] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000190] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000198] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 +++/* [0x000001a0] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) +++/* [0x000001a8] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 +++/* [0x000001b0] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base +++/* [0x000001b8] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000001c0] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base +++/* [0x000001c8] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000001d0] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000001d8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000001e0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001e8] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 +++/* [0x000001f0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x000001f8] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x00000200] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 +++/* [0x00000208] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++ /* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif ++ /* [0x00000218] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000220] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000228] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000230] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000238] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000240] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000248] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000250] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000220] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000228] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000230] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000238] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000240] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000248] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000250] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000258] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv ++-/* [0x00000258] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000260] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000268] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000270] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000278] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000280] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000288] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000290] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000298] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000002a0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000002a8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000002b0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002b8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002c0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002c8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002d0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002d8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002e0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000002e8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x000002f0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002f8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000300] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000308] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000310] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000340] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000350] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000360] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000368] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000370] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000378] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000380] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000388] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000390] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000398] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x000003a0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000003a8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003b0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000260] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000268] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000270] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000278] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000280] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000288] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000290] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000298] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000002a0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000002a8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000002b0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000002b8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002c0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002c8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002d0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002d8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002e0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002e8] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000002f0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000002f8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000310] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000318] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000320] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000328] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000340] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000348] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000350] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000360] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000368] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000370] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000378] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000380] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000388] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000390] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000398] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000003a0] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x000003a8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000003b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003b8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x000003b8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003c0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000003c8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003d0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003d8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003e0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003e8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003f0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003f8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000400] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000408] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000410] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000418] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000420] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000428] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000430] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000438] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000440] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000448] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000450] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000458] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000460] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000468] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000470] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000478] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000480] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000488] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000490] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000498] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x000004a0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x000004a8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x000004b0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x000004b8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000004c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000004c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000004d0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000004d8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004e0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000004e8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000004f0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000004f8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000500] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000508] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000510] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000518] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000520] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000528] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000530] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000538] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000540] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000548] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000550] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000558] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000560] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000568] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000570] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000578] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000580] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000588] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000590] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000598] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000005a0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000005a8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000005b0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000005b8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000003c0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003c8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000003d0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003d8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003e0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003e8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003f0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003f8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000400] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000408] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000410] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000418] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000420] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000428] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000430] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000438] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000440] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000448] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000450] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000458] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000460] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000468] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000470] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000478] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000480] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000488] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000490] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000498] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x000004a0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x000004a8] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x000004b0] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x000004b8] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x000004c0] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x000004c8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000004d0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000004d8] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x000004e0] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004e8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000004f0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000004f8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000500] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000508] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000510] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000518] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000520] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000528] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000530] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000538] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000540] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000548] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000550] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000558] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000560] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000568] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000570] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000578] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000580] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000588] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000590] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000598] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000005a0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000005a8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000005b0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000005b8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000005c0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x000005c0] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000005c8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000005d0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000005d8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000005e0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000005e8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000005f0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000005f8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000600] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000608] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000610] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000618] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000620] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000628] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000630] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000638] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000640] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000648] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000650] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000658] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000660] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000668] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000670] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000678] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000680] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000688] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000690] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000698] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000006a8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000006c8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000006e8] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f0] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f8] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000700] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000708] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000710] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000718] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000005c8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000005d0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000005d8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000005e0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000005e8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000005f0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000005f8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000600] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000608] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000610] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000618] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000620] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000628] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000630] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000638] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000640] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000648] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000650] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000658] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000660] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000668] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000670] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000678] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000680] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000688] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000690] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000698] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000006b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000006d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000006f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000006f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000700] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000708] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000710] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000718] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000720] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000720] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000728] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000730] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000738] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000740] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000748] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000750] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000758] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000760] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000768] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000770] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000778] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000780] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000788] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000790] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000798] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000007a0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000007a8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000007b0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000007b8] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000007c0] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000007c8] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000007d0] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000007d8] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000007e0] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000007e8] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000007f0] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x000007f8] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000800] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000808] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000810] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000818] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000820] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000828] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000830] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000838] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000840] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000848] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000850] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000858] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000860] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000868] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000870] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000878] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000880] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000888] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000890] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000898] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000008a0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000008a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000008b0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000008b8] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x000008c0] */ 0xfffffad8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000008c8] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x000008d0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000008d8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000008e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000008e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000008f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000008f8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000900] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000908] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000910] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000918] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000920] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000728] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000730] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000738] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000740] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000748] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000750] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000758] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000760] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000768] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000770] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000778] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000780] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000788] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000790] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000798] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000007a0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000007a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000007b0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000007b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000007c0] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000007c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000007d0] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000007d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000007e0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000007e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000007f0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000007f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000800] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000808] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000810] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000818] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000820] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000828] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000830] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000838] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000840] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000848] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000850] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000858] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000860] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000868] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000870] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000878] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000880] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000888] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000890] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000898] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x000008a0] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000008a8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000008b0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000008b8] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000008c0] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 +++/* [0x000008c8] */ 0x009e7000, 0x100009e7, // nop +++/* [0x000008d0] */ 0x009e7000, 0x100009e7, // nop +++/* [0x000008d8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000008e0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000008e8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008f0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000008f8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000900] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000908] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000910] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000918] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x00000928] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000930] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000938] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000940] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000948] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000950] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000958] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000960] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000968] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000970] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000978] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000980] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000988] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000990] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000998] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000009a0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000009a8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000009b0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000009b8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x000009c0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000009c8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x000009d0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x000009d8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x000009e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000009e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000009f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000009f8] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000a00] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000a08] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000a10] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a18] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a20] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a28] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000a30] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a38] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a40] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a48] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000a50] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a58] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a60] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a68] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000a70] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a78] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a80] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a88] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000a90] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000a98] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000aa0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000920] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000928] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000930] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000938] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000940] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000948] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000950] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000958] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000960] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000968] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000970] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000978] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000980] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000988] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000990] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000998] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000009a0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000009a8] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000009b0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000009b8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000009c0] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x000009c8] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x000009d0] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x000009d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000009e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000009e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000009f0] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x000009f8] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000a00] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000a08] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a10] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a18] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a20] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000a28] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a30] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a38] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a40] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000a48] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a50] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a58] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a60] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000a68] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a70] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a78] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000a80] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000a88] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000a90] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000a98] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000aa8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000ab0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000ab8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000ac0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000ac8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000ad0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000ad8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000ae0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000ae8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000af0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000af8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000b00] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000b08] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000b10] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000b18] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000b20] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000b28] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000b30] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000b38] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000b40] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000b48] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000b50] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000b58] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000b60] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000b68] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000b70] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000b78] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000b80] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000b88] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000b90] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000b98] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000ba0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000ba8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000bb0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000bb8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000bc0] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000bc8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000bd0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000bd8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000be0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000be8] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000bf0] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000bf8] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000c00] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000c08] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000c10] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000c18] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000c20] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000c28] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000c30] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000c38] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000c40] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000c48] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000c50] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000c58] */ 0x0cc01dc0, 0xd0020827, // add r0, vpm, 1 ++-/* [0x00000c60] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000c68] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000c70] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x00000c78] */ 0x0e9c13c0, 0xd0020c27, // shr vpm, r1, 1 ++-/* [0x00000c80] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000c88] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000c90] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000c98] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000ca0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000ca8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000cb0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000cb8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000cc0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000aa0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000aa8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000ab0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000ab8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000ac0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000ac8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000ad0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000ad8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000ae0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000ae8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000af0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000af8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000b00] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000b08] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000b10] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000b18] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000b20] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000b28] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000b30] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000b38] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000b40] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000b48] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000b50] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000b58] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000b60] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000b68] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000b70] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000b78] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000b80] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000b88] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000b90] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000b98] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000ba0] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000ba8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000bb0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000bb8] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000bc0] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000bc8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000bd0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000bd8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000be0] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000be8] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000bf0] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000bf8] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000c00] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000c08] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000c10] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000c18] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000c20] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000c28] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000c30] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000c38] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000c40] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000c48] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000c50] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000c58] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000c60] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000c68] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000c70] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000c78] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000c80] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000c88] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000c90] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000c98] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000ca0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000ca8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000cc8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000cd0] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000cb0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000cb8] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000cc0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000cc8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000cd0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000cd8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ce0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ce8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000cf0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000cf8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000d00] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000d08] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000ce0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ce8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000cf0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000d10] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000cf8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000d00] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d08] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d10] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000d18] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d20] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d28] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d30] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000d20] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d28] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000d30] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000d38] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000d40] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000d48] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000d50] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d58] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d60] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d70] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000d78] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000d80] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000d58] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000d60] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000d68] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 809e582..6562fa9 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,11 +4,11 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 150) ++-#define mc_filter_uv_b0 (rpi_shader + 368) ++-#define mc_filter_uv_b (rpi_shader + 586) ++-#define mc_exit (rpi_shader + 818) ++-#define mc_interrupt_exit8 (rpi_shader + 836) ++-#define mc_end (rpi_shader + 866) +++#define mc_filter_uv (rpi_shader + 152) +++#define mc_filter_uv_b0 (rpi_shader + 370) +++#define mc_filter_uv_b (rpi_shader + 584) +++#define mc_exit (rpi_shader + 812) +++#define mc_interrupt_exit8 (rpi_shader + 830) +++#define mc_end (rpi_shader + 860) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 9577121..562dc35 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -39,13 +39,13 @@ ++ # rb30 frame height-1 ++ # rb31 used as temp to count loop iterations ++ # ++-# ra24...ra30 15, 14, 13, 12, 11, 10, 9 ++ # ra24 clipped(row start address+8+elem_num)&~3 ++ # ra25 per-channel shifts 2 ++ # ra26 next ra24 ++ # ra27 next ra25 ++ # ra28 next y ++ # ra29 y for next texture access +++# ra30 64 ++ # ++ # ra31 next kernel address ++ ++@@ -102,6 +102,7 @@ mov ra20, 1 ++ mov ra21, 32 ++ mov ra22, 256 ++ mov ra23, 8 +++mov ra30, 64 ++ ++ mov rb20, 0xffffff00 ++ mov rb22, 255 ++@@ -472,7 +473,7 @@ sub.setf -, r3, 8 ; mov r1, ra22 ++ # apply horizontal filter ++ brr.anyn -, r:uvloop_b0 ++ mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll ++-asr ra15, r0, 8 ; nop +++asr ra15, r0, 8 ; nop # TODO isn't ra15 already in 24bit precision, may not need the sign extension here? ++ nop ; nop # Delay slot 3 (TODO move more of the context scroll into here) ++ ++ # apply vertical filter and write to VPM ++@@ -487,18 +488,18 @@ add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ add r1, r1, r0 ; mul24 r0, ra15, rb15 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 14 ++-add r1, r1, ra21 ++-brr.anyn -, r:uvloop ++-asr r1, r1, 6 # Delay 1 ++-min r1, r1, rb22 # Delay 2 ++-max vpm, r1, 0 # Delay 3 +++#asr r1, r1, 14 +++#add r1, r1, ra21 +++brr.anyn -, r:uvloop_b0 +++asr vpm, r1, 14 # Delay 1 shifts down by shift2=6, but results are still in 16bit precision TODO may be able to avoid the mul24 and use more delay slots +++nop # Delay 2 +++nop # Delay 3 ++ ++ # DMA out for U ++ ++ mov vw_setup, rb26 # VDW setup 0 ++ mov vw_setup, rb29 # Stride ++-mov vw_addr, unif # start the VDW +++mov vw_addr, unif # start the VDW # TODO in pass0 we don't need to save any results ++ ++ # DMA out for V ++ # We need to wait for the U to complete first, but have nothing useful to compute while we wait. ++@@ -639,12 +640,11 @@ mov ra12, ra13 ++ mov ra13, ra14 ++ ++ sub.setf -, r3, 8 ; mov r1, ra22 ++- ++ # apply horizontal filter ++ brr.anyn -, r:uvloop_b ++ mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++ asr ra15, r0, 8 ; nop ++-nop ; nop +++nop ; nop # TODO improve use of delay slots ++ ++ # apply vertical filter and write to VPM ++ ++@@ -658,15 +658,13 @@ add r1, r1, r0 ; mul24 r0, ra8, rb8 ++ add r1, r1, r0 ; mul24 r0, ra15, rb15 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 14 ++-add r1, r1, ra21 ++-asr r1, r1, 6 ++-min r1, r1, rb22 ++-add r0, vpm, 1 # Blend in previous VPM contents at this location +++asr r1, r1, 14 # shift2=6 +++add r1, r1, vpm # Blend in previous VPM contents at this location +++add r1, r1, ra30 ++ brr.anyn -, r:uvloop_b ++-max r1, r1, 0 ++-add r1, r1, r0 ++-shr vpm, r1, 1 +++asr r1, r1, 7 # Delay 1 +++min r1, r1, rb22 # Delay 2 +++max vpm, r1, 0 # Delay 3 ++ ++ ++ # DMA out for U ++-- ++2.5.0 ++ ++ ++From 7f612d9e21849e339ef0ad0e2e5d8a2acaad2552 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 10:55:07 +0100 ++Subject: [PATCH 27/68] P prediction uses 4 tap filters ++ ++--- ++ libavcodec/hevc.c | 50 ++-- ++ libavcodec/rpi_shader.c | 631 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 10 +- ++ libavcodec/rpi_shader.qasm | 43 +-- ++ 4 files changed, 344 insertions(+), 390 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 68cd237..8984585 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -65,15 +65,15 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ #define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++ // TODO Chroma only needs 4 taps ++-static uint32_t rpi_filter_coefs[8][2] = { ++- { ENCODE_COEFFS( 0, 0, 0, 64), ENCODE_COEFFS( 0, 0, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -2, 58), ENCODE_COEFFS( 10, -2, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -4, 54), ENCODE_COEFFS( 16, -2, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -6, 46), ENCODE_COEFFS( 28, -4, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -4, 36), ENCODE_COEFFS( 36, -4, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -4, 28), ENCODE_COEFFS( 46, -6, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -2, 16), ENCODE_COEFFS( 54, -4, 0, 0 ) }, ++- { ENCODE_COEFFS( 0, 0, -2, 10), ENCODE_COEFFS( 58, -2, 0, 0 ) } +++static uint32_t rpi_filter_coefs[8][1] = { +++ { ENCODE_COEFFS( 0, 64, 0, 0) }, +++ { ENCODE_COEFFS( -2, 58, 10, -2) }, +++ { ENCODE_COEFFS( -4, 54, 16, -2) }, +++ { ENCODE_COEFFS( -6, 46, 28, -4) }, +++ { ENCODE_COEFFS( -4, 36, 36, -4) }, +++ { ENCODE_COEFFS( -4, 28, 46, -6) }, +++ { ENCODE_COEFFS( -2, 16, 54, -4) }, +++ { ENCODE_COEFFS( -2, 10, 58, -2) } ++ }; ++ ++ static uint32_t get_vc_address(AVBufferRef *bref) { ++@@ -2016,16 +2016,16 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++- *u++ = rpi_filter_coefs[_mx][1]; +++ u++; ++ *u++ = rpi_filter_coefs[_my][0]; ++- *u++ = rpi_filter_coefs[_my][1]; +++ u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2073,16 +2073,16 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++- *u++ = rpi_filter_coefs[_mx][1]; +++ u++; ++ *u++ = rpi_filter_coefs[_my][0]; ++- *u++ = rpi_filter_coefs[_my][1]; +++ u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2137,29 +2137,29 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b0; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 3 + start_x; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++ *u++ = ( (nPbW_cframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); // TODO this will become unused once we have a dedicated pass0 filter ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = x2_c - 3 + start_x; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = y2_c - 3 + start_y; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = x2_c - 1 + start_x; +++ u++[-RPI_CHROMA_COMMAND_WORDS] = y2_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx2][0]; ++- *u++ = rpi_filter_coefs[_mx2][1]; +++ u++; ++ *u++ = rpi_filter_coefs[_my2][0]; ++- *u++ = rpi_filter_coefs[_my2][1]; +++ u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 77cca46..c8d0728 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -116,8 +116,8 @@ unsigned int rpi_shader[] = { ++ /* [0x000002d0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++ /* [0x000002d8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++ /* [0x000002e0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002e8] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000002f0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000002e8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000002f0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++ /* [0x000002f8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++ /* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++ /* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++@@ -128,338 +128,315 @@ unsigned int rpi_shader[] = { ++ /* [0x00000330] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ /* [0x00000338] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ /* [0x00000340] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000348] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000350] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000360] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000368] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000370] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000378] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000380] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000388] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000390] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000398] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000003a0] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x000003a8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000003b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003b8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000348] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000350] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000360] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000368] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000370] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000378] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000380] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x000003c0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003c8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000003d0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003d8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003e0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003e8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003f0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003f8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000400] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000408] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000410] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000418] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000420] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000428] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000430] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000438] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000440] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000448] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000450] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000458] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000460] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000468] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000470] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000478] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000480] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000488] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000490] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000498] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x000004a0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x000004a8] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x000004b0] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x000004b8] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x000004c0] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x000004c8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000004d0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000004d8] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x000004e0] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004e8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000004f0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000004f8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000500] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000508] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000510] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000518] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000520] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000528] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000530] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000538] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000540] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000548] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000550] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000558] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000560] */ 0xfffffe40, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000568] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000570] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000578] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000580] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000588] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000590] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000598] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000005a0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000005a8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000005b0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000005b8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000005c0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000388] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000390] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000398] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003a0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003a8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003b0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003c0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003c8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000003d0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000003d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003e0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003e8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000003f0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000003f8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000400] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000408] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000410] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000418] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000420] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000428] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000430] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000438] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000440] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 +++/* [0x00000448] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000450] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000458] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000460] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000468] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000470] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000478] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000480] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000488] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000490] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000498] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000004a0] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x000004a8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004b0] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x000004b8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000004c0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000004c8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000004d0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004d8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000004e0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000004e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000004f0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000004f8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000500] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000508] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x000005c8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000005d0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000005d8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000005e0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000005e8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000005f0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000005f8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000600] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000608] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000610] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000618] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000620] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000628] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000630] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000638] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000640] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000648] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000650] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000658] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000660] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000668] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000670] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000678] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000680] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000688] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000690] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000698] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000006b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000006d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000006f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000006f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000700] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000708] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000710] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000718] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000720] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000510] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000518] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000520] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000528] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000530] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000538] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000540] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000548] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000550] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000558] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000560] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000568] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000570] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000578] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000580] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000588] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000590] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000598] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000005a0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x000005a8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000005b0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000005b8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000005c0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000005c8] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x000005d0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005d8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005f0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005f8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000600] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000608] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000610] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000618] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000620] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000628] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000630] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000638] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000640] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000648] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000650] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000658] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000668] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000728] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000730] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000738] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000740] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000748] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000750] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000758] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000760] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000768] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000770] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000778] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000780] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000788] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000790] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000798] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000007a0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000007a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000007b0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000007b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000007c0] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000007c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000007d0] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000007d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000007e0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000007e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000007f0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000007f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000800] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000808] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000810] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000818] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000820] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000828] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000830] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000838] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000840] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000848] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000850] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000858] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000860] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000868] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000870] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000878] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000880] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000888] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000890] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000898] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x000008a0] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000008a8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000008b0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000008b8] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000008c0] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 ++-/* [0x000008c8] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x000008d0] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x000008d8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000008e0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000008e8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000008f0] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000008f8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000900] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000908] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000910] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000918] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000670] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000678] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000680] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000688] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000690] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000698] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000006a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000006a8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000006b0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000006b8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000006c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000006c8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000006d0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000006d8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000006e0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000006e8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000006f0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000006f8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000700] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000708] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000710] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000718] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000720] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000728] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000730] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000738] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000740] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000748] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000750] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000758] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000760] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000768] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000770] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000778] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000780] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000788] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000790] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000798] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000007a0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000007a8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000007b0] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x000007b8] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x000007c0] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x000007c8] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x000007d0] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x000007d8] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x000007e0] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x000007e8] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x000007f0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000007f8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000800] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000808] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 +++/* [0x00000810] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000818] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000820] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000828] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000830] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000838] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000840] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000848] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000850] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000858] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000860] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x00000920] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000928] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000930] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000938] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000940] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000948] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000950] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000958] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000960] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000968] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000970] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000978] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000980] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000988] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000990] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000998] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000009a0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000009a8] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000009b0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x000009b8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000009c0] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x000009c8] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x000009d0] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x000009d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000009e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000009e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000009f0] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x000009f8] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000a00] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000a08] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a10] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a18] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a20] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000a28] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a30] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a38] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a40] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000a48] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a50] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a58] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a60] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000a68] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a70] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a78] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000a80] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000a88] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000a90] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000a98] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000868] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000870] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000878] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000880] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000888] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000890] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000898] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000008a0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000008a8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000008b0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000008b8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000008c0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000008c8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000008d0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008d8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000008e0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000008e8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000008f0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x000008f8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000900] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000908] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000910] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000918] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000920] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000928] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000930] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000938] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000940] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000948] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000950] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000958] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000960] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000968] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000970] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000978] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000980] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000988] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000990] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000998] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000009a0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000009a8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000009b0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000009b8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000009c0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000009c8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x000009d0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000009d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000009e0] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000aa0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000aa8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000ab0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000ab8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000ac0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000ac8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000ad0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000ad8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000ae0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000ae8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000af0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000af8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000b00] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000b08] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000b10] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000b18] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000b20] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000b28] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000b30] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000b38] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000b40] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000b48] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000b50] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000b58] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000b60] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000b68] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000b70] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000b78] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000b80] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000b88] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000b90] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000b98] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000ba0] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000ba8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000bb0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000bb8] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000bc0] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000bc8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000bd0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000bd8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000be0] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000be8] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000bf0] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000bf8] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000c00] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000c08] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000c10] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000c18] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000c20] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000c28] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000c30] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000c38] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000c40] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000c48] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000c50] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000c58] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000c60] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000c68] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000c70] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000c78] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000c80] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000c88] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000c90] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000c98] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000ca0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000ca8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000009e8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000009f0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000009f8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000a00] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000a08] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000a10] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000a18] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000a20] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000a28] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000a30] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000a38] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000a40] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000a48] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000a50] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000a58] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000a60] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000a68] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000a70] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000a78] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000a80] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00000a88] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00000a90] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00000a98] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00000aa0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00000aa8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00000ab0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00000ab8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000ac0] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000ac8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000ad0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000ad8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000ae0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000ae8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000af0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000af8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000b00] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000b08] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000b10] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000b18] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000b20] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b28] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000b30] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000b38] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000b40] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000b48] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000b50] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000b58] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000b60] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000b68] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000b70] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000b78] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000b80] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000b88] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000b90] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000b98] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000ba0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000ba8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000bb0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000bb8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000bc0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000bc8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000bd0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000bd8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000be0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000be8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000bf0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000cb0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000cb8] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000cc0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000cc8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000cd0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000cd8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ce0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ce8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000cf0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000bf8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000c00] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000c08] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c10] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c18] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c20] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c28] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000c30] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000c38] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000cf8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000d00] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d08] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d10] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d18] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000d20] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d28] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d30] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d38] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d40] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d48] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d50] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000d58] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000d60] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000d68] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000c40] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000c48] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c50] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c58] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c60] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000c68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c80] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c88] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c90] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000c98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ca0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ca8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000cb0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 6562fa9..1bf7a68 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -5,10 +5,10 @@ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 152) ++-#define mc_filter_uv_b0 (rpi_shader + 370) ++-#define mc_filter_uv_b (rpi_shader + 584) ++-#define mc_exit (rpi_shader + 812) ++-#define mc_interrupt_exit8 (rpi_shader + 830) ++-#define mc_end (rpi_shader + 860) +++#define mc_filter_uv_b0 (rpi_shader + 324) +++#define mc_filter_uv_b (rpi_shader + 538) +++#define mc_exit (rpi_shader + 766) +++#define mc_interrupt_exit8 (rpi_shader + 784) +++#define mc_end (rpi_shader + 814) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 562dc35..8e4f18f 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -16,8 +16,8 @@ ++ # ra19 next ra17 ++ # ++ # rb16 pitch ++-# rb17 height + 5 ++-# rb18 height + 7 +++# rb17 height + 1 +++# rb18 height + 3 ++ # rb19 next ra16 ++ # ++ # ra20 1 ++@@ -214,8 +214,8 @@ mov r0, unif ++ shr r1, r0, r2 # Extract width ++ sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++ and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 +++add rb17, r0, 1 +++add rb18, r0, 3 ++ shl r0, r0, 7 ++ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++@@ -230,18 +230,11 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif +++ mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23; mov r0, unif ++-asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-asr rb12, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++@@ -283,26 +276,14 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++ add r0, r2, r3 ++ ++ mov r3, rb31 ++ ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++ mov ra12, ra13 ++ mov ra13, ra14 ++ ++-sub.setf -, r3, 8 ; mov r1, ra22 +++sub.setf -, r3, 4 ; mov r1, ra22 ++ ++ # apply horizontal filter ++ brr.anyn -, r:uvloop ++@@ -312,14 +293,10 @@ nop ; nop # Delay slot 3 (TODO move more of the context scr ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r1, ra14, rb14 ++-nop ; mul24 r0, ra13, rb13 ++-add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-add r1, r1, r0 ; mul24 r0, ra15, rb15 +++nop ; mul24 r1, ra14, rb10 +++nop ; mul24 r0, ra13, rb9 +++add r1, r1, r0 ; mul24 r0, ra12, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb11 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ asr r1, r1, 14 ++-- ++2.5.0 ++ ++ ++From b7f5bb6522a31aeb9e69f18f3b5cc9c73636685c Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:03:51 +0100 ++Subject: [PATCH 28/68] Optimised B0 pass ++ ++--- ++ libavcodec/rpi_shader.c | 424 +++++++++++++++++++++------------------------ ++ libavcodec/rpi_shader.h | 8 +- ++ libavcodec/rpi_shader.qasm | 43 +---- ++ 3 files changed, 212 insertions(+), 263 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index c8d0728..1f63ee0 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -204,239 +204,215 @@ unsigned int rpi_shader[] = { ++ /* [0x00000580] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++ /* [0x00000588] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++ /* [0x00000590] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000598] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000005a0] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000598] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000005a0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++ /* [0x000005a8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++ /* [0x000005b0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++ /* [0x000005b8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++ /* [0x000005c0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000005c8] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x000005d0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005d8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005f0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000005f8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000600] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000608] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000610] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000618] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000620] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000628] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000630] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000638] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000640] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000648] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000650] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000658] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000668] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000005c8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005d0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005d8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005f0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005f8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000600] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000608] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000610] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000618] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000620] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000628] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000670] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000678] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000680] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000688] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000690] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000698] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000006a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000006a8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000006b0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000006b8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000006c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000006c8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000006d0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000006d8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000006e0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000006e8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000006f0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000006f8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000700] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000708] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000710] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000718] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000720] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000728] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000730] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000738] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000740] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000748] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000750] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000758] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000760] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000768] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000770] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000778] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000780] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000788] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000790] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000798] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000007a0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000007a8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000007b0] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x000007b8] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x000007c0] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x000007c8] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x000007d0] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x000007d8] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x000007e0] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x000007e8] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x000007f0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000007f8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000800] */ 0xfffffe50, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000808] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 ++-/* [0x00000810] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000818] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000820] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000828] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000830] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000838] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000840] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000848] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000850] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000858] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000860] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000630] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000638] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000640] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000648] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000650] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000658] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000660] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000668] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000670] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000678] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000680] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000688] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000690] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000698] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000006a0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000006a8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000006b0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000006b8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000006c0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000006c8] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x000006d0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x000006d8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000006e0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000006e8] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 +++/* [0x000006f0] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006f8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000700] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000708] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000710] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000718] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000720] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000728] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000730] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000738] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000740] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000748] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 +++/* [0x00000750] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000758] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000760] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000768] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000770] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000778] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000780] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000788] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000790] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000798] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000007a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x00000868] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000870] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000878] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000880] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000888] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000890] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000898] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000008a0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000008a8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000008b0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000008b8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000008c0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000008c8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000008d0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008d8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000008e0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000008e8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000008f0] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x000008f8] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000900] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000908] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000910] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000918] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000920] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000928] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000930] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000938] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000940] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000948] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000950] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000958] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000960] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000968] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000970] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000978] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000980] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000988] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000990] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000998] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000009a0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000009a8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000009b0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000009b8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000009c0] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000009c8] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x000009d0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000009d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000009e0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000007a8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000007b0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000007b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000007c0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000007c8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000007d0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007d8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007e0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007e8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000007f0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000007f8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000800] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000808] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000810] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000818] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000820] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000828] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000830] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000838] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000840] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000848] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000850] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000858] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000860] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000868] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000870] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000878] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000880] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 +++/* [0x00000888] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000890] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000898] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000008b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000008d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000008f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000900] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000908] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 +++/* [0x00000910] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000918] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000920] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000009e8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000009f0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000009f8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000a00] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000a08] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000a10] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000a18] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000a20] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000a28] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000a30] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000a38] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000a40] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000a48] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000a50] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000a58] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000a60] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000a68] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000a70] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000a78] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000a80] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00000a88] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00000a90] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00000a98] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00000aa0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00000aa8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00000ab0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00000ab8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000ac0] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000ac8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000ad0] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000ad8] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000ae0] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000ae8] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000af0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000af8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000b00] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000b08] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000b10] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000b18] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000b20] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000b28] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000b30] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000b38] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000b40] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000b48] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000b50] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000b58] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000b60] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000b68] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000b70] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000b78] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000b80] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000b88] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000b90] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000b98] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000ba0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000ba8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000bb0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000bb8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000bc0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000bc8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000bd0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000bd8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000be0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000be8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000bf0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000928] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000930] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000938] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000940] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000948] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000950] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000958] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000960] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000968] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000970] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000978] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000980] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000988] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000990] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000998] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000009a0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000009a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000009b0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000009b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000009c0] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x000009c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x000009d0] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x000009d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x000009e0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x000009e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x000009f0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x000009f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00000a00] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000a08] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000a10] */ 0x15267d80, 0x10020227, // mov ra8, ra9 +++/* [0x00000a18] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00000a20] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00000a28] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00000a30] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000a38] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000a40] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 +++/* [0x00000a48] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000a50] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x00000a58] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x00000a60] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a68] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 +++/* [0x00000a70] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 +++/* [0x00000a78] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 +++/* [0x00000a80] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 +++/* [0x00000a88] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 +++/* [0x00000a90] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 +++/* [0x00000a98] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 +++/* [0x00000aa0] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 +++/* [0x00000aa8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000ab0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000ab8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000ac0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000ac8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000ad0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000ad8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000ae0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000ae8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000af0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000af8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000b00] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000b08] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000b10] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000b18] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000b20] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000b28] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000b30] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000bf8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000c00] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000c08] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c10] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c18] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c20] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c28] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000c30] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000c38] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000b40] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000b48] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b50] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b58] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b60] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b68] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b70] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b78] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000c40] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000c48] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c50] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c58] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c60] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000c68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c80] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c88] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c90] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000c98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ca0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ca8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000cb0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b80] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000b88] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b90] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000b98] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ba0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ba8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bb0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bb8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bc0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bc8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bd0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000bd8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000be0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000be8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000bf0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 1bf7a68..cb74887 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -6,9 +6,9 @@ extern unsigned int rpi_shader[]; ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 152) ++ #define mc_filter_uv_b0 (rpi_shader + 324) ++-#define mc_filter_uv_b (rpi_shader + 538) ++-#define mc_exit (rpi_shader + 766) ++-#define mc_interrupt_exit8 (rpi_shader + 784) ++-#define mc_end (rpi_shader + 814) +++#define mc_filter_uv_b (rpi_shader + 490) +++#define mc_exit (rpi_shader + 718) +++#define mc_interrupt_exit8 (rpi_shader + 736) +++#define mc_end (rpi_shader + 766) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 8e4f18f..faa5755 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -357,15 +357,13 @@ mov r0, unif ++ shr r1, r0, r2 # Extract width ++ sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++ and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 +++add rb17, r0, 1 +++add rb18, r0, 3 ++ shl r0, r0, 7 ++ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++ add rb26, r0, rb27 ++ ++-sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++- ++ # get filter coefficients ++ ++ mov r0, unif ++@@ -373,18 +371,11 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif +++ mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23; mov r0, unif ++-asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-asr rb12, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++@@ -426,26 +417,14 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++ add r0, r2, r3 ++ ++ mov r3, rb31 ++ ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++ mov ra12, ra13 ++ mov ra13, ra14 ++ ++-sub.setf -, r3, 8 ; mov r1, ra22 +++sub.setf -, r3, 4 ; mov r1, ra22 ++ ++ # apply horizontal filter ++ brr.anyn -, r:uvloop_b0 ++@@ -455,18 +434,12 @@ nop ; nop # Delay slot 3 (TODO move more of the context scr ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r1, ra14, rb14 ++-nop ; mul24 r0, ra13, rb13 ++-add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-add r1, r1, r0 ; mul24 r0, ra15, rb15 +++nop ; mul24 r1, ra14, rb10 +++nop ; mul24 r0, ra13, rb9 +++add r1, r1, r0 ; mul24 r0, ra12, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb11 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-#asr r1, r1, 14 ++-#add r1, r1, ra21 ++ brr.anyn -, r:uvloop_b0 ++ asr vpm, r1, 14 # Delay 1 shifts down by shift2=6, but results are still in 16bit precision TODO may be able to avoid the mul24 and use more delay slots ++ nop # Delay 2 ++-- ++2.5.0 ++ ++ ++From 6e69afcdf13d39d3f108824ae4496df799f7a6bd Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:12:43 +0100 ++Subject: [PATCH 29/68] Optimised B pass ++ ++--- ++ libavcodec/rpi_shader.c | 202 ++++++++++++++++++++------------------------- ++ libavcodec/rpi_shader.h | 6 +- ++ libavcodec/rpi_shader.qasm | 41 ++------- ++ 3 files changed, 100 insertions(+), 149 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 1f63ee0..4e6c5ea 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -289,8 +289,8 @@ unsigned int rpi_shader[] = { ++ /* [0x00000818] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++ /* [0x00000820] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++ /* [0x00000828] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000830] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000838] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000830] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000838] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++ /* [0x00000840] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++ /* [0x00000848] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++ /* [0x00000850] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++@@ -299,120 +299,96 @@ unsigned int rpi_shader[] = { ++ /* [0x00000868] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++ /* [0x00000870] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++ /* [0x00000878] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000880] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000888] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000890] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000898] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000008b0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b8] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c8] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000008d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000008f0] */ 0x4f5971c6, 0x100253e0, // asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008f8] */ 0x4f5971c6, 0x100253a0, // asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000900] */ 0x4f5971c6, 0x10025360, // asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000908] */ 0x0f9d71c0, 0x10021327, // asr rb12, r0, rb23 ++-/* [0x00000910] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000918] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000920] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000880] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000888] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000890] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000898] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000008a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008b0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000008d0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008e0] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000928] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000930] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000938] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000940] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000948] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000950] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000958] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000960] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000968] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000970] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000978] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000980] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000988] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000990] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000998] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000009a0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000009a8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000009b0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000009b8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000009c0] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x000009c8] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x000009d0] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x000009d8] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x000009e0] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x000009e8] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x000009f0] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x000009f8] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00000a00] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000a08] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000a10] */ 0x15267d80, 0x10020227, // mov ra8, ra9 ++-/* [0x00000a18] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00000a20] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00000a28] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00000a30] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000a38] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000a40] */ 0x8d5887f6, 0xd00269e1, // sub.setf -, r3, 8 ; mov r1, ra22 ++-/* [0x00000a48] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000a50] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000a58] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000a60] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000a68] */ 0x4038e037, 0x100049e1, // nop ; mul24 r1, ra14, rb14 ++-/* [0x00000a70] */ 0x4034d037, 0x100049e0, // nop ; mul24 r0, ra13, rb13 ++-/* [0x00000a78] */ 0x4c30c237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-/* [0x00000a80] */ 0x4c2cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-/* [0x00000a88] */ 0x4c28a237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-/* [0x00000a90] */ 0x4c249237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-/* [0x00000a98] */ 0x4c208237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-/* [0x00000aa0] */ 0x4c3cf237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb15 ++-/* [0x00000aa8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000ab0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000ab8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000ac0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000ac8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000ad0] */ 0xfffffe38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000ad8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000ae0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000ae8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000af0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000af8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000b00] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000b08] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000b10] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000b18] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000b20] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000b28] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000b30] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008e8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000008f0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000008f8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000900] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000908] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000910] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000918] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000920] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000928] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000930] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000938] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000940] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000948] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000950] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000958] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000960] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000968] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000970] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000978] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000980] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000988] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000990] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000998] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000009a0] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 +++/* [0x000009a8] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009b0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000009b8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000009c0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000009c8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000009d0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000009d8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000009e0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000009e8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009f0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009f8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000a00] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000a08] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000a10] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000a18] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000a20] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a28] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a30] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a38] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a40] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000a48] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a50] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a60] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000b38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000b40] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000b48] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b50] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b58] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b60] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b68] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b70] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000b78] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a78] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a80] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a98] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000aa0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ab0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000b80] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000b88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b90] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000b98] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ba0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ba8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bb0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bb8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bc0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bc8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bd0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000bd8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000be0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000be8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000bf0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000ac0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ae0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b08] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b10] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b18] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b20] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b28] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000b30] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index cb74887..53da629 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -7,8 +7,8 @@ extern unsigned int rpi_shader[]; ++ #define mc_filter_uv (rpi_shader + 152) ++ #define mc_filter_uv_b0 (rpi_shader + 324) ++ #define mc_filter_uv_b (rpi_shader + 490) ++-#define mc_exit (rpi_shader + 718) ++-#define mc_interrupt_exit8 (rpi_shader + 736) ++-#define mc_end (rpi_shader + 766) +++#define mc_exit (rpi_shader + 670) +++#define mc_interrupt_exit8 (rpi_shader + 688) +++#define mc_end (rpi_shader + 718) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index faa5755..f38c926 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -491,8 +491,8 @@ mov r0, unif ++ shr r1, r0, r2 # Extract width ++ sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++ and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 +++add rb17, r0, 1 +++add rb18, r0, 3 ++ shl r0, r0, 7 ++ ++ # r0 is currently height<<7 ++@@ -508,8 +508,6 @@ add rb26, r0, rb27 ++ # In a B frame, so also set up VPM read (reading back 16bit precision) ++ add vr_setup, r3, rb21 ++ ++-sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++- ++ # get filter coefficients ++ ++ mov r0, unif ++@@ -517,18 +515,11 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif +++ mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23; mov r0, unif ++-asr rb15, r0, rb23; mul24 r0, r0, ra22 ++-asr rb14, r0, rb23; mul24 r0, r0, ra22 ++-asr rb13, r0, rb23; mul24 r0, r0, ra22 ++-asr rb12, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++@@ -570,26 +561,14 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++ add r0, r2, r3 ++ ++ mov r3, rb31 ++ ++-mov ra8, ra9 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++ mov ra12, ra13 ++ mov ra13, ra14 ++ ++-sub.setf -, r3, 8 ; mov r1, ra22 +++sub.setf -, r3, 4 ; mov r1, ra22 ++ # apply horizontal filter ++ brr.anyn -, r:uvloop_b ++ mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++@@ -598,14 +577,10 @@ nop ; nop # TODO improve use of delay slots ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r1, ra14, rb14 ++-nop ; mul24 r0, ra13, rb13 ++-add r1, r1, r0 ; mul24 r0, ra12, rb12 ++-add r1, r1, r0 ; mul24 r0, ra11, rb11 ++-add r1, r1, r0 ; mul24 r0, ra10, rb10 ++-add r1, r1, r0 ; mul24 r0, ra9, rb9 ++-add r1, r1, r0 ; mul24 r0, ra8, rb8 ++-add r1, r1, r0 ; mul24 r0, ra15, rb15 +++nop ; mul24 r1, ra14, rb10 +++nop ; mul24 r0, ra13, rb9 +++add r1, r1, r0 ; mul24 r0, ra12, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb11 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ asr r1, r1, 14 # shift2=6 ++-- ++2.5.0 ++ ++ ++From 75ce019e80ff7f2234d56949c191413ab1d9ad7e Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:17:09 +0100 ++Subject: [PATCH 30/68] Used P delay slots more efficiently ++ ++--- ++ libavcodec/rpi_shader.c | 437 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 10 +- ++ libavcodec/rpi_shader.qasm | 19 +- ++ 3 files changed, 228 insertions(+), 238 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 4e6c5ea..a1af4e3 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -156,239 +156,236 @@ unsigned int rpi_shader[] = { ++ /* [0x00000408] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ /* [0x00000410] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ /* [0x00000418] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000420] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000428] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000430] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000420] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000428] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000430] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++ /* [0x00000438] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000440] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 ++-/* [0x00000448] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000450] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000458] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000460] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000468] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000470] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000478] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000480] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000488] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000490] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000498] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000004a0] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x000004a8] */ 0xfffffec0, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004b0] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x000004b8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000004c0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000004c8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000004d0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004d8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000004e0] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000004e8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000004f0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000004f8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000500] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000508] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000440] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000448] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000450] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000458] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000460] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000468] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000470] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000478] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000480] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000488] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000490] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000498] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x000004a0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000004a8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000004b0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000004b8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004c0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000004c8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000004d0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000004d8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000004e0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000004e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x00000510] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000518] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000520] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000528] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000530] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000538] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000540] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000548] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000550] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000558] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000560] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000568] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000570] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000578] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000580] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000588] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000590] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000598] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000005a0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000005a8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000005b0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000005b8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000005c0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000005c8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005d0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005d8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000005f0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005f8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000600] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000608] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000610] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000618] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000620] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000628] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000004f8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000500] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000508] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000510] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000518] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000520] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000528] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000530] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000538] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000540] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000548] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000550] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000558] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000560] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000568] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000570] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000578] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000580] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000588] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000590] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000598] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000005a0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000005a8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000005b0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005b8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005d0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005d8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000600] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000608] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000610] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000630] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000638] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000640] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000648] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000650] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000658] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000660] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000668] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000670] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000678] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000680] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000688] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000690] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000698] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000006a0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000006a8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000006b0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000006b8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000006c0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000006c8] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x000006d0] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x000006d8] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000006e0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000006e8] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 ++-/* [0x000006f0] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000006f8] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x00000700] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x00000708] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000710] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000718] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000720] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000728] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000730] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000738] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000740] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000748] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 ++-/* [0x00000750] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000758] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000760] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000768] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000770] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000778] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000780] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000788] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000790] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000798] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000007a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000618] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000620] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000628] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000630] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000638] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000640] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000648] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000650] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000658] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000660] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000668] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000670] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000678] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000680] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000688] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000690] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000698] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000006a0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000006a8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000006b0] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x000006b8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x000006c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x000006c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000006d0] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 +++/* [0x000006d8] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006e0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000006e8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000006f0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000006f8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000700] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000708] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000710] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000718] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000720] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000728] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000730] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 +++/* [0x00000738] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000740] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000748] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000750] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000758] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000760] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000768] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000770] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000778] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000780] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000788] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x000007a8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000007b0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000007b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000007c0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000007c8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000007d0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007d8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007e0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007e8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000007f0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000007f8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000800] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000808] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000810] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000818] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000820] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000828] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000830] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000838] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000840] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000848] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000850] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000858] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000860] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000868] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000870] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000878] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000880] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000888] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000890] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000898] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000008a8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008b0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000008d0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008e0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000790] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000798] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000007a0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000007a8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000007b0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000007b8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007c0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007c8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007d0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000007d8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000007e0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000007e8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000007f0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000007f8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000800] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000808] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000810] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000818] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000820] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000828] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000830] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000838] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000840] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000848] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000850] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000858] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000860] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000868] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000870] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000878] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000880] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000888] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000890] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000898] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000008b8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008c8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000008e8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000008f0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000008f8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000900] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000908] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000910] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000918] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000920] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000928] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000930] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000938] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000940] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000948] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000950] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000958] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000960] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000968] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000970] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000978] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000980] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000988] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000990] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000998] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000009a0] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 ++-/* [0x000009a8] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009b0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000009b8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000009c0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000009c8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000009d0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000009d8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000009e0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000009e8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009f0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009f8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000a00] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000a08] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000a10] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000a18] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000a20] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a28] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a30] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a38] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a40] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000a48] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a50] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a60] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008d0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000008d8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000008e0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000008e8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000008f0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000008f8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000900] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000908] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000910] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000918] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000920] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000928] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000930] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000938] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000940] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000948] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000950] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000958] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000960] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000968] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 +++/* [0x00000970] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 +++/* [0x00000978] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00000980] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000988] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 +++/* [0x00000990] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000998] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 +++/* [0x000009a0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop +++/* [0x000009a8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000009b0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000009b8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000009c0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000009c8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000009d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000009e8] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x000009f0] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x000009f8] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000a00] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000a08] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a10] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a18] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a20] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a28] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000a30] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a40] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a48] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a50] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a58] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a78] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a80] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a60] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a68] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a70] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a98] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000aa0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ab0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a90] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a98] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000aa0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000ac0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000aa8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ab0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ab8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ac0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ad0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ad8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ae0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ad8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ae0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b08] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b10] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b18] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b20] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b28] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000b30] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b08] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b10] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000b18] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 53da629..1fb3e37 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -5,10 +5,10 @@ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 152) ++-#define mc_filter_uv_b0 (rpi_shader + 324) ++-#define mc_filter_uv_b (rpi_shader + 490) ++-#define mc_exit (rpi_shader + 670) ++-#define mc_interrupt_exit8 (rpi_shader + 688) ++-#define mc_end (rpi_shader + 718) +++#define mc_filter_uv_b0 (rpi_shader + 318) +++#define mc_filter_uv_b (rpi_shader + 484) +++#define mc_exit (rpi_shader + 664) +++#define mc_interrupt_exit8 (rpi_shader + 682) +++#define mc_end (rpi_shader + 712) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index f38c926..02e95dd 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -268,6 +268,7 @@ add t0s, ra_x2_base, r2 ++ ++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ +++# apply horizontal filter ++ nop ; mul24 r2, r0, ra0 ++ nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++ nop ; mul24 r3, ra1 << 1, r0 << 1 ++@@ -276,20 +277,12 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r0, r2, r3 ++- ++-mov r3, rb31 ++- ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 4 ; mov r1, ra22 ++- ++-# apply horizontal filter +++add r0, r2, r3 ; mov r3, rb31 +++sub.setf -, r3, 4 ; mov ra12, ra13 ++ brr.anyn -, r:uvloop ++-mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll ++-asr ra15, r0, 8 ; nop ++-nop ; nop # Delay slot 3 (TODO move more of the context scroll into here) +++mov ra13, ra14 # Delay slot 1 +++mov ra14, ra15 # Delay slot 2 +++mov ra15, r0 # Delay slot 3 ++ ++ # apply vertical filter and write to VPM ++ ++-- ++2.5.0 ++ ++ ++From a92dda80bf8043b39fa85752d9a9592e90370d77 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:22:25 +0100 ++Subject: [PATCH 31/68] Improved use of delay slots ++ ++--- ++ libavcodec/rpi_shader.c | 503 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 10 +- ++ libavcodec/rpi_shader.qasm | 41 ++-- ++ 3 files changed, 265 insertions(+), 289 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index a1af4e3..c498f28 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -122,270 +122,263 @@ unsigned int rpi_shader[] = { ++ /* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++ /* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++ /* [0x00000310] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000318] */ 0x0d9c8e40, 0xd00229e7, // sub.setf -,8,r1 ++-/* [0x00000320] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000328] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000340] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000348] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000350] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000360] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000368] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000370] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000378] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000380] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000340] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000348] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000350] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000360] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000368] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000370] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000378] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x00000388] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000390] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000398] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003a0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003a8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003b0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003c0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003c8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003d0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000003d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003e0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000003e8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000003f0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000003f8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000400] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000408] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000410] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000418] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000420] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000428] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000430] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000438] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000440] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000448] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000450] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000458] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000460] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000468] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000470] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000478] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000480] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000488] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000490] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000498] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x000004a0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000004a8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000004b0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000004b8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004c0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000004c8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000004d0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000004d8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000004e0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000004e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000380] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000388] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000390] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000398] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003a0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003a8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003b8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003c0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000003c8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000003d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003d8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003e0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000003e8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000003f0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000003f8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000400] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000408] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000410] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000418] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000420] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000428] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000430] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000438] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000440] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000448] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000450] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000458] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000460] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000468] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000470] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000478] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000480] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000488] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000490] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000498] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000004a0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000004a8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000004b0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004b8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000004c0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000004c8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000004d0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000004d8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000004e0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004e8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x000004f8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000500] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000508] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000510] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000518] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000520] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000528] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000530] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000538] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000540] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000548] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000550] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000558] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000560] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000568] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000570] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000578] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000580] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000588] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000590] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000598] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000005a0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000005a8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000005b0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005b8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005d0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000005d8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000600] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000608] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000610] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000004f0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000004f8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000500] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000508] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000510] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000518] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000520] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000528] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000530] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000538] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000540] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000548] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000550] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000558] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000560] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000568] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000570] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000578] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000580] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000588] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000590] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000598] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000005a0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000005a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005b0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005b8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005d0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005d8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005e8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005f0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000005f8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000600] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000608] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000618] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000620] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000628] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000630] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000638] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000640] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000648] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000650] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000658] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000660] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000668] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000670] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000678] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000680] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000688] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000690] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000698] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000006a0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000006a8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000006b0] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x000006b8] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x000006c0] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x000006c8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000006d0] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 ++-/* [0x000006d8] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000006e0] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000006e8] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000006f0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000006f8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000700] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000708] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000710] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000718] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000720] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000728] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000730] */ 0x0f9ce3c0, 0xd0020c27, // asr vpm, r1, 14 ++-/* [0x00000738] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000740] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000748] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000750] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000758] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000760] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000768] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000770] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000778] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000780] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000788] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000610] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000618] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000620] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000628] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000630] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000638] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000640] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000648] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000650] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000658] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000668] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000670] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000678] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000680] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000688] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000690] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000698] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000006a0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000006a8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x000006b0] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x000006b8] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006c0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000006c8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000006d0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000006d8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000006e0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000006e8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000006f0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000006f8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000700] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x00000708] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000710] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x00000718] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000720] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000728] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000730] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000738] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000740] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000748] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000750] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000758] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000760] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000768] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b ++-/* [0x00000790] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000798] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000007a0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000007a8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000007b0] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000007b8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007c0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007c8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007d0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000007d8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000007e0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000007e8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000007f0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000007f8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000800] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000808] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000810] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000818] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000820] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000828] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000830] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000838] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000840] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000848] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000850] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000858] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000860] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000868] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000870] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000878] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000880] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000888] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000890] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000898] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000008b8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008c8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000770] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000778] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000780] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000788] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000790] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000798] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007a0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007a8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007b0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000007b8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000007c0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000007c8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000007d0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000007d8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007e0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000007e8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000007f0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000007f8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000800] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000808] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000810] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000818] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000820] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000828] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000830] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000838] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000840] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000848] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000850] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000858] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000860] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000868] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000870] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000878] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000880] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000888] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000890] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000898] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008a0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008a8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000008d0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000008d8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000008e0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000008e8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000008f0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000008f8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000900] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000908] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000910] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000918] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000920] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000928] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000930] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000938] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000940] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000948] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000950] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000958] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000960] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000968] */ 0x0c9e74c0, 0x10020827, // add r0, r2, r3 ++-/* [0x00000970] */ 0x159dffc0, 0x100208e7, // mov r3, rb31 ++-/* [0x00000978] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00000980] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000988] */ 0x8d5847f6, 0xd00269e1, // sub.setf -, r3, 4 ; mov r1, ra22 ++-/* [0x00000990] */ 0xffffff20, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000998] */ 0x553e7d81, 0x100243a0, // mov ra14, ra15 ; mul24 r0, r0, r1 ++-/* [0x000009a0] */ 0x0f9c81c0, 0xd00203e7, // asr ra15, r0, 8 ; nop ++-/* [0x000009a8] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x000009b0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000009b8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000009c0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000009c8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000009d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000009e8] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x000009f0] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x000009f8] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000a00] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000a08] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a10] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a18] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a20] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a28] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000a30] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a38] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a40] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a48] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a50] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a58] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008b0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000008b8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000008c0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000008c8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000008d0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000008d8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000008e0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000008e8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000008f0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000008f8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000900] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000908] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000910] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000918] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000920] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000928] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000930] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000938] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000940] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000948] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000950] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000958] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000960] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000968] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000970] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000978] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000980] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000988] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000990] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000998] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009a0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009a8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000009b0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x000009b8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x000009c0] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009c8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x000009d0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000009d8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000009e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000009e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000009f8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a00] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a08] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a10] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a18] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a20] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a60] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a68] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000a70] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a28] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a30] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a38] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a40] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a48] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a50] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a58] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a60] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a68] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_interrupt_exit8 +++/* [0x00000a70] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++ /* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a90] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a98] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000aa0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-// ::mc_interrupt_exit8 ++-/* [0x00000aa8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000ab0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ab8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ac0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ad0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ad8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ae0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b08] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b10] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000b18] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000aa0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000aa8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ab0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ab8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ac0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ac8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ad0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ad8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000ae0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 1fb3e37..3fac45f 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -5,10 +5,10 @@ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 152) ++-#define mc_filter_uv_b0 (rpi_shader + 318) ++-#define mc_filter_uv_b (rpi_shader + 484) ++-#define mc_exit (rpi_shader + 664) ++-#define mc_interrupt_exit8 (rpi_shader + 682) ++-#define mc_end (rpi_shader + 712) +++#define mc_filter_uv_b0 (rpi_shader + 316) +++#define mc_filter_uv_b (rpi_shader + 476) +++#define mc_exit (rpi_shader + 650) +++#define mc_interrupt_exit8 (rpi_shader + 668) +++#define mc_end (rpi_shader + 698) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 02e95dd..10f5113 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -221,8 +221,6 @@ add r0, r0, r1 # Combine width and height of destination area ++ shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++ add rb26, r0, rb27 ++ ++-sub.setf -,8,r1 # 8-r1, so if <0 (negative) we need to use the full code ++- ++ # get filter coefficients ++ ++ mov r0, unif ++@@ -410,20 +408,12 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r0, r2, r3 ++- ++-mov r3, rb31 ++- ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 4 ; mov r1, ra22 ++- ++-# apply horizontal filter +++add r0, r2, r3 ; mov r3, rb31 +++sub.setf -, r3, 4 ; mov ra12, ra13 ++ brr.anyn -, r:uvloop_b0 ++-mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll ++-asr ra15, r0, 8 ; nop # TODO isn't ra15 already in 24bit precision, may not need the sign extension here? ++-nop ; nop # Delay slot 3 (TODO move more of the context scroll into here) +++mov ra13, ra14 # Delay slot 1 +++mov ra14, ra15 # Delay slot 2 +++mov ra15, r0 # Delay slot 3 ++ ++ # apply vertical filter and write to VPM ++ ++@@ -432,9 +422,9 @@ nop ; mul24 r0, ra13, rb9 ++ add r1, r1, r0 ; mul24 r0, ra12, rb8 ++ add r1, r1, r0 ; mul24 r0, ra15, rb11 ++ add r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++sub.setf -, r3, rb18 ++ brr.anyn -, r:uvloop_b0 ++-asr vpm, r1, 14 # Delay 1 shifts down by shift2=6, but results are still in 16bit precision TODO may be able to avoid the mul24 and use more delay slots +++asr vpm, r1, 6 # Delay 1 shifts down by shift2=6, but results are still in 16bit precision ++ nop # Delay 2 ++ nop # Delay 3 ++ ++@@ -554,19 +544,12 @@ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r0, r2, r3 ++- ++-mov r3, rb31 ++- ++-mov ra12, ra13 ++-mov ra13, ra14 ++- ++-sub.setf -, r3, 4 ; mov r1, ra22 ++-# apply horizontal filter +++add r0, r2, r3 ; mov r3, rb31 +++sub.setf -, r3, 4 ; mov ra12, ra13 ++ brr.anyn -, r:uvloop_b ++-mov ra14, ra15 ; mul24 r0, r0, r1 # last bit of context scroll, including clamp to zero ++-asr ra15, r0, 8 ; nop ++-nop ; nop # TODO improve use of delay slots +++mov ra13, ra14 # Delay slot 1 +++mov ra14, ra15 # Delay slot 2 +++mov ra15, r0 # Delay slot 3 ++ ++ # apply vertical filter and write to VPM ++ ++-- ++2.5.0 ++ ++ ++From 70bf426922557224722d0b6c3ca5d688b4e91f00 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:31:23 +0100 ++Subject: [PATCH 32/68] Avoid writeback of first B results ++ ++--- ++ libavcodec/rpi_shader.c | 229 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 8 +- ++ libavcodec/rpi_shader.qasm | 18 +--- ++ 3 files changed, 121 insertions(+), 134 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index c498f28..ba453a2 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -255,130 +255,125 @@ unsigned int rpi_shader[] = { ++ /* [0x00000710] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++ /* [0x00000718] */ 0x009e7000, 0x100009e7, // nop ++ /* [0x00000720] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000728] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000730] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000738] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000740] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000748] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000750] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000758] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000760] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000768] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000728] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000730] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000738] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000740] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x00000770] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000778] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000780] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000788] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000790] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000798] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007a0] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007a8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007b0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000007b8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000007c0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000007c8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000007d0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000007d8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000007e0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000007e8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000007f0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000007f8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000800] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000808] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000810] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000818] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000820] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000828] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000830] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000838] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000840] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000748] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000750] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000758] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000760] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000768] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000770] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000778] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000780] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000788] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000790] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000798] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000007a0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000007a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000007b0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000007c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000007c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000007d0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000007d8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000007e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000007e8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x000007f0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x000007f8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000800] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000808] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000810] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000818] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000820] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000828] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000830] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000838] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000840] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++ /* [0x00000848] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000850] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000858] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000860] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000868] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000870] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000878] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000880] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000888] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000890] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000898] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008a0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008a8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000850] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000858] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000860] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000868] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000870] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000878] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000880] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000008b0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000008b8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000008c0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000008c8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000008d0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000008d8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000008e0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000008e8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000008f0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000008f8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000900] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000908] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000910] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000918] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000920] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000928] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000930] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000938] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000940] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000948] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000950] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000958] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000960] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000968] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000970] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000978] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000980] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000988] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000990] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000998] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009a0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009a8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000009b0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x000009b8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x000009c0] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009c8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x000009d0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000009d8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000009e0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000009e8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000009f0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000009f8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a00] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a08] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a10] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a18] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a20] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000888] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000890] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000898] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000008a0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000008a8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000008b0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000008b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000008c0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000008c8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000008d0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000008d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008e0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000008e8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000008f0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000008f8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000900] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000908] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000910] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000918] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000920] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000928] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000930] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000938] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000940] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000948] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000950] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000958] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000960] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000968] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000970] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000978] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000980] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000988] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000990] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000998] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009a0] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x000009a8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000009b0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000009b8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000009c0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009c8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000009d0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000009d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000009e0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000009e8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000009f0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009f8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a28] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a30] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000a38] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a40] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a48] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a50] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a58] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a60] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000a68] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a00] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a08] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a10] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a18] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a20] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a28] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a30] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a38] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a40] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000a70] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a48] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a50] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a58] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a60] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a68] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a80] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a88] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a90] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000a98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000aa0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000aa8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ab0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ab8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ac0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ac8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ad0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ad8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000ae0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ab0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 3fac45f..45dbe0e 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -6,9 +6,9 @@ extern unsigned int rpi_shader[]; ++ #define mc_setup_uv (rpi_shader + 0) ++ #define mc_filter_uv (rpi_shader + 152) ++ #define mc_filter_uv_b0 (rpi_shader + 316) ++-#define mc_filter_uv_b (rpi_shader + 476) ++-#define mc_exit (rpi_shader + 650) ++-#define mc_interrupt_exit8 (rpi_shader + 668) ++-#define mc_end (rpi_shader + 698) +++#define mc_filter_uv_b (rpi_shader + 466) +++#define mc_exit (rpi_shader + 640) +++#define mc_interrupt_exit8 (rpi_shader + 658) +++#define mc_end (rpi_shader + 688) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 10f5113..e138c95 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -428,22 +428,14 @@ asr vpm, r1, 6 # Delay 1 shifts down by shift2=6, but results are still ++ nop # Delay 2 ++ nop # Delay 3 ++ +++# in pass0 we don't really need to save any results, but need to discard the uniforms ++ # DMA out for U ++ ++-mov vw_setup, rb26 # VDW setup 0 ++-mov vw_setup, rb29 # Stride ++-mov vw_addr, unif # start the VDW # TODO in pass0 we don't need to save any results ++- ++-# DMA out for V ++-# We need to wait for the U to complete first, but have nothing useful to compute while we wait. ++-# Could potentially push this write into the start of the next pipeline stage. ++-mov r0, 16 ++-mov -, vw_wait ++- ++ bra -, ra31 ++-add vw_setup, rb26, r0 # VDW setup 0 ++-mov vw_setup, rb29 # Stride ++-mov vw_addr, unif # start the VDW +++mov r0, unif # Delay 1 +++mov r0, unif # Delay 2 +++nop # Delay 3 +++ ++ ++ ################################################################################ ++ ++-- ++2.5.0 ++ ++ ++From fb7061693c79444c178f700799776ffd736f3561 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 14 May 2015 11:36:24 +0100 ++Subject: [PATCH 33/68] Cutdown size of chroma prediction commands ++ ++--- ++ libavcodec/hevc.c | 17 +- ++ libavcodec/rpi_shader.c | 543 ++++++++++++++++++++++----------------------- ++ libavcodec/rpi_shader.h | 12 +- ++ libavcodec/rpi_shader.qasm | 11 +- ++ 4 files changed, 281 insertions(+), 302 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 8984585..c65af74 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -56,7 +56,7 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ ++ #ifdef RPI_INTER_QPU ++ ++-#define RPI_CHROMA_COMMAND_WORDS 12 +++#define RPI_CHROMA_COMMAND_WORDS 10 ++ #define UV_COMMANDS_PER_QPU ((1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS) ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++@@ -2021,11 +2021,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++- u++; ++ *u++ = rpi_filter_coefs[_my][0]; ++- u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2080,9 +2077,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++- u++; ++ *u++ = rpi_filter_coefs[_my][0]; ++- u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2143,11 +2138,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++ *u++ = ( (nPbW_cframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); // TODO this will become unused once we have a dedicated pass0 filter ++- *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ u+=2; // Intermediate results are not written back in first pass of B filtering ++ ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x2_c - 1 + start_x; ++@@ -2155,11 +2147,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); ++ *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx2][0]; ++- u++; ++ *u++ = rpi_filter_coefs[_my2][0]; ++- u++; ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2797,7 +2786,7 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = pic_height; ++ *s->u_mvs[i]++ = s->frame->linesize[1]; ++ *s->u_mvs[i]++ = s->frame->linesize[2]; ++- s->u_mvs[i] += 3; // Padding words +++ s->u_mvs[i] += 1; // Padding words ++ } ++ } ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index ba453a2..b0b93b5 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -89,291 +89,286 @@ unsigned int rpi_shader[] = { ++ /* [0x00000200] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++ /* [0x00000208] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++ /* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000218] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000220] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000228] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000230] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000238] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000240] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000248] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000250] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000258] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000218] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000220] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000228] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000230] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000238] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000240] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000248] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv ++-/* [0x00000260] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000268] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000270] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000278] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000280] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000288] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000290] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000298] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000002a0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000002a8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000002b0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000002b8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002c0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002c8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002d0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002d8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002e0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002e8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000002f0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000002f8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000310] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000340] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000348] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000350] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000360] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000368] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000370] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000378] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000250] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000258] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000260] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000268] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000270] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000278] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000280] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000288] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000290] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000298] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000002a0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000002a8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002b0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002b8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002c0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002c8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002d0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002d8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000002e0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000002e8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002f0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002f8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000300] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000330] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000340] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000350] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000358] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000360] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x00000380] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000388] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000390] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000398] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003a0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003a8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003b8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003c0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003c8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000003d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003d8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000003e0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000003e8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000003f0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000003f8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000400] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000408] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000410] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000418] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000420] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000428] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000430] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000438] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000440] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000448] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000450] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000458] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000460] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000468] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000470] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000478] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000480] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000488] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000490] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000498] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000004a0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000004a8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000004b0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004b8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000004c0] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000004c8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000004d0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000004d8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000004e0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004e8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000368] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000370] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000378] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000380] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000388] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000390] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000398] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003a0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003a8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000003b0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000003b8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003c0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003c8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000003d0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000003d8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000003e0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000003e8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000003f0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000003f8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000400] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000408] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000410] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000418] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000420] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000428] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000430] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000438] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000440] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000448] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000450] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000458] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000460] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000468] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 +++/* [0x00000470] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000478] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00000480] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000488] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000490] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000498] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000004a8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000004b0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000004b8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000004c0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000004c8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004d0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x000004f0] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000004f8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000500] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000508] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000510] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000518] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000520] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000528] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000530] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000538] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000540] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000548] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000550] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000558] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000560] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000568] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000570] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000578] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000580] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000588] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000590] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000598] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000005a0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000005a8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005b0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005b8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000005d0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005d8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005e8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005f0] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000005f8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000600] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000608] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000004d8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000004e0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000004e8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000004f0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000004f8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000500] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000508] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000510] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000518] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000520] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000528] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000530] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000538] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000540] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000548] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000550] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000558] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000560] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000568] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000570] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000578] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000580] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000588] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000590] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000598] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005a0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005a8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005b0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005b8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005d0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x000005d8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000005e0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000005e8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000610] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000618] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000620] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000628] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000630] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000638] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000640] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000648] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000650] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000658] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000668] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000670] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000678] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000680] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000688] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000690] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000698] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000006a0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000006a8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x000006b0] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x000006b8] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000006c0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000006c8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x000006d0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000006d8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000006e0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000006e8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000006f0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000006f8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000700] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 ++-/* [0x00000708] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000710] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++-/* [0x00000718] */ 0x009e7000, 0x100009e7, // nop +++/* [0x000005f0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000005f8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000600] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000608] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000610] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000618] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000620] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000628] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000630] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000638] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000640] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000648] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000650] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000658] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000660] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000668] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000670] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000678] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000680] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000688] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000690] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000698] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006a0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000006a8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000006b0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000006b8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000006c0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000006c8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000006d0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000006d8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000006e0] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x000006e8] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006f0] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x000006f8] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000700] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000708] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000710] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000718] */ 0x15827d80, 0x10020827, // mov r0, unif ++ /* [0x00000720] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000728] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000730] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000738] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000740] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x00000748] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000750] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000758] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000760] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000768] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000770] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000778] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000780] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000788] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000790] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000798] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000007a0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000007a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000007b0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000007b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000007c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000007c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000007d0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000007d8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000007e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000007e8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x000007f0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x000007f8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000800] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000808] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000810] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000818] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000820] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000828] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000830] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000838] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000840] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000848] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000850] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000858] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000860] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000868] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000870] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000878] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000880] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000728] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000730] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000738] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000740] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000748] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000750] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000758] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000760] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000768] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000770] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000778] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000780] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000788] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000790] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000798] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000007a0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000007a8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000007b0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000007b8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000007c0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000007c8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x000007d0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x000007d8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x000007e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000007e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000007f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000007f8] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000800] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000808] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000810] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000818] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000820] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000828] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000830] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000838] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000840] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000848] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000850] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000858] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000888] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000890] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000898] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000008a0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000008a8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000008b0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000008b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000008c0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000008c8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000008d0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000008d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008e0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000008e8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000008f0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000008f8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000900] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000908] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000910] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000918] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000920] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000928] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000930] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000938] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000940] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000948] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000950] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000958] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000960] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000968] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000970] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000978] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000980] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000988] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000990] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000998] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009a0] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x000009a8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000009b0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000009b8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000009c0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000009c8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000009d0] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000009d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000009e0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000009e8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000009f0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000009f8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000860] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000868] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000870] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000878] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000880] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000888] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000890] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000898] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000008a0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000008a8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000008b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008b8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000008c0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000008c8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000008d0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000008d8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000008e0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000008e8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000008f0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000008f8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000900] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000908] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000910] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000918] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000920] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000928] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000930] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000938] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000940] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000948] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000950] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000958] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000960] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000968] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000970] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000978] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000980] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000988] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000990] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000998] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000009a8] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000009b0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000009b8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000009c0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000009c8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009d0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a00] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a08] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000a10] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a18] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a20] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a28] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a30] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a38] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000a40] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000009d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000009e0] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x000009e8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000009f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x000009f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a00] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a08] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a10] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a18] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000a48] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a50] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a58] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a60] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a68] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a20] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a28] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a30] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a38] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a40] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a48] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a50] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a58] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a60] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000a70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000a78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a80] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a88] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a90] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000aa0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ab0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a80] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a88] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000a90] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 45dbe0e..99927c4 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,11 +4,11 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 152) ++-#define mc_filter_uv_b0 (rpi_shader + 316) ++-#define mc_filter_uv_b (rpi_shader + 466) ++-#define mc_exit (rpi_shader + 640) ++-#define mc_interrupt_exit8 (rpi_shader + 658) ++-#define mc_end (rpi_shader + 688) +++#define mc_filter_uv (rpi_shader + 148) +++#define mc_filter_uv_b0 (rpi_shader + 310) +++#define mc_filter_uv_b (rpi_shader + 458) +++#define mc_exit (rpi_shader + 630) +++#define mc_interrupt_exit8 (rpi_shader + 648) +++#define mc_end (rpi_shader + 678) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index e138c95..d9ffcda 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -167,8 +167,6 @@ add t0s, r2, r1 ++ ++ # Dump padding words ++ mov r0, unif ++-mov r0, unif ++-mov r0, unif ++ ++ # submit texture requests for second line ++ max r1, ra_y, 0 ++@@ -228,11 +226,10 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++- mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif +++asr rb8, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++@@ -362,11 +359,10 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++- mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif +++asr rb8, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++@@ -490,11 +486,10 @@ asr ra3, r0, rb23; mul24 r0, r0, ra22 ++ asr ra2, r0, rb23; mul24 r0, r0, ra22 ++ asr ra1, r0, rb23; mul24 r0, r0, ra22 ++ asr ra0, r0, rb23; mov r0, unif ++- mov r0, unif ++ asr rb11, r0, rb23; mul24 r0, r0, ra22 ++ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif +++asr rb8, r0, rb23 ++ ++ # r2 is elem_num ++ # r3 is loop counter ++-- ++2.5.0 ++ ++ ++From 87ea97549920ec537d6bb03b6848be12b7b4e252 Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 14 May 2015 15:21:49 +0100 ++Subject: [PATCH 34/68] hevc: don't redirect when not rpi_enabled ++ ++--- ++ libavcodec/hevc.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index c65af74..e2f8a87 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -1457,7 +1457,7 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) ++ */ ++ ++ #ifdef RPI_INTER ++-#define RPI_REDIRECT(fn) rpi_ ## fn +++#define RPI_REDIRECT(fn) (s->enable_rpi ? rpi_ ## fn : fn) ++ static void rpi_luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref, const Mv *mv, int x_off, int y_off, ++ int block_w, int block_h, int luma_weight, int luma_offset) ++-- ++2.5.0 ++ ++ ++From d922347fd57c0320b6c6983a6c0b7c3200dae393 Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 14 May 2015 15:22:02 +0100 ++Subject: [PATCH 35/68] Use /dev/vcio for mailbox access ++ ++--- ++ libavcodec/rpi_mailbox.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/libavcodec/rpi_mailbox.c b/libavcodec/rpi_mailbox.c ++index 536896f..77a56dd 100644 ++--- a/libavcodec/rpi_mailbox.c +++++ b/libavcodec/rpi_mailbox.c ++@@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++ #define MAJOR_NUM 100 ++ #define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) ++-#define DEVICE_FILE_NAME "/dev/char_dev" +++#define DEVICE_FILE_NAME "/dev/vcio" ++ ++ #include "rpi_mailbox.h" ++ ++-- ++2.5.0 ++ ++ ++From 70688cd4e7a3bb073fe32a1dbdded4c4dfee3a42 Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 14 May 2015 15:25:25 +0100 ++Subject: [PATCH 36/68] Use vcsm for all memory allocations ++ ++--- ++ libavcodec/rpi_qpu.c | 174 +++++++++++++++++++-------------------------------- ++ 1 file changed, 64 insertions(+), 110 deletions(-) ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 60bf079..f62051f 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -1,7 +1,5 @@ ++ #ifdef RPI ++-// define RPI_USE_VCSM to use the vcsm device for shared memory ++ // This works better than the mmap in that the memory can be cached, but requires a kernel modification to enable the device. ++-#define RPI_USE_VCSM ++ // define RPI_TIME_TOTAL_QPU to print out how much time is spent in the QPU code ++ #define RPI_TIME_TOTAL_QPU ++ // define RPI_TIME_TOTAL_VPU to print out how much time is spent in the VPI code ++@@ -25,9 +23,7 @@ ++ #include "rpi_shader.h" ++ #include "rpi_hevc_transform.h" ++ ++-#ifdef RPI_USE_VCSM ++ #include "rpi_user_vcsm.h" ++-#endif ++ ++ // On Pi2 there is no way to access the VPU L2 cache ++ // GPU_MEM_FLG should be 4 for uncached memory. (Or C for alias to allocate in the VPU L2 cache) ++@@ -96,7 +92,6 @@ struct GPU ++ unsigned int vpu_code[VPU_CODE_SIZE]; ++ short transMatrix2even[16*16*2]; ++ int open_count; // Number of allocated video buffers ++- unsigned int vc_handle; // Handle of this memory ++ int mb; // Mailbox handle ++ int vc; // Address in GPU memory ++ int mail[12]; // These are used to pass pairs of code/unifs to the QPUs ++@@ -105,6 +100,7 @@ struct GPU ++ // Stop more than one thread trying to allocate memory or use the processing resources at once ++ static pthread_mutex_t gpu_mutex = PTHREAD_MUTEX_INITIALIZER; ++ static volatile struct GPU* gpu = NULL; +++static GPU_MEM_PTR_T gpu_mem_ptr; ++ ++ #if defined(RPI_TIME_TOTAL_QPU) || defined(RPI_TIME_TOTAL_VPU) ++ static unsigned int Microseconds(void) { ++@@ -132,39 +128,27 @@ static volatile int vpu_async_tail=0; // Contains the number of posted jobs ++ static volatile int vpu_async_head=0; ++ #endif ++ +++static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb); +++static void gpu_free_internal(GPU_MEM_PTR_T *p); +++ ++ // Connect to QPU, returns 0 on success. ++ static int gpu_init(volatile struct GPU **gpu) { ++ int mb = mbox_open(); ++ int vc; ++- int handle; ++ volatile struct GPU* ptr; ++ if (mb < 0) ++ return -1; ++ ++ if (qpu_enable(mb, 1)) return -2; ++ ++-#ifdef RPI_USE_VCSM ++ vcsm_init(); ++-#endif +++ gpu_malloc_uncached_internal(sizeof(struct GPU), &gpu_mem_ptr, mb); +++ ptr = (volatile struct GPU*)gpu_mem_ptr.arm; +++ memset(ptr, 0, sizeof *ptr); +++ vc = gpu_mem_ptr.vc; ++ ++- handle = mem_alloc(mb, sizeof(struct GPU), 4096, GPU_MEM_FLG); ++- if (!handle) ++- { ++- qpu_enable(mb, 0); ++- return -3; ++- } ++- vc = mem_lock(mb, handle); ++- ptr = mapmem_shared((vc+GPU_MEM_MAP)&~0xc0000000, sizeof(struct GPU)); ++- if (ptr == NULL) ++- { mem_free(mb, handle); ++- mem_unlock(mb, handle); ++- qpu_enable(mb, 0); ++- return -4; ++- } ++- ++- ptr->mb = mb; ++- ptr->vc_handle = handle; ++- ptr->vc = vc; +++ ptr->mb = mb; +++ ptr->vc = vc; ++ ++ printf("GPU allocated at 0x%x\n",vc); ++ ++@@ -226,94 +210,74 @@ static void gpu_unlock(void) { ++ pthread_mutex_unlock(&gpu_mutex); ++ } ++ +++static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb) { +++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); +++ assert(p->vcsm_handle); +++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); +++ assert(p->vc_handle); +++ p->arm = vcsm_lock(p->vcsm_handle); +++ assert(p->arm); +++ p->vc = mem_lock(mb, p->vc_handle); +++ assert(p->vc); +++ return 0; +++} +++ ++ // Allocate memory on GPU ++ // Fills in structure

containing ARM pointer, videocore handle, videocore memory address, numbytes ++ // Returns 0 on success. ++ // This allocates memory that will not be cached in ARM's data cache. ++ // Therefore safe to use without data cache flushing. ++-int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) { +++int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) +++{ +++ int r; ++ gpu_lock(); ++- p->vc_handle = mem_alloc(gpu->mb, numbytes, 4096, GPU_MEM_FLG); ++- p->vcsm_handle = 0; ++- if (!p->vc_handle) ++- { ++- qpu_enable(gpu->mb, 0); ++- return -3; ++- } ++- p->vc = mem_lock(gpu->mb, p->vc_handle); ++- p->arm = mapmem_shared((p->vc+GPU_MEM_MAP)&~0xc0000000,numbytes); ++- p->numbytes = numbytes; ++- if (p->arm == NULL) ++- { ++- mem_free(gpu->mb, p->vc_handle); ++- mem_unlock(gpu->mb, p->vc_handle); ++- gpu_unlock(); ++- qpu_enable(gpu->mb, 0); ++- return -4; ++- } +++ r = gpu_malloc_uncached_internal(numbytes, p, gpu->mb); ++ gpu->open_count++; ++ gpu_unlock(); ++- return 0; +++ return r; ++ } ++ ++ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ { ++- // This only works when using RPI_USE_VCSM ++ void *tmp = vcsm_lock(p->vcsm_handle); ++ vcsm_unlock_ptr(tmp); ++ } ++ +++static int gpu_malloc_cached_internal(int numbytes, GPU_MEM_PTR_T *p) { +++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST, (char *)"Video Frame" ); +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC, (char *)"Video Frame" ); +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); +++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST_AND_VC, (char *)"Video Frame" ); +++ assert(p->vcsm_handle); +++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); +++ assert(p->vc_handle); +++ p->arm = vcsm_lock(p->vcsm_handle); +++ assert(p->arm); +++ p->vc = mem_lock(gpu->mb, p->vc_handle); +++ assert(p->vc); +++ return 0; +++} +++ ++ // This allocates data that will be ++ // Cached in ARM L2 ++ // Uncached in VPU L2 ++-int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p) { +++int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p) +++{ +++ int r; ++ gpu_lock(); ++-#ifdef RPI_USE_VCSM ++- { ++- p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST, (char *)"Video Frame" ); // f....... locks up for VP9 - retest this? ++- //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC, (char *)"Video Frame" ); // 3b...... works ++- //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); //fb...... locks up ++- //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST_AND_VC, (char *)"Video Frame" ); // 3b works (but corrupted due to caching) ++- p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); ++- p->arm = vcsm_lock(p->vcsm_handle); ++- p->vc = mem_lock(gpu->mb, p->vc_handle); ++- } ++-#else ++- p->vc_handle = mem_alloc(gpu->mb, numbytes, 4096, GPU_MEM_FLG); ++- p->vcsm_handle = 0; ++- if (!p->handle) ++- { ++- qpu_enable(gpu->mb, 0); ++- return -3; ++- } ++- p->vc = mem_lock(gpu->mb, p->vc_handle); ++- printf("This mapmem_private does not seem to work\n"); ++- exit(-1); ++- p->arm = mapmem_private((p->vc+GPU_MEM_MAP)&~0xc0000000,numbytes); ++- p->numbytes = numbytes; ++- if (p->arm == NULL) ++- { ++- mem_free(gpu->mb, p->handle); ++- mem_unlock(gpu->mb, p->handle); ++- gpu_unlock(); ++- qpu_enable(gpu->mb, 0); ++- return -4; ++- } ++-#endif +++ r = gpu_malloc_cached_internal(numbytes, p); ++ gpu->open_count++; ++ gpu_unlock(); ++- return 0; +++ return r; ++ } ++ ++ static void gpu_term(void) ++ { ++- int mb; ++- unsigned handle; +++ int mb; ++ ++ if (gpu==NULL) ++ return; ++ mb = gpu->mb; ++- handle = gpu->vc_handle; ++ ++ #ifdef RPI_ASYNC ++ { ++@@ -323,37 +287,26 @@ static void gpu_term(void) ++ } ++ #endif ++ +++ qpu_enable(mb, 0); +++ gpu_free_internal(&gpu_mem_ptr); ++ ++- unmapmem((void*)gpu, sizeof(struct GPU)); ++- mem_unlock(mb, handle); ++- mem_free(mb, handle); ++- qpu_enable(mb, 0); ++-#ifdef RPI_USE_VCSM ++ vcsm_exit(); ++-#endif ++- mbox_close(mb); +++ +++ mbox_close(mb); ++ gpu = NULL; ++ } ++ ++-void gpu_free(GPU_MEM_PTR_T *p) { +++void gpu_free_internal(GPU_MEM_PTR_T *p) { ++ int mb = gpu->mb; ++- unsigned handle = p->vc_handle; +++ mem_unlock(mb,p->vc_handle); +++ vcsm_unlock_ptr(p->arm); +++ vcsm_free(p->vcsm_handle); +++} +++ +++void gpu_free(GPU_MEM_PTR_T *p) { ++ gpu_lock(); ++-#ifdef RPI_USE_VCSM ++- if (p->vcsm_handle) { ++- mem_unlock(mb,p->vc_handle); ++- vcsm_unlock_ptr(p->arm); ++- vcsm_free(p->vcsm_handle); ++- } else { ++- unmapmem((void*)p->arm, sizeof(struct GPU)); ++- mem_unlock(mb, handle); ++- mem_free(mb, handle); ++- } ++-#else ++- unmapmem((void*)p->arm, sizeof(struct GPU)); ++- mem_unlock(mb, handle); ++- mem_free(mb, handle); ++-#endif +++ +++ gpu_free_internal(p); ++ ++ gpu->open_count--; ++ if (gpu->open_count==0) { ++@@ -386,20 +339,21 @@ unsigned int vpu_get_constants(void) { ++ ++ static void *vpu_start(void *arg) { ++ while(1) { +++ int *p; ++ pthread_mutex_lock(&post_mutex); ++ while( vpu_async_tail - vpu_async_head <= 0) ++ { ++ //printf("Checking number %d %d\n",vpu_async_head,vpu_async_tail); ++ pthread_cond_wait(&post_cond_tail, &post_mutex); ++ } ++- int *p = vpu_cmds[vpu_async_head%MAXCMDS]; +++ p = vpu_cmds[vpu_async_head%MAXCMDS]; ++ pthread_mutex_unlock(&post_mutex); ++ ++ if (p[6] == -1) { ++ break; // Last job ++ } ++ if (p[7]) { ++- GPU_MEM_PTR_T *buf = (GPU_MEM_PTR_T *)p[7]; +++ //GPU_MEM_PTR_T *buf = (GPU_MEM_PTR_T *)p[7]; ++ //gpu_cache_flush(buf); ++ } ++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); ++-- ++2.5.0 ++ ++ ++From a98ba0c30ea93bdf25308e679ed5a38f09b63f9d Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 14 May 2015 15:43:17 +0100 ++Subject: [PATCH 37/68] Enable EARLY_MALLOC and fix sps access bug ++ ++--- ++ libavcodec/hevc.c | 5 +++-- ++ 1 file changed, 3 insertions(+), 2 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index e2f8a87..61f6dfb 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -44,7 +44,7 @@ ++ #ifdef RPI ++ #include "rpi_qpu.h" ++ // For some unknown reason, the code seems to crash if I do a late malloc ++- #define EARLY_MALLOC +++ //#define EARLY_MALLOC ++ // Move Inter prediction into separate pass ++ #define RPI_INTER ++ #endif ++@@ -149,7 +149,8 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ #ifdef RPI ++ #ifdef EARLY_MALLOC ++ #else ++- int coeffs_in_ctb = (1 << s->ps.sps->log2_ctb_size) * (1 << s->ps.sps->log2_ctb_size); +++ assert(sps); +++ int coeffs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); ++ int coefs_per_row = sps->ctb_width * coeffs_in_ctb * 3; // Allow space for chroma ++ printf("pic_arrays_init\n"); ++ printf("Allocated %d\n",coefs_per_row); ++-- ++2.5.0 ++ ++ ++From 3e7256195852455e030586a1945cccc3fc7eb44a Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 14 May 2015 16:40:51 +0100 ++Subject: [PATCH 38/68] Add copy of av_mod_uintp2 for use with stable ffmpeg ++ ++--- ++ libavcodec/hevc.c | 8 ++++++++ ++ 1 file changed, 8 insertions(+) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 61f6dfb..d27c7f3 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -51,6 +51,14 @@ ++ ++ // #define DISABLE_MC ++ +++#ifndef av_mod_uintp2 +++static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p) +++{ +++ return a & ((1 << p) - 1); +++} +++# define av_mod_uintp2 av_mod_uintp2_c +++#endif +++ ++ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ ++ ++-- ++2.5.0 ++ ++ ++From ba9624fdc6073af3392753925bcb712dba984be8 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 18 May 2015 11:11:02 +0100 ++Subject: [PATCH 39/68] Added support for weighted prediction in P frames ++ ++--- ++ libavcodec/hevc.c | 52 ++++- ++ libavcodec/rpi_shader.c | 566 +++++++++++++++++++++++---------------------- ++ libavcodec/rpi_shader.h | 12 +- ++ libavcodec/rpi_shader.qasm | 39 +++- ++ 4 files changed, 384 insertions(+), 285 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index d27c7f3..98f8461 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -64,7 +64,7 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ ++ #ifdef RPI_INTER_QPU ++ ++-#define RPI_CHROMA_COMMAND_WORDS 10 +++#define RPI_CHROMA_COMMAND_WORDS 12 ++ #define UV_COMMANDS_PER_QPU ((1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS) ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++@@ -2020,6 +2020,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int y1_c = y0_c + (mv->y >> (2 + hshift)); ++ //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++ int chan = x0>>8; +++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || +++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++@@ -2032,6 +2034,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = ( (nPbW_csh.chroma_offset_l0[current_mv.ref_idx[0]][0] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0] & 0xffff); +++ *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1] & 0xffff); +++ } else { +++ *u++ = 1; // Weight of 1 and offset of 0 +++ *u++ = 1; +++ } ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2074,6 +2083,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int y1_c = y0_c + (mv->y >> (2 + hshift)); ++ //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++ int chan = x0>>8; +++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || +++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++@@ -2087,6 +2098,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ // TODO chroma weight and offset... s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++ *u++ = rpi_filter_coefs[_my][0]; +++ if (weight_flag) { +++ *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[1]][0] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[1]][0] & 0xffff); +++ *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[1]][1] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[1]][1] & 0xffff); +++ } else { +++ *u++ = 1; // Weight of 1 and offset of 0 +++ *u++ = 1; +++ } ++ *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2148,6 +2166,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = ( (nPbW_cmc_filter_uv_b; ++@@ -2158,6 +2177,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = ( (nPbW_cframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++@@ -2784,6 +2804,9 @@ static void rpi_inter_clear(HEVCContext *s) ++ int i; ++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; +++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || +++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); +++ ++ for(i=0;i<8;i++) { ++ s->u_mvs[i] = s->mvs_base[i]; ++ *s->u_mvs[i]++ = 0; ++@@ -2795,6 +2818,13 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = pic_height; ++ *s->u_mvs[i]++ = s->frame->linesize[1]; ++ *s->u_mvs[i]++ = s->frame->linesize[2]; +++ if (weight_flag) { +++ *s->u_mvs[i]++ = 1 << (s->sh.chroma_log2_weight_denom + 6 - 1); +++ *s->u_mvs[i]++ = s->sh.chroma_log2_weight_denom + 6; +++ } else { +++ *s->u_mvs[i]++ = 1 << 5; +++ *s->u_mvs[i]++ = 6; +++ } ++ s->u_mvs[i] += 1; // Padding words ++ } ++ } ++@@ -2838,12 +2868,29 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ ++ #ifdef RPI +++#ifdef RPI_INTER_QPU ++ s->enable_rpi = s->ps.sps->bit_depth == 8 ++ && s->ps.sps->width <= RPI_MAX_WIDTH ++ && !s->ps.pps->cross_component_prediction_enabled_flag ++ && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1 ++- && !(s->ps.pps->weighted_pred_flag && s->sh.slice_type == P_SLICE) ++ && !(s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE); +++#else +++ s->enable_rpi = s->ps.sps->bit_depth == 8 +++ && s->ps.sps->width <= RPI_MAX_WIDTH +++ && !s->ps.pps->cross_component_prediction_enabled_flag +++ && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1; +++#endif +++ +++ /*if (!s->enable_rpi) { +++ if (s->ps.pps->cross_component_prediction_enabled_flag) +++ printf("Cross component\n"); +++ if (s->ps.pps->num_tile_rows > 1 || s->ps.pps->num_tile_columns > 1) +++ printf("Tiles\n"); +++ if (s->ps.pps->weighted_pred_flag && s->sh.slice_type == P_SLICE) +++ printf("Weighted P slice\n"); +++ if (s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE) +++ printf("Weighted B slice\n"); +++ }*/ ++ ++ #endif ++ ++@@ -2976,6 +3023,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int ++ ++ #ifdef RPI ++ s->enable_rpi = 0; +++ //printf("Wavefront\n"); ++ #endif ++ ++ if(ctb_row) { ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index b0b93b5..3f04d80 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -88,287 +88,307 @@ unsigned int rpi_shader[] = { ++ /* [0x000001f8] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++ /* [0x00000200] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++ /* [0x00000208] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000218] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000220] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000228] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000230] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000238] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000240] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000248] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000210] */ 0x15827d80, 0x10021327, // mov rb12,unif +++/* [0x00000218] */ 0x15827d80, 0x10021367, // mov rb13,unif +++/* [0x00000220] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000228] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000230] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000238] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000240] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000248] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000250] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base +++/* [0x00000258] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base ++ // ::mc_filter_uv ++-/* [0x00000250] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000258] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000260] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000268] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000270] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000278] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000280] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000288] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000290] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000298] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000002a0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000002a8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002b0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002b8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002c0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002c8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002d0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002d8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000002e0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000002e8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002f0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000002f8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000300] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000330] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000340] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000350] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000358] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000360] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000260] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000268] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000270] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000278] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000280] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000288] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000290] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000298] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000002a0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000002a8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000002b0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000002b8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002c0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002c8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002d0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002d8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002e0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002e8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000002f0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000002f8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000310] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000340] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000350] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000358] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000360] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000368] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000370] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000378] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000380] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00000388] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000390] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 +++/* [0x00000398] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000003a0] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 +++/* [0x000003a8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000003b0] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x00000368] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000370] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000378] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000380] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000388] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000390] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000398] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003a0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003a8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003b0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000003b8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003c0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000003c8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000003d0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000003d8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000003e0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000003e8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000003f0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000003f8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000400] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000408] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000410] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000418] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000420] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000428] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000430] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000438] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000440] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000448] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000450] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000458] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000460] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000468] */ 0x0c567380, 0x10020867, // add r1, r1, ra21 ++-/* [0x00000470] */ 0xfffffed8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000478] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 ++-/* [0x00000480] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000488] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000490] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000498] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000004a8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000004b0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000004b8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000004c0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000004c8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000004d0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000003b8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003c0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x000003c8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x000003d0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003d8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003e0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003e8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003f0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003f8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000400] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000408] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000410] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000418] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000420] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000428] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000430] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000438] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000440] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000448] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000450] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000458] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000460] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000468] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000470] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000478] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000480] */ 0x00000020, 0xe0021327, // mov rb12,32 +++/* [0x00000488] */ 0x00000006, 0xe0021367, // mov rb13,6 +++/* [0x00000490] */ 0x00000001, 0xe00213a7, // mov rb14,1 +++/* [0x00000498] */ 0x00000000, 0xe00213e7, // mov rb15,0 +++/* [0x000004a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000004a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000004b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000004b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000004c0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000004c8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000004d0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000004d8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x000004e0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x000004e8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x000004f0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004f8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x00000500] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000508] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000510] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000518] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000520] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000528] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000530] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000538] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000540] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000548] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000550] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x000004d8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000004e0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000004e8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000004f0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000004f8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000500] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000508] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000510] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000518] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000520] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000528] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000530] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000538] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000540] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000548] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000550] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000558] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000560] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000568] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000570] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000578] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000580] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000588] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000590] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000598] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005a0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005a8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005b0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000005b8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005c8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000005d0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x000005d8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000005e0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000005e8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000558] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000560] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000568] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000570] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000578] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000580] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000588] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000590] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000598] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x000005a0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000005a8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x000005b0] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x000005b8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000005c0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005c8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000005d0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000005d8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000005e0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000005e8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000005f0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000005f8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000600] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000608] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000610] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000618] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000620] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000628] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000630] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000638] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000640] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000648] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000650] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000658] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000660] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000668] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000670] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000678] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x000005f0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000005f8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000600] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000608] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000610] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000618] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000620] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000628] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000630] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000638] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000640] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000648] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000650] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000658] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000660] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000668] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000670] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000678] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000680] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000688] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000690] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000698] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000006a0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000006a8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x000006b0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000006b8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000006c0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000006c8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000006d0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000006d8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000006e0] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 ++-/* [0x000006e8] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x000006f0] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++-/* [0x000006f8] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000700] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000708] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000710] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000718] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000720] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000680] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000688] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000690] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000698] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000006a0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000006a8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000006b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000006b8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000006c0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x000006c8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x000006d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000006d8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000006e0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000006e8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000006f0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000006f8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000700] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000708] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000710] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000718] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000720] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000728] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000730] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000738] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000740] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000748] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000750] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000758] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000760] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000768] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000770] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x00000778] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000780] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x00000788] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000790] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000798] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000007a0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007b0] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x00000728] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000730] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000738] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000740] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000748] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000750] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000758] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000760] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000768] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000770] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000778] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000780] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000788] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000790] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000798] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000007a0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000007a8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000007b0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000007b8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000007c0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000007c8] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x000007d0] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x000007d8] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x000007e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000007e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000007f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000007f8] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000800] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000808] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000810] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000818] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000820] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000828] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000830] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000838] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000840] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000848] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000850] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000858] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000007b8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000007c0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000007c8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000007d0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000007d8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000007e0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007e8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007f0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007f8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 +++/* [0x00000800] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000808] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 +++/* [0x00000810] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000818] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000820] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000828] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000830] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000838] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000840] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000848] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000850] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000858] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000860] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000868] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000870] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000878] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000880] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000888] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000890] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000898] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000008b8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008d0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x000008d8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008e0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008e8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008f0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008f8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000860] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000868] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000870] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000878] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000880] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000888] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000890] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000898] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000008a0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000008a8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000008b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008b8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000008c0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000008c8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000008d0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000008d8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000008e0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000008e8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000008f0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000008f8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000900] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000908] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000910] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000918] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000920] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000928] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000930] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000938] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000940] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000948] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000950] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x00000958] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000960] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000968] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000970] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000978] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000980] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000988] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000990] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000998] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000009a0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x000009a8] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x000009b0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000009b8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000009c0] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x000009c8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x000009d0] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000900] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000908] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 +++/* [0x00000910] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++/* [0x00000918] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000920] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000928] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000930] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000938] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000940] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 +++/* [0x00000948] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 +++/* [0x00000950] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000958] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000960] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000968] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000970] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000978] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000980] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000988] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000990] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000998] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x000009a0] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x000009a8] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009b0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000009b8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000009c0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000009c8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000009d0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000009d8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000009e0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000009e8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009f0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009f8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000a00] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000a08] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000a10] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000a18] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000a20] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a28] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a30] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a38] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a40] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000a48] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a50] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a60] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x000009d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x000009e0] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x000009e8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009f0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x000009f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a00] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a08] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a10] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000a18] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a78] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a80] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a98] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000aa0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ab0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000a20] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a28] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a30] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a38] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a40] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a48] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a50] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a58] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a60] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a68] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000a80] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a88] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000a90] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000ac0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ae0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b08] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b10] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b18] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000b20] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b28] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000b30] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 99927c4..cec9901 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,11 +4,11 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 148) ++-#define mc_filter_uv_b0 (rpi_shader + 310) ++-#define mc_filter_uv_b (rpi_shader + 458) ++-#define mc_exit (rpi_shader + 630) ++-#define mc_interrupt_exit8 (rpi_shader + 648) ++-#define mc_end (rpi_shader + 678) +++#define mc_filter_uv (rpi_shader + 152) +++#define mc_filter_uv_b0 (rpi_shader + 342) +++#define mc_filter_uv_b (rpi_shader + 494) +++#define mc_exit (rpi_shader + 670) +++#define mc_interrupt_exit8 (rpi_shader + 688) +++#define mc_end (rpi_shader + 718) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index d9ffcda..97c4c02 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -9,7 +9,12 @@ ++ # (ra15 isn't clamped to zero - this happens during the ++ # copy to ra14, and during its use in the vertical filter) ++ # ++-# rb8...rb15 eight vertical filter coefficients +++# rb8...rb11 eight vertical filter coefficients +++ +++# rb12 offset to add before shift +++# rb13 shift +++# rb14 weight (U on left, V on right) +++# rb15 offset (U on left, V on right) ++ # ++ # ra16 clipped(row start address+elem_num)&~3 ++ # ra17 per-channel shifts ++@@ -165,6 +170,9 @@ add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++ add t0s, r0, r1 ; mov ra_x2_base, r2 ++ add t0s, r2, r1 ++ +++mov rb12,unif # offset before shift +++mov rb13,unif # offset after shift +++ ++ # Dump padding words ++ mov r0, unif ++ ++@@ -231,11 +239,21 @@ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23 ++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++mov r0, unif # U offset/weight +++asr rb15, r0, r2 # Compute offset from MSBs +++shl r0, r0, r2 +++asr rb14, r0, r2 # Compute weight from LSBs +++mov r0, unif # V offset/weight +++asr.ifnz rb15, r0, r2 +++shl r0, r0, r2 +++asr.ifnz rb14, r0, r2 +++ ++ # r2 is elem_num ++ # r3 is loop counter ++ ++ mov r5rep, -8 ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++ # retrieve texture results and pick out bytes ++ # then submit two more texture requests ++@@ -279,6 +297,11 @@ mov ra13, ra14 # Delay slot 1 ++ mov ra14, ra15 # Delay slot 2 ++ mov ra15, r0 # Delay slot 3 ++ +++mov rb12,32 +++mov rb13,6 +++mov rb14,1 +++mov rb15,0 +++ ++ # apply vertical filter and write to VPM ++ ++ nop ; mul24 r1, ra14, rb10 ++@@ -288,9 +311,11 @@ add r1, r1, r0 ; mul24 r0, ra15, rb11 ++ add r1, r1, r0 ; mov -, vw_wait ++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++ asr r1, r1, 14 ++-add r1, r1, ra21 +++nop ; mul24 r1, r1, rb14 +++add r1, r1, rb12 +++asr r1, r1, rb13 ++ brr.anyn -, r:uvloop ++-asr r1, r1, 6 # Delay 1 +++add r1, r1, rb15 # Delay 1 ++ min r1, r1, rb22 # Delay 2 ++ max vpm, r1, 0 # Delay 3 ++ ++@@ -364,6 +389,9 @@ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23 ++ +++mov r0, unif # U offset/weight +++mov r0, unif # V offset/weight +++ ++ # r2 is elem_num ++ # r3 is loop counter ++ ++@@ -491,6 +519,9 @@ asr rb10, r0, rb23; mul24 r0, r0, ra22 ++ asr rb9, r0, rb23; mul24 r0, r0, ra22 ++ asr rb8, r0, rb23 ++ +++mov r0, unif # U offset/weight +++mov r0, unif # V offset/weight +++ ++ # r2 is elem_num ++ # r3 is loop counter ++ ++-- ++2.5.0 ++ ++ ++From b789dfe8032e13b13384315c6e40d59891c1d248 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 19 May 2015 08:43:30 +0100 ++Subject: [PATCH 40/68] Improved ordering of tasks ++ ++--- ++ libavcodec/hevc.c | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 98f8461..01898fd 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2932,15 +2932,15 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->dblk_cmds[s->num_dblk_cmds][0] = x_ctb; ++ s->dblk_cmds[s->num_dblk_cmds++][1] = y_ctb; ++ if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { ++-#ifdef RPI_INTER_QPU ++- // Kick off inter prediction on QPUs ++- rpi_execute_inter_qpu(s); ++-#endif ++ // Transform all blocks ++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++ rpi_execute_transform(s); ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); +++#ifdef RPI_INTER_QPU +++ // Kick off inter prediction on QPUs +++ rpi_execute_inter_qpu(s); +++#endif ++ // Wait for transform completion ++ vpu_wait(s->vpu_id); ++ ++-- ++2.5.0 ++ ++ ++From 005310ce2e038c9d9d8d6761b11718d218983975 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 20 May 2015 19:58:19 +0100 ++Subject: [PATCH 41/68] Drafted Luma inter prediction ++ ++--- ++ libavcodec/rpi_shader.qasm | 594 ++++++++++++++++++++++++++++++++++++++++++--- ++ 1 file changed, 554 insertions(+), 40 deletions(-) ++ ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 97c4c02..9cfc0d9 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -2,7 +2,10 @@ ++ # ++ # ra0...ra7 eight horizontal filter coefficients ++ # ++-# rb1...rb7 seven shifted copies of the current unfiltered row +++# rb0 rx_shift2 +++# rb1 ra_y2_next +++# +++# rb4...rb7 ++ # ++ # ra8...ra15 eight filtered rows of context (rb15 == most recent) ++ # ++@@ -26,9 +29,9 @@ ++ # rb19 next ra16 ++ # ++ # ra20 1 ++-# ra21 32 +++# ra21 ra_21 ++ # ra22 256 ++-# ra23 8 +++# ra23 rx_shift2_next ++ # ++ # rb20 0xffffff00 ++ # rb21 vpm_setup for reading/writing 16bit results into VPM ++@@ -57,16 +60,23 @@ ++ .set rb_frame_width_minus_1, rb25 ++ .set rb_frame_height_minus_1, rb30 ++ .set rb_pitch, rb16 ++-.set ra_x_base, ra16 ++-.set rb_x_base_next, rb19 ++-.set ra_x2_base, ra24 ++-.set ra_x2_base_next, ra26 +++.set ra_x, ra16 +++.set ra_y2, ra21 +++.set ra_y2_next, rb1 +++ +++.set rb_x_next, rb19 +++.set rx_frame_base2_next, rb19 +++ +++.set ra_frame_base, ra24 +++.set ra_frame_base_next, ra26 ++ .set ra_xshift, ra17 ++ ++-.set ra_x2shift, ra25 ++ .set ra_u2v_ref_offset, ra25 +++.set ra_frame_base2, ra25 ++ ++ .set ra_xshift_next, ra19 +++.set rx_xshift2, rb0 +++.set rx_xshift2_next, ra23 ++ ++ .set ra_x2shift_next, ra27 ++ .set ra_u2v_dst_offset, ra27 ++@@ -83,11 +93,11 @@ ++ mov ra31, unif ++ ++ # Load first request location ++-add ra_x_base, unif, elem_num # Store x +++add ra_x, unif, elem_num # Store x ++ mov ra_y, unif # Store y ++-mov ra_x2_base, unif # Store frame u base +++mov ra_frame_base, unif # Store frame u base ++ nop ++-sub ra_u2v_ref_offset, unif, ra_x2_base # Store offset to add to move from u to v in reference frame +++sub ra_u2v_ref_offset, unif, ra_frame_base # Store offset to add to move from u to v in reference frame ++ ++ # Read image dimensions ++ sub rb25,unif,1 ++@@ -104,9 +114,7 @@ add rb24, r1, r0 ++ # load constants ++ ++ mov ra20, 1 ++-mov ra21, 32 ++ mov ra22, 256 ++-mov ra23, 8 ++ mov ra30, 64 ++ ++ mov rb20, 0xffffff00 ++@@ -156,18 +164,18 @@ mov r1, vpm_setup(0, 2, h16p(0, 0)) # 2 is stride - stride acts on ADDR which i ++ add rb21, r0, r1 ++ ++ # Compute base address for first and second access ++-mov r0, ra_x_base # Load x +++mov r0, ra_x # Load x ++ max r0, r0, 0; mov r1, ra_y # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base # Load the frame base +++min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base # Load the frame base ++ shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++ add ra_y, r1, 1 ++ add r0, r0, r3 ++ and r0, r0, ~3 ++-max r1, r1, 0 ; mov ra_x_base, r0 # y +++max r1, r1, 0 ; mov ra_x, r0 # y ++ min r1, r1, rb_frame_height_minus_1 ++ # submit texture requests for first line ++ add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-add t0s, r0, r1 ; mov ra_x2_base, r2 +++add t0s, r0, r1 ; mov ra_frame_base, r2 ++ add t0s, r2, r1 ++ ++ mov rb12,unif # offset before shift ++@@ -182,8 +190,8 @@ min r1, r1, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ++ bra -, ra31 ++ nop ; mul24 r1, r1, rb_pitch ++-add t0s, r1, ra_x_base ++-add t0s, r1, ra_x2_base +++add t0s, r1, ra_x +++add t0s, r1, ra_frame_base ++ ++ ++ ++@@ -192,7 +200,7 @@ add t0s, r1, ra_x2_base ++ # mc_filter_uv(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) ++ ++ # At this point we have already issued two pairs of texture requests for the current block ++-# ra_x_base, ra_x16_base point to the current coordinates for this block +++# ra_x, ra_x16_base point to the current coordinates for this block ++ ::mc_filter_uv ++ mov ra31, unif ++ ++@@ -207,9 +215,9 @@ min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base ++ shl ra_xshift_next, r0, 3 ++ sub r2, unif, r3 # compute offset from frame base u to frame base v ++ add r0, r0, r3 ++-and rb_x_base_next, r0, ~3 +++and rb_x_next, r0, ~3 ++ mov ra_y_next, r1 ++-add ra_x2_base_next, rb_x_base_next, r2 +++add ra_frame_base_next, rb_x_next, r2 ++ ++ # set up VPM write ++ mov vw_setup, rb28 ++@@ -265,16 +273,16 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 +++add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -297,7 +305,7 @@ mov ra13, ra14 # Delay slot 1 ++ mov ra14, ra15 # Delay slot 2 ++ mov ra15, r0 # Delay slot 3 ++ ++-mov rb12,32 +++mov rb12,32 # TODO remove these to make P weighted prediction work properly ++ mov rb13,6 ++ mov rb14,1 ++ mov rb15,0 ++@@ -342,7 +350,7 @@ mov vw_addr, unif # start the VDW ++ # mc_filter_uv_b0(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) ++ ++ # At this point we have already issued two pairs of texture requests for the current block ++-# ra_x_base, ra_x16_base point to the current coordinates for this block +++# ra_x, ra_x16_base point to the current coordinates for this block ++ ::mc_filter_uv_b0 ++ mov ra31, unif ++ ++@@ -357,9 +365,9 @@ min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base ++ shl ra_xshift_next, r0, 3 ++ sub r2, unif, r3 # compute offset from frame base u to frame base v ++ add r0, r0, r3 ++-and rb_x_base_next, r0, ~3 +++and rb_x_next, r0, ~3 ++ mov ra_y_next, r1 ++-add ra_x2_base_next, rb_x_base_next, r2 +++add ra_frame_base_next, rb_x_next, r2 ++ ++ # set up VPM write, we need to save 16bit precision ++ mov vw_setup, rb21 ++@@ -408,16 +416,16 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 +++add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -477,9 +485,9 @@ min r0, r0, rb_frame_width_minus_1 ; mov r3, unif # frame_base ++ shl ra_xshift_next, r0, 3 ++ sub r2, unif, r3 # compute offset from frame base u to frame base v ++ add r0, r0, r3 ++-and rb_x_base_next, r0, ~3 +++and rb_x_next, r0, ~3 ++ mov ra_y_next, r1 ++-add ra_x2_base_next, rb_x_base_next, r2 +++add ra_frame_base_next, rb_x_next, r2 ++ ++ # set up VPM write ++ mov vw_setup, rb28 ++@@ -538,16 +546,16 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ ++ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_x2_base, r2 +++add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++add t0s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -642,5 +650,511 @@ nop ; nop ; thrend ++ mov interrupt, 1; nop # delay slot 1 ++ nop ; nop # delay slot 2 ++ +++ +++ +++ +++ +++# LUMA CODE +++ +++# The idea is to form B predictions by doing 8 pixels from ref0 in parallel with 8 pixels from ref1. +++# For P frames we make the second x,y coordinates offset by +8 +++ +++################################################################################ +++# mc_setup(next_kernel, x, y, ref_y_base, x2, y2, ref_y2_base, frame_width, frame_height, pitch, dst_pitch, offset, shift, pad2) +++::mc_setup +++ +++# Read starting kernel +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++mov ra31, unif +++ +++# Compute base address for first and second access +++add r0, unif, elem_num # Load x +++max r0, r0, 0; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl ra_xshift_next, r0, 3 # Compute shifts +++add ra_y, r1, 1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add r2, r2, r0 # r2 is address for frame0 (not including y offset) +++max r1, r1, 0 +++min r1, r1, rb_frame_height_minus_1 +++nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 +++add t0s, r2, r1 ; mov ra_frame_base, r2 +++ +++add r0, unif, elem_num # Load x +++max r0, r0, 0; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl rx_xshift2_next, r0, 3 # Compute shifts +++add ra_y2, r1, 1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add r2, r2, r0 # r2 is address for frame1 (not including y offset) +++max r1, r1, 0 +++min r1, r1, rb_frame_height_minus_1 +++nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 +++add t0s, r2, r1 ; mov ra_frame_base2, r2 +++ +++ +++# Read image dimensions +++sub rb25,unif,1 +++sub rb30,unif,1 +++ +++# get source pitch +++mov rb16, unif +++ +++# get destination pitch +++mov r0, unif +++mov r1, vdw_setup_1(0) +++add rb24, r1, r0 +++ +++# load constants +++ +++mov ra20, 1 +++mov ra22, 256 +++mov ra30, 64 +++ +++mov rb20, 0xffffff00 +++mov rb22, 255 +++mov rb23, 24 +++ +++# touch vertical context to keep simulator happy +++ +++mov ra8, 0 +++mov ra9, 0 +++mov ra10, 0 +++mov ra11, 0 +++mov ra12, 0 +++mov ra13, 0 +++mov ra14, 0 +++mov ra15, 0 +++ +++# Compute part of VPM to use for DMA output +++mov r2, qpu_num +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later +++shl r0, r0, 5 +++add rb27, r0, r1 +++ +++# Compute part of VPM to save data into +++mov r2, qpu_num # qpu_num = abcd +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 +++mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit +++add rb28, r0, r1 +++ +++mov rb12,unif # offset before shift +++mov rb13,unif # shift +++ +++# Dump padding words +++mov r0, unif +++ +++# submit texture requests for second line +++max r1, ra_y, 0 +++min r1, r1, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 +++nop ; mul24 r1, r1, rb_pitch +++add t0s, r1, ra_frame_base +++ +++max r1, ra_y2, 0 +++min r1, r1, rb_frame_height_minus_1 +++bra -, ra31 +++add ra_y2, ra_y2, 1 # Delay 1 +++nop ; mul24 r1, r1, rb_pitch # Delay 2 +++add t0s, r1, ra_frame_base2 # Delay 3 +++ +++ +++################################################################################ +++ +++# mc_filter(next_kernel, x, y, frame_base, x2, y2, frame_base2, height, hcoeffs[0], hcoeffs2[0], hcoeffs[1], hcoeffs2[1], vcoeffs[0], vcoeffs2[0], vcoeffs[1], vcoeffs2[1], offsetweight0, offsetweight1, this_dst) +++# In a P block, only the first half of coefficients contain used information. +++# At this point we have already issued two pairs of texture requests for the current block +++# ra_x, ra_x16_base point to the current coordinates for this block +++::mc_filter +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++mov rx_xshift2, rx_xshift2_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # Load x +++max r0, r0, 0; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl ra_xshift_next, r0, 3 # Compute shifts +++mov ra_y_next, r1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add ra_frame_base_next, r2, r0 # r2 is address for frame0 (not including y offset) +++ +++add r0, unif, elem_num # Load x +++max r0, r0, 0 ; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl rx_xshift2_next, r0, 3 # Compute shifts +++add ra_y2_next, r1, 1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add rx_frame_base2_next, r2, r0 # r2 is address for frame1 (not including y offset) +++ +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++# get filter coefficients and discard unused B frame values +++mov r0, unif +++mov.ifnz -, unif # Alternate coefficients are unused for P frames +++asr ra3, r0, rb23; mul24 r0, r0, ra22 # These may need some pre-rotation to be used in B frames correctly +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++mov.ifnz -, unif +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++asr ra4, r0, rb23; mov r0, unif +++mov.ifnz -, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++mov.ifnz -, unif +++asr rb7, r0, rb23; mul24 r0, r0, ra22 +++asr rb6, r0, rb23; mul24 r0, r0, ra22 +++asr rb5, r0, rb23; mul24 r0, r0, ra22 +++asr rb4, r0, rb23 +++ +++mov r0, unif # Frame0 offset/weight +++mov.ifnz -, unif # Frame1 offset/weight unused +++asr rb15, r0, r2 # Compute offset from MSBs +++shl r0, r0, r2 +++asr rb14, r0, r2 # Compute weight from LSBs +++ +++# r3 is loop counter +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++mov r3, 0 +++ +++:yloop +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++# If we knew there was no clipping then this code would get simpler. +++# Perhaps we could add on the pitch and clip using larger values? +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, rx_xshift2 +++mov.ifz ra_y2, ra_y2_next +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y2, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++ +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# apply horizontal filter +++nop ; mul24 r2, r0, ra0 +++nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++nop ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++add r0, r2, r3 ; mov r3, rb31 +++sub.setf -, r3, 8 ; mov ra12, ra13 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++brr.anyn -, r:yloop +++mov ra13, ra14 # Delay slot 1 +++mov ra14, ra15 # Delay slot 2 +++mov ra15, r0 # Delay slot 3 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r1, ra14, rb10 +++nop ; mul24 r0, ra13, rb9 +++add r1, r1, r0 ; mul24 r0, ra12, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb11 +++add r1, r1, r0 ; mul24 r0, ra8, rb4 +++add r1, r1, r0 ; mul24 r0, ra9, rb5 +++add r1, r1, r0 ; mul24 r0, ra10, rb6 +++add r1, r1, r0 ; mul24 r0, ra11, rb7 +++ +++add r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++asr r1, r1, 14 +++nop ; mul24 r1, r1, rb14 +++add r1, r1, rb12 +++asr r1, r1, rb13 +++brr.anyn -, r:yloop +++add r1, r1, rb15 # Delay 1 +++min r1, r1, rb22 # Delay 2 +++max vpm, r1, 0 # Delay 3 +++ +++# DMA out +++ +++bra -, ra31 +++mov vw_setup, rb26 # VDW setup 0 Delay 1 +++mov vw_setup, rb29 # Stride Delay 2 +++mov vw_addr, unif # start the VDW Delay 3 +++ +++ +++ +++################################################################################ +++ +++# mc_filter_b(next_kernel, x, y, frame_base, x2, y2, frame_base2, width_height, hcoeffs[0], hcoeffs2[0], hcoeffs[1], hcoeffs2[1], vcoeffs[0], vcoeffs2[0], vcoeffs[1], vcoeffs2[1], offsetweight0, offsetweight1, this_dst) +++# In a P block, only the first half of coefficients contain used information. +++# At this point we have already issued two pairs of texture requests for the current block +++# May be better to just send 16.16 motion vector and figure out the coefficients inside this block (only 4 cases so can compute hcoeffs in around 24 cycles?) +++# Can fill in the coefficients so only +++# Can also assume default weighted prediction for B frames. +++# Perhaps can unpack coefficients in a more efficient manner by doing H/V for a and b at the same time? +++# Or possibly by taking advantage of symmetry? +++# From 19->7 32bits per command. +++::mc_filter_b +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++mov ra31, unif +++ +++# per-channel shifts were calculated on the *previous* invocation +++ +++mov ra_xshift, ra_xshift_next +++mov rx_xshift2, rx_xshift2_next +++ +++# get base addresses and per-channel shifts for *next* invocation +++add r0, unif, elem_num # Load x +++max r0, r0, 0; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl ra_xshift_next, r0, 3 # Compute shifts +++mov ra_y_next, r1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add ra_frame_base_next, r2, r0 # r2 is address for frame0 (not including y offset) +++ +++add r0, unif, elem_num # Load x +++max r0, r0, 0 ; mov r1, unif # Load y +++min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++shl rx_xshift2_next, r0, 3 # Compute shifts +++add ra_y2_next, r1, 1 +++and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++add rx_frame_base2_next, r2, r0 # r2 is address for frame1 (not including y offset) +++ +++ +++# set up VPM write +++mov vw_setup, rb28 +++ +++# get width,height of block +++mov r2, 16 +++mov r0, unif +++shr r1, r0, r2 # Extract width +++sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++and r0, r0, rb22 # Extract height +++add rb17, r0, 5 +++add rb18, r0, 7 +++shl r0, r0, 7 +++add r0, r0, r1 # Combine width and height of destination area +++shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register +++add rb26, r0, rb27 +++ +++# get filter coefficients and discard unused B frame values +++mov r0, unif +++mov r1, 1 +++mov.ifnz r0, unif # Alternate coefficients are unused for P frames +++nop ; mul24 r0, r0 << 13, r1 << 13 +++asr ra3, r0, rb23; mul24 r0, r0, ra22 +++nop ; mul24 r0, r0 << 14, r1 << 14 +++asr ra2, r0, rb23; mul24 r0, r0, ra22 +++nop ; mul24 r0, r0 << 15, r1 << 15 # Adjust such that a rotate of 1 will produce the values with first 8 on left, second 8 on right +++asr ra1, r0, rb23; mul24 r0, r0, ra22 +++asr ra0, r0, rb23; mov r0, unif +++mov.ifnz r0, unif +++nop ; mul24 r0, r0 << 9, r1 << 9 +++asr ra7, r0, rb23; mul24 r0, r0, ra22 +++nop ; mul24 r0, r0 << 10, r1 << 10 +++asr ra6, r0, rb23; mul24 r0, r0, ra22 +++nop ; mul24 r0, r0 << 11, r1 << 11 +++asr ra5, r0, rb23; mul24 r0, r0, ra22 +++nop ; mul24 r0, r0 << 12, r1 << 12 +++asr ra4, r0, rb23; mov r0, unif +++mov.ifnz r0, unif +++asr rb11, r0, rb23; mul24 r0, r0, ra22 +++asr rb10, r0, rb23; mul24 r0, r0, ra22 +++asr rb9, r0, rb23; mul24 r0, r0, ra22 +++asr rb8, r0, rb23; mov r0, unif +++mov.ifnz r0, unif +++asr rb7, r0, rb23; mul24 r0, r0, ra22 +++asr rb6, r0, rb23; mul24 r0, r0, ra22 +++asr rb5, r0, rb23; mul24 r0, r0, ra22 +++asr rb4, r0, rb23 +++ +++mov r0, unif # Frame0 offset/weight +++mov.ifnz r0, unif # Frame1 offset/weight unused +++asr rb15, r0, r2 # Compute offset from MSBs +++shl r0, r0, r2 +++asr rb14, r0, r2 # Compute weight from LSBs +++ +++# r3 is loop counter +++ +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++mov r3, 0 +++ +++:yloopb +++# retrieve texture results and pick out bytes +++# then submit two more texture requests +++ +++# If we knew there was no clipping then this code would get simpler. +++# Perhaps we could add on the pitch and clip using larger values? +++ +++sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++shr r1, r4, rx_xshift2 +++mov.ifz ra_y2, ra_y2_next +++ +++max r2, ra_y, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte +++ +++max r2, ra_y2, 0 # y +++min r2, r2, rb_frame_height_minus_1 +++add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++ +++ +++# generate seven shifted versions +++# interleave with scroll of vertical context +++ +++mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ +++# apply horizontal filter +++nop ; mul24 r2, r0, ra0 +++nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++nop ; mul24 r3, ra1 << 1, r0 << 1 +++nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++add r0, r2, r3 ; mov r3, rb31 +++sub.setf -, r3, 8 ; mov ra12, ra13 +++mov ra9, ra10 +++mov ra10, ra11 +++mov ra11, ra12 +++mov ra12, ra13 +++brr.anyn -, r:yloopb +++mov ra13, ra14 # Delay slot 1 +++mov ra14, ra15 # Delay slot 2 +++mov ra15, r0 # Delay slot 3 +++ +++# apply vertical filter and write to VPM +++ +++nop ; mul24 r1, ra14, rb10 +++nop ; mul24 r0, ra13, rb9 +++add r1, r1, r0 ; mul24 r0, ra12, rb8 +++add r1, r1, r0 ; mul24 r0, ra15, rb11 +++add r1, r1, r0 ; mul24 r0, ra8, rb4 +++add r1, r1, r0 ; mul24 r0, ra9, rb5 +++add r1, r1, r0 ; mul24 r0, ra10, rb6 +++add r1, r1, r0 ; mul24 r0, ra11, rb7 +++ +++add r1, r1, r0 ; mov -, vw_wait +++sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++asr r1, r1, 14 +++nop ; mul24 r1, r1 << 8, ra20 << 8 # Rotate to align left and right halves +++add r1, r1, ra30 ; mul24 r0, r1, rb14 +++add r1, r1, r0 +++brr.anyn -, r:yloopb +++asr r1, r1, 7 # Delay 1 +++min r1, r1, rb22 # Delay 2 +++max vpm, r1, 0 # Delay 3 +++ +++# DMA out +++bra -, ra31 +++mov vw_setup, rb26 # VDW setup 0 Delay 1 +++mov vw_setup, rb29 # Stride Delay 2 +++mov vw_addr, unif # start the VDW Delay 3 +++ +++################################################################################ +++ +++# mc_interrupt_exit12() +++::mc_interrupt_exit12 +++mov -, vw_wait # wait on the VDW +++ +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ldtmu0 +++ +++mov -,sacq(0) # 1 +++mov -,sacq(0) # 2 +++mov -,sacq(0) # 3 +++mov -,sacq(0) # 4 +++mov -,sacq(0) # 5 +++mov -,sacq(0) # 6 +++mov -,sacq(0) # 7 +++mov -,sacq(0) # 8 +++mov -,sacq(0) # 9 +++mov -,sacq(0) # 10 +++mov -,sacq(0) # 11 +++ +++nop ; nop ; thrend +++mov interrupt, 1; nop # delay slot 1 +++nop ; nop # delay slot 2 +++ +++ ++ ::mc_end ++ # Do not add code here because mc_end must appear after all other code. ++-- ++2.5.0 ++ ++ ++From e6e832826a1f27e07c1c9ff48e0690fe4a732dd3 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 20 May 2015 19:58:30 +0100 ++Subject: [PATCH 42/68] Added support for fast cache flush in deblocker ++ ++--- ++ libavcodec/hevc_filter.c | 44 +- ++ libavcodec/rpi_qpu.c | 6 + ++ libavcodec/rpi_qpu.h | 2 + ++ libavcodec/rpi_shader.c | 1028 +++++++++++++++++++++++++++++--------------- ++ libavcodec/rpi_shader.h | 16 +- ++ libavcodec/rpi_user_vcsm.h | 22 + ++ 6 files changed, 768 insertions(+), 350 deletions(-) ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 92a8271..186317a 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -37,6 +37,11 @@ ++ ++ #include "bit_depth_template.c" ++ +++#ifdef RPI +++#include "rpi_user_vcsm.h" +++#include "rpi_qpu.h" +++#endif +++ ++ #define LUMA 0 ++ #define CB 1 ++ #define CR 2 ++@@ -872,15 +877,46 @@ static void flush_buffer(AVBufferRef *bref) { ++ gpu_cache_flush(p); ++ } ++ ++-static void ff_hevc_flush_chroma(HEVCContext *s) +++// Return Physical address for this image +++static int ff_hevc_buf_base(AVBufferRef *bref) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); +++ return p->vc & 0x3fffffff; +++} +++ +++static void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n) ++ { ++ if (s->enable_rpi && !( s->nal_unit_type == NAL_TRAIL_N || ++ s->nal_unit_type == NAL_TSA_N || ++ s->nal_unit_type == NAL_STSA_N || ++ s->nal_unit_type == NAL_RADL_N || ++ s->nal_unit_type == NAL_RASL_N )) { +++#define RPI_FAST_CACHEFLUSH +++#ifdef RPI_FAST_CACHEFLUSH +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ int curr_y = f->progress->data[0]; +++ int sz,base; +++ if (curr_y < 0) curr_y = 0; +++ if (n<=curr_y) return; // Should not happen +++ sz = s->frame->linesize[1] * (n-curr_y); +++ base = s->frame->linesize[1] * curr_y; +++ iocache.s[0].cmd = 3; // Flush L1 cache +++ iocache.s[0].addr = 0; +++ iocache.s[0].size = 0; +++ +++ iocache.s[1].cmd = 2; +++ iocache.s[1].addr = ff_hevc_buf_base(s->frame->buf[1]) + base; +++ iocache.s[1].size = sz; +++ +++ iocache.s[2].cmd = 2; +++ iocache.s[2].addr = ff_hevc_buf_base(s->frame->buf[2]) + base; +++ iocache.s[2].size = sz; +++ +++ vcsm_clean_invalid( gpu_get_mailbox(), &iocache ); +++ +++#else ++ flush_buffer(s->frame->buf[1]); ++ flush_buffer(s->frame->buf[2]); +++#endif ++ //memcpy(s->dummy.arm,s->frame->data[0],2048*64); ++ //memcpy(s->dummy.arm,s->frame->data[1],1024*32); ++ //memcpy(s->dummy.arm,s->frame->data[2],1024*32); ++@@ -903,7 +939,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ sao_filter_CTB(s, x, y - ctb_size); ++ if (s->threads_type & FF_THREAD_FRAME ) { ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s); +++ ff_hevc_flush_chroma(s,&s->ref->tf, y); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y, 0); ++ } ++@@ -912,7 +948,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ sao_filter_CTB(s, x , y); ++ if (s->threads_type & FF_THREAD_FRAME ) { ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s); +++ ff_hevc_flush_chroma(s, &s->ref->tf, y + ctb_size); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0); ++ } ++@@ -922,7 +958,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ //int currh = s->ref->tf.progress->data[0]; ++ //if (((y + ctb_size)&63)==0) ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s); +++ ff_hevc_flush_chroma(s, &s->ref->tf, y + ctb_size - 4); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index f62051f..fd8a276 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -237,6 +237,12 @@ int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) ++ return r; ++ } ++ +++int gpu_get_mailbox(void) +++{ +++ assert(gpu); +++ return gpu->mb; +++} +++ ++ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ { ++ void *tmp = vcsm_lock(p->vcsm_handle); ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 543c84b..88965e5 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -49,4 +49,6 @@ extern int rpi_test_shader(void); ++ extern void rpi_do_block(const unsigned char *in_buffer_vc, int src_pitch, unsigned char *dst_vc, int dst_pitch, unsigned char *dst); ++ extern void rpi_do_block_arm(const unsigned char *in_buffer, int src_pitch, unsigned char *dst, int dst_pitch); ++ +++extern int gpu_get_mailbox(void); +++ ++ #endif ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 3f04d80..9c30e32 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -23,11 +23,11 @@ __attribute__((aligned(8))) ++ unsigned int rpi_shader[] = { ++ // ::mc_setup_uv ++ /* [0x00000000] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000008] */ 0x0c9a0f80, 0x10020427, // add ra_x_base, unif, elem_num +++/* [0x00000008] */ 0x0c9a0f80, 0x10020427, // add ra_x, unif, elem_num ++ /* [0x00000010] */ 0x15827d80, 0x10020767, // mov ra_y, unif ++-/* [0x00000018] */ 0x15827d80, 0x10020627, // mov ra_x2_base, unif +++/* [0x00000018] */ 0x15827d80, 0x10020627, // mov ra_frame_base, unif ++ /* [0x00000020] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000028] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_x2_base +++/* [0x00000028] */ 0x0d620f80, 0x10020667, // sub ra_u2v_ref_offset, unif, ra_frame_base ++ /* [0x00000030] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++ /* [0x00000038] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++ /* [0x00000040] */ 0x15827d80, 0x10021427, // mov rb16, unif ++@@ -35,360 +35,708 @@ unsigned int rpi_shader[] = { ++ /* [0x00000050] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++ /* [0x00000058] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++ /* [0x00000060] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x00000068] */ 0x00000020, 0xe0020567, // mov ra21, 32 ++-/* [0x00000070] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x00000078] */ 0x00000008, 0xe00205e7, // mov ra23, 8 ++-/* [0x00000080] */ 0x00000040, 0xe00207a7, // mov ra30, 64 ++-/* [0x00000088] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000090] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000098] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x000000a0] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x000000a8] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x000000b0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x000000b8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x000000c0] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x000000c8] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x000000d0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x000000d8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000e0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x000000e8] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-/* [0x000000f0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x000000f8] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000100] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000108] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000110] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000118] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000120] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000128] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000130] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000138] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000140] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000148] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-/* [0x00000150] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000158] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000160] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000168] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000170] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000178] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000180] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000188] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000190] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000198] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 ++-/* [0x000001a0] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++-/* [0x000001a8] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 ++-/* [0x000001b0] */ 0x15427d80, 0x10020827, // mov r0, ra_x_base ++-/* [0x000001b8] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000001c0] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_x2_base ++-/* [0x000001c8] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000001d0] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001d8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000001e0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001e8] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x_base, r0 ++-/* [0x000001f0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001f8] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x00000200] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_x2_base, r2 ++-/* [0x00000208] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00000210] */ 0x15827d80, 0x10021327, // mov rb12,unif ++-/* [0x00000218] */ 0x15827d80, 0x10021367, // mov rb13,unif ++-/* [0x00000220] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000228] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000230] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000238] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000240] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000248] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000250] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x_base ++-/* [0x00000258] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_x2_base +++/* [0x00000068] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000070] */ 0x00000040, 0xe00207a7, // mov ra30, 64 +++/* [0x00000078] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000080] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000088] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000090] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00000098] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x000000a0] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x000000a8] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x000000b0] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x000000b8] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x000000c0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x000000c8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x000000d0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x000000d8] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x000000e0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x000000e8] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x000000f0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x000000f8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000100] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000108] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000110] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000118] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000120] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000128] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000130] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000138] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x00000140] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000148] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000150] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000158] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000160] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000168] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000170] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000178] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000180] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000188] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 +++/* [0x00000190] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) +++/* [0x00000198] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 +++/* [0x000001a0] */ 0x15427d80, 0x10020827, // mov r0, ra_x +++/* [0x000001a8] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000001b0] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base +++/* [0x000001b8] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000001c0] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000001c8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000001d0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001d8] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x, r0 +++/* [0x000001e0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x000001e8] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x000001f0] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 +++/* [0x000001f8] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x00000200] */ 0x15827d80, 0x10021327, // mov rb12,unif +++/* [0x00000208] */ 0x15827d80, 0x10021367, // mov rb13,unif +++/* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000218] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000220] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000228] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000230] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000238] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000240] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x +++/* [0x00000248] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base ++ // ::mc_filter_uv ++-/* [0x00000260] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000268] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000270] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000278] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000280] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000288] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000290] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000298] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000002a0] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000002a8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000002b0] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000002b8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002c0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002c8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002d0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002d8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002e0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002e8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000002f0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000002f8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000300] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000308] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000310] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000318] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000320] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000340] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000350] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000358] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000360] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000368] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000370] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00000378] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000380] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00000388] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000390] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 ++-/* [0x00000398] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000003a0] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 ++-/* [0x000003a8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000003b0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000250] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000258] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000260] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000268] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000270] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000278] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000280] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000288] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000290] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000298] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000002a0] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x000002a8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002b0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002b8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002c0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002c8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002d0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002d8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000002e0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000002e8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002f0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002f8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000300] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000330] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000340] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000348] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000350] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000358] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000360] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000368] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000370] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00000378] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000380] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 +++/* [0x00000388] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000390] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 +++/* [0x00000398] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000003a0] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x000003b8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003c0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x000003c8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x000003d0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003d8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003e0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003e8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003f0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003f8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000400] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000408] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000410] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000418] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000420] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000428] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000430] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000438] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000440] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000448] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000450] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000458] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000460] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000468] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000470] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000478] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000480] */ 0x00000020, 0xe0021327, // mov rb12,32 ++-/* [0x00000488] */ 0x00000006, 0xe0021367, // mov rb13,6 ++-/* [0x00000490] */ 0x00000001, 0xe00213a7, // mov rb14,1 ++-/* [0x00000498] */ 0x00000000, 0xe00213e7, // mov rb15,0 ++-/* [0x000004a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000004a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000004b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000004b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000004c0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000004c8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000004d0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000004d8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 ++-/* [0x000004e0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 ++-/* [0x000004e8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 ++-/* [0x000004f0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004f8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 ++-/* [0x00000500] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000508] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000510] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000518] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000520] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000528] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000530] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000538] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000540] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000548] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000550] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000003a8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003b0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x000003b8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x000003c0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003c8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003d0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003d8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003e0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000400] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000408] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000410] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000420] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000428] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000430] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000438] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000440] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000448] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000450] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000458] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000460] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000468] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000470] */ 0x00000020, 0xe0021327, // mov rb12,32 +++/* [0x00000478] */ 0x00000006, 0xe0021367, // mov rb13,6 +++/* [0x00000480] */ 0x00000001, 0xe00213a7, // mov rb14,1 +++/* [0x00000488] */ 0x00000000, 0xe00213e7, // mov rb15,0 +++/* [0x00000490] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000498] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000004a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000004a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000004b0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000004b8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000004c0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000004c8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x000004d0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x000004d8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x000004e0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004e8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x000004f0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000004f8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000500] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000508] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000510] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000518] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000520] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000528] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000530] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000538] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000540] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x00000558] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000560] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000568] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000570] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000578] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000580] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000588] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000590] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000598] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x000005a0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000005a8] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x000005b0] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x000005b8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000005c0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005c8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000005d0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000005d8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000005e0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000005e8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000005f0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000005f8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000600] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000608] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000610] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000618] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000620] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000628] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000630] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000638] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000640] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000648] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000650] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000658] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000660] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000668] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000670] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000678] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000548] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000550] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000558] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000560] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000568] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000570] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000578] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000580] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000588] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000590] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000598] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x000005a0] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x000005a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000005b0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000005c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000005c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000005d0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000005d8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000005e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000005e8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000005f0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000005f8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000600] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000608] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000610] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000618] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000620] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000628] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000630] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000638] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000640] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000648] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000650] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000658] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000668] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000680] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000688] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000690] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000698] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000006a0] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000006a8] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000006b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000006b8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000006c0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x000006c8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x000006d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000006d8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000006e0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000006e8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000006f0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000006f8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000700] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000708] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000710] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000718] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000720] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000728] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000730] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000738] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000740] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000748] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000750] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000758] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000760] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000768] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000770] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 ++-/* [0x00000778] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000780] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++-/* [0x00000788] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000790] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000798] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x000007a0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000007a8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000007b0] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000670] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000678] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x00000680] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000688] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000690] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000698] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000006a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000006a8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000006b0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000006b8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x000006c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000006c8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000006d0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000006d8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000006e0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000006e8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000006f0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000006f8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000700] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000708] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000710] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000718] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000720] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000728] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000730] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000738] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000740] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000748] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000750] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000758] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000760] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x00000768] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000770] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x00000778] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000780] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000788] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000790] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000798] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007a0] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x000007b8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000007c0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000007c8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000007d0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000007d8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000007e0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007e8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007f0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007f8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_base_next, r0, ~3 ++-/* [0x00000800] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000808] */ 0x0c9d3e80, 0x100206a7, // add ra_x2_base_next, rb_x_base_next, r2 ++-/* [0x00000810] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000818] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000820] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000828] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000830] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000838] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000840] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000848] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000850] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000858] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000860] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000868] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000870] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000878] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000880] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000888] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000890] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000898] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000008b8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008d0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x000008d8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008e0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008e8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008f0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008f8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000007a8] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000007b0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000007b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000007c0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000007c8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000007d0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007d8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007e0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007e8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x000007f0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000007f8] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000800] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000808] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000810] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000818] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000820] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000828] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000830] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000838] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000840] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000848] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000850] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000858] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000860] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000868] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000870] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000878] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000880] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000888] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000890] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000898] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000008a8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008c0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x000008c8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008d0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008d8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008e0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008e8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x00000900] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000908] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x_base, rb_x_base_next ; ldtmu0 ++-/* [0x00000910] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_x2_base, ra_x2_base_next ; mov rb31, r3 ++-/* [0x00000918] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000920] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000928] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000930] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000938] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000940] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x_base, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000948] */ 0x0c627c80, 0x10020e27, // add t0s, ra_x2_base, r2 ++-/* [0x00000950] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000958] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000960] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000968] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000970] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000978] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000980] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000988] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000990] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000998] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x000009a0] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x000009a8] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009b0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000009b8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x000009c0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000009c8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000009d0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000009d8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000009e0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000009e8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009f0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009f8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x00000a00] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x00000a08] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000a10] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000a18] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000a20] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a28] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a30] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a38] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a40] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000a48] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a50] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a58] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a60] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a68] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a70] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008f0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000008f8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x00000900] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000908] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000910] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000918] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000920] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000928] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000930] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x00000938] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x00000940] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000948] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000950] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000958] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000960] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000968] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000970] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000978] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000980] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000988] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000990] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000998] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009a0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000009a8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000009b0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000009b8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000009c0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000009c8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000009d0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000009d8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009e0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009e8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000009f0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x000009f8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000a00] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000a08] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000a10] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a18] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a20] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a28] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a30] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000a38] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a40] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a48] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a50] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a58] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a60] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a78] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a80] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a68] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a70] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a98] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000aa0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000ab0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a98] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000aa0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000aa8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000ac0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ab0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000ab8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ac0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000ad0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ad8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ae0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ad8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ae0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000b08] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b10] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b18] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b20] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b28] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000b30] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b10] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b18] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000b20] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_setup +++/* [0x00000b28] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000b30] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000b38] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000b40] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000b48] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000b50] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000b58] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x00000b60] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000b68] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000b70] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000b78] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000b80] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000b88] */ 0x8c9e7452, 0x10025e18, // add t0s, r2, r1 ; mov ra_frame_base, r2 +++/* [0x00000b90] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000b98] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000ba0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000ba8] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000bb0] */ 0x0c9c13c0, 0xd0020567, // add ra_y2, r1, 1 +++/* [0x00000bb8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000bc0] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000bc8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000bd0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000bd8] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000be0] */ 0x8c9e7452, 0x10025e19, // add t0s, r2, r1 ; mov ra_frame_base2, r2 +++/* [0x00000be8] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00000bf0] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x00000bf8] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x00000c00] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000c08] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x00000c10] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x00000c18] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x00000c20] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000c28] */ 0x00000040, 0xe00207a7, // mov ra30, 64 +++/* [0x00000c30] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000c38] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000c40] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000c48] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00000c50] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x00000c58] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x00000c60] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x00000c68] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x00000c70] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x00000c78] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x00000c80] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x00000c88] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000c90] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000c98] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000ca0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000ca8] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000cb0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000cb8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000cc0] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000cc8] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000cd0] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000cd8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000ce0] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000ce8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000cf0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000cf8] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000d00] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000d08] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000d10] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000d18] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000d20] */ 0x15827d80, 0x10021327, // mov rb12,unif +++/* [0x00000d28] */ 0x15827d80, 0x10021367, // mov rb13,unif +++/* [0x00000d30] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000d38] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000d40] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000d48] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000d50] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000d58] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base +++/* [0x00000d60] */ 0x13540dc0, 0xd0020867, // max r1, ra_y2, 0 +++/* [0x00000d68] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000d70] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000d78] */ 0x0c541dc0, 0xd0020567, // add ra_y2, ra_y2, 1 +++/* [0x00000d80] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000d88] */ 0x0c667380, 0x10020e27, // add t0s, r1, ra_frame_base2 +++// ::mc_filter +++/* [0x00000d90] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000d98] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000da0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000da8] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next +++/* [0x00000db0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000db8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000dc0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000dc8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000dd0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000dd8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000de0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 +++/* [0x00000de8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000df0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif +++/* [0x00000df8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000e00] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000e08] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 +++/* [0x00000e10] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000e18] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 +++/* [0x00000e20] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000e28] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000e30] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e38] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000e40] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000e48] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000e50] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000e58] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000e60] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000e68] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000e70] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000e78] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000e80] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e88] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000e90] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000e98] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ea0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ea8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000eb0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000eb8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ec0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ec8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ed0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000ed8] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000ee0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ee8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ef0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ef8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000f00] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000f08] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f10] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f18] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f20] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 +++/* [0x00000f28] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000f30] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000f38] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000f40] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000f48] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00000f50] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :yloop +++/* [0x00000f58] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000f60] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++/* [0x00000f68] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000f70] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000f78] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00000f80] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00000f88] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000f90] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000f98] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000fa0] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x00000fa8] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x00000fb0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000fb8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x00000fc0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++/* [0x00000fc8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000fd0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000fd8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000fe0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000fe8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000ff0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000ff8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00001000] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00001008] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001010] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001018] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001020] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001028] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001030] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001038] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001040] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001048] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001050] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001058] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 +++/* [0x00001060] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001068] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001070] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001078] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001080] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001088] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001090] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00001098] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000010a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000010a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000010b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000010b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000010c0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000010c8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000010d0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000010d8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000010e0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000010e8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000010f0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000010f8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x00001100] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x00001108] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x00001110] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001118] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x00001120] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001128] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001130] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001138] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001140] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001148] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_filter_b +++/* [0x00001150] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001158] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00001160] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00001168] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next +++/* [0x00001170] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00001178] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00001180] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00001188] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00001190] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00001198] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000011a0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 +++/* [0x000011a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000011b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif +++/* [0x000011b8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x000011c0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x000011c8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 +++/* [0x000011d0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000011d8] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 +++/* [0x000011e0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000011e8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000011f0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000011f8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00001200] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00001208] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00001210] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00001218] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00001220] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00001228] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001230] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001238] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00001240] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001248] */ 0x00000001, 0xe0020867, // mov r1, 1 +++/* [0x00001250] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001258] */ 0x409f3001, 0xd00049e0, // nop ; mul24 r0, r0 << 13, r1 << 13 +++/* [0x00001260] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001268] */ 0x409f2001, 0xd00049e0, // nop ; mul24 r0, r0 << 14, r1 << 14 +++/* [0x00001270] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001278] */ 0x409f1001, 0xd00049e0, // nop ; mul24 r0, r0 << 15, r1 << 15 +++/* [0x00001280] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001288] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00001290] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001298] */ 0x409f7001, 0xd00049e0, // nop ; mul24 r0, r0 << 9, r1 << 9 +++/* [0x000012a0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012a8] */ 0x409f6001, 0xd00049e0, // nop ; mul24 r0, r0 << 10, r1 << 10 +++/* [0x000012b0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012b8] */ 0x409f5001, 0xd00049e0, // nop ; mul24 r0, r0 << 11, r1 << 11 +++/* [0x000012c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012c8] */ 0x409f4001, 0xd00049e0, // nop ; mul24 r0, r0 << 12, r1 << 12 +++/* [0x000012d0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000012d8] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x000012e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00001300] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001308] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001310] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001318] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001320] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 +++/* [0x00001328] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001330] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001338] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00001340] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001348] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00001350] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++// :yloopb +++/* [0x00001358] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001360] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++/* [0x00001368] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00001370] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001378] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00001380] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00001388] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001390] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00001398] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000013a0] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x000013a8] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x000013b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000013b8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x000013c0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++/* [0x000013c8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000013d0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000013d8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000013e0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000013e8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000013f0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000013f8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00001400] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00001408] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001410] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001418] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001420] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001428] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001430] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001438] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001440] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001448] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001450] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001458] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 +++/* [0x00001460] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001468] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001470] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001478] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001480] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001488] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001490] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00001498] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000014a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000014a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000014b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000014b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000014c0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000014c8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000014d0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000014d8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000014e0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000014e8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000014f0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000014f8] */ 0x4053800e, 0xd00049e1, // nop ; mul24 r1, r1 << 8, ra20 << 8 +++/* [0x00001500] */ 0x4c78e38f, 0x10024860, // add r1, r1, ra30 ; mul24 r0, r1, rb14 +++/* [0x00001508] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00001510] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001518] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00001520] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001528] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001530] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001538] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001540] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001548] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++// ::mc_interrupt_exit12 +++/* [0x00001550] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001558] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001560] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001568] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001570] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001578] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001580] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001588] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001590] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001598] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015a0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000015d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000015d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000015e0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index cec9901..3fa8531 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,11 +4,15 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 152) ++-#define mc_filter_uv_b0 (rpi_shader + 342) ++-#define mc_filter_uv_b (rpi_shader + 494) ++-#define mc_exit (rpi_shader + 670) ++-#define mc_interrupt_exit8 (rpi_shader + 688) ++-#define mc_end (rpi_shader + 718) +++#define mc_filter_uv (rpi_shader + 148) +++#define mc_filter_uv_b0 (rpi_shader + 338) +++#define mc_filter_uv_b (rpi_shader + 490) +++#define mc_exit (rpi_shader + 666) +++#define mc_interrupt_exit8 (rpi_shader + 684) +++#define mc_setup (rpi_shader + 714) +++#define mc_filter (rpi_shader + 868) +++#define mc_filter_b (rpi_shader + 1108) +++#define mc_interrupt_exit12 (rpi_shader + 1364) +++#define mc_end (rpi_shader + 1402) ++ ++ #endif ++diff --git a/libavcodec/rpi_user_vcsm.h b/libavcodec/rpi_user_vcsm.h ++index fbebbbe..95e6de1 100644 ++--- a/libavcodec/rpi_user_vcsm.h +++++ b/libavcodec/rpi_user_vcsm.h ++@@ -418,6 +418,28 @@ int vcsm_unlock_hdl( unsigned int handle ); ++ */ ++ int vcsm_unlock_hdl_sp( unsigned int handle, int cache_no_flush ); ++ +++/* Clean and/or invalidate the memory associated with this user opaque handle +++** +++** Returns: non-zero on error +++** +++** structure contains a list of flush/invalidate commands. Commands are: +++** 0: nop +++** 1: invalidate given physical range in L2 +++** 2: clean given physical range in L2 +++** 3: clean+invalidate all of L1 +++** 4: flush all of L2 and all of L1 +++*/ +++struct vcsm_user_clean_invalid_s { +++ struct { +++ unsigned int cmd; +++ unsigned int addr; +++ unsigned int size; +++ } s[8]; +++}; +++ +++int vcsm_clean_invalid( unsigned int handle, struct vcsm_user_clean_invalid_s *s ); +++ +++ ++ #ifdef __cplusplus ++ } ++ #endif ++-- ++2.5.0 ++ ++ ++From b3e42f057641ce7855d21f7c45f533df8c6c462d Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 20 May 2015 21:12:55 +0100 ++Subject: [PATCH 43/68] Added multi mailbox - not working ++ ++--- ++ libavcodec/hevc.c | 40 ++++++++++++++++++++++++++++--- ++ libavcodec/rpi_mailbox.c | 47 +++++++++++++++++++++++++++++++++++++ ++ libavcodec/rpi_mailbox.h | 5 ++++ ++ libavcodec/rpi_qpu.c | 61 ++++++++++++++++++++++++++++++++++++++++++++---- ++ libavcodec/rpi_qpu.h | 2 ++ ++ 5 files changed, 147 insertions(+), 8 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 01898fd..2ca783a 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -47,6 +47,11 @@ ++ //#define EARLY_MALLOC ++ // Move Inter prediction into separate pass ++ #define RPI_INTER +++ +++ #ifdef RPI_INTER_QPU +++ // Define RPI_MULTI_MAILBOX to use the updated mailbox that can launch both QPU and VPU +++ #define RPI_MULTI_MAILBOX +++ #endif ++ #endif ++ ++ // #define DISABLE_MC ++@@ -2832,10 +2837,14 @@ static void rpi_inter_clear(HEVCContext *s) ++ static void rpi_execute_inter_qpu(HEVCContext *s) ++ { ++ int k; +++ int i; ++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr.vc; ++- ++- if (s->sh.slice_type == I_SLICE) ++- return; +++ if (s->sh.slice_type == I_SLICE) { +++#ifdef RPI_MULTI_MAILBOX +++ rpi_execute_transform(s); +++ return; +++#endif +++ } ++ for(k=0;k<8;k++) { ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++@@ -2845,6 +2854,22 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ ++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++ +++#ifdef RPI_MULTI_MAILBOX +++ gpu_cache_flush(&s->coeffs_buf_accelerated); +++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, +++ qpu_get_fn(QPU_MC_SETUP_UV), +++ (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[2 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[3 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) +++ ); +++ for(i=0;i<4;i++) +++ s->num_coeffs[i] = 0; +++#else ++ qpu_run_shader8(qpu_get_fn(QPU_MC_SETUP_UV), ++ (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++ (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++@@ -2855,6 +2880,7 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) ++ ); +++#endif ++ } ++ #endif ++ ++@@ -2934,6 +2960,12 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { ++ // Transform all blocks ++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); +++#ifdef RPI_MULTI_MAILBOX +++ // Kick off inter prediction on QPUs +++ rpi_execute_inter_qpu(s); +++ // Perform luma inter prediction +++ rpi_execute_inter_cmds(s); +++#else ++ rpi_execute_transform(s); ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); ++@@ -2941,6 +2973,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ // Kick off inter prediction on QPUs ++ rpi_execute_inter_qpu(s); ++ #endif +++#endif +++ ++ // Wait for transform completion ++ vpu_wait(s->vpu_id); ++ ++diff --git a/libavcodec/rpi_mailbox.c b/libavcodec/rpi_mailbox.c ++index 77a56dd..3904efc 100644 ++--- a/libavcodec/rpi_mailbox.c +++++ b/libavcodec/rpi_mailbox.c ++@@ -276,6 +276,53 @@ unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigne ++ return p[5]; ++ } ++ +++void execute_multi(int file_desc, +++ unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout, +++ unsigned num_qpus_2, unsigned control_2, unsigned noflush_2, unsigned timeout_2, +++ unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, +++ unsigned code_2, unsigned r0_2, unsigned r1_2, unsigned r2_2, unsigned r3_2, unsigned r4_2, unsigned r5_2) { +++ int i=0; +++ unsigned p[32]; +++ +++ p[i++] = 0; // size +++ p[i++] = 0x00000000; // process request +++ p[i++] = 0x30018; // (the tag id) +++ p[i++] = 88; // (size of the buffer) +++ p[i++] = 88; // (size of the data) +++ +++ p[i++] = num_qpus; +++ p[i++] = control; +++ p[i++] = noflush; +++ p[i++] = timeout; // ms +++ +++ p[i++] = num_qpus_2; +++ p[i++] = control_2; +++ p[i++] = noflush_2; +++ p[i++] = timeout_2; // ms +++ +++ p[i++] = code; +++ p[i++] = r0; +++ p[i++] = r1; +++ p[i++] = r2; +++ p[i++] = r3; +++ p[i++] = r4; +++ p[i++] = r5; +++ +++ p[i++] = code_2; +++ p[i++] = r0_2; +++ p[i++] = r1_2; +++ p[i++] = r2_2; +++ p[i++] = r3_2; +++ p[i++] = r4_2; +++ p[i++] = r5_2; +++ +++ p[i++] = 0x00000000; // end tag +++ p[0] = i*sizeof *p; // actual size +++ +++ mbox_property(file_desc, p); +++ return; +++} +++ ++ int mbox_open() { ++ int file_desc; ++ ++diff --git a/libavcodec/rpi_mailbox.h b/libavcodec/rpi_mailbox.h ++index c264d2e..5898102 100644 ++--- a/libavcodec/rpi_mailbox.h +++++ b/libavcodec/rpi_mailbox.h ++@@ -15,6 +15,11 @@ extern void unmapmem(void *addr, unsigned size); ++ ++ extern unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); ++ extern unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout); +++extern void execute_multi(int file_desc, +++ unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout, +++ unsigned num_qpus_2, unsigned control_2, unsigned noflush_2, unsigned timeout_2, +++ unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, +++ unsigned code_2, unsigned r0_2, unsigned r1_2, unsigned r2_2, unsigned r3_2, unsigned r4_2, unsigned r5_2); ++ extern unsigned qpu_enable(int file_desc, unsigned enable); ++ ++ #endif ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index fd8a276..feb3284 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -123,7 +123,7 @@ static pthread_cond_t post_cond_head = PTHREAD_COND_INITIALIZER; ++ static pthread_cond_t post_cond_tail = PTHREAD_COND_INITIALIZER; ++ static pthread_mutex_t post_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++-static int vpu_cmds[MAXCMDS][8]; +++static int vpu_cmds[MAXCMDS][16]; ++ static volatile int vpu_async_tail=0; // Contains the number of posted jobs ++ static volatile int vpu_async_head=0; ++ #endif ++@@ -346,6 +346,7 @@ unsigned int vpu_get_constants(void) { ++ static void *vpu_start(void *arg) { ++ while(1) { ++ int *p; +++ int qpu_code; ++ pthread_mutex_lock(&post_mutex); ++ while( vpu_async_tail - vpu_async_head <= 0) ++ { ++@@ -358,12 +359,25 @@ static void *vpu_start(void *arg) { ++ if (p[6] == -1) { ++ break; // Last job ++ } ++- if (p[7]) { +++ qpu_code = p[7]; +++ //if (p[7]) { ++ //GPU_MEM_PTR_T *buf = (GPU_MEM_PTR_T *)p[7]; ++ //gpu_cache_flush(buf); ++- } ++- vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); +++ //} +++ if (!qpu_code) { +++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); +++ } else { +++ int i; +++ for(i=0;i<8;i++) { +++ gpu->mail[i*2] = p[8+i]; +++ gpu->mail[i*2 + 1] = qpu_code; +++ } ++ +++ execute_multi(gpu->mb,8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, +++ 0, 0, 0, 0, +++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 +++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 +++ } ++ pthread_mutex_lock(&post_mutex); ++ vpu_async_head++; ++ pthread_cond_broadcast(&post_cond_head); ++@@ -400,7 +414,43 @@ int vpu_post_code(unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned ++ p[4] = r3; ++ p[5] = r4; ++ p[6] = r5; ++- p[7] = (int) buf; +++ p[7] = 0; +++ if (num<=1) +++ pthread_cond_broadcast(&post_cond_tail); // Otherwise the vpu thread must already be awake +++ pthread_mutex_unlock(&post_mutex); +++ return id; +++ } +++} +++ +++int vpu_qpu_post_code(unsigned vpu_code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, +++ int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8) +++{ +++ +++ pthread_mutex_lock(&post_mutex); +++ { +++ int id = vpu_async_tail++; +++ int *p = vpu_cmds[id%MAXCMDS]; +++ int num = vpu_async_tail - vpu_async_head; +++ if (num>MAXCMDS) { +++ printf("Too many commands submitted\n"); +++ exit(-1); +++ } +++ p[0] = vpu_code; +++ p[1] = r0; +++ p[2] = r1; +++ p[3] = r2; +++ p[4] = r3; +++ p[5] = r4; +++ p[6] = r5; +++ p[7] = qpu_code; +++ p[8 ] = unifs1; +++ p[9 ] = unifs2; +++ p[10] = unifs3; +++ p[11] = unifs4; +++ p[12] = unifs5; +++ p[13] = unifs6; +++ p[14] = unifs7; +++ p[15] = unifs8; ++ if (num<=1) ++ pthread_cond_broadcast(&post_cond_tail); // Otherwise the vpu thread must already be awake ++ pthread_mutex_unlock(&post_mutex); ++@@ -966,6 +1016,7 @@ void rpi_do_block(const uint8_t *in_buffer_vc, int src_pitch, uint8_t *dst_vc, i ++ } ++ ++ +++ ++ #endif ++ ++ #endif // RPI ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 88965e5..2f08f03 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -41,6 +41,8 @@ extern unsigned int vpu_get_fn(void); ++ extern unsigned int vpu_get_constants(void); ++ extern unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); ++ extern int vpu_post_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, GPU_MEM_PTR_T *buf); +++int vpu_qpu_post_code(unsigned vpu_code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, +++ int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); ++ extern void vpu_wait( int id); ++ ++ // Simple test of shader code ++-- ++2.5.0 ++ ++ ++From 71b8a1d77652d1cc298df2a1441ef3c913c2926b Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 21 May 2015 16:50:02 +0100 ++Subject: [PATCH 44/68] Pass qpu number in as uniform ++ ++--- ++ libavcodec/hevc.c | 2 +- ++ libavcodec/rpi_shader.c | 1288 ++++++++++++++++++++++---------------------- ++ libavcodec/rpi_shader.h | 20 +- ++ libavcodec/rpi_shader.qasm | 10 +- ++ 4 files changed, 657 insertions(+), 663 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 2ca783a..9605459 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -2823,6 +2823,7 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = pic_height; ++ *s->u_mvs[i]++ = s->frame->linesize[1]; ++ *s->u_mvs[i]++ = s->frame->linesize[2]; +++ *s->u_mvs[i]++ = i; ++ if (weight_flag) { ++ *s->u_mvs[i]++ = 1 << (s->sh.chroma_log2_weight_denom + 6 - 1); ++ *s->u_mvs[i]++ = s->sh.chroma_log2_weight_denom + 6; ++@@ -2830,7 +2831,6 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = 1 << 5; ++ *s->u_mvs[i]++ = 6; ++ } ++- s->u_mvs[i] += 1; // Padding words ++ } ++ } ++ ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index 9c30e32..a0f0282 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -48,8 +48,8 @@ unsigned int rpi_shader[] = { ++ /* [0x000000b8] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++ /* [0x000000c0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++ /* [0x000000c8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000d0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x000000d8] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x000000d0] */ 0x15827d80, 0x100208e7, // mov r3, unif +++/* [0x000000d8] */ 0x119c17c0, 0xd00208a7, // shl r2, r3, 1 ++ /* [0x000000e0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++ /* [0x000000e8] */ 0x159e7480, 0x10020867, // mov r1, r2 ++ /* [0x000000f0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++@@ -60,669 +60,669 @@ unsigned int rpi_shader[] = { ++ /* [0x00000118] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++ /* [0x00000120] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++ /* [0x00000128] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000130] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000138] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-/* [0x00000140] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000148] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000150] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000158] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000160] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000168] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000170] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000178] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000180] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000188] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 ++-/* [0x00000190] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++-/* [0x00000198] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 ++-/* [0x000001a0] */ 0x15427d80, 0x10020827, // mov r0, ra_x ++-/* [0x000001a8] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000001b0] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base ++-/* [0x000001b8] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000001c0] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001c8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000001d0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001d8] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x, r0 ++-/* [0x000001e0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001e8] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x000001f0] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 ++-/* [0x000001f8] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x00000200] */ 0x15827d80, 0x10021327, // mov rb12,unif ++-/* [0x00000208] */ 0x15827d80, 0x10021367, // mov rb13,unif ++-/* [0x00000210] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000218] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000220] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000228] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000230] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000238] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000240] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x ++-/* [0x00000248] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base +++/* [0x00000130] */ 0x119c17c0, 0xd00208a7, // shl r2, r3, 1 +++/* [0x00000138] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000140] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000148] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000150] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000158] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000160] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000168] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000170] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000178] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000180] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 +++/* [0x00000188] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) +++/* [0x00000190] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 +++/* [0x00000198] */ 0x15427d80, 0x10020827, // mov r0, ra_x +++/* [0x000001a0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000001a8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base +++/* [0x000001b0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000001b8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000001c0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000001c8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000001d0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x, r0 +++/* [0x000001d8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x000001e0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x000001e8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 +++/* [0x000001f0] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 +++/* [0x000001f8] */ 0x15827d80, 0x10021327, // mov rb12,unif +++/* [0x00000200] */ 0x15827d80, 0x10021367, // mov rb13,unif +++/* [0x00000208] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000210] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000218] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000220] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000228] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000230] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x +++/* [0x00000238] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base ++ // ::mc_filter_uv ++-/* [0x00000250] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000258] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000260] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000268] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000270] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000278] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000280] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000288] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000290] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x00000298] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000002a0] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x000002a8] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002b0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002b8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002c0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002c8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002d0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002d8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000002e0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000002e8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002f0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000002f8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000300] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000308] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000310] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000318] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000320] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000330] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000340] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000348] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000350] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000358] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000360] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00000368] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000370] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00000378] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000380] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 ++-/* [0x00000388] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000390] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 ++-/* [0x00000398] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000003a0] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000240] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000248] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000250] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000258] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000260] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000268] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000270] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000278] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000280] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000288] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000290] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000298] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000002a0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000002a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002b0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000002b8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000002c0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000002c8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000002d0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000002d8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000002f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000002f8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000300] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000308] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000310] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000318] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000320] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000328] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000330] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000338] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000340] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000348] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000350] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000358] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000360] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00000368] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000370] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 +++/* [0x00000378] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000380] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 +++/* [0x00000388] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000390] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x000003a8] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003b0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x000003b8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x000003c0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003c8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003d0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003d8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003e0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003e8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003f0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x000003f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000400] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000408] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000410] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000418] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000420] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000428] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000430] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000438] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000440] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000448] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000450] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000458] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000460] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000468] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000470] */ 0x00000020, 0xe0021327, // mov rb12,32 ++-/* [0x00000478] */ 0x00000006, 0xe0021367, // mov rb13,6 ++-/* [0x00000480] */ 0x00000001, 0xe00213a7, // mov rb14,1 ++-/* [0x00000488] */ 0x00000000, 0xe00213e7, // mov rb15,0 ++-/* [0x00000490] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000498] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000004a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000004a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000004b0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000004b8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000004c0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000004c8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 ++-/* [0x000004d0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 ++-/* [0x000004d8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 ++-/* [0x000004e0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004e8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 ++-/* [0x000004f0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000004f8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000500] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000508] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000510] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000518] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000520] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000528] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000530] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000538] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000540] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000398] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000003a0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x000003a8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x000003b0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000003b8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000003c0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000003c8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000003d0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003d8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000003e0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x000003e8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003f0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003f8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000400] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000408] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000410] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000418] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000420] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000428] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000430] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000438] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000440] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000448] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000450] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000458] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000460] */ 0x00000020, 0xe0021327, // mov rb12,32 +++/* [0x00000468] */ 0x00000006, 0xe0021367, // mov rb13,6 +++/* [0x00000470] */ 0x00000001, 0xe00213a7, // mov rb14,1 +++/* [0x00000478] */ 0x00000000, 0xe00213e7, // mov rb15,0 +++/* [0x00000480] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000488] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000490] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000498] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000004a0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000004a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000004b0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000004b8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x000004c0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x000004c8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x000004d0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x000004d8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x000004e0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000004e8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000004f0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000004f8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000500] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000508] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000510] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000518] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000520] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000528] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000530] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x00000548] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000550] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000558] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000560] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000568] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000570] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000578] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000580] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000588] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x00000590] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000598] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x000005a0] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x000005a8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000005b0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005b8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000005c0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000005c8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000005d0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000005d8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000005e0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000005e8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000005f0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000005f8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000600] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000608] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000610] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000618] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000620] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000628] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000630] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000638] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000640] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000648] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000650] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000658] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000660] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000668] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000538] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000540] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000548] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000550] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000558] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000560] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000568] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000570] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000578] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000580] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000588] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000590] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000598] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000005a0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005a8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000005b0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000005b8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000005c0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000005c8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000005d0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000005d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000005e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000005e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000005f0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005f8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000600] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000608] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000610] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000618] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000620] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000628] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000630] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000638] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000640] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000648] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000650] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000658] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000670] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000678] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x00000680] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00000688] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000690] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000698] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000006a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000006a8] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000006b0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x000006b8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x000006c0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000006c8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000006d0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000006d8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000006e0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000006e8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000006f0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000006f8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000700] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000708] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000710] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000718] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000720] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000728] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000730] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000738] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000740] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000748] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000750] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000758] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000760] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 ++-/* [0x00000768] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000770] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++-/* [0x00000778] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000780] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000788] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000790] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000798] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000007a0] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000660] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000668] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x00000670] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000678] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000680] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000688] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000690] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000698] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000006a0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000006a8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x000006b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000006b8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000006c0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000006c8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000006d0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000006d8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000006e0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000006e8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000006f0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000006f8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000700] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000708] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000710] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000718] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000720] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000728] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000730] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000738] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000740] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000748] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000750] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x00000758] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000760] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x00000768] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000770] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000778] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000780] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000788] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000790] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x000007a8] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000007b0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000007b8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000007c0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000007c8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000007d0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007d8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007e0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007e8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x000007f0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000007f8] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x00000800] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000808] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000810] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000818] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000820] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000828] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000830] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000838] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000840] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000848] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000850] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000858] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000860] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000868] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000870] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000878] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000880] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000888] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000890] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000898] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x000008a8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008c0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x000008c8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008d0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008d8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008e0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008e8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000798] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000007a0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000007a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000007b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x000007b8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x000007c0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x000007c8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x000007d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x000007d8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x000007e0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x000007e8] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x000007f0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000007f8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000800] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000808] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000810] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000818] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000820] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000828] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000830] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000838] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x00000840] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x00000848] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x00000850] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000858] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000860] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000868] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000870] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000878] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000880] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000888] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000890] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000898] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008a8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000008b0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x000008b8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008c0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000008c8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000008d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008d8] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000008f0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000008f8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x00000900] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00000908] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000910] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000918] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000920] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000928] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000930] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000938] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x00000940] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000948] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000950] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000958] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000960] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000968] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000970] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000978] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000980] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000988] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000990] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000998] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009a0] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x000009a8] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x000009b0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000009b8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000009c0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000009c8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000009d0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000009d8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009e0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009e8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000009f0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x000009f8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x00000a00] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000a08] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000a10] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a18] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a20] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a28] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a30] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000a38] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a40] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a48] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a50] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a58] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a60] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000008e0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x000008e8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++/* [0x000008f0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x000008f8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000900] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000908] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000910] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000918] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000920] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x00000928] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 +++/* [0x00000930] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000938] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000940] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000948] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000950] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000958] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000960] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000968] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000970] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000978] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000980] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000988] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000990] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000998] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000009a0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000009a8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000009b0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000009b8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000009c0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000009c8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000009d0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000009d8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000009e0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x000009e8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x000009f0] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009f8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00000a00] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000a08] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000a10] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00000a18] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a20] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000a28] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x00000a30] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a38] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000a40] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x00000a48] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00000a50] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a68] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a70] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a58] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a60] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a68] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a70] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a88] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a90] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a98] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000aa0] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000aa8] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a88] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a90] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a98] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000ab0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000aa0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000aa8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ab0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000ab8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00000ac0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ac8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ad0] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000ac8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000ad0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000ad8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000ae0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b00] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b08] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b10] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b18] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000b20] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000b00] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000b08] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000b10] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_setup ++-/* [0x00000b28] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000b30] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000b38] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000b40] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000b48] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000b50] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000b58] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x00000b60] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000b68] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 ++-/* [0x00000b70] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000b78] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000b80] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000b88] */ 0x8c9e7452, 0x10025e18, // add t0s, r2, r1 ; mov ra_frame_base, r2 ++-/* [0x00000b90] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000b98] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000ba0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000ba8] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x00000bb0] */ 0x0c9c13c0, 0xd0020567, // add ra_y2, r1, 1 ++-/* [0x00000bb8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000bc0] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 ++-/* [0x00000bc8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000bd0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000bd8] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000be0] */ 0x8c9e7452, 0x10025e19, // add t0s, r2, r1 ; mov ra_frame_base2, r2 ++-/* [0x00000be8] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++-/* [0x00000bf0] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++-/* [0x00000bf8] */ 0x15827d80, 0x10021427, // mov rb16, unif ++-/* [0x00000c00] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000c08] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++-/* [0x00000c10] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++-/* [0x00000c18] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x00000c20] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x00000c28] */ 0x00000040, 0xe00207a7, // mov ra30, 64 ++-/* [0x00000c30] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000c38] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000c40] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x00000c48] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x00000c50] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x00000c58] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x00000c60] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x00000c68] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x00000c70] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x00000c78] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x00000c80] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x00000c88] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000c90] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000c98] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000ca0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000ca8] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000cb0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000cb8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000cc0] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000cc8] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000cd0] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000cd8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000ce0] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000ce8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000cf0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000cf8] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000d00] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000d08] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000d10] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000d18] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000d20] */ 0x15827d80, 0x10021327, // mov rb12,unif ++-/* [0x00000d28] */ 0x15827d80, 0x10021367, // mov rb13,unif ++-/* [0x00000d30] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000d38] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000d40] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000d48] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000d50] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000d58] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base ++-/* [0x00000d60] */ 0x13540dc0, 0xd0020867, // max r1, ra_y2, 0 ++-/* [0x00000d68] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000d70] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000d78] */ 0x0c541dc0, 0xd0020567, // add ra_y2, ra_y2, 1 ++-/* [0x00000d80] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000d88] */ 0x0c667380, 0x10020e27, // add t0s, r1, ra_frame_base2 +++/* [0x00000b18] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000b20] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000b28] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000b30] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000b38] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000b40] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000b48] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x00000b50] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000b58] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000b60] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000b68] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000b70] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000b78] */ 0x8c9e7452, 0x10025e18, // add t0s, r2, r1 ; mov ra_frame_base, r2 +++/* [0x00000b80] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000b88] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000b90] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000b98] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000ba0] */ 0x0c9c13c0, 0xd0020567, // add ra_y2, r1, 1 +++/* [0x00000ba8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000bb0] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000bb8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000bc0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000bc8] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000bd0] */ 0x8c9e7452, 0x10025e19, // add t0s, r2, r1 ; mov ra_frame_base2, r2 +++/* [0x00000bd8] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 +++/* [0x00000be0] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 +++/* [0x00000be8] */ 0x15827d80, 0x10021427, // mov rb16, unif +++/* [0x00000bf0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000bf8] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x00000c00] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x00000c08] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x00000c10] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000c18] */ 0x00000040, 0xe00207a7, // mov ra30, 64 +++/* [0x00000c20] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000c28] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000c30] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000c38] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00000c40] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x00000c48] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x00000c50] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x00000c58] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x00000c60] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x00000c68] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x00000c70] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x00000c78] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000c80] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000c88] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000c90] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000c98] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000ca0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000ca8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000cb0] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000cb8] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000cc0] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000cc8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000cd0] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000cd8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000ce0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000ce8] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000cf0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000cf8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000d00] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000d08] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000d10] */ 0x15827d80, 0x10021327, // mov rb12,unif +++/* [0x00000d18] */ 0x15827d80, 0x10021367, // mov rb13,unif +++/* [0x00000d20] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000d28] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000d30] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000d38] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000d40] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000d48] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base +++/* [0x00000d50] */ 0x13540dc0, 0xd0020867, // max r1, ra_y2, 0 +++/* [0x00000d58] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000d60] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000d68] */ 0x0c541dc0, 0xd0020567, // add ra_y2, ra_y2, 1 +++/* [0x00000d70] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000d78] */ 0x0c667380, 0x10020e27, // add t0s, r1, ra_frame_base2 ++ // ::mc_filter ++-/* [0x00000d90] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000d98] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000da0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000da8] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next ++-/* [0x00000db0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000db8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000dc0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000dc8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000dd0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000dd8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000de0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 ++-/* [0x00000de8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000df0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif ++-/* [0x00000df8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000e00] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x00000e08] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 ++-/* [0x00000e10] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000e18] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 ++-/* [0x00000e20] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000e28] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000e30] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000e38] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000e40] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000e48] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000e50] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000e58] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000e60] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000e68] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000e70] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000e78] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000e80] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000e88] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000e90] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000e98] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ea0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ea8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000eb0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000eb8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ec0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ec8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ed0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000ed8] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000ee0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ee8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ef0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ef8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000f00] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000f08] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f10] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f18] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f20] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 ++-/* [0x00000f28] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000f30] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000f38] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00000f40] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000f48] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00000f50] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000d80] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000d88] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000d90] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000d98] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next +++/* [0x00000da0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000da8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000db0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000db8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000dc0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000dc8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000dd0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 +++/* [0x00000dd8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000de0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif +++/* [0x00000de8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000df0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000df8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 +++/* [0x00000e00] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000e08] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 +++/* [0x00000e10] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000e18] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000e20] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e28] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000e30] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000e38] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000e40] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000e48] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000e50] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000e58] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000e60] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000e68] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000e70] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e78] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000e80] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000e88] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000e90] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000e98] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000ea0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000ea8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000eb0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000eb8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ec0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x00000ec8] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000ed0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ed8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ee0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ee8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x00000ef0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000ef8] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f00] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f08] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000f10] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 +++/* [0x00000f18] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000f20] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif +++/* [0x00000f28] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000f30] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000f38] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00000f40] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :yloop ++-/* [0x00000f58] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000f60] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-/* [0x00000f68] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00000f70] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000f78] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 ++-/* [0x00000f80] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next ++-/* [0x00000f88] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000f90] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000f98] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000fa0] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000fa8] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 ++-/* [0x00000fb0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000fb8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-/* [0x00000fc0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000fc8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000fd0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000fd8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000fe0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000fe8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000ff0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000ff8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00001000] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00001008] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00001010] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00001018] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00001020] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00001028] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00001030] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00001038] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00001040] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001048] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001050] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001058] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 ++-/* [0x00001060] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001068] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001070] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001078] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001080] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloop ++-/* [0x00001088] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001090] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00001098] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000010a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000010a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000010b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000010b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000010c0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-/* [0x000010c8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-/* [0x000010d0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-/* [0x000010d8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 ++-/* [0x000010e0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000010e8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000010f0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000010f8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 ++-/* [0x00001100] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 ++-/* [0x00001108] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 ++-/* [0x00001110] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloop ++-/* [0x00001118] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 ++-/* [0x00001120] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00001128] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00001130] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001138] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001140] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001148] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000f48] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000f50] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++/* [0x00000f58] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000f60] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000f68] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00000f70] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00000f78] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000f80] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000f88] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000f90] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x00000f98] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x00000fa0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000fa8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x00000fb0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++/* [0x00000fb8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000fc0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000fc8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000fd0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000fd8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000fe0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000fe8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000ff0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000ff8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001000] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001008] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001010] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001018] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001020] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001028] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001030] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001038] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001040] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001048] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 +++/* [0x00001050] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001058] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001060] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001068] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001070] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001078] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001080] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00001088] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00001090] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00001098] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000010a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000010a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000010b0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000010b8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000010c0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000010c8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000010d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000010d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000010e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000010e8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x000010f0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x000010f8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x00001100] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001108] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x00001110] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001118] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001120] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001128] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001130] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001138] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_b ++-/* [0x00001150] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001158] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00001160] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00001168] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next ++-/* [0x00001170] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00001178] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00001180] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00001188] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00001190] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00001198] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000011a0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 ++-/* [0x000011a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000011b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif ++-/* [0x000011b8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x000011c0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x000011c8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 ++-/* [0x000011d0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000011d8] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 ++-/* [0x000011e0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000011e8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000011f0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000011f8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00001200] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00001208] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00001210] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00001218] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00001220] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00001228] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001230] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001238] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00001240] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001248] */ 0x00000001, 0xe0020867, // mov r1, 1 ++-/* [0x00001250] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001258] */ 0x409f3001, 0xd00049e0, // nop ; mul24 r0, r0 << 13, r1 << 13 ++-/* [0x00001260] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001268] */ 0x409f2001, 0xd00049e0, // nop ; mul24 r0, r0 << 14, r1 << 14 ++-/* [0x00001270] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001278] */ 0x409f1001, 0xd00049e0, // nop ; mul24 r0, r0 << 15, r1 << 15 ++-/* [0x00001280] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001288] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00001290] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001298] */ 0x409f7001, 0xd00049e0, // nop ; mul24 r0, r0 << 9, r1 << 9 ++-/* [0x000012a0] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012a8] */ 0x409f6001, 0xd00049e0, // nop ; mul24 r0, r0 << 10, r1 << 10 ++-/* [0x000012b0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012b8] */ 0x409f5001, 0xd00049e0, // nop ; mul24 r0, r0 << 11, r1 << 11 ++-/* [0x000012c0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012c8] */ 0x409f4001, 0xd00049e0, // nop ; mul24 r0, r0 << 12, r1 << 12 ++-/* [0x000012d0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000012d8] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x000012e0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012e8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012f0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012f8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00001300] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001308] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001310] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001318] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001320] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 ++-/* [0x00001328] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001330] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001338] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00001340] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001348] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00001350] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00001140] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00001148] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00001150] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00001158] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next +++/* [0x00001160] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00001168] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00001170] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00001178] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00001180] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00001188] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00001190] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 +++/* [0x00001198] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000011a0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif +++/* [0x000011a8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x000011b0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x000011b8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 +++/* [0x000011c0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x000011c8] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 +++/* [0x000011d0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000011d8] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000011e0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000011e8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000011f0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000011f8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00001200] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00001208] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00001210] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00001218] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00001220] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001228] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00001230] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001238] */ 0x00000001, 0xe0020867, // mov r1, 1 +++/* [0x00001240] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001248] */ 0x409f3001, 0xd00049e0, // nop ; mul24 r0, r0 << 13, r1 << 13 +++/* [0x00001250] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001258] */ 0x409f2001, 0xd00049e0, // nop ; mul24 r0, r0 << 14, r1 << 14 +++/* [0x00001260] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001268] */ 0x409f1001, 0xd00049e0, // nop ; mul24 r0, r0 << 15, r1 << 15 +++/* [0x00001270] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001278] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00001280] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001288] */ 0x409f7001, 0xd00049e0, // nop ; mul24 r0, r0 << 9, r1 << 9 +++/* [0x00001290] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001298] */ 0x409f6001, 0xd00049e0, // nop ; mul24 r0, r0 << 10, r1 << 10 +++/* [0x000012a0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012a8] */ 0x409f5001, 0xd00049e0, // nop ; mul24 r0, r0 << 11, r1 << 11 +++/* [0x000012b0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012b8] */ 0x409f4001, 0xd00049e0, // nop ; mul24 r0, r0 << 12, r1 << 12 +++/* [0x000012c0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif +++/* [0x000012c8] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x000012d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000012e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif +++/* [0x000012f0] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x000012f8] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001300] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001308] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00001310] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 +++/* [0x00001318] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001320] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif +++/* [0x00001328] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00001330] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00001338] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 +++/* [0x00001340] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :yloopb ++-/* [0x00001358] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00001360] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-/* [0x00001368] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00001370] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00001378] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 ++-/* [0x00001380] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next ++-/* [0x00001388] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00001390] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00001398] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000013a0] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x000013a8] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 ++-/* [0x000013b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000013b8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-/* [0x000013c0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 ++-/* [0x000013c8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000013d0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000013d8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000013e0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000013e8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000013f0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000013f8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00001400] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00001408] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00001410] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00001418] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00001420] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00001428] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00001430] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00001438] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00001440] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001448] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001450] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001458] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 ++-/* [0x00001460] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001468] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001470] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001478] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001480] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloopb ++-/* [0x00001488] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001490] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00001498] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000014a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000014a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000014b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000014b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000014c0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-/* [0x000014c8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-/* [0x000014d0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-/* [0x000014d8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 ++-/* [0x000014e0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000014e8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000014f0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000014f8] */ 0x4053800e, 0xd00049e1, // nop ; mul24 r1, r1 << 8, ra20 << 8 ++-/* [0x00001500] */ 0x4c78e38f, 0x10024860, // add r1, r1, ra30 ; mul24 r0, r1, rb14 ++-/* [0x00001508] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x00001510] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloopb ++-/* [0x00001518] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00001520] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00001528] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00001530] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001538] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001540] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001548] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00001348] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001350] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 +++/* [0x00001358] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00001360] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001368] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00001370] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00001378] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001380] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00001388] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00001390] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x00001398] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x000013a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000013a8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x000013b0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++/* [0x000013b8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000013c0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000013c8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000013d0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000013d8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000013e0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000013e8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000013f0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000013f8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001400] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001408] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001410] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001418] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001420] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001428] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001430] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001438] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001440] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001448] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 +++/* [0x00001450] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001458] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001460] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001468] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001470] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001478] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001480] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00001488] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00001490] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00001498] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000014a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000014a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000014b0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000014b8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000014c0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000014c8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000014d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000014d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000014e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x000014e8] */ 0x4053800e, 0xd00049e1, // nop ; mul24 r1, r1 << 8, ra20 << 8 +++/* [0x000014f0] */ 0x4c78e38f, 0x10024860, // add r1, r1, ra30 ; mul24 r0, r1, rb14 +++/* [0x000014f8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00001500] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001508] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x00001510] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001518] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001520] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001528] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001530] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001538] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_interrupt_exit12 ++-/* [0x00001550] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001540] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001548] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001550] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001558] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++ /* [0x00001560] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001568] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001570] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001568] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001570] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001578] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001580] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x00001588] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++@@ -732,11 +732,9 @@ unsigned int rpi_shader[] = { ++ /* [0x000015a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000015b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++ /* [0x000015b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015d0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000015d8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000015e0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x000015c0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000015c8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000015d0] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 3fa8531..6e552d9 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,15 +4,15 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 148) ++-#define mc_filter_uv_b0 (rpi_shader + 338) ++-#define mc_filter_uv_b (rpi_shader + 490) ++-#define mc_exit (rpi_shader + 666) ++-#define mc_interrupt_exit8 (rpi_shader + 684) ++-#define mc_setup (rpi_shader + 714) ++-#define mc_filter (rpi_shader + 868) ++-#define mc_filter_b (rpi_shader + 1108) ++-#define mc_interrupt_exit12 (rpi_shader + 1364) ++-#define mc_end (rpi_shader + 1402) +++#define mc_filter_uv (rpi_shader + 144) +++#define mc_filter_uv_b0 (rpi_shader + 334) +++#define mc_filter_uv_b (rpi_shader + 486) +++#define mc_exit (rpi_shader + 662) +++#define mc_interrupt_exit8 (rpi_shader + 680) +++#define mc_setup (rpi_shader + 710) +++#define mc_filter (rpi_shader + 864) +++#define mc_filter_b (rpi_shader + 1104) +++#define mc_interrupt_exit12 (rpi_shader + 1360) +++#define mc_end (rpi_shader + 1398) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 9cfc0d9..a0b8e5a 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -133,8 +133,8 @@ mov ra14, 0 ++ mov ra15, 0 ++ ++ # Compute part of VPM to use for DMA output ++-mov r2, qpu_num ++-shl r2, r2, 1 # Convert QPU numbers to be even (this means we can only use 8 QPUs, but is necessary as we need to save 16bit intermediate results) +++mov r3, unif +++shl r2, r3, 1 # Convert QPU numbers to be even (this means we can only use 8 QPUs, but is necessary as we need to save 16bit intermediate results) ++ and r2, r2, 15 ++ mov r1, r2 ++ asr r1, r1, 2 ++@@ -147,8 +147,7 @@ shl r0, r0, 5 ++ add rb27, r0, r1 ++ ++ # Compute part of VPM to save data into ++-mov r2, qpu_num # qpu_num = abcd ++-shl r2, r2, 1 +++shl r2, r3, 1 ++ and r2, r2, 15 # r2 = bcd0 ++ mov r1, r2 # r1 = bcd0 ++ asr r1, r1, 2 # r1 = bc ++@@ -181,9 +180,6 @@ add t0s, r2, r1 ++ mov rb12,unif # offset before shift ++ mov rb13,unif # offset after shift ++ ++-# Dump padding words ++-mov r0, unif ++- ++ # submit texture requests for second line ++ max r1, ra_y, 0 ++ min r1, r1, rb_frame_height_minus_1 ++-- ++2.5.0 ++ ++ ++From f9771d28dc02023eb3d051fb9104b6e051f0a58b Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Sat, 23 May 2015 13:20:21 +0100 ++Subject: [PATCH 45/68] Add new cache flushing routine ++ ++--- ++ libavcodec/hevc.c | 8 +++-- ++ libavcodec/hevc_filter.c | 39 ++++++++++----------- ++ libavcodec/rpi_qpu.c | 17 +++++++-- ++ libavcodec/rpi_qpu.h | 2 ++ ++ libavcodec/rpi_user_vcsm.h | 86 ++++++++++++++++++++++++++-------------------- ++ 5 files changed, 91 insertions(+), 61 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 9605459..52293bf 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3564,9 +3564,13 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) ++ } ++ ++ fail: ++- if (s->ref && s->threads_type == FF_THREAD_FRAME) +++ if (s->ref && s->threads_type == FF_THREAD_FRAME) { +++#ifdef RPI_INTER_QPU +++ void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n); +++ ff_hevc_flush_chroma(s, &s->ref->tf, s->ps.sps->height); +++#endif ++ ff_thread_report_progress(&s->ref->tf, INT_MAX, 0); ++- +++ } ++ return ret; ++ } ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 186317a..ec84e8a 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -883,36 +883,35 @@ static int ff_hevc_buf_base(AVBufferRef *bref) { ++ return p->vc & 0x3fffffff; ++ } ++ ++-static void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n) +++void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n); +++void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n) ++ { ++ if (s->enable_rpi && !( s->nal_unit_type == NAL_TRAIL_N || ++ s->nal_unit_type == NAL_TSA_N || ++ s->nal_unit_type == NAL_STSA_N || ++ s->nal_unit_type == NAL_RADL_N || ++ s->nal_unit_type == NAL_RASL_N )) { ++-#define RPI_FAST_CACHEFLUSH ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++- int curr_y = f->progress->data[0]; +++ int curr_y = ((int *)f->progress->data)[0]; +++ int curr_uv = curr_y >> s->ps.sps->vshift[1]; +++ int n_uv = n >> s->ps.sps->vshift[1]; ++ int sz,base; ++- if (curr_y < 0) curr_y = 0; ++- if (n<=curr_y) return; // Should not happen ++- sz = s->frame->linesize[1] * (n-curr_y); ++- base = s->frame->linesize[1] * curr_y; ++- iocache.s[0].cmd = 3; // Flush L1 cache ++- iocache.s[0].addr = 0; ++- iocache.s[0].size = 0; ++- ++- iocache.s[1].cmd = 2; ++- iocache.s[1].addr = ff_hevc_buf_base(s->frame->buf[1]) + base; +++ if (curr_uv < 0) curr_uv = 0; +++ if (n_uv<=curr_uv) { assert(0); return; } // Should not happen +++ sz = s->frame->linesize[1] * (n_uv-curr_uv); +++ base = s->frame->linesize[1] * curr_uv; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(s->frame->buf[1]); +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = p->arm + base; +++ iocache.s[0].size = sz; +++ p = av_buffer_pool_opaque(s->frame->buf[2]); +++ iocache.s[1].handle = p->vcsm_handle; +++ iocache.s[1].cmd = 3; // clean+invalidate +++ iocache.s[1].addr = p->arm + base; ++ iocache.s[1].size = sz; ++- ++- iocache.s[2].cmd = 2; ++- iocache.s[2].addr = ff_hevc_buf_base(s->frame->buf[2]) + base; ++- iocache.s[2].size = sz; ++- ++- vcsm_clean_invalid( gpu_get_mailbox(), &iocache ); ++- +++ vcsm_clean_invalid( &iocache ); ++ #else ++ flush_buffer(s->frame->buf[1]); ++ flush_buffer(s->frame->buf[2]); ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index feb3284..aa65a77 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -211,6 +211,7 @@ static void gpu_unlock(void) { ++ } ++ ++ static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb) { +++ p->numbytes = numbytes; ++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); ++ assert(p->vcsm_handle); ++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); ++@@ -243,13 +244,25 @@ int gpu_get_mailbox(void) ++ return gpu->mb; ++ } ++ +++// Call this to clean and invalidate a region of memory ++ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ { ++- void *tmp = vcsm_lock(p->vcsm_handle); ++- vcsm_unlock_ptr(tmp); +++#define RPI_FAST_CACHEFLUSH +++#ifdef RPI_FAST_CACHEFLUSH +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = p->arm; +++ iocache.s[0].size = p->numbytes; +++ vcsm_clean_invalid( &iocache ); +++#else +++ void *tmp = vcsm_lock(p->vcsm_handle); +++ vcsm_unlock_ptr(tmp); +++#endif ++ } ++ ++ static int gpu_malloc_cached_internal(int numbytes, GPU_MEM_PTR_T *p) { +++ p->numbytes = numbytes; ++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST, (char *)"Video Frame" ); ++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC, (char *)"Video Frame" ); ++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 2f08f03..0565a60 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -1,6 +1,8 @@ ++ #ifndef RPI_QPU_H ++ #define RPI_QPU_H ++ +++#define RPI_FAST_CACHEFLUSH +++ ++ typedef struct gpu_mem_ptr_s { ++ unsigned char *arm; // Pointer to memory mapped on ARM side ++ int vc_handle; // Videocore handle of relocatable memory ++diff --git a/libavcodec/rpi_user_vcsm.h b/libavcodec/rpi_user_vcsm.h ++index 95e6de1..db41a4d 100644 ++--- a/libavcodec/rpi_user_vcsm.h +++++ b/libavcodec/rpi_user_vcsm.h ++@@ -1,29 +1,41 @@ ++-/* ++-Copyright (c) 2012, Broadcom Europe Ltd ++-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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE ++-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. ++-*/ +++/***************************************************************************** +++* Copyright 2001 - 2011 Broadcom Corporation. All rights reserved. +++* +++* This program is the proprietary software of Broadcom Corporation and/or +++* its licensors, and may only be used, duplicated, modified or distributed +++* pursuant to the terms and conditions of a separate, written license +++* agreement executed between you and Broadcom (an "Authorized License"). +++* Except as set forth in an Authorized License, Broadcom grants no license +++* (express or implied), right to use, or waiver of any kind with respect to +++* the Software, and Broadcom expressly reserves all rights in and to the +++* Software and all intellectual property rights therein. IF YOU HAVE NO +++* AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY +++* WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE ALL USE OF +++* THE SOFTWARE. +++* +++* Except as expressly set forth in the Authorized License, +++* 1. This program, including its structure, sequence and organization, +++* constitutes the valuable trade secrets of Broadcom, and you shall use +++* all reasonable efforts to protect the confidentiality thereof, and to +++* use this information only in connection with your use of Broadcom +++* integrated circuit products. +++* 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +++* AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR +++* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH +++* RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL +++* IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS +++* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, +++* QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. YOU +++* ASSUME THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE. +++* 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS +++* LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, +++* OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO +++* YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN +++* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS +++* OF THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER +++* IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF +++* ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. +++*****************************************************************************/ ++ ++ #ifndef __USER_VCSM__H__INCLUDED__ ++ #define __USER_VCSM__H__INCLUDED__ ++@@ -424,21 +436,21 @@ int vcsm_unlock_hdl_sp( unsigned int handle, int cache_no_flush ); ++ ** ++ ** structure contains a list of flush/invalidate commands. Commands are: ++ ** 0: nop ++-** 1: invalidate given physical range in L2 ++-** 2: clean given physical range in L2 ++-** 3: clean+invalidate all of L1 ++-** 4: flush all of L2 and all of L1 +++** 1: invalidate given virtual range in L1/L2 +++** 2: clean given virtual range in L1/L2 +++** 3: clean+invalidate given virtual range in L1/L2 +++** 4: flush all L1/L2 ++ */ ++ struct vcsm_user_clean_invalid_s { ++- struct { ++- unsigned int cmd; ++- unsigned int addr; ++- unsigned int size; ++- } s[8]; +++ struct { +++ unsigned int cmd; +++ unsigned int handle; +++ unsigned int addr; +++ unsigned int size; +++ } s[8]; ++ }; ++ ++-int vcsm_clean_invalid( unsigned int handle, struct vcsm_user_clean_invalid_s *s ); ++- +++int vcsm_clean_invalid( struct vcsm_user_clean_invalid_s *s ); ++ ++ #ifdef __cplusplus ++ } ++-- ++2.5.0 ++ ++ ++From b91ec9a8437e65c59dddf323de875e62ee227403 Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Sat, 23 May 2015 21:10:10 +0100 ++Subject: [PATCH 46/68] Fix multi mailbox extra transform call ++ ++--- ++ libavcodec/hevc.c | 2 ++ ++ 1 file changed, 2 insertions(+) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 52293bf..fa6d788 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3013,7 +3013,9 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI_INTER_QPU ++ rpi_execute_inter_qpu(s); ++ #endif +++#ifndef RPI_MULTI_MAILBOX ++ rpi_execute_transform(s); +++#endif ++ rpi_execute_inter_cmds(s); ++ vpu_wait(s->vpu_id); ++ rpi_execute_pred_cmds(s); ++-- ++2.5.0 ++ ++ ++From 03bbcfdda2db59b9603018b1cf0ca340d9ffc088 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 27 May 2015 16:44:29 +0100 ++Subject: [PATCH 47/68] Added support for running luma prediction on QPUs ++ ++--- ++ libavcodec/hevc.c | 237 +++++++- ++ libavcodec/hevc.h | 26 +- ++ libavcodec/hevc_filter.c | 23 +- ++ libavcodec/rpi_qpu.c | 156 ++++-- ++ libavcodec/rpi_qpu.h | 8 +- ++ libavcodec/rpi_shader.c | 1313 ++++++++++++++++++++++---------------------- ++ libavcodec/rpi_shader.h | 21 +- ++ libavcodec/rpi_shader.qasm | 883 ++++++++++++++--------------- ++ 8 files changed, 1464 insertions(+), 1203 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index fa6d788..11b9e60 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -52,6 +52,11 @@ ++ // Define RPI_MULTI_MAILBOX to use the updated mailbox that can launch both QPU and VPU ++ #define RPI_MULTI_MAILBOX ++ #endif +++ +++ // Define RPI_CACHE_UNIF_MVS to write motion vector uniform stream to cached memory +++ // RPI_CACHE_UNIF_MVS doesn't seem to make much difference, so left undefined. +++ +++ ++ #endif ++ ++ // #define DISABLE_MC ++@@ -74,6 +79,13 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++ +++// Split image of 2048 into parts 64 wide +++// So some QPUs will have 3 blocks of 64 to do, and others 2 blocks for an image 2048 wide with 32 blocks across +++// Each block of 64*64 +++// Smallest CTU size is 16x16, so smallest block is 8x8 +++// Corresponds to a total of 83kbytes over all 12 QPUs +++#define RPI_LUMA_COMMAND_WORDS 9 +++#define Y_COMMANDS_PER_QPU ((1+3*(64*64)/(8*8)) * RPI_LUMA_COMMAND_WORDS) ++ ++ #define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++@@ -2004,10 +2016,46 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref0->frame, +++#ifdef RPI_LUMA_QPU +++ if (s->enable_rpi) { +++ int reflist = 0; +++ const Mv *mv = ¤t_mv.mv[reflist]; +++ int mx = mv->x & 3; +++ int my = mv->y & 3; +++ int my_mx = (my<<8) + mx; +++ int my2_mx2_my_mx = (my_mx << 16) + my_mx; +++ int x1 = x0 + (mv->x >> 2); +++ int y1 = y0 + (mv->y >> 2); +++ int chan = x0>>6; // 64 wide blocks per QPU +++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || +++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); +++ uint32_t *y = s->y_mvs[chan % 12]; +++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go +++ for(int start_x=0;start_x < nPbW;start_x+=16) { +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ *y++ = ( (nPbW<16 ? nPbW : 16) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = my2_mx2_my_mx; +++ if (weight_flag) { +++ *y++ = (s->sh.luma_offset_l0[current_mv.ref_idx[reflist]] << 16) + (s->sh.luma_weight_l0[current_mv.ref_idx[reflist]] & 0xffff); +++ } else { +++ *y++ = 1; // Weight of 1 and offset of 0 +++ } +++ *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; +++ } +++ } +++ s->y_mvs[chan % 12] = y; +++ } else +++#endif +++ { +++ RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l0[current_mv.ref_idx[0]], ++ s->sh.luma_offset_l0[current_mv.ref_idx[0]]); +++ } ++ ++ if (s->ps.sps->chroma_format_idc) { ++ #ifdef RPI_INTER_QPU ++@@ -2067,10 +2115,47 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref1->frame, +++#ifdef RPI_LUMA_QPU +++ if (s->enable_rpi) { +++ int reflist = 1; +++ const Mv *mv = ¤t_mv.mv[reflist]; +++ int mx = mv->x & 3; +++ int my = mv->y & 3; +++ int my_mx = (my<<8) + mx; +++ int my2_mx2_my_mx = (my_mx << 16) + my_mx; +++ int x1 = x0 + (mv->x >> 2); +++ int y1 = y0 + (mv->y >> 2); +++ int chan = x0>>6; // 64 wide blocks per QPU +++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || +++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); +++ uint32_t *y = s->y_mvs[chan % 12]; +++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go +++ for(int start_x=0;start_x < nPbW;start_x+=16) { +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ *y++ = ( (nPbW<16 ? nPbW : 16) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = my2_mx2_my_mx; +++ if (weight_flag) { +++ *y++ = (s->sh.luma_offset_l0[current_mv.ref_idx[reflist]] << 16) + (s->sh.luma_weight_l0[current_mv.ref_idx[reflist]] & 0xffff); +++ } else { +++ *y++ = 1; // Weight of 1 and offset of 0 +++ } +++ *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; +++ } +++ } +++ s->y_mvs[chan % 12] = y; +++ } else +++#endif +++ +++ { +++ RPI_REDIRECT(luma_mc_uni)(s, dst0, s->frame->linesize[0], ref1->frame, ++ ¤t_mv.mv[1], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l1[current_mv.ref_idx[1]], ++ s->sh.luma_offset_l1[current_mv.ref_idx[1]]); +++ } ++ ++ if (s->ps.sps->chroma_format_idc) { ++ #ifdef RPI_INTER_QPU ++@@ -2104,8 +2189,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = rpi_filter_coefs[_mx][0]; ++ *u++ = rpi_filter_coefs[_my][0]; ++ if (weight_flag) { ++- *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[1]][0] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[1]][0] & 0xffff); ++- *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[1]][1] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[1]][1] & 0xffff); +++ *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[reflist]][0] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[reflist]][0] & 0xffff); +++ *u++ = (s->sh.chroma_offset_l0[current_mv.ref_idx[reflist]][1] << 16) + (s->sh.chroma_weight_l0[current_mv.ref_idx[reflist]][1] & 0xffff); ++ } else { ++ *u++ = 1; // Weight of 1 and offset of 0 ++ *u++ = 1; ++@@ -2132,9 +2217,44 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++- RPI_REDIRECT(luma_mc_bi)(s, dst0, s->frame->linesize[0], ref0->frame, +++#ifdef RPI_LUMA_QPU +++ if (s->enable_rpi) { +++ const Mv *mv = ¤t_mv.mv[0]; +++ int mx = mv->x & 3; +++ int my = mv->y & 3; +++ int my_mx = (my<<8) + mx; +++ const Mv *mv2 = ¤t_mv.mv[1]; +++ int mx2 = mv2->x & 3; +++ int my2 = mv2->y & 3; +++ int my2_mx2 = (my2<<8) + mx2; +++ int my2_mx2_my_mx = (my2_mx2 << 16) + my_mx; +++ int x1 = x0 + (mv->x >> 2); +++ int y1 = y0 + (mv->y >> 2); +++ int x2 = x0 + (mv2->x >> 2); +++ int y2 = y0 + (mv2->y >> 2); +++ int chan = x0>>6; // 64 wide blocks per QPU +++ uint32_t *y = s->y_mvs[chan % 12]; +++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go +++ for(int start_x=0;start_x < nPbW;start_x+=8) { // B blocks work 8 at a time +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y2 - 3 + start_y) << 16) + ( (x2 - 3 + start_x) & 0xffff); // Second fetch is for ref1 +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ *y++ = ( (nPbW<8 ? nPbW : 8) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = my2_mx2_my_mx; +++ *y++ = 1; // B frame weighted prediction not supported +++ *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter_b; +++ } +++ } +++ s->y_mvs[chan % 12] = y; +++ } else +++#endif +++ { +++ RPI_REDIRECT(luma_mc_bi)(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ ref1->frame, ¤t_mv.mv[1], ¤t_mv); +++ } ++ ++ if (s->ps.sps->chroma_format_idc) { ++ #ifdef RPI_INTER_QPU ++@@ -2823,7 +2943,6 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = pic_height; ++ *s->u_mvs[i]++ = s->frame->linesize[1]; ++ *s->u_mvs[i]++ = s->frame->linesize[2]; ++- *s->u_mvs[i]++ = i; ++ if (weight_flag) { ++ *s->u_mvs[i]++ = 1 << (s->sh.chroma_log2_weight_denom + 6 - 1); ++ *s->u_mvs[i]++ = s->sh.chroma_log2_weight_denom + 6; ++@@ -2831,7 +2950,31 @@ static void rpi_inter_clear(HEVCContext *s) ++ *s->u_mvs[i]++ = 1 << 5; ++ *s->u_mvs[i]++ = 6; ++ } +++ *s->u_mvs[i]++ = i; // Select section of VPM (avoid collisions with 3d unit) +++ } +++ +++#ifdef RPI_LUMA_QPU +++ for(i=0;i<12;i++) { +++ s->y_mvs[i] = s->y_mvs_base[i]; +++ *s->y_mvs[i]++ = 0; // y_x +++ *s->y_mvs[i]++ = 0; // ref_y_base +++ *s->y_mvs[i]++ = 0; // y2_x2 +++ *s->y_mvs[i]++ = 0; // ref_y2_base +++ *s->y_mvs[i]++ = (s->ps.sps->width << 16) + s->ps.sps->height; +++ *s->y_mvs[i]++ = s->frame->linesize[0]; // pitch +++ *s->y_mvs[i]++ = s->frame->linesize[0]; // dst_pitch +++ if (weight_flag) { +++ int offset = 1 << (s->sh.luma_log2_weight_denom + 6 - 1); +++ int shift = s->sh.luma_log2_weight_denom + 6; +++ *s->y_mvs[i]++ = (offset << 16) + shift; +++ } else { +++ int offset = 1 << 5; +++ int shift = 6; +++ *s->y_mvs[i]++ = (offset << 16) + shift; +++ } +++ *s->y_mvs[i]++ = 0; // Next kernel ++ } +++#endif ++ } ++ ++ static void rpi_execute_inter_qpu(HEVCContext *s) ++@@ -2839,6 +2982,9 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ int k; ++ int i; ++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr.vc; +++#ifdef RPI_LUMA_QPU +++ uint32_t *y_unif_vc = (uint32_t *)s->y_unif_mvs_ptr.vc; +++#endif ++ if (s->sh.slice_type == I_SLICE) { ++ #ifdef RPI_MULTI_MAILBOX ++ rpi_execute_transform(s); ++@@ -2854,8 +3000,23 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ ++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++ +++#ifdef RPI_LUMA_QPU +++ for(k=0;k<12;k++) { +++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+1] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for second request +++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_EXIT); // Add exit command +++ assert(s->y_mvs[k] - s->y_mvs_base[k] < Y_COMMANDS_PER_QPU); +++ } +++ s->y_mvs[12-1][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT12); // This QPU will signal interrupt when all others are done and have acquired a semaphore +++#endif +++ +++ ++ #ifdef RPI_MULTI_MAILBOX +++#ifdef RPI_CACHE_UNIF_MVS +++ gpu_cache_flush3(&s->coeffs_buf_accelerated,&s->y_unif_mvs_ptr, &s->unif_mvs_ptr); +++#else ++ gpu_cache_flush(&s->coeffs_buf_accelerated); +++#endif ++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++ (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++@@ -2865,7 +3026,27 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++ (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++ (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) +++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++#ifdef RPI_LUMA_QPU +++ qpu_get_fn(QPU_MC_SETUP), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[0 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[1 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[2 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[3 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[4 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[5 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[6 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[7 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[8 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[9 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[10 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[11 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)) +++#else +++ 0, +++ 0,0,0,0, +++ 0,0,0,0, +++ 0,0,0,0 +++#endif ++ ); ++ for(i=0;i<4;i++) ++ s->num_coeffs[i] = 0; ++@@ -2881,6 +3062,8 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) ++ ); ++ #endif +++ +++ ++ } ++ #endif ++ ++@@ -3568,8 +3751,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) ++ fail: ++ if (s->ref && s->threads_type == FF_THREAD_FRAME) { ++ #ifdef RPI_INTER_QPU ++- void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n); ++- ff_hevc_flush_chroma(s, &s->ref->tf, s->ps.sps->height); +++ ff_hevc_flush_buffer(s, &s->ref->tf, s->ps.sps->height); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, INT_MAX, 0); ++ } ++@@ -3756,7 +3938,6 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ ++ #ifdef RPI ++ av_freep(&s->unif_mv_cmds); ++- av_freep(&s->unif_xfm_cmds); ++ av_freep(&s->univ_pred_cmds); ++ ++ #ifdef RPI_INTER_QPU ++@@ -3765,7 +3946,12 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ s->unif_mvs = 0; ++ } ++ #endif ++- //gpu_free(&s->dummy); +++#ifdef RPI_LUMA_QPU +++ if (s->y_unif_mvs) { +++ gpu_free( &s->y_unif_mvs_ptr ); +++ s->y_unif_mvs = 0; +++ } +++#endif ++ ++ #ifdef EARLY_MALLOC ++ printf("hevc_decode_free\n"); ++@@ -3855,9 +4041,6 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->unif_mv_cmds = av_mallocz(sizeof(HEVCMvCmd)*RPI_MAX_MV_CMDS); ++ if (!s->unif_mv_cmds) ++ goto fail; ++- s->unif_xfm_cmds = av_mallocz(sizeof(HEVCXfmCmd)*RPI_MAX_XFM_CMDS); ++- if (!s->unif_xfm_cmds) ++- goto fail; ++ s->univ_pred_cmds = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); ++ if (!s->univ_pred_cmds) ++ goto fail; ++@@ -3871,7 +4054,11 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ { ++ int uv_commands_per_qpu = UV_COMMANDS_PER_QPU; ++ uint32_t *p; +++#ifdef RPI_CACHE_UNIF_MVS +++ gpu_malloc_cached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); +++#else ++ gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); +++#endif ++ s->unif_mvs = (uint32_t *) s->unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC ++ ++ // Set up initial locations for uniform streams ++@@ -3886,6 +4073,28 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ ++ } ++ #endif +++#ifdef RPI_LUMA_QPU +++ { +++ int y_commands_per_qpu = Y_COMMANDS_PER_QPU; +++ uint32_t *p; +++#ifdef RPI_CACHE_UNIF_MVS +++ gpu_malloc_cached( 12 * y_commands_per_qpu * sizeof(uint32_t), &s->y_unif_mvs_ptr ); +++#else +++ gpu_malloc_uncached( 12 * y_commands_per_qpu * sizeof(uint32_t), &s->y_unif_mvs_ptr ); +++#endif +++ s->y_unif_mvs = (uint32_t *) s->y_unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC +++ +++ // Set up initial locations for uniform streams +++ p = s->y_unif_mvs; +++ for(i = 0; i < 12; i++) { +++ s->y_mvs_base[i] = p; +++ p += y_commands_per_qpu; +++ } +++ s->mc_filter = qpu_get_fn(QPU_MC_FILTER); +++ s->mc_filter_b = qpu_get_fn(QPU_MC_FILTER_B); +++ +++ } +++#endif ++ //gpu_malloc_uncached(2048*64,&s->dummy); ++ ++ #ifdef EARLY_MALLOC ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index d33ab74..a3668a2 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -43,9 +43,13 @@ ++ #ifdef RPI ++ ++ #include "rpi_qpu.h" ++- // Use QPU for inter prediction +++ // Define RPI_INTER_QPU to use QPU for chroma inter prediction ++ #define RPI_INTER_QPU ++ +++ #ifdef RPI_INTER_QPU +++ // Define RPI_LUMA_QPU to also use QPU for luma inter prediction +++ #define RPI_LUMA_QPU +++ #endif ++ #endif ++ ++ #define MAX_DPB_SIZE 16 // A.4.1 ++@@ -835,7 +839,6 @@ typedef struct HEVCLocalContext { ++ ++ // Worst case is for 4:4:4 4x4 blocks with 64 high coding tree blocks, so 16 MV cmds per 4 pixels across for each colour plane, * 2 for bi ++ #define RPI_MAX_MV_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) ++-#define RPI_MAX_XFM_CMDS (16*3*(RPI_MAX_WIDTH/4)) ++ // Each block can have an intra prediction and a transform_add command ++ #define RPI_MAX_PRED_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) ++ // Worst case is 16x16 CTUs ++@@ -870,9 +873,6 @@ typedef struct HEVCMvCmd { ++ int8_t ref_idx[2]; ++ } HEVCMvCmd; ++ ++-// Command for transform to process a block of coefficients ++-typedef struct HEVCXfmCmd { ++-} HEVCXfmCmd; ++ ++ // Command for intra prediction and transform_add of predictions to coefficients ++ #define RPI_PRED_TRANSFORM_ADD 0 ++@@ -918,8 +918,7 @@ typedef struct HEVCContext { ++ ++ #ifdef RPI ++ int enable_rpi; ++- HEVCMvCmd *unif_mv_cmds; // TODO rename ++- HEVCXfmCmd *unif_xfm_cmds; +++ HEVCMvCmd *unif_mv_cmds; ++ HEVCPredCmd *univ_pred_cmds; ++ int buf_width; ++ GPU_MEM_PTR_T coeffs_buf_default; ++@@ -946,6 +945,15 @@ typedef struct HEVCContext { ++ uint32_t mc_filter_uv_b0; ++ uint32_t mc_filter_uv_b; ++ #endif +++#ifdef RPI_LUMA_QPU +++ GPU_MEM_PTR_T y_unif_mvs_ptr; +++ uint32_t *y_unif_mvs; // Base of memory for motion vector commands +++ uint32_t *y_mvs_base[12]; +++ uint32_t *y_mvs[12]; +++ // Function pointers +++ uint32_t mc_filter; +++ uint32_t mc_filter_b; +++#endif ++ ++ #endif ++ ++@@ -1192,6 +1200,10 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ int log2_trafo_size, enum ScanType scan_idx, ++ int c_idx); ++ +++#ifdef RPI_INTER_QPU +++extern void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n); +++#endif +++ ++ void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size); ++ ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index ec84e8a..11629e4 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -883,8 +883,7 @@ static int ff_hevc_buf_base(AVBufferRef *bref) { ++ return p->vc & 0x3fffffff; ++ } ++ ++-void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n); ++-void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n) +++void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ { ++ if (s->enable_rpi && !( s->nal_unit_type == NAL_TRAIL_N || ++ s->nal_unit_type == NAL_TSA_N || ++@@ -911,10 +910,24 @@ void ff_hevc_flush_chroma(HEVCContext *s, ThreadFrame *f, int n) ++ iocache.s[1].cmd = 3; // clean+invalidate ++ iocache.s[1].addr = p->arm + base; ++ iocache.s[1].size = sz; +++ +++#ifdef RPI_LUMA_QPU +++ p = av_buffer_pool_opaque(s->frame->buf[0]); +++ sz = s->frame->linesize[0] * (n-curr_y); +++ base = s->frame->linesize[0] * curr_y; +++ iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].cmd = 3; // clean+invalidate +++ iocache.s[2].addr = p->arm + base; +++ iocache.s[2].size = sz; +++#endif ++ vcsm_clean_invalid( &iocache ); ++ #else ++ flush_buffer(s->frame->buf[1]); ++ flush_buffer(s->frame->buf[2]); +++#ifdef RPI_LUMA_QPU +++ flush_buffer(s->frame->buf[1]); +++#endif +++ ++ #endif ++ //memcpy(s->dummy.arm,s->frame->data[0],2048*64); ++ //memcpy(s->dummy.arm,s->frame->data[1],1024*32); ++@@ -938,7 +951,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ sao_filter_CTB(s, x, y - ctb_size); ++ if (s->threads_type & FF_THREAD_FRAME ) { ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s,&s->ref->tf, y); +++ ff_hevc_flush_buffer(s,&s->ref->tf, y); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y, 0); ++ } ++@@ -947,7 +960,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ sao_filter_CTB(s, x , y); ++ if (s->threads_type & FF_THREAD_FRAME ) { ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s, &s->ref->tf, y + ctb_size); +++ ff_hevc_flush_buffer(s, &s->ref->tf, y + ctb_size); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0); ++ } ++@@ -957,7 +970,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ //int currh = s->ref->tf.progress->data[0]; ++ //if (((y + ctb_size)&63)==0) ++ #ifdef RPI_INTER_QPU ++- ff_hevc_flush_chroma(s, &s->ref->tf, y + ctb_size - 4); +++ ff_hevc_flush_buffer(s, &s->ref->tf, y + ctb_size - 4); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index aa65a77..e12304b 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -1,9 +1,11 @@ ++ #ifdef RPI ++ // This works better than the mmap in that the memory can be cached, but requires a kernel modification to enable the device. ++ // define RPI_TIME_TOTAL_QPU to print out how much time is spent in the QPU code ++-#define RPI_TIME_TOTAL_QPU +++//#define RPI_TIME_TOTAL_QPU ++ // define RPI_TIME_TOTAL_VPU to print out how much time is spent in the VPI code ++ //#define RPI_TIME_TOTAL_VPU +++// define RPI_TIME_TOTAL_POSTED to print out how much time is spent in the multi execute QPU/VPU combined +++//#define RPI_TIME_TOTAL_POSTED ++ // define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion ++ #define RPI_ASYNC ++ ++@@ -94,7 +96,8 @@ struct GPU ++ int open_count; // Number of allocated video buffers ++ int mb; // Mailbox handle ++ int vc; // Address in GPU memory ++- int mail[12]; // These are used to pass pairs of code/unifs to the QPUs +++ int mail[12*2]; // These are used to pass pairs of code/unifs to the QPUs for the first QPU task +++ int mail2[12*2]; // These are used to pass pairs of code/unifs to the QPUs for the second QPU task ++ }; ++ ++ // Stop more than one thread trying to allocate memory or use the processing resources at once ++@@ -102,7 +105,7 @@ static pthread_mutex_t gpu_mutex = PTHREAD_MUTEX_INITIALIZER; ++ static volatile struct GPU* gpu = NULL; ++ static GPU_MEM_PTR_T gpu_mem_ptr; ++ ++-#if defined(RPI_TIME_TOTAL_QPU) || defined(RPI_TIME_TOTAL_VPU) +++#if defined(RPI_TIME_TOTAL_QPU) || defined(RPI_TIME_TOTAL_VPU) || defined(RPI_TIME_TOTAL_POSTED) ++ static unsigned int Microseconds(void) { ++ struct timespec ts; ++ unsigned int x; ++@@ -123,7 +126,7 @@ static pthread_cond_t post_cond_head = PTHREAD_COND_INITIALIZER; ++ static pthread_cond_t post_cond_tail = PTHREAD_COND_INITIALIZER; ++ static pthread_mutex_t post_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++-static int vpu_cmds[MAXCMDS][16]; +++static int vpu_cmds[MAXCMDS][32]; ++ static volatile int vpu_async_tail=0; // Contains the number of posted jobs ++ static volatile int vpu_async_head=0; ++ #endif ++@@ -247,7 +250,6 @@ int gpu_get_mailbox(void) ++ // Call this to clean and invalidate a region of memory ++ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ { ++-#define RPI_FAST_CACHEFLUSH ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++ iocache.s[0].handle = p->vcsm_handle; ++@@ -261,6 +263,34 @@ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ #endif ++ } ++ +++void gpu_cache_flush3(GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2) +++{ +++#ifdef RPI_FAST_CACHEFLUSH +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ iocache.s[0].handle = p0->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = (int) p0->arm; +++ iocache.s[0].size = p0->numbytes; +++ iocache.s[1].handle = p1->vcsm_handle; +++ iocache.s[1].cmd = 3; // clean+invalidate +++ iocache.s[1].addr = (int) p1->arm; +++ iocache.s[1].size = p1->numbytes; +++ iocache.s[2].handle = p2->vcsm_handle; +++ iocache.s[2].cmd = 3; // clean+invalidate +++ iocache.s[2].addr = (int) p2->arm; +++ iocache.s[2].size = p2->numbytes; +++ vcsm_clean_invalid( &iocache ); +++#else +++ void *tmp; +++ tmp = vcsm_lock(p0->vcsm_handle); +++ vcsm_unlock_ptr(tmp); +++ tmp = vcsm_lock(p1->vcsm_handle); +++ vcsm_unlock_ptr(tmp); +++ tmp = vcsm_lock(p2->vcsm_handle); +++ vcsm_unlock_ptr(tmp); +++#endif +++} +++ ++ static int gpu_malloc_cached_internal(int numbytes, GPU_MEM_PTR_T *p) { ++ p->numbytes = numbytes; ++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST, (char *)"Video Frame" ); ++@@ -357,9 +387,19 @@ unsigned int vpu_get_constants(void) { ++ #ifdef RPI_ASYNC ++ ++ static void *vpu_start(void *arg) { +++#ifdef RPI_TIME_TOTAL_POSTED +++ int last_time=0; +++ long long on_time=0; +++ long long off_time=0; +++ int start_time; +++ int end_time; +++ int count=0; +++#endif ++ while(1) { +++ int i; ++ int *p; ++ int qpu_code; +++ int qpu_codeb; ++ pthread_mutex_lock(&post_mutex); ++ while( vpu_async_tail - vpu_async_head <= 0) ++ { ++@@ -373,24 +413,49 @@ static void *vpu_start(void *arg) { ++ break; // Last job ++ } ++ qpu_code = p[7]; +++ qpu_codeb = p[16]; ++ //if (p[7]) { ++ //GPU_MEM_PTR_T *buf = (GPU_MEM_PTR_T *)p[7]; ++ //gpu_cache_flush(buf); ++ //} +++ +++#ifdef RPI_TIME_TOTAL_POSTED +++ start_time = Microseconds(); +++ if (last_time==0) +++ last_time = start_time; +++ off_time += start_time-last_time; +++#endif +++ ++ if (!qpu_code) { ++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); ++ } else { ++- int i; ++ for(i=0;i<8;i++) { ++ gpu->mail[i*2] = p[8+i]; ++ gpu->mail[i*2 + 1] = qpu_code; ++ } ++- ++- execute_multi(gpu->mb,8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, ++- 0, 0, 0, 0, +++ for(i=0;i<12;i++) { +++ gpu->mail2[i*2] = p[17+i]; +++ gpu->mail2[i*2 + 1] = qpu_codeb; +++ } +++#if (0) +++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); +++ execute_qpu(gpu->mb,8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */); +++#else +++ execute_multi(gpu->mb, +++ 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, ++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 ++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 +++#endif ++ } +++#ifdef RPI_TIME_TOTAL_POSTED +++ end_time = Microseconds(); +++ last_time = end_time; +++ on_time += end_time - start_time; +++ count++; +++ if ((count&0x7f)==0) +++ printf("Posted %d On=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(off_time/1000)); +++#endif ++ pthread_mutex_lock(&post_mutex); ++ vpu_async_head++; ++ pthread_cond_broadcast(&post_cond_head); ++@@ -436,7 +501,9 @@ int vpu_post_code(unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned ++ } ++ ++ int vpu_qpu_post_code(unsigned vpu_code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, ++- int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8) +++ int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, +++ int qpu_codeb, int unifs1b, int unifs2b, int unifs3b, int unifs4b, int unifs5b, int unifs6b, int unifs7b, int unifs8b, int unifs9b, int unifs10b, int unifs11b, int unifs12b +++ ) ++ { ++ ++ pthread_mutex_lock(&post_mutex); ++@@ -464,6 +531,21 @@ int vpu_qpu_post_code(unsigned vpu_code, unsigned r0, unsigned r1, unsigned r2, ++ p[13] = unifs6; ++ p[14] = unifs7; ++ p[15] = unifs8; +++ +++ p[16] = qpu_codeb; +++ p[17] = unifs1b; +++ p[18] = unifs2b; +++ p[19] = unifs3b; +++ p[20] = unifs4b; +++ p[21] = unifs5b; +++ p[22] = unifs6b; +++ p[23] = unifs7b; +++ p[24] = unifs8b; +++ p[25] = unifs9b; +++ p[26] = unifs10b; +++ p[27] = unifs11b; +++ p[28] = unifs12b; +++ ++ if (num<=1) ++ pthread_cond_broadcast(&post_cond_tail); // Otherwise the vpu thread must already be awake ++ pthread_mutex_unlock(&post_mutex); ++@@ -544,27 +626,27 @@ void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int un ++ off_time += start_time-last_time; ++ #endif ++ for(i=0;imail[i*2 + 1] = code; +++ gpu->mail2[i*2 + 1] = code; ++ } ++ for(;imail[i*2 + 1] = code2; +++ gpu->mail2[i*2 + 1] = code2; ++ } ++- gpu->mail[0 ] = unifs1; ++- gpu->mail[2 ] = unifs2; ++- gpu->mail[4 ] = unifs3; ++- gpu->mail[6 ] = unifs4; ++- gpu->mail[8 ] = unifs5; ++- gpu->mail[10] = unifs6; ++- gpu->mail[12] = unifs7; ++- gpu->mail[14] = unifs8; ++- gpu->mail[16] = unifs9; ++- gpu->mail[18] = unifs10; ++- gpu->mail[20] = unifs11; ++- gpu->mail[22] = unifs12; +++ gpu->mail2[0 ] = unifs1; +++ gpu->mail2[2 ] = unifs2; +++ gpu->mail2[4 ] = unifs3; +++ gpu->mail2[6 ] = unifs4; +++ gpu->mail2[8 ] = unifs5; +++ gpu->mail2[10] = unifs6; +++ gpu->mail2[12] = unifs7; +++ gpu->mail2[14] = unifs8; +++ gpu->mail2[16] = unifs9; +++ gpu->mail2[18] = unifs10; +++ gpu->mail2[20] = unifs11; +++ gpu->mail2[22] = unifs12; ++ execute_qpu( ++ gpu->mb, ++ 12 /* Number of QPUs */, ++- gpu->vc + offsetof(struct GPU, mail), +++ gpu->vc + offsetof(struct GPU, mail2), ++ 1 /* no flush */, // Don't flush VPU L1 cache ++ 5000 /* timeout ms */); ++ #ifdef RPI_TIME_TOTAL_QPU ++@@ -635,21 +717,21 @@ unsigned int qpu_get_fn(int num) { ++ gpu_unlock(); ++ } ++ switch(num) { ++- //case QPU_MC_SETUP: ++- // fn = mc_setup; ++- // break; ++- //case QPU_MC_FILTER: ++- // fn = mc_filter; ++- // break; +++ case QPU_MC_SETUP: +++ fn = mc_setup; +++ break; +++ case QPU_MC_FILTER: +++ fn = mc_filter; +++ break; ++ case QPU_MC_EXIT: ++ fn = mc_exit; ++ break; ++- //case QPU_MC_INTERRUPT_EXIT: ++- // fn = mc_interrupt_exit; ++- // break; ++- //case QPU_MC_FILTER_B: ++- // fn = mc_filter_b; ++- // break; +++ case QPU_MC_INTERRUPT_EXIT12: +++ fn = mc_interrupt_exit12; +++ break; +++ case QPU_MC_FILTER_B: +++ fn = mc_filter_b; +++ break; ++ //case QPU_MC_FILTER_HONLY: ++ // fn = mc_filter_honly; ++ // break; ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 0565a60..81c2bb1 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -1,6 +1,7 @@ ++ #ifndef RPI_QPU_H ++ #define RPI_QPU_H ++ +++// Define RPI_FAST_CACHEFLUSH to use the VCSM cache flush code ++ #define RPI_FAST_CACHEFLUSH ++ ++ typedef struct gpu_mem_ptr_s { ++@@ -16,6 +17,7 @@ extern int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p); ++ extern int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p); ++ extern void gpu_free(GPU_MEM_PTR_T *p); ++ extern void gpu_cache_flush(GPU_MEM_PTR_T *p); +++extern void gpu_cache_flush3(GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2); ++ ++ // QPU specific functions ++ extern void qpu_run_shader8(int code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); ++@@ -26,7 +28,7 @@ enum { ++ QPU_MC_SETUP, ++ QPU_MC_FILTER, ++ QPU_MC_EXIT, ++- QPU_MC_INTERRUPT_EXIT, +++ QPU_MC_INTERRUPT_EXIT12, ++ QPU_MC_FILTER_B, ++ QPU_MC_FILTER_HONLY, ++ QPU_MC_SETUP_UV, ++@@ -44,7 +46,9 @@ extern unsigned int vpu_get_constants(void); ++ extern unsigned vpu_execute_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); ++ extern int vpu_post_code( unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, GPU_MEM_PTR_T *buf); ++ int vpu_qpu_post_code(unsigned vpu_code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5, ++- int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); +++ int qpu_code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, +++ int qpu_codeb, int unifs1b, int unifs2b, int unifs3b, int unifs4b, int unifs5b, int unifs6b, int unifs7b, int unifs8b, int unifs9b, int unifs10b, int unifs11b, int unifs12b +++ ); ++ extern void vpu_wait( int id); ++ ++ // Simple test of shader code ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index a0f0282..e86eb30 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -48,693 +48,674 @@ unsigned int rpi_shader[] = { ++ /* [0x000000b8] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++ /* [0x000000c0] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++ /* [0x000000c8] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x000000d0] */ 0x15827d80, 0x100208e7, // mov r3, unif ++-/* [0x000000d8] */ 0x119c17c0, 0xd00208a7, // shl r2, r3, 1 ++-/* [0x000000e0] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x000000e8] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x000000f0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x000000f8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000100] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000108] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000110] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000118] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000120] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000128] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000130] */ 0x119c17c0, 0xd00208a7, // shl r2, r3, 1 ++-/* [0x00000138] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 ++-/* [0x00000140] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000148] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000150] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000158] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000160] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000168] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000170] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000178] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000180] */ 0x0f9c11c0, 0xd0020827, // asr r0, r0, 1 ++-/* [0x00000188] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) ++-/* [0x00000190] */ 0x0c9e7040, 0x10021567, // add rb21, r0, r1 ++-/* [0x00000198] */ 0x15427d80, 0x10020827, // mov r0, ra_x ++-/* [0x000001a0] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y ++-/* [0x000001a8] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base ++-/* [0x000001b0] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset ++-/* [0x000001b8] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x000001c0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000001c8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000001d0] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x, r0 +++/* [0x000000d0] */ 0x15427d80, 0x10020827, // mov r0, ra_x +++/* [0x000000d8] */ 0x937401f6, 0xd0024821, // max r0, r0, 0; mov r1, ra_y +++/* [0x000000e0] */ 0x926191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, ra_frame_base +++/* [0x000000e8] */ 0x916431f6, 0xd00244e2, // shl ra_xshift_next, r0, 3 ; mov r2, ra_u2v_ref_offset +++/* [0x000000f0] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x000000f8] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000100] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000108] */ 0x939c03c0, 0xd0025850, // max r1, r1, 0 ; mov ra_x, r0 +++/* [0x00000110] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000118] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch +++/* [0x00000120] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 +++/* [0x00000128] */ 0x0c9e7440, 0x10020f27, // add t1s, r2, r1 +++/* [0x00000130] */ 0x00000008, 0xe00208a7, // mov r2,8 +++/* [0x00000138] */ 0x11827c80, 0x10021327, // shl rb12,unif, r2 +++/* [0x00000140] */ 0x0c827c80, 0x10021367, // add rb13,unif,r2 +++/* [0x00000148] */ 0x15827d80, 0x100208a7, // mov r2, unif +++/* [0x00000150] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 +++/* [0x00000158] */ 0x149cf5c0, 0xd00208a7, // and r2, r2, 15 +++/* [0x00000160] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000168] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000170] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000178] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000180] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000188] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000190] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000198] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x000001a0] */ 0x0f9c11c0, 0xd00208a7, // asr r2, r0, 1 +++/* [0x000001a8] */ 0x00002900, 0xe0020867, // mov r1, vpm_setup(0, 2, h16p(0, 0)) +++/* [0x000001b0] */ 0x0c9e7440, 0x10021567, // add rb21, r2, r1 +++/* [0x000001b8] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x000001c0] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x000001c8] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x000001d0] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++ /* [0x000001d8] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x000001e0] */ 0x4c9d040f, 0x100248a1, // add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++-/* [0x000001e8] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 ++-/* [0x000001f0] */ 0x0c9e7440, 0x10020e27, // add t0s, r2, r1 ++-/* [0x000001f8] */ 0x15827d80, 0x10021327, // mov rb12,unif ++-/* [0x00000200] */ 0x15827d80, 0x10021367, // mov rb13,unif ++-/* [0x00000208] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000210] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000218] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000220] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000228] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000230] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x ++-/* [0x00000238] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base +++/* [0x000001e0] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x000001e8] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000001f0] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x000001f8] */ 0x0c427380, 0x10020e27, // add t0s, r1, ra_x +++/* [0x00000200] */ 0x0c627380, 0x10020f27, // add t1s, r1, ra_frame_base ++ // ::mc_filter_uv ++-/* [0x00000240] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000248] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000250] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000258] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000260] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000268] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000270] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000278] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000280] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x00000288] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000290] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x00000298] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000002a0] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000002a8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000002b0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000002b8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000002c0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000002c8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000002d0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000002d8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000002e0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000002e8] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000002f0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000002f8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000300] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000308] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000310] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000318] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000320] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000328] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000330] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000338] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000340] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000348] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000350] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00000358] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000360] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00000368] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000370] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 ++-/* [0x00000378] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000380] */ 0x0f9e7080, 0x100613a7, // asr.ifnz rb14, r0, r2 ++-/* [0x00000388] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000390] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000208] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000210] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000218] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000220] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000228] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000230] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000238] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000240] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000248] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000250] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000258] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000260] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000268] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000270] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000278] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000280] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000288] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000290] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000298] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000002a0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000002a8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x000002b0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x000002b8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x000002c0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000002c8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000002d0] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000002d8] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000002e0] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000002e8] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000002f0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000002f8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000300] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000308] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000310] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000318] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 +++/* [0x00000320] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000328] */ 0x0f9e7080, 0x100208e7, // asr r3, r0, r2 +++/* [0x00000330] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000338] */ 0x0f9e7080, 0x100613e7, // asr.ifnz rb15, r0, r2 +++/* [0x00000340] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000348] */ 0x0f9e7080, 0x100608e7, // asr.ifnz r3, r0, r2 +++/* [0x00000350] */ 0x119c87c0, 0xd00213a7, // shl rb14,r3,8 +++/* [0x00000358] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop ++-/* [0x00000398] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000003a0] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x000003a8] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x000003b0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x000003b8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x000003c0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x000003c8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000003d0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000003d8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x000003e0] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x000003e8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000003f0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000003f8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000400] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000408] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000410] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000418] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000420] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000428] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000430] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000438] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000440] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x00000448] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000450] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000458] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000460] */ 0x00000020, 0xe0021327, // mov rb12,32 ++-/* [0x00000468] */ 0x00000006, 0xe0021367, // mov rb13,6 ++-/* [0x00000470] */ 0x00000001, 0xe00213a7, // mov rb14,1 ++-/* [0x00000478] */ 0x00000000, 0xe00213e7, // mov rb15,0 ++-/* [0x00000480] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000488] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000490] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000498] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000004a0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000004a8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000004b0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000004b8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 ++-/* [0x000004c0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 ++-/* [0x000004c8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 ++-/* [0x000004d0] */ 0xfffffea8, 0xf06809e7, // brr.anyn -, r:uvloop ++-/* [0x000004d8] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 ++-/* [0x000004e0] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x000004e8] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x000004f0] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x000004f8] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000500] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000508] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000510] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000518] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000520] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000528] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000530] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000360] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000368] */ 0x8e4539bf, 0xb0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 +++/* [0x00000370] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000378] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000380] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000388] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000390] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000398] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000003a0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000003a8] */ 0x0c627c80, 0x10020f27, // add t1s, ra_frame_base, r2 +++/* [0x000003b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000003b8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000003c0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000003c8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000003d0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000003d8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000003e0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x000003e8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x000003f0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000003f8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000400] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000408] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000410] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000418] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000420] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000428] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000430] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000438] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000440] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000448] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000450] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000458] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000460] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x00000468] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x00000470] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x00000478] */ 0xfffffec8, 0xf06809e7, // brr.anyn -, r:uvloop +++/* [0x00000480] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x00000488] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00000490] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00000498] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000004a0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004a8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000004b0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000004b8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000004c0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000004c8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000004d0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000004d8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_uv_b0 ++-/* [0x00000538] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000540] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00000548] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000550] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000558] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x00000560] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000568] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x00000570] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x00000578] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x00000580] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000588] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x00000590] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 ++-/* [0x00000598] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000005a0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005a8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000005b0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000005b8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x000005c0] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x000005c8] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x000005d0] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x000005d8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x000005e0] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x000005e8] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x000005f0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000005f8] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000600] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000608] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000610] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000618] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000620] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000628] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000630] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x00000638] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000640] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000648] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x00000650] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000658] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x000004e0] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x000004e8] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x000004f0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x000004f8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000500] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000508] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000510] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000518] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000520] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000528] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000530] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000538] */ 0x159d5fc0, 0x10021c67, // mov vw_setup, rb21 +++/* [0x00000540] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x00000548] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000550] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x00000558] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000560] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000568] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x00000570] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x00000578] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000580] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000588] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000590] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000598] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005a0] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005a8] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005b0] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005b8] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x000005c0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005c8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005d0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x000005d8] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x000005e0] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005e8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000005f0] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x000005f8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000600] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b0 ++-/* [0x00000660] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000668] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x00000670] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00000678] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000680] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000688] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000690] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000698] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x000006a0] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x000006a8] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x000006b0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000006b8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000006c0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000006c8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000006d0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000006d8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000006e0] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000006e8] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000006f0] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x000006f8] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000700] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000708] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000710] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000718] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00000720] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00000728] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00000730] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x00000738] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x00000740] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x00000748] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x00000750] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 ++-/* [0x00000758] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 ++-/* [0x00000760] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 ++-/* [0x00000768] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000770] */ 0x009e7000, 0x100009e7, // nop ++-/* [0x00000778] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000780] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000788] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000790] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000608] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000610] */ 0x8e4539bf, 0xb0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 +++/* [0x00000618] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00000620] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00000628] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x00000630] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00000638] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00000640] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x00000648] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x00000650] */ 0x0c627c80, 0x10020f27, // add t1s, ra_frame_base, r2 +++/* [0x00000658] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000660] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x00000668] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x00000670] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x00000678] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000680] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000688] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000690] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000698] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x000006a0] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x000006a8] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x000006b0] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x000006b8] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x000006c0] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000006c8] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000006d0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000006d8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000006e0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000006e8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000006f0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000006f8] */ 0x0d9d27c0, 0x100229e7, // sub.setf -, r3, rb18 +++/* [0x00000700] */ 0xfffffee8, 0xf06809e7, // brr.anyn -, r:uvloop_b0 +++/* [0x00000708] */ 0x0f9c63c0, 0xd0020c27, // asr vpm, r1, 6 +++/* [0x00000710] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000718] */ 0x009e7000, 0x100009e7, // nop +++/* [0x00000720] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000728] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000730] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000738] */ 0x009e7000, 0x100009e7, // nop ++ // ::mc_filter_uv_b ++-/* [0x00000798] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x000007a0] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x000007a8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000007b0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x000007b8] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif ++-/* [0x000007c0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x000007c8] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 ++-/* [0x000007d0] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 ++-/* [0x000007d8] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 ++-/* [0x000007e0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x000007e8] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 ++-/* [0x000007f0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000007f8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000800] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000808] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000810] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000818] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000820] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 ++-/* [0x00000828] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 ++-/* [0x00000830] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000838] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 ++-/* [0x00000840] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 ++-/* [0x00000848] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 ++-/* [0x00000850] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000858] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000860] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000868] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 ++-/* [0x00000870] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000878] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000880] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000888] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000890] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000898] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a0] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008a8] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000008b0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 ++-/* [0x000008b8] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008c0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000008c8] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 ++-/* [0x000008d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000008d8] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000740] */ 0x15827d80, 0x100207e7, // mov ra31, unif +++/* [0x00000748] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next +++/* [0x00000750] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num +++/* [0x00000758] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif +++/* [0x00000760] */ 0x928191f6, 0x10024823, // min r0, r0, rb_frame_width_minus_1 ; mov r3, unif +++/* [0x00000768] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000770] */ 0x0d827cc0, 0x100208a7, // sub r2, unif, r3 +++/* [0x00000778] */ 0x0c9e70c0, 0x10020827, // add r0, r0, r3 +++/* [0x00000780] */ 0x149dc1c0, 0xd00214e7, // and rb_x_next, r0, ~3 +++/* [0x00000788] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000790] */ 0x0c9d3e80, 0x100206a7, // add ra_frame_base_next, rb_x_next, r2 +++/* [0x00000798] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x000007a0] */ 0x00000010, 0xe00208a7, // mov r2, 16 +++/* [0x000007a8] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x000007b0] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 +++/* [0x000007b8] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x000007c0] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x000007c8] */ 0x0c9c11c0, 0xd0021467, // add rb17, r0, 1 +++/* [0x000007d0] */ 0x0c9c31c0, 0xd00214a7, // add rb18, r0, 3 +++/* [0x000007d8] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x000007e0] */ 0x119cd1c0, 0xd00208e7, // shl r3, r0, 13 +++/* [0x000007e8] */ 0x119c87c0, 0xd00208e7, // shl r3, r3, 8 +++/* [0x000007f0] */ 0x0e9c87c0, 0xd00208e7, // shr r3, r3, 8 +++/* [0x000007f8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000800] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 +++/* [0x00000808] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000810] */ 0x0c9d57c0, 0x10020c67, // add vr_setup, r3, rb21 +++/* [0x00000818] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000820] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000828] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000830] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000838] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif +++/* [0x00000840] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000848] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000850] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000858] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000860] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000868] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000870] */ 0xfffffff8, 0xe0021967, // mov r5rep, -8 +++/* [0x00000878] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x00000880] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :uvloop_b ++-/* [0x000008e0] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x000008e8] */ 0x8e4539bf, 0xa0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 ++-/* [0x000008f0] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x000008f8] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000900] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 ++-/* [0x00000908] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000910] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000918] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000920] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-/* [0x00000928] */ 0x0c627c80, 0x10020e27, // add t0s, ra_frame_base, r2 ++-/* [0x00000930] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000938] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000940] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000948] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000950] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000958] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000960] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000968] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000970] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00000978] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00000980] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 ++-/* [0x00000988] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x00000990] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00000998] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x000009a0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x000009a8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x000009b0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000009b8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000009c0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000009c8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000009d0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000009d8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000009e0] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm ++-/* [0x000009e8] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 ++-/* [0x000009f0] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b ++-/* [0x000009f8] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00000a00] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00000a08] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00000a10] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00000a18] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a20] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++-/* [0x00000a28] */ 0x00000010, 0xe0020827, // mov r0, 16 ++-/* [0x00000a30] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a38] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00000a40] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 ++-/* [0x00000a48] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00000a50] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00000888] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00000890] */ 0x8e4539bf, 0xb0029810, // shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 +++/* [0x00000898] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x000008a0] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x000008a8] */ 0xee454987, 0x10024860, // shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 +++/* [0x000008b0] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x000008b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000008c0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000008c8] */ 0xec414c8f, 0x10024e21, // add t0s, ra_x, r2 ; v8subs r1, r1, rb20 +++/* [0x000008d0] */ 0x0c627c80, 0x10020f27, // add t1s, ra_frame_base, r2 +++/* [0x000008d8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000008e0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000008e8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000008f0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000008f8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x00000900] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00000908] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00000910] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00000918] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00000920] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00000928] */ 0x8d3447f6, 0xd00279cc, // sub.setf -, r3, 4 ; mov ra12, ra13 +++/* [0x00000930] */ 0xffffff38, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x00000938] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00000940] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00000948] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x00000950] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x00000958] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x00000960] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x00000968] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x00000970] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x00000978] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x00000980] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00000988] */ 0x0cc27380, 0x10020867, // add r1, r1, vpm +++/* [0x00000990] */ 0x0c7a7380, 0x10020867, // add r1, r1, ra30 +++/* [0x00000998] */ 0xfffffed0, 0xf06809e7, // brr.anyn -, r:uvloop_b +++/* [0x000009a0] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 +++/* [0x000009a8] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x000009b0] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x000009b8] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x000009c0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009c8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x000009d0] */ 0x00000010, 0xe0020827, // mov r0, 16 +++/* [0x000009d8] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000009e0] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x000009e8] */ 0x0c9dae00, 0x10021c67, // add vw_setup, rb26, r0 +++/* [0x000009f0] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x000009f8] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_exit ++-/* [0x00000a58] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000a60] */ 0x00000000, 0xe80009e7, // mov -,srel(0) ++-/* [0x00000a68] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a70] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a78] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a80] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000a88] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000a90] */ 0x009e7000, 0x100009e7, // nop ; nop ++-/* [0x00000a98] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a00] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a08] */ 0x00000000, 0xe80009e7, // mov -,srel(0) +++/* [0x00000a10] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a18] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00000a20] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a28] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00000a30] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000a38] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a40] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_interrupt_exit8 ++-/* [0x00000aa0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00000aa8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ab0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ab8] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ac0] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00000ac8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ad0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ad8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ae0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000ae8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000af0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000af8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00000b00] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x00000b08] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x00000b10] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00000a48] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00000a50] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a58] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00000a60] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00000a68] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00000a70] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a78] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a80] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a88] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a90] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000a98] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000aa0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00000aa8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00000ab0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00000ab8] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_setup ++-/* [0x00000b18] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000b20] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00000b28] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000b30] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000b38] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000b40] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000b48] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 ++-/* [0x00000b50] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000b58] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 ++-/* [0x00000b60] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000b68] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000b70] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000b78] */ 0x8c9e7452, 0x10025e18, // add t0s, r2, r1 ; mov ra_frame_base, r2 ++-/* [0x00000b80] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000b88] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000b90] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000b98] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x00000ba0] */ 0x0c9c13c0, 0xd0020567, // add ra_y2, r1, 1 ++-/* [0x00000ba8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000bb0] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 ++-/* [0x00000bb8] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 ++-/* [0x00000bc0] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000bc8] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000bd0] */ 0x8c9e7452, 0x10025e19, // add t0s, r2, r1 ; mov ra_frame_base2, r2 ++-/* [0x00000bd8] */ 0x0d801dc0, 0xd0021667, // sub rb25,unif,1 ++-/* [0x00000be0] */ 0x0d801dc0, 0xd00217a7, // sub rb30,unif,1 ++-/* [0x00000be8] */ 0x15827d80, 0x10021427, // mov rb16, unif ++-/* [0x00000bf0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000bf8] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) ++-/* [0x00000c00] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 ++-/* [0x00000c08] */ 0x00000001, 0xe0020527, // mov ra20, 1 ++-/* [0x00000c10] */ 0x00000100, 0xe00205a7, // mov ra22, 256 ++-/* [0x00000c18] */ 0x00000040, 0xe00207a7, // mov ra30, 64 ++-/* [0x00000c20] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 ++-/* [0x00000c28] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 ++-/* [0x00000c30] */ 0x00000018, 0xe00215e7, // mov rb23, 24 ++-/* [0x00000c38] */ 0x00000000, 0xe0020227, // mov ra8, 0 ++-/* [0x00000c40] */ 0x00000000, 0xe0020267, // mov ra9, 0 ++-/* [0x00000c48] */ 0x00000000, 0xe00202a7, // mov ra10, 0 ++-/* [0x00000c50] */ 0x00000000, 0xe00202e7, // mov ra11, 0 ++-/* [0x00000c58] */ 0x00000000, 0xe0020327, // mov ra12, 0 ++-/* [0x00000c60] */ 0x00000000, 0xe0020367, // mov ra13, 0 ++-/* [0x00000c68] */ 0x00000000, 0xe00203a7, // mov ra14, 0 ++-/* [0x00000c70] */ 0x00000000, 0xe00203e7, // mov ra15, 0 ++-/* [0x00000c78] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000c80] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000c88] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000c90] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000c98] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000ca0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000ca8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000cb0] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) ++-/* [0x00000cb8] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 ++-/* [0x00000cc0] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 ++-/* [0x00000cc8] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num ++-/* [0x00000cd0] */ 0x159e7480, 0x10020867, // mov r1, r2 ++-/* [0x00000cd8] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 ++-/* [0x00000ce0] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 ++-/* [0x00000ce8] */ 0x159e7480, 0x10020827, // mov r0, r2 ++-/* [0x00000cf0] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 ++-/* [0x00000cf8] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000d00] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) ++-/* [0x00000d08] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 ++-/* [0x00000d10] */ 0x15827d80, 0x10021327, // mov rb12,unif ++-/* [0x00000d18] */ 0x15827d80, 0x10021367, // mov rb13,unif ++-/* [0x00000d20] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000d28] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 ++-/* [0x00000d30] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000d38] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 ++-/* [0x00000d40] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000d48] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base ++-/* [0x00000d50] */ 0x13540dc0, 0xd0020867, // max r1, ra_y2, 0 ++-/* [0x00000d58] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++-/* [0x00000d60] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00000ac0] */ 0x00000010, 0xe00208e7, // mov r3, 16 +++/* [0x00000ac8] */ 0x15827d80, 0x10020227, // mov ra8, unif +++/* [0x00000ad0] */ 0x15827d80, 0x10020267, // mov ra9, unif +++/* [0x00000ad8] */ 0x15827d80, 0x100202a7, // mov ra10, unif +++/* [0x00000ae0] */ 0x15827d80, 0x100202e7, // mov ra11, unif +++/* [0x00000ae8] */ 0x15827d80, 0x10020867, // mov r1, unif +++/* [0x00000af0] */ 0x119e72c0, 0x10020827, // shl r0,r1,r3 +++/* [0x00000af8] */ 0x0f9e72c0, 0x10020867, // asr r1,r1,r3 +++/* [0x00000b00] */ 0x0f9e70c0, 0x10020827, // asr r0,r0,r3 +++/* [0x00000b08] */ 0x0d9c13c0, 0xd0021667, // sub rb_frame_width_minus_1,r1,1 +++/* [0x00000b10] */ 0x0d9c11c0, 0xd00217a7, // sub rb_frame_height_minus_1,r0,1 +++/* [0x00000b18] */ 0x15827d80, 0x10021427, // mov rb_pitch, unif +++/* [0x00000b20] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000b28] */ 0xc0000000, 0xe0020867, // mov r1, vdw_setup_1(0) +++/* [0x00000b30] */ 0x0c9e7200, 0x10021627, // add rb24, r1, r0 +++/* [0x00000b38] */ 0x15227d80, 0x10020867, // mov r1, ra8 +++/* [0x00000b40] */ 0x119e72c0, 0x10020827, // shl r0,r1,r3 +++/* [0x00000b48] */ 0x0f9e72c0, 0x10020867, // asr r1,r1,r3 +++/* [0x00000b50] */ 0x0f9e70c0, 0x10020827, // asr r0,r0,r3 +++/* [0x00000b58] */ 0x0c9a7180, 0x10020827, // add r0, r0, elem_num +++/* [0x00000b60] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 +++/* [0x00000b68] */ 0x922591f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, ra9 +++/* [0x00000b70] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000b78] */ 0x0c9c13c0, 0xd0020767, // add ra_y, r1, 1 +++/* [0x00000b80] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000b88] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000b90] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000b98] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000ba0] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000ba8] */ 0x8c9e7452, 0x10025e18, // add t0s, r2, r1 ; mov ra_frame_base, r2 +++/* [0x00000bb0] */ 0x152a7d80, 0x10020867, // mov r1, ra10 +++/* [0x00000bb8] */ 0x119e72c0, 0x10020827, // shl r0,r1,r3 +++/* [0x00000bc0] */ 0x0f9e72c0, 0x10020867, // asr r1,r1,r3 +++/* [0x00000bc8] */ 0x0f9e70c0, 0x10020827, // asr r0,r0,r3 +++/* [0x00000bd0] */ 0x0c9a7180, 0x10020827, // add r0, r0, elem_num +++/* [0x00000bd8] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 +++/* [0x00000be0] */ 0x922d91f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, ra11 +++/* [0x00000be8] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000bf0] */ 0x0c9c13c0, 0xd0020567, // add ra_y2, r1, 1 +++/* [0x00000bf8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000c00] */ 0x0c9e7400, 0x100208a7, // add r2, r2, r0 +++/* [0x00000c08] */ 0x139c03c0, 0xd0020867, // max r1, r1, 0 +++/* [0x00000c10] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000c18] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000c20] */ 0x8c9e7452, 0x10025f19, // add t1s, r2, r1 ; mov ra_frame_base2, r2 +++/* [0x00000c28] */ 0x00000001, 0xe0020527, // mov ra20, 1 +++/* [0x00000c30] */ 0x00000100, 0xe00205a7, // mov ra22, 256 +++/* [0x00000c38] */ 0x00000040, 0xe00207a7, // mov ra30, 64 +++/* [0x00000c40] */ 0xffffff00, 0xe0021527, // mov rb20, 0xffffff00 +++/* [0x00000c48] */ 0x000000ff, 0xe00215a7, // mov rb22, 255 +++/* [0x00000c50] */ 0x00000018, 0xe00215e7, // mov rb23, 24 +++/* [0x00000c58] */ 0x00000000, 0xe0020227, // mov ra8, 0 +++/* [0x00000c60] */ 0x00000000, 0xe0020267, // mov ra9, 0 +++/* [0x00000c68] */ 0x00000000, 0xe00202a7, // mov ra10, 0 +++/* [0x00000c70] */ 0x00000000, 0xe00202e7, // mov ra11, 0 +++/* [0x00000c78] */ 0x00000000, 0xe0020327, // mov ra12, 0 +++/* [0x00000c80] */ 0x00000000, 0xe0020367, // mov ra13, 0 +++/* [0x00000c88] */ 0x00000000, 0xe00203a7, // mov ra14, 0 +++/* [0x00000c90] */ 0x00000000, 0xe00203e7, // mov ra15, 0 +++/* [0x00000c98] */ 0x00004000, 0xe00204a7, // mov ra18, 0x4000 +++/* [0x00000ca0] */ 0x159e6fc0, 0x100208a7, // mov r2, qpu_num +++/* [0x00000ca8] */ 0x159e7480, 0x10020867, // mov r1, r2 +++/* [0x00000cb0] */ 0x0f9c23c0, 0xd0020867, // asr r1, r1, 2 +++/* [0x00000cb8] */ 0x119c63c0, 0xd0020867, // shl r1, r1, 6 +++/* [0x00000cc0] */ 0x159e7480, 0x10020827, // mov r0, r2 +++/* [0x00000cc8] */ 0x149c31c0, 0xd0020827, // and r0, r0, 3 +++/* [0x00000cd0] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000cd8] */ 0x00004800, 0xe0020867, // mov r1, vpm_setup(0, 4, h8p(0, 0)) +++/* [0x00000ce0] */ 0x0c9e7040, 0x10021727, // add rb28, r0, r1 +++/* [0x00000ce8] */ 0x80004004, 0xe0020867, // mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) +++/* [0x00000cf0] */ 0x119c51c0, 0xd0020827, // shl r0, r0, 5 +++/* [0x00000cf8] */ 0x0c9e7040, 0x100216e7, // add rb27, r0, r1 +++/* [0x00000d00] */ 0x15827d80, 0x10020867, // mov r1, unif +++/* [0x00000d08] */ 0x919c82ff, 0xd0024822, // shl r0,r1,r3 ; mov r2,8 +++/* [0x00000d10] */ 0x0f9e70c0, 0x10021367, // asr rb13,r0,r3 +++/* [0x00000d18] */ 0x0f9e72c0, 0x10021327, // asr rb12,r1,r3 +++/* [0x00000d20] */ 0x0c9cde80, 0x10021367, // add rb13,rb13,r2 +++/* [0x00000d28] */ 0x119cce80, 0x10021327, // shl rb12, rb12, r2 +++/* [0x00000d30] */ 0x13740dc0, 0xd0020867, // max r1, ra_y, 0 +++/* [0x00000d38] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 +++/* [0x00000d40] */ 0x0c741dc0, 0xd0020767, // add ra_y, ra_y, 1 +++/* [0x00000d48] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch +++/* [0x00000d50] */ 0x0c627380, 0x10020e27, // add t0s, r1, ra_frame_base +++/* [0x00000d58] */ 0x13540dc0, 0xd0020867, // max r1, ra_y2, 0 +++/* [0x00000d60] */ 0x129de3c0, 0x10020867, // min r1, r1, rb_frame_height_minus_1 ++ /* [0x00000d68] */ 0x0c541dc0, 0xd0020567, // add ra_y2, ra_y2, 1 ++ /* [0x00000d70] */ 0x409d000f, 0x100049e1, // nop ; mul24 r1, r1, rb_pitch ++-/* [0x00000d78] */ 0x0c667380, 0x10020e27, // add t0s, r1, ra_frame_base2 ++-// ::mc_filter +++/* [0x00000d78] */ 0x0c667380, 0x10020f27, // add t1s, r1, ra_frame_base2 +++// :per_block_setup ++ /* [0x00000d80] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ /* [0x00000d88] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++ /* [0x00000d90] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++ /* [0x00000d98] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next ++-/* [0x00000da0] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000da8] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00000db0] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000db8] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00000dc0] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00000dc8] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000dd0] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 ++-/* [0x00000dd8] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00000de0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif ++-/* [0x00000de8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00000df0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x00000df8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 ++-/* [0x00000e00] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00000e08] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 ++-/* [0x00000e10] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x00000e18] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x00000e20] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000e28] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x00000e30] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x00000e38] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00000e40] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00000e48] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00000e50] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00000e58] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00000e60] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000e68] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00000e70] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000e78] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000e80] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000e88] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000e90] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000e98] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00000ea0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000ea8] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000eb0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000eb8] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ec0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x00000ec8] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000ed0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ed8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ee0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000ee8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x00000ef0] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000ef8] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f00] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00000f08] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000da0] */ 0x00000010, 0xe00208e7, // mov r3, 16 +++/* [0x00000da8] */ 0x15827d80, 0x10020867, // mov r1, unif +++/* [0x00000db0] */ 0x119e72c0, 0x10020827, // shl r0,r1,r3 +++/* [0x00000db8] */ 0x0f9e72c0, 0x10020867, // asr r1,r1,r3 +++/* [0x00000dc0] */ 0x0f9e70c0, 0x10020827, // asr r0,r0,r3 +++/* [0x00000dc8] */ 0x0c9a7180, 0x10020827, // add r0, r0, elem_num +++/* [0x00000dd0] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 +++/* [0x00000dd8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000de0] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 +++/* [0x00000de8] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 +++/* [0x00000df0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000df8] */ 0x8c827436, 0x100246a1, // add ra_frame_base_next, r2, r0 ; mov r1, unif +++/* [0x00000e00] */ 0x119e72c0, 0x10020827, // shl r0,r1,r3 +++/* [0x00000e08] */ 0x0f9e72c0, 0x10020867, // asr r1,r1,r3 +++/* [0x00000e10] */ 0x0f9e70c0, 0x10020827, // asr r0,r0,r3 +++/* [0x00000e18] */ 0x0c9a7180, 0x10020827, // add r0, r0, elem_num +++/* [0x00000e20] */ 0x139c01c0, 0xd0020827, // max r0, r0, 0 +++/* [0x00000e28] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif +++/* [0x00000e30] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 +++/* [0x00000e38] */ 0x159e7240, 0x10021067, // mov ra_y2_next, r1 +++/* [0x00000e40] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 +++/* [0x00000e48] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 +++/* [0x00000e50] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 +++/* [0x00000e58] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00000e60] */ 0x0e9e70c0, 0x10020867, // shr r1, r0, r3 +++/* [0x00000e68] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 +++/* [0x00000e70] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 +++/* [0x00000e78] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 +++/* [0x00000e80] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 +++/* [0x00000e88] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 +++/* [0x00000e90] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 +++/* [0x00000e98] */ 0x119e70c0, 0x10020827, // shl r0, r0, r3 +++/* [0x00000ea0] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 +++/* [0x00000ea8] */ 0x95801dbf, 0xd0024821, // mov r0, unif ; mov r1,1 +++/* [0x00000eb0] */ 0x4f5971c6, 0x10024260, // asr ra9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000eb8] */ 0x4f5971c6, 0x10024220, // asr ra8, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ec0] */ 0x4f5971c6, 0x10044260, // asr.ifz ra9, r0, rb23; mul24 r0, r0, ra22 +++/* [0x00000ec8] */ 0x0f9d71c0, 0x10040227, // asr.ifz ra8, r0, rb23 +++/* [0x00000ed0] */ 0x0d243f80, 0xd0020267, // sub ra9,3,ra9 +++/* [0x00000ed8] */ 0x0d203f80, 0xd0020227, // sub ra8,3,ra8 +++/* [0x00000ee0] */ 0x11243dc0, 0xd0020267, // shl ra9,ra9,3 +++/* [0x00000ee8] */ 0x11203dc0, 0xd0020227, // shl ra8,ra8,3 +++/* [0x00000ef0] */ 0x00ffff00, 0xe0020867, // mov r1,0xffff00 +++/* [0x00000ef8] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000f00] */ 0x0f9d71c0, 0x10020027, // asr ra0, r0, rb23 +++/* [0x00000f08] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 ++ /* [0x00000f10] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 ++-/* [0x00000f18] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00000f20] */ 0x15827d80, 0x100009e7, // mov.ifnz -, unif ++-/* [0x00000f28] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00000f30] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00000f38] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00000f40] */ 0x00000000, 0xe00208e7, // mov r3, 0 +++/* [0x00000f18] */ 0x01040400, 0xe0020867, // mov r1,0x1040400 +++/* [0x00000f20] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000f28] */ 0x0f9d71c0, 0x10020067, // asr ra1, r0, rb23 +++/* [0x00000f30] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00000f38] */ 0x0f9d71c0, 0x10021167, // asr rb5, r0, rb23 +++/* [0x00000f40] */ 0xfbf5f600, 0xe0020867, // mov r1,0xfbf5f600 +++/* [0x00000f48] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000f50] */ 0x0f9d71c0, 0x100200a7, // asr ra2, r0, rb23 +++/* [0x00000f58] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00000f60] */ 0x0f9d71c0, 0x100211a7, // asr rb6, r0, rb23 +++/* [0x00000f68] */ 0x11283a40, 0xe0020867, // mov r1,0x11283a40 +++/* [0x00000f70] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000f78] */ 0x0f9d71c0, 0x100200e7, // asr ra3, r0, rb23 +++/* [0x00000f80] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00000f88] */ 0x0f9d71c0, 0x100211e7, // asr rb7, r0, rb23 +++/* [0x00000f90] */ 0x3a281100, 0xe0020867, // mov r1,0x3a281100 +++/* [0x00000f98] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000fa0] */ 0x0f9d71c0, 0x10020127, // asr ra4, r0, rb23 +++/* [0x00000fa8] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00000fb0] */ 0x0f9d71c0, 0x10021227, // asr rb8, r0, rb23 +++/* [0x00000fb8] */ 0xf6f5fb00, 0xe0020867, // mov r1,0xf6f5fb00 +++/* [0x00000fc0] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000fc8] */ 0x0f9d71c0, 0x10020167, // asr ra5, r0, rb23 +++/* [0x00000fd0] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00000fd8] */ 0x0f9d71c0, 0x10021267, // asr rb9, r0, rb23 +++/* [0x00000fe0] */ 0x04040100, 0xe0020867, // mov r1,0x4040100 +++/* [0x00000fe8] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00000ff0] */ 0x0f9d71c0, 0x100201a7, // asr ra6, r0, rb23 +++/* [0x00000ff8] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00001000] */ 0x0f9d71c0, 0x100212a7, // asr rb10, r0, rb23 +++/* [0x00001008] */ 0xffff0000, 0xe0020867, // mov r1,0xffff0000 +++/* [0x00001010] */ 0x11227380, 0x10020827, // shl r0, r1, ra8 +++/* [0x00001018] */ 0x0f9d71c0, 0x100201e7, // asr ra7, r0, rb23 +++/* [0x00001020] */ 0x11267380, 0x10020827, // shl r0, r1, ra9 +++/* [0x00001028] */ 0x0f9d71c0, 0x100212e7, // asr rb11, r0, rb23 +++/* [0x00001030] */ 0x15827d80, 0x10020827, // mov r0, unif +++/* [0x00001038] */ 0x0f9e70c0, 0x100213e7, // asr rb15, r0, r3 +++/* [0x00001040] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 +++/* [0x00001048] */ 0x119e70c0, 0x10020827, // shl r0, r0, r3 +++/* [0x00001050] */ 0x8f9c00ff, 0xd0024823, // asr r0, r0, r3 ; mov r3, 0 +++/* [0x00001058] */ 0x119c81c0, 0xd00213a7, // shl rb14, r0, 8 +++// ::mc_filter ++ // :yloop ++-/* [0x00000f48] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00000f50] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-/* [0x00000f58] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00000f60] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00000f68] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 ++-/* [0x00000f70] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next ++-/* [0x00000f78] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00000f80] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000f88] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00000f90] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000f98] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 ++-/* [0x00000fa0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00000fa8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-/* [0x00000fb0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 ++-/* [0x00000fb8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00000fc0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x00000fc8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x00000fd0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x00000fd8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x00000fe0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x00000fe8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x00000ff0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x00000ff8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00001000] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00001008] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00001010] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00001018] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00001020] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00001028] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00001030] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001038] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001040] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001048] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 ++-/* [0x00001050] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001058] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001060] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001068] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001070] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloop ++-/* [0x00001078] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001080] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00001088] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00001090] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00001098] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000010a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000010a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000010b0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-/* [0x000010b8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-/* [0x000010c0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-/* [0x000010c8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 ++-/* [0x000010d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000010d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000010e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000010e8] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 ++-/* [0x000010f0] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 ++-/* [0x000010f8] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 ++-/* [0x00001100] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloop ++-/* [0x00001108] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 ++-/* [0x00001110] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00001118] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00001120] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001128] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001130] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001138] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00001060] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001068] */ 0x8e4539bf, 0xb0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu1 +++/* [0x00001070] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00001078] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001080] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00001088] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00001090] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001098] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000010a0] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000010a8] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x000010b0] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x000010b8] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000010c0] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x000010c8] */ 0xec654c8f, 0x10024f21, // add t1s, ra_frame_base2, r2 ; v8subs r1, r1, rb20 +++/* [0x000010d0] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000010d8] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000010e0] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000010e8] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000010f0] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000010f8] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x00001100] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00001108] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00001110] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001118] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001120] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001128] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001130] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001138] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001140] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001148] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001150] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001158] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001160] */ 0x8d2487f6, 0xd00279c8, // sub.setf -, r3, 8 ; mov ra8, ra9 +++/* [0x00001168] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001170] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001178] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001180] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001188] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001190] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001198] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x000011a0] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000011a8] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000011b0] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000011b8] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000011c0] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000011c8] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000011d0] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000011d8] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000011e0] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000011e8] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000011f0] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000011f8] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 +++/* [0x00001200] */ 0x409ce00f, 0x100049e1, // nop ; mul24 r1, r1, rb14 +++/* [0x00001208] */ 0x0c9cc3c0, 0x10020867, // add r1, r1, rb12 +++/* [0x00001210] */ 0x0f9cd3c0, 0x10020867, // asr r1, r1, rb13 +++/* [0x00001218] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloop +++/* [0x00001220] */ 0x0c9cf3c0, 0x10020867, // add r1, r1, rb15 +++/* [0x00001228] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001230] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001238] */ 0xfffffb28, 0xf0f809e7, // brr -, r:per_block_setup +++/* [0x00001240] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001248] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001250] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_filter_b ++-/* [0x00001140] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x00001148] */ 0x15827d80, 0x100207e7, // mov ra31, unif ++-/* [0x00001150] */ 0x154e7d80, 0x10020467, // mov ra_xshift, ra_xshift_next ++-/* [0x00001158] */ 0x155e7d80, 0x10021027, // mov rx_xshift2, rx_xshift2_next ++-/* [0x00001160] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x00001168] */ 0x938001f6, 0xd0024821, // max r0, r0, 0; mov r1, unif ++-/* [0x00001170] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x00001178] */ 0x119c31c0, 0xd00204e7, // shl ra_xshift_next, r0, 3 ++-/* [0x00001180] */ 0x159e7240, 0x10020727, // mov ra_y_next, r1 ++-/* [0x00001188] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x00001190] */ 0x0c9e7400, 0x100206a7, // add ra_frame_base_next, r2, r0 ++-/* [0x00001198] */ 0x0c9a0f80, 0x10020827, // add r0, unif, elem_num ++-/* [0x000011a0] */ 0x938001f6, 0xd0024821, // max r0, r0, 0 ; mov r1, unif ++-/* [0x000011a8] */ 0x928191f6, 0x10024822, // min r0, r0, rb_frame_width_minus_1 ; mov r2, unif ++-/* [0x000011b0] */ 0x119c31c0, 0xd00205e7, // shl rx_xshift2_next, r0, 3 ++-/* [0x000011b8] */ 0x0c9c13c0, 0xd0021067, // add ra_y2_next, r1, 1 ++-/* [0x000011c0] */ 0x149dc1c0, 0xd0020827, // and r0, r0, ~3 ++-/* [0x000011c8] */ 0x0c9e7400, 0x100214e7, // add rx_frame_base2_next, r2, r0 ++-/* [0x000011d0] */ 0x159dcfc0, 0x10021c67, // mov vw_setup, rb28 ++-/* [0x000011d8] */ 0x00000010, 0xe00208a7, // mov r2, 16 ++-/* [0x000011e0] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x000011e8] */ 0x0e9e7080, 0x10020867, // shr r1, r0, r2 ++-/* [0x000011f0] */ 0x0d9d8e40, 0x10021767, // sub rb29, rb24, r1 ++-/* [0x000011f8] */ 0x149d61c0, 0x10020827, // and r0, r0, rb22 ++-/* [0x00001200] */ 0x0c9c51c0, 0xd0021467, // add rb17, r0, 5 ++-/* [0x00001208] */ 0x0c9c71c0, 0xd00214a7, // add rb18, r0, 7 ++-/* [0x00001210] */ 0x119c71c0, 0xd0020827, // shl r0, r0, 7 ++-/* [0x00001218] */ 0x0c9e7040, 0x10020827, // add r0, r0, r1 ++-/* [0x00001220] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001228] */ 0x0c9db1c0, 0x100216a7, // add rb26, r0, rb27 ++-/* [0x00001230] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001238] */ 0x00000001, 0xe0020867, // mov r1, 1 ++-/* [0x00001240] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001248] */ 0x409f3001, 0xd00049e0, // nop ; mul24 r0, r0 << 13, r1 << 13 ++-/* [0x00001250] */ 0x4f5971c6, 0x100240e0, // asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001258] */ 0x409f2001, 0xd00049e0, // nop ; mul24 r0, r0 << 14, r1 << 14 ++-/* [0x00001260] */ 0x4f5971c6, 0x100240a0, // asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001268] */ 0x409f1001, 0xd00049e0, // nop ; mul24 r0, r0 << 15, r1 << 15 ++-/* [0x00001270] */ 0x4f5971c6, 0x10024060, // asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001278] */ 0x8f8171f6, 0x10024020, // asr ra0, r0, rb23; mov r0, unif ++-/* [0x00001280] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001288] */ 0x409f7001, 0xd00049e0, // nop ; mul24 r0, r0 << 9, r1 << 9 ++-/* [0x00001290] */ 0x4f5971c6, 0x100241e0, // asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001298] */ 0x409f6001, 0xd00049e0, // nop ; mul24 r0, r0 << 10, r1 << 10 ++-/* [0x000012a0] */ 0x4f5971c6, 0x100241a0, // asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012a8] */ 0x409f5001, 0xd00049e0, // nop ; mul24 r0, r0 << 11, r1 << 11 ++-/* [0x000012b0] */ 0x4f5971c6, 0x10024160, // asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012b8] */ 0x409f4001, 0xd00049e0, // nop ; mul24 r0, r0 << 12, r1 << 12 ++-/* [0x000012c0] */ 0x8f8171f6, 0x10024120, // asr ra4, r0, rb23; mov r0, unif ++-/* [0x000012c8] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x000012d0] */ 0x4f5971c6, 0x100252e0, // asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012d8] */ 0x4f5971c6, 0x100252a0, // asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012e0] */ 0x4f5971c6, 0x10025260, // asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x000012e8] */ 0x8f8171f6, 0x10025220, // asr rb8, r0, rb23; mov r0, unif ++-/* [0x000012f0] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x000012f8] */ 0x4f5971c6, 0x100251e0, // asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001300] */ 0x4f5971c6, 0x100251a0, // asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001308] */ 0x4f5971c6, 0x10025160, // asr rb5, r0, rb23; mul24 r0, r0, ra22 ++-/* [0x00001310] */ 0x0f9d71c0, 0x10021127, // asr rb4, r0, rb23 ++-/* [0x00001318] */ 0x15827d80, 0x10020827, // mov r0, unif ++-/* [0x00001320] */ 0x15827d80, 0x10060827, // mov.ifnz r0, unif ++-/* [0x00001328] */ 0x0f9e7080, 0x100213e7, // asr rb15, r0, r2 ++-/* [0x00001330] */ 0x119e7080, 0x10020827, // shl r0, r0, r2 ++-/* [0x00001338] */ 0x0f9e7080, 0x100213a7, // asr rb14, r0, r2 ++-/* [0x00001340] */ 0x00000000, 0xe00208e7, // mov r3, 0 ++ // :yloopb ++-/* [0x00001348] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-/* [0x00001350] */ 0x8e4539bf, 0xa0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-/* [0x00001358] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-/* [0x00001360] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-/* [0x00001368] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 ++-/* [0x00001370] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next ++-/* [0x00001378] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 ++-/* [0x00001380] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x00001388] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-/* [0x00001390] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 ++-/* [0x00001398] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 ++-/* [0x000013a0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 ++-/* [0x000013a8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-/* [0x000013b0] */ 0xec654c87, 0x10024e20, // add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 ++-/* [0x000013b8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-/* [0x000013c0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 ++-/* [0x000013c8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-/* [0x000013d0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 ++-/* [0x000013d8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-/* [0x000013e0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-/* [0x000013e8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-/* [0x000013f0] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-/* [0x000013f8] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-/* [0x00001400] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-/* [0x00001408] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-/* [0x00001410] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-/* [0x00001418] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-/* [0x00001420] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-/* [0x00001428] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-/* [0x00001430] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-/* [0x00001438] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-/* [0x00001440] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 ++-/* [0x00001448] */ 0x8d3487f6, 0xd00279cc, // sub.setf -, r3, 8 ; mov ra12, ra13 ++-/* [0x00001450] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 ++-/* [0x00001458] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 ++-/* [0x00001460] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 ++-/* [0x00001468] */ 0x15367d80, 0x10020327, // mov ra12, ra13 ++-/* [0x00001470] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloopb ++-/* [0x00001478] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 ++-/* [0x00001480] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 ++-/* [0x00001488] */ 0x159e7000, 0x100203e7, // mov ra15, r0 ++-/* [0x00001490] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 ++-/* [0x00001498] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 ++-/* [0x000014a0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-/* [0x000014a8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-/* [0x000014b0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-/* [0x000014b8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-/* [0x000014c0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-/* [0x000014c8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 ++-/* [0x000014d0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait ++-/* [0x000014d8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-/* [0x000014e0] */ 0x0f9ce3c0, 0xd0020867, // asr r1, r1, 14 ++-/* [0x000014e8] */ 0x4053800e, 0xd00049e1, // nop ; mul24 r1, r1 << 8, ra20 << 8 ++-/* [0x000014f0] */ 0x4c78e38f, 0x10024860, // add r1, r1, ra30 ; mul24 r0, r1, rb14 ++-/* [0x000014f8] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 ++-/* [0x00001500] */ 0xfffffe28, 0xf06809e7, // brr.anyn -, r:yloopb ++-/* [0x00001508] */ 0x0f9c73c0, 0xd0020867, // asr r1, r1, 7 ++-/* [0x00001510] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 ++-/* [0x00001518] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 ++-/* [0x00001520] */ 0x00000000, 0xf0f7e9e7, // bra -, ra31 ++-/* [0x00001528] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 ++-/* [0x00001530] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 ++-/* [0x00001538] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif +++/* [0x00001258] */ 0xcd5117de, 0xa00269e3, // sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++/* [0x00001260] */ 0x8e4539bf, 0xb0029819, // shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu1 +++/* [0x00001268] */ 0x956a7d9b, 0x1004461f, // mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++/* [0x00001270] */ 0x95710dbf, 0x10044763, // mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++/* [0x00001278] */ 0x0e9c09c0, 0x10020867, // shr r1, r4, rx_xshift2 +++/* [0x00001280] */ 0x159c1fc0, 0x10040567, // mov.ifz ra_y2, ra_y2_next +++/* [0x00001288] */ 0x13740dc0, 0xd00208a7, // max r2, ra_y, 0 +++/* [0x00001290] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x00001298] */ 0x4c741dd3, 0xd0024762, // add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++/* [0x000012a0] */ 0xec614c87, 0x10024e20, // add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 +++/* [0x000012a8] */ 0x13540dc0, 0xd00208a7, // max r2, ra_y2, 0 +++/* [0x000012b0] */ 0x129de5c0, 0x100208a7, // min r2, r2, rb_frame_height_minus_1 +++/* [0x000012b8] */ 0x4c541dd3, 0xd0024562, // add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++/* [0x000012c0] */ 0xec654c8f, 0x10024f21, // add t1s, ra_frame_base2, r2 ; v8subs r1, r1, rb20 +++/* [0x000012c8] */ 0x0000ff00, 0xe20229e7, // mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++/* [0x000012d0] */ 0x40027006, 0x100049e2, // nop ; mul24 r2, r0, ra0 +++/* [0x000012d8] */ 0x40038031, 0xd000c9e2, // nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++/* [0x000012e0] */ 0x4007f030, 0xd00049e3, // nop ; mul24 r3, ra1 << 1, r0 << 1 +++/* [0x000012e8] */ 0x40077031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++/* [0x000012f0] */ 0x4c0be4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++/* [0x000012f8] */ 0x400b6031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++/* [0x00001300] */ 0x4c0fd4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++/* [0x00001308] */ 0x400f5031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++/* [0x00001310] */ 0x4c13c4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++/* [0x00001318] */ 0x40134031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++/* [0x00001320] */ 0x4c17b4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++/* [0x00001328] */ 0x40173031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++/* [0x00001330] */ 0x4c1ba4f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++/* [0x00001338] */ 0x401b2031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++/* [0x00001340] */ 0x4c1f94f0, 0xd00248a3, // add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++/* [0x00001348] */ 0x401f1031, 0xd000c9e3, // nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++/* [0x00001350] */ 0x8c9df4ff, 0x10024823, // add r0, r2, r3 ; mov r3, rb31 +++/* [0x00001358] */ 0x8d2487f6, 0xd00279c8, // sub.setf -, r3, 8 ; mov ra8, ra9 +++/* [0x00001360] */ 0x152a7d80, 0x10020267, // mov ra9, ra10 +++/* [0x00001368] */ 0x152e7d80, 0x100202a7, // mov ra10, ra11 +++/* [0x00001370] */ 0x15327d80, 0x100202e7, // mov ra11, ra12 +++/* [0x00001378] */ 0x15367d80, 0x10020327, // mov ra12, ra13 +++/* [0x00001380] */ 0xfffffeb8, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001388] */ 0x153a7d80, 0x10020367, // mov ra13, ra14 +++/* [0x00001390] */ 0x153e7d80, 0x100203a7, // mov ra14, ra15 +++/* [0x00001398] */ 0x159e7000, 0x100203e7, // mov ra15, r0 +++/* [0x000013a0] */ 0x4038a037, 0x100049e1, // nop ; mul24 r1, ra14, rb10 +++/* [0x000013a8] */ 0x40349037, 0x100049e0, // nop ; mul24 r0, ra13, rb9 +++/* [0x000013b0] */ 0x4c308237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra12, rb8 +++/* [0x000013b8] */ 0x4c3cb237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra15, rb11 +++/* [0x000013c0] */ 0x4c204237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra8, rb4 +++/* [0x000013c8] */ 0x4c245237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra9, rb5 +++/* [0x000013d0] */ 0x4c286237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra10, rb6 +++/* [0x000013d8] */ 0x4c2c7237, 0x10024860, // add r1, r1, r0 ; mul24 r0, ra11, rb7 +++/* [0x000013e0] */ 0x8c9f223f, 0x10020867, // add r1, r1, r0 ; mov -, vw_wait +++/* [0x000013e8] */ 0x4d5927ce, 0x100269e1, // sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++/* [0x000013f0] */ 0x0f9ce3c0, 0xd0020827, // asr r0, r1, 14 +++/* [0x000013f8] */ 0x0f9c63c0, 0xd0020867, // asr r1, r1, 6 +++/* [0x00001400] */ 0x405b8006, 0xd00049e0, // nop ; mul24 r0, r0 << 8, ra22 << 8 +++/* [0x00001408] */ 0x0c4a7380, 0x10020867, // add r1, r1, ra18 +++/* [0x00001410] */ 0x0c9e7200, 0x10020867, // add r1, r1, r0 +++/* [0x00001418] */ 0xfffffe20, 0xf06809e7, // brr.anyn -, r:yloopb +++/* [0x00001420] */ 0x0f9cf3c0, 0xd0020867, // asr r1, r1, 15 +++/* [0x00001428] */ 0x129d63c0, 0x10020867, // min r1, r1, rb22 +++/* [0x00001430] */ 0x139c03c0, 0xd0020c27, // max vpm, r1, 0 +++/* [0x00001438] */ 0xfffff928, 0xf0f809e7, // brr -, r:per_block_setup +++/* [0x00001440] */ 0x159dafc0, 0x10021c67, // mov vw_setup, rb26 +++/* [0x00001448] */ 0x159ddfc0, 0x10021c67, // mov vw_setup, rb29 +++/* [0x00001450] */ 0x15827d80, 0x10021ca7, // mov vw_addr, unif ++ // ::mc_interrupt_exit12 ++-/* [0x00001540] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait ++-/* [0x00001548] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001550] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001558] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001560] */ 0x009e7000, 0xa00009e7, // ldtmu0 ++-/* [0x00001568] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001570] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001578] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001580] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001588] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001590] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x00001598] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015a0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) ++-/* [0x000015c0] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend ++-/* [0x000015c8] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop ++-/* [0x000015d0] */ 0x009e7000, 0x100009e7, // nop ; nop +++/* [0x00001458] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x00001460] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001468] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001470] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00001478] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00001480] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001488] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001490] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x00001498] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014a0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014a8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014b0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014b8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014c0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014c8] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014d0] */ 0x00000010, 0xe80009e7, // mov -,sacq(0) +++/* [0x000014d8] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x000014e0] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x000014e8] */ 0x009e7000, 0x100009e7, // nop ; nop +++// ::mc_exit1 +++/* [0x000014f0] */ 0x159f2fc0, 0x100009e7, // mov -, vw_wait +++/* [0x000014f8] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001500] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00001508] */ 0x009e7000, 0xa00009e7, // ldtmu0 +++/* [0x00001510] */ 0x009e7000, 0xb00009e7, // ldtmu1 +++/* [0x00001518] */ 0x009e7000, 0x300009e7, // nop ; nop ; thrend +++/* [0x00001520] */ 0x00000001, 0xe00209a7, // mov interrupt, 1; nop +++/* [0x00001528] */ 0x009e7000, 0x100009e7, // nop ; nop ++ // ::mc_end ++ }; ++ #ifdef __HIGHC__ ++diff --git a/libavcodec/rpi_shader.h b/libavcodec/rpi_shader.h ++index 6e552d9..760bd17 100644 ++--- a/libavcodec/rpi_shader.h +++++ b/libavcodec/rpi_shader.h ++@@ -4,15 +4,16 @@ ++ extern unsigned int rpi_shader[]; ++ ++ #define mc_setup_uv (rpi_shader + 0) ++-#define mc_filter_uv (rpi_shader + 144) ++-#define mc_filter_uv_b0 (rpi_shader + 334) ++-#define mc_filter_uv_b (rpi_shader + 486) ++-#define mc_exit (rpi_shader + 662) ++-#define mc_interrupt_exit8 (rpi_shader + 680) ++-#define mc_setup (rpi_shader + 710) ++-#define mc_filter (rpi_shader + 864) ++-#define mc_filter_b (rpi_shader + 1104) ++-#define mc_interrupt_exit12 (rpi_shader + 1360) ++-#define mc_end (rpi_shader + 1398) +++#define mc_filter_uv (rpi_shader + 130) +++#define mc_filter_uv_b0 (rpi_shader + 312) +++#define mc_filter_uv_b (rpi_shader + 464) +++#define mc_exit (rpi_shader + 640) +++#define mc_interrupt_exit8 (rpi_shader + 658) +++#define mc_setup (rpi_shader + 688) +++#define mc_filter (rpi_shader + 1048) +++#define mc_filter_b (rpi_shader + 1174) +++#define mc_interrupt_exit12 (rpi_shader + 1302) +++#define mc_exit1 (rpi_shader + 1340) +++#define mc_end (rpi_shader + 1356) ++ ++ #endif ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index a0b8e5a..60d1ec2 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -21,6 +21,7 @@ ++ # ++ # ra16 clipped(row start address+elem_num)&~3 ++ # ra17 per-channel shifts +++# ra18 0x4000 ++ # ra19 next ra17 ++ # ++ # rb16 pitch ++@@ -86,7 +87,7 @@ ++ ++ ++ ################################################################################ ++-# mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, pad0, pad1, pad2) +++# mc_setup_uv(next_kernel, x, y, ref_u_base, ref_v_base, frame_width, frame_height, pitch, dst_pitch, offset, denom, vpm_id) ++ ::mc_setup_uv ++ ++ # Read starting kernel ++@@ -132,36 +133,6 @@ mov ra13, 0 ++ mov ra14, 0 ++ mov ra15, 0 ++ ++-# Compute part of VPM to use for DMA output ++-mov r3, unif ++-shl r2, r3, 1 # Convert QPU numbers to be even (this means we can only use 8 QPUs, but is necessary as we need to save 16bit intermediate results) ++-and r2, r2, 15 ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later ++-shl r0, r0, 5 ++-add rb27, r0, r1 ++- ++-# Compute part of VPM to save data into ++-shl r2, r3, 1 ++-and r2, r2, 15 # r2 = bcd0 ++-mov r1, r2 # r1 = bcd0 ++-asr r1, r1, 2 # r1 = bc ++-shl r1, r1, 6 # r1 = bc000000 ++-mov r0, r2 # r0 = bcd0 ++-and r0, r0, 3 # r0 = d0 ++-add r0, r0, r1 # r0 = bc0000d0 ++-mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit ++-add rb28, r0, r1 ++-asr r0, r0, 1 # r0 = bc0000d ++-# Prepare VPM command for 16bit intermediates ++-mov r1, vpm_setup(0, 2, h16p(0, 0)) # 2 is stride - stride acts on ADDR which is Y[5:0],H[0] for 16 bit ++-add rb21, r0, r1 ++- ++ # Compute base address for first and second access ++ mov r0, ra_x # Load x ++ max r0, r0, 0; mov r1, ra_y # Load y ++@@ -175,10 +146,31 @@ min r1, r1, rb_frame_height_minus_1 ++ # submit texture requests for first line ++ add r2, r2, r0 ; mul24 r1, r1, rb_pitch ++ add t0s, r0, r1 ; mov ra_frame_base, r2 ++-add t0s, r2, r1 +++add t1s, r2, r1 +++ +++mov r2,8 +++shl rb12,unif, r2 # offset before shift +++add rb13,unif,r2 # offset after shift +++ +++# Compute part of VPM to use for DMA output +++mov r2, unif +++shl r2, r2, 1 # Convert QPU numbers to be even (this means we can only use 8 QPUs, but is necessary as we need to save 16bit intermediate results) +++and r2, r2, 15 +++mov r1, r2 +++asr r1, r1, 2 +++shl r1, r1, 6 +++mov r0, r2 +++and r0, r0, 3 +++add r0, r0, r1 ++ ++-mov rb12,unif # offset before shift ++-mov rb13,unif # offset after shift +++mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit +++add rb28, r0, r1 # VPM 8bit storage +++asr r2, r0, 1 # r0 = bc0000d +++mov r1, vpm_setup(0, 2, h16p(0, 0)) # 2 is stride - stride acts on ADDR which is Y[5:0],H[0] for 16 bit +++add rb21, r2, r1 # VPM for 16bit intermediates +++mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later +++shl r0, r0, 5 +++add rb27, r0, r1 # DMA out ++ ++ # submit texture requests for second line ++ max r1, ra_y, 0 ++@@ -187,7 +179,7 @@ add ra_y, ra_y, 1 ++ bra -, ra31 ++ nop ; mul24 r1, r1, rb_pitch ++ add t0s, r1, ra_x ++-add t0s, r1, ra_frame_base +++add t1s, r1, ra_frame_base ++ ++ ++ ++@@ -248,17 +240,15 @@ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ mov r0, unif # U offset/weight ++ asr rb15, r0, r2 # Compute offset from MSBs ++ shl r0, r0, r2 ++-asr rb14, r0, r2 # Compute weight from LSBs +++asr r3, r0, r2 # Compute weight from LSBs ++ mov r0, unif # V offset/weight ++ asr.ifnz rb15, r0, r2 ++ shl r0, r0, r2 ++-asr.ifnz rb14, r0, r2 +++asr.ifnz r3, r0, r2 +++shl rb14,r3,8 # Scale up weights so we can use mul24 in signed fashion ++ ++ # r2 is elem_num ++ # r3 is loop counter ++- ++-mov r5rep, -8 ++- ++ # retrieve texture results and pick out bytes ++ # then submit two more texture requests ++ ++@@ -269,7 +259,7 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 ++ mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++@@ -278,7 +268,7 @@ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++ add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_frame_base, r2 +++add t1s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -301,11 +291,6 @@ mov ra13, ra14 # Delay slot 1 ++ mov ra14, ra15 # Delay slot 2 ++ mov ra15, r0 # Delay slot 3 ++ ++-mov rb12,32 # TODO remove these to make P weighted prediction work properly ++-mov rb13,6 ++-mov rb14,1 ++-mov rb15,0 ++- ++ # apply vertical filter and write to VPM ++ ++ nop ; mul24 r1, ra14, rb10 ++@@ -412,7 +397,7 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 ++ mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++@@ -421,7 +406,7 @@ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++ add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_frame_base, r2 +++add t1s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -542,7 +527,7 @@ mov r3, 0 ++ # then submit two more texture requests ++ ++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 # loop counter increment ++-shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu0 +++shr r0, r4, ra_xshift ; mov.ifz ra_x, rb_x_next ; ldtmu1 ++ mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++ shr r1, r4, ra_xshift ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++@@ -551,7 +536,7 @@ max r2, ra_y, 0 # y ++ min r2, r2, rb_frame_height_minus_1 ++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++ add t0s, ra_x, r2 ; v8subs r1, r1, rb20 ++-add t0s, ra_frame_base, r2 +++add t1s, ra_frame_base, r2 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++@@ -617,9 +602,9 @@ mov -, vw_wait # wait on the VDW ++ mov -,srel(0) ++ ++ ldtmu0 +++ldtmu1 ++ ldtmu0 ++-ldtmu0 ++-ldtmu0 +++ldtmu1 ++ ++ nop ; nop ; thrend ++ nop ; nop # delay slot 1 ++@@ -630,9 +615,9 @@ nop ; nop # delay slot 2 ++ mov -, vw_wait # wait on the VDW ++ ++ ldtmu0 +++ldtmu1 ++ ldtmu0 ++-ldtmu0 ++-ldtmu0 +++ldtmu1 ++ ++ mov -,sacq(0) # 1 ++ mov -,sacq(0) # 2 ++@@ -656,200 +641,249 @@ nop ; nop # delay slot 2 ++ # For P frames we make the second x,y coordinates offset by +8 ++ ++ ################################################################################ ++-# mc_setup(next_kernel, x, y, ref_y_base, x2, y2, ref_y2_base, frame_width, frame_height, pitch, dst_pitch, offset, shift, pad2) +++# mc_setup(y_x, ref_y_base, y2_x2, ref_y2_base, frame_width_height, pitch, dst_pitch, offset_shift, next_kernel) ++ ::mc_setup +++ mov r3, 16 ++ ++-# Read starting kernel ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-mov ra31, unif ++- ++-# Compute base address for first and second access ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl ra_xshift_next, r0, 3 # Compute shifts ++-add ra_y, r1, 1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add r2, r2, r0 # r2 is address for frame0 (not including y offset) ++-max r1, r1, 0 ++-min r1, r1, rb_frame_height_minus_1 ++-nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 ++-add t0s, r2, r1 ; mov ra_frame_base, r2 ++- ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl rx_xshift2_next, r0, 3 # Compute shifts ++-add ra_y2, r1, 1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add r2, r2, r0 # r2 is address for frame1 (not including y offset) ++-max r1, r1, 0 ++-min r1, r1, rb_frame_height_minus_1 ++-nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 ++-add t0s, r2, r1 ; mov ra_frame_base2, r2 ++- +++ # Need to save these because we need to know the frame dimensions before computing texture coordinates +++ mov ra8, unif +++ mov ra9, unif +++ mov ra10, unif +++ mov ra11, unif ++ ++ # Read image dimensions ++-sub rb25,unif,1 ++-sub rb30,unif,1 +++ mov r1, unif # width_height +++ shl r0,r1,r3 +++ asr r1,r1,r3 # width +++ asr r0,r0,r3 # height +++ sub rb_frame_width_minus_1,r1,1 +++ sub rb_frame_height_minus_1,r0,1 ++ ++ # get source pitch ++-mov rb16, unif +++ mov rb_pitch, unif ++ ++ # get destination pitch ++-mov r0, unif ++-mov r1, vdw_setup_1(0) ++-add rb24, r1, r0 +++ mov r0, unif +++ mov r1, vdw_setup_1(0) +++ add rb24, r1, r0 ++ ++-# load constants ++- ++-mov ra20, 1 ++-mov ra22, 256 ++-mov ra30, 64 ++- ++-mov rb20, 0xffffff00 ++-mov rb22, 255 ++-mov rb23, 24 +++# Compute base address for first and second access +++ mov r1, ra8 # y_x +++ shl r0,r1,r3 # r0 is x<<16 +++ asr r1,r1,r3 # r1 is y +++ asr r0,r0,r3 # r0 is x +++ add r0, r0, elem_num # Load x +++ max r0, r0, 0 +++ min r0, r0, rb_frame_width_minus_1 ; mov r2, ra9 # Load the frame base +++ shl ra_xshift_next, r0, 3 # Compute shifts +++ add ra_y, r1, 1 +++ and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++ add r2, r2, r0 # r2 is address for frame0 (not including y offset) +++ max r1, r1, 0 +++ min r1, r1, rb_frame_height_minus_1 +++ nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 +++ add t0s, r2, r1 ; mov ra_frame_base, r2 +++ +++ mov r1, ra10 # y_x +++ shl r0,r1,r3 # r0 is x<<16 +++ asr r1,r1,r3 # r1 is y +++ asr r0,r0,r3 # r0 is x +++ add r0, r0, elem_num # Load x +++ max r0, r0, 0 +++ min r0, r0, rb_frame_width_minus_1 ; mov r2, ra11 # Load the frame base +++ shl rx_xshift2_next, r0, 3 # Compute shifts +++ add ra_y2, r1, 1 +++ and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++ add r2, r2, r0 # r2 is address for frame1 (not including y offset) +++ max r1, r1, 0 +++ min r1, r1, rb_frame_height_minus_1 +++ nop ; mul24 r1, r1, rb_pitch # r2 contains the addresses (not including y offset) for frame0 +++ add t1s, r2, r1 ; mov ra_frame_base2, r2 ++ ++-# touch vertical context to keep simulator happy ++ ++-mov ra8, 0 ++-mov ra9, 0 ++-mov ra10, 0 ++-mov ra11, 0 ++-mov ra12, 0 ++-mov ra13, 0 ++-mov ra14, 0 ++-mov ra15, 0 +++# load constants ++ ++-# Compute part of VPM to use for DMA output ++-mov r2, qpu_num ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later ++-shl r0, r0, 5 ++-add rb27, r0, r1 +++ mov ra20, 1 +++ mov ra22, 256 +++ mov ra30, 64 ++ ++-# Compute part of VPM to save data into ++-mov r2, qpu_num # qpu_num = abcd ++-mov r1, r2 ++-asr r1, r1, 2 ++-shl r1, r1, 6 ++-mov r0, r2 ++-and r0, r0, 3 ++-add r0, r0, r1 ++-mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit ++-add rb28, r0, r1 +++ mov rb20, 0xffffff00 +++ mov rb22, 255 +++ mov rb23, 24 ++ ++-mov rb12,unif # offset before shift ++-mov rb13,unif # shift +++# touch vertical context to keep simulator happy ++ ++-# Dump padding words ++-mov r0, unif +++ mov ra8, 0 +++ mov ra9, 0 +++ mov ra10, 0 +++ mov ra11, 0 +++ mov ra12, 0 +++ mov ra13, 0 +++ mov ra14, 0 +++ mov ra15, 0 +++ mov ra18, 0x4000 +++ +++# Compute part of VPM to use +++ mov r2, qpu_num +++ mov r1, r2 +++ asr r1, r1, 2 +++ shl r1, r1, 6 +++ mov r0, r2 +++ and r0, r0, 3 +++ add r0, r0, r1 +++ mov r1, vpm_setup(0, 4, h8p(0, 0)) # 4 is stride - stride acts on ADDR which is Y[5:0],B[1:0] for 8 bit +++ add rb28, r0, r1 # VPM for saving data +++ mov r1, vdw_setup_0(0, 0, dma_h8p(0,0,0)) # height,width added later +++ shl r0, r0, 5 +++ add rb27, r0, r1 # Command for dma output +++ +++# Weighted prediction denom +++ +++ mov r1, unif # offset_shift +++ shl r0,r1,r3 ; mov r2,8 +++ asr rb13,r0,r3 # shift +++ asr rb12,r1,r3 # offset +++ add rb13,rb13,r2 # mul24 is unsigned so scale up into high bits +++ shl rb12, rb12, r2 # Account for larger shift ++ ++ # submit texture requests for second line ++-max r1, ra_y, 0 ++-min r1, r1, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ++-nop ; mul24 r1, r1, rb_pitch ++-add t0s, r1, ra_frame_base ++- ++-max r1, ra_y2, 0 ++-min r1, r1, rb_frame_height_minus_1 ++-bra -, ra31 ++-add ra_y2, ra_y2, 1 # Delay 1 ++-nop ; mul24 r1, r1, rb_pitch # Delay 2 ++-add t0s, r1, ra_frame_base2 # Delay 3 ++- ++- ++-################################################################################ ++- ++-# mc_filter(next_kernel, x, y, frame_base, x2, y2, frame_base2, height, hcoeffs[0], hcoeffs2[0], hcoeffs[1], hcoeffs2[1], vcoeffs[0], vcoeffs2[0], vcoeffs[1], vcoeffs2[1], offsetweight0, offsetweight1, this_dst) ++-# In a P block, only the first half of coefficients contain used information. ++-# At this point we have already issued two pairs of texture requests for the current block ++-# ra_x, ra_x16_base point to the current coordinates for this block ++-::mc_filter ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-mov ra31, unif +++ max r1, ra_y, 0 +++ min r1, r1, rb_frame_height_minus_1 +++ add ra_y, ra_y, 1 +++ nop ; mul24 r1, r1, rb_pitch +++ add t0s, r1, ra_frame_base +++ +++ max r1, ra_y2, 0 +++ min r1, r1, rb_frame_height_minus_1 +++ add ra_y2, ra_y2, 1 +++ nop ; mul24 r1, r1, rb_pitch +++ add t1s, r1, ra_frame_base2 +++ +++# FALL THROUGHT TO PER-BLOCK SETUP +++ +++# Start of per-block setup code +++# P and B blocks share the same setup code to save on Icache space +++:per_block_setup +++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ mov ra31, unif ++ ++ # per-channel shifts were calculated on the *previous* invocation ++- ++-mov ra_xshift, ra_xshift_next ++-mov rx_xshift2, rx_xshift2_next +++ mov ra_xshift, ra_xshift_next +++ mov rx_xshift2, rx_xshift2_next ++ ++ # get base addresses and per-channel shifts for *next* invocation ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl ra_xshift_next, r0, 3 # Compute shifts ++-mov ra_y_next, r1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add ra_frame_base_next, r2, r0 # r2 is address for frame0 (not including y offset) ++- ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0 ; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl rx_xshift2_next, r0, 3 # Compute shifts ++-add ra_y2_next, r1, 1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add rx_frame_base2_next, r2, r0 # r2 is address for frame1 (not including y offset) ++- +++ mov r3, 16 +++ mov r1, unif # y_x +++ shl r0,r1,r3 # r0 is x<<16 +++ asr r1,r1,r3 # r1 is y +++ asr r0,r0,r3 # r0 is x +++ add r0, r0, elem_num # Load x +++ max r0, r0, 0 +++ min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++ shl ra_xshift_next, r0, 3 # Compute shifts +++ mov ra_y_next, r1 +++ and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++ add ra_frame_base_next, r2, r0 ; mov r1, unif # y2_x2 +++ +++ shl r0,r1,r3 # r0 is x2<<16 +++ asr r1,r1,r3 # r1 is y2 +++ asr r0,r0,r3 # r0 is x2 +++ add r0, r0, elem_num # Load x +++ max r0, r0, 0 +++ min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base +++ shl rx_xshift2_next, r0, 3 # Compute shifts +++ mov ra_y2_next, r1 +++ and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate +++ add rx_frame_base2_next, r2, r0 # r2 is address for frame1 (not including y offset) ++ ++ # set up VPM write ++-mov vw_setup, rb28 +++ mov vw_setup, rb28 ++ ++ # get width,height of block ++-mov r2, 16 ++-mov r0, unif ++-shr r1, r0, r2 # Extract width ++-sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++-and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 ++-shl r0, r0, 7 ++-add r0, r0, r1 # Combine width and height of destination area ++-shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++-add rb26, r0, rb27 +++ mov r0, unif +++ shr r1, r0, r3 # Extract width +++ sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) +++ and r0, r0, rb22 # Extract height +++ add rb17, r0, 5 +++ add rb18, r0, 7 +++ shl r0, r0, 7 +++ add r0, r0, r1 # Combine width and height of destination area +++ shl r0, r0, r3 # Shift into bits 16 upwards of the vdw_setup0 register +++ add rb26, r0, rb27 ++ ++ # get filter coefficients and discard unused B frame values ++-mov r0, unif ++-mov.ifnz -, unif # Alternate coefficients are unused for P frames ++-asr ra3, r0, rb23; mul24 r0, r0, ra22 # These may need some pre-rotation to be used in B frames correctly ++-asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-asr ra0, r0, rb23; mov r0, unif ++-mov.ifnz -, unif ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-asr ra4, r0, rb23; mov r0, unif ++-mov.ifnz -, unif ++-asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif ++-mov.ifnz -, unif ++-asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-asr rb5, r0, rb23; mul24 r0, r0, ra22 ++-asr rb4, r0, rb23 ++- ++-mov r0, unif # Frame0 offset/weight ++-mov.ifnz -, unif # Frame1 offset/weight unused ++-asr rb15, r0, r2 # Compute offset from MSBs ++-shl r0, r0, r2 ++-asr rb14, r0, r2 # Compute weight from LSBs ++- ++-# r3 is loop counter +++ mov r0, unif ; mov r1,1 # Packed filter offsets, unpack into ra8... (to be used for vertical context later) +++ asr ra9, r0, rb23; mul24 r0, r0, ra22 # my2 +++ asr ra8, r0, rb23; mul24 r0, r0, ra22 # mx2 +++ asr.ifz ra9, r0, rb23; mul24 r0, r0, ra22 # my:my2 +++ asr.ifz ra8, r0, rb23 # mx:mx2 +++ sub ra9,3,ra9 +++ sub ra8,3,ra8 +++ shl ra9,ra9,3 # Scale up by 8 +++ shl ra8,ra8,3 # Scale up by 8 +++# Now if we want aligned we have a mul of 1, so put 0 coefficients at the top +++ mov r1,0xffff00 +++ shl r0, r1, ra8 +++ asr ra0, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb4, r0, rb23 +++ +++ mov r1,0x1040400 +++ shl r0, r1, ra8 +++ asr ra1, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb5, r0, rb23 +++ +++ mov r1,0xfbf5f600 +++ shl r0, r1, ra8 +++ asr ra2, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb6, r0, rb23 +++ +++ mov r1,0x11283a40 +++ shl r0, r1, ra8 +++ asr ra3, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb7, r0, rb23 +++ +++ mov r1,0x3a281100 +++ shl r0, r1, ra8 +++ asr ra4, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb8, r0, rb23 +++ +++ mov r1,0xf6f5fb00 +++ shl r0, r1, ra8 +++ asr ra5, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb9, r0, rb23 +++ +++ mov r1,0x4040100 +++ shl r0, r1, ra8 +++ asr ra6, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb10, r0, rb23 +++ +++ mov r1,0xffff0000 +++ shl r0, r1, ra8 +++ asr ra7, r0, rb23 +++ shl r0, r1, ra9 +++ asr rb11, r0, rb23 +++ +++# Extract weighted prediction information +++ mov r0, unif # offset/weight TODO move up +++ asr rb15, r0, r3 # Compute offset from MSBs +++ bra -, ra31 +++ shl r0, r0, r3 # Delay 1 +++ asr r0, r0, r3 ; mov r3, 0 # Compute weight from LSBs and reset loop counter Delay 2 +++ shl rb14, r0, 8 # Use a larger shift to avoid unsigned multiply problem Delay 3 ++ ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests +++################################################################################ +++# mc_filter(y_x, frame_base, y2_x2, frame_base2, width_height, my2_mx2_my_mx, offsetweight0, this_dst, next_kernel) +++# In a P block, y2_x2 should be y_x+8 +++# At this point we have already issued two pairs of texture requests for the current block ++ ++-mov r3, 0 +++::mc_filter ++ ++ :yloop ++ # retrieve texture results and pick out bytes ++@@ -858,91 +892,90 @@ mov r3, 0 ++ # If we knew there was no clipping then this code would get simpler. ++ # Perhaps we could add on the pitch and clip using larger values? ++ ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, rx_xshift2 ++-mov.ifz ra_y2, ra_y2_next +++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++ shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu1 +++ mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++ shr r1, r4, rx_xshift2 +++ mov.ifz ra_y2, ra_y2_next ++ ++-max r2, ra_y, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++- ++-max r2, ra_y2, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++ max r2, ra_y, 0 # y +++ min r2, r2, rb_frame_height_minus_1 +++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++ add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ +++ max r2, ra_y2, 0 # y +++ min r2, r2, rb_frame_height_minus_1 +++ add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++ add t1s, ra_frame_base2, r2 ; v8subs r1, r1, rb20 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++ ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++ # apply horizontal filter ++-nop ; mul24 r2, r0, ra0 ++-nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-nop ; mul24 r3, ra1 << 1, r0 << 1 ++-nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-add r0, r2, r3 ; mov r3, rb31 ++-sub.setf -, r3, 8 ; mov ra12, ra13 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++-mov ra12, ra13 ++-brr.anyn -, r:yloop ++-mov ra13, ra14 # Delay slot 1 ++-mov ra14, ra15 # Delay slot 2 ++-mov ra15, r0 # Delay slot 3 +++ nop ; mul24 r2, r0, ra0 +++ nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++ nop ; mul24 r3, ra1 << 1, r0 << 1 +++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++ add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++ nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++ add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++ nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++ add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++ nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++ add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++ nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++ add r0, r2, r3 ; mov r3, rb31 +++ sub.setf -, r3, 8 ; mov ra8, ra9 +++ mov ra9, ra10 +++ mov ra10, ra11 +++ mov ra11, ra12 +++ mov ra12, ra13 +++ brr.anyn -, r:yloop +++ mov ra13, ra14 # Delay slot 1 +++ mov ra14, ra15 # Delay slot 2 +++ mov ra15, r0 # Delay slot 3 ++ ++ # apply vertical filter and write to VPM ++ ++-nop ; mul24 r1, ra14, rb10 ++-nop ; mul24 r0, ra13, rb9 ++-add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-add r1, r1, r0 ; mul24 r0, ra11, rb7 ++- ++-add r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 14 ++-nop ; mul24 r1, r1, rb14 ++-add r1, r1, rb12 ++-asr r1, r1, rb13 ++-brr.anyn -, r:yloop ++-add r1, r1, rb15 # Delay 1 ++-min r1, r1, rb22 # Delay 2 ++-max vpm, r1, 0 # Delay 3 +++ nop ; mul24 r1, ra14, rb10 +++ nop ; mul24 r0, ra13, rb9 +++ add r1, r1, r0 ; mul24 r0, ra12, rb8 +++ add r1, r1, r0 ; mul24 r0, ra15, rb11 +++ add r1, r1, r0 ; mul24 r0, ra8, rb4 +++ add r1, r1, r0 ; mul24 r0, ra9, rb5 +++ add r1, r1, r0 ; mul24 r0, ra10, rb6 +++ add r1, r1, r0 ; mul24 r0, ra11, rb7 +++ +++ add r1, r1, r0 ; mov -, vw_wait +++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++ asr r1, r1, 14 +++ nop ; mul24 r1, r1, rb14 +++ add r1, r1, rb12 +++ asr r1, r1, rb13 +++ brr.anyn -, r:yloop +++ add r1, r1, rb15 # Delay 1 +++ min r1, r1, rb22 # Delay 2 +++ max vpm, r1, 0 # Delay 3 ++ ++ # DMA out ++ ++-bra -, ra31 ++-mov vw_setup, rb26 # VDW setup 0 Delay 1 ++-mov vw_setup, rb29 # Stride Delay 2 ++-mov vw_addr, unif # start the VDW Delay 3 +++ brr -, r:per_block_setup +++ mov vw_setup, rb26 # VDW setup 0 Delay 1 +++ mov vw_setup, rb29 # Stride Delay 2 +++ mov vw_addr, unif # start the VDW Delay 3 ++ ++ ++ ++ ################################################################################ ++ ++-# mc_filter_b(next_kernel, x, y, frame_base, x2, y2, frame_base2, width_height, hcoeffs[0], hcoeffs2[0], hcoeffs[1], hcoeffs2[1], vcoeffs[0], vcoeffs2[0], vcoeffs[1], vcoeffs2[1], offsetweight0, offsetweight1, this_dst) +++# mc_filter_b(y_x, frame_base, y2_x2, frame_base2, width_height, my2_mx2_my_mx, offsetweight0, this_dst, next_kernel) ++ # In a P block, only the first half of coefficients contain used information. ++ # At this point we have already issued two pairs of texture requests for the current block ++ # May be better to just send 16.16 motion vector and figure out the coefficients inside this block (only 4 cases so can compute hcoeffs in around 24 cycles?) ++@@ -952,92 +985,6 @@ mov vw_addr, unif # start the VDW Delay 3 ++ # Or possibly by taking advantage of symmetry? ++ # From 19->7 32bits per command. ++ ::mc_filter_b ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++-mov ra31, unif ++- ++-# per-channel shifts were calculated on the *previous* invocation ++- ++-mov ra_xshift, ra_xshift_next ++-mov rx_xshift2, rx_xshift2_next ++- ++-# get base addresses and per-channel shifts for *next* invocation ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl ra_xshift_next, r0, 3 # Compute shifts ++-mov ra_y_next, r1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add ra_frame_base_next, r2, r0 # r2 is address for frame0 (not including y offset) ++- ++-add r0, unif, elem_num # Load x ++-max r0, r0, 0 ; mov r1, unif # Load y ++-min r0, r0, rb_frame_width_minus_1 ; mov r2, unif # Load the frame base ++-shl rx_xshift2_next, r0, 3 # Compute shifts ++-add ra_y2_next, r1, 1 ++-and r0, r0, ~3 # r0 gives the clipped and aligned x coordinate ++-add rx_frame_base2_next, r2, r0 # r2 is address for frame1 (not including y offset) ++- ++- ++-# set up VPM write ++-mov vw_setup, rb28 ++- ++-# get width,height of block ++-mov r2, 16 ++-mov r0, unif ++-shr r1, r0, r2 # Extract width ++-sub rb29, rb24, r1 # Compute vdw_setup1(dst_pitch-width) ++-and r0, r0, rb22 # Extract height ++-add rb17, r0, 5 ++-add rb18, r0, 7 ++-shl r0, r0, 7 ++-add r0, r0, r1 # Combine width and height of destination area ++-shl r0, r0, r2 # Shift into bits 16 upwards of the vdw_setup0 register ++-add rb26, r0, rb27 ++- ++-# get filter coefficients and discard unused B frame values ++-mov r0, unif ++-mov r1, 1 ++-mov.ifnz r0, unif # Alternate coefficients are unused for P frames ++-nop ; mul24 r0, r0 << 13, r1 << 13 ++-asr ra3, r0, rb23; mul24 r0, r0, ra22 ++-nop ; mul24 r0, r0 << 14, r1 << 14 ++-asr ra2, r0, rb23; mul24 r0, r0, ra22 ++-nop ; mul24 r0, r0 << 15, r1 << 15 # Adjust such that a rotate of 1 will produce the values with first 8 on left, second 8 on right ++-asr ra1, r0, rb23; mul24 r0, r0, ra22 ++-asr ra0, r0, rb23; mov r0, unif ++-mov.ifnz r0, unif ++-nop ; mul24 r0, r0 << 9, r1 << 9 ++-asr ra7, r0, rb23; mul24 r0, r0, ra22 ++-nop ; mul24 r0, r0 << 10, r1 << 10 ++-asr ra6, r0, rb23; mul24 r0, r0, ra22 ++-nop ; mul24 r0, r0 << 11, r1 << 11 ++-asr ra5, r0, rb23; mul24 r0, r0, ra22 ++-nop ; mul24 r0, r0 << 12, r1 << 12 ++-asr ra4, r0, rb23; mov r0, unif ++-mov.ifnz r0, unif ++-asr rb11, r0, rb23; mul24 r0, r0, ra22 ++-asr rb10, r0, rb23; mul24 r0, r0, ra22 ++-asr rb9, r0, rb23; mul24 r0, r0, ra22 ++-asr rb8, r0, rb23; mov r0, unif ++-mov.ifnz r0, unif ++-asr rb7, r0, rb23; mul24 r0, r0, ra22 ++-asr rb6, r0, rb23; mul24 r0, r0, ra22 ++-asr rb5, r0, rb23; mul24 r0, r0, ra22 ++-asr rb4, r0, rb23 ++- ++-mov r0, unif # Frame0 offset/weight ++-mov.ifnz r0, unif # Frame1 offset/weight unused ++-asr rb15, r0, r2 # Compute offset from MSBs ++-shl r0, r0, r2 ++-asr rb14, r0, r2 # Compute weight from LSBs ++- ++-# r3 is loop counter ++- ++-# retrieve texture results and pick out bytes ++-# then submit two more texture requests ++- ++-mov r3, 0 ++- ++ :yloopb ++ # retrieve texture results and pick out bytes ++ # then submit two more texture requests ++@@ -1045,111 +992,123 @@ mov r3, 0 ++ # If we knew there was no clipping then this code would get simpler. ++ # Perhaps we could add on the pitch and clip using larger values? ++ ++-sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 ++-shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu0 ++-mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 ++-mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch ++-shr r1, r4, rx_xshift2 ++-mov.ifz ra_y2, ra_y2_next +++ sub.setf -, r3, rb17 ; v8adds r3, r3, ra20 ; ldtmu0 +++ shr r0, r4, ra_xshift ; mov.ifz ra_frame_base2, rx_frame_base2_next ; ldtmu1 +++ mov.ifz ra_frame_base, ra_frame_base_next ; mov rb31, r3 +++ mov.ifz ra_y, ra_y_next ; mov r3, rb_pitch +++ shr r1, r4, rx_xshift2 +++ mov.ifz ra_y2, ra_y2_next ++ ++-max r2, ra_y, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y, ra_y, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++- ++-max r2, ra_y2, 0 # y ++-min r2, r2, rb_frame_height_minus_1 ++-add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 ++-add t0s, ra_frame_base2, r2 ; v8subs r0, r0, rb20 +++ max r2, ra_y, 0 # y +++ min r2, r2, rb_frame_height_minus_1 +++ add ra_y, ra_y, 1 ; mul24 r2, r2, r3 +++ add t0s, ra_frame_base, r2 ; v8subs r0, r0, rb20 # v8subs masks out all but bottom byte ++ +++ max r2, ra_y2, 0 # y +++ min r2, r2, rb_frame_height_minus_1 +++ add ra_y2, ra_y2, 1 ; mul24 r2, r2, r3 +++ add t1s, ra_frame_base2, r2 ; v8subs r1, r1, rb20 ++ ++ # generate seven shifted versions ++ # interleave with scroll of vertical context ++ ++-mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] +++ mov.setf -, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] ++ ++ # apply horizontal filter ++-nop ; mul24 r2, r0, ra0 ++-nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 ++-nop ; mul24 r3, ra1 << 1, r0 << 1 ++-nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 ++-add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 ++-nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 ++-add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 ++-nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 ++-add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 ++-nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 ++-add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 ++-nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 ++-add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 ++-nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 ++-add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 ++-nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 ++-add r0, r2, r3 ; mov r3, rb31 ++-sub.setf -, r3, 8 ; mov ra12, ra13 ++-mov ra9, ra10 ++-mov ra10, ra11 ++-mov ra11, ra12 ++-mov ra12, ra13 ++-brr.anyn -, r:yloopb ++-mov ra13, ra14 # Delay slot 1 ++-mov ra14, ra15 # Delay slot 2 ++-mov ra15, r0 # Delay slot 3 ++- ++-# apply vertical filter and write to VPM ++- ++-nop ; mul24 r1, ra14, rb10 ++-nop ; mul24 r0, ra13, rb9 ++-add r1, r1, r0 ; mul24 r0, ra12, rb8 ++-add r1, r1, r0 ; mul24 r0, ra15, rb11 ++-add r1, r1, r0 ; mul24 r0, ra8, rb4 ++-add r1, r1, r0 ; mul24 r0, ra9, rb5 ++-add r1, r1, r0 ; mul24 r0, ra10, rb6 ++-add r1, r1, r0 ; mul24 r0, ra11, rb7 ++- ++-add r1, r1, r0 ; mov -, vw_wait ++-sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 ++-asr r1, r1, 14 ++-nop ; mul24 r1, r1 << 8, ra20 << 8 # Rotate to align left and right halves ++-add r1, r1, ra30 ; mul24 r0, r1, rb14 ++-add r1, r1, r0 ++-brr.anyn -, r:yloopb ++-asr r1, r1, 7 # Delay 1 ++-min r1, r1, rb22 # Delay 2 ++-max vpm, r1, 0 # Delay 3 +++ nop ; mul24 r2, r0, ra0 +++ nop ; mul24.ifnz r2, ra0 << 8, r1 << 8 +++ nop ; mul24 r3, ra1 << 1, r0 << 1 +++ nop ; mul24.ifnz r3, ra1 << 9, r1 << 9 +++ add r2, r2, r3 ; mul24 r3, ra2 << 2, r0 << 2 +++ nop ; mul24.ifnz r3, ra2 << 10, r1 << 10 +++ add r2, r2, r3 ; mul24 r3, ra3 << 3, r0 << 3 +++ nop ; mul24.ifnz r3, ra3 << 11, r1 << 11 +++ add r2, r2, r3 ; mul24 r3, ra4 << 4, r0 << 4 +++ nop ; mul24.ifnz r3, ra4 << 12, r1 << 12 +++ add r2, r2, r3 ; mul24 r3, ra5 << 5, r0 << 5 +++ nop ; mul24.ifnz r3, ra5 << 13, r1 << 13 +++ add r2, r2, r3 ; mul24 r3, ra6 << 6, r0 << 6 +++ nop ; mul24.ifnz r3, ra6 << 14, r1 << 14 +++ add r2, r2, r3 ; mul24 r3, ra7 << 7, r0 << 7 +++ nop ; mul24.ifnz r3, ra7 << 15, r1 << 15 +++ add r0, r2, r3 ; mov r3, rb31 +++ sub.setf -, r3, 8 ; mov ra8, ra9 +++ mov ra9, ra10 +++ mov ra10, ra11 +++ mov ra11, ra12 +++ mov ra12, ra13 +++ brr.anyn -, r:yloopb +++ mov ra13, ra14 # Delay slot 1 +++ mov ra14, ra15 # Delay slot 2 +++ mov ra15, r0 # Delay slot 3 +++ +++ # apply vertical filter and write to VPM +++ +++ nop ; mul24 r1, ra14, rb10 +++ nop ; mul24 r0, ra13, rb9 +++ add r1, r1, r0 ; mul24 r0, ra12, rb8 +++ add r1, r1, r0 ; mul24 r0, ra15, rb11 +++ add r1, r1, r0 ; mul24 r0, ra8, rb4 +++ add r1, r1, r0 ; mul24 r0, ra9, rb5 +++ add r1, r1, r0 ; mul24 r0, ra10, rb6 +++ add r1, r1, r0 ; mul24 r0, ra11, rb7 +++ +++ add r1, r1, r0 ; mov -, vw_wait +++ sub.setf -, r3, rb18 ; mul24 r1, r1, ra22 +++ asr r0, r1, 14 +++ asr r1, r1, 6 # Wait state so we can use the rotate instruction +++ nop ; mul24 r0, r0 << 8, ra22 << 8 # Rotate to align left and right halves +++ add r1, r1, ra18 +++ add r1, r1, r0 +++ brr.anyn -, r:yloopb +++ asr r1, r1, 15 # Delay 1 +++ min r1, r1, rb22 # Delay 2 +++ max vpm, r1, 0 # Delay 3 ++ ++ # DMA out ++-bra -, ra31 ++-mov vw_setup, rb26 # VDW setup 0 Delay 1 ++-mov vw_setup, rb29 # Stride Delay 2 ++-mov vw_addr, unif # start the VDW Delay 3 +++ brr -, r:per_block_setup +++ mov vw_setup, rb26 # VDW setup 0 Delay 1 +++ mov vw_setup, rb29 # Stride Delay 2 +++ mov vw_addr, unif # start the VDW Delay 3 ++ ++ ################################################################################ ++ ++ # mc_interrupt_exit12() ++ ::mc_interrupt_exit12 ++-mov -, vw_wait # wait on the VDW ++- ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++-ldtmu0 ++- ++-mov -,sacq(0) # 1 ++-mov -,sacq(0) # 2 ++-mov -,sacq(0) # 3 ++-mov -,sacq(0) # 4 ++-mov -,sacq(0) # 5 ++-mov -,sacq(0) # 6 ++-mov -,sacq(0) # 7 ++-mov -,sacq(0) # 8 ++-mov -,sacq(0) # 9 ++-mov -,sacq(0) # 10 ++-mov -,sacq(0) # 11 ++- ++-nop ; nop ; thrend ++-mov interrupt, 1; nop # delay slot 1 ++-nop ; nop # delay slot 2 +++ mov -, vw_wait # wait on the VDW +++ +++ ldtmu0 +++ ldtmu0 +++ ldtmu1 +++ ldtmu1 +++ +++ mov -,sacq(0) # 1 +++ mov -,sacq(0) # 2 +++ mov -,sacq(0) # 3 +++ mov -,sacq(0) # 4 +++ mov -,sacq(0) # 5 +++ mov -,sacq(0) # 6 +++ mov -,sacq(0) # 7 +++ mov -,sacq(0) # 8 +++ mov -,sacq(0) # 9 +++ mov -,sacq(0) # 10 +++ mov -,sacq(0) # 11 +++ +++ nop ; nop ; thrend +++ mov interrupt, 1; nop # delay slot 1 +++ nop ; nop # delay slot 2 +++ +++ +++::mc_exit1 +++ mov -, vw_wait # wait on the VDW +++ +++ ldtmu0 +++ ldtmu1 +++ ldtmu0 +++ ldtmu1 +++ nop ; nop ; thrend +++ mov interrupt, 1; nop # delay slot 1 +++ nop ; nop # delay slot 2 ++ ++ ++ ::mc_end ++-- ++2.5.0 ++ ++ ++From e5b20751b9a026e127ff0cdd8768b1d37ca5aa27 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 2 Jun 2015 10:58:25 +0100 ++Subject: [PATCH 48/68] Added option to simulate QPUs ++ ++--- ++ libavcodec/hevc.c | 288 +++++++++++++++++++++++++++++++++++++++++++-- ++ libavcodec/rpi_qpu.c | 24 ++-- ++ libavcodec/rpi_shader.qasm | 6 +- ++ 3 files changed, 295 insertions(+), 23 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 11b9e60..9be5276 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -56,6 +56,8 @@ ++ // Define RPI_CACHE_UNIF_MVS to write motion vector uniform stream to cached memory ++ // RPI_CACHE_UNIF_MVS doesn't seem to make much difference, so left undefined. ++ +++ // Define RPI_SIMULATE_QPUS for debugging to run QPU code on the ARMs +++ //#define RPI_SIMULATE_QPUS ++ ++ #endif ++ ++@@ -124,7 +126,6 @@ static void pic_arrays_free(HEVCContext *s) ++ ++ #ifdef EARLY_MALLOC ++ #else ++- printf("pic_arrays_free\n"); ++ if (s->coeffs_buf_arm[0]) { ++ gpu_free(&s->coeffs_buf_default); ++ s->coeffs_buf_arm[0] = 0; ++@@ -174,11 +175,9 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ #ifdef RPI ++ #ifdef EARLY_MALLOC ++ #else ++- assert(sps); +++ av_assert0(sps); ++ int coeffs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); ++ int coefs_per_row = sps->ctb_width * coeffs_in_ctb * 3; // Allow space for chroma ++- printf("pic_arrays_init\n"); ++- printf("Allocated %d\n",coefs_per_row); ++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); ++ s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; ++ if (!s->coeffs_buf_arm[0]) ++@@ -2977,6 +2976,274 @@ static void rpi_inter_clear(HEVCContext *s) ++ #endif ++ } ++ +++ +++#ifdef RPI_SIMULATE_QPUS +++ +++static int32_t clipx(int x,int FRAME_WIDTH) +++{ +++ if (x<=0) return 0; +++ if (x>=FRAME_WIDTH) return FRAME_WIDTH-1; +++ return x; +++} +++ +++static int32_t clipy(int y,int FRAME_HEIGHT) +++{ +++ if (y<=0) return 0; +++ if (y>=FRAME_HEIGHT) return FRAME_HEIGHT-1; +++ return y; +++} +++ +++/*static int32_t filter8(uint8_t *data, int x0, int y0, int pitch, int mx, int my,int round,int denom,int weight,int offset) +++{ +++ int32_t vsum = 0; +++ int x, y; +++ +++ for (y = 0; y < 8; y++) { +++ int32_t hsum = 0; +++ +++ for (x = 0; x < 8; x++) +++ hsum += lumaFilter[mx][x]*data[clipx(x + x0) + clipy(y + y0) * pitch]; +++ +++ vsum += lumaFilter[my][y]*hsum; +++ } +++ vsum >>= 6; +++ vsum = (((vsum*weight)+round)>>denom)+offset; +++ +++ return av_clip_uint8( vsum ); +++}*/ +++ +++static int32_t filter8_chroma(uint8_t *data, int x0, int y0, int pitch, int hcoeffs, int vcoeffs,int offset_weight,int offset_before,int denom,int pic_width, int pic_height) +++{ +++ int32_t vsum = 0; +++ int x, y; +++ int chromaFilterH[4]; +++ int chromaFilterV[4]; +++ int i; +++ int offset_after = offset_weight>>16; +++ int weight = (offset_weight<<16)>>16; +++ for(i=0;i<4;i++) { +++ chromaFilterH[i] = ((hcoeffs>>(8*i))<<24)>>24; +++ chromaFilterV[i] = ((vcoeffs>>(8*i))<<24)>>24; +++ } +++ +++ for (y = 0; y < 4; y++) { +++ int32_t hsum = 0; +++ +++ for (x = 0; x < 4; x++) +++ hsum += chromaFilterH[x]*data[clipx(x + x0,pic_width) + clipy(y + y0,pic_height) * pitch]; +++ +++ vsum += chromaFilterV[y]*hsum; +++ } +++ vsum >>= 6; +++ vsum = (((vsum*weight)+offset_before)>>denom)+offset_after; +++ +++ return vsum; +++} +++ +++int lumaFilter[4][8]={ {0,0,0,64,0,0,0,0},{-1,4,-10,58,17,-5,1,0},{-1,4,-11,40,40,-11,4,-1},{0,1,-5,17,58,-10,4,-1} }; +++ +++static int32_t filter8_luma(uint8_t *data, int x0, int y0, int pitch, int my_mx,int offset_weight,int offset_before,int denom,int pic_width, int pic_height) +++{ +++ int32_t vsum = 0; +++ int x, y; +++ int i; +++ int offset_after = offset_weight>>16; +++ int weight = (offset_weight<<16)>>16; +++ +++ for (y = 0; y < 8; y++) { +++ int32_t hsum = 0; +++ +++ for (x = 0; x < 8; x++) +++ hsum += lumaFilter[my_mx&3][x]*data[clipx(x + x0,pic_width) + clipy(y + y0,pic_height) * pitch]; +++ +++ vsum += lumaFilter[(my_mx>>8)&3][y]*hsum; +++ } +++ vsum >>= 6; +++ vsum = (((vsum*weight)+offset_before)>>denom)+offset_after; +++ +++ return vsum; +++} +++ +++static uint8_t *test_frame(HEVCContext *s,uint32_t p, AVFrame *frame, int cIdx) +++{ +++ //int pic_width = s->ps.sps->width >> s->ps.sps->hshift[cIdx]; +++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[cIdx]; +++ int pitch = frame->linesize[cIdx]; +++ uint32_t base = get_vc_address(frame->buf[cIdx]); +++ if (p>=base && pdata[cIdx] + (p-base); +++ } +++ return NULL; +++} +++ +++static uint8_t *compute_arm_addr(HEVCContext *s,uint32_t p, int cIdx) +++{ +++ SliceHeader *sh = &s->sh; +++ uint8_t *arm = test_frame(s,p,s->frame,cIdx); +++ int i; +++ if (arm) return arm; +++ if (sh->slice_type == P_SLICE || sh->slice_type == B_SLICE) +++ { +++ for(i=0;inb_refs[L0];i++) { +++ arm = test_frame(s,p,s->ref->refPicList[0].ref[i]->frame,cIdx); +++ if (arm) return arm; +++ } +++ } +++ if (sh->slice_type == B_SLICE) { +++ for(i=0;inb_refs[L1];i++) { +++ arm = test_frame(s,p,s->ref->refPicList[1].ref[i]->frame,cIdx); +++ if (arm) return arm; +++ } +++ } +++ printf("Frame 0x%x not found! Exit=%x\n",p,qpu_get_fn(QPU_MC_EXIT)); +++ exit(-1); +++ return NULL; +++} +++ +++static void rpi_simulate_inter_chroma(HEVCContext *s,uint32_t *p) +++{ +++ uint32_t next_kernel; +++ uint32_t x0; +++ uint32_t y0; +++ uint8_t *ref_u_base; +++ uint8_t *ref_v_base; +++ uint32_t frame_width = p[5]; +++ uint32_t frame_height = p[6]; +++ uint32_t pitch = p[7]; +++ uint32_t dst_pitch = p[8]; +++ int32_t offset_before = p[9]; +++ int32_t denom = p[10]; +++ uint32_t vpm_id = p[11]; +++ uint32_t tmp_u_dst[256]; +++ uint32_t tmp_v_dst[256]; +++ while(1) { +++ p += 12; +++ next_kernel = p[0-12]; +++ x0 = p[1-12]; +++ y0 = p[2-12]; +++ if (next_kernel==s->mc_filter_uv || next_kernel==s->mc_filter_uv_b0 || next_kernel==s->mc_filter_uv_b) { +++ int x,y; +++ uint32_t width_height = p[5]; +++ uint32_t hcoeffs = p[6]; +++ uint32_t vcoeffs = p[7]; +++ uint32_t offset_weight_u = p[8]; +++ uint32_t offset_weight_v = p[9]; +++ uint8_t *this_u_dst; +++ uint8_t *this_v_dst; +++ uint32_t width = width_height >> 16; +++ uint32_t height = (width_height << 16) >> 16; +++ ref_u_base = compute_arm_addr(s,p[3-12],1); +++ ref_v_base = compute_arm_addr(s,p[4-12],2); +++ if (next_kernel!=s->mc_filter_uv_b0) +++ { +++ this_u_dst = compute_arm_addr(s,p[10],1); +++ this_v_dst = compute_arm_addr(s,p[11],2); +++ } +++ for (y=0; ymc_filter_uv) { +++ int32_t refa = filter8_chroma(ref_u_base,x+x0, y+y0, pitch, hcoeffs, vcoeffs, offset_weight_u,offset_before,denom,frame_width,frame_height); +++ int32_t refb = filter8_chroma(ref_v_base,x+x0, y+y0, pitch, hcoeffs, vcoeffs, offset_weight_v,offset_before,denom,frame_width,frame_height); +++ this_u_dst[x+y*dst_pitch] = av_clip_uint8(refa); +++ this_v_dst[x+y*dst_pitch] = av_clip_uint8(refb); +++ } else if (next_kernel==s->mc_filter_uv_b0) { +++ int32_t refa = filter8_chroma(ref_u_base, x+x0, y+y0, pitch, hcoeffs, vcoeffs, 1,0,0,frame_width,frame_height); +++ int32_t refb = filter8_chroma(ref_v_base, x+x0, y+y0, pitch, hcoeffs, vcoeffs, 1,0,0,frame_width,frame_height); +++ tmp_u_dst[x+y*16] = refa; +++ tmp_v_dst[x+y*16] = refb; +++ } else { +++ int32_t refa = filter8_chroma(ref_u_base, x+x0, y+y0, pitch, hcoeffs, vcoeffs, 1, 64 + tmp_u_dst[x+y*16], 7, frame_width, frame_height); +++ int32_t refb = filter8_chroma(ref_v_base, x+x0, y+y0, pitch, hcoeffs, vcoeffs, 1, 64 + tmp_v_dst[x+y*16], 7, frame_width, frame_height); +++ this_u_dst[x+y*dst_pitch] = av_clip_uint8(refa); +++ this_v_dst[x+y*dst_pitch] = av_clip_uint8(refb); +++ } +++ } +++ } +++ } else { +++ av_assert0(next_kernel==qpu_get_fn(QPU_MC_INTERRUPT_EXIT8) || next_kernel==qpu_get_fn(QPU_MC_EXIT) ); +++ break; +++ } +++ } +++} +++ +++// mc_setup(y_x, ref_y_base, y2_x2, ref_y2_base, frame_width_height, pitch, dst_pitch, offset_shift, next_kernel) +++static void rpi_simulate_inter_luma(HEVCContext *s,uint32_t *p) +++{ +++ uint32_t next_kernel; +++ int y_x,y2_x2; +++ uint32_t x0; +++ uint32_t y0; +++ uint32_t x2; +++ uint32_t y2; +++ uint8_t *ref_y_base; +++ uint8_t *ref_y2_base; +++ uint32_t frame_width_height = p[4]; +++ uint32_t frame_width = frame_width_height>>16; +++ uint32_t frame_height = (frame_width_height<<16)>>16; +++ uint32_t pitch = p[5]; +++ uint32_t dst_pitch = p[6]; +++ int offset_shift = p[7]; +++ int32_t offset_before = offset_shift>>16; +++ int32_t denom = (offset_shift<<16)>>16; +++ while(1) { +++ p += 9; +++ next_kernel = p[8-9]; +++ y_x = p[0-9]; +++ x0 = (y_x<<16)>>16; +++ y0 = y_x>>16; +++ y2_x2 = p[2-9]; +++ x2 = (y2_x2<<16)>>16; +++ y2 = y2_x2>>16; +++ +++ if (next_kernel==s->mc_filter || next_kernel==s->mc_filter_b) { +++ // y_x, frame_base, y2_x2, frame_base2, width_height, my2_mx2_my_mx, offsetweight0, this_dst, next_kernel) +++ int x,y; +++ uint32_t width_height = p[4]; +++ uint32_t my2_mx2_my_mx = p[5]; +++ uint32_t offset_weight = p[6]; +++ uint8_t *this_dst = compute_arm_addr(s,p[7],0); +++ uint32_t width = width_height >> 16; +++ uint32_t height = (width_height << 16) >> 16; +++ ref_y_base = compute_arm_addr(s,p[1-9],0); +++ ref_y2_base = compute_arm_addr(s,p[3-9],0); +++ for (y=0; ymc_filter) { +++ int32_t refa = filter8_luma(ref_y_base,x+x0, y+y0, pitch, my2_mx2_my_mx, offset_weight,offset_before,denom,frame_width,frame_height); +++ this_dst[x+y*dst_pitch] = av_clip_uint8(refa); +++ } +++ else { +++ int32_t refa = filter8_luma(ref_y_base, x+x0, y+y0, pitch, my2_mx2_my_mx, 1, 0, 0, frame_width, frame_height); +++ int32_t refb = filter8_luma(ref_y2_base, x+x2, y+y2, pitch, my2_mx2_my_mx>>16, 1, 64 + refa, 7, frame_width, frame_height); +++ this_dst[x+y*dst_pitch] = av_clip_uint8(refb); +++ } +++ } +++ } +++ } else { +++ av_assert0(next_kernel==qpu_get_fn(QPU_MC_INTERRUPT_EXIT12) || next_kernel==qpu_get_fn(QPU_MC_EXIT) ); +++ break; +++ } +++ } +++} +++ +++static void rpi_simulate_inter_qpu(HEVCContext *s) +++{ +++ // First run the transform as normal +++ int i; +++ rpi_execute_transform(s); +++ for(i=0;i<8;i++) +++ { +++ rpi_simulate_inter_chroma(s,s->mvs_base[i]); +++ } +++ for(i=0;i<12;i++) +++ { +++ rpi_simulate_inter_luma(s,s->y_mvs_base[i]); +++ } +++} +++ +++#endif +++ +++ ++ static void rpi_execute_inter_qpu(HEVCContext *s) ++ { ++ int k; ++@@ -2995,7 +3262,7 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++ s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for V ++- assert(s->u_mvs[k] - s->mvs_base[k] < UV_COMMANDS_PER_QPU); +++ av_assert0(s->u_mvs[k] - s->mvs_base[k] < UV_COMMANDS_PER_QPU); ++ } ++ ++ s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++@@ -3005,11 +3272,16 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+1] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for second request ++ s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++- assert(s->y_mvs[k] - s->y_mvs_base[k] < Y_COMMANDS_PER_QPU); +++ av_assert0(s->y_mvs[k] - s->y_mvs_base[k] < Y_COMMANDS_PER_QPU); ++ } ++ s->y_mvs[12-1][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT12); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++ #endif ++ +++#ifdef RPI_SIMULATE_QPUS +++ rpi_simulate_inter_qpu(s); +++ s->vpu_id = -1; +++ return; +++#endif ++ ++ #ifdef RPI_MULTI_MAILBOX ++ #ifdef RPI_CACHE_UNIF_MVS ++@@ -3090,7 +3362,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1; ++ #endif ++ ++- /*if (!s->enable_rpi) { +++ if (!s->enable_rpi) { ++ if (s->ps.pps->cross_component_prediction_enabled_flag) ++ printf("Cross component\n"); ++ if (s->ps.pps->num_tile_rows > 1 || s->ps.pps->num_tile_columns > 1) ++@@ -3099,7 +3371,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ printf("Weighted P slice\n"); ++ if (s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE) ++ printf("Weighted B slice\n"); ++- }*/ +++ } ++ ++ #endif ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index e12304b..4480f72 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -13,7 +13,7 @@ ++ #include ++ #include ++ #include ++-#include +++#include "libavutil/avassert.h" ++ ++ #include "config.h" ++ ++@@ -160,13 +160,13 @@ static int gpu_init(volatile struct GPU **gpu) { ++ // Now copy over the QPU code into GPU memory ++ { ++ int num_bytes = qpu_get_fn(QPU_MC_END) - qpu_get_fn(QPU_MC_SETUP_UV); ++- assert(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); +++ av_assert0(num_bytes<=QPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->qpu_code, rpi_shader, num_bytes); ++ } ++ // And the VPU code ++ { ++ int num_bytes = sizeof(rpi_hevc_transform); ++- assert(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); +++ av_assert0(num_bytes<=VPU_CODE_SIZE*sizeof(unsigned int)); ++ memcpy((void*)ptr->vpu_code, rpi_hevc_transform, num_bytes); ++ } ++ // And the transform coefficients ++@@ -216,13 +216,13 @@ static void gpu_unlock(void) { ++ static int gpu_malloc_uncached_internal(int numbytes, GPU_MEM_PTR_T *p, int mb) { ++ p->numbytes = numbytes; ++ p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); ++- assert(p->vcsm_handle); +++ av_assert0(p->vcsm_handle); ++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); ++- assert(p->vc_handle); +++ av_assert0(p->vc_handle); ++ p->arm = vcsm_lock(p->vcsm_handle); ++- assert(p->arm); +++ av_assert0(p->arm); ++ p->vc = mem_lock(mb, p->vc_handle); ++- assert(p->vc); +++ av_assert0(p->vc); ++ return 0; ++ } ++ ++@@ -243,7 +243,7 @@ int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p) ++ ++ int gpu_get_mailbox(void) ++ { ++- assert(gpu); +++ av_assert0(gpu); ++ return gpu->mb; ++ } ++ ++@@ -297,13 +297,13 @@ static int gpu_malloc_cached_internal(int numbytes, GPU_MEM_PTR_T *p) { ++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_VC, (char *)"Video Frame" ); ++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_NONE, (char *)"Video Frame" ); ++ //p->vcsm_handle = vcsm_malloc_cache(numbytes, VCSM_CACHE_TYPE_HOST_AND_VC, (char *)"Video Frame" ); ++- assert(p->vcsm_handle); +++ av_assert0(p->vcsm_handle); ++ p->vc_handle = vcsm_vc_hdl_from_hdl(p->vcsm_handle); ++- assert(p->vc_handle); +++ av_assert0(p->vc_handle); ++ p->arm = vcsm_lock(p->vcsm_handle); ++- assert(p->arm); +++ av_assert0(p->arm); ++ p->vc = mem_lock(gpu->mb, p->vc_handle); ++- assert(p->vc); +++ av_assert0(p->vc); ++ return 0; ++ } ++ ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 60d1ec2..0686249 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -149,8 +149,8 @@ add t0s, r0, r1 ; mov ra_frame_base, r2 ++ add t1s, r2, r1 ++ ++ mov r2,8 ++-shl rb12,unif, r2 # offset before shift ++-add rb13,unif,r2 # offset after shift +++shl rb12,unif,r2 # offset before shift +++add rb13,unif,r2 # denominator ++ ++ # Compute part of VPM to use for DMA output ++ mov r2, unif ++@@ -185,7 +185,7 @@ add t1s, r1, ra_frame_base ++ ++ ################################################################################ ++ ++-# mc_filter_uv(next_kernel, x, y, frame_u_base, frame_v_base, height, hcoeffs[0], hcoeffs[1], vcoeffs[0], vcoeffs[1], this_u_dst, this_v_dst) +++# mc_filter_uv(next_kernel, x, y, frame_u_base, frame_v_base, width_height, hcoeffs, vcoeffs, offset_weight_u, offset_weight_v, this_u_dst, this_v_dst) ++ ++ # At this point we have already issued two pairs of texture requests for the current block ++ # ra_x, ra_x16_base point to the current coordinates for this block ++-- ++2.5.0 ++ ++ ++From 1c4e1f07dbed84272a36cd8c25cf9d40be5cfd7c Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 2 Jun 2015 13:17:50 +0100 ++Subject: [PATCH 49/68] Increased motion vector memory and fixed block size ++ computation for non-multiple of 2 block sizes ++ ++--- ++ libavcodec/hevc.c | 50 +++++++++++++++++++++++++++++++------------------- ++ 1 file changed, 31 insertions(+), 19 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 9be5276..c864ddb 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -83,11 +83,9 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ ++ // Split image of 2048 into parts 64 wide ++ // So some QPUs will have 3 blocks of 64 to do, and others 2 blocks for an image 2048 wide with 32 blocks across ++-// Each block of 64*64 ++-// Smallest CTU size is 16x16, so smallest block is 8x8 ++-// Corresponds to a total of 83kbytes over all 12 QPUs +++// For each block of 64*64 the smallest block size is 8x4 ++ #define RPI_LUMA_COMMAND_WORDS 9 ++-#define Y_COMMANDS_PER_QPU ((1+3*(64*64)/(8*8)) * RPI_LUMA_COMMAND_WORDS) +++#define Y_COMMANDS_PER_QPU ((1+3*(64*64)/(8*4)) * RPI_LUMA_COMMAND_WORDS) ++ ++ #define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++@@ -2031,11 +2029,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *y = s->y_mvs[chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { +++ int bw = nPbW-start_x; +++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); ++- *y++ = ( (nPbW<16 ? nPbW : 16) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = ( (bw<16 ? bw : 16) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ if (weight_flag) { ++ *y++ = (s->sh.luma_offset_l0[current_mv.ref_idx[reflist]] << 16) + (s->sh.luma_weight_l0[current_mv.ref_idx[reflist]] & 0xffff); ++@@ -2078,12 +2078,14 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ int bw = nPbW_c-start_x; +++ int bh = nPbH_c-start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++- *u++ = ( (nPbW_cy_mvs[chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { +++ int bw = nPbW-start_x; +++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); ++- *y++ = ( (nPbW<16 ? nPbW : 16) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = ( (bw<16 ? bw : 16) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ if (weight_flag) { ++ *y++ = (s->sh.luma_offset_l0[current_mv.ref_idx[reflist]] << 16) + (s->sh.luma_weight_l0[current_mv.ref_idx[reflist]] & 0xffff); ++@@ -2178,12 +2182,14 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ int bw = nPbW_c-start_x; +++ int bh = nPbH_c-start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); ++- *u++ = ( (nPbW_csh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++ *u++ = rpi_filter_coefs[_my][0]; ++@@ -2235,11 +2241,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *y = s->y_mvs[chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=8) { // B blocks work 8 at a time +++ int bw = nPbW-start_x; +++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y2 - 3 + start_y) << 16) + ( (x2 - 3 + start_x) & 0xffff); // Second fetch is for ref1 ++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); ++- *y++ = ( (nPbW<8 ? nPbW : 8) << 16 ) + (nPbH<16 ? nPbH : 16); +++ *y++ = ( (bw<8 ? bw : 8) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ *y++ = 1; // B frame weighted prediction not supported ++ *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); ++@@ -2282,12 +2290,14 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ uint32_t *u = s->u_mvs[chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { +++ int bw = nPbW_c-start_x; +++ int bh = nPbH_c-start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b0; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); ++- *u++ = ( (nPbW_cframe->buf[1]); ++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); ++- *u++ = ( (nPbW_c> 16; ++ uint32_t height = (width_height << 16) >> 16; +++ uint8_t *dst_base = s->frame->data[0]; ++ ref_y_base = compute_arm_addr(s,p[1-9],0); ++ ref_y2_base = compute_arm_addr(s,p[3-9],0); ++ for (y=0; ymc_filter) { ++ int32_t refa = filter8_luma(ref_y_base,x+x0, y+y0, pitch, my2_mx2_my_mx, offset_weight,offset_before,denom,frame_width,frame_height); ++- this_dst[x+y*dst_pitch] = av_clip_uint8(refa); +++ refa = av_clip_uint8(refa); +++ this_dst[x+y*dst_pitch] = refa; ++ } ++ else { ++ int32_t refa = filter8_luma(ref_y_base, x+x0, y+y0, pitch, my2_mx2_my_mx, 1, 0, 0, frame_width, frame_height); ++@@ -3237,7 +3250,7 @@ static void rpi_simulate_inter_qpu(HEVCContext *s) ++ } ++ for(i=0;i<12;i++) ++ { ++- rpi_simulate_inter_luma(s,s->y_mvs_base[i]); +++ rpi_simulate_inter_luma(s,s->y_mvs_base[i],i); ++ } ++ } ++ ++@@ -3279,7 +3292,6 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ ++ #ifdef RPI_SIMULATE_QPUS ++ rpi_simulate_inter_qpu(s); ++- s->vpu_id = -1; ++ return; ++ #endif ++ ++-- ++2.5.0 ++ ++ ++From e6447ea51d299460471d5ac7e2fb6efe374574ee Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 2 Jun 2015 14:36:54 +0100 ++Subject: [PATCH 50/68] Added support for skip deblock ++ ++--- ++ libavcodec/hevc.c | 5 +++++ ++ libavcodec/hevc.h | 2 ++ ++ libavcodec/hevc_filter.c | 14 ++++---------- ++ 3 files changed, 11 insertions(+), 10 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index c864ddb..7acd243 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3386,6 +3386,11 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ } ++ ++ #endif +++ s->used_for_ref = !(s->nal_unit_type == NAL_TRAIL_N || +++ s->nal_unit_type == NAL_TSA_N || +++ s->nal_unit_type == NAL_STSA_N || +++ s->nal_unit_type == NAL_RADL_N || +++ s->nal_unit_type == NAL_RASL_N); ++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index a3668a2..520d16f 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -916,6 +916,8 @@ typedef struct HEVCContext { ++ int width; ++ int height; ++ +++ int used_for_ref; +++ ++ #ifdef RPI ++ int enable_rpi; ++ HEVCMvCmd *unif_mv_cmds; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 11629e4..14a0952 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -512,16 +512,14 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->ps.pps->transquant_bypass_enable_flag; ++ ++ #ifdef DISABLE_DEBLOCK_NONREF ++- if ( s->nal_unit_type == NAL_TRAIL_N || ++- s->nal_unit_type == NAL_TSA_N || ++- s->nal_unit_type == NAL_STSA_N || ++- s->nal_unit_type == NAL_RADL_N || ++- s->nal_unit_type == NAL_RASL_N ) +++ if (!s->used_for_ref) ++ return; // Don't deblock non-reference frames ++ #endif ++ #ifdef DISABLE_DEBLOCK ++ return; ++ #endif +++ if (!s->used_for_ref && s->avctx->skip_loop_filter >= AVDISCARD_NONREF) +++ return; ++ ++ if (x0) { ++ left_tc_offset = s->deblock[ctb - 1].tc_offset; ++@@ -885,11 +883,7 @@ static int ff_hevc_buf_base(AVBufferRef *bref) { ++ ++ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ { ++- if (s->enable_rpi && !( s->nal_unit_type == NAL_TRAIL_N || ++- s->nal_unit_type == NAL_TSA_N || ++- s->nal_unit_type == NAL_STSA_N || ++- s->nal_unit_type == NAL_RADL_N || ++- s->nal_unit_type == NAL_RASL_N )) { +++ if (s->enable_rpi && s->used_for_ref) { ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++ int curr_y = ((int *)f->progress->data)[0]; ++-- ++2.5.0 ++ ++ ++From 0b1f5a86b7b99b237d1eae321ed4083365f4103b Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Tue, 2 Jun 2015 15:22:52 +0100 ++Subject: [PATCH 51/68] Added support for skip_frame ++ ++--- ++ libavcodec/hevc.c | 15 ++++++++++----- ++ 1 file changed, 10 insertions(+), 5 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 7acd243..0324968 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3386,11 +3386,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ } ++ ++ #endif ++- s->used_for_ref = !(s->nal_unit_type == NAL_TRAIL_N || ++- s->nal_unit_type == NAL_TSA_N || ++- s->nal_unit_type == NAL_STSA_N || ++- s->nal_unit_type == NAL_RADL_N || ++- s->nal_unit_type == NAL_RASL_N); ++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++@@ -3914,6 +3909,16 @@ static int decode_nal_unit(HEVCContext *s, const HEVCNAL *nal) ++ if (ret < 0) ++ return ret; ++ +++ s->used_for_ref = !(s->nal_unit_type == NAL_TRAIL_N || +++ s->nal_unit_type == NAL_TSA_N || +++ s->nal_unit_type == NAL_STSA_N || +++ s->nal_unit_type == NAL_RADL_N || +++ s->nal_unit_type == NAL_RASL_N); +++ +++ if (!s->used_for_ref && s->avctx->skip_frame >= AVDISCARD_NONREF) { +++ s->is_decoded = 0; +++ break; +++ } ++ if (s->max_ra == INT_MAX) { ++ if (s->nal_unit_type == NAL_CRA_NUT || IS_BLA(s)) { ++ s->max_ra = s->poc; ++-- ++2.5.0 ++ ++ ++From 04e23231d9f7c40c6b6d124a048fac976f302a52 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 3 Jun 2015 09:15:38 +0100 ++Subject: [PATCH 52/68] Fixed cache flushing of luma when using old method ++ ++--- ++ libavcodec/hevc_filter.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 14a0952..b286bbf 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -919,7 +919,7 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ flush_buffer(s->frame->buf[1]); ++ flush_buffer(s->frame->buf[2]); ++ #ifdef RPI_LUMA_QPU ++- flush_buffer(s->frame->buf[1]); +++ flush_buffer(s->frame->buf[0]); ++ #endif ++ ++ #endif ++-- ++2.5.0 ++ ++ ++From 26eae6b28ba1027063a48258f47d4702ccba53cc Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 3 Jun 2015 11:37:27 +0100 ++Subject: [PATCH 53/68] Option to parallelise coefficient decode and inter ++ prediction and deblock for each frame ++ ++--- ++ libavcodec/hevc.c | 701 +++++++++++++++++++++++++++-------------- ++ libavcodec/hevc.h | 74 +++-- ++ libavcodec/hevc_cabac.c | 12 +- ++ libavcodec/hevcpred_template.c | 5 +- ++ 4 files changed, 522 insertions(+), 270 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 0324968..6f67872 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -43,8 +43,6 @@ ++ ++ #ifdef RPI ++ #include "rpi_qpu.h" ++- // For some unknown reason, the code seems to crash if I do a late malloc ++- //#define EARLY_MALLOC ++ // Move Inter prediction into separate pass ++ #define RPI_INTER ++ ++@@ -58,6 +56,21 @@ ++ ++ // Define RPI_SIMULATE_QPUS for debugging to run QPU code on the ARMs ++ //#define RPI_SIMULATE_QPUS +++ #ifdef RPI_WORKER +++ #include "pthread.h" +++ #endif +++ +++ static void rpi_execute_dblk_cmds(HEVCContext *s); +++ static void rpi_execute_transform(HEVCContext *s); +++ static void rpi_execute_inter_qpu(HEVCContext *s); +++ static void rpi_execute_pred_cmds(HEVCContext *s); +++ static void rpi_execute_inter_cmds(HEVCContext *s); +++ static void rpi_inter_clear(HEVCContext *s); +++ +++ // Define INTER_PASS0 to do inter prediction in first pass +++ //#define INTER_PASS0 +++ // Define LAUNCH_PASS0 to launch QPU/VPU from pass0 +++ //#define LAUNCH_PASS0 ++ ++ #endif ++ ++@@ -105,6 +118,143 @@ static uint32_t get_vc_address(AVBufferRef *bref) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++ return p->vc; ++ } +++#endif +++ +++ +++#ifdef RPI_WORKER +++ +++//#define LOG_ENTER printf("Enter %s: p0=%d p1=%d (%d jobs) %p\n", __func__,s->pass0_job,s->pass1_job,s->worker_tail-s->worker_head,s); +++//#define LOG_EXIT printf("Exit %s: p0=%d p1=%d (%d jobs) %p\n", __func__,s->pass0_job,s->pass1_job,s->worker_tail-s->worker_head,s); +++ +++#define LOG_ENTER +++#define LOG_EXIT +++ +++// Call this when we have completed pass0 and wish to trigger pass1 for the current job +++static void worker_submit_job(HEVCContext *s) +++{ +++ LOG_ENTER +++ //pthread_mutex_lock(&s->worker_mutex); +++ s->worker_tail++; // This is the only place that can change tail so we do not need the mutex +++ s->pass0_job = (s->pass0_job + 1) % RPI_MAX_JOBS; // Move onto the next slot +++ pthread_cond_broadcast(&s->worker_cond_tail); // Let people know that the tail has moved +++ //pthread_mutex_unlock(&s->worker_mutex); +++ LOG_EXIT +++} +++ +++// Call this to say we have completed pass1 +++static void worker_complete_middle_job(HEVCContext *s) +++{ +++ LOG_ENTER +++ //pthread_mutex_lock(&s->worker_mutex); +++ s->worker_middle++; // This is the only place that can change head so we do not need the mutex +++ s->pass1_job = (s->pass1_job + 1) % RPI_MAX_JOBS; // Move onto the next slot +++ pthread_cond_broadcast(&s->worker_cond_middle); // Let people know that the tail has moved +++ //pthread_mutex_unlock(&s->worker_mutex); +++ LOG_EXIT +++} +++ +++// Call this to say we have completed pass2 +++static void worker_complete_job(HEVCContext *s) +++{ +++ LOG_ENTER +++ //pthread_mutex_lock(&s->worker_mutex); +++ s->worker_head++; // This is the only place that can change head so we do not need the mutex +++ s->pass2_job = (s->pass2_job + 1) % RPI_MAX_JOBS; // Move onto the next slot +++ pthread_cond_broadcast(&s->worker_cond_head); // Let people know that the tail has moved +++ //pthread_mutex_unlock(&s->worker_mutex); +++ LOG_EXIT +++} +++ +++// Call this to wait for all jobs to have completed at the end of a frame +++static void worker_wait(HEVCContext *s) +++{ +++ LOG_ENTER +++ pthread_mutex_lock(&s->worker_mutex); +++ while( s->worker_head !=s->worker_tail) +++ { +++ pthread_cond_wait(&s->worker_cond_head, &s->worker_mutex); +++ } +++ pthread_mutex_unlock(&s->worker_mutex); +++ LOG_EXIT +++} +++ +++// Call worker_pass0_ready to wait until the s->pass0_job slot becomes +++// available to receive the next job. +++static void worker_pass0_ready(HEVCContext *s) +++{ +++ LOG_ENTER +++ pthread_mutex_lock(&s->worker_mutex); +++ // tail is number of submitted jobs +++ // head is number of completed jobs +++ // tail-head is number of outstanding jobs in the queue +++ // we need to ensure there is at least 1 space left for us to use +++ while( s->worker_tail - s->worker_head >= RPI_MAX_JOBS) +++ { +++ // Wait until another job is completed +++ pthread_cond_wait(&s->worker_cond_head, &s->worker_mutex); +++ } +++ pthread_mutex_unlock(&s->worker_mutex); +++ LOG_EXIT +++} +++ +++static void *worker_start(void *arg) +++{ +++ HEVCContext *s = (HEVCContext *)arg; +++ while(1) { +++ pthread_mutex_lock(&s->worker_mutex); +++ +++ while( !s->kill_worker && s->worker_tail - s->worker_middle <= 0) +++ { +++ pthread_cond_wait(&s->worker_cond_tail, &s->worker_mutex); +++ } +++ pthread_mutex_unlock(&s->worker_mutex); +++ +++ if (s->kill_worker) { +++ break; +++ } +++ LOG_ENTER +++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); +++#ifndef LAUNCH_PASS0 +++ rpi_execute_inter_qpu(s); +++#endif +++#ifndef INTER_PASS0 +++ // Perform inter prediction +++ rpi_execute_inter_cmds(s); +++#endif +++ // Wait for transform completion +++ vpu_wait(s->vpu_id); +++ +++ worker_complete_middle_job(s); +++ LOG_EXIT +++ } +++ return NULL; +++} +++ +++static void *worker_deblock_start(void *arg) +++{ +++ HEVCContext *s = (HEVCContext *)arg; +++ while(1) { +++ pthread_mutex_lock(&s->worker_mutex); +++ while( !s->kill_worker && s->worker_middle - s->worker_head <= 0) +++ { +++ pthread_cond_wait(&s->worker_cond_middle, &s->worker_mutex); +++ } +++ pthread_mutex_unlock(&s->worker_mutex); +++ +++ if (s->kill_worker) { +++ break; +++ } +++ LOG_ENTER +++ // Perform intra prediction and residual reconstruction +++ rpi_execute_pred_cmds(s); +++ // Perform deblocking for CTBs in this row +++ rpi_execute_dblk_cmds(s); +++ +++ worker_complete_job(s); +++ LOG_EXIT +++ } +++ return NULL; +++} ++ ++ #endif ++ ++@@ -121,19 +271,18 @@ static uint32_t get_vc_address(AVBufferRef *bref) { ++ static void pic_arrays_free(HEVCContext *s) ++ { ++ #ifdef RPI ++- ++-#ifdef EARLY_MALLOC ++-#else ++- if (s->coeffs_buf_arm[0]) { ++- gpu_free(&s->coeffs_buf_default); ++- s->coeffs_buf_arm[0] = 0; ++- } ++- if (s->coeffs_buf_arm[2]) { ++- gpu_free(&s->coeffs_buf_accelerated); ++- s->coeffs_buf_arm[2] = 0; +++ int job; +++ for(job=0;jobcoeffs_buf_arm[job][0]) { +++ gpu_free(&s->coeffs_buf_default[job]); +++ s->coeffs_buf_arm[job][0] = 0; +++ } +++ if (s->coeffs_buf_arm[job][2]) { +++ gpu_free(&s->coeffs_buf_accelerated[job]); +++ s->coeffs_buf_arm[job][2] = 0; +++ } ++ } ++ #endif ++-#endif ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++ ++@@ -171,24 +320,26 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ int min_pu_size = sps->min_pu_width * sps->min_pu_height; ++ ++ #ifdef RPI ++-#ifdef EARLY_MALLOC ++-#else ++ av_assert0(sps); ++ int coeffs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); ++ int coefs_per_row = sps->ctb_width * coeffs_in_ctb * 3; // Allow space for chroma ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); ++- s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; ++- if (!s->coeffs_buf_arm[0]) ++- goto fail; ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); ++- s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; ++- s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; ++- if (!s->coeffs_buf_arm[2]) ++- goto fail; ++- s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; ++- s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; ++- printf("Done\n"); ++-#endif +++ int job; +++ for(job=0;jobcoeffs_buf_default[job]); +++ s->coeffs_buf_arm[job][0] = (int16_t*) s->coeffs_buf_default[job].arm; +++ if (!s->coeffs_buf_arm[job][0]) +++ goto fail; +++ gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated[job]); +++ s->coeffs_buf_arm[job][2] = (int16_t*) s->coeffs_buf_accelerated[job].arm; +++ s->coeffs_buf_vc[job][2] = s->coeffs_buf_accelerated[job].vc; +++ if (!s->coeffs_buf_arm[job][2]) +++ goto fail; +++ s->coeffs_buf_arm[job][3] = coefs_per_row + s->coeffs_buf_arm[job][2]; +++ s->coeffs_buf_vc[job][3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[job][2]; +++ } +++ } ++ #endif ++ ++ s->bs_width = (width >> 2) + 1; ++@@ -1025,7 +1176,7 @@ static void rpi_intra_pred(HEVCContext *s, int log2_trafo_size, int x0, int y0, ++ { ++ if (s->enable_rpi) { ++ HEVCLocalContext *lc = s->HEVClc; ++- HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; +++ HEVCPredCmd *cmd = s->univ_pred_cmds[s->pass0_job] + s->num_pred_cmds[s->pass0_job]++; ++ cmd->type = RPI_PRED_INTRA; ++ cmd->size = log2_trafo_size; ++ cmd->c_idx = c_idx; ++@@ -1485,7 +1636,7 @@ static void rpi_luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref, const Mv *mv, int x_off, int y_off, ++ int block_w, int block_h, int luma_weight, int luma_offset) ++ { ++- HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds[s->pass0_job] + s->num_mv_cmds[s->pass0_job]++; ++ cmd->cmd = RPI_CMD_LUMA_UNI; ++ cmd->dst = dst; ++ cmd->dststride = dststride; ++@@ -1504,7 +1655,7 @@ static void rpi_luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref0, const Mv *mv0, int x_off, int y_off, ++ int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) ++ { ++- HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds[s->pass0_job] + s->num_mv_cmds[s->pass0_job]++; ++ cmd->cmd = RPI_CMD_LUMA_BI; ++ cmd->dst = dst; ++ cmd->dststride = dststride; ++@@ -1526,7 +1677,7 @@ static void rpi_chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset) ++ { ++- HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds[s->pass0_job] + s->num_mv_cmds[s->pass0_job]++; ++ cmd->cmd = RPI_CMD_CHROMA_UNI; ++ cmd->dst = dst0; ++ cmd->dststride = dststride; ++@@ -1544,7 +1695,7 @@ static void rpi_chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ static void rpi_chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx) ++ { ++- HEVCMvCmd *cmd = s->unif_mv_cmds + s->num_mv_cmds++; +++ HEVCMvCmd *cmd = s->unif_mv_cmds[s->pass0_job] + s->num_mv_cmds[s->pass0_job]++; ++ cmd->cmd = RPI_CMD_CHROMA_BI+cidx; ++ cmd->dst = dst0; ++ cmd->dststride = dststride; ++@@ -2026,7 +2177,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int chan = x0>>6; // 64 wide blocks per QPU ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++- uint32_t *y = s->y_mvs[chan % 12]; +++ uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { ++ int bw = nPbW-start_x; ++@@ -2046,7 +2197,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++- s->y_mvs[chan % 12] = y; +++ s->y_mvs[s->pass0_job][chan % 12] = y; ++ } else ++ #endif ++ { ++@@ -2075,7 +2226,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++- uint32_t *u = s->u_mvs[chan & 7]; +++ uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2099,7 +2250,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[chan & 7] = u; +++ s->u_mvs[s->pass0_job][chan & 7] = u; ++ return; ++ } ++ #endif ++@@ -2129,7 +2280,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int chan = x0>>6; // 64 wide blocks per QPU ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++- uint32_t *y = s->y_mvs[chan % 12]; +++ uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { ++ int bw = nPbW-start_x; ++@@ -2149,7 +2300,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++- s->y_mvs[chan % 12] = y; +++ s->y_mvs[s->pass0_job][chan % 12] = y; ++ } else ++ #endif ++ ++@@ -2179,7 +2330,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++- uint32_t *u = s->u_mvs[chan & 7]; +++ uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2204,7 +2355,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[chan & 7] = u; +++ s->u_mvs[s->pass0_job][chan & 7] = u; ++ return; ++ } ++ #endif ++@@ -2238,7 +2389,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int x2 = x0 + (mv2->x >> 2); ++ int y2 = y0 + (mv2->y >> 2); ++ int chan = x0>>6; // 64 wide blocks per QPU ++- uint32_t *y = s->y_mvs[chan % 12]; +++ uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=8) { // B blocks work 8 at a time ++ int bw = nPbW-start_x; ++@@ -2254,7 +2405,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter_b; ++ } ++ } ++- s->y_mvs[chan % 12] = y; +++ s->y_mvs[s->pass0_job][chan % 12] = y; ++ } else ++ #endif ++ { ++@@ -2287,7 +2438,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ ++ int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++ ++- uint32_t *u = s->u_mvs[chan & 7]; +++ uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2316,7 +2467,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[chan & 7] = u; +++ s->u_mvs[s->pass0_job][chan & 7] = u; ++ return; ++ } ++ #endif ++@@ -2821,40 +2972,54 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ static void rpi_execute_dblk_cmds(HEVCContext *s) ++ { ++ int n; +++ int job = s->pass2_job; ++ int ctb_size = 1 << s->ps.sps->log2_ctb_size; ++- int (*p)[2] = s->dblk_cmds; ++- for(n = s->num_dblk_cmds; n>0 ;n--,p++) { +++ int (*p)[2] = s->dblk_cmds[job]; +++ for(n = s->num_dblk_cmds[job]; n>0 ;n--,p++) { ++ ff_hevc_hls_filters(s, (*p)[0], (*p)[1], ctb_size); ++ } ++- s->num_dblk_cmds = 0; +++ s->num_dblk_cmds[job] = 0; ++ } ++ ++ static void rpi_execute_transform(HEVCContext *s) ++ { ++ int i=2; +++#ifdef LAUNCH_PASS0 +++ int job = s->pass0_job; +++#else +++ int job = s->pass1_job; +++#endif ++ //int j; ++ //int16_t *coeffs = s->coeffs_buf_arm[i]; ++ //for(j=s->num_coeffs[i]; j > 0; j-= 16*16, coeffs+=16*16) { ++ // s->hevcdsp.idct[4-2](coeffs, 16); ++ //} ++ ++- gpu_cache_flush(&s->coeffs_buf_accelerated); ++- s->vpu_id = vpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, &s->coeffs_buf_accelerated); +++ gpu_cache_flush(&s->coeffs_buf_accelerated[job]); +++ s->vpu_id = vpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], +++ s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], +++ s->num_coeffs[job][3] >> 10, 0, &s->coeffs_buf_accelerated[job]); ++ //vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); ++ //gpu_cache_flush(&s->coeffs_buf_accelerated); ++ //vpu_wait(s->vpu_id); ++ ++ for(i=0;i<4;i++) ++- s->num_coeffs[i] = 0; +++ s->num_coeffs[job][i] = 0; ++ } ++ ++ static void rpi_execute_pred_cmds(HEVCContext *s) ++ { ++ int i; ++- HEVCPredCmd *cmd = s->univ_pred_cmds; +++ int job = s->pass2_job; +++ HEVCPredCmd *cmd = s->univ_pred_cmds[job]; +++#ifdef RPI_WORKER +++ HEVCLocalContextIntra *lc = &s->HEVClcIntra; +++#else ++ HEVCLocalContext *lc = s->HEVClc; +++#endif ++ ++- for(i = s->num_pred_cmds; i > 0; i--, cmd++) { +++ for(i = s->num_pred_cmds[job]; i > 0; i--, cmd++) { +++ //printf("i=%d cmd=%p job1=%d job0=%d\n",i,cmd,s->pass1_job,s->pass0_job); ++ if (cmd->type == RPI_PRED_INTRA) { ++ lc->tu.intra_pred_mode_c = lc->tu.intra_pred_mode = cmd->mode; ++ lc->na.cand_bottom_left = (cmd->na >> 4) & 1; ++@@ -2873,21 +3038,26 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ #endif ++ } ++ } ++- s->num_pred_cmds = 0; +++ s->num_pred_cmds[job] = 0; ++ } ++ ++ static void rpi_execute_inter_cmds(HEVCContext *s) ++ { ++- HEVCMvCmd *cmd = s->unif_mv_cmds; +++#ifdef INTER_PASS0 +++ int job = s->pass0_job; +++#else +++ int job = s->pass1_job; +++#endif +++ HEVCMvCmd *cmd = s->unif_mv_cmds[job]; ++ int n,cidx; ++ AVFrame myref; ++ AVFrame myref1; ++ struct MvField mymv; ++- if (s->num_mv_cmds > RPI_MAX_MV_CMDS) { +++ if (s->num_mv_cmds[job] > RPI_MAX_MV_CMDS) { ++ printf("Overflow inter_cmds\n"); ++ exit(-1); ++ } ++- for(n = s->num_mv_cmds; n>0 ; n--, cmd++) { +++ for(n = s->num_mv_cmds[job]; n>0 ; n--, cmd++) { ++ switch(cmd->cmd) { ++ case RPI_CMD_LUMA_UNI: ++ myref.data[0] = cmd->src; ++@@ -2927,7 +3097,28 @@ static void rpi_execute_inter_cmds(HEVCContext *s) ++ break; ++ } ++ } ++- s->num_mv_cmds = 0; +++ s->num_mv_cmds[job] = 0; +++} +++ +++static void rpi_do_all_passes(HEVCContext *s) +++{ +++#ifdef RPI_INTER_QPU +++ // Kick off inter prediction on QPUs +++ rpi_execute_inter_qpu(s); +++#else +++ rpi_execute_transform(s); +++#endif +++ // Perform luma inter prediction +++ rpi_execute_inter_cmds(s); +++ // Wait for transform completion +++ vpu_wait(s->vpu_id); +++ // Perform intra prediction and residual reconstruction +++ rpi_execute_pred_cmds(s); +++ // Perform deblocking for CTBs in this row +++ rpi_execute_dblk_cmds(s); +++#ifdef RPI_INTER_QPU +++ rpi_inter_clear(s); +++#endif ++ } ++ ++ #endif ++@@ -2935,6 +3126,7 @@ static void rpi_execute_inter_cmds(HEVCContext *s) ++ #ifdef RPI_INTER_QPU ++ static void rpi_inter_clear(HEVCContext *s) ++ { +++ int job = s->pass0_job; ++ int i; ++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; ++@@ -2942,51 +3134,50 @@ static void rpi_inter_clear(HEVCContext *s) ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++ for(i=0;i<8;i++) { ++- s->u_mvs[i] = s->mvs_base[i]; ++- *s->u_mvs[i]++ = 0; ++- *s->u_mvs[i]++ = 0; ++- *s->u_mvs[i]++ = 0; ++- *s->u_mvs[i]++ = 0; ++- *s->u_mvs[i]++ = 0; ++- *s->u_mvs[i]++ = pic_width; ++- *s->u_mvs[i]++ = pic_height; ++- *s->u_mvs[i]++ = s->frame->linesize[1]; ++- *s->u_mvs[i]++ = s->frame->linesize[2]; +++ s->u_mvs[job][i] = s->mvs_base[job][i]; +++ *s->u_mvs[job][i]++ = 0; +++ *s->u_mvs[job][i]++ = 0; +++ *s->u_mvs[job][i]++ = 0; +++ *s->u_mvs[job][i]++ = 0; +++ *s->u_mvs[job][i]++ = 0; +++ *s->u_mvs[job][i]++ = pic_width; +++ *s->u_mvs[job][i]++ = pic_height; +++ *s->u_mvs[job][i]++ = s->frame->linesize[1]; +++ *s->u_mvs[job][i]++ = s->frame->linesize[2]; ++ if (weight_flag) { ++- *s->u_mvs[i]++ = 1 << (s->sh.chroma_log2_weight_denom + 6 - 1); ++- *s->u_mvs[i]++ = s->sh.chroma_log2_weight_denom + 6; +++ *s->u_mvs[job][i]++ = 1 << (s->sh.chroma_log2_weight_denom + 6 - 1); +++ *s->u_mvs[job][i]++ = s->sh.chroma_log2_weight_denom + 6; ++ } else { ++- *s->u_mvs[i]++ = 1 << 5; ++- *s->u_mvs[i]++ = 6; +++ *s->u_mvs[job][i]++ = 1 << 5; +++ *s->u_mvs[job][i]++ = 6; ++ } ++- *s->u_mvs[i]++ = i; // Select section of VPM (avoid collisions with 3d unit) +++ *s->u_mvs[job][i]++ = i; // Select section of VPM (avoid collisions with 3d unit) ++ } ++ ++ #ifdef RPI_LUMA_QPU ++ for(i=0;i<12;i++) { ++- s->y_mvs[i] = s->y_mvs_base[i]; ++- *s->y_mvs[i]++ = 0; // y_x ++- *s->y_mvs[i]++ = 0; // ref_y_base ++- *s->y_mvs[i]++ = 0; // y2_x2 ++- *s->y_mvs[i]++ = 0; // ref_y2_base ++- *s->y_mvs[i]++ = (s->ps.sps->width << 16) + s->ps.sps->height; ++- *s->y_mvs[i]++ = s->frame->linesize[0]; // pitch ++- *s->y_mvs[i]++ = s->frame->linesize[0]; // dst_pitch +++ s->y_mvs[job][i] = s->y_mvs_base[job][i]; +++ *s->y_mvs[job][i]++ = 0; // y_x +++ *s->y_mvs[job][i]++ = 0; // ref_y_base +++ *s->y_mvs[job][i]++ = 0; // y2_x2 +++ *s->y_mvs[job][i]++ = 0; // ref_y2_base +++ *s->y_mvs[job][i]++ = (s->ps.sps->width << 16) + s->ps.sps->height; +++ *s->y_mvs[job][i]++ = s->frame->linesize[0]; // pitch +++ *s->y_mvs[job][i]++ = s->frame->linesize[0]; // dst_pitch ++ if (weight_flag) { ++ int offset = 1 << (s->sh.luma_log2_weight_denom + 6 - 1); ++ int shift = s->sh.luma_log2_weight_denom + 6; ++- *s->y_mvs[i]++ = (offset << 16) + shift; +++ *s->y_mvs[job][i]++ = (offset << 16) + shift; ++ } else { ++ int offset = 1 << 5; ++ int shift = 6; ++- *s->y_mvs[i]++ = (offset << 16) + shift; +++ *s->y_mvs[job][i]++ = (offset << 16) + shift; ++ } ++- *s->y_mvs[i]++ = 0; // Next kernel +++ *s->y_mvs[job][i]++ = 0; // Next kernel ++ } ++ #endif ++ } ++ ++- ++ #ifdef RPI_SIMULATE_QPUS ++ ++ static int32_t clipx(int x,int FRAME_WIDTH) ++@@ -3260,10 +3451,15 @@ static void rpi_simulate_inter_qpu(HEVCContext *s) ++ static void rpi_execute_inter_qpu(HEVCContext *s) ++ { ++ int k; +++#ifdef LAUNCH_PASS0 +++ int job = s->pass0_job; +++#else +++ int job = s->pass1_job; +++#endif ++ int i; ++- uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr.vc; +++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr[job].vc; ++ #ifdef RPI_LUMA_QPU ++- uint32_t *y_unif_vc = (uint32_t *)s->y_unif_mvs_ptr.vc; +++ uint32_t *y_unif_vc = (uint32_t *)s->y_unif_mvs_ptr[job].vc; ++ #endif ++ if (s->sh.slice_type == I_SLICE) { ++ #ifdef RPI_MULTI_MAILBOX ++@@ -3272,22 +3468,22 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ #endif ++ } ++ for(k=0;k<8;k++) { ++- s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++- s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++- s->u_mvs[k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for V ++- av_assert0(s->u_mvs[k] - s->mvs_base[k] < UV_COMMANDS_PER_QPU); +++ s->u_mvs[job][k][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_EXIT); // Add exit command +++ s->u_mvs[job][k][-RPI_CHROMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->u_mvs[job][k][-RPI_CHROMA_COMMAND_WORDS+4] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for V +++ av_assert0(s->u_mvs[job][k] - s->mvs_base[job][k] < UV_COMMANDS_PER_QPU); ++ } ++ ++- s->u_mvs[8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore +++ s->u_mvs[job][8-1][-RPI_CHROMA_COMMAND_WORDS] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT8); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++ ++ #ifdef RPI_LUMA_QPU ++ for(k=0;k<12;k++) { ++- s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+1] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined ++- s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for second request ++- s->y_mvs[k][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_EXIT); // Add exit command ++- av_assert0(s->y_mvs[k] - s->y_mvs_base[k] < Y_COMMANDS_PER_QPU); +++ s->y_mvs[job][k][-RPI_LUMA_COMMAND_WORDS+1] = qpu_get_fn(QPU_MC_SETUP_UV); // A dummy texture location (maps to our code) - this is needed as the texture requests are pipelined +++ s->y_mvs[job][k][-RPI_LUMA_COMMAND_WORDS+3] = qpu_get_fn(QPU_MC_SETUP_UV); // Also need a dummy for second request +++ s->y_mvs[job][k][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_EXIT); // Add exit command +++ av_assert0(s->y_mvs[job][k] - s->y_mvs_base[job][k] < Y_COMMANDS_PER_QPU); ++ } ++- s->y_mvs[12-1][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT12); // This QPU will signal interrupt when all others are done and have acquired a semaphore +++ s->y_mvs[job][12-1][-RPI_LUMA_COMMAND_WORDS+8] = qpu_get_fn(QPU_MC_INTERRUPT_EXIT12); // This QPU will signal interrupt when all others are done and have acquired a semaphore ++ #endif ++ ++ #ifdef RPI_SIMULATE_QPUS ++@@ -3297,34 +3493,34 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ ++ #ifdef RPI_MULTI_MAILBOX ++ #ifdef RPI_CACHE_UNIF_MVS ++- gpu_cache_flush3(&s->coeffs_buf_accelerated,&s->y_unif_mvs_ptr, &s->unif_mvs_ptr); +++ gpu_cache_flush3(&s->coeffs_buf_accelerated[job],&s->y_unif_mvs_ptr[job], &s->unif_mvs_ptr[job]); ++ #else ++- gpu_cache_flush(&s->coeffs_buf_accelerated); +++ gpu_cache_flush(&s->coeffs_buf_accelerated[job]); ++ #endif ++- s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0, +++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], s->num_coeffs[job][3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++- (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[2 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[3 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][0 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][1 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][2 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][3 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][4 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][5 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][6 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][7 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), ++ #ifdef RPI_LUMA_QPU ++ qpu_get_fn(QPU_MC_SETUP), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[0 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[1 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[2 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[3 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[4 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[5 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[6 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[7 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[8 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[9 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[10 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)), ++- (uint32_t)(y_unif_vc+(s->y_mvs_base[11 ] - (uint32_t*)s->y_unif_mvs_ptr.arm)) +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][0 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][1 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][2 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][3 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][4 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][5 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][6 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][7 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][8 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][9 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][10 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)), +++ (uint32_t)(y_unif_vc+(s->y_mvs_base[job][11 ] - (uint32_t*)s->y_unif_mvs_ptr[job].arm)) ++ #else ++ 0, ++ 0,0,0,0, ++@@ -3333,17 +3529,17 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ #endif ++ ); ++ for(i=0;i<4;i++) ++- s->num_coeffs[i] = 0; +++ s->num_coeffs[job][i] = 0; ++ #else ++ qpu_run_shader8(qpu_get_fn(QPU_MC_SETUP_UV), ++- (uint32_t)(unif_vc+(s->mvs_base[0 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[1 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[2 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[3 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[4 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[5 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[6 ] - (uint32_t*)s->unif_mvs_ptr.arm)), ++- (uint32_t)(unif_vc+(s->mvs_base[7 ] - (uint32_t*)s->unif_mvs_ptr.arm)) +++ (uint32_t)(unif_vc+(s->mvs_base[job][0 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][1 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][2 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][3 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][4 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][5 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][6 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), +++ (uint32_t)(unif_vc+(s->mvs_base[job][7 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)) ++ ); ++ #endif ++ ++@@ -3400,6 +3596,11 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ } ++ } ++ +++#ifdef RPI_WORKER +++ s->pass0_job = 0; +++ s->pass1_job = 0; +++ s->pass2_job = 0; +++#endif ++ #ifdef RPI_INTER_QPU ++ rpi_inter_clear(s); ++ #endif ++@@ -3420,46 +3621,42 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); +++ ++ #ifdef RPI ++ if (s->enable_rpi) { ++- s->dblk_cmds[s->num_dblk_cmds][0] = x_ctb; ++- s->dblk_cmds[s->num_dblk_cmds++][1] = y_ctb; +++ s->dblk_cmds[s->pass0_job][s->num_dblk_cmds[s->pass0_job]][0] = x_ctb; +++ s->dblk_cmds[s->pass0_job][s->num_dblk_cmds[s->pass0_job]++][1] = y_ctb; ++ if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { ++- // Transform all blocks ++- // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++-#ifdef RPI_MULTI_MAILBOX ++- // Kick off inter prediction on QPUs ++- rpi_execute_inter_qpu(s); ++- // Perform luma inter prediction ++- rpi_execute_inter_cmds(s); ++-#else ++- rpi_execute_transform(s); ++- // Perform inter prediction ++- rpi_execute_inter_cmds(s); ++-#ifdef RPI_INTER_QPU ++- // Kick off inter prediction on QPUs ++- rpi_execute_inter_qpu(s); ++-#endif ++-#endif ++- ++- // Wait for transform completion ++- vpu_wait(s->vpu_id); ++- ++- // Copy back reconstructed data ++- //memcpy(s->frame->data[0],s->dummy.arm,2048*64); ++- //memcpy(s->frame->data[1],s->dummy.arm,1024*32); ++- //memcpy(s->frame->data[2],s->dummy.arm,1024*32); +++#ifdef RPI_WORKER +++ if (s->used_for_ref) { +++ // Split work load onto separate threads so we make as rapid progress as possible with this frame +++ #ifdef INTER_PASS0 +++ rpi_execute_inter_cmds(s); +++ #endif +++ #ifdef LAUNCH_PASS0 +++ rpi_execute_inter_qpu(s); +++ #endif +++ // Pass on this job to worker thread +++ worker_submit_job(s); +++ // Make sure we have space to prepare the next job +++ worker_pass0_ready(s); ++ ++- // Perform intra prediction and residual reconstruction ++- rpi_execute_pred_cmds(s); ++- // Perform deblocking for CTBs in this row ++- rpi_execute_dblk_cmds(s); +++ // Prepare the next batch of commands ++ #ifdef RPI_INTER_QPU ++- rpi_inter_clear(s); +++ rpi_inter_clear(s); +++#endif +++ } else { +++ // Non-ref frame so do it all on this thread +++ rpi_do_all_passes(s); +++ } +++#else +++ rpi_do_all_passes(s); ++ #endif ++ } ++ } ++ #endif +++ +++ ++ if (more_data < 0) { ++ s->tab_slice_address[ctb_addr_rs] = -1; ++ return more_data; ++@@ -3476,18 +3673,21 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ } ++ ++ #ifdef RPI ++- if (s->enable_rpi && s->num_dblk_cmds) { ++-#ifdef RPI_INTER_QPU ++- rpi_execute_inter_qpu(s); ++-#endif ++-#ifndef RPI_MULTI_MAILBOX ++- rpi_execute_transform(s); +++ +++#ifdef RPI_WORKER +++ // Wait for the worker to finish all its jobs +++ if (s->enable_rpi) { +++ worker_wait(s); +++ av_assert0(s->pass0_job==s->pass1_job); +++ av_assert0(s->pass1_job==s->pass2_job); +++ } ++ #endif ++- rpi_execute_inter_cmds(s); ++- vpu_wait(s->vpu_id); ++- rpi_execute_pred_cmds(s); ++- rpi_execute_dblk_cmds(s); +++ +++ // Finish off any half-completed rows +++ if (s->enable_rpi && s->num_dblk_cmds[s->pass0_job]) { +++ rpi_do_all_passes(s); ++ } +++ ++ #endif ++ ++ if (x_ctb + ctb_size >= s->ps.sps->width && ++@@ -4219,6 +4419,48 @@ fail: ++ return AVERROR(ENOMEM); ++ } ++ +++#ifdef RPI_WORKER +++static av_cold void hevc_init_worker(HEVCContext *s) +++{ +++ int err; +++ pthread_cond_init(&s->worker_cond_head, NULL); +++ pthread_cond_init(&s->worker_cond_middle, NULL); +++ pthread_cond_init(&s->worker_cond_tail, NULL); +++ pthread_mutex_init(&s->worker_mutex, NULL); +++ +++ s->worker_tail=0; +++ s->worker_middle=0; +++ s->worker_head=0; +++ s->kill_worker=0; +++ err = pthread_create(&s->worker_thread, NULL, worker_start, s); +++ err = pthread_create(&s->worker_deblock_thread, NULL, worker_deblock_start, s); +++ if (err) { +++ printf("Failed to create worker thread\n"); +++ exit(-1); +++ } +++} +++ +++static av_cold void hevc_exit_worker(HEVCContext *s) +++{ +++ void *res; +++ s->kill_worker=1; +++ pthread_cond_broadcast(&s->worker_cond_tail); +++ pthread_cond_broadcast(&s->worker_cond_middle); +++ pthread_join(s->worker_thread, &res); +++ pthread_join(s->worker_deblock_thread, &res); +++ +++ pthread_cond_destroy(&s->worker_cond_head); +++ pthread_cond_destroy(&s->worker_cond_middle); +++ pthread_cond_destroy(&s->worker_cond_tail); +++ pthread_mutex_destroy(&s->worker_mutex); +++ +++ s->worker_tail=0; +++ s->worker_middle=0; +++ s->worker_head=0; +++ s->kill_worker=0; +++} +++#endif +++ ++ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ { ++ HEVCContext *s = avctx->priv_data; ++@@ -4231,33 +4473,29 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ++ av_freep(&s->cabac_state); ++ ++ #ifdef RPI ++- av_freep(&s->unif_mv_cmds); ++- av_freep(&s->univ_pred_cmds); +++ +++#ifdef RPI_WORKER +++ hevc_exit_worker(s); +++#endif +++ +++ for(i=0;iunif_mv_cmds[i]); +++ av_freep(&s->univ_pred_cmds[i]); ++ ++ #ifdef RPI_INTER_QPU ++- if (s->unif_mvs) { ++- gpu_free( &s->unif_mvs_ptr ); ++- s->unif_mvs = 0; ++- } +++ if (s->unif_mvs[i]) { +++ gpu_free( &s->unif_mvs_ptr[i] ); +++ s->unif_mvs[i] = 0; +++ } ++ #endif ++ #ifdef RPI_LUMA_QPU ++- if (s->y_unif_mvs) { ++- gpu_free( &s->y_unif_mvs_ptr ); ++- s->y_unif_mvs = 0; ++- } +++ if (s->y_unif_mvs[i]) { +++ gpu_free( &s->y_unif_mvs_ptr[i] ); +++ s->y_unif_mvs[i] = 0; +++ } ++ #endif ++- ++-#ifdef EARLY_MALLOC ++- printf("hevc_decode_free\n"); ++- if (s->coeffs_buf_arm[0]) { ++- gpu_free(&s->coeffs_buf_default); ++- s->coeffs_buf_arm[0] = 0; ++- } ++- if (s->coeffs_buf_arm[2]) { ++- gpu_free(&s->coeffs_buf_accelerated); ++- s->coeffs_buf_arm[2] = 0; ++ } ++-#endif +++ ++ #endif ++ ++ for (i = 0; i < 3; i++) { ++@@ -4322,6 +4560,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ { ++ HEVCContext *s = avctx->priv_data; ++ int i; +++ int job; ++ ++ s->avctx = avctx; ++ ++@@ -4332,12 +4571,14 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ s->sList[0] = s; ++ ++ #ifdef RPI ++- s->unif_mv_cmds = av_mallocz(sizeof(HEVCMvCmd)*RPI_MAX_MV_CMDS); ++- if (!s->unif_mv_cmds) ++- goto fail; ++- s->univ_pred_cmds = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); ++- if (!s->univ_pred_cmds) ++- goto fail; +++ for(job=0;jobunif_mv_cmds[job] = av_mallocz(sizeof(HEVCMvCmd)*RPI_MAX_MV_CMDS); +++ if (!s->unif_mv_cmds[job]) +++ goto fail; +++ s->univ_pred_cmds[job] = av_mallocz(sizeof(HEVCPredCmd)*RPI_MAX_PRED_CMDS); +++ if (!s->univ_pred_cmds[job]) +++ goto fail; +++ } ++ ++ #ifdef RPI_INTER_QPU ++ // We divide the image into blocks 256 wide and 64 high ++@@ -4348,18 +4589,20 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ { ++ int uv_commands_per_qpu = UV_COMMANDS_PER_QPU; ++ uint32_t *p; +++ for(job=0;jobunif_mvs_ptr ); +++ gpu_malloc_cached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr[job] ); ++ #else ++- gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr ); +++ gpu_malloc_uncached( 8 * uv_commands_per_qpu * sizeof(uint32_t), &s->unif_mvs_ptr[job] ); ++ #endif ++- s->unif_mvs = (uint32_t *) s->unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC +++ s->unif_mvs[job] = (uint32_t *) s->unif_mvs_ptr[job].arm; ++ ++- // Set up initial locations for uniform streams ++- p = s->unif_mvs; ++- for(i = 0; i < 8; i++) { ++- s->mvs_base[i] = p; +++ // Set up initial locations for uniform streams +++ p = s->unif_mvs[job]; +++ for(i = 0; i < 8; i++) { +++ s->mvs_base[job][i] = p; ++ p += uv_commands_per_qpu; +++ } ++ } ++ s->mc_filter_uv = qpu_get_fn(QPU_MC_FILTER_UV); ++ s->mc_filter_uv_b0 = qpu_get_fn(QPU_MC_FILTER_UV_B0); ++@@ -4368,61 +4611,35 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ++ } ++ #endif ++ #ifdef RPI_LUMA_QPU +++ for(job=0;joby_unif_mvs_ptr ); +++ gpu_malloc_cached( 12 * y_commands_per_qpu * sizeof(uint32_t), &s->y_unif_mvs_ptr[job] ); ++ #else ++- gpu_malloc_uncached( 12 * y_commands_per_qpu * sizeof(uint32_t), &s->y_unif_mvs_ptr ); +++ gpu_malloc_uncached( 12 * y_commands_per_qpu * sizeof(uint32_t), &s->y_unif_mvs_ptr[job] ); ++ #endif ++- s->y_unif_mvs = (uint32_t *) s->y_unif_mvs_ptr.arm; // TODO support this allocation in non EARLY_MALLOC +++ s->y_unif_mvs[job] = (uint32_t *) s->y_unif_mvs_ptr[job].arm; ++ ++ // Set up initial locations for uniform streams ++- p = s->y_unif_mvs; +++ p = s->y_unif_mvs[job]; ++ for(i = 0; i < 12; i++) { ++- s->y_mvs_base[i] = p; +++ s->y_mvs_base[job][i] = p; ++ p += y_commands_per_qpu; ++ } ++- s->mc_filter = qpu_get_fn(QPU_MC_FILTER); ++- s->mc_filter_b = qpu_get_fn(QPU_MC_FILTER_B); ++- ++ } +++ s->mc_filter = qpu_get_fn(QPU_MC_FILTER); +++ s->mc_filter_b = qpu_get_fn(QPU_MC_FILTER_B); ++ #endif ++ //gpu_malloc_uncached(2048*64,&s->dummy); ++ ++-#ifdef EARLY_MALLOC ++- { ++- int coeffs_in_ctb = 64*64; ++- int coefs_per_row = (2048/64) * coeffs_in_ctb * 3; // Allow space for chroma ++- s->coeffs_buf_arm[0] = 0; ++- s->coeffs_buf_arm[2] = 0; ++- printf("Allocated %d\n",coefs_per_row); ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row, &s->coeffs_buf_default); ++- s->coeffs_buf_arm[0] = (int16_t*) s->coeffs_buf_default.arm; ++- if (!s->coeffs_buf_arm[0]) ++- goto fail; ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated); ++- s->coeffs_buf_arm[2] = (int16_t*) s->coeffs_buf_accelerated.arm; ++- s->coeffs_buf_vc[2] = s->coeffs_buf_accelerated.vc; ++- if (!s->coeffs_buf_arm[2]) ++- goto fail; ++- s->coeffs_buf_arm[3] = coefs_per_row + s->coeffs_buf_arm[2]; ++- s->coeffs_buf_vc[3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[2]; ++- printf("Done\n"); ++-#ifdef RPI_PRECLEAR ++- //memset(s->coeffs_buf_arm[0],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[0], coefs_per_row); ++- //memset(s->coeffs_buf_arm[2],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[2], coefs_per_row); ++- //memset(s->coeffs_buf_arm[3],0, sizeof(int16_t) * coefs_per_row); ++- memclear16(s->coeffs_buf_arm[3], coefs_per_row); ++-#endif ++- } ++-#endif ++- ++ s->enable_rpi = 0; ++ +++#ifdef RPI_WORKER +++ hevc_init_worker(s); +++#endif +++ ++ #endif ++ ++ s->cabac_state = av_malloc(HEVC_CONTEXTS); ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 520d16f..b540ca5 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -50,6 +50,12 @@ ++ // Define RPI_LUMA_QPU to also use QPU for luma inter prediction ++ #define RPI_LUMA_QPU ++ #endif +++ +++ // By passing jobs to a worker thread we hope to be able to catch up during slow frames +++ #define RPI_MAX_JOBS 2 +++ // Define RPI_WORKER to launch a worker thread for pixel processing tasks +++ #define RPI_WORKER +++ ++ #endif ++ ++ #define MAX_DPB_SIZE 16 // A.4.1 ++@@ -832,6 +838,13 @@ typedef struct HEVCLocalContext { ++ int boundary_flags; ++ } HEVCLocalContext; ++ +++#ifdef RPI_WORKER +++typedef struct HEVCLocalContextIntra { +++ TransformUnit tu; +++ NeighbourAvailable na; +++} HEVCLocalContextIntra; +++#endif +++ ++ #ifdef RPI ++ ++ // RPI_MAX_WIDTH is maximum width in pixels supported by the accelerated code ++@@ -900,7 +913,7 @@ typedef struct HEVCPredCmd { ++ ++ typedef struct HEVCContext { ++ #ifdef RPI ++- int dblk_cmds[RPI_MAX_DEBLOCK_CMDS][2]; +++ int dblk_cmds[RPI_MAX_JOBS][RPI_MAX_DEBLOCK_CMDS][2]; ++ #endif ++ const AVClass *c; // needed by private avoptions ++ AVCodecContext *avctx; ++@@ -909,7 +922,9 @@ typedef struct HEVCContext { ++ ++ HEVCLocalContext *HEVClcList[MAX_NB_THREADS]; ++ HEVCLocalContext *HEVClc; ++- +++#ifdef RPI_WORKER +++ HEVCLocalContextIntra HEVClcIntra; +++#endif ++ uint8_t threads_type; ++ uint8_t threads_number; ++ ++@@ -920,43 +935,60 @@ typedef struct HEVCContext { ++ ++ #ifdef RPI ++ int enable_rpi; ++- HEVCMvCmd *unif_mv_cmds; ++- HEVCPredCmd *univ_pred_cmds; +++ HEVCMvCmd *unif_mv_cmds[RPI_MAX_JOBS]; +++ HEVCPredCmd *univ_pred_cmds[RPI_MAX_JOBS]; ++ int buf_width; ++- GPU_MEM_PTR_T coeffs_buf_default; ++- GPU_MEM_PTR_T coeffs_buf_accelerated; ++- int16_t *coeffs_buf_arm[4]; ++- unsigned int coeffs_buf_vc[4]; ++- int num_coeffs[4]; ++- int num_xfm_cmds; ++- int num_mv_cmds; ++- int num_pred_cmds; ++- int num_dblk_cmds; +++ GPU_MEM_PTR_T coeffs_buf_default[RPI_MAX_JOBS]; +++ GPU_MEM_PTR_T coeffs_buf_accelerated[RPI_MAX_JOBS]; +++ int16_t *coeffs_buf_arm[RPI_MAX_JOBS][4]; +++ unsigned int coeffs_buf_vc[RPI_MAX_JOBS][4]; +++ int num_coeffs[RPI_MAX_JOBS][4]; +++ int num_xfm_cmds[RPI_MAX_JOBS]; +++ int num_mv_cmds[RPI_MAX_JOBS]; +++ int num_pred_cmds[RPI_MAX_JOBS]; +++ int num_dblk_cmds[RPI_MAX_JOBS]; ++ int vpu_id; ++ //GPU_MEM_PTR_T dummy; +++ int pass0_job; // Pass0 does coefficient decode +++ int pass1_job; // Pass1 does pixel processing +++ int pass2_job; // Pass2 does reconstruction and deblocking ++ #ifdef RPI_INTER_QPU ++- GPU_MEM_PTR_T unif_mvs_ptr; ++- uint32_t *unif_mvs; // Base of memory for motion vector commands +++ GPU_MEM_PTR_T unif_mvs_ptr[RPI_MAX_JOBS]; +++ uint32_t *unif_mvs[RPI_MAX_JOBS]; // Base of memory for motion vector commands ++ ++ // _base pointers are to the start of the row ++- uint32_t *mvs_base[8]; +++ uint32_t *mvs_base[RPI_MAX_JOBS][8]; ++ // these pointers are to the next free space ++- uint32_t *u_mvs[8]; +++ uint32_t *u_mvs[RPI_MAX_JOBS][8]; ++ // Function pointers ++ uint32_t mc_filter_uv; ++ uint32_t mc_filter_uv_b0; ++ uint32_t mc_filter_uv_b; ++ #endif ++ #ifdef RPI_LUMA_QPU ++- GPU_MEM_PTR_T y_unif_mvs_ptr; ++- uint32_t *y_unif_mvs; // Base of memory for motion vector commands ++- uint32_t *y_mvs_base[12]; ++- uint32_t *y_mvs[12]; +++ GPU_MEM_PTR_T y_unif_mvs_ptr[RPI_MAX_JOBS]; +++ uint32_t *y_unif_mvs[RPI_MAX_JOBS]; // Base of memory for motion vector commands +++ uint32_t *y_mvs_base[RPI_MAX_JOBS][12]; +++ uint32_t *y_mvs[RPI_MAX_JOBS][12]; ++ // Function pointers ++ uint32_t mc_filter; ++ uint32_t mc_filter_b; ++ #endif ++ +++#ifdef RPI_WORKER +++ pthread_t worker_thread; +++ pthread_t worker_deblock_thread; +++ pthread_cond_t worker_cond_head; +++ pthread_cond_t worker_cond_tail; +++ pthread_cond_t worker_cond_middle; +++ pthread_mutex_t worker_mutex; +++ +++ int worker_tail; // Contains the number of posted jobs +++ int worker_head; // Contains the number of completed jobs +++ int worker_middle; // Contains the number of completed jobs +++ int kill_worker; // set to 1 to terminate the worker +++#endif +++ ++ #endif ++ ++ uint8_t *cabac_state; ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index ca76cb0..b9f773b 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1051,11 +1051,11 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ if (s->enable_rpi) { ++ int n = trafo_size * trafo_size; ++ if (use_vpu) { ++- coeffs = s->coeffs_buf_arm[log2_trafo_size - 2] + s->num_coeffs[log2_trafo_size - 2]; ++- s->num_coeffs[log2_trafo_size - 2] += n; +++ coeffs = s->coeffs_buf_arm[s->pass0_job][log2_trafo_size - 2] + s->num_coeffs[s->pass0_job][log2_trafo_size - 2]; +++ s->num_coeffs[s->pass0_job][log2_trafo_size - 2] += n; ++ } else { ++- coeffs = s->coeffs_buf_arm[0] + s->num_coeffs[0]; ++- s->num_coeffs[0] += n; +++ coeffs = s->coeffs_buf_arm[s->pass0_job][0] + s->num_coeffs[s->pass0_job][0]; +++ s->num_coeffs[s->pass0_job][0] += n; ++ } ++ } ++ // We now do the memset after transform_add while we know the data is cached. ++@@ -1508,7 +1508,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode); ++ } ++ } else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) { ++- s->hevcdsp.idct_4x4_luma(coeffs); +++ s->hevcdsp.idct_4x4_luma(coeffs); ++ } else { ++ #ifdef RPI ++ if (!use_vpu) { ++@@ -1553,7 +1553,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ } ++ #ifdef RPI ++ if (s->enable_rpi) { ++- HEVCPredCmd *cmd = s->univ_pred_cmds + s->num_pred_cmds++; +++ HEVCPredCmd *cmd = s->univ_pred_cmds[s->pass0_job] + s->num_pred_cmds[s->pass0_job]++; ++ cmd->type = RPI_PRED_TRANSFORM_ADD; ++ cmd->size = log2_trafo_size; ++ cmd->buf = coeffs; ++diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c ++index 71c6d52..344e021 100644 ++--- a/libavcodec/hevcpred_template.c +++++ b/libavcodec/hevcpred_template.c ++@@ -71,8 +71,11 @@ do { \ ++ AV_WN4P(&ptr[i], a); \ ++ else \ ++ a = PIXEL_SPLAT_X4(ptr[i + 3]) ++- +++#ifdef RPI_WORKER +++ HEVCLocalContextIntra *lc = &s->HEVClcIntra; +++#else ++ HEVCLocalContext *lc = s->HEVClc; +++#endif ++ int i; ++ int hshift = s->ps.sps->hshift[c_idx]; ++ int vshift = s->ps.sps->vshift[c_idx]; ++-- ++2.5.0 ++ ++ ++From ec8c58875a457dcda45e8bbe1edc0efec41e4707 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 3 Jun 2015 13:43:48 +0100 ++Subject: [PATCH 54/68] Avoid lockup bug with RPI_WORKER enabled ++ ++--- ++ libavcodec/hevc.c | 22 +++++++++++----------- ++ libavcodec/hevc_cabac.c | 1 - ++ 2 files changed, 11 insertions(+), 12 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 6f67872..865f5ec 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -133,11 +133,11 @@ static uint32_t get_vc_address(AVBufferRef *bref) { ++ static void worker_submit_job(HEVCContext *s) ++ { ++ LOG_ENTER ++- //pthread_mutex_lock(&s->worker_mutex); ++- s->worker_tail++; // This is the only place that can change tail so we do not need the mutex +++ pthread_mutex_lock(&s->worker_mutex); +++ s->worker_tail++; ++ s->pass0_job = (s->pass0_job + 1) % RPI_MAX_JOBS; // Move onto the next slot ++ pthread_cond_broadcast(&s->worker_cond_tail); // Let people know that the tail has moved ++- //pthread_mutex_unlock(&s->worker_mutex); +++ pthread_mutex_unlock(&s->worker_mutex); ++ LOG_EXIT ++ } ++ ++@@ -145,11 +145,11 @@ static void worker_submit_job(HEVCContext *s) ++ static void worker_complete_middle_job(HEVCContext *s) ++ { ++ LOG_ENTER ++- //pthread_mutex_lock(&s->worker_mutex); ++- s->worker_middle++; // This is the only place that can change head so we do not need the mutex +++ pthread_mutex_lock(&s->worker_mutex); +++ s->worker_middle++; ++ s->pass1_job = (s->pass1_job + 1) % RPI_MAX_JOBS; // Move onto the next slot ++- pthread_cond_broadcast(&s->worker_cond_middle); // Let people know that the tail has moved ++- //pthread_mutex_unlock(&s->worker_mutex); +++ pthread_cond_broadcast(&s->worker_cond_middle); // Let people know that the middle has moved +++ pthread_mutex_unlock(&s->worker_mutex); ++ LOG_EXIT ++ } ++ ++@@ -157,11 +157,11 @@ static void worker_complete_middle_job(HEVCContext *s) ++ static void worker_complete_job(HEVCContext *s) ++ { ++ LOG_ENTER ++- //pthread_mutex_lock(&s->worker_mutex); ++- s->worker_head++; // This is the only place that can change head so we do not need the mutex +++ pthread_mutex_lock(&s->worker_mutex); +++ s->worker_head++; ++ s->pass2_job = (s->pass2_job + 1) % RPI_MAX_JOBS; // Move onto the next slot ++- pthread_cond_broadcast(&s->worker_cond_head); // Let people know that the tail has moved ++- //pthread_mutex_unlock(&s->worker_mutex); +++ pthread_cond_broadcast(&s->worker_cond_head); // Let people know that the head has moved +++ pthread_mutex_unlock(&s->worker_mutex); ++ LOG_EXIT ++ } ++ ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index b9f773b..16e7ac3 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1497,7 +1497,6 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ for (i = 0; i < 8; i++) ++ FFSWAP(int16_t, coeffs[i], coeffs[16 - i - 1]); ++ } ++- ++ s->hevcdsp.transform_skip(coeffs, log2_trafo_size); ++ ++ if (explicit_rdpcm_flag || (s->ps.sps->implicit_rdpcm_enabled_flag && ++-- ++2.5.0 ++ ++ ++From d9e7ab6809af47b65372b9fd99e2d519c3d44b10 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 3 Jun 2015 15:37:19 +0100 ++Subject: [PATCH 55/68] Added code to flush buffers at start of frame ++ ++--- ++ libavcodec/hevc.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 72 insertions(+) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 865f5ec..3a94830 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -43,6 +43,7 @@ ++ ++ #ifdef RPI ++ #include "rpi_qpu.h" +++ #include "rpi_user_vcsm.h" ++ // Move Inter prediction into separate pass ++ #define RPI_INTER ++ ++@@ -3497,6 +3498,7 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ #else ++ gpu_cache_flush(&s->coeffs_buf_accelerated[job]); ++ #endif +++ ++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], s->num_coeffs[job][3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++ (uint32_t)(unif_vc+(s->mvs_base[job][0 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), ++@@ -3547,6 +3549,71 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ } ++ #endif ++ +++#ifdef RPI +++ +++static void flush_buffer(AVBufferRef *bref) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); +++ gpu_cache_flush(p); +++} +++ +++static void flush_frame(HEVCContext *s,AVFrame *frame) +++{ +++#if 1 +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ int n = s->ps.sps->height; +++ int curr_y = 0; +++ int curr_uv = 0; +++ int n_uv = n >> s->ps.sps->vshift[1]; +++ int sz,base; +++ sz = s->frame->linesize[1] * (n_uv-curr_uv); +++ base = s->frame->linesize[1] * curr_uv; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = p->arm + base; +++ iocache.s[0].size = sz; +++ p = av_buffer_pool_opaque(frame->buf[2]); +++ iocache.s[1].handle = p->vcsm_handle; +++ iocache.s[1].cmd = 3; // clean+invalidate +++ iocache.s[1].addr = p->arm + base; +++ iocache.s[1].size = sz; +++ p = av_buffer_pool_opaque(frame->buf[0]); +++ sz = s->frame->linesize[0] * (n-curr_y); +++ base = s->frame->linesize[0] * curr_y; +++ iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].cmd = 3; // clean+invalidate +++ iocache.s[2].addr = p->arm + base; +++ iocache.s[2].size = sz; +++ vcsm_clean_invalid( &iocache ); +++#else +++ flush_buffer(frame->buf[0]); +++ flush_buffer(frame->buf[1]); +++ flush_buffer(frame->buf[2]); +++#endif +++} +++ +++static void flush_all(HEVCContext *s) +++{ +++#if 0 +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(s->frame->buf[0]); +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 4; // Flush all +++ iocache.s[0].addr = p->arm; +++ iocache.s[0].size = 4096; +++ vcsm_clean_invalid( &iocache ); +++#else +++ int i,k; +++ for(i=0;i<2;i++) { +++ for (k = 0; k < s->sh.nb_refs[i]; k++) { +++ flush_frame(s,s->ref->refPicList[i].ref[k]->frame); +++ } +++ } +++ flush_frame(s,s->frame); +++#endif +++} +++#endif +++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ { ++ HEVCContext *s = avctxt->priv_data; ++@@ -3581,8 +3648,12 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ printf("Weighted B slice\n"); ++ } ++ +++ // Now flush all reference frames and our destination frame to get everything ready for decode +++ flush_all(s); ++ #endif ++ +++ //printf("L0=%d L1=%d\n",s->sh.nb_refs[L1],s->sh.nb_refs[L1]); +++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++ return AVERROR_INVALIDDATA; ++@@ -3653,6 +3724,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ rpi_do_all_passes(s); ++ #endif ++ } +++ ++ } ++ #endif ++ ++-- ++2.5.0 ++ ++ ++From 2e0fc42393a67cc61d84311640d1e44b32f2bffb Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 3 Jun 2015 16:42:24 +0100 ++Subject: [PATCH 56/68] Reduce the amount that needs to be flushed ++ ++--- ++ libavcodec/hevc.c | 35 +++++++++++------------------------ ++ 1 file changed, 11 insertions(+), 24 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 3a94830..3fcbc57 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3558,7 +3558,7 @@ static void flush_buffer(AVBufferRef *bref) { ++ ++ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ { ++-#if 1 +++#ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++ int n = s->ps.sps->height; ++ int curr_y = 0; ++@@ -3592,26 +3592,6 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ #endif ++ } ++ ++-static void flush_all(HEVCContext *s) ++-{ ++-#if 0 ++- struct vcsm_user_clean_invalid_s iocache = {}; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(s->frame->buf[0]); ++- iocache.s[0].handle = p->vcsm_handle; ++- iocache.s[0].cmd = 4; // Flush all ++- iocache.s[0].addr = p->arm; ++- iocache.s[0].size = 4096; ++- vcsm_clean_invalid( &iocache ); ++-#else ++- int i,k; ++- for(i=0;i<2;i++) { ++- for (k = 0; k < s->sh.nb_refs[i]; k++) { ++- flush_frame(s,s->ref->refPicList[i].ref[k]->frame); ++- } ++- } ++- flush_frame(s,s->frame); ++-#endif ++-} ++ #endif ++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++@@ -3647,9 +3627,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ if (s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE) ++ printf("Weighted B slice\n"); ++ } ++- ++- // Now flush all reference frames and our destination frame to get everything ready for decode ++- flush_all(s); ++ #endif ++ ++ //printf("L0=%d L1=%d\n",s->sh.nb_refs[L1],s->sh.nb_refs[L1]); ++@@ -4119,6 +4096,11 @@ static int hevc_frame_start(HEVCContext *s) ++ if (!s->avctx->hwaccel) ++ ff_thread_finish_setup(s->avctx); ++ +++#ifdef RPI_INTER_QPU +++ // Invalidate the output data buffer so it is ready for the QPUs to write into it. +++ flush_frame(s,s->frame); +++#endif +++ ++ return 0; ++ ++ fail: ++@@ -4320,6 +4302,11 @@ fail: ++ ff_hevc_flush_buffer(s, &s->ref->tf, s->ps.sps->height); ++ #endif ++ ff_thread_report_progress(&s->ref->tf, INT_MAX, 0); +++ } else if (s->ref) { +++#ifdef RPI_INTER_QPU +++ // When running single threaded we need to flush the whole frame +++ flush_frame(s,s->frame); +++#endif ++ } ++ return ret; ++ } ++-- ++2.5.0 ++ ++ ++From 0cc4754dcc1c36647d92c3f42be39f24d24c48a2 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 4 Jun 2015 07:59:28 +0100 ++Subject: [PATCH 57/68] Corrected support for disabled rpi when using ++ RPI_WORKER ++ ++--- ++ libavcodec/hevc.h | 18 ++++++++++-------- ++ libavcodec/hevcpred_template.c | 2 +- ++ 2 files changed, 11 insertions(+), 9 deletions(-) ++ ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index b540ca5..c48d0cd 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -795,7 +795,17 @@ typedef struct HEVCPacket { ++ int nals_allocated; ++ } HEVCPacket; ++ +++#ifdef RPI_WORKER +++typedef struct HEVCLocalContextIntra { +++ TransformUnit tu; +++ NeighbourAvailable na; +++} HEVCLocalContextIntra; +++#endif +++ ++ typedef struct HEVCLocalContext { +++ TransformUnit tu; +++ NeighbourAvailable na; // WARNING tu and na must be the first two fields to match HEVCLocalContextIntra +++ ++ uint8_t cabac_state[HEVC_CONTEXTS]; ++ ++ uint8_t stat_coeff[4]; ++@@ -810,7 +820,6 @@ typedef struct HEVCLocalContext { ++ ++ int qPy_pred; ++ ++- TransformUnit tu; ++ ++ uint8_t ctb_left_flag; ++ uint8_t ctb_up_flag; ++@@ -827,7 +836,6 @@ typedef struct HEVCLocalContext { ++ int ct_depth; ++ CodingUnit cu; ++ PredictionUnit pu; ++- NeighbourAvailable na; ++ ++ #define BOUNDARY_LEFT_SLICE (1 << 0) ++ #define BOUNDARY_LEFT_TILE (1 << 1) ++@@ -838,12 +846,6 @@ typedef struct HEVCLocalContext { ++ int boundary_flags; ++ } HEVCLocalContext; ++ ++-#ifdef RPI_WORKER ++-typedef struct HEVCLocalContextIntra { ++- TransformUnit tu; ++- NeighbourAvailable na; ++-} HEVCLocalContextIntra; ++-#endif ++ ++ #ifdef RPI ++ ++diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c ++index 344e021..325b60e 100644 ++--- a/libavcodec/hevcpred_template.c +++++ b/libavcodec/hevcpred_template.c ++@@ -72,7 +72,7 @@ do { \ ++ else \ ++ a = PIXEL_SPLAT_X4(ptr[i + 3]) ++ #ifdef RPI_WORKER ++- HEVCLocalContextIntra *lc = &s->HEVClcIntra; +++ HEVCLocalContextIntra *lc = s->enable_rpi ? &s->HEVClcIntra : (HEVCLocalContextIntra *)s->HEVClc ; ++ #else ++ HEVCLocalContext *lc = s->HEVClc; ++ #endif ++-- ++2.5.0 ++ ++ ++From b1ca5230c3a2e5e74945c6f06f75c5dcec62d9d0 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 4 Jun 2015 11:52:55 +0100 ++Subject: [PATCH 58/68] Draft support for tiles ++ ++--- ++ libavcodec/hevc.c | 140 +++++++++++++++++++++++------------------ ++ libavcodec/hevc.h | 21 +++++-- ++ libavcodec/hevc_filter.c | 2 +- ++ libavcodec/hevcpred_template.c | 2 +- ++ 4 files changed, 99 insertions(+), 66 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 3fcbc57..23c4e17 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -63,10 +63,10 @@ ++ ++ static void rpi_execute_dblk_cmds(HEVCContext *s); ++ static void rpi_execute_transform(HEVCContext *s); ++- static void rpi_execute_inter_qpu(HEVCContext *s); +++ static void rpi_launch_vpu_qpu(HEVCContext *s); ++ static void rpi_execute_pred_cmds(HEVCContext *s); ++ static void rpi_execute_inter_cmds(HEVCContext *s); ++- static void rpi_inter_clear(HEVCContext *s); +++ static void rpi_begin(HEVCContext *s); ++ ++ // Define INTER_PASS0 to do inter prediction in first pass ++ //#define INTER_PASS0 ++@@ -90,16 +90,18 @@ const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12 ++ ++ #ifdef RPI_INTER_QPU ++ +++// Each luma QPU processes 2*RPI_NUM_CHUNKS 64x64 blocks +++// Each chroma QPU processes 3*RPI_NUM_CHUNKS 64x64 blocks, but requires two commands for B blocks +++// For each block of 64*64 the smallest block size is 8x4 +++// We also need an extra command for the setup information +++ ++ #define RPI_CHROMA_COMMAND_WORDS 12 ++-#define UV_COMMANDS_PER_QPU ((1 + (256*64*2)/(4*4)) * RPI_CHROMA_COMMAND_WORDS) +++#define UV_COMMANDS_PER_QPU ((1 + 3*RPI_NUM_CHUNKS*(64*64)*2/(8*4)) * RPI_CHROMA_COMMAND_WORDS) ++ // The QPU code for UV blocks only works up to a block width of 8 ++ #define RPI_CHROMA_BLOCK_WIDTH 8 ++ ++-// Split image of 2048 into parts 64 wide ++-// So some QPUs will have 3 blocks of 64 to do, and others 2 blocks for an image 2048 wide with 32 blocks across ++-// For each block of 64*64 the smallest block size is 8x4 ++ #define RPI_LUMA_COMMAND_WORDS 9 ++-#define Y_COMMANDS_PER_QPU ((1+3*(64*64)/(8*4)) * RPI_LUMA_COMMAND_WORDS) +++#define Y_COMMANDS_PER_QPU ((1+2*RPI_NUM_CHUNKS*(64*64)/(8*4)) * RPI_LUMA_COMMAND_WORDS) ++ ++ #define ENCODE_COEFFS(c0, c1, c2, c3) (((c0) & 0xff) | ((c1) & 0xff) << 8 | ((c2) & 0xff) << 16 | ((c3) & 0xff) << 24) ++ ++@@ -216,7 +218,7 @@ static void *worker_start(void *arg) ++ LOG_ENTER ++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++ #ifndef LAUNCH_PASS0 ++- rpi_execute_inter_qpu(s); +++ rpi_launch_vpu_qpu(s); ++ #endif ++ #ifndef INTER_PASS0 ++ // Perform inter prediction ++@@ -322,9 +324,14 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ ++ #ifdef RPI ++ av_assert0(sps); ++- int coeffs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); ++- int coefs_per_row = sps->ctb_width * coeffs_in_ctb * 3; // Allow space for chroma +++ int coefs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); +++ int coefs_per_luma = 64*64*24*RPI_NUM_CHUNKS; +++ int coefs_per_chroma = (coefs_per_luma * 2) >> sps->vshift[1] >> sps->hshift[1]; +++ int coefs_per_row = coefs_per_luma + coefs_per_chroma; ++ int job; +++ s->max_ctu_count = coefs_per_luma / coefs_in_ctb; +++ s->ctu_per_y_chan = s->max_ctu_count / 12; +++ s->ctu_per_uv_chan = s->max_ctu_count / 8; ++ for(job=0;jobx >> 2); ++ int y1 = y0 + (mv->y >> 2); ++- int chan = x0>>6; // 64 wide blocks per QPU ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++- uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; +++ uint32_t *y = s->curr_y_mvs; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { ++ int bw = nPbW-start_x; ++@@ -2198,7 +2204,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++- s->y_mvs[s->pass0_job][chan % 12] = y; +++ s->curr_y_mvs = y; ++ } else ++ #endif ++ { ++@@ -2222,12 +2228,10 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ ++ int x1_c = x0_c + (mv->x >> (2 + hshift)); ++ int y1_c = y0_c + (mv->y >> (2 + hshift)); ++- //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++- int chan = x0>>8; ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++- uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; +++ uint32_t *u = s->curr_u_mvs; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2251,7 +2255,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[s->pass0_job][chan & 7] = u; +++ s->curr_u_mvs = u; ++ return; ++ } ++ #endif ++@@ -2278,10 +2282,9 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int my2_mx2_my_mx = (my_mx << 16) + my_mx; ++ int x1 = x0 + (mv->x >> 2); ++ int y1 = y0 + (mv->y >> 2); ++- int chan = x0>>6; // 64 wide blocks per QPU ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++- uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; +++ uint32_t *y = s->curr_y_mvs; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=16) { ++ int bw = nPbW-start_x; ++@@ -2301,7 +2304,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++- s->y_mvs[s->pass0_job][chan % 12] = y; +++ s->curr_y_mvs = y; ++ } else ++ #endif ++ ++@@ -2326,12 +2329,10 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ ++ int x1_c = x0_c + (mv->x >> (2 + hshift)); ++ int y1_c = y0_c + (mv->y >> (2 + hshift)); ++- //int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++- int chan = x0>>8; ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == B_SLICE && s->ps.pps->weighted_bipred_flag); ++ ++- uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; +++ uint32_t *u = s->curr_u_mvs; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2356,7 +2357,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[s->pass0_job][chan & 7] = u; +++ s->curr_u_mvs = u; ++ return; ++ } ++ #endif ++@@ -2389,8 +2390,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int y1 = y0 + (mv->y >> 2); ++ int x2 = x0 + (mv2->x >> 2); ++ int y2 = y0 + (mv2->y >> 2); ++- int chan = x0>>6; // 64 wide blocks per QPU ++- uint32_t *y = s->y_mvs[s->pass0_job][chan % 12]; +++ uint32_t *y = s->curr_y_mvs; ++ for(int start_y=0;start_y < nPbH;start_y+=16) { // Potentially we could change the assembly code to support taller sizes in one go ++ for(int start_x=0;start_x < nPbW;start_x+=8) { // B blocks work 8 at a time ++ int bw = nPbW-start_x; ++@@ -2406,7 +2406,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter_b; ++ } ++ } ++- s->y_mvs[s->pass0_job][chan % 12] = y; +++ s->curr_y_mvs = y; ++ } else ++ #endif ++ { ++@@ -2437,9 +2437,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int x2_c = x0_c + (mv2->x >> (2 + hshift)); ++ int y2_c = y0_c + (mv2->y >> (2 + hshift)); ++ ++- int chan = x0>>8; // Allocate commands for the first 256 luma pixels across to the first QPU. This is optimised for images around 1920 width ++ ++- uint32_t *u = s->u_mvs[s->pass0_job][chan & 7]; +++ uint32_t *u = s->curr_u_mvs; ++ for(int start_y=0;start_y < nPbH_c;start_y+=16) { ++ for(int start_x=0;start_x < nPbW_c;start_x+=RPI_CHROMA_BLOCK_WIDTH) { ++ int bw = nPbW_c-start_x; ++@@ -2468,7 +2467,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++- s->u_mvs[s->pass0_job][chan & 7] = u; +++ s->curr_u_mvs = u; ++ return; ++ } ++ #endif ++@@ -3103,12 +3102,8 @@ static void rpi_execute_inter_cmds(HEVCContext *s) ++ ++ static void rpi_do_all_passes(HEVCContext *s) ++ { ++-#ifdef RPI_INTER_QPU ++- // Kick off inter prediction on QPUs ++- rpi_execute_inter_qpu(s); ++-#else ++- rpi_execute_transform(s); ++-#endif +++ // Kick off QPUs and VPUs +++ rpi_launch_vpu_qpu(s); ++ // Perform luma inter prediction ++ rpi_execute_inter_cmds(s); ++ // Wait for transform completion ++@@ -3117,18 +3112,18 @@ static void rpi_do_all_passes(HEVCContext *s) ++ rpi_execute_pred_cmds(s); ++ // Perform deblocking for CTBs in this row ++ rpi_execute_dblk_cmds(s); ++-#ifdef RPI_INTER_QPU ++- rpi_inter_clear(s); ++-#endif +++ // Prepare next batch +++ rpi_begin(s); ++ } ++ ++ #endif ++ ++-#ifdef RPI_INTER_QPU ++-static void rpi_inter_clear(HEVCContext *s) +++#ifdef RPI +++static void rpi_begin(HEVCContext *s) ++ { ++ int job = s->pass0_job; ++ int i; +++#ifdef RPI_INTER_QPU ++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; ++ int weight_flag = (s->sh.slice_type == P_SLICE && s->ps.pps->weighted_pred_flag) || ++@@ -3154,6 +3149,8 @@ static void rpi_inter_clear(HEVCContext *s) ++ } ++ *s->u_mvs[job][i]++ = i; // Select section of VPM (avoid collisions with 3d unit) ++ } +++ s->curr_u_mvs = s->u_mvs[job][0]; +++#endif ++ ++ #ifdef RPI_LUMA_QPU ++ for(i=0;i<12;i++) { ++@@ -3176,8 +3173,11 @@ static void rpi_inter_clear(HEVCContext *s) ++ } ++ *s->y_mvs[job][i]++ = 0; // Next kernel ++ } +++ s->curr_y_mvs = s->y_mvs[job][0]; ++ #endif +++ s->ctu_count = 0; ++ } +++#endif ++ ++ #ifdef RPI_SIMULATE_QPUS ++ ++@@ -3448,8 +3448,9 @@ static void rpi_simulate_inter_qpu(HEVCContext *s) ++ ++ #endif ++ +++#ifdef RPI_INTER_QPU ++ ++-static void rpi_execute_inter_qpu(HEVCContext *s) +++static void rpi_launch_vpu_qpu(HEVCContext *s) ++ { ++ int k; ++ #ifdef LAUNCH_PASS0 ++@@ -3547,6 +3548,15 @@ static void rpi_execute_inter_qpu(HEVCContext *s) ++ ++ ++ } +++#else +++ +++#ifdef RPI +++static void rpi_launch_vpu_qpu(HEVCContext *s) +++{ +++ rpi_execute_transform(s); +++} +++#endif +++ ++ #endif ++ ++ #ifdef RPI ++@@ -3606,29 +3616,20 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI ++ #ifdef RPI_INTER_QPU ++ s->enable_rpi = s->ps.sps->bit_depth == 8 ++- && s->ps.sps->width <= RPI_MAX_WIDTH ++ && !s->ps.pps->cross_component_prediction_enabled_flag ++- && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1 ++ && !(s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE); ++ #else ++ s->enable_rpi = s->ps.sps->bit_depth == 8 ++- && s->ps.sps->width <= RPI_MAX_WIDTH ++- && !s->ps.pps->cross_component_prediction_enabled_flag ++- && s->ps.pps->num_tile_rows <= 1 && s->ps.pps->num_tile_columns <= 1; +++ && !s->ps.pps->cross_component_prediction_enabled_flag; ++ #endif ++ ++ if (!s->enable_rpi) { ++ if (s->ps.pps->cross_component_prediction_enabled_flag) ++ printf("Cross component\n"); ++- if (s->ps.pps->num_tile_rows > 1 || s->ps.pps->num_tile_columns > 1) ++- printf("Tiles\n"); ++- if (s->ps.pps->weighted_pred_flag && s->sh.slice_type == P_SLICE) ++- printf("Weighted P slice\n"); ++ if (s->ps.pps->weighted_bipred_flag && s->sh.slice_type == B_SLICE) ++ printf("Weighted B slice\n"); ++ } ++ #endif ++- ++ //printf("L0=%d L1=%d\n",s->sh.nb_refs[L1],s->sh.nb_refs[L1]); ++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++@@ -3649,8 +3650,8 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->pass1_job = 0; ++ s->pass2_job = 0; ++ #endif ++-#ifdef RPI_INTER_QPU ++- rpi_inter_clear(s); +++#ifdef RPI +++ rpi_begin(s); ++ #endif ++ ++ while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) { ++@@ -3668,13 +3669,34 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->deblock[ctb_addr_rs].tc_offset = s->sh.tc_offset; ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ +++#ifdef RPI_INTER_QPU +++ s->curr_u_mvs = s->u_mvs[s->pass0_job][s->ctu_count / s->ctu_per_uv_chan]; +++#endif +++#ifdef RPI_LUMA_QPU +++ s->curr_y_mvs = s->y_mvs[s->pass0_job][s->ctu_count / s->ctu_per_y_chan]; +++#endif +++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ +++#ifdef RPI_INTER_QPU +++ s->u_mvs[s->pass0_job][s->ctu_count / s->ctu_per_uv_chan] = s->curr_u_mvs; +++#endif +++#ifdef RPI_LUMA_QPU +++ s->y_mvs[s->pass0_job][s->ctu_count / s->ctu_per_y_chan] = s->curr_y_mvs; +++#endif +++ ++ #ifdef RPI ++ if (s->enable_rpi) { +++ //av_assert0(s->num_dblk_cmds[s->pass0_job]>=0); +++ //av_assert0(s->num_dblk_cmds[s->pass0_job]pass0_jobpass0_job>=0); ++ s->dblk_cmds[s->pass0_job][s->num_dblk_cmds[s->pass0_job]][0] = x_ctb; ++ s->dblk_cmds[s->pass0_job][s->num_dblk_cmds[s->pass0_job]++][1] = y_ctb; ++- if ( (((y_ctb + ctb_size)&63) == 0) && x_ctb + ctb_size >= s->ps.sps->width) { +++ s->ctu_count++; +++ //printf("%d %d/%d job=%d\n",s->ctu_count,s->num_dblk_cmds[s->pass0_job],RPI_MAX_DEBLOCK_CMDS,s->pass0_job); +++ +++ if ( s->ctu_count >= s->max_ctu_count ) { ++ #ifdef RPI_WORKER ++ if (s->used_for_ref) { ++ // Split work load onto separate threads so we make as rapid progress as possible with this frame ++@@ -3682,7 +3704,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ rpi_execute_inter_cmds(s); ++ #endif ++ #ifdef LAUNCH_PASS0 ++- rpi_execute_inter_qpu(s); +++ rpi_launch_vpu_qpu(s); ++ #endif ++ // Pass on this job to worker thread ++ worker_submit_job(s); ++@@ -3690,9 +3712,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ worker_pass0_ready(s); ++ ++ // Prepare the next batch of commands ++-#ifdef RPI_INTER_QPU ++- rpi_inter_clear(s); ++-#endif +++ rpi_begin(s); ++ } else { ++ // Non-ref frame so do it all on this thread ++ rpi_do_all_passes(s); ++@@ -3733,7 +3753,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #endif ++ ++ // Finish off any half-completed rows ++- if (s->enable_rpi && s->num_dblk_cmds[s->pass0_job]) { +++ if (s->enable_rpi && s->ctu_count) { ++ rpi_do_all_passes(s); ++ } ++ ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index c48d0cd..3aea745 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -849,8 +849,15 @@ typedef struct HEVCLocalContext { ++ ++ #ifdef RPI ++ +++// The processing is done in chunks +++// Each chunk corresponds to 24 64x64 luma blocks (24 so it is divisible by 8 for chroma and 12 for luma) +++// This is a distance of 1536 pixels across the screen +++// Increasing RPI_NUM_CHUNKS will reduce time spent activating QPUs and cache flushing, +++// but allocate more memory and increase the latency before data in the next frame can be processed +++#define RPI_NUM_CHUNKS 1 +++ ++ // RPI_MAX_WIDTH is maximum width in pixels supported by the accelerated code ++-#define RPI_MAX_WIDTH 2048 +++#define RPI_MAX_WIDTH (RPI_NUM_CHUNKS*64*24) ++ ++ // Worst case is for 4:4:4 4x4 blocks with 64 high coding tree blocks, so 16 MV cmds per 4 pixels across for each colour plane, * 2 for bi ++ #define RPI_MAX_MV_CMDS (2*16*3*(RPI_MAX_WIDTH/4)) ++@@ -914,9 +921,6 @@ typedef struct HEVCPredCmd { ++ #endif ++ ++ typedef struct HEVCContext { ++-#ifdef RPI ++- int dblk_cmds[RPI_MAX_JOBS][RPI_MAX_DEBLOCK_CMDS][2]; ++-#endif ++ const AVClass *c; // needed by private avoptions ++ AVCodecContext *avctx; ++ ++@@ -954,6 +958,10 @@ typedef struct HEVCContext { ++ int pass0_job; // Pass0 does coefficient decode ++ int pass1_job; // Pass1 does pixel processing ++ int pass2_job; // Pass2 does reconstruction and deblocking +++ int ctu_count; // Number of CTUs done in pass0 so far +++ int max_ctu_count; // Number of CTUs when we trigger a round of processing +++ int ctu_per_y_chan; // Number of CTUs per luma QPU +++ int ctu_per_uv_chan; // Number of CTUs per chroma QPU ++ #ifdef RPI_INTER_QPU ++ GPU_MEM_PTR_T unif_mvs_ptr[RPI_MAX_JOBS]; ++ uint32_t *unif_mvs[RPI_MAX_JOBS]; // Base of memory for motion vector commands ++@@ -962,6 +970,7 @@ typedef struct HEVCContext { ++ uint32_t *mvs_base[RPI_MAX_JOBS][8]; ++ // these pointers are to the next free space ++ uint32_t *u_mvs[RPI_MAX_JOBS][8]; +++ uint32_t *curr_u_mvs; // Current uniform stream to use for chroma ++ // Function pointers ++ uint32_t mc_filter_uv; ++ uint32_t mc_filter_uv_b0; ++@@ -972,6 +981,7 @@ typedef struct HEVCContext { ++ uint32_t *y_unif_mvs[RPI_MAX_JOBS]; // Base of memory for motion vector commands ++ uint32_t *y_mvs_base[RPI_MAX_JOBS][12]; ++ uint32_t *y_mvs[RPI_MAX_JOBS][12]; +++ uint32_t *curr_y_mvs; // Current uniform stream for luma ++ // Function pointers ++ uint32_t mc_filter; ++ uint32_t mc_filter_b; ++@@ -1110,6 +1120,9 @@ typedef struct HEVCContext { ++ uint32_t max_mastering_luminance; ++ uint32_t min_mastering_luminance; ++ +++#ifdef RPI +++ int dblk_cmds[RPI_MAX_JOBS][RPI_MAX_DEBLOCK_CMDS][2]; +++#endif ++ } HEVCContext; ++ ++ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index b286bbf..1f04790 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -891,7 +891,7 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ int n_uv = n >> s->ps.sps->vshift[1]; ++ int sz,base; ++ if (curr_uv < 0) curr_uv = 0; ++- if (n_uv<=curr_uv) { assert(0); return; } // Should not happen +++ if (n_uv<=curr_uv) { return; } ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(s->frame->buf[1]); ++diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c ++index 325b60e..28d2653 100644 ++--- a/libavcodec/hevcpred_template.c +++++ b/libavcodec/hevcpred_template.c ++@@ -72,7 +72,7 @@ do { \ ++ else \ ++ a = PIXEL_SPLAT_X4(ptr[i + 3]) ++ #ifdef RPI_WORKER ++- HEVCLocalContextIntra *lc = s->enable_rpi ? &s->HEVClcIntra : (HEVCLocalContextIntra *)s->HEVClc ; +++ HEVCLocalContextIntra *lc = (s->enable_rpi) ? &s->HEVClcIntra : (HEVCLocalContextIntra *)s->HEVClc ; ++ #else ++ HEVCLocalContext *lc = s->HEVClc; ++ #endif ++-- ++2.5.0 ++ ++ ++From eaaaee12acbb4d4c27191ceafadaa778d3ba0f2f Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 4 Jun 2015 15:48:10 +0100 ++Subject: [PATCH 59/68] Move deblocker into second pass ++ ++--- ++ libavcodec/hevc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++---------- ++ 1 file changed, 65 insertions(+), 14 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 23c4e17..dde932f 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -67,6 +67,8 @@ ++ static void rpi_execute_pred_cmds(HEVCContext *s); ++ static void rpi_execute_inter_cmds(HEVCContext *s); ++ static void rpi_begin(HEVCContext *s); +++ static void flush_frame(HEVCContext *s,AVFrame *frame); +++ static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2); ++ ++ // Define INTER_PASS0 to do inter prediction in first pass ++ //#define INTER_PASS0 ++@@ -227,6 +229,11 @@ static void *worker_start(void *arg) ++ // Wait for transform completion ++ vpu_wait(s->vpu_id); ++ +++ // Perform intra prediction and residual reconstruction +++ rpi_execute_pred_cmds(s); +++ // Perform deblocking for CTBs in this row +++ rpi_execute_dblk_cmds(s); +++ ++ worker_complete_middle_job(s); ++ LOG_EXIT ++ } ++@@ -248,10 +255,6 @@ static void *worker_deblock_start(void *arg) ++ break; ++ } ++ LOG_ENTER ++- // Perform intra prediction and residual reconstruction ++- rpi_execute_pred_cmds(s); ++- // Perform deblocking for CTBs in this row ++- rpi_execute_dblk_cmds(s); ++ ++ worker_complete_job(s); ++ LOG_EXIT ++@@ -2972,7 +2975,7 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ static void rpi_execute_dblk_cmds(HEVCContext *s) ++ { ++ int n; ++- int job = s->pass2_job; +++ int job = s->pass1_job; ++ int ctb_size = 1 << s->ps.sps->log2_ctb_size; ++ int (*p)[2] = s->dblk_cmds[job]; ++ for(n = s->num_dblk_cmds[job]; n>0 ;n--,p++) { ++@@ -3010,7 +3013,7 @@ static void rpi_execute_transform(HEVCContext *s) ++ static void rpi_execute_pred_cmds(HEVCContext *s) ++ { ++ int i; ++- int job = s->pass2_job; +++ int job = s->pass1_job; ++ HEVCPredCmd *cmd = s->univ_pred_cmds[job]; ++ #ifdef RPI_WORKER ++ HEVCLocalContextIntra *lc = &s->HEVClcIntra; ++@@ -3495,11 +3498,10 @@ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ ++ #ifdef RPI_MULTI_MAILBOX ++ #ifdef RPI_CACHE_UNIF_MVS ++- gpu_cache_flush3(&s->coeffs_buf_accelerated[job],&s->y_unif_mvs_ptr[job], &s->unif_mvs_ptr[job]); +++ flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],&s->y_unif_mvs_ptr[job], &s->unif_mvs_ptr[job]); ++ #else ++- gpu_cache_flush(&s->coeffs_buf_accelerated[job]); +++ flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],NULL,NULL); ++ #endif ++- ++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], s->num_coeffs[job][3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++ (uint32_t)(unif_vc+(s->mvs_base[job][0 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), ++@@ -3602,6 +3604,60 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ #endif ++ } ++ +++static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2) +++{ +++#ifdef RPI_FAST_CACHEFLUSH +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ int n = s->ps.sps->height; +++ int curr_y = 0; +++ int curr_uv = 0; +++ int n_uv = n >> s->ps.sps->vshift[1]; +++ int sz,base; +++ sz = s->frame->linesize[1] * (n_uv-curr_uv); +++ base = s->frame->linesize[1] * curr_uv; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = p->arm + base; +++ iocache.s[0].size = sz; +++ p = av_buffer_pool_opaque(frame->buf[2]); +++ iocache.s[1].handle = p->vcsm_handle; +++ iocache.s[1].cmd = 3; // clean+invalidate +++ iocache.s[1].addr = p->arm + base; +++ iocache.s[1].size = sz; +++ p = av_buffer_pool_opaque(frame->buf[0]); +++ sz = s->frame->linesize[0] * (n-curr_y); +++ base = s->frame->linesize[0] * curr_y; +++ iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].cmd = 3; // clean+invalidate +++ iocache.s[2].addr = p->arm + base; +++ iocache.s[2].size = sz; +++ +++ iocache.s[3].handle = p0->vcsm_handle; +++ iocache.s[3].cmd = 3; // clean+invalidate +++ iocache.s[3].addr = (int) p0->arm; +++ iocache.s[3].size = p0->numbytes; +++ if (p1) { +++ iocache.s[4].handle = p1->vcsm_handle; +++ iocache.s[4].cmd = 3; // clean+invalidate +++ iocache.s[4].addr = (int) p1->arm; +++ iocache.s[4].size = p1->numbytes; +++ } +++ if (p2) { +++ iocache.s[5].handle = p2->vcsm_handle; +++ iocache.s[5].cmd = 3; // clean+invalidate +++ iocache.s[5].addr = (int) p2->arm; +++ iocache.s[5].size = p2->numbytes; +++ } +++ vcsm_clean_invalid( &iocache ); +++#else +++ flush_buffer(frame->buf[0]); +++ flush_buffer(frame->buf[1]); +++ flush_buffer(frame->buf[2]); +++ gpu_cache_flush3(p0, p1, p2); +++#endif +++} +++ ++ #endif ++ ++ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++@@ -4116,11 +4172,6 @@ static int hevc_frame_start(HEVCContext *s) ++ if (!s->avctx->hwaccel) ++ ff_thread_finish_setup(s->avctx); ++ ++-#ifdef RPI_INTER_QPU ++- // Invalidate the output data buffer so it is ready for the QPUs to write into it. ++- flush_frame(s,s->frame); ++-#endif ++- ++ return 0; ++ ++ fail: ++-- ++2.5.0 ++ ++ ++From f45417c35888b74a36a5ecc6959480787e727b0c Mon Sep 17 00:00:00 2001 ++From: popcornmix ++Date: Thu, 4 Jun 2015 16:10:23 +0100 ++Subject: [PATCH 60/68] Change order of ctu accesses to improve qpu performance ++ ++--- ++ libavcodec/hevc.c | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index dde932f..e247444 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -3726,19 +3726,19 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ ++ #ifdef RPI_INTER_QPU ++- s->curr_u_mvs = s->u_mvs[s->pass0_job][s->ctu_count / s->ctu_per_uv_chan]; +++ s->curr_u_mvs = s->u_mvs[s->pass0_job][s->ctu_count % 8]; ++ #endif ++ #ifdef RPI_LUMA_QPU ++- s->curr_y_mvs = s->y_mvs[s->pass0_job][s->ctu_count / s->ctu_per_y_chan]; +++ s->curr_y_mvs = s->y_mvs[s->pass0_job][s->ctu_count % 12]; ++ #endif ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ ++ #ifdef RPI_INTER_QPU ++- s->u_mvs[s->pass0_job][s->ctu_count / s->ctu_per_uv_chan] = s->curr_u_mvs; +++ s->u_mvs[s->pass0_job][s->ctu_count % 8]= s->curr_u_mvs; ++ #endif ++ #ifdef RPI_LUMA_QPU ++- s->y_mvs[s->pass0_job][s->ctu_count / s->ctu_per_y_chan] = s->curr_y_mvs; +++ s->y_mvs[s->pass0_job][s->ctu_count % 12] = s->curr_y_mvs; ++ #endif ++ ++ #ifdef RPI ++-- ++2.5.0 ++ ++ ++From 8d8b31eeffebf0a40c3b267d1b16401ef267bbf5 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 8 Jun 2015 09:36:59 +0100 ++Subject: [PATCH 61/68] Removed deblocker thread ++ ++--- ++ libavcodec/hevc.c | 77 +++---------------------------------------------------- ++ libavcodec/hevc.h | 4 --- ++ 2 files changed, 4 insertions(+), 77 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index e247444..bbb7ad3 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -70,11 +70,6 @@ ++ static void flush_frame(HEVCContext *s,AVFrame *frame); ++ static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2); ++ ++- // Define INTER_PASS0 to do inter prediction in first pass ++- //#define INTER_PASS0 ++- // Define LAUNCH_PASS0 to launch QPU/VPU from pass0 ++- //#define LAUNCH_PASS0 ++- ++ #endif ++ ++ // #define DISABLE_MC ++@@ -147,24 +142,12 @@ static void worker_submit_job(HEVCContext *s) ++ } ++ ++ // Call this to say we have completed pass1 ++-static void worker_complete_middle_job(HEVCContext *s) ++-{ ++- LOG_ENTER ++- pthread_mutex_lock(&s->worker_mutex); ++- s->worker_middle++; ++- s->pass1_job = (s->pass1_job + 1) % RPI_MAX_JOBS; // Move onto the next slot ++- pthread_cond_broadcast(&s->worker_cond_middle); // Let people know that the middle has moved ++- pthread_mutex_unlock(&s->worker_mutex); ++- LOG_EXIT ++-} ++- ++-// Call this to say we have completed pass2 ++ static void worker_complete_job(HEVCContext *s) ++ { ++ LOG_ENTER ++ pthread_mutex_lock(&s->worker_mutex); ++ s->worker_head++; ++- s->pass2_job = (s->pass2_job + 1) % RPI_MAX_JOBS; // Move onto the next slot +++ s->pass1_job = (s->pass1_job + 1) % RPI_MAX_JOBS; // Move onto the next slot ++ pthread_cond_broadcast(&s->worker_cond_head); // Let people know that the head has moved ++ pthread_mutex_unlock(&s->worker_mutex); ++ LOG_EXIT ++@@ -208,7 +191,7 @@ static void *worker_start(void *arg) ++ while(1) { ++ pthread_mutex_lock(&s->worker_mutex); ++ ++- while( !s->kill_worker && s->worker_tail - s->worker_middle <= 0) +++ while( !s->kill_worker && s->worker_tail - s->worker_head <= 0) ++ { ++ pthread_cond_wait(&s->worker_cond_tail, &s->worker_mutex); ++ } ++@@ -219,13 +202,9 @@ static void *worker_start(void *arg) ++ } ++ LOG_ENTER ++ // printf("%d %d %d : %d %d %d %d\n",s->poc, x_ctb, y_ctb, s->num_pred_cmds,s->num_mv_cmds,s->num_coeffs[2] >> 8,s->num_coeffs[3] >> 10); ++-#ifndef LAUNCH_PASS0 ++ rpi_launch_vpu_qpu(s); ++-#endif ++-#ifndef INTER_PASS0 ++ // Perform inter prediction ++ rpi_execute_inter_cmds(s); ++-#endif ++ // Wait for transform completion ++ vpu_wait(s->vpu_id); ++ ++@@ -234,28 +213,6 @@ static void *worker_start(void *arg) ++ // Perform deblocking for CTBs in this row ++ rpi_execute_dblk_cmds(s); ++ ++- worker_complete_middle_job(s); ++- LOG_EXIT ++- } ++- return NULL; ++-} ++- ++-static void *worker_deblock_start(void *arg) ++-{ ++- HEVCContext *s = (HEVCContext *)arg; ++- while(1) { ++- pthread_mutex_lock(&s->worker_mutex); ++- while( !s->kill_worker && s->worker_middle - s->worker_head <= 0) ++- { ++- pthread_cond_wait(&s->worker_cond_middle, &s->worker_mutex); ++- } ++- pthread_mutex_unlock(&s->worker_mutex); ++- ++- if (s->kill_worker) { ++- break; ++- } ++- LOG_ENTER ++- ++ worker_complete_job(s); ++ LOG_EXIT ++ } ++@@ -2987,11 +2944,7 @@ static void rpi_execute_dblk_cmds(HEVCContext *s) ++ static void rpi_execute_transform(HEVCContext *s) ++ { ++ int i=2; ++-#ifdef LAUNCH_PASS0 ++- int job = s->pass0_job; ++-#else ++ int job = s->pass1_job; ++-#endif ++ //int j; ++ //int16_t *coeffs = s->coeffs_buf_arm[i]; ++ //for(j=s->num_coeffs[i]; j > 0; j-= 16*16, coeffs+=16*16) { ++@@ -3046,11 +2999,7 @@ static void rpi_execute_pred_cmds(HEVCContext *s) ++ ++ static void rpi_execute_inter_cmds(HEVCContext *s) ++ { ++-#ifdef INTER_PASS0 ++- int job = s->pass0_job; ++-#else ++ int job = s->pass1_job; ++-#endif ++ HEVCMvCmd *cmd = s->unif_mv_cmds[job]; ++ int n,cidx; ++ AVFrame myref; ++@@ -3456,11 +3405,7 @@ static void rpi_simulate_inter_qpu(HEVCContext *s) ++ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ { ++ int k; ++-#ifdef LAUNCH_PASS0 ++- int job = s->pass0_job; ++-#else ++ int job = s->pass1_job; ++-#endif ++ int i; ++ uint32_t *unif_vc = (uint32_t *)s->unif_mvs_ptr[job].vc; ++ #ifdef RPI_LUMA_QPU ++@@ -3563,10 +3508,12 @@ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ ++ #ifdef RPI ++ +++#ifndef RPI_FAST_CACHEFLUSH ++ static void flush_buffer(AVBufferRef *bref) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++ gpu_cache_flush(p); ++ } +++#endif ++ ++ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ { ++@@ -3704,7 +3651,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI_WORKER ++ s->pass0_job = 0; ++ s->pass1_job = 0; ++- s->pass2_job = 0; ++ #endif ++ #ifdef RPI ++ rpi_begin(s); ++@@ -3756,12 +3702,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ #ifdef RPI_WORKER ++ if (s->used_for_ref) { ++ // Split work load onto separate threads so we make as rapid progress as possible with this frame ++- #ifdef INTER_PASS0 ++- rpi_execute_inter_cmds(s); ++- #endif ++- #ifdef LAUNCH_PASS0 ++- rpi_launch_vpu_qpu(s); ++- #endif ++ // Pass on this job to worker thread ++ worker_submit_job(s); ++ // Make sure we have space to prepare the next job ++@@ -3803,8 +3743,6 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++ // Wait for the worker to finish all its jobs ++ if (s->enable_rpi) { ++ worker_wait(s); ++- av_assert0(s->pass0_job==s->pass1_job); ++- av_assert0(s->pass1_job==s->pass2_job); ++ } ++ #endif ++ ++@@ -4554,16 +4492,13 @@ static av_cold void hevc_init_worker(HEVCContext *s) ++ { ++ int err; ++ pthread_cond_init(&s->worker_cond_head, NULL); ++- pthread_cond_init(&s->worker_cond_middle, NULL); ++ pthread_cond_init(&s->worker_cond_tail, NULL); ++ pthread_mutex_init(&s->worker_mutex, NULL); ++ ++ s->worker_tail=0; ++- s->worker_middle=0; ++ s->worker_head=0; ++ s->kill_worker=0; ++ err = pthread_create(&s->worker_thread, NULL, worker_start, s); ++- err = pthread_create(&s->worker_deblock_thread, NULL, worker_deblock_start, s); ++ if (err) { ++ printf("Failed to create worker thread\n"); ++ exit(-1); ++@@ -4575,17 +4510,13 @@ static av_cold void hevc_exit_worker(HEVCContext *s) ++ void *res; ++ s->kill_worker=1; ++ pthread_cond_broadcast(&s->worker_cond_tail); ++- pthread_cond_broadcast(&s->worker_cond_middle); ++ pthread_join(s->worker_thread, &res); ++- pthread_join(s->worker_deblock_thread, &res); ++ ++ pthread_cond_destroy(&s->worker_cond_head); ++- pthread_cond_destroy(&s->worker_cond_middle); ++ pthread_cond_destroy(&s->worker_cond_tail); ++ pthread_mutex_destroy(&s->worker_mutex); ++ ++ s->worker_tail=0; ++- s->worker_middle=0; ++ s->worker_head=0; ++ s->kill_worker=0; ++ } ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index 3aea745..a577fcb 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -957,7 +957,6 @@ typedef struct HEVCContext { ++ //GPU_MEM_PTR_T dummy; ++ int pass0_job; // Pass0 does coefficient decode ++ int pass1_job; // Pass1 does pixel processing ++- int pass2_job; // Pass2 does reconstruction and deblocking ++ int ctu_count; // Number of CTUs done in pass0 so far ++ int max_ctu_count; // Number of CTUs when we trigger a round of processing ++ int ctu_per_y_chan; // Number of CTUs per luma QPU ++@@ -989,15 +988,12 @@ typedef struct HEVCContext { ++ ++ #ifdef RPI_WORKER ++ pthread_t worker_thread; ++- pthread_t worker_deblock_thread; ++ pthread_cond_t worker_cond_head; ++ pthread_cond_t worker_cond_tail; ++- pthread_cond_t worker_cond_middle; ++ pthread_mutex_t worker_mutex; ++ ++ int worker_tail; // Contains the number of posted jobs ++ int worker_head; // Contains the number of completed jobs ++- int worker_middle; // Contains the number of completed jobs ++ int kill_worker; // set to 1 to terminate the worker ++ #endif ++ ++-- ++2.5.0 ++ ++ ++From 9ad14cb77eeec547db386bd2c3a6e25f41ae5b31 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 8 Jun 2015 11:04:43 +0100 ++Subject: [PATCH 62/68] Reduced amount of output frame that is invalidated ++ ++--- ++ libavcodec/hevc.c | 45 +++++++++++++++++++++++++++++---------------- ++ 1 file changed, 29 insertions(+), 16 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index bbb7ad3..2374c2b 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -68,7 +68,7 @@ ++ static void rpi_execute_inter_cmds(HEVCContext *s); ++ static void rpi_begin(HEVCContext *s); ++ static void flush_frame(HEVCContext *s,AVFrame *frame); ++- static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2); +++ static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2, int job); ++ ++ #endif ++ ++@@ -3443,9 +3443,9 @@ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ ++ #ifdef RPI_MULTI_MAILBOX ++ #ifdef RPI_CACHE_UNIF_MVS ++- flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],&s->y_unif_mvs_ptr[job], &s->unif_mvs_ptr[job]); +++ flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],&s->y_unif_mvs_ptr[job], &s->unif_mvs_ptr[job], job); ++ #else ++- flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],NULL,NULL); +++ flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],NULL,NULL, job); ++ #endif ++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], s->num_coeffs[job][3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++@@ -3519,6 +3519,7 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ { ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); ++ int n = s->ps.sps->height; ++ int curr_y = 0; ++ int curr_uv = 0; ++@@ -3526,22 +3527,21 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ int sz,base; ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); ++ iocache.s[0].handle = p->vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = p->arm + base; +++ iocache.s[0].addr = (int)(p->arm) + base; ++ iocache.s[0].size = sz; ++ p = av_buffer_pool_opaque(frame->buf[2]); ++ iocache.s[1].handle = p->vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = p->arm + base; +++ iocache.s[1].addr = (int)(p->arm) + base; ++ iocache.s[1].size = sz; ++ p = av_buffer_pool_opaque(frame->buf[0]); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++ iocache.s[2].handle = p->vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = p->arm + base; +++ iocache.s[2].addr = (int)(p->arm) + base; ++ iocache.s[2].size = sz; ++ vcsm_clean_invalid( &iocache ); ++ #else ++@@ -3551,33 +3551,46 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ #endif ++ } ++ ++-static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2) +++static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2, int job) ++ { ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++- int n = s->ps.sps->height; ++- int curr_y = 0; ++- int curr_uv = 0; ++- int n_uv = n >> s->ps.sps->vshift[1]; +++ int n; +++ int curr_y; +++ int curr_uv; +++ int n_uv; +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); ++ int sz,base; +++ int (*d)[2] = s->dblk_cmds[job]; +++ int low=(*d)[1]; +++ int high=(*d)[1]; +++ for(n = s->num_dblk_cmds[job]; n>0 ;n--,d++) { +++ int y = (*d)[1]; +++ low=FFMIN(low,y); +++ high=FFMAX(high,y); +++ } +++ curr_y = low; +++ n = high+(1 << s->ps.sps->log2_ctb_size); +++ curr_uv = curr_y >> s->ps.sps->vshift[1]; +++ n_uv = n >> s->ps.sps->vshift[1]; +++ ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); ++ iocache.s[0].handle = p->vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = p->arm + base; +++ iocache.s[0].addr = (int)(p->arm) + base; ++ iocache.s[0].size = sz; ++ p = av_buffer_pool_opaque(frame->buf[2]); ++ iocache.s[1].handle = p->vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = p->arm + base; +++ iocache.s[1].addr = (int)(p->arm) + base; ++ iocache.s[1].size = sz; ++ p = av_buffer_pool_opaque(frame->buf[0]); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++ iocache.s[2].handle = p->vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = p->arm + base; +++ iocache.s[2].addr = (int)(p->arm) + base; ++ iocache.s[2].size = sz; ++ ++ iocache.s[3].handle = p0->vcsm_handle; ++-- ++2.5.0 ++ ++ ++From e5e5d6e39c9361a4c842656103b7411b75098c0c Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Mon, 8 Jun 2015 11:55:29 +0100 ++Subject: [PATCH 63/68] Packed 16x16 and 32x32 into the same buffer ++ ++--- ++ libavcodec/hevc.c | 24 +++++++++++++++--------- ++ libavcodec/hevc_cabac.c | 9 ++++++++- ++ libavcodec/rpi_qpu.c | 2 +- ++ 3 files changed, 24 insertions(+), 11 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 2374c2b..3df6308 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -299,12 +299,12 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ s->coeffs_buf_arm[job][0] = (int16_t*) s->coeffs_buf_default[job].arm; ++ if (!s->coeffs_buf_arm[job][0]) ++ goto fail; ++- gpu_malloc_cached(sizeof(int16_t) * coefs_per_row * 2, &s->coeffs_buf_accelerated[job]); +++ gpu_malloc_cached(sizeof(int16_t) * (coefs_per_row + 32*32), &s->coeffs_buf_accelerated[job]); // We prefetch past the end so provide an extra blocks worth of data ++ s->coeffs_buf_arm[job][2] = (int16_t*) s->coeffs_buf_accelerated[job].arm; ++ s->coeffs_buf_vc[job][2] = s->coeffs_buf_accelerated[job].vc; ++ if (!s->coeffs_buf_arm[job][2]) ++ goto fail; ++- s->coeffs_buf_arm[job][3] = coefs_per_row + s->coeffs_buf_arm[job][2]; +++ s->coeffs_buf_arm[job][3] = coefs_per_row + s->coeffs_buf_arm[job][2]; // This points to just beyond the end of the buffer. Coefficients fill in backwards. ++ s->coeffs_buf_vc[job][3] = sizeof(int16_t) * coefs_per_row + s->coeffs_buf_vc[job][2]; ++ } ++ } ++@@ -2945,15 +2945,20 @@ static void rpi_execute_transform(HEVCContext *s) ++ { ++ int i=2; ++ int job = s->pass1_job; ++- //int j; ++- //int16_t *coeffs = s->coeffs_buf_arm[i]; ++- //for(j=s->num_coeffs[i]; j > 0; j-= 16*16, coeffs+=16*16) { ++- // s->hevcdsp.idct[4-2](coeffs, 16); ++- //} +++ /*int j; +++ int16_t *coeffs = s->coeffs_buf_arm[job][i]; +++ for(j=s->num_coeffs[job][i]; j > 0; j-= 16*16, coeffs+=16*16) { +++ s->hevcdsp.idct[4-2](coeffs, 16); +++ } +++ i=3; +++ coeffs = s->coeffs_buf_arm[job][i] - s->num_coeffs[job][i]; +++ for(j=s->num_coeffs[job][i]; j > 0; j-= 32*32, coeffs+=32*32) { +++ s->hevcdsp.idct[5-2](coeffs, 32); +++ }*/ ++ ++ gpu_cache_flush(&s->coeffs_buf_accelerated[job]); ++ s->vpu_id = vpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], ++- s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], +++ s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3] - sizeof(int16_t) * s->num_coeffs[job][3], ++ s->num_coeffs[job][3] >> 10, 0, &s->coeffs_buf_accelerated[job]); ++ //vpu_execute_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[2], s->num_coeffs[2] >> 8, s->coeffs_buf_vc[3], s->num_coeffs[3] >> 10, 0); ++ //gpu_cache_flush(&s->coeffs_buf_accelerated); ++@@ -3447,7 +3452,8 @@ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ #else ++ flush_frame3(s, s->frame,&s->coeffs_buf_accelerated[job],NULL,NULL, job); ++ #endif ++- s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, s->coeffs_buf_vc[job][3], s->num_coeffs[job][3] >> 10, 0, +++ s->vpu_id = vpu_qpu_post_code( vpu_get_fn(), vpu_get_constants(), s->coeffs_buf_vc[job][2], s->num_coeffs[job][2] >> 8, +++ s->coeffs_buf_vc[job][3] - sizeof(int16_t) * s->num_coeffs[job][3], s->num_coeffs[job][3] >> 10, 0, ++ qpu_get_fn(QPU_MC_SETUP_UV), ++ (uint32_t)(unif_vc+(s->mvs_base[job][0 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), ++ (uint32_t)(unif_vc+(s->mvs_base[job][1 ] - (uint32_t*)s->unif_mvs_ptr[job].arm)), ++diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c ++index 16e7ac3..271e17a 100644 ++--- a/libavcodec/hevc_cabac.c +++++ b/libavcodec/hevc_cabac.c ++@@ -1051,7 +1051,14 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, ++ if (s->enable_rpi) { ++ int n = trafo_size * trafo_size; ++ if (use_vpu) { ++- coeffs = s->coeffs_buf_arm[s->pass0_job][log2_trafo_size - 2] + s->num_coeffs[s->pass0_job][log2_trafo_size - 2]; +++ // We support size 4 and size 5. +++ // Size 4 grows from the front (Coeffs_buf_arm[2] points to start of buf) +++ // Size 5 grows from the back (Coeffs_buf_arm[3] points to end of buf) +++ // num_coeffs is indexed by log2_trafo_size-2 +++ if (log2_trafo_size == 4) +++ coeffs = s->coeffs_buf_arm[s->pass0_job][log2_trafo_size - 2] + s->num_coeffs[s->pass0_job][log2_trafo_size - 2]; +++ else +++ coeffs = s->coeffs_buf_arm[s->pass0_job][log2_trafo_size - 2] - s->num_coeffs[s->pass0_job][log2_trafo_size - 2] - n; ++ s->num_coeffs[s->pass0_job][log2_trafo_size - 2] += n; ++ } else { ++ coeffs = s->coeffs_buf_arm[s->pass0_job][0] + s->num_coeffs[s->pass0_job][0]; ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 4480f72..0121fca 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -5,7 +5,7 @@ ++ // define RPI_TIME_TOTAL_VPU to print out how much time is spent in the VPI code ++ //#define RPI_TIME_TOTAL_VPU ++ // define RPI_TIME_TOTAL_POSTED to print out how much time is spent in the multi execute QPU/VPU combined ++-//#define RPI_TIME_TOTAL_POSTED +++#define RPI_TIME_TOTAL_POSTED ++ // define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion ++ #define RPI_ASYNC ++ ++-- ++2.5.0 ++ ++ ++From a1c0980a8ce8b0059637e9fdc61b1cbd64c58e43 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Thu, 25 Jun 2015 09:02:47 +0100 ++Subject: [PATCH 64/68] Moved luma deblock to VPU ++ ++--- ++ libavcodec/hevc.c | 18 +- ++ libavcodec/hevc.h | 11 + ++ libavcodec/hevc_filter.c | 120 ++- ++ libavcodec/rpi_hevc_transform.h | 1802 ++++++++++++++++++++++++++++++++++++++- ++ libavcodec/rpi_hevc_transform.s | 426 +++++++++ ++ libavcodec/rpi_qpu.c | 12 +- ++ libavcodec/rpi_shader.c | 2 +- ++ 7 files changed, 2378 insertions(+), 13 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 3df6308..0ecaf05 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -246,6 +246,12 @@ static void pic_arrays_free(HEVCContext *s) ++ } ++ } ++ #endif +++#ifdef RPI_DEBLOCK_VPU +++ if (s->y_setup_arm) { +++ gpu_free(&s->y_setup_ptr); +++ s->y_setup_arm = 0; +++ } +++#endif ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++ ++@@ -283,12 +289,12 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ int min_pu_size = sps->min_pu_width * sps->min_pu_height; ++ ++ #ifdef RPI ++- av_assert0(sps); ++ int coefs_in_ctb = (1 << sps->log2_ctb_size) * (1 << sps->log2_ctb_size); ++ int coefs_per_luma = 64*64*24*RPI_NUM_CHUNKS; ++ int coefs_per_chroma = (coefs_per_luma * 2) >> sps->vshift[1] >> sps->hshift[1]; ++ int coefs_per_row = coefs_per_luma + coefs_per_chroma; ++ int job; +++ av_assert0(sps); ++ s->max_ctu_count = coefs_per_luma / coefs_in_ctb; ++ s->ctu_per_y_chan = s->max_ctu_count / 12; ++ s->ctu_per_uv_chan = s->max_ctu_count / 8; ++@@ -309,6 +315,16 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ } ++ } ++ #endif +++#ifdef RPI_DEBLOCK_VPU +++ s->enable_rpi_deblock = !sps->sao_enabled; +++ s->setup_width = (sps->width+15) / 16; +++ s->setup_height = (sps->height+15) / 16; +++ gpu_malloc_uncached(sizeof(*s->y_setup_arm) * s->setup_width * s->setup_height, &s->y_setup_ptr); // TODO make this cached +++ s->y_setup_arm = (void*)s->y_setup_ptr.arm; +++ s->y_setup_vc = (void*)s->y_setup_ptr.vc; +++ memset(s->y_setup_arm, 0, s->y_setup_ptr.numbytes); +++ printf("Setup %d by %d by %d\n",s->setup_width,s->setup_height,sizeof(*s->y_setup_arm)); +++#endif ++ ++ s->bs_width = (width >> 2) + 1; ++ s->bs_height = (height >> 2) + 1; ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index a577fcb..b1d3ee0 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -56,6 +56,8 @@ ++ // Define RPI_WORKER to launch a worker thread for pixel processing tasks ++ #define RPI_WORKER ++ +++ #define RPI_DEBLOCK_VPU +++ ++ #endif ++ ++ #define MAX_DPB_SIZE 16 // A.4.1 ++@@ -997,6 +999,15 @@ typedef struct HEVCContext { ++ int kill_worker; // set to 1 to terminate the worker ++ #endif ++ +++#ifdef RPI_DEBLOCK_VPU +++ int enable_rpi_deblock; +++ GPU_MEM_PTR_T y_setup_ptr; +++ uint8_t (*y_setup_arm)[2][2][2][4]; +++ uint8_t (*y_setup_vc)[2][2][2][4]; +++ int setup_width; // Number of 16x16 blocks across the image +++ int setup_height; // Number of 16x16 blocks down the image +++#endif +++ ++ #endif ++ ++ uint8_t *cabac_state; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 1f04790..06371da 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -564,6 +564,19 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->frame->linesize[LUMA], ++ beta, tc, no_p, no_q); ++ } else +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock) { +++ uint8_t (*setup)[2][2][4]; +++ int num16 = (y>>4)*s->setup_width + (x>>4); +++ int a = ((y>>3) & 1) << 1; +++ int b = (x>>3) & 1; +++ setup = s->y_setup_arm[num16]; +++ setup[0][b][0][a] = beta; +++ setup[0][b][0][a + 1] = beta; +++ setup[0][b][1][a] = tc[0]; +++ setup[0][b][1][a + 1] = tc[1]; +++ } else +++#endif ++ s->hevcdsp.hevc_v_loop_filter_luma(src, ++ s->frame->linesize[LUMA], ++ beta, tc, no_p, no_q); ++@@ -596,6 +609,19 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->frame->linesize[LUMA], ++ beta, tc, no_p, no_q); ++ } else +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock) { +++ uint8_t (*setup)[2][2][4]; +++ int num16 = (y>>4)*s->setup_width + (x>>4); +++ int a = ((x>>3) & 1) << 1; +++ int b = (y>>3) & 1; +++ setup = s->y_setup_arm[num16]; +++ setup[1][b][0][a] = beta; +++ setup[1][b][0][a + 1] = beta; +++ setup[1][b][1][a] = tc[0]; +++ setup[1][b][1][a + 1] = tc[1]; +++ } else +++#endif ++ s->hevcdsp.hevc_h_loop_filter_luma(src, ++ s->frame->linesize[LUMA], ++ beta, tc, no_p, no_q); ++@@ -876,33 +902,85 @@ static void flush_buffer(AVBufferRef *bref) { ++ } ++ ++ // Return Physical address for this image ++-static int ff_hevc_buf_base(AVBufferRef *bref) { +++static uint32_t get_vc_address(AVBufferRef *bref) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++- return p->vc & 0x3fffffff; +++ return p->vc; ++ } ++ +++// ff_hevc_flush_buffer_lines +++// flushes and invalidates all pixel rows in [start,end-1] +++static void ff_hevc_flush_buffer_lines(HEVCContext *s, int start, int end, int flush_luma, int flush_chroma) +++{ +++#ifdef RPI_FAST_CACHEFLUSH +++ struct vcsm_user_clean_invalid_s iocache = {}; +++ int curr_y = start; +++ int n = end; +++ int curr_uv = curr_y >> s->ps.sps->vshift[1]; +++ int n_uv = n >> s->ps.sps->vshift[1]; +++ int sz,base; +++ GPU_MEM_PTR_T *p; +++ if (curr_uv < 0) curr_uv = 0; +++ if (n_uv<=curr_uv) { return; } +++ sz = s->frame->linesize[1] * (n_uv-curr_uv); +++ base = s->frame->linesize[1] * curr_uv; +++ if (flush_chroma) { +++ p = av_buffer_pool_opaque(s->frame->buf[1]); +++ iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].cmd = 3; // clean+invalidate +++ iocache.s[0].addr = (int)p->arm + base; +++ iocache.s[0].size = sz; +++ p = av_buffer_pool_opaque(s->frame->buf[2]); +++ iocache.s[1].handle = p->vcsm_handle; +++ iocache.s[1].cmd = 3; // clean+invalidate +++ iocache.s[1].addr = (int)p->arm + base; +++ iocache.s[1].size = sz; +++ } +++ if (flush_luma) { +++ p = av_buffer_pool_opaque(s->frame->buf[0]); +++ sz = s->frame->linesize[0] * (n-curr_y); +++ base = s->frame->linesize[0] * curr_y; +++ iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].cmd = 3; // clean+invalidate +++ iocache.s[2].addr = (int)p->arm + base; +++ iocache.s[2].size = sz; +++ } +++ vcsm_clean_invalid( &iocache ); +++#else +++ if (flush_chroma) { +++ flush_buffer(s->frame->buf[1]); +++ flush_buffer(s->frame->buf[2]); +++ } +++ if (flush_luma) { +++ flush_buffer(s->frame->buf[0]); +++ } +++#endif +++} +++ +++ ++ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ { ++ if (s->enable_rpi && s->used_for_ref) { +++ // TODO make this use ff_hevc_flush_buffer_lines ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++ int curr_y = ((int *)f->progress->data)[0]; ++ int curr_uv = curr_y >> s->ps.sps->vshift[1]; ++ int n_uv = n >> s->ps.sps->vshift[1]; ++ int sz,base; +++ GPU_MEM_PTR_T *p; ++ if (curr_uv < 0) curr_uv = 0; ++ if (n_uv<=curr_uv) { return; } ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(s->frame->buf[1]); +++ p = av_buffer_pool_opaque(s->frame->buf[1]); ++ iocache.s[0].handle = p->vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = p->arm + base; +++ iocache.s[0].addr = (int)p->arm + base; ++ iocache.s[0].size = sz; ++ p = av_buffer_pool_opaque(s->frame->buf[2]); ++ iocache.s[1].handle = p->vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = p->arm + base; +++ iocache.s[1].addr = (int)p->arm + base; ++ iocache.s[1].size = sz; ++ ++ #ifdef RPI_LUMA_QPU ++@@ -911,7 +989,7 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ base = s->frame->linesize[0] * curr_y; ++ iocache.s[2].handle = p->vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = p->arm + base; +++ iocache.s[2].addr = (int)p->arm + base; ++ iocache.s[2].size = sz; ++ #endif ++ vcsm_clean_invalid( &iocache ); ++@@ -930,11 +1008,40 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ } ++ #endif ++ +++#ifdef RPI_DEBLOCK_VPU +++/* rpi_deblock deblocks an entire row of ctbs using the VPU */ +++static void rpi_deblock(HEVCContext *s, int y, int ctb_size) +++{ +++ // Flush image, 4 lines above to bottom of ctb stripe +++ ff_hevc_flush_buffer_lines(s, FFMAX(y-4,0), y+ctb_size, 1, 0); +++ // TODO flush buffer of beta/tc setup when it becomes cached +++ // Call VPU +++ // TODO add this to a separate pipeline of VPU jobs that can be run in parallel and wait for completion +++ vpu_wait(vpu_post_code( vpu_get_fn(), get_vc_address(s->frame->buf[0]) + s->frame->linesize[0] * y, s->frame->linesize[0], +++ s->setup_width, (int) ( s->y_setup_vc + s->setup_width * (y>>4) ), +++ ctb_size>>4, 2, 0)); // 2 means to do the deblocking code +++} +++ +++static void rpi_deblock2(HEVCContext *s, int y, int ctb_size) +++{ +++ int y2; +++ for(y2=y;y2= s->ps.sps->width - ctb_size; ++ if (s->avctx->skip_loop_filter < AVDISCARD_ALL) ++ deblocking_filter_CTB(s, x, y); +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock && x_end) +++ { +++ rpi_deblock(s, y, ctb_size); +++ } +++#endif ++ if (s->ps.sps->sao_enabled) { ++ int y_end = y >= s->ps.sps->height - ctb_size; ++ if (y && x) ++@@ -965,6 +1072,7 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ //if (((y + ctb_size)&63)==0) ++ #ifdef RPI_INTER_QPU ++ ff_hevc_flush_buffer(s, &s->ref->tf, y + ctb_size - 4); +++ // TODO we no longer need to flush the luma buffer as it is in GPU memory when using deblocking on the rpi ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); ++ } ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++index 4f13622..b3f155f 100644 ++--- a/libavcodec/rpi_hevc_transform.h +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -3,7 +3,13 @@ unsigned char rpi_hevc_transform [] = { ++ 106, ++ 0, ++ 144, ++-35, +++38, +++1, +++37, +++106, +++0, +++144, +++57, ++ 1, ++ 169, ++ 3, ++@@ -627,4 +633,1798 @@ unsigned char rpi_hevc_transform [] = { ++ 30, ++ 90, ++ 0, +++169, +++3, +++73, +++64, +++52, +++64, +++45, +++64, +++2, +++64, +++10, +++64, +++64, +++198, +++1, +++7, +++8, +++232, +++63, +++0, +++0, +++0, +++6, +++232, +++253, +++255, +++255, +++255, +++0, +++246, +++0, +++0, +++0, +++4, +++215, +++64, +++3, +++96, +++2, +++248, +++0, +++35, +++0, +++0, +++64, +++56, +++0, +++0, +++4, +++248, +++0, +++36, +++0, +++0, +++64, +++56, +++8, +++0, +++0, +++240, +++64, +++0, +++132, +++3, +++128, +++240, +++0, +++0, +++132, +++3, +++128, +++144, +++137, +++0, +++131, +++98, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++129, +++0, +++131, +++102, +++0, +++158, +++67, +++0, +++2, +++248, +++0, +++35, +++0, +++0, +++64, +++56, +++0, +++0, +++4, +++248, +++0, +++36, +++0, +++0, +++64, +++56, +++8, +++0, +++0, +++240, +++64, +++0, +++132, +++3, +++128, +++240, +++0, +++0, +++132, +++3, +++128, +++144, +++108, +++0, +++131, +++98, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++100, +++0, +++131, +++102, +++0, +++248, +++64, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++248, +++0, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++144, +++161, +++0, +++188, +++64, +++67, +++232, +++0, +++2, +++0, +++0, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++150, +++0, +++195, +++232, +++0, +++2, +++0, +++0, +++12, +++128, +++7, +++192, +++130, +++248, +++0, +++0, +++112, +++192, +++224, +++16, +++195, +++31, +++132, +++248, +++1, +++0, +++112, +++0, +++224, +++16, +++203, +++31, +++3, +++99, +++131, +++71, +++68, +++232, +++32, +++0, +++0, +++0, +++0, +++99, +++2, +++99, +++23, +++102, +++7, +++106, +++127, +++156, +++182, +++255, +++0, +++248, +++64, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++248, +++0, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++144, +++112, +++0, +++188, +++64, +++67, +++232, +++0, +++2, +++0, +++0, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++101, +++0, +++195, +++232, +++0, +++2, +++0, +++0, +++12, +++128, +++7, +++192, +++130, +++248, +++0, +++0, +++112, +++192, +++224, +++16, +++195, +++31, +++132, +++248, +++1, +++0, +++112, +++0, +++224, +++16, +++203, +++31, +++25, +++102, +++9, +++106, +++2, +++30, +++41, +++3, +++26, +++87, +++162, +++64, +++64, +++198, +++1, +++23, +++127, +++158, +++103, +++255, +++239, +++3, +++0, +++254, +++0, +++143, +++92, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++64, +++143, +++93, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++143, +++94, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++143, +++95, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++142, +++208, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++142, +++209, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++64, +++142, +++210, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++0, +++142, +++211, +++0, +++0, +++240, +++12, +++0, +++128, +++144, +++107, +++0, +++8, +++255, +++99, +++23, +++0, +++212, +++192, +++51, +++0, +++0, +++8, +++255, +++163, +++23, +++0, +++228, +++192, +++51, +++0, +++0, +++8, +++255, +++227, +++23, +++0, +++244, +++192, +++51, +++0, +++0, +++8, +++255, +++35, +++52, +++0, +++180, +++192, +++51, +++0, +++0, +++8, +++255, +++99, +++52, +++0, +++164, +++192, +++51, +++0, +++0, +++8, +++255, +++163, +++52, +++0, +++148, +++192, +++51, +++0, +++0, +++111, +++3, +++239, +++3, +++0, +++254, +++0, +++143, +++12, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++64, +++143, +++13, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++143, +++14, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++143, +++15, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++142, +++16, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++142, +++17, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++64, +++142, +++18, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++0, +++142, +++19, +++0, +++0, +++240, +++12, +++0, +++128, +++144, +++33, +++0, +++8, +++255, +++99, +++3, +++0, +++212, +++192, +++51, +++0, +++0, +++8, +++255, +++163, +++3, +++0, +++228, +++192, +++51, +++0, +++0, +++8, +++255, +++227, +++3, +++0, +++244, +++192, +++51, +++0, +++0, +++8, +++255, +++35, +++4, +++0, +++180, +++192, +++51, +++0, +++0, +++8, +++255, +++99, +++4, +++0, +++164, +++192, +++51, +++0, +++0, +++8, +++255, +++163, +++4, +++0, +++148, +++192, +++51, +++0, +++0, +++111, +++3, +++32, +++246, +++192, +++11, +++1, +++16, +++32, +++246, +++2, +++137, +++47, +++240, +++40, +++246, +++2, +++140, +++47, +++240, +++128, +++245, +++99, +++140, +++5, +++4, +++0, +++247, +++99, +++140, +++1, +++20, +++88, +++246, +++99, +++140, +++1, +++20, +++0, +++247, +++35, +++136, +++62, +++226, +++32, +++247, +++35, +++136, +++32, +++210, +++0, +++247, +++34, +++136, +++63, +++2, +++208, +++246, +++34, +++136, +++0, +++4, +++0, +++247, +++99, +++136, +++58, +++162, +++32, +++247, +++99, +++136, +++33, +++146, +++0, +++247, +++98, +++136, +++59, +++18, +++208, +++246, +++98, +++136, +++0, +++20, +++0, +++247, +++162, +++136, +++33, +++2, +++88, +++246, +++98, +++137, +++2, +++68, +++88, +++246, +++162, +++137, +++3, +++68, +++208, +++254, +++227, +++136, +++60, +++242, +++192, +++243, +++188, +++11, +++208, +++254, +++227, +++136, +++56, +++178, +++192, +++243, +++188, +++10, +++32, +++255, +++226, +++136, +++38, +++58, +++192, +++243, +++60, +++0, +++208, +++254, +++227, +++136, +++59, +++242, +++192, +++243, +++60, +++128, +++32, +++255, +++226, +++136, +++49, +++58, +++192, +++243, +++60, +++128, +++0, +++255, +++226, +++136, +++34, +++34, +++192, +++243, +++60, +++128, +++32, +++255, +++226, +++136, +++37, +++58, +++192, +++243, +++60, +++128, +++0, +++254, +++192, +++136, +++1, +++4, +++0, +++240, +++0, +++160, +++0, +++255, +++194, +++8, +++0, +++52, +++195, +++243, +++0, +++128, +++0, +++255, +++202, +++40, +++0, +++52, +++195, +++243, +++0, +++128, +++0, +++254, +++0, +++240, +++35, +++10, +++0, +++240, +++60, +++0, +++0, +++254, +++192, +++136, +++1, +++4, +++0, +++240, +++0, +++160, +++0, +++255, +++226, +++140, +++34, +++34, +++195, +++243, +++60, +++0, +++32, +++255, +++227, +++140, +++36, +++58, +++192, +++243, +++60, +++0, +++0, +++254, +++192, +++136, +++0, +++4, +++0, +++240, +++0, +++160, +++16, +++246, +++226, +++136, +++35, +++50, +++16, +++246, +++226, +++136, +++35, +++50, +++32, +++246, +++226, +++136, +++35, +++50, +++32, +++254, +++226, +++136, +++35, +++58, +++192, +++243, +++60, +++0, +++11, +++96, +++0, +++254, +++0, +++240, +++1, +++4, +++0, +++240, +++64, +++115, +++5, +++106, +++0, +++144, +++173, +++1, +++27, +++96, +++0, +++254, +++0, +++240, +++1, +++4, +++0, +++240, +++64, +++147, +++5, +++106, +++0, +++144, +++227, +++0, +++64, +++246, +++163, +++140, +++1, +++4, +++0, +++246, +++192, +++175, +++63, +++2, +++0, +++246, +++192, +++174, +++59, +++2, +++0, +++246, +++128, +++175, +++62, +++2, +++0, +++246, +++128, +++174, +++58, +++2, +++0, +++246, +++64, +++175, +++61, +++2, +++0, +++246, +++64, +++174, +++57, +++2, +++0, +++255, +++43, +++240, +++4, +++212, +++192, +++243, +++128, +++11, +++64, +++254, +++43, +++240, +++1, +++228, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++240, +++1, +++244, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++240, +++1, +++180, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++141, +++0, +++164, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++3, +++68, +++32, +++247, +++35, +++141, +++191, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++235, +++143, +++52, +++242, +++192, +++243, +++60, +++128, +++0, +++255, +++43, +++240, +++2, +++212, +++192, +++243, +++128, +++11, +++0, +++255, +++43, +++240, +++191, +++226, +++192, +++243, +++188, +++10, +++64, +++254, +++43, +++141, +++0, +++180, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++2, +++68, +++32, +++247, +++35, +++141, +++190, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++171, +++143, +++52, +++226, +++192, +++243, +++60, +++128, +++0, +++255, +++43, +++240, +++4, +++180, +++192, +++243, +++128, +++11, +++0, +++255, +++43, +++240, +++191, +++226, +++192, +++243, +++188, +++10, +++128, +++253, +++43, +++240, +++3, +++212, +++192, +++243, +++128, +++10, +++64, +++254, +++35, +++141, +++1, +++196, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++3, +++68, +++32, +++247, +++35, +++141, +++189, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++107, +++143, +++52, +++210, +++192, +++243, +++60, +++128, +++0, +++255, +++43, +++240, +++4, +++148, +++192, +++243, +++128, +++11, +++64, +++254, +++43, +++240, +++1, +++164, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++240, +++1, +++180, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++240, +++1, +++244, +++192, +++243, +++128, +++10, +++64, +++254, +++43, +++141, +++0, +++228, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++3, +++68, +++32, +++247, +++35, +++141, +++187, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++235, +++142, +++52, +++178, +++192, +++243, +++60, +++128, +++0, +++255, +++43, +++240, +++2, +++148, +++192, +++243, +++128, +++11, +++0, +++255, +++43, +++240, +++187, +++162, +++192, +++243, +++188, +++10, +++64, +++254, +++43, +++141, +++0, +++244, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++2, +++68, +++32, +++247, +++35, +++141, +++186, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++171, +++142, +++52, +++162, +++192, +++243, +++60, +++128, +++0, +++255, +++43, +++240, +++4, +++244, +++192, +++243, +++128, +++11, +++0, +++255, +++43, +++240, +++187, +++162, +++192, +++243, +++188, +++10, +++128, +++253, +++43, +++240, +++3, +++148, +++192, +++243, +++128, +++10, +++64, +++254, +++35, +++141, +++1, +++132, +++192, +++243, +++128, +++10, +++88, +++246, +++35, +++141, +++3, +++68, +++32, +++247, +++35, +++141, +++185, +++66, +++240, +++246, +++35, +++141, +++50, +++66, +++0, +++255, +++107, +++142, +++52, +++146, +++192, +++243, +++60, +++128, +++64, +++255, +++98, +++141, +++0, +++52, +++192, +++243, +++0, +++0, +++0, +++254, +++0, +++240, +++53, +++10, +++0, +++240, +++60, +++0, +++0, +++254, +++0, +++240, +++1, +++4, +++0, +++240, +++64, +++147, +++5, +++106, +++0, +++144, +++177, +++0, +++88, +++246, +++163, +++140, +++1, +++4, +++128, +++245, +++99, +++141, +++10, +++4, +++88, +++246, +++162, +++138, +++1, +++68, +++0, +++247, +++162, +++138, +++36, +++162, +++88, +++254, +++162, +++138, +++3, +++164, +++192, +++243, +++128, +++11, +++0, +++255, +++226, +++137, +++32, +++2, +++195, +++243, +++60, +++0, +++32, +++247, +++226, +++137, +++42, +++114, +++0, +++255, +++34, +++138, +++33, +++18, +++195, +++243, +++60, +++0, +++32, +++247, +++34, +++138, +++42, +++130, +++16, +++246, +++98, +++138, +++40, +++114, +++16, +++246, +++98, +++138, +++41, +++146, +++32, +++246, +++98, +++138, +++41, +++146, +++32, +++246, +++226, +++137, +++41, +++146, +++40, +++246, +++34, +++138, +++41, +++146, +++32, +++247, +++163, +++141, +++63, +++178, +++32, +++247, +++227, +++141, +++62, +++162, +++0, +++254, +++0, +++240, +++8, +++4, +++0, +++240, +++128, +++11, +++128, +++253, +++35, +++240, +++9, +++100, +++192, +++243, +++128, +++10, +++128, +++253, +++163, +++141, +++128, +++115, +++192, +++243, +++152, +++10, +++88, +++246, +++163, +++141, +++4, +++100, +++208, +++246, +++35, +++139, +++0, +++100, +++32, +++255, +++34, +++139, +++53, +++202, +++192, +++243, +++60, +++128, +++0, +++254, +++0, +++139, +++0, +++4, +++0, +++240, +++0, +++160, +++240, +++246, +++163, +++141, +++48, +++98, +++0, +++247, +++99, +++139, +++63, +++210, +++0, +++247, +++98, +++139, +++1, +++212, +++88, +++254, +++98, +++139, +++1, +++212, +++192, +++243, +++128, +++11, +++32, +++255, +++99, +++139, +++62, +++98, +++192, +++243, +++188, +++10, +++88, +++246, +++98, +++139, +++1, +++212, +++240, +++246, +++98, +++139, +++50, +++210, +++0, +++247, +++163, +++128, +++59, +++146, +++0, +++247, +++160, +++128, +++1, +++36, +++88, +++254, +++160, +++128, +++1, +++36, +++192, +++243, +++128, +++11, +++0, +++247, +++163, +++128, +++58, +++98, +++64, +++255, +++35, +++240, +++0, +++100, +++192, +++243, +++128, +++10, +++64, +++255, +++163, +++128, +++0, +++164, +++192, +++243, +++128, +++10, +++88, +++246, +++160, +++128, +++1, +++36, +++240, +++246, +++160, +++128, +++50, +++34, +++8, +++255, +++227, +++143, +++54, +++242, +++192, +++243, +++60, +++128, +++40, +++255, +++227, +++142, +++54, +++178, +++192, +++243, +++60, +++128, +++0, +++254, +++0, +++240, +++39, +++10, +++0, +++240, +++60, +++128, +++8, +++255, +++163, +++143, +++45, +++226, +++192, +++243, +++60, +++128, +++0, +++254, +++0, +++240, +++44, +++10, +++0, +++240, +++60, +++0, +++0, +++254, +++0, +++240, +++40, +++10, +++0, +++240, +++60, +++128, +++8, +++255, +++163, +++142, +++2, +++162, +++192, +++243, +++60, +++128, +++90, +++0, ++ }; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++index fd159bc..b055208 100644 ++--- a/libavcodec/rpi_hevc_transform.s +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -83,6 +83,8 @@ ++ hevc_trans_16x16: ++ cmp r5,1 ++ beq memclear16 +++ cmp r5,2 +++ beq hevc_deblock_16x16 ++ push r6-r15, lr # TODO cut down number of used registers ++ mov r14,r3 # coeffs32 ++ mov r15,r4 # num32 ++@@ -282,3 +284,427 @@ loop: ++ cmp r1,0 ++ bgt loop ++ b lr +++ +++ +++################################################################################ +++# HEVC VPU Deblock +++# +++# Vertical edges before horizontal +++# Decision can change every 4 pixels, but only 8 pixel boundaries are deblocked +++# +++# ARM is responsible for storing beta and tc for each 4 pixels horiz and vert edge. +++# The VPU code works in units of 16x16 blocks. +++# We do vertical filtering for the current block followed by horizontal filtering for the previous (except for the first time). +++# One final horizontal filter is required at the end. +++# PCM is not allowed in this code. +++# +++# +++# H(16-4:16+15,0) contains previous block (note that we need 4 lines above of context that may get altered during filtering) +++# H(16:31,16) contains current block (note that we do not need the upper lines until the horizontal filtering. +++ +++.set P0,63 +++.set P1,62 +++.set P2,61 +++.set P3,60 +++.set Q0,59 +++.set Q1,58 +++.set Q2,57 +++.set Q3,56 +++ +++.set dp,32 +++.set dq,33 +++.set d,34 +++.set decision,35 +++.set beta,36 +++.set beta2,37 +++.set beta3,38 +++.set ptest,39 +++.set qtest,40 +++.set pqtest,41 +++.set thresh,42 +++.set deltatest, 44 +++.set deltap1, 45 +++.set tc25, 46 +++.set setup,47 +++.set tc,48 +++.set tc25,49 +++.set tc2, 50 +++.set do_filter, 51 +++.set delta, 52 +++.set tc10, 53 +++.set delta0, 54 +++.set delta1, 55 +++.set zeros, 0 +++.set setup_input, 1 +++.set deltaq1, 2 +++ +++ +++ +++# hevc_deblock_16x16 deblocks an entire row that is 16 pixels high by the full width of the image. +++# Row has num16 16x16 blocks across +++# Beta goes from 0 to 64 +++# tc goes from 0 to 24 +++# setup[block_idx][0=vert,1=horz][0=first edge, 1=second edge][0=beta,1=tc][0..3=edge number] +++# has 8 bytes per edge +++# has 16 bytes per direction +++# has 32 bytes per 16x16 block +++# hevc_deblock_16x16(uint8_t *img (r0), int stride (r1), int num16w (r2), uint8_t setup[num16][2][2][2][4](r3),int num16h(r4)) +++hevc_deblock_16x16: +++ push r6-r15, lr +++ mov r9,r4 +++ mov r4,r3 +++ mov r13,r2 +++ mov r2,r0 +++ mov r10,r0 +++ subscale4 r0,r1 +++ mov r8,63 +++ mov r6,-3 +++ vmov H(zeros,0),0 +++# r7 is number of blocks still to load +++# r0 is location of current block - 4 * stride +++# r1 is stride +++# r2 is location of current block +++# r3 is offset of start of block (actual edges start at H(16,16)+r3 for horizontal and H(16,0)+r3 for vertical +++# r4 is setup +++# r5 is for temporary calculations +++# r8 holds 63 +++# r6 holds -3 +++# r9 holds the number of 16 high rows to process +++# r10 holds the original img base +++# r11 returns 0 if no filtering was done on the edge +++# r12 saves a copy of this +++# r13 is copy of width +++ +++process_row: +++ # First iteration does not do horizontal filtering on previous +++ mov r7, r13 +++ mov r3,0 +++ vldb H(12++,16)+r3,(r0 += r1) REP 4 # Load the current block +++ vldb H(16++,16)+r3,(r2 += r1) REP 16 +++ vldb H(setup_input,0), (r4) # We may wish to prefetch these +++ vstb H(zeros,0),(r4) +++ bl vert_filter +++ add r3,8 +++ vadd H(setup_input,0),H(setup_input,8),0 # Rotate to second set of 8 +++ bl vert_filter +++ sub r3,8 +++ b start_deblock_loop +++deblock_loop: +++ # Middle iterations do vertical on current block and horizontal on preceding +++ vldb H(12++,16)+r3,(r0 += r1) REP 4 # load the current block +++ vldb H(16++,16)+r3,(r2 += r1) REP 16 +++ vldb H(setup_input,0), (r4) +++ vstb H(zeros,0),(r4) +++ bl vert_filter +++ add r3,8 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl vert_filter +++ sub r3,8 +++ vldb H(setup_input,0), -16(r4) +++ vstb H(zeros,0),-16(r4) +++ bl horz_filter +++ mov r12,r11 +++ add r3,8*64 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl horz_filter +++ sub r3,8*64 +++ addcmpbeq r12,0,0,skip_save_top +++ vstb H(12++,0)+r3,-16(r0 += r1) REP 4 # Save the deblocked pixels for the previous block +++skip_save_top: +++ vstb H(16++,0)+r3,-16(r2 += r1) REP 16 +++start_deblock_loop: +++ # move onto next 16x16 (could do this with circular buffer support instead) +++ add r3,16 +++ and r3,r8 +++ add r4,32 +++ # Perform loop counter operations (may work with an addcmpbgt as well?) +++ add r0,16 +++ add r2,16 +++ sub r7,1 +++ cmp r7,0 # Are there still more blocks to load +++ bgt deblock_loop +++ +++ # Final iteration needs to just do horizontal filtering +++ vldb H(setup_input,0), -16(r4) +++ vstb H(zeros,0),-16(r4) +++ bl horz_filter +++ mov r12,r11 +++ add r3,8*64 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl horz_filter +++ sub r3,64*8 +++ addcmpbeq r12,0,0,skip_save_top2 +++ vstb H(12++,0)+r3,-16(r0 += r1) REP 4 # Save the deblocked pixels for the previous block +++skip_save_top2: +++ vstb H(16++,0)+r3,-16(r2 += r1) REP 16 +++ +++# Now look to see if we should do another row +++ sub r9,1 +++ cmp r9,0 +++ bgt start_again +++ pop r6-r15, pc +++start_again: +++ # Need to sort out r0,r2 to point to next row down +++ addscale16 r10,r1 +++ mov r2,r10 +++ subscale4 r0,r2,r1 +++ b process_row +++ +++ +++# At this stage H(16,16)+r3 points to the first pixel of the 16 high edge to be filtered +++# So we can reuse the code we move the parts to be filtered into HX(P0/P1/P2/P3/Q0/Q1/Q2/Q3,0) - we will perform a final saturation step on placing them back into the correct locations +++ +++vert_filter: +++ push lr +++ +++ vmov HX(P3,0), V(16,12)+r3 +++ vmov HX(P2,0), V(16,13)+r3 +++ vmov HX(P1,0), V(16,14)+r3 +++ vmov HX(P0,0), V(16,15)+r3 +++ vmov HX(Q0,0), V(16,16)+r3 +++ vmov HX(Q1,0), V(16,17)+r3 +++ vmov HX(Q2,0), V(16,18)+r3 +++ vmov HX(Q3,0), V(16,19)+r3 +++ +++ bl do_luma_filter +++ +++ vadds V(16,13)+r3, HX(P2,0), 0 +++ vadds V(16,14)+r3, HX(P1,0), 0 +++ vadds V(16,15)+r3, HX(P0,0), 0 +++ # P3 and Q3 never change so don't bother saving back +++ vadds V(16,16)+r3, HX(Q0,0), 0 +++ vadds V(16,17)+r3, HX(Q1,0), 0 +++ vadds V(16,18)+r3, HX(Q2,0), 0 +++ +++ pop pc +++ +++# Filter edge at H(16,0)+r3 +++horz_filter: +++ push lr +++ +++ vmov HX(P3,0), H(12,0)+r3 +++ vmov HX(P2,0), H(13,0)+r3 +++ vmov HX(P1,0), H(14,0)+r3 +++ vmov HX(P0,0), H(15,0)+r3 +++ vmov HX(Q0,0), H(16,0)+r3 +++ vmov HX(Q1,0), H(17,0)+r3 +++ vmov HX(Q2,0), H(18,0)+r3 +++ vmov HX(Q3,0), H(19,0)+r3 +++ +++ bl do_luma_filter +++ +++ vadds H(13,0)+r3, HX(P2,0), 0 +++ vadds H(14,0)+r3, HX(P1,0), 0 +++ vadds H(15,0)+r3, HX(P0,0), 0 +++ # P3 and Q3 never change so don't bother saving back +++ vadds H(16,0)+r3, HX(Q0,0), 0 +++ vadds H(17,0)+r3, HX(Q1,0), 0 +++ vadds H(18,0)+r3, HX(Q2,0), 0 +++ +++ pop pc +++ +++# r4 points to array of beta/tc for each 4 length edge +++do_luma_filter: +++ valtl H(setup,0),H(setup_input,0),H(setup_input,0) # b*8tc*8 +++ valtl HX(beta,0),H(setup,0),H(setup,0) +++ valtu HX(tc,0),H(setup,0),H(setup,0) +++ vmul HX(tc25,0), HX(tc,0), 5 +++ vadd HX(tc25,0),HX(tc25,0), 1 +++ vasr HX(tc25,0), HX(tc25,0), 1 +++ +++ # Compute decision +++ vadd HX(dp,0),HX(P1,0),HX(P1,0) # 2*P1 +++ vsub HX(dp,0),HX(P2,0),HX(dp,0) # P2-2*P1 +++ vadd HX(dp,0),HX(dp,0),HX(P0,0) # P2-2*P1+P0 +++ vdist HX(dp,0),HX(dp,0),0 # abs(P2-2*P1+P0) # dp0 +++ +++ vadd HX(dq,0),HX(Q1,0),HX(Q1,0) # 2*Q1 +++ vsub HX(dq,0),HX(Q2,0),HX(dq,0) # Q2-2*Q1 +++ vadd HX(dq,0),HX(dq,0),HX(Q0,0) # Q2-2*Q1+Q0 +++ vdist HX(dq,0),HX(dq,0),0 # abs(Q2-2*Q1+Q0) # dq0 +++ +++ vadd HX(d,0), HX(dp,0), HX(dq,0) +++ vasr HX(beta2,0),HX(beta,0),2 +++ vasr HX(beta3,0),HX(beta,0),3 +++ +++ # Compute flags that are negative if all conditions pass +++ vdist HX(decision,0), HX(P0,0), HX(P3,0) CLRA SACC +++ vdist HX(decision,0), HX(Q0,0), HX(Q3,0) SACC +++ vsub HX(decision,0), HX(decision,0), HX(beta3,0) SETF +++ +++ vdist HX(decision,0), HX(P0,0), HX(Q0,0) IFN +++ vsub HX(decision,0), HX(decision,0), HX(tc25,0) IFN SETF +++ vadd HX(decision,0), HX(d,0), HX(d,0) IFN +++ vsub HX(decision,0), HX(decision,0), HX(beta2,0) IFN SETF +++ vmov HX(decision,0), 1 IFNN +++ vadd H(decision,0),H(decision,3),0 IFN +++ vadd H(decision,16),H(decision,19),0 IFN +++ vmov -,HX(decision,0) SETF # N marks strong filter +++ vmov HX(decision,0), 1 IFNN # NN marks normal filter +++ +++ vadd HX(do_filter,0), HX(d,3), HX(d,0) +++ vsub HX(do_filter,0), HX(do_filter,0), HX(beta,0) SETF # IFNN means no filter +++ vmov HX(decision,0),0 IFNN # Z marks no filter +++ +++ # Expand out decision (currently valid one every 4 pixels) 0...1...2...3 +++ # First extract out even terms +++ vodd HX(decision,0),HX(decision,0),HX(decision,0) # 0.1.2.3 +++ vodd HX(decision,0),HX(decision,0),HX(decision,0) # 0123 +++ # Now expand back +++ valtl HX(decision,0),HX(decision,0),HX(decision,0) # 00112233 +++ valtl HX(decision,0),HX(decision,0),HX(decision,0) SETF # 0000111122223333 +++ +++ # HX(decision,0) is negative if want strong filtering, 1 if want normal filtering, 0 if want no filtering +++ +++ # Do a quick check to see if there is anything to do +++ mov r11, 0 # Signal no filtering +++ vmov -,1 IFNZ SUMS r5 +++ cmp r5,0 +++ beq filtering_done +++ mov r11, 1 # Signal some filtering +++ # And whether there is any strong filtering +++ vmov -,1 IFN SUMS r5 +++ cmp r5,0 +++ beq normal_filtering +++ +++ ############################################################################## +++ # Strong filtering - could maybe fast case if all have same sign? (especially if all disabled!) +++ vshl HX(tc2,0), HX(tc,0), 1 # Note that in normal filtering tx2 is tc/2, while here it is tc*2 +++ +++ # Take a copy of the original pixels for use in decision calculation +++ vmov HX(P0,32),HX(P0,0) +++ vmov HX(Q0,32),HX(Q0,0) +++ vmov HX(P1,32),HX(P1,0) +++ vmov HX(Q1,32),HX(Q1,0) +++ vmov HX(P2,32),HX(P2,0) +++ vmov HX(Q2,32),HX(Q2,0) +++ +++ vadd -,HX(P2,32),4 CLRA SACC +++ vshl -,HX(P1,32),1 SACC +++ vshl -,HX(P0,32),1 SACC +++ vshl -,HX(Q0,32),1 SACC +++ vshl HX(delta,0),HX(Q1,32),0 SACC +++ vasr HX(delta,0),HX(delta,0), 3 +++ vsub HX(delta,0),HX(delta,0),HX(P0,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(P0,0),HX(P0,32),HX(delta,0) IFN +++ +++ vadd -,HX(P2,32),2 CLRA SACC +++ vadd -,HX(P1,32),HX(P0,32) SACC +++ vshl HX(delta,0),HX(Q0,32),0 SACC +++ vasr HX(delta,0),HX(delta,0), 2 +++ vsub HX(delta,0),HX(delta,0),HX(P1,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(P1,0),HX(P1,32),HX(delta,0) IFN +++ +++ vadd -,HX(Q0,32),4 CLRA SACC +++ vadd -,HX(P1,32),HX(P0,32) SACC +++ vmul -,HX(P2,32),3 SACC +++ vshl HX(delta,0),HX(P3,0),1 SACC # Note that we have not made a copy of P3, so using P3,0 is correct +++ vasr HX(delta,0),HX(delta,0), 3 +++ vsub HX(delta,0),HX(delta,0),HX(P2,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(P2,0),HX(P2,32),HX(delta,0) IFN +++ #vmov HX(P2,0),3 IFN +++ +++ # Now reverse all P/Qs +++ +++ vadd -,HX(Q2,32),4 CLRA SACC +++ vshl -,HX(Q1,32),1 SACC +++ vshl -,HX(Q0,32),1 SACC +++ vshl -,HX(P0,32),1 SACC +++ vshl HX(delta,0),HX(P1,32),0 SACC +++ vasr HX(delta,0),HX(delta,0), 3 +++ vsub HX(delta,0),HX(delta,0),HX(Q0,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(Q0,0),HX(Q0,32),HX(delta,0) IFN +++ +++ vadd -,HX(Q2,32),2 CLRA SACC +++ vadd -,HX(Q1,32),HX(Q0,32) SACC +++ vshl HX(delta,0),HX(P0,32),0 SACC +++ vasr HX(delta,0),HX(delta,0), 2 +++ vsub HX(delta,0),HX(delta,0),HX(Q1,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(Q1,0),HX(Q1,32),HX(delta,0) IFN +++ +++ vadd -,HX(P0,32),4 CLRA SACC +++ vadd -,HX(Q1,32),HX(Q0,32) SACC +++ vmul -,HX(Q2,32),3 SACC +++ vshl HX(delta,0),HX(Q3,0),1 SACC # Note that we have not made a copy of Q3, so using Q3,0 is correct +++ vasr HX(delta,0),HX(delta,0), 3 +++ vsub HX(delta,0),HX(delta,0),HX(Q2,32) +++ vclamps HX(delta,0), HX(delta,0), HX(tc2,0) +++ vadd HX(Q2,0),HX(Q2,32),HX(delta,0) IFN +++ +++ ############################################################################## +++ # Normal filtering +++normal_filtering: +++ # Invert the decision flags +++ # make instruction more complicated as assembler has error and loses SETF +++ vrsub HX(tc10,0), HX(decision,0), 0 SETF # IFN means normal filtering +++ vmov -, HX(tc10,0) SETF # IFN means normal filtering +++ +++ vmov -,1 IFN SUMS r5 +++ cmp r5,0 +++ beq filtering_done +++ +++ vasr HX(tc2,0), HX(tc,0), 1 +++ vmul HX(tc10,0), HX(tc,0), 10 +++ +++ vasr HX(thresh,0), HX(beta,0), 1 +++ vadd HX(thresh,0), HX(thresh,0), HX(beta,0) +++ vasr HX(thresh,0), HX(thresh,0), 3 CLRA SACC +++ +++ vadd HX(ptest,0),HX(dp,3),HX(dp,0) +++ vsub HX(ptest,0),HX(ptest,0),HX(thresh,0) # ptest is negative if we need to do the P2 pixel +++ vadd HX(qtest,0),HX(dq,3),HX(dq,0) +++ vsub HX(qtest,0),HX(qtest,0),HX(thresh,0) # qtest is negative if we need to do the Q2 pixel +++ # Expand ptest and qtest together +++ vodd HX(pqtest,0),HX(ptest,0),HX(qtest,0) # p.p.p.p.q.q.q.q +++ vodd HX(pqtest,0),HX(pqtest,0),HX(pqtest,0) # ppppqqqq........ +++ valtl HX(pqtest,0),HX(pqtest,0),HX(pqtest,0) # ppppppppqqqqqqqq +++ valtl HX(ptest,0),HX(pqtest,0),HX(pqtest,0) +++ valtu HX(qtest,0),HX(pqtest,0),HX(pqtest,0) +++ +++ vsub HX(delta0,0), HX(Q0,0), HX(P0,0) +++ vsub HX(delta1,0), HX(Q1,0), HX(P1,0) +++ vmov -,8 CLRA SACC +++ vmul -,HX(delta0,0), 9 SACC +++ vmul HX(delta0,0),HX(delta1,0), r6 SACC +++ vasr HX(delta0,0), HX(delta0,0), 4 +++ vdist HX(deltatest,0), HX(delta0,0), 0 +++ vsub HX(deltatest,0), HX(deltatest,0), HX(tc10,0) IFN SETF # negative if still need to do something +++ vmov HX(deltatest,0), 0 IFNN # clear if no need to do anything so we can reload flags later +++ +++ vclamps HX(delta0,0), HX(delta0,0), HX(tc,0) +++ +++ vadd HX(deltap1,0), HX(P2,0), HX(P0,0) +++ vadd HX(deltap1,0), HX(deltap1,0), 1 +++ vasr HX(deltap1,0), HX(deltap1,0), 1 CLRA SACC +++ vsub HX(deltap1,0), HX(delta0,0), HX(P1,0) SACC +++ vasr HX(deltap1,0), HX(deltap1,0), 1 +++ vclamps HX(deltap1,0), HX(deltap1,0), HX(tc2,0) +++ +++ vadd HX(deltaq1,0), HX(Q2,0), HX(Q0,0) +++ vadd HX(deltaq1,0), HX(deltaq1,0), 1 +++ vasr HX(deltaq1,0), HX(deltaq1,0), 1 CLRA SACC +++ vadd HX(deltaq1,0), HX(delta0,0), HX(Q1,0) +++ vrsub -, HX(delta0,0), 0 SACC +++ vrsub HX(deltaq1,0), HX(Q1,0), 0 SACC +++ vasr HX(deltaq1,0), HX(deltaq1,0), 1 +++ vclamps HX(deltaq1,0), HX(deltaq1,0), HX(tc2,0) +++ +++ vadds HX(P0,0), HX(P0,0), HX(delta0,0) IFN +++ vsubs HX(Q0,0), HX(Q0,0), HX(delta0,0) IFN +++ +++ vmov -,HX(ptest,0) IFN SETF # Negative if need to do p1 +++ vadds HX(P1,0), HX(P1,0), HX(deltap1,0) IFN +++ +++ vmov -,HX(deltatest,0) SETF +++ vmov -,HX(qtest,0) IFN SETF # Negative if need to do q1 +++ vadds HX(Q1,0), HX(Q1,0), HX(deltaq1,0) IFN +++ +++ #vmov HX(P2,0),1 IFN +++ +++filtering_done: +++ b lr ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 0121fca..05b2169 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -147,7 +147,7 @@ static int gpu_init(volatile struct GPU **gpu) { ++ vcsm_init(); ++ gpu_malloc_uncached_internal(sizeof(struct GPU), &gpu_mem_ptr, mb); ++ ptr = (volatile struct GPU*)gpu_mem_ptr.arm; ++- memset(ptr, 0, sizeof *ptr); +++ memset((void*)ptr, 0, sizeof *ptr); ++ vc = gpu_mem_ptr.vc; ++ ++ ptr->mb = mb; ++@@ -254,7 +254,7 @@ void gpu_cache_flush(GPU_MEM_PTR_T *p) ++ struct vcsm_user_clean_invalid_s iocache = {}; ++ iocache.s[0].handle = p->vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = p->arm; +++ iocache.s[0].addr = (int) p->arm; ++ iocache.s[0].size = p->numbytes; ++ vcsm_clean_invalid( &iocache ); ++ #else ++@@ -390,6 +390,7 @@ static void *vpu_start(void *arg) { ++ #ifdef RPI_TIME_TOTAL_POSTED ++ int last_time=0; ++ long long on_time=0; +++ long long on_time_deblock=0; ++ long long off_time=0; ++ int start_time; ++ int end_time; ++@@ -451,10 +452,13 @@ static void *vpu_start(void *arg) { ++ #ifdef RPI_TIME_TOTAL_POSTED ++ end_time = Microseconds(); ++ last_time = end_time; ++- on_time += end_time - start_time; +++ if (p[6]==2) +++ on_time_deblock += end_time - start_time; +++ else +++ on_time += end_time - start_time; ++ count++; ++ if ((count&0x7f)==0) ++- printf("Posted %d On=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(off_time/1000)); +++ printf("Posted %d On=%dms, On_deblock=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(on_time_deblock/1000),(int)(off_time/1000)); ++ #endif ++ pthread_mutex_lock(&post_mutex); ++ vpu_async_head++; ++diff --git a/libavcodec/rpi_shader.c b/libavcodec/rpi_shader.c ++index e86eb30..c5d8b29 100644 ++--- a/libavcodec/rpi_shader.c +++++ b/libavcodec/rpi_shader.c ++@@ -61,7 +61,7 @@ unsigned int rpi_shader[] = { ++ /* [0x00000120] */ 0x8c9e7052, 0x10025e18, // add t0s, r0, r1 ; mov ra_frame_base, r2 ++ /* [0x00000128] */ 0x0c9e7440, 0x10020f27, // add t1s, r2, r1 ++ /* [0x00000130] */ 0x00000008, 0xe00208a7, // mov r2,8 ++-/* [0x00000138] */ 0x11827c80, 0x10021327, // shl rb12,unif, r2 +++/* [0x00000138] */ 0x11827c80, 0x10021327, // shl rb12,unif,r2 ++ /* [0x00000140] */ 0x0c827c80, 0x10021367, // add rb13,unif,r2 ++ /* [0x00000148] */ 0x15827d80, 0x100208a7, // mov r2, unif ++ /* [0x00000150] */ 0x119c15c0, 0xd00208a7, // shl r2, r2, 1 ++-- ++2.5.0 ++ ++ ++From 1c7aae12a916196defd7ca1d5e8f052551535034 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 1 Jul 2015 09:21:17 +0100 ++Subject: [PATCH 65/68] Added ability to combine jobs ++ ++--- ++ libavcodec/rpi_qpu.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- ++ 1 file changed, 80 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 05b2169..91777be 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -8,6 +8,8 @@ ++ #define RPI_TIME_TOTAL_POSTED ++ // define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion ++ #define RPI_ASYNC +++// Define RPI_COMBINE_JOBS to find jobs that can be executed in parallel +++#define RPI_COMBINE_JOBS ++ ++ #include ++ #include ++@@ -398,9 +400,15 @@ static void *vpu_start(void *arg) { ++ #endif ++ while(1) { ++ int i; ++- int *p; +++ int *p; // Pointer for a QPU/VPU job +++#ifdef RPI_COMBINE_JOBS +++ int *q = NULL; // Pointer for a VPU only job +++ int have_qpu = 0; +++ int have_vpu = 0; +++#endif ++ int qpu_code; ++ int qpu_codeb; +++ int num_jobs; // Number of jobs available ++ pthread_mutex_lock(&post_mutex); ++ while( vpu_async_tail - vpu_async_head <= 0) ++ { ++@@ -408,13 +416,38 @@ static void *vpu_start(void *arg) { ++ pthread_cond_wait(&post_cond_tail, &post_mutex); ++ } ++ p = vpu_cmds[vpu_async_head%MAXCMDS]; +++ num_jobs = vpu_async_tail - vpu_async_head; ++ pthread_mutex_unlock(&post_mutex); ++ ++ if (p[6] == -1) { ++ break; // Last job ++ } +++ if (p[7] == 0 && p[0] == 0 && p[16]==0) +++ goto job_done_early; +++ +++#ifdef RPI_COMBINE_JOBS +++ // First scan for a qpu job +++ for (int x=0;xmail[i*2] = p[8+i]; +++ gpu->mail[i*2 + 1] = qpu_code; +++ } +++ for(i=0;i<12;i++) { +++ gpu->mail2[i*2] = p[17+i]; +++ gpu->mail2[i*2 + 1] = qpu_codeb; +++ } +++ if (have_vpu) { +++ execute_multi(gpu->mb, +++ 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, +++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 +++ q[0], q[1], q[2], q[3], q[4], q[5], q[6]); // VPU1 +++ q[0] = 0; +++ } else { +++ execute_multi(gpu->mb, +++ 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, +++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 +++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 +++ } +++ p[0] = 0; +++ p[7] = 0; +++ p[16] = 0; +++ } else { +++ av_assert0(have_vpu); +++ vpu_execute_code(q[0], q[1], q[2], q[3], q[4], q[5], q[6]); +++ q[0] = 0; +++ } +++#else +++ ++ if (!qpu_code) { ++ vpu_execute_code(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); ++ } else { ++@@ -449,17 +516,29 @@ static void *vpu_start(void *arg) { ++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 ++ #endif ++ } +++#endif +++ ++ #ifdef RPI_TIME_TOTAL_POSTED ++ end_time = Microseconds(); ++ last_time = end_time; +++#ifdef RPI_COMBINE_JOBS +++ // There are three cases we may wish to distinguish of VPU/QPU activity +++ on_time += end_time - start_time; +++#else ++ if (p[6]==2) ++ on_time_deblock += end_time - start_time; ++ else ++ on_time += end_time - start_time; +++#endif ++ count++; ++ if ((count&0x7f)==0) +++#ifdef RPI_COMBINE_JOBS ++ printf("Posted %d On=%dms, On_deblock=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(on_time_deblock/1000),(int)(off_time/1000)); +++#else +++ printf("Posted %d On=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(off_time/1000)); +++#endif ++ #endif +++job_done_early: ++ pthread_mutex_lock(&post_mutex); ++ vpu_async_head++; ++ pthread_cond_broadcast(&post_cond_head); ++-- ++2.5.0 ++ ++ ++From 3b056ce7d9bc16ac6d62fc84cb26e0991741ec26 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 1 Jul 2015 12:53:10 +0100 ++Subject: [PATCH 66/68] Added chroma deblocking ++ ++--- ++ libavcodec/hevc.c | 20 ++ ++ libavcodec/hevc.h | 12 +- ++ libavcodec/hevc_filter.c | 92 +++++- ++ libavcodec/rpi_hevc_transform.h | 644 +++++++++++++++++++++++++++++++++++++++- ++ libavcodec/rpi_hevc_transform.s | 207 +++++++++++++ ++ libavcodec/rpi_qpu.c | 27 +- ++ libavcodec/rpi_shader.qasm | 11 + ++ 7 files changed, 988 insertions(+), 25 deletions(-) ++ ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 0ecaf05..35a1394 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -251,6 +251,14 @@ static void pic_arrays_free(HEVCContext *s) ++ gpu_free(&s->y_setup_ptr); ++ s->y_setup_arm = 0; ++ } +++ if (s->uv_setup_arm) { +++ gpu_free(&s->uv_setup_ptr); +++ s->uv_setup_arm = 0; +++ } +++ if (s->vpu_cmds_arm) { +++ gpu_free(&s->vpu_cmds_ptr); +++ s->vpu_cmds_arm = 0; +++ } ++ #endif ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++@@ -324,6 +332,18 @@ static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++ s->y_setup_vc = (void*)s->y_setup_ptr.vc; ++ memset(s->y_setup_arm, 0, s->y_setup_ptr.numbytes); ++ printf("Setup %d by %d by %d\n",s->setup_width,s->setup_height,sizeof(*s->y_setup_arm)); +++ +++ s->uv_setup_width = ( (sps->width >> sps->hshift[1]) + 15) / 16; +++ s->uv_setup_height = ( (sps->height >> sps->vshift[1]) + 15) / 16; +++ gpu_malloc_uncached(sizeof(*s->uv_setup_arm) * s->uv_setup_width * s->uv_setup_height, &s->uv_setup_ptr); // TODO make this cached +++ s->uv_setup_arm = (void*)s->uv_setup_ptr.arm; +++ s->uv_setup_vc = (void*)s->uv_setup_ptr.vc; +++ memset(s->uv_setup_arm, 0, s->uv_setup_ptr.numbytes); +++ printf("Setup uv %d by %d by %d\n",s->uv_setup_width,s->uv_setup_height,sizeof(*s->uv_setup_arm)); +++ +++ gpu_malloc_uncached(sizeof(*s->vpu_cmds_arm) * 3,&s->vpu_cmds_ptr); +++ s->vpu_cmds_arm = (void*) s->vpu_cmds_ptr.arm; +++ s->vpu_cmds_vc = s->vpu_cmds_ptr.vc; ++ #endif ++ ++ s->bs_width = (width >> 2) + 1; ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index b1d3ee0..aa7cdc3 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -55,7 +55,7 @@ ++ #define RPI_MAX_JOBS 2 ++ // Define RPI_WORKER to launch a worker thread for pixel processing tasks ++ #define RPI_WORKER ++- +++ // Define RPI_DEBLOCK_VPU to perform deblocking on the VPUs ++ #define RPI_DEBLOCK_VPU ++ ++ #endif ++@@ -1006,6 +1006,16 @@ typedef struct HEVCContext { ++ uint8_t (*y_setup_vc)[2][2][2][4]; ++ int setup_width; // Number of 16x16 blocks across the image ++ int setup_height; // Number of 16x16 blocks down the image +++ +++ GPU_MEM_PTR_T uv_setup_ptr; +++ uint8_t (*uv_setup_arm)[2][2][2][4]; // Half of this is unused [][][1][], but easier for the VPU as it allows us to store with zeros and addresses are aligned +++ uint8_t (*uv_setup_vc)[2][2][2][4]; +++ int uv_setup_width; +++ int uv_setup_height; +++ +++ GPU_MEM_PTR_T vpu_cmds_ptr; +++ int (*vpu_cmds_arm)[6]; // r0-r5 for each command +++ int vpu_cmds_vc; ++ #endif ++ ++ #endif ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 06371da..6367068 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -656,9 +656,23 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->frame->linesize[chroma], ++ c_tc, no_p, no_q); ++ } else +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock) { +++ uint8_t (*setup)[2][2][4]; +++ int xc = x>>s->ps.sps->hshift[chroma]; +++ int yc = y>>s->ps.sps->vshift[chroma]; +++ int num16 = (yc>>4)*s->uv_setup_width + (xc>>4); +++ int a = ((yc>>3) & 1) << 1; +++ int b = (xc>>3) & 1; +++ setup = s->uv_setup_arm[num16]; +++ setup[0][b][0][a] = c_tc[0]; +++ setup[0][b][0][a + 1] = c_tc[1]; +++ } else +++#endif ++ s->hevcdsp.hevc_v_loop_filter_chroma(src, ++ s->frame->linesize[chroma], ++ c_tc, no_p, no_q); +++ ++ } ++ } ++ ++@@ -689,6 +703,19 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ s->frame->linesize[chroma], ++ c_tc, no_p, no_q); ++ } else +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock) { +++ uint8_t (*setup)[2][2][4]; +++ int xc = x>>s->ps.sps->hshift[chroma]; +++ int yc = y>>s->ps.sps->vshift[chroma]; +++ int num16 = (yc>>4)*s->uv_setup_width + (xc>>4); +++ int a = ((xc>>3) & 1) << 1; +++ int b = (yc>>3) & 1; +++ setup = s->uv_setup_arm[num16]; +++ setup[1][b][0][a] = c_tc[0]; +++ setup[1][b][0][a + 1] = c_tc[1]; +++ } else +++#endif ++ s->hevcdsp.hevc_h_loop_filter_chroma(src, ++ s->frame->linesize[chroma], ++ c_tc, no_p, no_q); ++@@ -1013,33 +1040,56 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ static void rpi_deblock(HEVCContext *s, int y, int ctb_size) ++ { ++ // Flush image, 4 lines above to bottom of ctb stripe ++- ff_hevc_flush_buffer_lines(s, FFMAX(y-4,0), y+ctb_size, 1, 0); +++ ff_hevc_flush_buffer_lines(s, FFMAX(y-4,0), y+ctb_size, 1, 1); ++ // TODO flush buffer of beta/tc setup when it becomes cached +++ +++ // Prepare three commands at once to avoid calling overhead +++ s->vpu_cmds_arm[0][0] = get_vc_address(s->frame->buf[0]) + s->frame->linesize[0] * y; +++ s->vpu_cmds_arm[0][1] = s->frame->linesize[0]; +++ s->vpu_cmds_arm[0][2] = s->setup_width; +++ s->vpu_cmds_arm[0][3] = (int) ( s->y_setup_vc + s->setup_width * (y>>4) ); +++ s->vpu_cmds_arm[0][4] = ctb_size>>4; +++ s->vpu_cmds_arm[0][5] = 2; +++ +++ s->vpu_cmds_arm[1][0] = get_vc_address(s->frame->buf[1]) + s->frame->linesize[1] * (y>> s->ps.sps->vshift[1]); +++ s->vpu_cmds_arm[1][1] = s->frame->linesize[1]; +++ s->vpu_cmds_arm[1][2] = s->uv_setup_width; +++ s->vpu_cmds_arm[1][3] = (int) ( s->uv_setup_vc + s->uv_setup_width * ((y>>4)>> s->ps.sps->vshift[1]) ); +++ s->vpu_cmds_arm[1][4] = (ctb_size>>4)>> s->ps.sps->vshift[1]; +++ s->vpu_cmds_arm[1][5] = 3; +++ +++ s->vpu_cmds_arm[2][0] = get_vc_address(s->frame->buf[2]) + s->frame->linesize[2] * (y>> s->ps.sps->vshift[2]); +++ s->vpu_cmds_arm[2][1] = s->frame->linesize[2]; +++ s->vpu_cmds_arm[2][2] = s->uv_setup_width; +++ s->vpu_cmds_arm[2][3] = (int) ( s->uv_setup_vc + s->uv_setup_width * ((y>>4)>> s->ps.sps->vshift[1]) ); +++ s->vpu_cmds_arm[2][4] = (ctb_size>>4)>> s->ps.sps->vshift[1]; +++ s->vpu_cmds_arm[2][5] = 4; +++ ++ // Call VPU ++- // TODO add this to a separate pipeline of VPU jobs that can be run in parallel and wait for completion ++- vpu_wait(vpu_post_code( vpu_get_fn(), get_vc_address(s->frame->buf[0]) + s->frame->linesize[0] * y, s->frame->linesize[0], ++- s->setup_width, (int) ( s->y_setup_vc + s->setup_width * (y>>4) ), ++- ctb_size>>4, 2, 0)); // 2 means to do the deblocking code +++ vpu_wait(vpu_post_code( vpu_get_fn(), s->vpu_cmds_vc, 3, 0, 0, 0, 5, 0)); // 5 means to do all the commands ++ } ++ ++-static void rpi_deblock2(HEVCContext *s, int y, int ctb_size) ++-{ ++- int y2; ++- for(y2=y;y2= s->ps.sps->width - ctb_size; +++#ifdef RPI_DEBLOCK_VPU +++ int done_deblock = 0; +++#endif ++ if (s->avctx->skip_loop_filter < AVDISCARD_ALL) ++ deblocking_filter_CTB(s, x, y); ++ #ifdef RPI_DEBLOCK_VPU ++ if (s->enable_rpi_deblock && x_end) ++ { ++- rpi_deblock(s, y, ctb_size); +++ int y_at_end = y >= s->ps.sps->height - ctb_size; +++ int height = 64; // Deblock in units 64 high to avoid too many VPU calls +++ int y_start = y&~63; +++ if (y_at_end) height = s->ps.sps->height - y_start; +++ if ((((y+ctb_size)&63)==0) || y_at_end) { +++ done_deblock = 1; +++ rpi_deblock(s, y_start, height); +++ } ++ } ++ #endif ++ if (s->ps.sps->sao_enabled) { ++@@ -1070,11 +1120,25 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) ++ //int newh = y + ctb_size - 4; ++ //int currh = s->ref->tf.progress->data[0]; ++ //if (((y + ctb_size)&63)==0) +++#ifdef RPI_DEBLOCK_VPU +++ if (s->enable_rpi_deblock) { +++ // we no longer need to flush the luma buffer as it is in GPU memory when using deblocking on the rpi +++ if (done_deblock) { +++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); +++ } +++ } else { +++#ifdef RPI_INTER_QPU +++ ff_hevc_flush_buffer(s, &s->ref->tf, y + ctb_size - 4); +++#endif +++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); +++ } +++#else ++ #ifdef RPI_INTER_QPU ++ ff_hevc_flush_buffer(s, &s->ref->tf, y + ctb_size - 4); ++- // TODO we no longer need to flush the luma buffer as it is in GPU memory when using deblocking on the rpi +++ // we no longer need to flush the luma buffer as it is in GPU memory when using deblocking on the rpi ++ #endif ++ ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0); +++#endif ++ } ++ } ++ ++diff --git a/libavcodec/rpi_hevc_transform.h b/libavcodec/rpi_hevc_transform.h ++index b3f155f..4309f1c 100644 ++--- a/libavcodec/rpi_hevc_transform.h +++++ b/libavcodec/rpi_hevc_transform.h ++@@ -3,14 +3,32 @@ unsigned char rpi_hevc_transform [] = { ++ 106, ++ 0, ++ 144, ++-38, +++47, ++ 1, ++ 37, ++ 106, ++ 0, ++ 144, ++-57, +++66, ++ 1, +++53, +++106, +++0, +++144, +++192, +++4, +++69, +++106, +++0, +++144, +++192, +++4, +++85, +++106, +++0, +++144, +++220, +++5, ++ 169, ++ 3, ++ 62, ++@@ -2427,4 +2445,626 @@ unsigned char rpi_hevc_transform [] = { ++ 128, ++ 90, ++ 0, +++169, +++3, +++14, +++96, +++4, +++31, +++169, +++3, +++30, +++96, +++1, +++31, +++73, +++64, +++52, +++64, +++45, +++64, +++2, +++64, +++10, +++64, +++64, +++198, +++1, +++7, +++8, +++232, +++63, +++0, +++0, +++0, +++6, +++232, +++253, +++255, +++255, +++255, +++0, +++246, +++0, +++0, +++0, +++4, +++215, +++64, +++3, +++96, +++2, +++248, +++0, +++35, +++0, +++0, +++64, +++56, +++0, +++0, +++4, +++248, +++0, +++36, +++0, +++0, +++64, +++56, +++8, +++0, +++0, +++240, +++64, +++0, +++132, +++3, +++30, +++106, +++132, +++24, +++128, +++240, +++0, +++0, +++132, +++3, +++128, +++144, +++143, +++0, +++131, +++98, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++135, +++0, +++131, +++102, +++0, +++158, +++71, +++0, +++2, +++248, +++0, +++35, +++0, +++0, +++64, +++56, +++0, +++0, +++4, +++248, +++0, +++36, +++0, +++0, +++64, +++56, +++8, +++0, +++0, +++240, +++64, +++0, +++132, +++3, +++30, +++106, +++132, +++24, +++128, +++240, +++0, +++0, +++132, +++3, +++128, +++144, +++112, +++0, +++131, +++98, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++104, +++0, +++131, +++102, +++0, +++248, +++64, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++30, +++106, +++134, +++24, +++128, +++248, +++0, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++144, +++123, +++0, +++188, +++64, +++67, +++232, +++0, +++2, +++0, +++0, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++112, +++0, +++195, +++232, +++0, +++2, +++0, +++0, +++12, +++128, +++7, +++192, +++130, +++248, +++0, +++0, +++112, +++192, +++224, +++16, +++195, +++31, +++132, +++248, +++1, +++0, +++112, +++0, +++224, +++16, +++203, +++31, +++3, +++99, +++131, +++71, +++68, +++232, +++32, +++0, +++0, +++0, +++0, +++99, +++2, +++99, +++23, +++102, +++7, +++106, +++127, +++156, +++178, +++255, +++0, +++248, +++64, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++30, +++106, +++134, +++24, +++128, +++248, +++0, +++0, +++112, +++0, +++192, +++243, +++211, +++31, +++128, +++144, +++72, +++0, +++188, +++64, +++67, +++232, +++0, +++2, +++0, +++0, +++0, +++255, +++64, +++0, +++0, +++20, +++200, +++243, +++0, +++0, +++128, +++144, +++61, +++0, +++195, +++232, +++0, +++2, +++0, +++0, +++12, +++128, +++7, +++192, +++130, +++248, +++0, +++0, +++112, +++192, +++224, +++16, +++195, +++31, +++132, +++248, +++1, +++0, +++112, +++0, +++224, +++16, +++203, +++31, +++25, +++102, +++9, +++106, +++2, +++30, +++41, +++3, +++26, +++87, +++162, +++64, +++64, +++198, +++1, +++23, +++127, +++158, +++95, +++255, +++239, +++3, +++0, +++254, +++128, +++143, +++94, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++143, +++95, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++142, +++208, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++142, +++209, +++0, +++0, +++240, +++12, +++0, +++128, +++144, +++47, +++0, +++8, +++255, +++227, +++23, +++0, +++244, +++192, +++51, +++0, +++0, +++8, +++255, +++35, +++52, +++0, +++180, +++192, +++51, +++0, +++0, +++111, +++3, +++239, +++3, +++0, +++254, +++128, +++143, +++14, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++143, +++15, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++192, +++142, +++16, +++0, +++0, +++240, +++12, +++0, +++0, +++254, +++128, +++142, +++17, +++0, +++0, +++240, +++12, +++0, +++128, +++144, +++13, +++0, +++8, +++255, +++227, +++3, +++0, +++244, +++192, +++51, +++0, +++0, +++8, +++255, +++35, +++4, +++0, +++180, +++192, +++51, +++0, +++0, +++111, +++3, +++32, +++246, +++192, +++11, +++1, +++16, +++32, +++246, +++2, +++140, +++47, +++240, +++32, +++247, +++35, +++141, +++63, +++178, +++64, +++254, +++35, +++141, +++2, +++68, +++192, +++243, +++128, +++11, +++32, +++255, +++35, +++240, +++58, +++226, +++192, +++243, +++188, +++10, +++0, +++254, +++0, +++141, +++4, +++4, +++0, +++240, +++128, +++10, +++88, +++246, +++35, +++141, +++3, +++68, +++240, +++246, +++35, +++141, +++48, +++66, +++0, +++247, +++227, +++143, +++52, +++242, +++32, +++247, +++227, +++142, +++52, +++178, +++90, +++0, +++161, +++3, +++6, +++64, +++23, +++64, +++96, +++8, +++70, +++98, +++97, +++8, +++70, +++98, +++98, +++8, +++70, +++98, +++99, +++8, +++70, +++98, +++100, +++8, +++70, +++98, +++101, +++8, +++70, +++98, +++255, +++159, +++8, +++250, +++23, +++102, +++7, +++106, +++112, +++30, +++33, +++3, ++ }; ++diff --git a/libavcodec/rpi_hevc_transform.s b/libavcodec/rpi_hevc_transform.s ++index b055208..5543093 100644 ++--- a/libavcodec/rpi_hevc_transform.s +++++ b/libavcodec/rpi_hevc_transform.s ++@@ -85,6 +85,13 @@ hevc_trans_16x16: ++ beq memclear16 ++ cmp r5,2 ++ beq hevc_deblock_16x16 +++ cmp r5,3 +++ beq hevc_uv_deblock_16x16 +++ cmp r5,4 +++ beq hevc_uv_deblock_16x16_with_clear +++ cmp r5,5 +++ beq hevc_run_command_list +++ ++ push r6-r15, lr # TODO cut down number of used registers ++ mov r14,r3 # coeffs32 ++ mov r15,r4 # num32 ++@@ -708,3 +715,203 @@ normal_filtering: ++ ++ filtering_done: ++ b lr +++ +++ +++hevc_uv_deblock_16x16: +++ push r6-r15, lr +++ mov r14,0 +++ b hevc_uv_start +++hevc_uv_deblock_16x16_with_clear: +++ push r6-r15, lr +++ mov r14,1 +++ b hevc_uv_start +++ +++hevc_uv_start: +++ mov r9,r4 +++ mov r4,r3 +++ mov r13,r2 +++ mov r2,r0 +++ mov r10,r0 +++ subscale4 r0,r1 +++ mov r8,63 +++ mov r6,-3 +++ vmov H(zeros,0),0 +++# r7 is number of blocks still to load +++# r0 is location of current block - 4 * stride +++# r1 is stride +++# r2 is location of current block +++# r3 is offset of start of block (actual edges start at H(16,16)+r3 for horizontal and H(16,0)+r3 for vertical +++# r4 is setup +++# r5 is for temporary calculations +++# r8 holds 63 +++# r6 holds -3 +++# r9 holds the number of 16 high rows to process +++# r10 holds the original img base +++# r11 returns 0 if no filtering was done on the edge +++# r12 saves a copy of this +++# r13 is copy of width +++# r14 is 1 if we should clear the old contents, or 0 if not +++ +++uv_process_row: +++ # First iteration does not do horizontal filtering on previous +++ mov r7, r13 +++ mov r3,0 +++ vldb H(12++,16)+r3,(r0 += r1) REP 4 # Load the current block +++ vldb H(16++,16)+r3,(r2 += r1) REP 16 +++ vldb H(setup_input,0), (r4) # We may wish to prefetch these +++ cmp r14,1 +++ bne uv_skip0 +++ vstb H(zeros,0),(r4) +++uv_skip0: +++ bl uv_vert_filter +++ add r3,8 +++ vadd H(setup_input,0),H(setup_input,8),0 # Rotate to second set of 8 +++ bl uv_vert_filter +++ sub r3,8 +++ b uv_start_deblock_loop +++uv_deblock_loop: +++ # Middle iterations do vertical on current block and horizontal on preceding +++ vldb H(12++,16)+r3,(r0 += r1) REP 4 # load the current block +++ vldb H(16++,16)+r3,(r2 += r1) REP 16 +++ vldb H(setup_input,0), (r4) +++ cmp r14,1 +++ bne uv_skip1 +++ vstb H(zeros,0),(r4) +++uv_skip1: +++ bl uv_vert_filter +++ add r3,8 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl uv_vert_filter +++ sub r3,8 +++ vldb H(setup_input,0), -16(r4) +++ cmp r14,1 +++ bne uv_skip3 +++ vstb H(zeros,0),-16(r4) +++uv_skip3: +++ bl uv_horz_filter +++ mov r12,r11 +++ add r3,8*64 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl uv_horz_filter +++ sub r3,8*64 +++ addcmpbeq r12,0,0,uv_skip_save_top +++ vstb H(12++,0)+r3,-16(r0 += r1) REP 4 # Save the deblocked pixels for the previous block +++uv_skip_save_top: +++ vstb H(16++,0)+r3,-16(r2 += r1) REP 16 +++uv_start_deblock_loop: +++ # move onto next 16x16 (could do this with circular buffer support instead) +++ add r3,16 +++ and r3,r8 +++ add r4,32 +++ # Perform loop counter operations (may work with an addcmpbgt as well?) +++ add r0,16 +++ add r2,16 +++ sub r7,1 +++ cmp r7,0 # Are there still more blocks to load +++ bgt uv_deblock_loop +++ +++ # Final iteration needs to just do horizontal filtering +++ vldb H(setup_input,0), -16(r4) +++ cmp r14,1 +++ bne uv_skip2 +++ vstb H(zeros,0),-16(r4) +++uv_skip2: +++ bl uv_horz_filter +++ mov r12,r11 +++ add r3,8*64 +++ vadd H(setup_input,0),H(setup_input,8),0 +++ bl uv_horz_filter +++ sub r3,64*8 +++ addcmpbeq r12,0,0,uv_skip_save_top2 +++ vstb H(12++,0)+r3,-16(r0 += r1) REP 4 # Save the deblocked pixels for the previous block +++uv_skip_save_top2: +++ vstb H(16++,0)+r3,-16(r2 += r1) REP 16 +++ +++# Now look to see if we should do another row +++ sub r9,1 +++ cmp r9,0 +++ bgt uv_start_again +++ pop r6-r15, pc +++uv_start_again: +++ # Need to sort out r0,r2 to point to next row down +++ addscale16 r10,r1 +++ mov r2,r10 +++ subscale4 r0,r2,r1 +++ b uv_process_row +++ +++ +++# At this stage H(16,16)+r3 points to the first pixel of the 16 high edge to be filtered +++# So we can reuse the code we move the parts to be filtered into HX(P0/P1/P2/P3/Q0/Q1/Q2/Q3,0) - we will perform a final saturation step on placing them back into the correct locations +++ +++uv_vert_filter: +++ push lr +++ +++ vmov HX(P1,0), V(16,14)+r3 +++ vmov HX(P0,0), V(16,15)+r3 +++ vmov HX(Q0,0), V(16,16)+r3 +++ vmov HX(Q1,0), V(16,17)+r3 +++ +++ bl do_chroma_filter +++ +++ vadds V(16,15)+r3, HX(P0,0), 0 +++ vadds V(16,16)+r3, HX(Q0,0), 0 +++ +++ pop pc +++ +++# Filter edge at H(16,0)+r3 +++uv_horz_filter: +++ push lr +++ +++ vmov HX(P1,0), H(14,0)+r3 +++ vmov HX(P0,0), H(15,0)+r3 +++ vmov HX(Q0,0), H(16,0)+r3 +++ vmov HX(Q1,0), H(17,0)+r3 +++ +++ bl do_chroma_filter +++ +++ vadds H(15,0)+r3, HX(P0,0), 0 +++ # P3 and Q3 never change so don't bother saving back +++ vadds H(16,0)+r3, HX(Q0,0), 0 +++ +++ pop pc +++ +++# r4 points to array of beta/tc for each 4 length edge +++do_chroma_filter: +++ valtl H(setup,0),H(setup_input,0),H(setup_input,0) # tc*8 +++ valtl HX(tc,0),H(setup,0),H(setup,0) +++ +++ vsub HX(delta,0),HX(Q0,0),HX(P0,0) +++ vshl HX(delta,0),HX(delta,0),2 CLRA SACC +++ vsub -,HX(P1,0),HX(Q1,0) SACC +++ vmov HX(delta,0),4 SACC +++ vasr HX(delta,0),HX(delta,0),3 +++ vclamps HX(delta,0), HX(delta,0), HX(tc,0) +++ vadd HX(P0,0),HX(P0,0),HX(delta,0) +++ vsub HX(Q0,0),HX(Q0,0),HX(delta,0) +++ b lr +++ +++# r0 = list +++# r1 = number +++hevc_run_command_list: +++ push r6-r7, lr +++ mov r6, r0 +++ mov r7, r1 +++loop_cmds: +++ ld r0,(r6) # How to encode r6++? +++ add r6,4 +++ ld r1,(r6) +++ add r6,4 +++ ld r2,(r6) +++ add r6,4 +++ ld r3,(r6) +++ add r6,4 +++ ld r4,(r6) +++ add r6,4 +++ ld r5,(r6) +++ add r6,4 +++ bl hevc_trans_16x16 +++ sub r7,1 +++ cmp r7,0 +++ bgt loop_cmds +++ +++ pop r6-r7, pc ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 91777be..5aa0432 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -397,6 +397,8 @@ static void *vpu_start(void *arg) { ++ int start_time; ++ int end_time; ++ int count=0; +++ int count_deblock=0; +++ int count_qpu=0; ++ #endif ++ while(1) { ++ int i; ++@@ -442,7 +444,7 @@ static void *vpu_start(void *arg) { ++ break; ++ } ++ } ++- printf("Have_qpu = %d, have_vpu=%d\n",have_qpu,have_vpu); +++ //printf("Have_qpu = %d, have_vpu=%d\n",have_qpu,have_vpu); ++ #endif ++ qpu_code = p[7]; ++ qpu_codeb = p[16]; ++@@ -460,6 +462,12 @@ static void *vpu_start(void *arg) { ++ off_time += start_time-last_time; ++ #endif ++ +++#define NO_FLUSH 1 +++#define CLEAR_PROFILE 2 +++#define OUTPUT_COUNTS 4 +++ +++#define FLAGS_FOR_PROFILING (NO_FLUSH) +++ ++ #ifdef RPI_COMBINE_JOBS ++ if (have_qpu) { ++ for(i=0;i<8;i++) { ++@@ -472,14 +480,14 @@ static void *vpu_start(void *arg) { ++ } ++ if (have_vpu) { ++ execute_multi(gpu->mb, ++- 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 12,gpu->vc + offsetof(struct GPU, mail2), FLAGS_FOR_PROFILING, 5000, ++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, ++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 ++ q[0], q[1], q[2], q[3], q[4], q[5], q[6]); // VPU1 ++ q[0] = 0; ++ } else { ++ execute_multi(gpu->mb, ++- 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 12,gpu->vc + offsetof(struct GPU, mail2), FLAGS_FOR_PROFILING, 5000, ++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, ++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 ++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 ++@@ -510,7 +518,7 @@ static void *vpu_start(void *arg) { ++ execute_qpu(gpu->mb,8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */); ++ #else ++ execute_multi(gpu->mb, ++- 12,gpu->vc + offsetof(struct GPU, mail2), 1, 5000, +++ 12,gpu->vc + offsetof(struct GPU, mail2), FLAGS_FOR_PROFILING , 5000, ++ 8,gpu->vc + offsetof(struct GPU, mail), 1 /* no flush */, 5000 /* timeout ms */, ++ p[0], p[1], p[2], p[3], p[4], p[5], p[6], // VPU0 ++ 0, 0 , 0 , 0 , 0 , 0 , 0); // VPU1 ++@@ -525,17 +533,20 @@ static void *vpu_start(void *arg) { ++ // There are three cases we may wish to distinguish of VPU/QPU activity ++ on_time += end_time - start_time; ++ #else ++- if (p[6]==2) +++ if (p[6]>1) { +++ count_deblock++; ++ on_time_deblock += end_time - start_time; ++- else +++ } else { ++ on_time += end_time - start_time; +++ count_qpu++; +++ } ++ #endif ++ count++; ++ if ((count&0x7f)==0) ++ #ifdef RPI_COMBINE_JOBS ++- printf("Posted %d On=%dms, On_deblock=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(on_time_deblock/1000),(int)(off_time/1000)); ++-#else ++ printf("Posted %d On=%dms, Off=%dms\n",count,(int)(on_time/1000),(int)(off_time/1000)); +++#else +++ printf("Posted %d On=%dms (%d calls), On_deblock=%dms (%d calls), Off=%dms\n",count,(int)(on_time/1000),count_qpu,(int)(on_time_deblock/1000),count_deblock,(int)(off_time/1000)); ++ #endif ++ #endif ++ job_done_early: ++diff --git a/libavcodec/rpi_shader.qasm b/libavcodec/rpi_shader.qasm ++index 0686249..64bf5b0 100644 ++--- a/libavcodec/rpi_shader.qasm +++++ b/libavcodec/rpi_shader.qasm ++@@ -1077,6 +1077,17 @@ nop ; nop # delay slot 2 ++ ::mc_interrupt_exit12 ++ mov -, vw_wait # wait on the VDW ++ +++ # Dummy wait to test instructions +++# mov r3,1000000 +++#:dummy_loop +++# sub.setf r3, r3, 1 +++# nop +++# nop +++# brr.anynn -, r:dummy_loop +++# nop +++# nop +++# nop +++ ++ ldtmu0 ++ ldtmu0 ++ ldtmu1 ++-- ++2.5.0 ++ ++ ++From 9f07110097a85bc056c338f9bd1891ca2027f580 Mon Sep 17 00:00:00 2001 ++From: Ben Avison ++Date: Tue, 23 Jun 2015 23:42:03 +0100 ++Subject: [PATCH 67/68] armv7/hevc: Optimise deblocking boundary strength ++ calculation ++ ++--- ++ libavcodec/arm/hevcdsp_deblock_neon.S | 115 +++++++++++++++++ ++ libavcodec/arm/hevcdsp_init_neon.c | 9 ++ ++ libavcodec/hevc.h | 11 -- ++ libavcodec/hevc_filter.c | 224 ++++++++++++++-------------------- ++ libavcodec/hevcdsp.c | 116 ++++++++++++++++++ ++ libavcodec/hevcdsp.h | 14 +++ ++ 6 files changed, 344 insertions(+), 145 deletions(-) ++ ++diff --git a/libavcodec/arm/hevcdsp_deblock_neon.S b/libavcodec/arm/hevcdsp_deblock_neon.S ++index 166bddb..bad4589 100644 ++--- a/libavcodec/arm/hevcdsp_deblock_neon.S +++++ b/libavcodec/arm/hevcdsp_deblock_neon.S ++@@ -383,3 +383,118 @@ function ff_hevc_h_loop_filter_chroma_neon, export=1 ++ vst1.8 {d4}, [r0] ++ bx lr ++ endfunc +++ +++/* ff_hevc_deblocking_boundary_strengths_neon(int pus, int dup, int in_inc, int out_inc, +++ * int *curr_rpl0, int *curr_rpl1, int *neigh_rpl0, int *neigh_rpl1, +++ * MvField *curr, MvField *neigh, uint8_t *bs) +++ */ +++function ff_hevc_deblocking_boundary_strengths_neon, export=1 +++ add ip, sp, #4*4 +++ push {a2-a4,v1-v8,lr} +++ ldmia ip, {v5-v7} +++1: ldmdb ip, {v1-v4} +++ ldrsb a3, [v5, #8] @ curr->ref_idx +++ ldrsb v8, [v5, #9] +++ ldrsb ip, [v6, #8] @ neigh->ref_idx +++ ldrsb lr, [v6, #9] +++ ldr v1, [v1, a3, lsl #2] +++ ldrb a3, [v5, #10] @ curr->pred_flag +++ ldr v2, [v2, v8, lsl #2] +++ ldrb v8, [v6, #10] @ neigh->pred_flag +++ ldr v3, [v3, ip, lsl #2] +++ ldr v4, [v4, lr, lsl #2] +++ teq a3, #3 +++ beq 20f +++ teq v8, #3 +++ beq 90f +++ +++ tst a3, #1 +++ ldrne a3, [v5, #0] @ curr->mv[0] +++ ldreq a3, [v5, #4] @ curr->mv[1] +++ moveq v1, v2 +++ tst v8, #1 +++ ldrne v8, [v6, #0] @ neigh->mv[0] +++ ldreq v8, [v6, #4] @ neigh->mv[1] +++ moveq v3, v4 +++ teq v1, v3 +++ bne 10f +++ ldr lr, =0xFFFCFFFC +++ ssub16 ip, v8, a3 +++ ssub16 a3, a3, v8 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ @ drop through +++10: movne a3, #1 +++11: subs a2, a2, #1 +++12: strbhs a3, [v7], a4 +++ subs a2, a2, #1 +++ bhs 12b +++ +++ ldm sp, {a2, a3} +++ add ip, sp, #16*4 +++ subs a1, a1, #1 +++ add v5, v5, a3 +++ add v6, v6, a3 +++ bhi 1b +++ pop {a2-a4,v1-v8,pc} +++ +++20: teq v8, #3 +++ bne 10b +++ +++ teq v1, v3 +++ teqeq v2, v4 +++ bne 40f +++ teq v1, v2 +++ bne 30f +++ +++ ldrd v1, v2, [v5] @ curr->mv +++ ldrd v3, v4, [v6] @ neigh->mv +++ ldr lr, =0xFFFCFFFC +++ ssub16 ip, v3, v1 +++ ssub16 a3, v1, v3 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ bne 25f +++ ssub16 ip, v4, v2 +++ ssub16 a3, v2, v4 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ beq 11b +++ @ drop through +++25: ssub16 ip, v4, v1 +++ ssub16 a3, v1, v4 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ bne 10b +++ ssub16 ip, v3, v2 +++ ssub16 a3, v2, v3 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ b 10b +++ +++30: ldrd v1, v2, [v5] @ curr->mv +++ ldrd v3, v4, [v6] @ neigh->mv +++ ldr lr, =0xFFFCFFFC +++ ssub16 ip, v3, v1 +++ ssub16 a3, v1, v3 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ bne 10b +++ ssub16 ip, v4, v2 +++ ssub16 a3, v2, v4 +++ sel a3, a3, ip +++ ands a3, a3, lr +++ b 10b +++ +++40: teq v1, v4 +++ teqeq v2, v3 +++ bne 10b +++ +++ ldrd v1, v2, [v5] @ curr->mv +++ ldrd v3, v4, [v6] @ neigh->mv +++ ldr lr, =0xFFFCFFFC +++ b 25b +++ +++90: mov a3, #1 +++ b 11b +++endfunc ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index e5da7e9..49c70dd 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -290,6 +290,10 @@ static void ff_hevc_sao_edge_neon_wrapper(uint8_t *_dst /* align 16 */, uint8_t ++ } ++ #undef CMP ++ +++void ff_hevc_deblocking_boundary_strengths_neon(int pus, int dup, int in_inc, int out_inc, +++ int *curr_rpl0, int *curr_rpl1, int *neigh_rpl0, int *neigh_rpl1, +++ MvField *curr, MvField *neigh, uint8_t *bs); +++ ++ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ { ++ if (bit_depth == 8) { ++@@ -387,4 +391,9 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->put_hevc_qpel_uni[8][0][0] = ff_hevc_put_qpel_uw_pixels_w48_neon_8; ++ c->put_hevc_qpel_uni[9][0][0] = ff_hevc_put_qpel_uw_pixels_w64_neon_8; ++ } +++ +++ assert(offsetof(MvField, mv) == 0); +++ assert(offsetof(MvField, ref_idx) == 8); +++ assert(offsetof(MvField, pred_flag) == 10); +++ c->hevc_deblocking_boundary_strengths = ff_hevc_deblocking_boundary_strengths_neon; ++ } ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index aa7cdc3..cfa7c61 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -683,17 +683,6 @@ typedef struct CodingUnit { ++ uint8_t cu_transquant_bypass_flag; ++ } CodingUnit; ++ ++-typedef struct Mv { ++- int16_t x; ///< horizontal component of motion vector ++- int16_t y; ///< vertical component of motion vector ++-} Mv; ++- ++-typedef struct MvField { ++- DECLARE_ALIGNED(4, Mv, mv)[2]; ++- int8_t ref_idx[2]; ++- int8_t pred_flag; ++-} MvField; ++- ++ typedef struct NeighbourAvailable { ++ int cand_bottom_left; ++ int cand_left; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 6367068..826a82f 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -726,69 +726,6 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) ++ } ++ } ++ ++-static int boundary_strength(HEVCContext *s, MvField *curr, MvField *neigh, ++- RefPicList *neigh_refPicList) ++-{ ++- if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) { ++- // same L0 and L1 ++- if (s->ref->refPicList[0].list[curr->ref_idx[0]] == neigh_refPicList[0].list[neigh->ref_idx[0]] && ++- s->ref->refPicList[0].list[curr->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]] && ++- neigh_refPicList[0].list[neigh->ref_idx[0]] == neigh_refPicList[1].list[neigh->ref_idx[1]]) { ++- if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || ++- FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) && ++- (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || ++- FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4)) ++- return 1; ++- else ++- return 0; ++- } else if (neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && ++- neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { ++- if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || ++- FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) ++- return 1; ++- else ++- return 0; ++- } else if (neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[0].list[curr->ref_idx[0]] && ++- neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) { ++- if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || ++- FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4) ++- return 1; ++- else ++- return 0; ++- } else { ++- return 1; ++- } ++- } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV ++- Mv A, B; ++- int ref_A, ref_B; ++- ++- if (curr->pred_flag & 1) { ++- A = curr->mv[0]; ++- ref_A = s->ref->refPicList[0].list[curr->ref_idx[0]]; ++- } else { ++- A = curr->mv[1]; ++- ref_A = s->ref->refPicList[1].list[curr->ref_idx[1]]; ++- } ++- ++- if (neigh->pred_flag & 1) { ++- B = neigh->mv[0]; ++- ref_B = neigh_refPicList[0].list[neigh->ref_idx[0]]; ++- } else { ++- B = neigh->mv[1]; ++- ref_B = neigh_refPicList[1].list[neigh->ref_idx[1]]; ++- } ++- ++- if (ref_A == ref_B) { ++- if (FFABS(A.x - B.x) >= 4 || FFABS(A.y - B.y) >= 4) ++- return 1; ++- else ++- return 0; ++- } else ++- return 1; ++- } ++- ++- return 1; ++-} ++ ++ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ int log2_trafo_size) ++@@ -799,10 +736,17 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ int log2_min_tu_size = s->ps.sps->log2_min_tb_size; ++ int min_pu_width = s->ps.sps->min_pu_width; ++ int min_tu_width = s->ps.sps->min_tb_width; ++- int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width + ++- (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA; ++ int boundary_upper, boundary_left; ++- int i, j, bs; +++ int i, j; +++ RefPicList *rpl = s->ref->refPicList; +++ int min_pu_in_4pix = (1 << log2_min_pu_size) >> 2; +++ int trafo_in_min_pus = (1 << log2_trafo_size) >> log2_min_pu_size; +++ int y_pu = y0 >> log2_min_pu_size; +++ int x_pu = x0 >> log2_min_pu_size; +++ MvField *curr = &tab_mvf[y_pu * min_pu_width + x_pu]; +++ int is_intra = curr->pred_flag == PF_INTRA; +++ int inc = log2_min_pu_size == 2 ? 2 : 1; +++ uint8_t *bs; ++ ++ #ifdef DISABLE_STRENGTHS ++ return; ++@@ -818,34 +762,56 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ (y0 % (1 << s->ps.sps->log2_ctb_size)) == 0))) ++ boundary_upper = 0; ++ +++ bs = &s->horizontal_bs[(x0 + y0 * s->bs_width) >> 2]; +++ ++ if (boundary_upper) { ++ RefPicList *rpl_top = (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ? ++ ff_hevc_get_ref_list(s, s->ref, x0, y0 - 1) : ++- s->ref->refPicList; ++- int yp_pu = (y0 - 1) >> log2_min_pu_size; ++- int yq_pu = y0 >> log2_min_pu_size; ++- int yp_tu = (y0 - 1) >> log2_min_tu_size; ++- int yq_tu = y0 >> log2_min_tu_size; +++ rpl; +++ MvField *top = curr - min_pu_width; +++ +++ if (is_intra) { +++ for (i = 0; i < (1 << log2_trafo_size); i += 4) +++ bs[i >> 2] = 2; +++ +++ } else { +++ int y_tu = y0 >> log2_min_tu_size; +++ int x_tu = x0 >> log2_min_tu_size; +++ uint8_t *curr_cbf_luma = &s->cbf_luma[y_tu * min_tu_width + x_tu]; +++ uint8_t *top_cbf_luma = curr_cbf_luma - min_tu_width; +++ +++ s->hevcdsp.hevc_deblocking_boundary_strengths(trafo_in_min_pus, +++ min_pu_in_4pix, sizeof (MvField), 4 >> 2, +++ rpl[0].list, rpl[1].list, rpl_top[0].list, rpl_top[1].list, +++ curr, top, bs); ++ ++ for (i = 0; i < (1 << log2_trafo_size); i += 4) { ++- int x_pu = (x0 + i) >> log2_min_pu_size; ++- int x_tu = (x0 + i) >> log2_min_tu_size; ++- MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu]; ++- MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu]; ++- uint8_t top_cbf_luma = s->cbf_luma[yp_tu * min_tu_width + x_tu]; ++- uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + x_tu]; ++- ++- if (curr->pred_flag == PF_INTRA || top->pred_flag == PF_INTRA) ++- bs = 2; ++- else if (curr_cbf_luma || top_cbf_luma) ++- bs = 1; ++- else ++- bs = boundary_strength(s, curr, top, rpl_top); ++- s->horizontal_bs[((x0 + i) + y0 * s->bs_width) >> 2] = bs; +++ int i_pu = i >> log2_min_pu_size; +++ int i_tu = i >> log2_min_tu_size; +++ +++ if (top[i_pu].pred_flag == PF_INTRA) +++ bs[i >> 2] = 2; +++ else if (curr_cbf_luma[i_tu] || top_cbf_luma[i_tu]) +++ bs[i >> 2] = 1; ++ } +++ } +++ } +++ +++ if (!is_intra) { +++ for (j = inc; j < trafo_in_min_pus; j += inc) { +++ MvField *top; +++ +++ curr += min_pu_width * inc; +++ top = curr - min_pu_width; +++ bs += s->bs_width * inc << log2_min_pu_size >> 2; +++ +++ s->hevcdsp.hevc_deblocking_boundary_strengths(trafo_in_min_pus, +++ min_pu_in_4pix, sizeof (MvField), 4 >> 2, +++ rpl[0].list, rpl[1].list, rpl[0].list, rpl[1].list, +++ curr, top, bs); +++ } ++ } ++ ++- // bs for vertical TU boundaries ++ boundary_left = x0 > 0 && !(x0 & 7); ++ if (boundary_left && ++ ((!s->sh.slice_loop_filter_across_slices_enabled_flag && ++@@ -856,64 +822,54 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ (x0 % (1 << s->ps.sps->log2_ctb_size)) == 0))) ++ boundary_left = 0; ++ +++ curr = &tab_mvf[y_pu * min_pu_width + x_pu]; +++ bs = &s->vertical_bs[(x0 + y0 * s->bs_width) >> 2]; +++ ++ if (boundary_left) { ++ RefPicList *rpl_left = (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? ++ ff_hevc_get_ref_list(s, s->ref, x0 - 1, y0) : ++- s->ref->refPicList; ++- int xp_pu = (x0 - 1) >> log2_min_pu_size; ++- int xq_pu = x0 >> log2_min_pu_size; ++- int xp_tu = (x0 - 1) >> log2_min_tu_size; ++- int xq_tu = x0 >> log2_min_tu_size; ++- ++- for (i = 0; i < (1 << log2_trafo_size); i += 4) { ++- int y_pu = (y0 + i) >> log2_min_pu_size; ++- int y_tu = (y0 + i) >> log2_min_tu_size; ++- MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu]; ++- MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu]; ++- uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xp_tu]; ++- uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xq_tu]; ++- ++- if (curr->pred_flag == PF_INTRA || left->pred_flag == PF_INTRA) ++- bs = 2; ++- else if (curr_cbf_luma || left_cbf_luma) ++- bs = 1; ++- else ++- bs = boundary_strength(s, curr, left, rpl_left); ++- s->vertical_bs[(x0 + (y0 + i) * s->bs_width) >> 2] = bs; ++- } ++- } +++ rpl; +++ MvField *left = curr - 1; ++ ++- if (log2_trafo_size > log2_min_pu_size && !is_intra) { ++- RefPicList *rpl = s->ref->refPicList; +++ if (is_intra) { +++ for (j = 0; j < (1 << log2_trafo_size); j += 4) +++ bs[j * s->bs_width >> 2] = 2; ++ ++- // bs for TU internal horizontal PU boundaries ++- for (j = 8; j < (1 << log2_trafo_size); j += 8) { ++- int yp_pu = (y0 + j - 1) >> log2_min_pu_size; ++- int yq_pu = (y0 + j) >> log2_min_pu_size; ++- ++- for (i = 0; i < (1 << log2_trafo_size); i += 4) { ++- int x_pu = (x0 + i) >> log2_min_pu_size; ++- MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu]; ++- MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu]; ++- ++- bs = boundary_strength(s, curr, top, rpl); ++- s->horizontal_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs; +++ } else { +++ int y_tu = y0 >> log2_min_tu_size; +++ int x_tu = x0 >> log2_min_tu_size; +++ uint8_t *curr_cbf_luma = &s->cbf_luma[y_tu * min_tu_width + x_tu]; +++ uint8_t *left_cbf_luma = curr_cbf_luma - 1; +++ +++ s->hevcdsp.hevc_deblocking_boundary_strengths(trafo_in_min_pus, +++ min_pu_in_4pix, min_pu_width * sizeof (MvField), 4 * s->bs_width >> 2, +++ rpl[0].list, rpl[1].list, rpl_left[0].list, rpl_left[1].list, +++ curr, left, bs); +++ +++ for (j = 0; j < (1 << log2_trafo_size); j += 4) { +++ int j_pu = j >> log2_min_pu_size; +++ int j_tu = j >> log2_min_tu_size; +++ +++ if (left[j_pu * min_pu_width].pred_flag == PF_INTRA) +++ bs[j * s->bs_width >> 2] = 2; +++ else if (curr_cbf_luma[j_tu * min_tu_width] || left_cbf_luma[j_tu * min_tu_width]) +++ bs[j * s->bs_width >> 2] = 1; ++ } ++ } +++ } ++ ++- // bs for TU internal vertical PU boundaries ++- for (j = 0; j < (1 << log2_trafo_size); j += 4) { ++- int y_pu = (y0 + j) >> log2_min_pu_size; +++ if (!is_intra) { +++ for (i = inc; i < trafo_in_min_pus; i += inc) { +++ MvField *left; ++ ++- for (i = 8; i < (1 << log2_trafo_size); i += 8) { ++- int xp_pu = (x0 + i - 1) >> log2_min_pu_size; ++- int xq_pu = (x0 + i) >> log2_min_pu_size; ++- MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu]; ++- MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu]; +++ curr += inc; +++ left = curr - 1; +++ bs += inc << log2_min_pu_size >> 2; ++ ++- bs = boundary_strength(s, curr, left, rpl); ++- s->vertical_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs; ++- } +++ s->hevcdsp.hevc_deblocking_boundary_strengths(trafo_in_min_pus, +++ min_pu_in_4pix, min_pu_width * sizeof (MvField), 4 * s->bs_width >> 2, +++ rpl[0].list, rpl[1].list, rpl[0].list, rpl[1].list, +++ curr, left, bs); ++ } ++ } ++ } ++diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c ++index 9d773d9..a6534a9 100644 ++--- a/libavcodec/hevcdsp.c +++++ b/libavcodec/hevcdsp.c ++@@ -123,6 +123,120 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_filters[3][16]) = { ++ #include "hevcdsp_template.c" ++ #undef BIT_DEPTH ++ +++static void hevc_deblocking_boundary_strengths(int pus, int dup, int in_inc, int out_inc, +++ int *curr_rpl0, int *curr_rpl1, int *neigh_rpl0, int *neigh_rpl1, +++ MvField *curr, MvField *neigh, uint8_t *bs) +++{ +++ for (; pus > 0; pus--) { +++ int strength, out; +++ int curr_refL0 = curr_rpl0[curr->ref_idx[0]]; +++ int curr_refL1 = curr_rpl1[curr->ref_idx[1]]; +++ int neigh_refL0 = neigh_rpl0[neigh->ref_idx[0]]; +++ int neigh_refL1 = neigh_rpl1[neigh->ref_idx[1]]; +++ +++#if 1 // This more directly matches the original implementation +++ if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) { +++ // same L0 and L1 +++ if (curr_refL0 == neigh_refL0 && +++ curr_refL0 == curr_refL1 && +++ neigh_refL0 == neigh_refL1) { +++ if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || +++ FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) && +++ (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || +++ FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4)) +++ strength = 1; +++ else +++ strength = 0; +++ } else if (neigh_refL0 == curr_refL0 && +++ neigh_refL1 == curr_refL1) { +++ if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 || +++ FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) +++ strength = 1; +++ else +++ strength = 0; +++ } else if (neigh_refL1 == curr_refL0 && +++ neigh_refL0 == curr_refL1) { +++ if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 || +++ FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4) +++ strength = 1; +++ else +++ strength = 0; +++ } else { +++ strength = 1; +++ } +++ } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV +++ Mv curr_mv0, neigh_mv0; +++ +++ if (curr->pred_flag & 1) { +++ curr_mv0 = curr->mv[0]; +++ } else { +++ curr_mv0 = curr->mv[1]; +++ curr_refL0 = curr_refL1; +++ } +++ +++ if (neigh->pred_flag & 1) { +++ neigh_mv0 = neigh->mv[0]; +++ } else { +++ neigh_mv0 = neigh->mv[1]; +++ neigh_refL0 = neigh_refL1; +++ } +++ +++ if (curr_refL0 == neigh_refL0) { +++ if (FFABS(curr_mv0.x - neigh_mv0.x) >= 4 || FFABS(curr_mv0.y - neigh_mv0.y) >= 4) +++ strength = 1; +++ else +++ strength = 0; +++ } else +++ strength = 1; +++ } else +++ strength = 1; +++#else // This has exactly the same effect, but is more suitable for vectorisation +++ Mv curr_mv[2]; +++ Mv neigh_mv[2]; +++ memcpy(curr_mv, curr->mv, sizeof curr_mv); +++ memcpy(neigh_mv, neigh->mv, sizeof neigh_mv); +++ +++ if (!(curr->pred_flag & 2)) { +++ curr_mv[1] = curr_mv[0]; +++ curr_refL1 = curr_refL0; +++ } +++ if (!(neigh->pred_flag & 2)) { +++ neigh_mv[1] = neigh_mv[0]; +++ neigh_refL1 = neigh_refL0; +++ } +++ if (!(curr->pred_flag & 1)) { +++ curr_mv[0] = curr_mv[1]; +++ curr_refL0 = curr_refL1; +++ } +++ if (!(neigh->pred_flag & 1)) { +++ neigh_mv[0] = neigh_mv[1]; +++ neigh_refL0 = neigh_refL1; +++ } +++ +++ strength = 1; +++ +++ strength &= (neigh_refL0 != curr_refL0) | (neigh_refL1 != curr_refL1) | +++ (FFABS(neigh_mv[0].x - curr_mv[0].x) >= 4) | (FFABS(neigh_mv[0].y - curr_mv[0].y) >= 4) | +++ (FFABS(neigh_mv[1].x - curr_mv[1].x) >= 4) | (FFABS(neigh_mv[1].y - curr_mv[1].y) >= 4); +++ +++ strength &= (neigh_refL1 != curr_refL0) | (neigh_refL0 != curr_refL1) | +++ (FFABS(neigh_mv[1].x - curr_mv[0].x) >= 4) | (FFABS(neigh_mv[1].y - curr_mv[0].y) >= 4) | +++ (FFABS(neigh_mv[0].x - curr_mv[1].x) >= 4) | (FFABS(neigh_mv[0].y - curr_mv[1].y) >= 4); +++ +++ strength |= (((curr->pred_flag + 1) ^ (neigh->pred_flag + 1)) >> 2); +++#endif +++ +++ curr += in_inc / sizeof (MvField); +++ neigh += in_inc / sizeof (MvField); +++ +++ for (out = dup; out > 0; out--) +++ { +++ *bs = strength; +++ bs += out_inc; +++ } +++ } +++} +++ ++ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) ++ { ++ #undef FUNC ++@@ -257,6 +371,8 @@ int i = 0; ++ break; ++ } ++ +++ hevcdsp->hevc_deblocking_boundary_strengths = hevc_deblocking_boundary_strengths; +++ ++ if (ARCH_X86) ++ ff_hevc_dsp_init_x86(hevcdsp, bit_depth); ++ if (ARCH_ARM) ++diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h ++index 9f1f6dd..e221e54 100644 ++--- a/libavcodec/hevcdsp.h +++++ b/libavcodec/hevcdsp.h ++@@ -42,6 +42,17 @@ typedef struct SAOParams { ++ uint8_t type_idx[3]; ///< sao_type_idx ++ } SAOParams; ++ +++typedef struct Mv { +++ int16_t x; ///< horizontal component of motion vector +++ int16_t y; ///< vertical component of motion vector +++} Mv; +++ +++typedef struct MvField { +++ DECLARE_ALIGNED(4, Mv, mv)[2]; +++ int8_t ref_idx[2]; +++ int8_t pred_flag; +++} MvField; +++ ++ typedef struct HEVCDSPContext { ++ void (*put_pcm)(uint8_t *_dst, ptrdiff_t _stride, int width, int height, ++ struct GetBitContext *gb, int pcm_bit_depth); ++@@ -120,6 +131,9 @@ typedef struct HEVCDSPContext { ++ void (*hevc_v_loop_filter_chroma_c)(uint8_t *pix, ptrdiff_t stride, ++ int32_t *tc, uint8_t *no_p, ++ uint8_t *no_q); +++ void (*hevc_deblocking_boundary_strengths)(int pus, int dup, int in_inc, int out_inc, +++ int *curr_rpl0, int *curr_rpl1, int *neigh_rpl0, int *neigh_rpl1, +++ MvField *curr, MvField *neigh, uint8_t *bs); ++ } HEVCDSPContext; ++ ++ void ff_hevc_dsp_init(HEVCDSPContext *hpc, int bit_depth); ++-- ++2.5.0 ++ ++ ++From 50c89ce45ad633db0a48f084d5ecae0ae989e704 Mon Sep 17 00:00:00 2001 ++From: Peter de Rivaz ++Date: Wed, 15 Jul 2015 09:09:11 +0100 ++Subject: [PATCH 68/68] Only enable qpu when needed ++ ++--- ++ libavcodec/hevc.h | 2 +- ++ libavcodec/rpi_qpu.c | 21 ++++++++++++++++----- ++ 2 files changed, 17 insertions(+), 6 deletions(-) ++ ++diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h ++index cfa7c61..cb4350d 100644 ++--- a/libavcodec/hevc.h +++++ b/libavcodec/hevc.h ++@@ -56,7 +56,7 @@ ++ // Define RPI_WORKER to launch a worker thread for pixel processing tasks ++ #define RPI_WORKER ++ // Define RPI_DEBLOCK_VPU to perform deblocking on the VPUs ++- #define RPI_DEBLOCK_VPU +++ //#define RPI_DEBLOCK_VPU ++ ++ #endif ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index 5aa0432..ffd13ca 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -9,7 +9,7 @@ ++ // define RPI_ASYNC to run the VPU in a separate thread, need to make a separate call to check for completion ++ #define RPI_ASYNC ++ // Define RPI_COMBINE_JOBS to find jobs that can be executed in parallel ++-#define RPI_COMBINE_JOBS +++//#define RPI_COMBINE_JOBS ++ ++ #include ++ #include ++@@ -143,9 +143,9 @@ static int gpu_init(volatile struct GPU **gpu) { ++ volatile struct GPU* ptr; ++ if (mb < 0) ++ return -1; ++- +++#ifndef RPI_ASYNC ++ if (qpu_enable(mb, 1)) return -2; ++- +++#endif ++ vcsm_init(); ++ gpu_malloc_uncached_internal(sizeof(struct GPU), &gpu_mem_ptr, mb); ++ ptr = (volatile struct GPU*)gpu_mem_ptr.arm; ++@@ -336,9 +336,9 @@ static void gpu_term(void) ++ vpu_post_code(0, 0, 0, 0, 0, 0, -1, NULL); ++ pthread_join(vpu_thread, &res); ++ } ++-#endif ++- +++#else ++ qpu_enable(mb, 0); +++#endif ++ gpu_free_internal(&gpu_mem_ptr); ++ ++ vcsm_exit(); ++@@ -400,6 +400,7 @@ static void *vpu_start(void *arg) { ++ int count_deblock=0; ++ int count_qpu=0; ++ #endif +++ int qpu_started = 0; ++ while(1) { ++ int i; ++ int *p; // Pointer for a QPU/VPU job ++@@ -427,6 +428,12 @@ static void *vpu_start(void *arg) { ++ if (p[7] == 0 && p[0] == 0 && p[16]==0) ++ goto job_done_early; ++ +++ if (!qpu_started) { +++ int result = qpu_enable(gpu->mb, 1); +++ av_assert0(result==0); +++ qpu_started = 1; +++ } +++ ++ #ifdef RPI_COMBINE_JOBS ++ // First scan for a qpu job ++ for (int x=0;xmb, 0); +++ } +++ ++ return NULL; ++ } ++ ++-- ++2.5.0 ++ ++From 544f5eb0b6f8cc1ad316a94cae5e78eadf2e1ec9 Mon Sep 17 00:00:00 2001 ++From: John Cox ++Date: Tue, 9 Feb 2016 11:57:40 +0000 ++Subject: [PATCH 1/2] Zero copy code v6 ++ ++This version has GPU buffer pooling code ++--- ++ ffmpeg.c | 123 +++++++++----- ++ libavcodec/Makefile | 2 + ++ libavcodec/avcodec.h | 6 + ++ libavcodec/hevc.c | 92 ++++++----- ++ libavcodec/hevc_filter.c | 83 +++++----- ++ libavcodec/rpi_qpu.c | 2 +- ++ libavcodec/rpi_qpu.h | 109 ++++++++++++- ++ libavcodec/rpi_zc.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++ ++ libavcodec/rpi_zc.h | 83 ++++++++++ ++ 9 files changed, 779 insertions(+), 127 deletions(-) ++ create mode 100644 libavcodec/rpi_zc.c ++ create mode 100644 libavcodec/rpi_zc.h ++ ++diff --git a/ffmpeg.c b/ffmpeg.c ++index 8828f48..36dc1a3 100644 ++--- a/ffmpeg.c +++++ b/ffmpeg.c ++@@ -25,7 +25,7 @@ ++ ++ #ifdef RPI ++ #define RPI_DISPLAY ++-//#define RPI_ZERO_COPY +++#define RPI_ZERO_COPY ++ #endif ++ ++ #include "config.h" ++@@ -80,9 +80,7 @@ ++ #include ++ #include ++ #include ++-#ifdef RPI_ZERO_COPY ++-#include "libavcodec/rpi_qpu.h" ++-#endif +++#include "libavcodec/rpi_zc.h" ++ #endif ++ ++ #if HAVE_SYS_RESOURCE_H ++@@ -183,13 +181,7 @@ static void free_input_threads(void); ++ ++ static MMAL_COMPONENT_T* rpi_display = NULL; ++ static MMAL_POOL_T *rpi_pool = NULL; ++- ++-#ifdef RPI_ZERO_COPY ++-static uint8_t *get_vc_handle(AVBufferRef *bref) { ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++- return (uint8_t *)p->vc_handle; ++-} ++-#endif +++static volatile int rpi_display_count = 0; ++ ++ static MMAL_POOL_T* display_alloc_pool(MMAL_PORT_T* port, size_t w, size_t h) ++ { ++@@ -206,7 +198,7 @@ static MMAL_POOL_T* display_alloc_pool(MMAL_PORT_T* port, size_t w, size_t h) ++ for (i = 0; i < NUM_BUFFERS; ++i) ++ { ++ MMAL_BUFFER_HEADER_T* buffer = pool->header[i]; ++- void* bufPtr = buffer->data; +++ char * bufPtr = buffer->data; ++ memset(bufPtr, i*30, w*h); ++ memset(bufPtr+w*h, 128, (w*h)/2); ++ } ++@@ -215,23 +207,31 @@ static MMAL_POOL_T* display_alloc_pool(MMAL_PORT_T* port, size_t w, size_t h) ++ return pool; ++ } ++ ++-static void display_cb_input(MMAL_PORT_T *port,MMAL_BUFFER_HEADER_T *buffer) { +++static void display_cb_input(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { +++#ifdef RPI_ZERO_COPY +++ av_rpi_zc_unref(buffer->user_data); +++ --rpi_display_count; +++#endif +++ mmal_buffer_header_release(buffer); +++} +++ +++static void display_cb_control(MMAL_PORT_T *port,MMAL_BUFFER_HEADER_T *buffer) { ++ mmal_buffer_header_release(buffer); ++ } ++ ++ static MMAL_COMPONENT_T* display_init(size_t x, size_t y, size_t w, size_t h) ++ { ++ MMAL_COMPONENT_T* display; ++- int w2 = (w+31)&~31; ++- int h2 = (h+15)&~15; ++ MMAL_DISPLAYREGION_T region = ++ { ++- {MMAL_PARAMETER_DISPLAYREGION, sizeof(region)}, +++ .hdr = {MMAL_PARAMETER_DISPLAYREGION, sizeof(region)}, ++ .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_FULLSCREEN | MMAL_DISPLAY_SET_DEST_RECT, ++ .layer = 2, ++ .fullscreen = 0, ++ .dest_rect = {x, y, w, h} ++ }; +++ const AVRpiZcFrameGeometry geo = av_rpi_zc_frame_geometry(w, h); +++ ++ bcm_host_init(); // TODO is this needed? ++ mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &display); ++ assert(display); ++@@ -240,8 +240,8 @@ static MMAL_COMPONENT_T* display_init(size_t x, size_t y, size_t w, size_t h) ++ ++ MMAL_ES_FORMAT_T* format = display->input[0]->format; ++ format->encoding = MMAL_ENCODING_I420; ++- format->es->video.width = w2; ++- format->es->video.height = h2; +++ format->es->video.width = geo.stride_y; +++ format->es->video.height = geo.height_y; ++ format->es->video.crop.x = 0; ++ format->es->video.crop.y = 0; ++ format->es->video.crop.width = w; ++@@ -250,46 +250,75 @@ static MMAL_COMPONENT_T* display_init(size_t x, size_t y, size_t w, size_t h) ++ ++ mmal_component_enable(display); ++ ++- rpi_pool = display_alloc_pool(display->input[0], w2, h2); +++ rpi_pool = display_alloc_pool(display->input[0], geo.stride_y, geo.height_y); ++ ++ mmal_port_enable(display->input[0],display_cb_input); ++- mmal_port_enable(display->control,display_cb_input); +++ mmal_port_enable(display->control,display_cb_control); ++ ++- printf("Allocated display %d %d\n",w,h); +++ printf("Allocated display %dx%d in %dx%d\n", w, h, geo.stride_y, geo.height_y); ++ ++ return display; ++ } ++ ++-static void display_frame(MMAL_COMPONENT_T* display,AVFrame* fr) +++static void display_frame(struct AVCodecContext * const s, MMAL_COMPONENT_T* const display, const AVFrame* const fr) ++ { ++- int w = fr->width; ++- int h = fr->height; ++- int w2 = (w+31)&~31; ++- int h2 = (h+15)&~15; ++ if (!display || !rpi_pool) ++ return; +++ +++ if (rpi_display_count >= 3) { +++ av_log(s, AV_LOG_VERBOSE, "Frame dropped\n"); +++ return; +++ } +++ ++ MMAL_BUFFER_HEADER_T* buf = mmal_queue_get(rpi_pool->queue); ++ if (!buf) { ++- // Running too fast so drop the frame ++- return; +++ // Running too fast so drop the frame +++ printf("Q alloc failure\n"); +++ return; ++ } ++ assert(buf); ++ buf->cmd = 0; ++- buf->length = (w2 * h2 * 3)/2; ++ buf->offset = 0; // Offset to valid data ++ buf->flags = 0; ++ #ifdef RPI_ZERO_COPY ++- buf->data = get_vc_handle(fr->buf[0]); ++- buf->alloc_size = (w2*h2*3)/2; +++{ +++ const AVRpiZcRefPtr fr_buf = av_rpi_zc_ref(s, fr, 1); +++ +++ buf->user_data = fr_buf; +++ buf->data = av_rpi_zc_vc_handle(fr_buf); +++ buf->alloc_size = +++ buf->length = av_rpi_zc_numbytes(fr_buf); +++ +++ ++rpi_display_count; +++} ++ #else +++{ +++#error YYY +++ int w = fr->width; +++ int h = fr->height; +++ int w2 = (w+31)&~31; +++ int h2 = (h+15)&~15; +++ +++ buf->length = (w2 * h2 * 3)/2; +++ buf->user_data = NULL; +++ ++ //mmal_buffer_header_mem_lock(buf); ++ memcpy(buf->data, fr->data[0], w2 * h); ++ memcpy(buf->data+w2*h2, fr->data[1], w2 * h / 4); ++ memcpy(buf->data+w2*h2*5/4, fr->data[2], w2 * h / 4); ++ //mmal_buffer_header_mem_unlock(buf); +++} ++ #endif ++ ++- mmal_port_send_buffer(display->input[0], buf); // I assume this will automatically get released +++ while (rpi_display_count >= 3) { +++ usleep(5000); +++ } +++ +++ if (mmal_port_send_buffer(display->input[0], buf) != MMAL_SUCCESS) +++ { +++ printf("** send failed: depth=%d\n", rpi_display_count); +++ display_cb_input(NULL, buf); +++ } ++ } ++ ++ static void display_exit(MMAL_COMPONENT_T* display) ++@@ -687,6 +716,11 @@ static void ffmpeg_cleanup(int ret) ++ avformat_close_input(&input_files[i]->ctx); ++ av_freep(&input_files[i]); ++ } +++ +++#ifdef RPI_DISPLAY +++ display_exit(rpi_display); +++#endif +++ ++ for (i = 0; i < nb_input_streams; i++) { ++ InputStream *ist = input_streams[i]; ++ ++@@ -698,6 +732,9 @@ static void ffmpeg_cleanup(int ret) ++ av_freep(&ist->filters); ++ av_freep(&ist->hwaccel_device); ++ +++#ifdef RPI_ZERO_COPY +++ av_rpi_zc_uninit(ist->dec_ctx); +++#endif ++ avcodec_free_context(&ist->dec_ctx); ++ ++ av_freep(&input_streams[i]); ++@@ -729,9 +766,6 @@ static void ffmpeg_cleanup(int ret) ++ term_exit(); ++ ffmpeg_exited = 1; ++ ++-#ifdef RPI_DISPLAY ++- display_exit(rpi_display); ++-#endif ++ } ++ ++ void remove_avoptions(AVDictionary **a, AVDictionary *b) ++@@ -1079,18 +1113,19 @@ static void do_video_out(AVFormatContext *s, ++ int frame_size = 0; ++ InputStream *ist = NULL; ++ AVFilterContext *filter = ost->filter->filter; +++ +++ if (ost->source_index >= 0) +++ ist = input_streams[ost->source_index]; +++ ++ #ifdef RPI_DISPLAY ++- if (next_picture) +++ if (next_picture && ist != NULL) ++ { ++- if (!rpi_display) +++ if (!rpi_display) ++ rpi_display = display_init(0,0,next_picture->width,next_picture->height); ++- display_frame(rpi_display,next_picture); +++ display_frame(ist->dec_ctx, rpi_display, next_picture); ++ } ++ #endif ++ ++- if (ost->source_index >= 0) ++- ist = input_streams[ost->source_index]; ++- ++ if (filter->inputs[0]->frame_rate.num > 0 && ++ filter->inputs[0]->frame_rate.den > 0) ++ duration = 1/(av_q2d(filter->inputs[0]->frame_rate) * av_q2d(enc->time_base)); ++@@ -2692,6 +2727,12 @@ static int init_input_stream(int ist_index, char *error, int error_len) ++ ist->dec_ctx->opaque = ist; ++ ist->dec_ctx->get_format = get_format; ++ ist->dec_ctx->get_buffer2 = get_buffer; +++ +++#ifdef RPI_ZERO_COPY +++ // Overrides the above get_buffer2 +++ av_rpi_zc_init(ist->dec_ctx); +++#endif +++ ++ ist->dec_ctx->thread_safe_callbacks = 1; ++ ++ av_opt_set_int(ist->dec_ctx, "refcounted_frames", 1, 0); ++diff --git a/libavcodec/Makefile b/libavcodec/Makefile ++index 0fd6767..bae3f2d 100644 ++--- a/libavcodec/Makefile +++++ b/libavcodec/Makefile ++@@ -9,6 +9,7 @@ HEADERS = avcodec.h \ ++ rpi_shader.h \ ++ rpi_mailbox.h \ ++ rpi_hevc_transform.h \ +++ rpi_zc.h \ ++ dv_profile.h \ ++ d3d11va.h \ ++ dirac.h \ ++@@ -46,6 +47,7 @@ OBJS = allcodecs.o \ ++ rpi_qpu.o \ ++ rpi_shader.o \ ++ rpi_mailbox.o \ +++ rpi_zc.o \ ++ vorbis_parser.o \ ++ xiph.o \ ++ ++diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h ++index d849765..b934740 100644 ++--- a/libavcodec/avcodec.h +++++ b/libavcodec/avcodec.h ++@@ -3355,6 +3355,12 @@ typedef struct AVCodecContext { ++ AVPacketSideData *coded_side_data; ++ int nb_coded_side_data; ++ +++ /** +++ * Opaque pointer for use by replacement get_buffer2 code +++ * +++ * @author jc (08/02/2016) +++ */ +++ void * get_buffer_context; ++ } AVCodecContext; ++ ++ AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); ++diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c ++index 35a1394..001c9e8 100644 ++--- a/libavcodec/hevc.c +++++ b/libavcodec/hevc.c ++@@ -114,10 +114,6 @@ static uint32_t rpi_filter_coefs[8][1] = { ++ { ENCODE_COEFFS( -2, 10, 58, -2) } ++ }; ++ ++-static uint32_t get_vc_address(AVBufferRef *bref) { ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++- return p->vc; ++-} ++ #endif ++ ++ ++@@ -2186,9 +2182,9 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int bw = nPbW-start_x; ++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref0->frame); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref0->frame); ++ *y++ = ( (bw<16 ? bw : 16) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ if (weight_flag) { ++@@ -2196,7 +2192,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ } else { ++ *y++ = 1; // Weight of 1 and offset of 0 ++ } ++- *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ *y++ = (get_vc_address_y(s->frame) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++@@ -2235,8 +2231,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_u(ref0->frame); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_v(ref0->frame); ++ *u++ = ( (bwframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++- *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ *u++ = (get_vc_address_u(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address_v(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++ s->curr_u_mvs = u; ++@@ -2286,9 +2282,9 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int bw = nPbW-start_x; ++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref1->frame); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + 8 + start_x) & 0xffff); ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref1->frame); ++ *y++ = ( (bw<16 ? bw : 16) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ if (weight_flag) { ++@@ -2296,7 +2292,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ } else { ++ *y++ = 1; // Weight of 1 and offset of 0 ++ } ++- *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ *y++ = (get_vc_address_y(s->frame) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter; ++ } ++ } ++@@ -2336,8 +2332,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_u(ref1->frame); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_v(ref1->frame); ++ *u++ = ( (bwsh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0] ++ *u++ = rpi_filter_coefs[_mx][0]; ++@@ -2349,8 +2345,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ *u++ = 1; // Weight of 1 and offset of 0 ++ *u++ = 1; ++ } ++- *u++ = (get_vc_address(s->frame->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++- *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ *u++ = (get_vc_address_u(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address_v(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++ s->curr_u_mvs = u; ++@@ -2392,13 +2388,13 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int bw = nPbW-start_x; ++ int bh = nPbH-start_y; ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y1 - 3 + start_y) << 16) + ( (x1 - 3 + start_x) & 0xffff); ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref0->frame); ++ y++[-RPI_LUMA_COMMAND_WORDS] = ((y2 - 3 + start_y) << 16) + ( (x2 - 3 + start_x) & 0xffff); // Second fetch is for ref1 ++- y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[0]); +++ y++[-RPI_LUMA_COMMAND_WORDS] = get_vc_address_y(ref1->frame); ++ *y++ = ( (bw<8 ? bw : 8) << 16 ) + (bh<16 ? bh : 16); ++ *y++ = my2_mx2_my_mx; ++ *y++ = 1; // B frame weighted prediction not supported ++- *y++ = (get_vc_address(s->frame->buf[0]) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); +++ *y++ = (get_vc_address_y(s->frame) + x0 + start_x + (start_y + y0) * s->frame->linesize[0]); ++ y++[-RPI_LUMA_COMMAND_WORDS] = s->mc_filter_b; ++ } ++ } ++@@ -2442,8 +2438,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ u++[-RPI_CHROMA_COMMAND_WORDS] = s->mc_filter_uv_b0; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x1_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y1_c - 1 + start_y; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[1]); ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref0->frame->buf[2]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_u(ref0->frame); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_v(ref0->frame); ++ *u++ = ( (bwmc_filter_uv_b; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = x2_c - 1 + start_x; ++ u++[-RPI_CHROMA_COMMAND_WORDS] = y2_c - 1 + start_y; ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[1]); ++- u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address(ref1->frame->buf[2]); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_u(ref1->frame); +++ u++[-RPI_CHROMA_COMMAND_WORDS] = get_vc_address_v(ref1->frame); ++ *u++ = ( (bwframe->buf[1]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); ++- *u++ = (get_vc_address(s->frame->buf[2]) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); +++ *u++ = (get_vc_address_u(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[1]); +++ *u++ = (get_vc_address_v(s->frame) + x0_c + start_x + (start_y + y0_c) * s->frame->linesize[2]); ++ } ++ } ++ s->curr_u_mvs = u; ++@@ -3259,12 +3255,13 @@ static int32_t filter8_luma(uint8_t *data, int x0, int y0, int pitch, int my_mx, ++ return vsum; ++ } ++ ++-static uint8_t *test_frame(HEVCContext *s,uint32_t p, AVFrame *frame, int cIdx) +++static uint8_t *test_frame(HEVCContext *s,uint32_t p, AVFrame *frame, const int cIdx) ++ { ++ //int pic_width = s->ps.sps->width >> s->ps.sps->hshift[cIdx]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[cIdx]; ++ int pitch = frame->linesize[cIdx]; ++- uint32_t base = get_vc_address(frame->buf[cIdx]); +++ uint32_t base = c_idx == 0 ? get_vc_address_y(frame); +++ c_idx == 1 ? get_vc_address_u(frame) : get_vc_address_v(frame); ++ if (p>=base && pdata[cIdx] + (p-base); ++ } ++@@ -3551,6 +3548,7 @@ static void rpi_launch_vpu_qpu(HEVCContext *s) ++ #ifdef RPI ++ ++ #ifndef RPI_FAST_CACHEFLUSH +++#error RPI_FAST_CACHEFLUSH is broken ++ static void flush_buffer(AVBufferRef *bref) { ++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++ gpu_cache_flush(p); ++@@ -3561,7 +3559,7 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ { ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); +++ GPU_MEM_PTR_T p = get_gpu_mem_ptr_u(s->frame); ++ int n = s->ps.sps->height; ++ int curr_y = 0; ++ int curr_uv = 0; ++@@ -3569,21 +3567,21 @@ static void flush_frame(HEVCContext *s,AVFrame *frame) ++ int sz,base; ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].handle = p.vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = (int)(p->arm) + base; +++ iocache.s[0].addr = (int)(p.arm) + base; ++ iocache.s[0].size = sz; ++- p = av_buffer_pool_opaque(frame->buf[2]); ++- iocache.s[1].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_v(s->frame); +++ iocache.s[1].handle = p.vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = (int)(p->arm) + base; +++ iocache.s[1].addr = (int)(p.arm) + base; ++ iocache.s[1].size = sz; ++- p = av_buffer_pool_opaque(frame->buf[0]); +++ p = get_gpu_mem_ptr_y(s->frame); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++- iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].handle = p.vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = (int)(p->arm) + base; +++ iocache.s[2].addr = (int)(p.arm) + base; ++ iocache.s[2].size = sz; ++ vcsm_clean_invalid( &iocache ); ++ #else ++@@ -3601,7 +3599,7 @@ static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM ++ int curr_y; ++ int curr_uv; ++ int n_uv; ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); +++ GPU_MEM_PTR_T p = get_gpu_mem_ptr_u(s->frame); ++ int sz,base; ++ int (*d)[2] = s->dblk_cmds[job]; ++ int low=(*d)[1]; ++@@ -3618,21 +3616,21 @@ static void flush_frame3(HEVCContext *s,AVFrame *frame,GPU_MEM_PTR_T *p0,GPU_MEM ++ ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- iocache.s[0].handle = p->vcsm_handle; +++ iocache.s[0].handle = p.vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = (int)(p->arm) + base; +++ iocache.s[0].addr = (int)(p.arm) + base; ++ iocache.s[0].size = sz; ++- p = av_buffer_pool_opaque(frame->buf[2]); ++- iocache.s[1].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_v(s->frame); +++ iocache.s[1].handle = p.vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = (int)(p->arm) + base; +++ iocache.s[1].addr = (int)(p.arm) + base; ++ iocache.s[1].size = sz; ++- p = av_buffer_pool_opaque(frame->buf[0]); +++ p = get_gpu_mem_ptr_y(s->frame); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++- iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].handle = p.vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = (int)(p->arm) + base; +++ iocache.s[2].addr = (int)(p.arm) + base; ++ iocache.s[2].size = sz; ++ ++ iocache.s[3].handle = p0->vcsm_handle; ++diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c ++index 826a82f..c4fa305 100644 ++--- a/libavcodec/hevc_filter.c +++++ b/libavcodec/hevc_filter.c ++@@ -879,17 +879,25 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, ++ #undef CR ++ ++ #ifdef RPI_INTER_QPU ++-static void flush_buffer(AVBufferRef *bref) { ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++- gpu_cache_flush(p); +++static void flush_buffer_y(const AVFrame * const frame) { +++ GPU_MEM_PTR_T p = get_gpu_mem_ptr_y(frame); +++ gpu_cache_flush(&p); ++ } ++ ++-// Return Physical address for this image ++-static uint32_t get_vc_address(AVBufferRef *bref) { ++- GPU_MEM_PTR_T *p = av_buffer_pool_opaque(bref); ++- return p->vc; +++static void flush_buffer_u(const AVFrame * const frame) { +++ GPU_MEM_PTR_T p = get_gpu_mem_ptr_u(frame); +++ gpu_cache_flush(&p); ++ } ++ +++static void flush_buffer_v(const AVFrame * const frame) { +++ GPU_MEM_PTR_T p = get_gpu_mem_ptr_v(frame); +++ gpu_cache_flush(&p); +++} +++ +++ +++#ifdef RPI_DEBLOCK_VPU +++#error Not fixed yet +++ ++ // ff_hevc_flush_buffer_lines ++ // flushes and invalidates all pixel rows in [start,end-1] ++ static void ff_hevc_flush_buffer_lines(HEVCContext *s, int start, int end, int flush_luma, int flush_chroma) ++@@ -901,44 +909,44 @@ static void ff_hevc_flush_buffer_lines(HEVCContext *s, int start, int end, int f ++ int curr_uv = curr_y >> s->ps.sps->vshift[1]; ++ int n_uv = n >> s->ps.sps->vshift[1]; ++ int sz,base; ++- GPU_MEM_PTR_T *p; +++ GPU_MEM_PTR_T p; ++ if (curr_uv < 0) curr_uv = 0; ++ if (n_uv<=curr_uv) { return; } ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++ if (flush_chroma) { ++- p = av_buffer_pool_opaque(s->frame->buf[1]); ++- iocache.s[0].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_u(s->frame); +++ iocache.s[0].handle = p.vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = (int)p->arm + base; +++ iocache.s[0].addr = (int)p.arm + base; ++ iocache.s[0].size = sz; ++- p = av_buffer_pool_opaque(s->frame->buf[2]); ++- iocache.s[1].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_v(s->frame); +++ iocache.s[1].handle = p.vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = (int)p->arm + base; +++ iocache.s[1].addr = (int)p.arm + base; ++ iocache.s[1].size = sz; ++ } ++ if (flush_luma) { ++- p = av_buffer_pool_opaque(s->frame->buf[0]); +++ p = get_gpu_mem_ptr_y(s->frame); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++- iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].handle = p.vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = (int)p->arm + base; +++ iocache.s[2].addr = (int)p.arm + base; ++ iocache.s[2].size = sz; ++ } ++ vcsm_clean_invalid( &iocache ); ++ #else ++ if (flush_chroma) { ++- flush_buffer(s->frame->buf[1]); ++- flush_buffer(s->frame->buf[2]); +++ flush_buffer_u(s->frame); +++ flush_buffer_v(s->frame); ++ } ++ if (flush_luma) { ++- flush_buffer(s->frame->buf[0]); +++ flush_buffer_y(s->frame); ++ } ++ #endif ++ } ++- +++#endif ++ ++ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ { ++@@ -950,37 +958,37 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ int curr_uv = curr_y >> s->ps.sps->vshift[1]; ++ int n_uv = n >> s->ps.sps->vshift[1]; ++ int sz,base; ++- GPU_MEM_PTR_T *p; +++ GPU_MEM_PTR_T p; ++ if (curr_uv < 0) curr_uv = 0; ++ if (n_uv<=curr_uv) { return; } ++ sz = s->frame->linesize[1] * (n_uv-curr_uv); ++ base = s->frame->linesize[1] * curr_uv; ++- p = av_buffer_pool_opaque(s->frame->buf[1]); ++- iocache.s[0].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_u(s->frame); +++ iocache.s[0].handle = p.vcsm_handle; ++ iocache.s[0].cmd = 3; // clean+invalidate ++- iocache.s[0].addr = (int)p->arm + base; +++ iocache.s[0].addr = (int)p.arm + base; ++ iocache.s[0].size = sz; ++- p = av_buffer_pool_opaque(s->frame->buf[2]); ++- iocache.s[1].handle = p->vcsm_handle; +++ p = get_gpu_mem_ptr_v(s->frame); +++ iocache.s[1].handle = p.vcsm_handle; ++ iocache.s[1].cmd = 3; // clean+invalidate ++- iocache.s[1].addr = (int)p->arm + base; +++ iocache.s[1].addr = (int)p.arm + base; ++ iocache.s[1].size = sz; ++ ++ #ifdef RPI_LUMA_QPU ++- p = av_buffer_pool_opaque(s->frame->buf[0]); +++ p = get_gpu_mem_ptr_y(s->frame); ++ sz = s->frame->linesize[0] * (n-curr_y); ++ base = s->frame->linesize[0] * curr_y; ++- iocache.s[2].handle = p->vcsm_handle; +++ iocache.s[2].handle = p.vcsm_handle; ++ iocache.s[2].cmd = 3; // clean+invalidate ++- iocache.s[2].addr = (int)p->arm + base; +++ iocache.s[2].addr = (int)p.arm + base; ++ iocache.s[2].size = sz; ++ #endif ++ vcsm_clean_invalid( &iocache ); ++ #else ++- flush_buffer(s->frame->buf[1]); ++- flush_buffer(s->frame->buf[2]); +++ flush_buffer_u(s->frame); +++ flush_buffer_v(s->frame); ++ #ifdef RPI_LUMA_QPU ++- flush_buffer(s->frame->buf[0]); +++ flush_buffer_y(s->frame); ++ #endif ++ ++ #endif ++@@ -992,6 +1000,7 @@ void ff_hevc_flush_buffer(HEVCContext *s, ThreadFrame *f, int n) ++ #endif ++ ++ #ifdef RPI_DEBLOCK_VPU +++#error XXX ++ /* rpi_deblock deblocks an entire row of ctbs using the VPU */ ++ static void rpi_deblock(HEVCContext *s, int y, int ctb_size) ++ { ++@@ -1000,21 +1009,21 @@ static void rpi_deblock(HEVCContext *s, int y, int ctb_size) ++ // TODO flush buffer of beta/tc setup when it becomes cached ++ ++ // Prepare three commands at once to avoid calling overhead ++- s->vpu_cmds_arm[0][0] = get_vc_address(s->frame->buf[0]) + s->frame->linesize[0] * y; +++ s->vpu_cmds_arm[0][0] = get_vc_address_y(s->frame) + s->frame->linesize[0] * y; ++ s->vpu_cmds_arm[0][1] = s->frame->linesize[0]; ++ s->vpu_cmds_arm[0][2] = s->setup_width; ++ s->vpu_cmds_arm[0][3] = (int) ( s->y_setup_vc + s->setup_width * (y>>4) ); ++ s->vpu_cmds_arm[0][4] = ctb_size>>4; ++ s->vpu_cmds_arm[0][5] = 2; ++ ++- s->vpu_cmds_arm[1][0] = get_vc_address(s->frame->buf[1]) + s->frame->linesize[1] * (y>> s->ps.sps->vshift[1]); +++ s->vpu_cmds_arm[1][0] = get_vc_address_u(s->frame) + s->frame->linesize[1] * (y>> s->ps.sps->vshift[1]); ++ s->vpu_cmds_arm[1][1] = s->frame->linesize[1]; ++ s->vpu_cmds_arm[1][2] = s->uv_setup_width; ++ s->vpu_cmds_arm[1][3] = (int) ( s->uv_setup_vc + s->uv_setup_width * ((y>>4)>> s->ps.sps->vshift[1]) ); ++ s->vpu_cmds_arm[1][4] = (ctb_size>>4)>> s->ps.sps->vshift[1]; ++ s->vpu_cmds_arm[1][5] = 3; ++ ++- s->vpu_cmds_arm[2][0] = get_vc_address(s->frame->buf[2]) + s->frame->linesize[2] * (y>> s->ps.sps->vshift[2]); +++ s->vpu_cmds_arm[2][0] = get_vc_address_v(s->frame) + s->frame->linesize[2] * (y>> s->ps.sps->vshift[2]); ++ s->vpu_cmds_arm[2][1] = s->frame->linesize[2]; ++ s->vpu_cmds_arm[2][2] = s->uv_setup_width; ++ s->vpu_cmds_arm[2][3] = (int) ( s->uv_setup_vc + s->uv_setup_width * ((y>>4)>> s->ps.sps->vshift[1]) ); ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index ffd13ca..b0c9bc5 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -250,7 +250,7 @@ int gpu_get_mailbox(void) ++ } ++ ++ // Call this to clean and invalidate a region of memory ++-void gpu_cache_flush(GPU_MEM_PTR_T *p) +++void gpu_cache_flush(const GPU_MEM_PTR_T * const p) ++ { ++ #ifdef RPI_FAST_CACHEFLUSH ++ struct vcsm_user_clean_invalid_s iocache = {}; ++diff --git a/libavcodec/rpi_qpu.h b/libavcodec/rpi_qpu.h ++index 81c2bb1..b913f79 100644 ++--- a/libavcodec/rpi_qpu.h +++++ b/libavcodec/rpi_qpu.h ++@@ -2,8 +2,11 @@ ++ #define RPI_QPU_H ++ ++ // Define RPI_FAST_CACHEFLUSH to use the VCSM cache flush code +++// *** N.B. Code has rotted & crashes if this is unset (before this set of changes) ++ #define RPI_FAST_CACHEFLUSH ++ +++#define RPI_ONE_BUF 1 +++ ++ typedef struct gpu_mem_ptr_s { ++ unsigned char *arm; // Pointer to memory mapped on ARM side ++ int vc_handle; // Videocore handle of relocatable memory ++@@ -16,9 +19,113 @@ typedef struct gpu_mem_ptr_s { ++ extern int gpu_malloc_cached(int numbytes, GPU_MEM_PTR_T *p); ++ extern int gpu_malloc_uncached(int numbytes, GPU_MEM_PTR_T *p); ++ extern void gpu_free(GPU_MEM_PTR_T *p); ++-extern void gpu_cache_flush(GPU_MEM_PTR_T *p); +++extern void gpu_cache_flush(const GPU_MEM_PTR_T * const p); ++ extern void gpu_cache_flush3(GPU_MEM_PTR_T *p0,GPU_MEM_PTR_T *p1,GPU_MEM_PTR_T *p2); ++ +++#include "libavutil/frame.h" +++#if !RPI_ONE_BUF +++static inline uint32_t get_vc_address_y(const AVFrame * const frame) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[0]); +++ return p->vc; +++} +++ +++static inline uint32_t get_vc_address_u(const AVFrame * const frame) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[1]); +++ return p->vc; +++} +++ +++static inline uint32_t get_vc_address_v(const AVFrame * const frame) { +++ GPU_MEM_PTR_T *p = av_buffer_pool_opaque(frame->buf[2]); +++ return p->vc; +++} +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_y(const AVFrame * const frame) { +++ return *(GPU_MEM_PTR_T *)av_buffer_pool_opaque(frame->buf[0]); +++} +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_u(const AVFrame * const frame) { +++ return *(GPU_MEM_PTR_T *)av_buffer_pool_opaque(frame->buf[1]); +++} +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_v(const AVFrame * const frame) { +++ return *(GPU_MEM_PTR_T *)av_buffer_pool_opaque(frame->buf[2]); +++} +++ +++#else +++ +++static inline int gpu_is_buf1(const AVFrame * const frame) +++{ +++ return frame->buf[1] == NULL; +++} +++ +++static inline GPU_MEM_PTR_T * gpu_buf1_gmem(const AVFrame * const frame) +++{ +++ return av_buffer_get_opaque(frame->buf[0]); +++} +++ +++static inline GPU_MEM_PTR_T * gpu_buf3_gmem(const AVFrame * const frame, const int n) +++{ +++ return av_buffer_pool_opaque(frame->buf[n]); +++} +++ +++ +++static inline uint32_t get_vc_address_y(const AVFrame * const frame) { +++ return gpu_is_buf1(frame) ? gpu_buf1_gmem(frame)->vc : gpu_buf3_gmem(frame, 0)->vc; +++} +++ +++static inline uint32_t get_vc_address_u(const AVFrame * const frame) { +++ return gpu_is_buf1(frame) ? +++ gpu_buf1_gmem(frame)->vc + frame->data[1] - frame->data[0] : +++ gpu_buf3_gmem(frame, 1)->vc; +++} +++ +++static inline uint32_t get_vc_address_v(const AVFrame * const frame) { +++ return gpu_is_buf1(frame) ? +++ gpu_buf1_gmem(frame)->vc + frame->data[2] - frame->data[0] : +++ gpu_buf3_gmem(frame, 2)->vc; +++} +++ +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_y(const AVFrame * const frame) { +++ if (gpu_is_buf1(frame)) +++ { +++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); +++ g.numbytes = frame->data[1] - frame->data[0]; +++ return g; +++ } +++ else +++ return *gpu_buf3_gmem(frame, 0); +++} +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_u(const AVFrame * const frame) { +++ if (gpu_is_buf1(frame)) +++ { +++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); +++ g.arm += frame->data[1] - frame->data[0]; +++ g.vc += frame->data[1] - frame->data[0]; +++ g.numbytes = frame->data[2] - frame->data[1]; // chroma size +++ return g; +++ } +++ else +++ return *gpu_buf3_gmem(frame, 1); +++} +++ +++static inline GPU_MEM_PTR_T get_gpu_mem_ptr_v(const AVFrame * const frame) { +++ if (gpu_is_buf1(frame)) +++ { +++ GPU_MEM_PTR_T g = *gpu_buf1_gmem(frame); +++ g.arm += frame->data[2] - frame->data[0]; +++ g.vc += frame->data[2] - frame->data[0]; +++ g.numbytes = frame->data[2] - frame->data[1]; // chroma size +++ return g; +++ } +++ else +++ return *gpu_buf3_gmem(frame, 2); +++} +++ +++#endif +++ +++ ++ // QPU specific functions ++ extern void qpu_run_shader8(int code, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8); ++ extern void qpu_run_shader12(int code, int num, int code2, int num2, int unifs1, int unifs2, int unifs3, int unifs4, int unifs5, int unifs6, int unifs7, int unifs8, int unifs9, int unifs10, int unifs11, int unifs12); ++diff --git a/libavcodec/rpi_zc.c b/libavcodec/rpi_zc.c ++new file mode 100644 ++index 0000000..9580165 ++--- /dev/null +++++ b/libavcodec/rpi_zc.c ++@@ -0,0 +1,406 @@ +++#include "config.h" +++#ifdef RPI +++#include "rpi_qpu.h" +++#include "rpi_zc.h" +++ +++#include "libavutil/buffer_internal.h" +++ +++struct ZcPoolEnt; +++ +++typedef struct ZcPool +++{ +++ int numbytes; +++ struct ZcPoolEnt * head; +++ pthread_mutex_t lock; +++} ZcPool; +++ +++typedef struct ZcPoolEnt +++{ +++ // It is important that we start with gmem as other bits of code will expect to see that +++ GPU_MEM_PTR_T gmem; +++ struct ZcPoolEnt * next; +++ struct ZcPool * pool; +++} ZcPoolEnt; +++ +++static ZcPoolEnt * zc_pool_ent_alloc(ZcPool * const pool, const int size) +++{ +++ ZcPoolEnt * const zp = av_malloc(sizeof(ZcPoolEnt)); +++ +++ if (zp == NULL) { +++ av_log(NULL, AV_LOG_ERROR, "av_malloc(ZcPoolEnt) failed\n"); +++ goto fail0; +++ } +++ +++ if (gpu_malloc_cached(size, &zp->gmem) != 0) +++ { +++ av_log(NULL, AV_LOG_ERROR, "av_gpu_malloc_cached(%d) failed\n", size); +++ goto fail1; +++ } +++ +++ zp->next = NULL; +++ zp->pool = pool; +++ return zp; +++ +++fail1: +++ av_free(zp); +++fail0: +++ return NULL; +++} +++ +++static void zc_pool_ent_free(ZcPoolEnt * const zp) +++{ +++ gpu_free(&zp->gmem); +++ av_free(zp); +++} +++ +++static void zc_pool_flush(ZcPool * const pool) +++{ +++ ZcPoolEnt * p = pool->head; +++ pool->head = NULL; +++ while (p != NULL) +++ { +++ ZcPoolEnt * const zp = p; +++ p = p->next; +++ zc_pool_ent_free(zp); +++ } +++} +++ +++static ZcPoolEnt * zc_pool_alloc(ZcPool * const pool, const int numbytes) +++{ +++ ZcPoolEnt * zp; +++ pthread_mutex_lock(&pool->lock); +++ +++ if (numbytes != pool->numbytes) +++ { +++ zc_pool_flush(pool); +++ pool->numbytes = numbytes; +++ } +++ +++ if (pool->head != NULL) +++ { +++ zp = pool->head; +++ pool->head = zp->next; +++ } +++ else +++ { +++ zp = zc_pool_ent_alloc(pool, numbytes); +++ } +++ +++ pthread_mutex_unlock(&pool->lock); +++ return zp; +++} +++ +++static void zc_pool_free(ZcPoolEnt * const zp) +++{ +++ ZcPool * const pool = zp == NULL ? NULL : zp->pool; +++ if (zp != NULL) +++ { +++ pthread_mutex_lock(&pool->lock); +++ if (pool->numbytes == zp->gmem.numbytes) +++ { +++ zp->next = pool->head; +++ pool->head = zp; +++ pthread_mutex_unlock(&pool->lock); +++ } +++ else +++ { +++ pthread_mutex_unlock(&pool->lock); +++ zc_pool_ent_free(zp); +++ } +++ } +++} +++ +++static void +++zc_pool_init(ZcPool * const pool) +++{ +++ pool->numbytes = -1; +++ pool->head = NULL; +++ pthread_mutex_init(&pool->lock, NULL); +++} +++ +++static void +++zc_pool_destroy(ZcPool * const pool) +++{ +++ pool->numbytes = -1; +++ zc_pool_flush(pool); +++ pthread_mutex_destroy(&pool->lock); +++} +++ +++ +++typedef struct AVZcEnv +++{ +++ ZcPool pool; +++} ZcEnv; +++ +++// Callback when buffer unrefed to zero +++static void rpi_free_display_buffer(void *opaque, uint8_t *data) +++{ +++ ZcPoolEnt *const zp = opaque; +++// printf("%s: data=%p\n", __func__, data); +++ zc_pool_free(zp); +++} +++ +++static inline GPU_MEM_PTR_T * pic_gm_ptr(AVBufferRef * const buf) +++{ +++ // Kludge where we check the free fn to check this is really +++ // one of our buffers - can't think of a better way +++ return buf == NULL || buf->buffer->free != rpi_free_display_buffer ? NULL : +++ av_buffer_get_opaque(buf); +++} +++ +++AVRpiZcFrameGeometry av_rpi_zc_frame_geometry( +++ const unsigned int video_width, const unsigned int video_height) +++{ +++ AVRpiZcFrameGeometry geo; +++ geo.stride_y = (video_width + 32 + 31) & ~31; +++ geo.stride_c = geo.stride_y / 2; +++// geo.height_y = (video_height + 15) & ~15; +++ geo.height_y = (video_height + 32 + 31) & ~31; +++ geo.height_c = geo.height_y / 2; +++ return geo; +++} +++ +++static AVBufferRef * rpi_buf_pool_alloc(ZcPool * const pool, int size) +++{ +++ ZcPoolEnt *const zp = zc_pool_alloc(pool, size); +++ AVBufferRef * buf; +++ +++ if (zp == NULL) { +++ av_log(NULL, AV_LOG_ERROR, "zc_pool_alloc(%d) failed\n", size); +++ goto fail0; +++ } +++ +++ if ((buf = av_buffer_create(zp->gmem.arm, size, rpi_free_display_buffer, zp, AV_BUFFER_FLAG_READONLY)) == NULL) +++ { +++ av_log(NULL, AV_LOG_ERROR, "av_buffer_create() failed\n"); +++ goto fail2; +++ } +++ +++ return buf; +++ +++fail2: +++ zc_pool_free(zp); +++fail0: +++ return NULL; +++} +++ +++static int rpi_get_display_buffer(struct AVCodecContext * const s, AVFrame * const frame) +++{ +++ ZcEnv *const zc = s->get_buffer_context; +++ const AVRpiZcFrameGeometry geo = av_rpi_zc_frame_geometry(frame->width, frame->height); +++ const unsigned int size_y = geo.stride_y * geo.height_y; +++ const unsigned int size_c = geo.stride_c * geo.height_c; +++ const unsigned int size_pic = size_y + size_c * 2; +++ AVBufferRef * buf; +++ unsigned int i; +++ +++// printf("Do local alloc: format=%#x, %dx%d: %u\n", frame->format, frame->width, frame->height, size_pic); +++ +++ if ((buf = rpi_buf_pool_alloc(&zc->pool, size_pic)) == NULL) +++ { +++ av_log(s, AV_LOG_ERROR, "rpi_get_display_buffer: Failed to get buffer from pool\n"); +++ return AVERROR(ENOMEM); +++ } +++ +++ for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { +++ frame->buf[i] = NULL; +++ frame->data[i] = NULL; +++ frame->linesize[i] = 0; +++ } +++ +++ frame->buf[0] = buf; +++ frame->linesize[0] = geo.stride_y; +++ frame->linesize[1] = geo.stride_c; +++ frame->linesize[2] = geo.stride_c; +++ frame->data[0] = buf->data; +++ frame->data[1] = frame->data[0] + size_y; +++ frame->data[2] = frame->data[1] + size_c; +++ frame->extended_data = frame->data; +++ // Leave extended buf alone +++ +++ return 0; +++} +++ +++ +++#define RPI_GET_BUFFER2 1 +++ +++int av_rpi_zc_get_buffer2(struct AVCodecContext *s, AVFrame *frame, int flags) +++{ +++#if !RPI_GET_BUFFER2 +++ return avcodec_default_get_buffer2(s, frame, flags); +++#else +++ int rv; +++ +++ if ((s->codec->capabilities & AV_CODEC_CAP_DR1) == 0 || +++ frame->format != AV_PIX_FMT_YUV420P) +++ { +++// printf("Do default alloc: format=%#x\n", frame->format); +++ rv = avcodec_default_get_buffer2(s, frame, flags); +++ } +++ else +++ { +++ rv = rpi_get_display_buffer(s, frame); +++ } +++ +++#if 0 +++ printf("%s: %dx%d lsize=%d/%d/%d data=%p/%p/%p bref=%p/%p/%p opaque[0]=%p\n", __func__, +++ frame->width, frame->height, +++ frame->linesize[0], frame->linesize[1], frame->linesize[2], +++ frame->data[0], frame->data[1], frame->data[2], +++ frame->buf[0], frame->buf[1], frame->buf[2], +++ av_buffer_get_opaque(frame->buf[0])); +++#endif +++ return rv; +++#endif +++} +++ +++ +++static AVBufferRef * zc_copy(struct AVCodecContext * const s, +++ const AVFrame * const src) +++{ +++ AVFrame dest_frame; +++ AVFrame * const dest = &dest_frame; +++ unsigned int i; +++ uint8_t * psrc, * pdest; +++ +++ dest->width = src->width; +++ dest->height = src->height; +++ +++ if (rpi_get_display_buffer(s, dest) != 0) +++ { +++ return NULL; +++ } +++ +++ for (i = 0, psrc = src->data[0], pdest = dest->data[0]; +++ i != dest->height; +++ ++i, psrc += src->linesize[0], pdest += dest->linesize[0]) +++ { +++ memcpy(pdest, psrc, dest->width); +++ } +++ for (i = 0, psrc = src->data[1], pdest = dest->data[1]; +++ i != dest->height / 2; +++ ++i, psrc += src->linesize[1], pdest += dest->linesize[1]) +++ { +++ memcpy(pdest, psrc, dest->width / 2); +++ } +++ for (i = 0, psrc = src->data[2], pdest = dest->data[2]; +++ i != dest->height / 2; +++ ++i, psrc += src->linesize[2], pdest += dest->linesize[2]) +++ { +++ memcpy(pdest, psrc, dest->width / 2); +++ } +++ +++ return dest->buf[0]; +++} +++ +++ +++AVRpiZcRefPtr av_rpi_zc_ref(struct AVCodecContext * const s, +++ const AVFrame * const frame, const int maycopy) +++{ +++ assert(s != NULL); +++ +++ if (frame->format != AV_PIX_FMT_YUV420P) +++ { +++ av_log(s, AV_LOG_WARNING, "%s: *** Format not YUV420P: %d\n", __func__, frame->format); +++ return NULL; +++ } +++ +++ if (frame->buf[1] != NULL) +++ { +++ if (maycopy) +++ { +++ av_log(s, AV_LOG_INFO, "%s: *** Not a single buf frame: copying\n", __func__); +++ return zc_copy(s, frame); +++ } +++ else +++ { +++ av_log(s, AV_LOG_WARNING, "%s: *** Not a single buf frame: NULL\n", __func__); +++ return NULL; +++ } +++ } +++ +++ if (pic_gm_ptr(frame->buf[0]) == NULL) +++ { +++ if (maycopy) +++ { +++ av_log(s, AV_LOG_INFO, "%s: *** Not one of our buffers: copying\n", __func__); +++ return zc_copy(s, frame); +++ } +++ else +++ { +++ av_log(s, AV_LOG_WARNING, "%s: *** Not one of our buffers: NULL\n", __func__); +++ return NULL; +++ } +++ } +++ +++ return av_buffer_ref(frame->buf[0]); +++} +++ +++int av_rpi_zc_vc_handle(const AVRpiZcRefPtr fr_ref) +++{ +++ const GPU_MEM_PTR_T * const p = pic_gm_ptr(fr_ref); +++ return p == NULL ? -1 : p->vc_handle; +++} +++ +++int av_rpi_zc_numbytes(const AVRpiZcRefPtr fr_ref) +++{ +++ const GPU_MEM_PTR_T * const p = pic_gm_ptr(fr_ref); +++ return p == NULL ? 0 : p->numbytes; +++} +++ +++void av_rpi_zc_unref(AVRpiZcRefPtr fr_ref) +++{ +++ if (fr_ref != NULL) +++ { +++ av_buffer_unref(&fr_ref); +++ } +++} +++ +++AVZcEnvPtr av_rpi_zc_env_alloc(void) +++{ +++ ZcEnv * const zc = av_mallocz(sizeof(ZcEnv)); +++ if (zc == NULL) +++ { +++ av_log(NULL, AV_LOG_ERROR, "av_rpi_zc_env_alloc: Context allocation failed\n"); +++ return NULL; +++ } +++ +++ zc_pool_init(&zc->pool); +++ return zc; +++} +++ +++void av_rpi_zc_env_free(AVZcEnvPtr zc) +++{ +++ if (zc != NULL) +++ { +++ zc_pool_destroy(&zc->pool); ; +++ av_free(zc); +++ } +++} +++ +++int av_rpi_zc_init(struct AVCodecContext * const s) +++{ +++ ZcEnv * const zc = av_rpi_zc_env_alloc(); +++ if (zc == NULL) +++ { +++ return AVERROR(ENOMEM); +++ } +++ +++ s->get_buffer_context = zc; +++ s->get_buffer2 = av_rpi_zc_get_buffer2; +++ return 0; +++} +++ +++void av_rpi_zc_uninit(struct AVCodecContext * const s) +++{ +++ if (s->get_buffer2 == av_rpi_zc_get_buffer2) +++ { +++ ZcEnv * const zc = s->get_buffer_context; +++ s->get_buffer2 = avcodec_default_get_buffer2; +++ s->get_buffer_context = NULL; +++ av_rpi_zc_env_free(zc); +++ } +++} +++ +++#endif // RPI +++ ++diff --git a/libavcodec/rpi_zc.h b/libavcodec/rpi_zc.h ++new file mode 100644 ++index 0000000..f0109f4 ++--- /dev/null +++++ b/libavcodec/rpi_zc.h ++@@ -0,0 +1,83 @@ +++#ifndef LIBAVCODEC_RPI_ZC_H +++#define LIBAVCODEC_RPI_ZC_H +++ +++// Zero-Copy frame code for RPi +++// RPi needs Y/U/V planes to be contiguous for display. By default +++// ffmpeg will allocate separated planes so a memcpy is needed before +++// display. This code prodes a method a making ffmpeg allocate a single +++// bit of memory for the frame when can then be refrence counted until +++// display ahs finsihed with it. +++ +++#include "libavutil/frame.h" +++#include "libavcodec/avcodec.h" +++ +++// "Opaque" pointer to whatever we are using as a buffer reference +++typedef AVBufferRef * AVRpiZcRefPtr; +++ +++struct AVZcEnv; +++typedef struct AVZcEnv * AVZcEnvPtr; +++ +++typedef struct AVRpiZcFrameGeometry +++{ +++ unsigned int stride_y; +++ unsigned int height_y; +++ unsigned int stride_c; +++ unsigned int height_c; +++} AVRpiZcFrameGeometry; +++ +++ +++AVRpiZcFrameGeometry av_rpi_zc_frame_geometry( +++ const unsigned int video_width, const unsigned int video_height); +++ +++// Replacement fn for avctx->get_buffer2 +++// Should be set before calling avcodec_decode_open2 +++// +++// N.B. in addition to to setting avctx->get_buffer2, avctx->refcounted_frames +++// must be set to 1 as otherwise the buffer info is killed before being returned +++// by avcodec_decode_video2. Note also that this means that the AVFrame that is +++// return must be manually derefed with av_frame_unref. This should be done +++// after av_rpi_zc_ref has been called. +++int av_rpi_zc_get_buffer2(struct AVCodecContext *s, AVFrame *frame, int flags); +++ +++// Generate a ZC reference to the buffer(s) in this frame +++// If the buffer doesn't appear to be one allocated by _get_buffer_2 +++// then the behaviour depends on maycopy: +++// If maycopy=0 then return NULL +++// If maycopy=1 && the src frame is in a form where we can easily copy +++// the data, then allocate a new buffer and copy the data into it +++// Otherwise return NULL +++AVRpiZcRefPtr av_rpi_zc_ref(struct AVCodecContext * const s, +++ const AVFrame * const frame, const int maycopy); +++ +++// Get the vc_handle from the frame ref +++// Returns -1 if ref doesn't look valid +++int av_rpi_zc_vc_handle(const AVRpiZcRefPtr fr_ref); +++// Get the number of bytes allocated from the frame ref +++// Returns 0 if ref doesn't look valid +++int av_rpi_zc_numbytes(const AVRpiZcRefPtr fr_ref); +++ +++// Unreference the buffer refed/allocated by _zc_ref +++// If fr_ref is NULL then this will NOP +++void av_rpi_zc_unref(AVRpiZcRefPtr fr_ref); +++ +++// Allocate an environment for the buffer pool used by the ZC code +++// This should be put in avctx->get_buffer_context so it can be found by +++// av_rpi_zc_get_buffer2 when it is called from ffmpeg +++AVZcEnvPtr av_rpi_zc_env_alloc(void); +++ +++// Allocate the environment used by the ZC code +++void av_rpi_zc_env_free(AVZcEnvPtr); +++ +++ +++// Init ZC into a context +++// There is nothing magic in this fn - it just packages setting +++// get_buffer2 & get_buffer_context +++int av_rpi_zc_init(struct AVCodecContext * const s); +++ +++// Free ZC from a context +++// There is nothing magic in this fn - it just packages unsetting +++// get_buffer2 & get_buffer_context +++void av_rpi_zc_uninit(struct AVCodecContext * const s); +++ +++#endif +++ ++-- ++2.5.0 ++ ++ ++From 4d8bccc7b9a611a54253c26dd55fbffbf9db4c48 Mon Sep 17 00:00:00 2001 ++From: John Cox ++Date: Tue, 1 Mar 2016 14:21:25 +0000 ++Subject: [PATCH 2/2] Set VPU scheduling thread to high priority after creation ++ ++--- ++ libavcodec/rpi_qpu.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- ++ 1 file changed, 47 insertions(+), 1 deletion(-) ++ ++diff --git a/libavcodec/rpi_qpu.c b/libavcodec/rpi_qpu.c ++index b0c9bc5..ee19231 100644 ++--- a/libavcodec/rpi_qpu.c +++++ b/libavcodec/rpi_qpu.c ++@@ -182,9 +182,55 @@ static int gpu_init(volatile struct GPU **gpu) { ++ err = pthread_create(&vpu_thread, NULL, vpu_start, NULL); ++ //printf("Created thread\n"); ++ if (err) { ++- printf("Failed to create vpu thread\n"); +++ av_log(NULL, AV_LOG_FATAL, "Failed to create vpu thread\n"); ++ return -4; ++ } +++ +++ { +++ struct sched_param param = {0}; +++ int policy = 0; +++ +++ if (pthread_getschedparam(vpu_thread, &policy, ¶m) != 0) +++ { +++ av_log(NULL, AV_LOG_ERROR, "Unable to get VPU thread scheduling parameters\n"); +++ } +++ else +++ { +++ av_log(NULL, AV_LOG_INFO, "VPU thread: policy=%d (%s), pri=%d\n", +++ policy, +++ policy == SCHED_RR ? "RR" : policy == SCHED_FIFO ? "FIFO" : "???" , +++ param.sched_priority); +++ +++ policy = SCHED_FIFO; +++ param.sched_priority = sched_get_priority_max(SCHED_FIFO); +++ +++ av_log(NULL, AV_LOG_INFO, "Attempt to set: policy=%d (%s), pri=%d\n", +++ policy, +++ policy == SCHED_RR ? "RR" : policy == SCHED_FIFO ? "FIFO" : "???" , +++ param.sched_priority); +++ +++ if (pthread_setschedparam(vpu_thread, policy, ¶m) != 0) +++ { +++ av_log(NULL, AV_LOG_ERROR, "Unable to set VPU thread scheduling parameters\n"); +++ } +++ else +++ { +++ if (pthread_getschedparam(vpu_thread, &policy, ¶m) != 0) +++ { +++ av_log(NULL, AV_LOG_ERROR, "Unable to get VPU thread scheduling parameters\n"); +++ } +++ else +++ { +++ av_log(NULL, AV_LOG_INFO, "VPU thread (after): policy=%d (%s), pri=%d\n", +++ policy, +++ policy == SCHED_RR ? "RR" : policy == SCHED_FIFO ? "FIFO" : "???" , +++ param.sched_priority); +++ } +++ } +++ } +++ +++ } +++ ++ } ++ #endif ++ ++-- ++2.5.0 ++ +diff --git a/tools/depends/target/gettext/Makefile b/tools/depends/target/gettext/Makefile +index 31ee560..85ca94d 100644 +--- a/tools/depends/target/gettext/Makefile ++++ b/tools/depends/target/gettext/Makefile +@@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile + + # lib name, version + LIBNAME=gettext +-VERSION=0.19.8 ++VERSION=0.18.2 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/target/jpeg/Makefile b/tools/depends/target/jpeg/Makefile +new file mode 100644 +index 0000000..5144f1d +--- /dev/null ++++ b/tools/depends/target/jpeg/Makefile +@@ -0,0 +1,39 @@ ++include ../../Makefile.include ++DEPS= ../../Makefile.include Makefile ++ ++# lib name, version ++LIBNAME=jpeg ++VERSION=8b ++SOURCE=$(LIBNAME)-$(VERSION) ++ARCHIVE=$(LIBNAME)src.v$(VERSION).tar.gz ++ ++# configuration settings ++CONFIGURE=./configure --prefix=$(PREFIX) ++ ++LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).so ++ ++CLEAN_FILES=$(ARCHIVE) $(PLATFORM) ++ ++all: $(LIBDYLIB) .installed-$(PLATFORM) ++ ++$(TARBALLS_LOCATION)/$(ARCHIVE): ++ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) ++ ++$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) ++ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) ++ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) ++ cd $(PLATFORM); $(CONFIGURE) ++ ++$(LIBDYLIB): $(PLATFORM) ++ $(MAKE) -C $(PLATFORM) ++ ++.installed-$(PLATFORM): $(LIBDYLIB) ++ $(MAKE) -C $(PLATFORM) install ++ touch $@ ++ ++clean: ++ $(MAKE) -C $(PLATFORM) clean ++ rm -f .installed-$(PLATFORM) ++ ++distclean:: ++ rm -rf $(PLATFORM) .installed-$(PLATFORM) +diff --git a/tools/depends/target/liblzo2/Makefile b/tools/depends/target/liblzo2/Makefile +index 32d29d8..9a670ed 100644 +--- a/tools/depends/target/liblzo2/Makefile ++++ b/tools/depends/target/liblzo2/Makefile +@@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile + + # lib name, version + LIBNAME=lzo +-VERSION=2.09 ++VERSION=2.06 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/target/libmicrohttpd/Makefile b/tools/depends/target/libmicrohttpd/Makefile +index c374c5f..d00d2ba 100644 +--- a/tools/depends/target/libmicrohttpd/Makefile ++++ b/tools/depends/target/libmicrohttpd/Makefile +@@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile + + # lib name, version + LIBNAME=libmicrohttpd +-VERSION=0.9.50 ++VERSION=svn-35533 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + +diff --git a/tools/depends/target/libmodplug/Makefile b/tools/depends/target/libmodplug/Makefile +new file mode 100644 +index 0000000..e2d2440 +--- /dev/null ++++ b/tools/depends/target/libmodplug/Makefile +@@ -0,0 +1,42 @@ ++include ../../Makefile.include ++DEPS= ../../Makefile.include Makefile ++ ++# lib name, version ++LIBNAME=libmodplug ++VERSION=0.8.7 ++SOURCE=$(LIBNAME)-$(VERSION) ++ARCHIVE=$(SOURCE).tar.gz ++ ++# configuration settings ++CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ ++ ./configure --prefix=$(PREFIX) ++ ++LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).la ++ ++CLEAN_FILES=$(ARCHIVE) $(PLATFORM) ++ ++all: .installed-$(PLATFORM) ++ ++$(TARBALLS_LOCATION)/$(ARCHIVE): ++ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) ++ ++$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) ++ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) ++ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) ++ cd $(PLATFORM); $(AUTORECONF) -vif ++ cd $(PLATFORM); $(CONFIGURE) ++ ++$(LIBDYLIB): $(PLATFORM) ++ $(MAKE) -C $(PLATFORM) ++ ++.installed-$(PLATFORM): $(LIBDYLIB) ++ $(MAKE) -C $(PLATFORM) install ++ touch $@ ++ ++clean: ++ $(MAKE) -C $(PLATFORM) clean ++ rm -f .installed-$(PLATFORM) ++ ++distclean:: ++ rm -rf $(PLATFORM) .installed-$(PLATFORM) ++ +diff --git a/tools/depends/target/libpng/Makefile b/tools/depends/target/libpng/Makefile +index ce45063..83fb583 100644 +--- a/tools/depends/target/libpng/Makefile ++++ b/tools/depends/target/libpng/Makefile +@@ -8,7 +8,7 @@ SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + + # configuration settings +-CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ ++CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; CFLAGS=-fPIC \ + ./configure --prefix=$(PREFIX) --disable-shared + + LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME)15.a +diff --git a/tools/depends/target/librtmp/Makefile b/tools/depends/target/librtmp/Makefile +index e78d375..15829b4 100644 +--- a/tools/depends/target/librtmp/Makefile ++++ b/tools/depends/target/librtmp/Makefile +@@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile prefix.patch + + # lib name, version + LIBNAME=rtmpdump +-VERSION=fa8646daeb19dfd12c181f7d19de708d623704c0 ++VERSION=a107cef9b392616dff54fabfd37f985ee2190a6f + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.gz + # configuration settings +diff --git a/tools/depends/target/python27/Makefile b/tools/depends/target/python27/Makefile +index d6a68bd..7bfc59f 100644 +--- a/tools/depends/target/python27/Makefile ++++ b/tools/depends/target/python27/Makefile +@@ -4,7 +4,7 @@ DEPS= ../../Makefile.include Makefile Python-2.7.10-crosscompile.patch Python-2. + + # lib name, version + LIBNAME=Python +-VERSION=2.7.11 ++VERSION=2.7.10 + SOURCE=$(LIBNAME)-$(VERSION) + ARCHIVE=$(SOURCE).tar.xz + +@@ -39,6 +39,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); patch -p0 < ../Python-2.7.10-android.patch + cd $(PLATFORM); patch -p0 < ../Python-no-export-path.patch + cd $(PLATFORM); patch -p0 < ../fix-ffi.patch ++ #cd $(PLATFORM); patch -p1 < ../urllib-ssl-no-cert_check.patch + ifeq ($(OS),ios) + cd $(PLATFORM); patch -p0 < ../make-fork-optional.patch + cd $(PLATFORM); patch -p0 < ../Python-2.6.5-urllib.diff +diff --git a/tools/depends/target/python27/Python-2.7.10-crosscompile.patch b/tools/depends/target/python27/Python-2.7.10-crosscompile.patch +index c7c1c42..7de1ead 100644 +--- a/tools/depends/target/python27/Python-2.7.10-crosscompile.patch ++++ b/tools/depends/target/python27/Python-2.7.10-crosscompile.patch +@@ -1,6 +1,6 @@ + --- Makefile.pre.in.orig 2015-05-23 18:09:16.000000000 +0200 + +++ Makefile.pre.in 2015-10-10 12:29:21.988926069 +0200 +-@@ -238,6 +238,7 @@ ++@@ -234,6 +234,7 @@ + ########################################################################## + # Parser + PGEN= Parser/pgen$(EXE) +@@ -8,7 +8,7 @@ + + PSRCS= \ + Parser/acceler.c \ +-@@ -497,9 +498,9 @@ ++@@ -472,9 +473,9 @@ + *\ -s*|s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ +@@ -20,7 +20,7 @@ + + # Build static library + # avoid long command lines, same as LIBRARY_OBJS +-@@ -636,7 +637,7 @@ ++@@ -611,7 +612,7 @@ + $(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGENSRCS) + @$(MKDIR_P) Include + $(MAKE) $(PGEN) +@@ -29,7 +29,7 @@ + $(GRAMMAR_C): $(GRAMMAR_H) $(GRAMMAR_INPUT) $(PGENSRCS) + $(MAKE) $(GRAMMAR_H) + touch $(GRAMMAR_C) +-@@ -1072,12 +1073,12 @@ ++@@ -1042,12 +1043,12 @@ + $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ + $(DESTDIR)$(LIBDEST)/distutils/tests ; \ + fi +@@ -44,7 +44,7 @@ + $(PYTHON_FOR_BUILD) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ +-@@ -1205,11 +1206,13 @@ ++@@ -1175,11 +1176,13 @@ + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: sharedmods +diff --git a/tools/depends/target/python27/Python-no-export-path.patch b/tools/depends/target/python27/Python-no-export-path.patch +index 6c486cc..5b001b1 100644 +--- a/tools/depends/target/python27/Python-no-export-path.patch ++++ b/tools/depends/target/python27/Python-no-export-path.patch +@@ -1,6 +1,6 @@ + --- Makefile.pre.in.orig 2015-10-09 19:10:15.042905069 +0200 + +++ Makefile.pre.in 2015-10-09 19:11:01.513642241 +0200 +-@@ -1100,8 +1100,6 @@ ++@@ -1070,8 +1070,6 @@ + $(srcdir)/Lib/$(PLATDIR): + mkdir $(srcdir)/Lib/$(PLATDIR) + cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen +diff --git a/tools/depends/target/python27/Python-setup.patch b/tools/depends/target/python27/Python-setup.patch +index e9ff0c2..e32dd50 100644 +--- a/tools/depends/target/python27/Python-setup.patch ++++ b/tools/depends/target/python27/Python-setup.patch +@@ -1,6 +1,6 @@ + --- setup.py.orig 2015-10-07 16:32:16.219083585 +0200 + +++ setup.py 2015-10-07 16:41:48.563085871 +0200 +-@@ -321,6 +321,9 @@ ++@@ -320,6 +320,9 @@ + self.announce('WARNING: skipping import check for Cygwin-based "%s"' + % ext.name) + return +@@ -10,7 +10,7 @@ + ext_filename = os.path.join( + self.build_lib, + self.get_ext_filename(self.get_ext_fullname(ext.name))) +-@@ -335,27 +338,30 @@ ++@@ -331,27 +334,30 @@ + try: + imp.load_dynamic(ext.name, ext_filename) + except ImportError, why: +diff --git a/tools/depends/target/python27/fix-ffi.patch b/tools/depends/target/python27/fix-ffi.patch +index 270ac0a..29f8af8 100644 +--- a/tools/depends/target/python27/fix-ffi.patch ++++ b/tools/depends/target/python27/fix-ffi.patch +@@ -23,7 +23,7 @@ + +*/ + --- Modules/_ctypes/cfield.c.orig 2015-10-11 20:34:03.034370393 +0200 + +++ Modules/_ctypes/cfield.c 2015-10-11 20:37:04.462377159 +0200 +-@@ -1724,6 +1724,7 @@ ++@@ -1723,6 +1723,7 @@ + */ + + /* align and size are bogus for void, but they must not be zero */ +@@ -31,7 +31,7 @@ + ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID }; + + ffi_type ffi_type_uint8 = { 1, 1, FFI_TYPE_UINT8 }; +-@@ -1740,14 +1741,14 @@ ++@@ -1739,14 +1740,14 @@ + + ffi_type ffi_type_float = { sizeof(float), FLOAT_ALIGN, FFI_TYPE_FLOAT }; + ffi_type ffi_type_double = { sizeof(double), DOUBLE_ALIGN, FFI_TYPE_DOUBLE }; +diff --git a/tools/depends/target/python27/urllib-ssl-no-cert_check.patch b/tools/depends/target/python27/urllib-ssl-no-cert_check.patch +new file mode 100644 +index 0000000..e57c419 +--- /dev/null ++++ b/tools/depends/target/python27/urllib-ssl-no-cert_check.patch +@@ -0,0 +1,14 @@ ++diff --git a/Lib/ssl.py b/Lib/ssl.py ++index 5df6ed3..a871519 100644 ++--- a/Lib/ssl.py +++++ b/Lib/ssl.py ++@@ -482,7 +482,7 @@ def _create_unverified_context(protocol=PROTOCOL_SSLv23, cert_reqs=None, ++ return context ++ ++ # Used by http.client if no context is explicitly passed. ++-_create_default_https_context = create_default_context +++_create_default_https_context = _create_unverified_context ++ ++ ++ # Backwards compatibility alias, even though it's not a public name. ++ +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 78e1253..ef87a89 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -29,15 +29,16 @@ + #include "utils/Splash.h" + #include "LangInfo.h" + #include "utils/Screenshot.h" ++#include ++#include + #include "Util.h" + #include "URL.h" + #include "guilib/TextureManager.h" + #include "cores/IPlayer.h" + #include "cores/VideoPlayer/DVDFileInfo.h" + #include "cores/AudioEngine/AEFactory.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "cores/AudioEngine/Utils/AEUtil.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "PlayListPlayer.h" + #include "Autorun.h" + #include "video/Bookmark.h" +@@ -49,7 +50,6 @@ + #include "guilib/GUIFontManager.h" + #include "guilib/GUIColorManager.h" + #include "guilib/StereoscopicsManager.h" +-#include "addons/BinaryAddonCache.h" + #include "addons/LanguageResource.h" + #include "addons/Skin.h" + #include "interfaces/generic/ScriptInvocationManager.h" +@@ -94,6 +94,7 @@ + #include "utils/CPUInfo.h" + #include "utils/SeekHandler.h" + ++#include "video/VideoReferenceClock.h" + #include "input/KeyboardLayoutManager.h" + + #if HAVE_SDL_VERSION == 1 +@@ -112,6 +113,9 @@ + #ifdef HAS_FILESYSTEM_NFS + #include "filesystem/NFSFile.h" + #endif ++#ifdef HAS_FILESYSTEM_AFP ++#include "filesystem/AFPFile.h" ++#endif + #ifdef HAS_FILESYSTEM_SFTP + #include "filesystem/SFTPFile.h" + #endif +@@ -217,10 +221,16 @@ + #include "utils/AMLUtils.h" + #endif + ++#ifdef HAS_IMXVPU ++#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h" ++#include "peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h" ++#endif ++ + #include "cores/FFmpeg.h" + #include "utils/CharsetConverter.h" + #include "pictures/GUIWindowSlideShow.h" + #include "windows/GUIWindowLoginScreen.h" ++#include "utils/Screen.h" + + using namespace ADDON; + using namespace XFILE; +@@ -281,6 +291,7 @@ CApplication::CApplication(void) + m_bPlaybackStarting = false; + m_ePlayState = PLAY_STATE_NONE; + m_skinReverting = false; ++ m_ourVT = -1; + + #ifdef HAS_GLX + XInitThreads(); +@@ -333,7 +344,10 @@ bool CApplication::OnEvent(XBMC_Event& newEvent) + { + case XBMC_QUIT: + if (!g_application.m_bStop) ++ { + CApplicationMessenger::GetInstance().PostMsg(TMSG_QUIT); ++ g_screen.SetOn(); ++ } + break; + case XBMC_VIDEORESIZE: + if (g_windowManager.Initialized() && +@@ -446,6 +460,7 @@ bool CApplication::Create() + CApplicationMessenger::GetInstance().RegisterReceiver(this); + CApplicationMessenger::GetInstance().RegisterReceiver(&g_playlistPlayer); + CApplicationMessenger::GetInstance().RegisterReceiver(&g_infoManager); ++ g_screen.RegisterToAnnouncer(); + + for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++) + { +@@ -691,7 +706,7 @@ bool CApplication::Create() + return true; + } + +-bool CApplication::CreateGUI() ++bool CApplication::CreateGUI(bool showXBMCSplash) + { + m_frameMoveGuard.lock(); + +@@ -735,6 +750,8 @@ bool CApplication::CreateGUI() + // Initialize core peripheral port support. Note: If these parameters + // are 0 and NULL, respectively, then the default number and types of + // controllers will be initialized. ++ RESOLUTION r = (RESOLUTION)CSettings::GetInstance().GetInt("videoscreen.resolution"); ++ CDisplaySettings::GetInstance().SetCurrentResolution(r ? r : RES_DESKTOP); + if (!g_Windowing.InitWindowSystem()) + { + CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system"); +@@ -778,7 +795,7 @@ bool CApplication::CreateGUI() + if (sav_res) + CDisplaySettings::GetInstance().SetCurrentResolution(RES_DESKTOP, true); + +- if (g_advancedSettings.m_splashImage) ++ if (g_advancedSettings.m_splashImage && showXBMCSplash) + CSplash::GetInstance().Show(); + + // The key mappings may already have been loaded by a peripheral +@@ -1066,9 +1083,9 @@ bool CApplication::Initialize() + cdio_loglevel_default = CDIO_LOG_ERROR; + #endif + +-#ifdef TARGET_POSIX //! @todo Win32 has no special://home/ mapping by default, so we +- //! must create these here. Ideally this should be using special://home/ and +- //! be platform agnostic (i.e. unify the InitDirectories*() functions) ++#ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we ++ // must create these here. Ideally this should be using special://home/ and ++ // be platform agnostic (i.e. unify the InitDirectories*() functions) + if (!m_bPlatformDirectories) + #endif + { +@@ -1087,6 +1104,9 @@ bool CApplication::Initialize() + #if !defined(TARGET_DARWIN_IOS) + g_peripherals.Initialise(); + #endif ++#if defined(HAS_IMXVPU) ++ g_peripherals.CreatePeripheralBus(std::make_shared(&g_peripherals)); ++#endif + + // Load curl so curl_global_init gets called before any service threads + // are started. Unloading will have no effect as curl is never fully unloaded. +@@ -1155,11 +1175,6 @@ bool CApplication::Initialize() + int firstWindow = g_SkinInfo->GetFirstWindow(); + g_windowManager.ActivateWindow(firstWindow); + +- if (g_windowManager.GetActiveWindowID() == WINDOW_STARTUP_ANIM) +- { +- CLog::Log(LOGWARNING, "CApplication::Initialize - startup.xml taints init process"); +- } +- + // the startup window is considered part of the initialization as it most likely switches to the final window + uiInitializationFinished = firstWindow != WINDOW_STARTUP_ANIM; + +@@ -1192,6 +1207,7 @@ bool CApplication::Initialize() + } + + m_slowTimer.StartZero(); ++ m_slowTimerVT.StartZero(); + + CAddonMgr::GetInstance().StartServices(true); + +@@ -1894,7 +1910,12 @@ void CApplication::Render() + g_infoManager.UpdateFPS(); + } + +- g_graphicsContext.Flip(hasRendered, m_pPlayer->IsRenderingVideoLayer()); ++ hasRendered &= !g_screen.GetScreenState(); ++ ++ // TODO: find better solution ++ // if video is rendered to a separate layer, we should not block this thread ++ if (!m_pPlayer->IsRenderingVideoLayer() || hasRendered) ++ g_graphicsContext.Flip(hasRendered); + + CTimeUtils::UpdateFrameTime(hasRendered); + } +@@ -2387,6 +2408,10 @@ void CApplication::OnApplicationMessage(ThreadMessage* pMsg) + #endif + break; + ++ case TMSG_CHANGEVT: ++ g_application.ChangeVT((int)pMsg->param1); ++ break; ++ + case TMSG_INHIBITIDLESHUTDOWN: + InhibitIdleShutdown(pMsg->param1 != 0); + break; +@@ -2415,6 +2440,11 @@ void CApplication::OnApplicationMessage(ThreadMessage* pMsg) + break; + #endif + ++ case TMSG_DISPLAY_RECONFIGURE: ++ g_Windowing.UpdateResolutions(); ++ g_graphicsContext.SetFullScreenVideo(g_graphicsContext.IsFullScreenVideo()); ++ break; ++ + case TMSG_SETAUDIODSPSTATE: + if(pMsg->param1 == ACTIVE_AE_DSP_STATE_ON) + CServiceBroker::GetADSP().Activate(); +@@ -2700,13 +2730,19 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) + if (processGUI && m_renderGUI) + { + m_skipGuiRender = false; ++ int idleSeconds = 15 * (m_pPlayer->IsPlayingAudio() && !m_pPlayer->IsPausedPlayback() ? 4*3/*3 min total*/ : 1); + int fps = 0; + + #if defined(TARGET_RASPBERRY_PI) || defined(HAS_IMXVPU) + // This code reduces rendering fps of the GUI layer when playing videos in fullscreen mode + // it makes only sense on architectures with multiple layers +- if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && m_pPlayer->IsRenderingVideoLayer()) ++ idleSeconds *= !(g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && m_pPlayer->IsRenderingVideoLayer()); ++#endif ++ if ((idleSeconds && m_screenSaverTimer.GetElapsedSeconds() > idleSeconds) || !idleSeconds) ++#if defined(TARGET_RASPBERRY_PI) || defined(HAS_IMXVPU) + fps = CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_LIMITGUIUPDATE); ++#else ++ fps = 5; + #endif + + unsigned int now = XbmcThreads::SystemClockMillis(); +@@ -3070,11 +3106,11 @@ PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart) + LoadVideoSettings(item); + + // see if we have the info in the database +- //! @todo If user changes the time speed (FPS via framerate conversion stuff) +- //! then these times will be wrong. +- //! Also, this is really just a hack for the slow load up times we have +- //! A much better solution is a fast reader of FPS and fileLength +- //! that we can use on a file to get it's time. ++ // TODO: If user changes the time speed (FPS via framerate conversion stuff) ++ // then these times will be wrong. ++ // Also, this is really just a hack for the slow load up times we have ++ // A much better solution is a fast reader of FPS and fileLength ++ // that we can use on a file to get it's time. + std::vector times; + bool haveTimes(false); + CVideoDatabase dbs; +@@ -3329,7 +3365,7 @@ PlayBackRet CApplication::PlayFile(CFileItem item, const std::string& player, bo + } + else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0) + { +- //! @todo - this will fail if user seeks back to first file in stack ++ // TODO - this will fail if user seeks back to first file in stack + if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME) + options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::GetInstance().DoesVideoStartWindowed(); + else +@@ -3708,8 +3744,8 @@ void CApplication::UpdateFileState() + // Ignore for PVR channels, PerformChannelSwitch takes care of this. + // Also ignore video playlists containing multiple items: video settings have already been saved in PlayFile() + // and we'd overwrite them with settings for the *previous* item. +- //! @todo these "exceptions" should be removed and the whole logic of saving settings be revisited and +- //! possibly moved out of CApplication. See PRs 5842, 5958, http://trac.kodi.tv/ticket/15704#comment:3 ++ // TODO: these "exceptions" should be removed and the whole logic of saving settings be revisited and ++ // possibly moved out of CApplication. See PRs 5842, 5958, http://trac.kodi.tv/ticket/15704#comment:3 + int playlist = g_playlistPlayer.GetCurrentPlaylist(); + if (!m_progressTrackingItem->IsPVRChannel() && !(playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)) + SaveFileState(); +@@ -3878,8 +3914,8 @@ bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false + { + if (m_dpmsIsManual) + return false; +- //! @todo if screensaver lock is specified but screensaver is not active +- //! (DPMS came first), activate screensaver now. ++ // TODO: if screensaver lock is specified but screensaver is not active ++ // (DPMS came first), activate screensaver now. + ToggleDPMS(false); + ResetScreenSaverTimer(); + result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed); +@@ -3893,6 +3929,9 @@ bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false + CVariant data(CVariant::VariantTypeObject); + data["shuttingdown"] = bPowerOffKeyPressed; + CAnnouncementManager::GetInstance().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data); ++ ++ if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black") ++ g_screen.SetOn(); + #ifdef TARGET_ANDROID + // Screensaver deactivated -> acquire wake lock + CXBMCApp::EnableWakeLock(true); +@@ -4388,6 +4427,62 @@ void CApplication::ShowAppMigrationMessage() + } + } + ++void CApplication::ChangeVT(int newVT) ++{ ++ std::string cmd = StringUtils::Format("sudo /sbin/start xbian-chvt TTYNR=%d", newVT); ++ CLog::Log(LOGINFO,"%s : activating tty%d", __FUNCTION__, newVT); ++ system(cmd.c_str()); ++} ++ ++void CApplication::checkVTchange() ++{ ++ struct vt_stat vts; ++ static int last_active; ++ ++ int cur_tty = open("/dev/tty0", O_RDONLY | O_NONBLOCK | O_NOCTTY); ++ if(cur_tty < 0 || ioctl(cur_tty, VT_GETSTATE, &vts) < 0) ++ goto out; ++ ++ if (last_active != vts.v_active && m_ourVT >= 0) ++ { ++ // We are back home ++ if (m_ourVT == vts.v_active) ++ { ++ CLog::Log(LOGDEBUG,"%s : our VT active again", __func__); ++ CWinEvents::Stop(false); ++#ifdef HAS_IMXVPU ++ g_IMXContext.Unblank(); ++#endif ++ SetRenderGUI(true); ++ g_graphicsContext.SetFullScreenVideo(g_graphicsContext.IsFullScreenVideo()); ++ //g_VideoReferenceClock.Start(); ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG,"%s : our VT being deactivated", __func__); ++ SetRenderGUI(false); ++ //g_VideoReferenceClock.Stop(); ++#ifdef HAS_IMXVPU ++ g_IMXContext.Blank(); ++#endif ++ { ++ CSingleLock lock(g_graphicsContext); ++ g_graphicsContext.Clear(0); ++ g_windowManager.Render(); ++ } ++ CWinEvents::Stop(true); ++ } ++ } ++ else if (m_ourVT < 0) ++ m_ourVT = vts.v_active; ++ ++ last_active = vts.v_active; ++ ++out: ++ if (cur_tty > -1) ++ close(cur_tty); ++} ++ + void CApplication::Process() + { + MEASURE_FUNCTION; +@@ -4433,6 +4528,12 @@ void CApplication::Process() + // update sound + m_pPlayer->DoAudioWork(); + ++ if( m_slowTimerVT.GetElapsedMilliseconds() > 100) ++ { ++ m_slowTimerVT.Reset(); ++ checkVTchange(); ++ } ++ + // do any processing that isn't needed on each run + if( m_slowTimer.GetElapsedMilliseconds() > 500 ) + { +@@ -4521,6 +4622,10 @@ void CApplication::ProcessSlow() + gNfsConnection.CheckIfIdle(); + #endif + ++#ifdef HAS_FILESYSTEM_AFP ++ gAfpConnection.CheckIfIdle(); ++#endif ++ + #ifdef HAS_FILESYSTEM_SFTP + CSFTPSessionManager::ClearOutIdleSessions(); + #endif +@@ -5168,7 +5273,11 @@ void CApplication::CloseNetworkShares() + #ifdef HAS_FILESYSTEM_NFS + gNfsConnection.Deinit(); + #endif +- ++ ++#ifdef HAS_FILESYSTEM_AFP ++ gAfpConnection.Deinit(); ++#endif ++ + #ifdef HAS_FILESYSTEM_SFTP + CSFTPSessionManager::DisconnectAllSessions(); + #endif +diff --git a/xbmc/Application.h b/xbmc/Application.h +index a43f802..aa1903f 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -29,11 +29,10 @@ + #include "messaging/IMessageTarget.h" + #include "ServiceManager.h" + +-#include + #include + #include + #include +-#include ++#include + + class CAction; + class CFileItem; +@@ -53,12 +52,9 @@ namespace MEDIA_DETECT + class CAutorun; + } + +-namespace PLAYLIST +-{ +- class CPlayList; +-} +- + #include "cores/IPlayerCallback.h" ++#include "cores/playercorefactory/PlayerCoreFactory.h" ++#include "PlayListPlayer.h" + #include "settings/lib/ISettingsHandler.h" + #include "settings/lib/ISettingCallback.h" + #include "settings/lib/ISubSettings.h" +@@ -76,7 +72,9 @@ namespace PLAYLIST + #include "threads/Thread.h" + + #include "ApplicationPlayer.h" +-#include "FileItem.h" ++#include "interfaces/IActionListener.h" ++ ++#include "guilib/Resolution.h" + + class CSeekHandler; + class CInertialScrollingHandler; +@@ -84,7 +82,6 @@ class DPMSSupport; + class CSplash; + class CBookmark; + class CNetwork; +-class IActionListener; + + namespace VIDEO + { +@@ -148,7 +145,7 @@ public: + virtual bool Create() override; + virtual bool Cleanup() override; + +- bool CreateGUI(); ++ bool CreateGUI(bool showXBMCSplash); + bool InitWindow(RESOLUTION res = RES_INVALID); + bool DestroyWindow(); + void StartServices(); +@@ -183,8 +180,8 @@ public: + virtual int GetMessageMask() override; + virtual void OnApplicationMessage(KODI::MESSAGING::ThreadMessage* pMsg) override; + +- bool PlayMedia(const CFileItem& item, const std::string &player, int iPlaylist); +- bool PlayMediaSync(const CFileItem& item, int iPlaylist); ++ bool PlayMedia(const CFileItem& item, const std::string &player, int iPlaylist = PLAYLIST_MUSIC); ++ bool PlayMediaSync(const CFileItem& item, int iPlaylist = PLAYLIST_MUSIC); + bool ProcessAndStartPlaylist(const std::string& strPlayList, PLAYLIST::CPlayList& playlist, int iPlaylist, int track=0); + PlayBackRet PlayFile(CFileItem item, const std::string& player, bool bRestart = false); + void SaveFileState(bool bForeground = false); +@@ -407,6 +404,9 @@ public: + */ + void UnlockFrameMoveGuard(); + ++ bool ScreenSaverDisablesAutoScrolling(); ++ void ChangeVT(int newVT); ++ + protected: + virtual bool OnSettingsSaving() const override; + +@@ -433,6 +433,9 @@ protected: + bool m_saveSkinOnUnloading; + bool m_autoExecScriptExecuted; + ++ int m_ourVT; ++ void checkVTchange(); ++ + #if defined(TARGET_DARWIN_IOS) + friend class CWinEventsIOS; + #endif +@@ -455,6 +458,7 @@ protected: + CStopWatch m_frameTime; + CStopWatch m_navigationTimer; + CStopWatch m_slowTimer; ++ CStopWatch m_slowTimerVT; + CStopWatch m_shutdownTimer; + + bool m_bInhibitIdleShutdown; +diff --git a/xbmc/ApplicationPlayer.cpp b/xbmc/ApplicationPlayer.cpp +index f163bcd..576748c 100644 +--- a/xbmc/ApplicationPlayer.cpp ++++ b/xbmc/ApplicationPlayer.cpp +@@ -20,9 +20,7 @@ + + #include "ApplicationPlayer.h" + #include "cores/IPlayer.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "Application.h" +-#include "PlayListPlayer.h" + #include "settings/MediaSettings.h" + + CApplicationPlayer::CApplicationPlayer() +diff --git a/xbmc/ApplicationPlayer.h b/xbmc/ApplicationPlayer.h +index 1cde0da..2a887f6 100644 +--- a/xbmc/ApplicationPlayer.h ++++ b/xbmc/ApplicationPlayer.h +@@ -21,12 +21,9 @@ + */ + + #include +-#include +-#include +- +-#include "threads/CriticalSection.h" + #include "threads/SystemClock.h" + #include "guilib/Resolution.h" ++#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "cores/IPlayer.h" + + typedef enum +diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp +index cd12746..fd5a5d5 100644 +--- a/xbmc/AutoSwitch.cpp ++++ b/xbmc/AutoSwitch.cpp +@@ -48,6 +48,20 @@ int CAutoSwitch::GetView(const CFileItemList &vecItems) + + switch (iCurrentWindow) + { ++ case WINDOW_MUSIC_FILES: ++ { ++ iSortMethod = METHOD_BYFOLDERTHUMBS; ++ iPercent = 50; ++ } ++ break; ++ ++ case WINDOW_VIDEO_FILES: ++ { ++ iSortMethod = METHOD_BYTHUMBPERCENT; ++ iPercent = 50; // 50% of thumbs -> use thumbs. ++ } ++ break; ++ + case WINDOW_PICTURES: + { + iSortMethod = METHOD_BYFILECOUNT; +diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp +index 909284d..fdf739a 100644 +--- a/xbmc/Autorun.cpp ++++ b/xbmc/Autorun.cpp +@@ -29,7 +29,6 @@ + #include "GUIPassword.h" + #include "GUIUserMessages.h" + #include "PlayListPlayer.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "filesystem/StackDirectory.h" + #include "filesystem/Directory.h" + #include "filesystem/DirectoryFactory.h" +@@ -201,7 +200,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAdde + + // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV"). + // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM). +- //! @todo for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically. ++ // ToDo: for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically. + if (StringUtils::EqualsNoCase(name, "BDMV") && bAllowVideo + && (bypassSettings || CSettings::GetInstance().GetBool(CSettings::SETTING_DVDS_AUTORUN))) + { +@@ -222,7 +221,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAdde + + // Check if the current foldername indicates a HD DVD structure (default is "HVDVD_TS"). + // Most HD DVD will also include an "ADV_OBJ" folder for advanced content. This folder should be handled first. +- //! @todo for the time beeing, the DVD autorun settings are used to determine if the HD DVD should be started automatically. ++ // ToDo: for the time beeing, the DVD autorun settings are used to determine if the HD DVD should be started automatically. + CFileItemList items, sitems; + + // Advanced Content HD DVD (most discs?) +@@ -383,7 +382,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAdde + bPlaying = true; + if (pItem->IsStack()) + { +- //! @todo remove this once the app/player is capable of handling stacks immediately ++ // TODO: remove this once the app/player is capable of handling stacks immediately + CStackDirectory dir; + CFileItemList items; + dir.GetDirectory(pItem->GetURL(), items); +@@ -400,8 +399,9 @@ bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAdde + if (!bypassSettings) + return false; + +- if (!g_passwordManager.IsMasterLockUnlocked(true)) +- return false; ++ if (g_windowManager.GetActiveWindow() != WINDOW_VIDEO_FILES) ++ if (!g_passwordManager.IsMasterLockUnlocked(true)) ++ return false; + } + g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); + g_playlistPlayer.Add(PLAYLIST_VIDEO, itemlist); +diff --git a/xbmc/ContextMenuItem.h b/xbmc/ContextMenuItem.h +index 27b4611..4c013b7 100644 +--- a/xbmc/ContextMenuItem.h ++++ b/xbmc/ContextMenuItem.h +@@ -61,7 +61,7 @@ private: + class CContextMenuItem : public IContextMenuItem + { + public: +- std::string GetLabel(const CFileItem& item) const override { return m_label; } ++ std::string GetLabel(const CFileItem& item) const { return m_label; } + bool IsVisible(const CFileItem& item) const override ; + bool IsParentOf(const CContextMenuItem& menuItem) const; + bool IsGroup() const override ; +diff --git a/xbmc/ContextMenuManager.cpp b/xbmc/ContextMenuManager.cpp +index 902ce1d..fc25540 100644 +--- a/xbmc/ContextMenuManager.cpp ++++ b/xbmc/ContextMenuManager.cpp +@@ -128,7 +128,7 @@ bool CContextMenuManager::IsVisible( + ContextMenuView CContextMenuManager::GetItems(const CFileItem& fileItem, const CContextMenuItem& root /*= MAIN*/) const + { + ContextMenuView result; +- //! @todo implement group support ++ //TODO: implement group support + if (&root == &MAIN) + { + CSingleLock lock(m_criticalSection); +diff --git a/xbmc/CueDocument.h b/xbmc/CueDocument.h +index d48c987..838bdd8 100644 +--- a/xbmc/CueDocument.h ++++ b/xbmc/CueDocument.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "music/Song.h" + + #define MAX_PATH_SIZE 1024 +diff --git a/xbmc/DatabaseManager.cpp b/xbmc/DatabaseManager.cpp +index ed0178d..5c13637 100644 +--- a/xbmc/DatabaseManager.cpp ++++ b/xbmc/DatabaseManager.cpp +@@ -28,7 +28,7 @@ + #include "pvr/PVRDatabase.h" + #include "epg/EpgDatabase.h" + #include "settings/AdvancedSettings.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + + using namespace EPG; + using namespace PVR; +diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in +index a4d4530..3bbab08 100644 +--- a/xbmc/DllPaths_generated.h.in ++++ b/xbmc/DllPaths_generated.h.in +@@ -28,8 +28,10 @@ + #define DLL_PATH_CPLUFF "special://xbmcbin/system/libcpluff-@ARCH@.so" + #define DLL_PATH_LIBEXIF "special://xbmcbin/system/libexif-@ARCH@.so" + ++#define DLL_PATH_LIBRTMP "@RTMP_SONAME@" + #define DLL_PATH_LIBNFS "@NFS_SONAME@" + ++#define DLL_PATH_LIBAFP "@AFPCLIENT_SONAME@" + #define DLL_PATH_LIBPLIST "@PLIST_SONAME@" + #define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@" + #define DLL_PATH_LIBCEC "@LIBCEC_SONAME@" +diff --git a/xbmc/DllPaths_generated_android.h.in b/xbmc/DllPaths_generated_android.h.in +index e05b984..e1e0136 100644 +--- a/xbmc/DllPaths_generated_android.h.in ++++ b/xbmc/DllPaths_generated_android.h.in +@@ -30,7 +30,9 @@ + #define DLL_PATH_CPLUFF "libcpluff-@ARCH@.so" + #define DLL_PATH_LIBEXIF "libexif-@ARCH@.so" + ++#define DLL_PATH_LIBRTMP "@RTMP_SONAME@" + #define DLL_PATH_LIBNFS "@NFS_SONAME@" ++#define DLL_PATH_LIBAFP "@AFPCLIENT_SONAME@" + #define DLL_PATH_LIBPLIST "@PLIST_SONAME@" + #define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@" + #define DLL_PATH_LIBCEC "@LIBCEC_SONAME@" +diff --git a/xbmc/DllPaths_win32.h b/xbmc/DllPaths_win32.h +index 3748589..ec3c346 100644 +--- a/xbmc/DllPaths_win32.h ++++ b/xbmc/DllPaths_win32.h +@@ -33,6 +33,7 @@ + /* VideoPlayer */ + #define DLL_PATH_LIBASS "special://xbmcbin/system/players/dvdplayer/libass.dll" + #define DLL_PATH_LIBDVDNAV "special://xbmcbin/system/players/VideoPlayer/libdvdnav.dll" ++#define DLL_PATH_LIBRTMP "special://xbmcbin/system/players/dvdplayer/librtmp.dll" + + /* libbluray */ + #define DLL_PATH_LIBBLURAY "special://xbmcbin/system/players/dvdplayer/libbluray.dll" +diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp +index 3cd0932..a3a5b91 100644 +--- a/xbmc/FileItem.cpp ++++ b/xbmc/FileItem.cpp +@@ -58,7 +58,6 @@ + #include "utils/log.h" + #include "utils/Variant.h" + #include "utils/Mime.h" +-#include "utils/Random.h" + + #include + #include +@@ -1066,6 +1065,11 @@ bool CFileItem::IsNfs() const + return URIUtils::IsNfs(m_strPath); + } + ++bool CFileItem::IsAfp() const ++{ ++ return URIUtils::IsAfp(m_strPath); ++} ++ + bool CFileItem::IsOnLAN() const + { + return URIUtils::IsOnLAN(m_strPath); +@@ -1312,7 +1316,7 @@ bool CFileItem::IsParentFolder() const + + void CFileItem::FillInMimeType(bool lookup /*= true*/) + { +- //! @todo adapt this to use CMime::GetMimeType() ++ // TODO: adapt this to use CMime::GetMimeType() + if (m_mimetype.empty()) + { + if( m_bIsFolder ) +@@ -1422,8 +1426,7 @@ bool CFileItem::IsAlbum() const + void CFileItem::UpdateInfo(const CFileItem &item, bool replaceLabels /*=true*/) + { + if (item.HasVideoInfoTag()) +- { // copy info across +- //! @todo premiered info is normally stored in m_dateTime by the db ++ { // copy info across (TODO: premiered info is normally stored in m_dateTime by the db) + *GetVideoInfoTag() = *item.GetVideoInfoTag(); + // preferably use some information from PVR info tag if available + if (m_pvrRecordingInfoTag) +@@ -1561,13 +1564,13 @@ std::string CFileItem::GetOpticalMediaPath() const + return dvdPath; + } + +-/** +-* @todo Ideally this (and SetPath) would not be available outside of construction +-* for CFileItem objects, or at least restricted to essentially be equivalent +-* to construction. This would require re-formulating a bunch of CFileItem +-* construction, and also allowing CFileItemList to have it's own (public) +-* SetURL() function, so for now we give direct access. +-*/ ++/* ++ TODO: Ideally this (and SetPath) would not be available outside of construction ++ for CFileItem objects, or at least restricted to essentially be equivalent ++ to construction. This would require re-formulating a bunch of CFileItem ++ construction, and also allowing CFileItemList to have it's own (public) ++ SetURL() function, so for now we give direct access. ++ */ + void CFileItem::SetURL(const CURL& url) + { + m_strPath = url.Get(); +@@ -2087,7 +2090,7 @@ void CFileItemList::Sort(SortDescription sortDescription) + void CFileItemList::Randomize() + { + CSingleLock lock(m_lock); +- KODI::UTILS::RandomShuffle(m_items.begin(), m_items.end()); ++ std::random_shuffle(m_items.begin(), m_items.end()); + } + + void CFileItemList::Archive(CArchive& ar) +@@ -2434,6 +2437,7 @@ void CFileItemList::StackFolders() + if( !item->IsRemote() + || item->IsSmb() + || item->IsNfs() ++ || item->IsAfp() + || URIUtils::IsInRAR(item->GetPath()) + || URIUtils::IsInZIP(item->GetPath()) + || URIUtils::IsOnLAN(item->GetPath()) +diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h +index 252f6c3..0b69f50 100644 +--- a/xbmc/FileItem.h ++++ b/xbmc/FileItem.h +@@ -204,6 +204,7 @@ public: + bool IsOnLAN() const; + bool IsHD() const; + bool IsNfs() const; ++ bool IsAfp() const; + bool IsRemote() const; + bool IsSmb() const; + bool IsURL() const; +diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp +index 4409dae..397401a 100644 +--- a/xbmc/GUIInfoManager.cpp ++++ b/xbmc/GUIInfoManager.cpp +@@ -44,7 +44,6 @@ + #include "music/tags/MusicInfoTag.h" + #include "guilib/IGUIContainer.h" + #include "guilib/GUIWindowManager.h" +-#include "PlayListPlayer.h" + #include "playlists/PlayList.h" + #include "profiles/ProfilesManager.h" + #include "windowing/WindowingFactory.h" +@@ -95,7 +94,7 @@ + #include "music/MusicThumbLoader.h" + #include "video/VideoDatabase.h" + #include "cores/IPlayer.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h" + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h" + #include "interfaces/info/InfoExpression.h" +@@ -3631,11 +3630,6 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, + /// _string_, + /// Todo + /// } +-// \table_row3{ `ListItem.AddonOrigin`, +-/// \anchor ListItem_AddonOrigin +-/// _string_, +-/// Name of the repository the add-on originates from. +-/// } + /// \table_end + /// + /// ----------------------------------------------------------------------------- +@@ -3809,14 +3803,12 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB }, + { "addonsummary", LISTITEM_ADDON_SUMMARY }, + { "addondescription", LISTITEM_ADDON_DESCRIPTION }, + { "addondisclaimer", LISTITEM_ADDON_DISCLAIMER }, +- { "addonnews", LISTITEM_ADDON_NEWS }, + { "addonbroken", LISTITEM_ADDON_BROKEN }, + { "addontype", LISTITEM_ADDON_TYPE }, + { "addoninstalldate", LISTITEM_ADDON_INSTALL_DATE }, + { "addonlastupdated", LISTITEM_ADDON_LAST_UPDATED }, + { "addonlastused", LISTITEM_ADDON_LAST_USED }, +- { "addonorigin", LISTITEM_ADDON_ORIGIN }, +- { "addonsize", LISTITEM_ADDON_SIZE }, ++ + }; + + /// \page modules__General__List_of_gui_access +@@ -5268,7 +5260,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + else if (cat.name == "library") + { + if (prop.name == "isscanning") return LIBRARY_IS_SCANNING; +- else if (prop.name == "isscanningvideo") return LIBRARY_IS_SCANNING_VIDEO; //! @todo change to IsScanning(Video) ++ else if (prop.name == "isscanningvideo") return LIBRARY_IS_SCANNING_VIDEO; // TODO: change to IsScanning(Video) + else if (prop.name == "isscanningmusic") return LIBRARY_IS_SCANNING_MUSIC; + else if (prop.name == "hascontent" && prop.num_params()) + { +@@ -5288,7 +5280,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + } + else if (cat.name == "musicplayer") + { +- for (size_t i = 0; i < sizeof(player_times) / sizeof(infomap); i++) //! @todo remove these, they're repeats ++ for (size_t i = 0; i < sizeof(player_times) / sizeof(infomap); i++) // TODO: remove these, they're repeats + { + if (prop.name == player_times[i].str) + return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param()))); +@@ -5306,7 +5298,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + } + else if (cat.name == "videoplayer") + { +- for (size_t i = 0; i < sizeof(player_times) / sizeof(infomap); i++) //! @todo remove these, they're repeats ++ for (size_t i = 0; i < sizeof(player_times) / sizeof(infomap); i++) // TODO: remove these, they're repeats + { + if (prop.name == player_times[i].str) + return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param()))); +@@ -5422,7 +5414,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + else if (cat.name == "window") + { + if (prop.name == "property" && prop.num_params() == 1) +- { //! @todo this doesn't support foo.xml ++ { // TODO: this doesn't support foo.xml + int winID = cat.param().empty() ? 0 : CButtonTranslator::TranslateWindow(cat.param()); + if (winID != WINDOW_INVALID) + return AddMultiInfo(GUIInfo(WINDOW_PROPERTY, winID, ConditionalStringParameter(prop.param()))); +@@ -5430,7 +5422,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + for (size_t i = 0; i < sizeof(window_bools) / sizeof(infomap); i++) + { + if (prop.name == window_bools[i].str) +- { //! @todo The parameter for these should really be on the first not the second property ++ { // TODO: The parameter for these should really be on the first not the second property + if (prop.param().find("xml") != std::string::npos) + return AddMultiInfo(GUIInfo(window_bools[i].val, 0, ConditionalStringParameter(prop.param()))); + int winID = prop.param().empty() ? WINDOW_INVALID : CButtonTranslator::TranslateWindow(prop.param()); +@@ -5443,7 +5435,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + for (size_t i = 0; i < sizeof(control_labels) / sizeof(infomap); i++) + { + if (prop.name == control_labels[i].str) +- { //! @todo The parameter for these should really be on the first not the second property ++ { // TODO: The parameter for these should really be on the first not the second property + int controlID = atoi(prop.param().c_str()); + if (controlID) + return AddMultiInfo(GUIInfo(control_labels[i].val, controlID, 0)); +@@ -5516,7 +5508,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + else if (info.size() == 3 || info.size() == 4) + { + if (info[0].name == "system" && info[1].name == "platform") +- { //! @todo replace with a single system.platform ++ { // TODO: replace with a single system.platform + std::string platform = info[2].name; + if (platform == "linux") + { +@@ -5534,7 +5526,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + else if (platform == "android") return SYSTEM_PLATFORM_ANDROID; + } + if (info[0].name == "musicplayer") +- { //! @todo these two don't allow duration(foo) and also don't allow more than this number of levels... ++ { // TODO: these two don't allow duration(foo) and also don't allow more than this number of levels... + if (info[1].name == "position") + { + int position = atoi(info[1].param().c_str()); +@@ -5579,7 +5571,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool + for (size_t i = 0; i < sizeof(control_labels) / sizeof(infomap); i++) + { + if (prop.name == control_labels[i].str) +- { //! @todo The parameter for these should really be on the first not the second property ++ { // TODO: The parameter for these should really be on the first not the second property + int controlID = atoi(prop.param().c_str()); + if (controlID) + return AddMultiInfo(GUIInfo(control_labels[i].val, controlID, atoi(info[2].param(0).c_str()))); +@@ -8654,8 +8646,8 @@ std::string CGUIInfoManager::GetVideoLabel(int item) + case VIDEOPLAYER_YEAR: + { + std::string strYear; +- if (m_currentFile->GetVideoInfoTag()->HasYear()) +- strYear = StringUtils::Format("%i", m_currentFile->GetVideoInfoTag()->GetYear()); ++ if (m_currentFile->GetVideoInfoTag()->m_iYear > 0) ++ strYear = StringUtils::Format("%i", m_currentFile->GetVideoInfoTag()->m_iYear); + return strYear; + } + break; +@@ -8664,8 +8656,8 @@ std::string CGUIInfoManager::GetVideoLabel(int item) + CDateTime dateTime; + if (m_currentFile->GetVideoInfoTag()->m_firstAired.IsValid()) + dateTime = m_currentFile->GetVideoInfoTag()->m_firstAired; +- else if (m_currentFile->GetVideoInfoTag()->HasPremiered()) +- dateTime = m_currentFile->GetVideoInfoTag()->GetPremiered(); ++ else if (m_currentFile->GetVideoInfoTag()->m_premiered.IsValid()) ++ dateTime = m_currentFile->GetVideoInfoTag()->m_premiered; + + if (dateTime.IsValid()) + return dateTime.GetAsLocalizedDate(); +@@ -9403,8 +9395,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + case LISTITEM_YEAR: + { + std::string year; +- if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->HasYear()) +- year = StringUtils::Format("%i", item->GetVideoInfoTag()->GetYear()); ++ if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iYear > 0) ++ year = StringUtils::Format("%i", item->GetVideoInfoTag()->m_iYear); + if (item->HasMusicInfoTag()) + year = item->GetMusicInfoTag()->GetYearString(); + if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->Year() > 0) +@@ -9415,8 +9407,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + if (tag && tag->Year() > 0) + year = StringUtils::Format("%i", tag->Year()); + } +- if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag()->HasYear()) +- year = StringUtils::Format("%i", item->GetPVRRecordingInfoTag()->GetYear()); ++ if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag()->m_iYear > 0) ++ year = StringUtils::Format("%i", item->GetPVRRecordingInfoTag()->m_iYear); + return year; + } + case LISTITEM_PREMIERED: +@@ -9425,8 +9417,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + CDateTime dateTime; + if (item->GetVideoInfoTag()->m_firstAired.IsValid()) + dateTime = item->GetVideoInfoTag()->m_firstAired; +- else if (item->GetVideoInfoTag()->HasPremiered()) +- dateTime = item->GetVideoInfoTag()->GetPremiered(); ++ else if (item->GetVideoInfoTag()->m_premiered.IsValid()) ++ dateTime = item->GetVideoInfoTag()->m_premiered; + + if (dateTime.IsValid()) + return dateTime.GetAsLocalizedDate(); +@@ -9937,8 +9929,6 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + return item->GetEPGInfoTag()->EndAsLocalTime().GetAsLocalizedTime("", false); + else if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->EndAsLocalTime().GetAsLocalizedTime("", false); +- else if (item->HasPVRRecordingInfoTag()) +- return (item->GetPVRRecordingInfoTag()->RecordingTimeAsLocalTime() + CDateTimeSpan(0, 0, 0, item->GetPVRRecordingInfoTag()->GetDuration())).GetAsLocalizedTime("", false); + else if (item->HasVideoInfoTag()) + { + CDateTimeSpan duration(0, 0, 0, item->GetVideoInfoTag()->GetDuration()); +@@ -10206,10 +10196,6 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + if (item->HasAddonInfo()) + return item->GetAddonInfo()->Disclaimer(); + break; +- case LISTITEM_ADDON_NEWS: +- if (item->HasAddonInfo()) +- return item->GetAddonInfo()->ChangeLog(); +- break; + case LISTITEM_ADDON_BROKEN: + if (item->HasAddonInfo()) + { +@@ -10234,21 +10220,6 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std:: + if (item->HasAddonInfo() && item->GetAddonInfo()->LastUsed().IsValid()) + return item->GetAddonInfo()->LastUsed().GetAsLocalizedDateTime(); + break; +- case LISTITEM_ADDON_ORIGIN: +- if (item->HasAddonInfo()) +- { +- if (item->GetAddonInfo()->Origin() == ORIGIN_SYSTEM) +- return g_localizeStrings.Get(24992); +- AddonPtr origin; +- if (CAddonMgr::GetInstance().GetAddon(item->GetAddonInfo()->Origin(), origin, ADDON_UNKNOWN, false)) +- return origin->Name(); +- return g_localizeStrings.Get(13205); +- } +- break; +- case LISTITEM_ADDON_SIZE: +- if (item->HasAddonInfo() && item->GetAddonInfo()->PackageSize() > 0) +- return StringUtils::FormatFileSize(item->GetAddonInfo()->PackageSize()); +- break; + } + + return ""; +diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h +index 1d08e8d..c2deb97 100644 +--- a/xbmc/GUIInfoManager.h ++++ b/xbmc/GUIInfoManager.h +@@ -40,7 +40,6 @@ + + #include + #include +-#include + + namespace MUSIC_INFO + { +diff --git a/xbmc/GUILargeTextureManager.h b/xbmc/GUILargeTextureManager.h +index 87ba927..cc6cb3e 100644 +--- a/xbmc/GUILargeTextureManager.h ++++ b/xbmc/GUILargeTextureManager.h +@@ -21,7 +21,6 @@ + */ + + #include +-#include + + #include "guilib/TextureManager.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/GUIPassword.cpp b/xbmc/GUIPassword.cpp +index 2c6de48..bec47d7 100644 +--- a/xbmc/GUIPassword.cpp ++++ b/xbmc/GUIPassword.cpp +@@ -373,13 +373,21 @@ bool CGUIPassword::CheckMenuLock(int iWindowID) + iSwitch = WINDOW_SETTINGS_MENU; + } + ++ if (iWindowID == WINDOW_MUSIC_FILES) ++ if (g_windowManager.GetActiveWindow() == WINDOW_MUSIC_NAV) ++ iSwitch = WINDOW_HOME; ++ + if (iWindowID == WINDOW_MUSIC_NAV) + if (g_windowManager.GetActiveWindow() == WINDOW_HOME) +- iSwitch = WINDOW_MUSIC_NAV; ++ iSwitch = WINDOW_MUSIC_FILES; + + if (iWindowID == WINDOW_VIDEO_NAV) + if (g_windowManager.GetActiveWindow() == WINDOW_HOME) +- iSwitch = WINDOW_VIDEO_NAV; ++ iSwitch = WINDOW_VIDEO_FILES; ++ ++ if (iWindowID == WINDOW_VIDEO_FILES) ++ if (g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV) ++ iSwitch = WINDOW_HOME; + + switch (iSwitch) + { +@@ -395,10 +403,10 @@ bool CGUIPassword::CheckMenuLock(int iWindowID) + case WINDOW_PROGRAMS: // Programs + bCheckPW = CProfilesManager::GetInstance().GetCurrentProfile().programsLocked(); + break; +- case WINDOW_MUSIC_NAV: // Music ++ case WINDOW_MUSIC_FILES: // Music + bCheckPW = CProfilesManager::GetInstance().GetCurrentProfile().musicLocked(); + break; +- case WINDOW_VIDEO_NAV: // Video ++ case WINDOW_VIDEO_FILES: // Video + bCheckPW = CProfilesManager::GetInstance().GetCurrentProfile().videoLocked(); + break; + case WINDOW_PICTURES: // Pictures +diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp +index 63112f5..f049188 100644 +--- a/xbmc/LangInfo.cpp ++++ b/xbmc/LangInfo.cpp +@@ -310,7 +310,7 @@ void CLangInfo::CRegion::SetGlobalLocale() + strLocale = "C"; + } + +- g_langInfo.m_systemLocale = current_locale; //! @todo move to CLangInfo class ++ g_langInfo.m_systemLocale = current_locale; // TODO: move to CLangInfo class + std::locale::global(current_locale); + #endif + g_charsetConverter.resetSystemCharset(); +@@ -667,20 +667,7 @@ bool CLangInfo::SetLanguage(bool& fallback, const std::string &strLanguage /* = + } + } + +- LanguageResourcePtr languageAddon; +- { +- std::string addonId = ADDON::CLanguageResource::GetAddonId(language); +- if (addonId.empty()) +- addonId = CSettings::GetInstance().GetString(CSettings::SETTING_LOCALE_LANGUAGE); +- +- ADDON::AddonPtr addon; +- if (ADDON::CAddonMgr::GetInstance().GetAddon(addonId, addon, ADDON::ADDON_RESOURCE_LANGUAGE, false)) +- { +- languageAddon = std::static_pointer_cast(addon); +- ADDON::CAddonMgr::GetInstance().EnableAddon(languageAddon->ID()); +- } +- } +- ++ LanguageResourcePtr languageAddon = GetLanguageAddon(language); + if (languageAddon == NULL) + { + CLog::Log(LOGWARNING, "CLangInfo: unable to load language \"%s\". Trying to determine matching language addon...", language.c_str()); +diff --git a/xbmc/PartyModeManager.cpp b/xbmc/PartyModeManager.cpp +index 8ec533f..9c9ce90 100644 +--- a/xbmc/PartyModeManager.cpp ++++ b/xbmc/PartyModeManager.cpp +@@ -36,7 +36,6 @@ + #include "profiles/ProfilesManager.h" + #include "threads/SystemClock.h" + #include "utils/log.h" +-#include "utils/Random.h" + #include "utils/StringUtils.h" + #include "utils/Variant.h" + #include "video/VideoDatabase.h" +@@ -645,7 +644,7 @@ bool CPartyModeManager::AddInitialSongs(std::vector< std::pair > &song + { + CFileItemPtr item(items[i]); + Add(item); +- //! @todo Allow "relaxed restrictions" later? ++ // TODO: Allow "relaxed restrictions" later? + } + } + return true; +@@ -694,7 +693,7 @@ void CPartyModeManager::AddToHistory(int type, int songID) + void CPartyModeManager::GetRandomSelection(std::vector< std::pair >& in, unsigned int number, std::vector< std::pair >& out) + { + number = std::min(number, (unsigned int)in.size()); +- KODI::UTILS::RandomShuffle(in.begin(), in.end()); ++ std::random_shuffle(in.begin(), in.end()); + out.assign(in.begin(), in.begin() + number); + } + +diff --git a/xbmc/PlayListPlayer.cpp b/xbmc/PlayListPlayer.cpp +index 577409c..3e5e4c2 100644 +--- a/xbmc/PlayListPlayer.cpp ++++ b/xbmc/PlayListPlayer.cpp +@@ -335,9 +335,9 @@ bool CPlayListPlayer::Play(int iSong, std::string player, bool bAutoPlay /* = fa + if (item->m_lStartOffset == STARTOFFSET_RESUME) + item->m_lStartOffset = 0; + +- //! @todo - move the above failure logic and the below success logic +- //! to callbacks instead so we don't rely on the return value +- //! of PlayFile() ++ // TODO - move the above failure logic and the below success logic ++ // to callbacks instead so we don't rely on the return value ++ // of PlayFile() + + // consecutive error counter so reset if the current item is playing + m_iFailedSongs = 0; +@@ -904,7 +904,6 @@ void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMess + g_windowManager.PreviousWindow(); + + g_application.ResetScreenSaver(); +- g_application.WakeUpScreenSaverAndDPMS(); + + // stop playing file + if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying(); +@@ -915,7 +914,6 @@ void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMess + if (g_application.m_pPlayer->HasPlayer()) + { + g_application.ResetScreenSaver(); +- g_application.WakeUpScreenSaverAndDPMS(); + g_application.m_pPlayer->Pause(); + } + break; +@@ -933,7 +931,6 @@ void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMess + if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) + { + g_application.ResetScreenSaver(); +- g_application.WakeUpScreenSaverAndDPMS(); + g_application.m_pPlayer->Pause(); + } + break; +diff --git a/xbmc/ServiceManager.cpp b/xbmc/ServiceManager.cpp +index 3cc188c..be05791 100644 +--- a/xbmc/ServiceManager.cpp ++++ b/xbmc/ServiceManager.cpp +@@ -19,13 +19,10 @@ + */ + + #include "ServiceManager.h" +-#include "addons/BinaryAddonCache.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "utils/log.h" + #include "interfaces/AnnouncementManager.h" + #include "interfaces/generic/ScriptInvocationManager.h" +-#include "interfaces/python/XBPython.h" +-#include "pvr/PVRManager.h" + + bool CServiceManager::Init1() + { +diff --git a/xbmc/ServiceManager.h b/xbmc/ServiceManager.h +index 9b7806f..cdb8399 100644 +--- a/xbmc/ServiceManager.h ++++ b/xbmc/ServiceManager.h +@@ -20,6 +20,10 @@ + + #pragma once + ++#include "addons/AddonManager.h" ++#include "addons/BinaryAddonCache.h" ++#include "interfaces/python/XBPython.h" ++#include "pvr/PVRManager.h" + #include + + namespace ADDON { +@@ -41,8 +45,6 @@ namespace PVR + class CPVRManager; + } + +-class XBPython; +- + class CServiceManager + { + public: +diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp +index bcd16c0..159310b 100644 +--- a/xbmc/TextureCache.cpp ++++ b/xbmc/TextureCache.cpp +@@ -168,7 +168,7 @@ bool CTextureCache::CacheImage(const std::string &image, CTextureDetails &detail + + void CTextureCache::ClearCachedImage(const std::string &url, bool deleteSource /*= false */) + { +- //! @todo This can be removed when the texture cache covers everything. ++ // TODO: This can be removed when the texture cache covers everything. + std::string path = deleteSource ? url : ""; + std::string cachedFile; + if (ClearCachedTexture(url, cachedFile)) +diff --git a/xbmc/TextureCache.h b/xbmc/TextureCache.h +index 696a64b..b4f07cd 100644 +--- a/xbmc/TextureCache.h ++++ b/xbmc/TextureCache.h +@@ -154,7 +154,7 @@ public: + \return true if we successfully exported the file, false otherwise. + */ + bool Export(const std::string &image, const std::string &destination, bool overwrite); +- bool Export(const std::string &image, const std::string &destination); //! @todo BACKWARD COMPATIBILITY FOR MUSIC THUMBS ++ bool Export(const std::string &image, const std::string &destination); // TODO: BACKWARD COMPATIBILITY FOR MUSIC THUMBS + private: + // private construction, and no assignements; use the provided singleton methods + CTextureCache(); +diff --git a/xbmc/TextureDatabase.cpp b/xbmc/TextureDatabase.cpp +index 9608243..db372e9 100644 +--- a/xbmc/TextureDatabase.cpp ++++ b/xbmc/TextureDatabase.cpp +@@ -183,7 +183,7 @@ void CTextureDatabase::CreateAnalytics() + m_pDS->exec("CREATE INDEX idxTexture ON texture(url)"); + m_pDS->exec("CREATE INDEX idxSize ON sizes(idtexture, size)"); + m_pDS->exec("CREATE INDEX idxSize2 ON sizes(idtexture, width, height)"); +- //! @todo Should the path index be a covering index? (we need only retrieve texture) ++ // TODO: Should the path index be a covering index? (we need only retrieve texture) + m_pDS->exec("CREATE INDEX idxPath ON path(url, type)"); + + CLog::Log(LOGINFO, "%s creating triggers", __FUNCTION__); +diff --git a/xbmc/TextureDatabase.h b/xbmc/TextureDatabase.h +index 9df9ca1..75676e4 100644 +--- a/xbmc/TextureDatabase.h ++++ b/xbmc/TextureDatabase.h +@@ -20,9 +20,6 @@ + + #pragma once + +-#include +-#include +- + #include "dbwrappers/Database.h" + #include "TextureCacheJob.h" + #include "dbwrappers/DatabaseQuery.h" +diff --git a/xbmc/ThumbnailCache.cpp b/xbmc/ThumbnailCache.cpp +index 6e60e06..9e3ff02 100644 +--- a/xbmc/ThumbnailCache.cpp ++++ b/xbmc/ThumbnailCache.cpp +@@ -23,6 +23,7 @@ + #include "threads/SingleLock.h" + + #include "FileItem.h" ++#include "video/VideoDatabase.h" + + using namespace XFILE; + using namespace MUSIC_INFO; +diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp +index cc734ad..a53b035 100644 +--- a/xbmc/URL.cpp ++++ b/xbmc/URL.cpp +@@ -152,6 +152,7 @@ void CURL::Parse(const std::string& strURL1) + IsProtocol("stack") || + IsProtocol("virtualpath") || + IsProtocol("multipath") || ++ IsProtocol("filereader") || + IsProtocol("special") || + IsProtocol("resource") + ) +@@ -179,7 +180,7 @@ void CURL::Parse(const std::string& strURL1) + size_t iEnd = strURL.length(); + const char* sep = NULL; + +- //! @todo fix all Addon paths ++ //TODO fix all Addon paths + std::string strProtocol2 = GetTranslatedProtocol(); + if(IsProtocol("rss") || + IsProtocol("rar") || +@@ -291,6 +292,8 @@ void CURL::Parse(const std::string& strURL1) + if (m_strHostName.empty()) + m_strHostName = strHostNameAndPort; + ++ m_strHostName = URIUtils::CanonizeIPv6(m_strHostName); ++ + if (iSlash != std::string::npos) + { + iPos = iSlash + 1; +@@ -791,7 +794,7 @@ std::string CURL::Encode(const std::string& strURLData) + const char kar = strURLData[i]; + + // Don't URL encode "-_.!()" according to RFC1738 +- //! @todo Update it to "-_.~" after Gotham according to RFC3986 ++ // TODO: Update it to "-_.~" after Gotham according to RFC3986 + if (StringUtils::isasciialphanum(kar) || kar == '-' || kar == '.' || kar == '_' || kar == '!' || kar == '(' || kar == ')') + strResult.push_back(kar); + else +diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp +index b0de1c8..9996881 100644 +--- a/xbmc/Util.cpp ++++ b/xbmc/Util.cpp +@@ -793,8 +793,8 @@ bool CUtil::CreateDirectoryEx(const std::string& strPath) + // return true if directory already exist + if (CDirectory::Exists(strPath)) return true; + +- // we currently only allow HD and smb and nfs paths +- if (!URIUtils::IsHD(strPath) && !URIUtils::IsSmb(strPath) && !URIUtils::IsNfs(strPath)) ++ // we currently only allow HD and smb, nfs and afp paths ++ if (!URIUtils::IsHD(strPath) && !URIUtils::IsSmb(strPath) && !URIUtils::IsNfs(strPath) && !URIUtils::IsAfp(strPath)) + { + CLog::Log(LOGERROR,"%s called with an unsupported path: %s", __FUNCTION__, strPath.c_str()); + return false; +@@ -846,8 +846,8 @@ std::string CUtil::MakeLegalPath(const std::string &strPathAndFile, int LegalTyp + return MakeLegalPath(CStackDirectory::GetFirstStackedFile(strPathAndFile)); + if (URIUtils::IsMultiPath(strPathAndFile)) + return MakeLegalPath(CMultiPathDirectory::GetFirstPath(strPathAndFile)); +- if (!URIUtils::IsHD(strPathAndFile) && !URIUtils::IsSmb(strPathAndFile) && !URIUtils::IsNfs(strPathAndFile)) +- return strPathAndFile; // we don't support writing anywhere except HD, SMB and NFS - no need to legalize path ++ if (!URIUtils::IsHD(strPathAndFile) && !URIUtils::IsSmb(strPathAndFile) && !URIUtils::IsNfs(strPathAndFile) && !URIUtils::IsAfp(strPathAndFile)) ++ return strPathAndFile; // we don't support writing anywhere except HD, SMB, NFS and AFP - no need to legalize path + + bool trailingSlash = URIUtils::HasSlashAtEnd(strPathAndFile); + std::vector dirs = URIUtils::SplitPath(strPathAndFile); +@@ -1378,7 +1378,7 @@ bool CUtil::MakeShortenPath(std::string StrInput, std::string& StrOutput, size_t + + bool CUtil::SupportsWriteFileOperations(const std::string& strPath) + { +- // currently only hd, smb, nfs and dav support delete and rename ++ // currently only hd, smb, nfs, afp and dav support delete and rename + if (URIUtils::IsHD(strPath)) + return true; + if (URIUtils::IsSmb(strPath)) +@@ -1387,6 +1387,8 @@ bool CUtil::SupportsWriteFileOperations(const std::string& strPath) + return CPVRDirectory::SupportsWriteFileOperations(strPath); + if (URIUtils::IsNfs(strPath)) + return true; ++ if (URIUtils::IsAfp(strPath)) ++ return true; + if (URIUtils::IsDAV(strPath)) + return true; + if (URIUtils::IsStack(strPath)) +@@ -1463,7 +1465,7 @@ bool CUtil::RunCommandLine(const std::string& cmdLine, bool waitExit) + // Strip quotes and whitespace around the arguments, or exec will fail. + // This allows the python invocation to be written more naturally with any amount of whitespace around the args. + // But it's still limited, for example quotes inside the strings are not expanded, etc. +- //! @todo Maybe some python library routine can parse this more properly ? ++ // TODO: Maybe some python library routine can parse this more properly ? + for (std::vector::iterator it = args.begin(); it != args.end(); ++it) + { + size_t pos; +@@ -1886,7 +1888,7 @@ void CUtil::ScanForExternalSubtitles(const std::string& strMovie, std::vector(localAddon)); + + //Fallback to the pre-install callback in the addon. +- //! @bug If primary extension point have changed we're calling the wrong method. ++ //BUG: If primary extension point have changed we're calling the wrong method. + addon->OnPreInstall(); + } + +diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h +index acc489b..2f00e04 100644 +--- a/xbmc/addons/Addon.h ++++ b/xbmc/addons/Addon.h +@@ -38,8 +38,6 @@ namespace ADDON + typedef std::vector VECADDONS; + typedef std::vector::iterator IVECADDONS; + +- const char* const ORIGIN_SYSTEM = "b6a50484-93a0-4afb-a01c-8d17e059feda"; +- + // utils + std::string TranslateType(TYPE type, bool pretty=false); + std::string GetIcon(TYPE type); +@@ -56,8 +54,8 @@ void OnPostUnInstall(const AddonPtr& addon); + class AddonProps + { + public: +- AddonProps() : type(ADDON_UNKNOWN), packageSize(0) {}; +- AddonProps(std::string id, TYPE type) : id(std::move(id)), type(type), packageSize(0) {} ++ AddonProps() : type(ADDON_UNKNOWN) {}; ++ AddonProps(std::string id, TYPE type) : id(std::move(id)), type(type) {} + + std::string id; + TYPE type; +@@ -70,10 +68,10 @@ public: + std::string libname; + std::string author; + std::string source; +- //! @todo fix parts relying on mutating these ++ //TODO: fix parts relying on mutating these + mutable std::string path; + mutable std::string icon; +- std::string changelog; ++ mutable std::string changelog; + mutable std::string fanart; + std::string disclaimer; + ADDONDEPS dependencies; +@@ -82,8 +80,6 @@ public: + CDateTime installDate; + CDateTime lastUpdated; + CDateTime lastUsed; +- std::string origin; +- uint64_t packageSize; + }; + + +@@ -116,8 +112,6 @@ public: + CDateTime InstallDate() const override { return m_props.installDate; } + CDateTime LastUpdated() const override { return m_props.lastUpdated; } + CDateTime LastUsed() const override { return m_props.lastUsed; } +- std::string Origin() const override { return m_props.origin; } +- uint64_t PackageSize() const override { return m_props.packageSize; } + const InfoMap& ExtraInfo() const override { return m_props.extrainfo; } + const ADDONDEPS& GetDeps() const override { return m_props.dependencies; } + +diff --git a/xbmc/addons/AddonBuilder.cpp b/xbmc/addons/AddonBuilder.cpp +index 835b439..347153f 100644 +--- a/xbmc/addons/AddonBuilder.cpp ++++ b/xbmc/addons/AddonBuilder.cpp +@@ -27,14 +27,13 @@ + #include "addons/LanguageResource.h" + #include "addons/PluginSource.h" + #include "addons/Repository.h" +-#include "addons/Scraper.h" + #include "addons/ScreenSaver.h" + #include "addons/Service.h" + #include "addons/Skin.h" + #include "addons/UISoundsResource.h" + #include "addons/Visualisation.h" + #include "addons/Webinterface.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h" + #include "games/controllers/Controller.h" + #include "peripherals/addons/PeripheralAddon.h" + #include "addons/PVRClient.h" +@@ -214,7 +213,7 @@ AddonPtr CAddonBuilder::FromProps(AddonProps addonProps) + case ADDON_INPUTSTREAM: + return AddonPtr(new CInputStream(std::move(addonProps))); + case ADDON_PERIPHERALDLL: +- return AddonPtr(new PERIPHERALS::CPeripheralAddon(std::move(addonProps), false, false)); //! @todo implement ++ return AddonPtr(new PERIPHERALS::CPeripheralAddon(std::move(addonProps), false, false)); // TODO + case ADDON_GAME_CONTROLLER: + return AddonPtr(new GAME::CController(std::move(addonProps))); + default: +diff --git a/xbmc/addons/AddonBuilder.h b/xbmc/addons/AddonBuilder.h +index 074f7eb..0eef650 100644 +--- a/xbmc/addons/AddonBuilder.h ++++ b/xbmc/addons/AddonBuilder.h +@@ -53,8 +53,6 @@ public: + void SetInstallDate(CDateTime installDate) { m_props.installDate = installDate; } + void SetLastUpdated(CDateTime lastUpdated) { m_props.lastUpdated = lastUpdated; } + void SetLastUsed(CDateTime lastUsed) { m_props.lastUsed = lastUsed; } +- void SetOrigin(std::string origin) { m_props.origin = std::move(origin); } +- void SetPackageSize(uint64_t size) { m_props.packageSize = size; } + + const std::string& GetId() const { return m_props.id; } + const AddonVersion& GetVersion() const { return m_props.version; } +diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp +index 6f49f14..d23be26 100644 +--- a/xbmc/addons/AddonDatabase.cpp ++++ b/xbmc/addons/AddonDatabase.cpp +@@ -28,8 +28,6 @@ + #include "addons/AddonManager.h" + #include "dbwrappers/dataset.h" + #include "filesystem/SpecialProtocol.h" +-#include "utils/JSONVariantParser.h" +-#include "utils/JSONVariantWriter.h" + #include "utils/log.h" + #include "utils/StringUtils.h" + #include "utils/Variant.h" +@@ -38,72 +36,6 @@ + + using namespace ADDON; + +-static std::string SerializeMetadata(const IAddon& addon) +-{ +- CVariant variant; +- variant["author"] = addon.Author(); +- variant["disclaimer"] = addon.Disclaimer(); +- variant["broken"] = addon.Broken(); +- variant["size"] = addon.PackageSize(); +- +- variant["path"] = addon.Path(); +- variant["fanart"] = addon.FanArt(); +- variant["icon"] = addon.Icon(); +- +- variant["extensions"] = CVariant(CVariant::VariantTypeArray); +- variant["extensions"].push_back(ADDON::TranslateType(addon.Type(), false)); +- +- variant["dependencies"] = CVariant(CVariant::VariantTypeArray); +- for (const auto& kv : addon.GetDeps()) +- { +- CVariant dep(CVariant::VariantTypeObject); +- dep["addonId"] = kv.first; +- dep["version"] = kv.second.first.asString(); +- dep["optional"] = kv.second.second; +- variant["dependencies"].push_back(std::move(dep)); +- } +- +- variant["extrainfo"] = CVariant(CVariant::VariantTypeArray); +- for (const auto& kv : addon.ExtraInfo()) +- { +- CVariant info(CVariant::VariantTypeObject); +- info["key"] = kv.first; +- info["value"] = kv.second; +- variant["extrainfo"].push_back(std::move(info)); +- } +- +- return CJSONVariantWriter::Write(variant, true); +-} +- +-static void DeserializeMetadata(const std::string& document, CAddonBuilder& builder) +-{ +- CVariant variant = CJSONVariantParser::Parse(document); +- +- builder.SetAuthor(variant["author"].asString()); +- builder.SetDisclaimer(variant["disclaimer"].asString()); +- builder.SetBroken(variant["broken"].asString()); +- builder.SetPackageSize(variant["size"].asUnsignedInteger()); +- +- builder.SetPath(variant["path"].asString()); +- builder.SetFanart(variant["fanart"].asString()); +- builder.SetIcon(variant["icon"].asString()); +- +- builder.SetType(TranslateType(variant["extensions"][0].asString())); +- +- ADDONDEPS deps; +- for (auto it = variant["dependencies"].begin_array(); it != variant["dependencies"].end_array(); ++it) +- { +- AddonVersion version((*it)["version"].asString()); +- deps.emplace((*it)["addonId"].asString(), std::make_pair(std::move(version), (*it)["optional"].asBoolean())); +- } +- builder.SetDependencies(std::move(deps)); +- +- InfoMap extraInfo; +- for (auto it = variant["extrainfo"].begin_array(); it != variant["extrainfo"].end_array(); ++it) +- extraInfo.emplace((*it)["key"].asString(), (*it)["value"].asString()); +- builder.SetExtrainfo(std::move(extraInfo)); +-} +- + CAddonDatabase::CAddonDatabase() + { + } +@@ -124,20 +56,23 @@ int CAddonDatabase::GetMinSchemaVersion() const + + int CAddonDatabase::GetSchemaVersion() const + { +- return 26; ++ return 24; + } + + void CAddonDatabase::CreateTables() + { +- CLog::Log(LOGINFO, "create addons table"); +- m_pDS->exec("CREATE TABLE addons (" +- "id INTEGER PRIMARY KEY," +- "metadata BLOB," +- "addonID TEXT NOT NULL," +- "version TEXT NOT NULL," +- "name TEXT NOT NULL," +- "summary TEXT NOT NULL," +- "description TEXT NOT NULL)"); ++ CLog::Log(LOGINFO, "create addon table"); ++ m_pDS->exec("CREATE TABLE addon (id integer primary key, type text," ++ "name text, summary text, description text, stars integer," ++ "path text, addonID text, icon text, version text, " ++ "changelog text, fanart text, author text, disclaimer text," ++ "minversion text)\n"); ++ ++ CLog::Log(LOGINFO, "create addonextra table"); ++ m_pDS->exec("CREATE TABLE addonextra (id integer, key text, value text)\n"); ++ ++ CLog::Log(LOGINFO, "create dependencies table"); ++ m_pDS->exec("CREATE TABLE dependencies (id integer, addon text, version text, optional boolean)\n"); + + CLog::Log(LOGINFO, "create repo table"); + m_pDS->exec("CREATE TABLE repo (id integer primary key, addonID text," +@@ -157,14 +92,15 @@ void CAddonDatabase::CreateTables() + + CLog::Log(LOGINFO, "create installed table"); + m_pDS->exec("CREATE TABLE installed (id INTEGER PRIMARY KEY, addonID TEXT UNIQUE, " +- "enabled BOOLEAN, installDate TEXT, lastUpdated TEXT, lastUsed TEXT, " +- "origin TEXT NOT NULL DEFAULT '') \n"); ++ "enabled BOOLEAN, installDate TEXT, lastUpdated TEXT, lastUsed TEXT) \n"); + } + + void CAddonDatabase::CreateAnalytics() + { + CLog::Log(LOGINFO, "%s creating indicies", __FUNCTION__); +- m_pDS->exec("CREATE INDEX idxAddons ON addons(addonID)"); ++ m_pDS->exec("CREATE INDEX idxAddon ON addon(addonID)"); ++ m_pDS->exec("CREATE INDEX idxAddonExtra ON addonextra(id)"); ++ m_pDS->exec("CREATE INDEX idxDependencies ON dependencies(id)"); + m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_1 ON addonlinkrepo ( idAddon, idRepo )\n"); + m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_2 ON addonlinkrepo ( idRepo, idAddon )\n"); + m_pDS->exec("CREATE UNIQUE INDEX idxBroken ON broken(addonID)"); +@@ -272,26 +208,6 @@ void CAddonDatabase::UpdateTables(int version) + m_pDS->exec("DELETE FROM addonlinkrepo"); + m_pDS->exec("DELETE FROM repo"); + } +- if (version < 25) +- { +- m_pDS->exec("ALTER TABLE installed ADD origin TEXT NOT NULL DEFAULT ''"); +- } +- if (version < 26) +- { +- m_pDS->exec("DROP TABLE addon"); +- m_pDS->exec("DROP TABLE addonextra"); +- m_pDS->exec("DROP TABLE dependencies"); +- m_pDS->exec("DELETE FROM addonlinkrepo"); +- m_pDS->exec("DELETE FROM repo"); +- m_pDS->exec("CREATE TABLE addons (" +- "id INTEGER PRIMARY KEY," +- "metadata BLOB," +- "addonID TEXT NOT NULL," +- "version TEXT NOT NULL," +- "name TEXT NOT NULL," +- "summary TEXT NOT NULL," +- "description TEXT NOT NULL)"); +- } + } + + void CAddonDatabase::SyncInstalled(const std::set& ids, +@@ -344,12 +260,7 @@ void CAddonDatabase::SyncInstalled(const std::set& ids, + } + + for (const auto& id : system) +- { + m_pDS->exec(PrepareSQL("UPDATE installed SET enabled=1 WHERE addonID='%s'", id.c_str())); +- // Set origin *only* for addons that do not have one yet as it may have been changed by an update. +- m_pDS->exec(PrepareSQL("UPDATE installed SET origin='%s' WHERE addonID='%s' AND origin=''", +- ORIGIN_SYSTEM, id.c_str())); +- } + + CommitTransaction(); + } +@@ -375,7 +286,6 @@ void CAddonDatabase::GetInstalled(std::vector& addons) + it->SetInstallDate(CDateTime::FromDBDateTime(m_pDS->fv(3).get_asString())); + it->SetLastUpdated(CDateTime::FromDBDateTime(m_pDS->fv(4).get_asString())); + it->SetLastUsed(CDateTime::FromDBDateTime(m_pDS->fv(5).get_asString())); +- it->SetOrigin(m_pDS->fv(6).get_asString()); + m_pDS->next(); + } + m_pDS->close(); +@@ -404,14 +314,18 @@ bool CAddonDatabase::SetLastUpdated(const std::string& addonId, const CDateTime& + return false; + } + +-bool CAddonDatabase::SetOrigin(const std::string& addonId, const std::string& origin) ++bool CAddonDatabase::SetLastUsed(const std::string& addonId, const CDateTime& dateTime) + { + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + +- m_pDS->exec(PrepareSQL("UPDATE installed SET origin='%s' WHERE addonID='%s'", origin.c_str(), addonId.c_str())); ++ auto start = XbmcThreads::SystemClockMillis(); ++ m_pDS->exec(PrepareSQL("UPDATE installed SET lastUsed='%s' WHERE addonID='%s'", ++ dateTime.GetAsDBDateTime().c_str(), addonId.c_str())); ++ ++ CLog::Log(LOGDEBUG, "CAddonDatabase::SetLastUsed[%s] took %i ms", addonId.c_str(), XbmcThreads::SystemClockMillis() - start); + return true; + } + catch (...) +@@ -421,25 +335,51 @@ bool CAddonDatabase::SetOrigin(const std::string& addonId, const std::string& or + return false; + } + +-bool CAddonDatabase::SetLastUsed(const std::string& addonId, const CDateTime& dateTime) ++int CAddonDatabase::AddAddon(const AddonPtr& addon, int idRepo) + { + try + { +- if (NULL == m_pDB.get()) return false; +- if (NULL == m_pDS.get()) return false; ++ if (NULL == m_pDB.get()) return -1; ++ if (NULL == m_pDS.get()) return -1; + +- auto start = XbmcThreads::SystemClockMillis(); +- m_pDS->exec(PrepareSQL("UPDATE installed SET lastUsed='%s' WHERE addonID='%s'", +- dateTime.GetAsDBDateTime().c_str(), addonId.c_str())); ++ std::string sql = PrepareSQL("insert into addon (id, type, name, summary," ++ "description, path, icon, changelog, " ++ "fanart, addonID, version, author, disclaimer, minversion)" ++ " values(NULL, '%s', '%s', '%s', '%s'," ++ "'%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s')", ++ TranslateType(addon->Type(),false).c_str(), ++ addon->Name().c_str(), addon->Summary().c_str(), ++ addon->Description().c_str(), ++ addon->Path().c_str(), addon->Icon().c_str(), ++ addon->ChangeLog().c_str(),addon->FanArt().c_str(), ++ addon->ID().c_str(), addon->Version().asString().c_str(), ++ addon->Author().c_str(),addon->Disclaimer().c_str(), ++ addon->MinVersion().asString().c_str()); ++ m_pDS->exec(sql); ++ int idAddon = (int)m_pDS->lastinsertid(); + +- CLog::Log(LOGDEBUG, "CAddonDatabase::SetLastUsed[%s] took %i ms", addonId.c_str(), XbmcThreads::SystemClockMillis() - start); +- return true; ++ sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon); ++ m_pDS->exec(sql); ++ ++ const InfoMap &info = addon->ExtraInfo(); ++ for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i) ++ { ++ sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str()); ++ m_pDS->exec(sql); ++ } ++ const ADDONDEPS &deps = addon->GetDeps(); ++ for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i) ++ { ++ sql = PrepareSQL("insert into dependencies(id, addon, version, optional) values (%i, '%s', '%s', %i)", idAddon, i->first.c_str(), i->second.first.asString().c_str(), i->second.second ? 1 : 0); ++ m_pDS->exec(sql); ++ } ++ return idAddon; + } + catch (...) + { +- CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addonId.c_str()); ++ CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str()); + } +- return false; ++ return -1; + } + + std::pair CAddonDatabase::GetAddonVersion(const std::string &id) +@@ -470,14 +410,14 @@ bool CAddonDatabase::GetAvailableVersions(const std::string& addonId, + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL( +- "SELECT addons.version, repo.addonID AS repoID FROM addons " +- "JOIN addonlinkrepo ON addonlinkrepo.idAddon=addons.id " ++ "SELECT addon.version, repo.addonID AS repoID FROM addon " ++ "JOIN addonlinkrepo ON addonlinkrepo.idAddon=addon.id " + "JOIN repo ON repo.id=addonlinkrepo.idRepo " + "WHERE " + "repo.checksum IS NOT NULL AND repo.checksum != '' " + "AND EXISTS (SELECT * FROM installed WHERE installed.addonID=repoID AND installed.enabled=1) " +- "AND NOT EXISTS (SELECT * FROM broken WHERE broken.addonID=addons.addonID) " +- "AND addons.addonID='%s'", addonId.c_str()); ++ "AND NOT EXISTS (SELECT * FROM broken WHERE broken.addonID=addon.addonID) " ++ "AND addon.addonID='%s'", addonId.c_str()); + + m_pDS->query(sql.c_str()); + while (!m_pDS->eof()) +@@ -504,10 +444,10 @@ bool CAddonDatabase::GetAddon(const std::string& addonID, const AddonVersion& ve + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL( +- "SELECT addons.id FROM addons " +- "JOIN addonlinkrepo ON addonlinkrepo.idAddon=addons.id " ++ "SELECT addon.id, addon.addonID, repo.addonID AS repoID FROM addon " ++ "JOIN addonlinkrepo ON addonlinkrepo.idAddon=addon.id " + "JOIN repo ON repo.id=addonlinkrepo.idRepo " +- "WHERE addons.addonID='%s' AND addons.version='%s' AND repo.addonID='%s'", ++ "WHERE addon.addonID='%s' AND addon.version='%s' AND repoID='%s'", + addonID.c_str(), version.asString().c_str(), repoId.c_str()); + + m_pDS->query(sql.c_str()); +@@ -534,7 +474,7 @@ bool CAddonDatabase::GetAddon(const std::string& id, AddonPtr& addon) + // there may be multiple addons with this id (eg from different repositories) in the database, + // so we want to retrieve the latest version. Order by version won't work as the database + // won't know that 1.10 > 1.2, so grab them all and order outside +- std::string sql = PrepareSQL("select id,version from addons where addonID='%s'",id.c_str()); ++ std::string sql = PrepareSQL("select id,version from addon where addonID='%s'",id.c_str()); + m_pDS2->query(sql); + + if (m_pDS2->eof()) +@@ -569,24 +509,66 @@ bool CAddonDatabase::GetAddon(int id, AddonPtr &addon) + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS2.get()) return false; + +- m_pDS2->query(PrepareSQL("SELECT * FROM addons WHERE id=%i", id)); +- if (m_pDS2->eof()) +- return false; ++ std::string sql = "SELECT addon.*," ++ " broken.reason," ++ " addonextra.key, addonextra.value," ++ " dependencies.addon, dependencies.version, dependencies.optional" ++ " FROM addon" ++ " LEFT JOIN broken" ++ " ON broken.addonID = addon.addonID" ++ " LEFT JOIN addonextra" ++ " ON addonextra.id = addon.id" ++ " LEFT JOIN dependencies" ++ " ON dependencies.id = addon.id"; ++ ++ sql += PrepareSQL(" WHERE addon.id=%i", id); ++ ++ m_pDS2->query(sql); ++ if (!m_pDS2->eof()) ++ { ++ const dbiplus::query_data &data = m_pDS2->get_result_set().records; ++ const dbiplus::sql_record* const record = data[0]; ++ ++ CAddonBuilder builder; ++ builder.SetId(record->at(addon_addonID).get_asString()); ++ builder.SetType(TranslateType(record->at(addon_type).get_asString())); ++ builder.SetVersion(AddonVersion(record->at(addon_version).get_asString())); ++ builder.SetMinVersion(AddonVersion(record->at(addon_minversion).get_asString())); ++ builder.SetName(record->at(addon_name).get_asString()); ++ builder.SetSummary(record->at(addon_summary).get_asString()); ++ builder.SetDescription(record->at(addon_description).get_asString()); ++ builder.SetChangelog(record->at(addon_changelog).get_asString()); ++ builder.SetDisclaimer(record->at(addon_disclaimer).get_asString()); ++ builder.SetAuthor(record->at(addon_author).get_asString()); ++ builder.SetBroken(record->at(broken_reason).get_asString()); ++ builder.SetPath(record->at(addon_path).get_asString()); ++ builder.SetIcon(record->at(addon_icon).get_asString()); ++ builder.SetFanart(record->at(addon_fanart).get_asString()); ++ ++ InfoMap extrainfo; ++ ADDONDEPS dependencies; ++ /* while this is a cartesion join and we'll typically get multiple rows, we rely on the fact that ++ extrainfo and dependencies are maps, so insert() will insert the first instance only */ ++ for (dbiplus::query_data::const_iterator i = data.begin(); i != data.end(); ++i) ++ { ++ const dbiplus::sql_record* const record = *i; ++ if (!record->at(addonextra_key).get_asString().empty()) ++ extrainfo.insert(std::make_pair(record->at(addonextra_key).get_asString(), record->at(addonextra_value).get_asString())); ++ if (!m_pDS2->fv(dependencies_addon).get_asString().empty()) ++ dependencies.insert(std::make_pair(record->at(dependencies_addon).get_asString(), std::make_pair(AddonVersion(record->at(dependencies_version).get_asString()), record->at(dependencies_optional).get_asBool()))); ++ } ++ builder.SetExtrainfo(std::move(extrainfo)); ++ builder.SetDependencies(std::move(dependencies)); + +- CAddonBuilder builder; +- builder.SetId(m_pDS2->fv(2).get_asString()); +- builder.SetVersion(AddonVersion(m_pDS2->fv(3).get_asString())); +- builder.SetName(m_pDS2->fv(4).get_asString()); +- builder.SetSummary(m_pDS2->fv(5).get_asString()); +- builder.SetDescription(m_pDS2->fv(6).get_asString()); +- DeserializeMetadata(m_pDS2->fv(1).get_asString(), builder); +- addon = builder.Build(); +- return addon != nullptr; ++ addon = builder.Build(); ++ return NULL != addon.get(); ++ } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %i", __FUNCTION__, id); + } ++ addon.reset(); + return false; + } + +@@ -595,7 +577,7 @@ bool CAddonDatabase::GetRepositoryContent(VECADDONS& addons) + return GetRepositoryContent("", addons); + } + +-bool CAddonDatabase::GetRepositoryContent(const std::string& id, VECADDONS& addons) ++bool CAddonDatabase::GetRepositoryContent(const std::string& repository, VECADDONS& addons) + { + try + { +@@ -613,8 +595,8 @@ bool CAddonDatabase::GetRepositoryContent(const std::string& id, VECADDONS& addo + " AND EXISTS (SELECT * FROM installed WHERE installed.addonID=repo.addonID AND" + " installed.enabled=1)"); + +- if (!id.empty()) +- sql += PrepareSQL(" AND repo.addonId='%s'", id.c_str()); ++ if (!repository.empty()) ++ sql += PrepareSQL(" AND repo.addonId='%s'", repository.c_str()); + + m_pDS->query(sql); + while (!m_pDS->eof()) +@@ -624,57 +606,124 @@ bool CAddonDatabase::GetRepositoryContent(const std::string& id, VECADDONS& addo + } + } + +- CLog::Log(LOGDEBUG, "CAddonDatabase: SELECT repo.id FROM repo .. took %d ms", XbmcThreads::SystemClockMillis() - start); +- + if (repoIds.empty()) + { +- CLog::Log(LOGDEBUG, "CAddonDatabase: no valid repository matching '%s'", id.c_str()); ++ CLog::Log(LOGDEBUG, "CAddonDatabase: no valid repository matching '%s'", repository.c_str()); + return false; + } + ++ std::string commonConstraint = PrepareSQL( ++ " JOIN addonlinkrepo ON addon.id=addonlinkrepo.idAddon" ++ " WHERE addonlinkrepo.idRepo IN (%s)" ++ " ORDER BY addon.addonID", StringUtils::Join(repoIds, ",").c_str()); ++ ++ std::vector result; ++ // Read basic info from the `addon` table ++ { ++ std::string sql = PrepareSQL("SELECT addon.*, broken.reason FROM addon " ++ "LEFT JOIN broken ON broken.addonID=addon.addonID ") + commonConstraint; ++ auto start = XbmcThreads::SystemClockMillis(); ++ m_pDS->query(sql); ++ CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(), ++ m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start); ++ ++ while (!m_pDS->eof()) ++ { ++ std::string addonId = m_pDS->fv(addon_addonID).get_asString(); ++ AddonVersion version(m_pDS->fv(addon_version).get_asString()); ++ ++ if (!result.empty() && result.back().GetId() == addonId && result.back().GetVersion() >= version) ++ { ++ // We already have a version of this addon in our list which is newer. ++ m_pDS->next(); ++ continue; ++ } ++ ++ CAddonBuilder builder; ++ builder.SetId(addonId); ++ builder.SetVersion(version); ++ builder.SetType(TranslateType(m_pDS->fv(addon_type).get_asString())); ++ builder.SetMinVersion(AddonVersion(m_pDS->fv(addon_minversion).get_asString())); ++ builder.SetName(m_pDS->fv(addon_name).get_asString()); ++ builder.SetSummary(m_pDS->fv(addon_summary).get_asString()); ++ builder.SetDescription(m_pDS->fv(addon_description).get_asString()); ++ builder.SetChangelog(m_pDS->fv(addon_changelog).get_asString()); ++ builder.SetDisclaimer(m_pDS->fv(addon_disclaimer).get_asString()); ++ builder.SetAuthor(m_pDS->fv(addon_author).get_asString()); ++ builder.SetPath(m_pDS->fv(addon_path).get_asString()); ++ builder.SetIcon(m_pDS->fv(addon_icon).get_asString()); ++ builder.SetFanart(m_pDS->fv(addon_fanart).get_asString()); ++ builder.SetBroken(m_pDS->fv(broken_reason).get_asString()); ++ if (!result.empty() && result.back().GetId() == addonId) ++ result.back() = std::move(builder); ++ else ++ result.push_back(std::move(builder)); ++ m_pDS->next(); ++ } ++ } ++ ++ // Read extra info. + { + std::string sql = PrepareSQL( +- " SELECT * FROM addons" +- " JOIN addonlinkrepo ON addons.id=addonlinkrepo.idAddon" +- " WHERE addonlinkrepo.idRepo IN (%s)" +- " ORDER BY addons.addonID", StringUtils::Join(repoIds, ",").c_str()); ++ "SELECT addon.addonID as owner, addonextra.key, addonextra.value " ++ "FROM addon JOIN addonextra ON addon.id=addonextra.id ") + commonConstraint; + + auto start = XbmcThreads::SystemClockMillis(); + m_pDS->query(sql); + CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(), + m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start); ++ ++ for (auto& builder : result) ++ { ++ //move cursor to current or next addon ++ while (!m_pDS->eof() && m_pDS->fv(0).get_asString() < builder.GetId()) ++ m_pDS->next(); ++ ++ InfoMap extraInfo; ++ while (!m_pDS->eof() && m_pDS->fv(0).get_asString() == builder.GetId()) ++ { ++ extraInfo.emplace(m_pDS->fv(1).get_asString(), m_pDS->fv(2).get_asString()); ++ m_pDS->next(); ++ } ++ builder.SetExtrainfo(std::move(extraInfo)); ++ } + } + +- VECADDONS result; +- while (!m_pDS->eof()) ++ // Read dependency info. + { +- std::string addonId = m_pDS->fv(2).get_asString(); +- AddonVersion version(m_pDS->fv(3).get_asString()); ++ std::string sql = PrepareSQL( ++ "SELECT addon.addonID as owner, dependencies.addon, dependencies.version, dependencies.optional " ++ "FROM addon JOIN dependencies ON addon.id=dependencies.id ") + commonConstraint; + +- if (!result.empty() && result.back()->ID() == addonId && result.back()->Version() >= version) ++ auto start = XbmcThreads::SystemClockMillis(); ++ m_pDS->query(sql); ++ CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(), ++ m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start); ++ ++ for (auto& builder : result) + { +- // We already have a version of this addon in our list which is newer. +- m_pDS->next(); +- continue; ++ //move cursor to the current or next addon ++ while (!m_pDS->eof() && m_pDS->fv(0).get_asString() < builder.GetId()) ++ m_pDS->next(); ++ ++ ADDONDEPS dependencies; ++ while (!m_pDS->eof() && m_pDS->fv(0).get_asString() == builder.GetId()) ++ { ++ dependencies.emplace(m_pDS->fv(1).get_asString(), ++ std::make_pair(AddonVersion(m_pDS->fv(2).get_asString()), m_pDS->fv(3).get_asBool())); ++ m_pDS->next(); ++ } ++ builder.SetDependencies(std::move(dependencies)); + } ++ } ++ m_pDS->close(); + +- CAddonBuilder builder; +- builder.SetId(addonId); +- builder.SetVersion(version); +- builder.SetName(m_pDS->fv(4).get_asString()); +- builder.SetSummary(m_pDS->fv(5).get_asString()); +- builder.SetDescription(m_pDS->fv(6).get_asString()); +- DeserializeMetadata(m_pDS->fv(1).get_asString(), builder); +- ++ for (auto& builder : result) ++ { + auto addon = builder.Build(); + if (addon) +- result.push_back(std::move(addon)); +- else +- CLog::Log(LOGWARNING, "CAddonDatabase: failed to build %s", addonId.c_str()); +- m_pDS->next(); ++ addons.push_back(std::move(addon)); + } +- m_pDS->close(); +- addons = std::move(result); + + CLog::Log(LOGDEBUG, "CAddonDatabase::GetAddons took %i ms", XbmcThreads::SystemClockMillis() - start); + return true; +@@ -700,7 +749,9 @@ void CAddonDatabase::DeleteRepository(const std::string& id) + int idRepo = m_pDS->fv(0).get_asInt(); + + m_pDS->exec(PrepareSQL("DELETE FROM repo WHERE id=%i", idRepo)); +- m_pDS->exec(PrepareSQL("DELETE FROM addons WHERE id IN (SELECT idAddon FROM addonlinkrepo WHERE idRepo=%i)", idRepo)); ++ m_pDS->exec(PrepareSQL("DELETE FROM addon WHERE id IN (SELECT idAddon FROM addonlinkrepo WHERE idRepo=%i)", idRepo)); ++ m_pDS->exec(PrepareSQL("DELETE FROM addonextra WHERE id IN (SELECT idAddon FROM addonlinkrepo WHERE idRepo=%i)", idRepo)); ++ m_pDS->exec(PrepareSQL("DELETE FROM dependencies WHERE id IN (SELECT idAddon FROM addonlinkrepo WHERE idRepo=%i)", idRepo)); + m_pDS->exec(PrepareSQL("DELETE FROM addonlinkrepo WHERE idRepo=%i", idRepo)); + } + catch (...) +@@ -709,17 +760,17 @@ void CAddonDatabase::DeleteRepository(const std::string& id) + } + } + +-bool CAddonDatabase::UpdateRepositoryContent(const std::string& repository, const AddonVersion& version, +- const std::string& checksum, const std::vector& addons) ++bool CAddonDatabase::UpdateRepositoryContent(const std::string& id, const VECADDONS& addons, ++ const std::string& checksum, const AddonVersion& version) + { + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + +- DeleteRepository(repository); ++ DeleteRepository(id); + +- if (!SetLastChecked(repository, version, CDateTime::GetCurrentDateTime().GetAsDBDateTime())) ++ if (!SetLastChecked(id, version, CDateTime::GetCurrentDateTime().GetAsDBDateTime())) + return false; + + int idRepo = static_cast(m_pDS->lastinsertid()); +@@ -728,34 +779,14 @@ bool CAddonDatabase::UpdateRepositoryContent(const std::string& repository, cons + m_pDB->start_transaction(); + m_pDS->exec(PrepareSQL("UPDATE repo SET checksum='%s' WHERE id='%d'", checksum.c_str(), idRepo)); + for (const auto& addon : addons) +- { +- m_pDS->exec(PrepareSQL( +- "INSERT INTO addons (id, metadata, addonID, version, name, summary, description) " +- "VALUES (NULL, '%s', '%s', '%s', '%s','%s', '%s')", +- SerializeMetadata(*addon).c_str(), +- addon->ID().c_str(), +- addon->Version().asString().c_str(), +- addon->Name().c_str(), +- addon->Summary().c_str(), +- addon->Description().c_str())); +- +- auto idAddon = m_pDS->lastinsertid(); +- if (idAddon <= 0) +- { +- CLog::Log(LOGERROR, "%s insert failed on addon '%s'", __FUNCTION__, addon->ID().c_str()); +- RollbackTransaction(); +- return false; +- } +- +- m_pDS->exec(PrepareSQL("INSERT INTO addonlinkrepo (idRepo, idAddon) VALUES (%i, %i)", idRepo, idAddon)); +- } ++ AddAddon(addon, idRepo); + + m_pDB->commit_transaction(); + return true; + } + catch (...) + { +- CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, repository.c_str()); ++ CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str()); + RollbackTransaction(); + } + return false; +@@ -844,7 +875,7 @@ bool CAddonDatabase::Search(const std::string& search, VECADDONS& addons) + if (NULL == m_pDS.get()) return false; + + std::string strSQL; +- strSQL=PrepareSQL("SELECT addonID FROM addons WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search.c_str(), search.c_str(), search.c_str()); ++ strSQL=PrepareSQL("SELECT addonID FROM addon WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search.c_str(), search.c_str(), search.c_str()); + CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); + + if (!m_pDS->query(strSQL)) return false; +@@ -943,9 +974,9 @@ bool CAddonDatabase::GetBlacklisted(std::set& addons) + return false; + } + +-bool CAddonDatabase::IsAddonBroken(const std::string &addonID) ++std::string CAddonDatabase::IsAddonBroken(const std::string &addonID) + { +- return !GetSingleValue(PrepareSQL("SELECT reason FROM broken WHERE addonID='%s'", addonID.c_str())).empty(); ++ return GetSingleValue(PrepareSQL("SELECT reason FROM broken WHERE addonID='%s'", addonID.c_str())); + } + + bool CAddonDatabase::BlacklistAddon(const std::string& addonID) +@@ -1015,7 +1046,7 @@ void CAddonDatabase::OnPostUnInstall(const std::string& addonId) + RemoveAddonFromBlacklist(addonId); + DeleteRepository(addonId); + +- //! @todo should be done before uninstall to avoid any race conditions ++ //TODO: should be done before uninstall to avoid any race conditions + try + { + if (NULL == m_pDB.get()) return; +diff --git a/xbmc/addons/AddonDatabase.h b/xbmc/addons/AddonDatabase.h +index 220d5c8..bb1140c 100644 +--- a/xbmc/addons/AddonDatabase.h ++++ b/xbmc/addons/AddonDatabase.h +@@ -48,9 +48,8 @@ public: + /*! Get the most recent version for an add-on and the repo id it belongs to*/ + std::pair GetAddonVersion(const std::string &id); + +- bool UpdateRepositoryContent(const std::string& repositoryId, const ADDON::AddonVersion& version, +- const std::string& checksum, const std::vector& addons); +- ++ bool UpdateRepositoryContent(const std::string& id, const ADDON::VECADDONS& addons, ++ const std::string& checksum, const ADDON::AddonVersion& version); + int GetRepoChecksum(const std::string& id, std::string& checksum); + + /*! +@@ -92,8 +91,9 @@ public: + + /*! \brief Check whether an addon has been marked as broken via BreakAddon. + \param addonID id of the addon to check ++ \return reason if the addon is broken, blank otherwise + \sa BreakAddon */ +- bool IsAddonBroken(const std::string &addonID); ++ std::string IsAddonBroken(const std::string &addonID); + + bool BlacklistAddon(const std::string& addonID); + bool RemoveAddonFromBlacklist(const std::string& addonID); +@@ -136,7 +136,6 @@ public: + void GetInstalled(std::vector& addons); + + bool SetLastUpdated(const std::string& addonId, const CDateTime& dateTime); +- bool SetOrigin(const std::string& addonId, const std::string& origin); + bool SetLastUsed(const std::string& addonId, const CDateTime& dateTime); + + +@@ -149,6 +148,33 @@ protected: + const char *GetBaseDBName() const { return "Addons"; } + + bool GetAddon(int id, ADDON::AddonPtr& addon); ++ int AddAddon(const ADDON::AddonPtr& item, int idRepo); + void DeleteRepository(const std::string& id); ++ ++ /* keep in sync with the addon table */ ++ enum AddonFields ++ { ++ addon_id=0, ++ addon_type, ++ addon_name, ++ addon_summary, ++ addon_description, ++ addon_stars, ++ addon_path, ++ addon_addonID, ++ addon_icon, ++ addon_version, ++ addon_changelog, ++ addon_fanart, ++ addon_author, ++ addon_disclaimer, ++ addon_minversion, ++ broken_reason, ++ addonextra_key, ++ addonextra_value, ++ dependencies_addon, ++ dependencies_version, ++ dependencies_optional ++ }; + }; + +diff --git a/xbmc/addons/AddonDll.h b/xbmc/addons/AddonDll.h +index 3058fe8..cc3c24a 100644 +--- a/xbmc/addons/AddonDll.h ++++ b/xbmc/addons/AddonDll.h +@@ -20,7 +20,6 @@ + */ + #include + #include +-#include + + #include "Addon.h" + #include "DllAddon.h" +diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp +index c0e365c..b0a57b6 100644 +--- a/xbmc/addons/AddonInstaller.cpp ++++ b/xbmc/addons/AddonInstaller.cpp +@@ -266,7 +266,7 @@ bool CAddonInstaller::InstallFromZip(const std::string &path) + + // grab the descriptive XML document from the zip, and read it in + CFileItemList items; +- //! @bug some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol ++ // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol + CURL pathToUrl(path); + CURL zipDir = URIUtils::CreateArchivePath("zip", pathToUrl, ""); + if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder) +@@ -277,7 +277,7 @@ bool CAddonInstaller::InstallFromZip(const std::string &path) + return false; + } + +- //! @todo possibly add support for github generated zips here? ++ // TODO: possibly add support for github generated zips here? + std::string archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml"); + + CXBMCTinyXML xml; +@@ -351,7 +351,7 @@ bool CAddonInstaller::CheckDependencies(const AddonPtr &addon, + } + + // at this point we have our dep, or the dep is optional (and we don't have it) so check that it's OK as well +- //! @todo should we assume that installed deps are OK? ++ // TODO: should we assume that installed deps are OK? + if (dep && std::find(preDeps.begin(), preDeps.end(), dep->ID()) == preDeps.end()) + { + if (!CheckDependencies(dep, preDeps, database, failedDep)) +@@ -627,12 +627,15 @@ bool CAddonInstallJob::DoWork() + //Enable it if it was previously disabled + CAddonMgr::GetInstance().EnableAddon(m_addon->ID()); + ++ if (m_update) + { +- CAddonDatabase database; +- database.Open(); +- database.SetOrigin(m_addon->ID(), m_repo ? m_repo->ID() : ""); +- if (m_update) +- database.SetLastUpdated(m_addon->ID(), CDateTime::GetCurrentDateTime()); ++ auto& addon = m_addon; ++ auto time = CDateTime::GetCurrentDateTime(); ++ CJobManager::GetInstance().Submit([addon, time](){ ++ CAddonDatabase db; ++ if (db.Open()) ++ db.SetLastUpdated(addon->ID(), time); ++ }); + } + + // notify any observers that add-ons have changed +diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h +index 02c7185..6cd7868 100644 +--- a/xbmc/addons/AddonInstaller.h ++++ b/xbmc/addons/AddonInstaller.h +@@ -19,9 +19,7 @@ + * + */ + +-#include + #include +-#include + + #include "addons/Addon.h" + #include "addons/Repository.h" +diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp +index e5a4c34..4c62232 100644 +--- a/xbmc/addons/AddonManager.cpp ++++ b/xbmc/addons/AddonManager.cpp +@@ -34,7 +34,7 @@ + #include "AudioEncoder.h" + #include "ContextMenuAddon.h" + #include "ContextMenuManager.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "DllAudioDSP.h" + #include "DllLibCPluff.h" + #include "events/AddonManagementEvent.h" +@@ -145,6 +145,7 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder + builder.SetPath(plugin->plugin_path); + builder.SetIcon(URIUtils::AddFileToFolder(plugin->plugin_path, "icon.png")); + builder.SetFanart(URIUtils::AddFileToFolder(plugin->plugin_path, "fanart.jpg")); ++ builder.SetChangelog(URIUtils::AddFileToFolder(plugin->plugin_path, "changelog.txt")); + } + + { +@@ -169,9 +170,7 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder + builder.SetSummary(CAddonMgr::GetInstance().GetTranslatedString(metadata->configuration, "summary")); + builder.SetDescription(CAddonMgr::GetInstance().GetTranslatedString(metadata->configuration, "description")); + builder.SetDisclaimer(CAddonMgr::GetInstance().GetTranslatedString(metadata->configuration, "disclaimer")); +- builder.SetChangelog(CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "news")); + builder.SetLicense(CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "license")); +- builder.SetPackageSize(StringUtils::ToUint64(CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "size"), 0)); + + std::string language = CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "language"); + if (!language.empty()) +@@ -187,6 +186,8 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder + builder.SetFanart(""); + if (CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "noicon") == "true") + builder.SetIcon(""); ++ if (CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "nochangelog") == "true") ++ builder.SetChangelog(""); + } + } + +@@ -282,7 +283,8 @@ bool CAddonMgr::Init() + return false; + } + +- //! @todo could separate addons into different contexts would allow partial unloading of addon framework ++ //TODO could separate addons into different contexts ++ // would allow partial unloading of addon framework + m_cp_context = m_cpluff->create_context(&status); + assert(m_cp_context); + status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://home/addons").c_str()); +@@ -574,7 +576,7 @@ bool CAddonMgr::GetAddon(const std::string &str, AddonPtr &addon, const TYPE &ty + return false; + } + +-//! @todo handle all 'default' cases here, not just scrapers & vizs ++//TODO handle all 'default' cases here, not just scrapers & vizs + bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon) + { + std::string setting; +diff --git a/xbmc/addons/AddonStatusHandler.cpp b/xbmc/addons/AddonStatusHandler.cpp +index 660bc2c..b1b687c 100644 +--- a/xbmc/addons/AddonStatusHandler.cpp ++++ b/xbmc/addons/AddonStatusHandler.cpp +@@ -50,8 +50,8 @@ CAddonStatusHandler::CAddonStatusHandler(const std::string &addonID, ADDON_STATU + : CThread(("AddonStatus " + addonID).c_str()), + m_status(ADDON_STATUS_UNKNOWN) + { +- //! @todo The status handled CAddonStatusHandler by is related to the class, not the instance +- //! having CAddonMgr construct an instance makes no sense ++ // TODO: the status handled CAddonStatusHandler by is related to the class, not the instance ++ // having CAddonMgr construct an instance makes no sense + if (!CAddonMgr::GetInstance().GetAddon(addonID, m_addon)) + return; + +@@ -121,7 +121,7 @@ void CAddonStatusHandler::Process() + + if (CGUIDialogAddonSettings::ShowAndGetInput(m_addon)) + { +- //! @todo Doesn't dialogaddonsettings save these automatically? It should do this. ++ //todo doesn't dialogaddonsettings save these automatically? should do + m_addon->SaveSettings(); + CAddonMgr::GetInstance().GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, true); + } +diff --git a/xbmc/addons/ContextMenuAddon.h b/xbmc/addons/ContextMenuAddon.h +index a3f9be2..63cd172 100644 +--- a/xbmc/addons/ContextMenuAddon.h ++++ b/xbmc/addons/ContextMenuAddon.h +@@ -21,9 +21,6 @@ + + #include + #include +-#include +-#include +- + #include "Addon.h" + #include "ContextMenuItem.h" + +diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp +index ae5756a..3c3ba99 100644 +--- a/xbmc/addons/GUIDialogAddonInfo.cpp ++++ b/xbmc/addons/GUIDialogAddonInfo.cpp +@@ -27,7 +27,7 @@ + #include "FileItem.h" + #include "filesystem/Directory.h" + #include "GUIDialogAddonSettings.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "dialogs/GUIDialogContextMenu.h" + #include "dialogs/GUIDialogTextViewer.h" + #include "dialogs/GUIDialogOK.h" +@@ -53,6 +53,7 @@ + #define CONTROL_BTN_ENABLE 7 + #define CONTROL_BTN_UPDATE 8 + #define CONTROL_BTN_SETTINGS 9 ++#define CONTROL_BTN_CHANGELOG 10 + #define CONTROL_BTN_SELECT 12 + #define CONTROL_BTN_AUTOUPDATE 13 + +@@ -61,7 +62,9 @@ using namespace XFILE; + + CGUIDialogAddonInfo::CGUIDialogAddonInfo(void) + : CGUIDialog(WINDOW_DIALOG_ADDON_INFO, "DialogAddonInfo.xml"), +- m_addonEnabled(false) ++ m_addonEnabled(false), ++ m_jobid(0), ++ m_changelog(false) + { + m_item = CFileItemPtr(new CFileItem); + m_loadType = KEEP_IN_MEMORY; +@@ -75,6 +78,13 @@ bool CGUIDialogAddonInfo::OnMessage(CGUIMessage& message) + { + switch ( message.GetMessage() ) + { ++ case GUI_MSG_WINDOW_DEINIT: ++ { ++ if (m_jobid) ++ CJobManager::GetInstance().CancelJob(m_jobid); ++ } ++ break; ++ + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); +@@ -130,6 +140,11 @@ bool CGUIDialogAddonInfo::OnMessage(CGUIMessage& message) + OnSettings(); + return true; + } ++ else if (iControl == CONTROL_BTN_CHANGELOG) ++ { ++ OnChangeLog(); ++ return true; ++ } + else if (iControl == CONTROL_BTN_AUTOUPDATE) + { + OnToggleAutoUpdates(); +@@ -158,6 +173,7 @@ void CGUIDialogAddonInfo::OnInitWindow() + { + UpdateControls(); + CGUIDialog::OnInitWindow(); ++ m_changelog = false; + } + + void CGUIDialogAddonInfo::UpdateControls() +@@ -170,6 +186,7 @@ void CGUIDialogAddonInfo::UpdateControls() + bool canDisable = isInstalled && CAddonMgr::GetInstance().CanAddonBeDisabled(m_localAddon->ID()); + bool canInstall = !isInstalled && m_item->GetAddonInfo()->Broken().empty(); + bool canUninstall = m_localAddon && CAddonMgr::GetInstance().CanUninstall(m_localAddon); ++ bool isRepo = (isInstalled && m_localAddon->Type() == ADDON_REPOSITORY) || (m_item->GetAddonInfo()->Type() == ADDON_REPOSITORY); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_INSTALL, canInstall || canUninstall); + SET_CONTROL_LABEL(CONTROL_BTN_INSTALL, isInstalled ? 24037 : 24038); +@@ -198,6 +215,7 @@ void CGUIDialogAddonInfo::UpdateControls() + SET_CONTROL_LABEL(CONTROL_BTN_SELECT, CanUse() ? 21480 : (CanOpen() ? 21478 : 21479)); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_SETTINGS, isInstalled && m_localAddon->HasSettings()); ++ CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_CHANGELOG, !isRepo); + } + + static const std::string LOCAL_CACHE = "\\0_local_cache"; // \0 to give it the lowest priority when sorting +@@ -215,8 +233,7 @@ int CGUIDialogAddonInfo::AskForVersion(std::vectorVersion() == versionInfo.first +- && m_item->GetAddonInfo()->Origin() == versionInfo.second) ++ if (m_localAddon && m_localAddon->Version() == versionInfo.first) + item.Select(true); + + AddonPtr repo; +@@ -442,6 +459,34 @@ void CGUIDialogAddonInfo::OnSettings() + CGUIDialogAddonSettings::ShowAndGetInput(m_localAddon); + } + ++void CGUIDialogAddonInfo::OnChangeLog() ++{ ++ CGUIDialogTextViewer* pDlgInfo = (CGUIDialogTextViewer*)g_windowManager.GetWindow(WINDOW_DIALOG_TEXT_VIEWER); ++ std::string name = m_localAddon ? m_localAddon->Name() : m_item->GetAddonInfo()->Name(); ++ pDlgInfo->SetHeading(g_localizeStrings.Get(24054)+" - "+name); ++ if (m_item->GetProperty("Addon.Changelog").empty()) ++ { ++ pDlgInfo->SetText(g_localizeStrings.Get(13413)); ++ CFileItemList items; ++ if (m_localAddon && !m_item->GetProperty("Addon.HasUpdate").asBoolean()) ++ { ++ items.Add(CFileItemPtr(new CFileItem(m_localAddon->ChangeLog(),false))); ++ } ++ else ++ items.Add(CFileItemPtr(new CFileItem(m_item->GetAddonInfo()->ChangeLog(),false))); ++ items[0]->Select(true); ++ m_jobid = CJobManager::GetInstance().AddJob( ++ new CFileOperationJob(CFileOperationJob::ActionCopy,items, ++ "special://temp/"),this); ++ } ++ else ++ pDlgInfo->SetText(m_item->GetProperty("Addon.Changelog").asString()); ++ ++ m_changelog = true; ++ pDlgInfo->Open(); ++ m_changelog = false; ++} ++ + bool CGUIDialogAddonInfo::ShowForItem(const CFileItemPtr& item) + { + if (!item) +@@ -467,3 +512,32 @@ bool CGUIDialogAddonInfo::SetItem(const CFileItemPtr& item) + CAddonMgr::GetInstance().GetAddon(item->GetAddonInfo()->ID(), m_localAddon, ADDON_UNKNOWN, false); + return true; + } ++ ++void CGUIDialogAddonInfo::OnJobComplete(unsigned int jobID, bool success, ++ CJob* job) ++{ ++ if (!m_changelog) ++ return; ++ ++ CGUIDialogTextViewer* pDlgInfo = (CGUIDialogTextViewer*)g_windowManager.GetWindow(WINDOW_DIALOG_TEXT_VIEWER); ++ ++ m_jobid = 0; ++ if (!success) ++ { ++ pDlgInfo->SetText(g_localizeStrings.Get(195)); ++ } ++ else ++ { ++ CFile file; ++ XFILE::auto_buffer buf; ++ if (file.LoadFile("special://temp/" + ++ URIUtils::GetFileName(((CFileOperationJob*)job)->GetItems()[0]->GetPath()), buf) > 0) ++ { ++ std::string str(buf.get(), buf.length()); ++ m_item->SetProperty("Addon.Changelog", str); ++ pDlgInfo->SetText(str); ++ } ++ } ++ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, WINDOW_DIALOG_TEXT_VIEWER, 0, GUI_MSG_UPDATE); ++ g_windowManager.SendThreadMessage(msg); ++} +diff --git a/xbmc/addons/GUIDialogAddonInfo.h b/xbmc/addons/GUIDialogAddonInfo.h +index aa99800..8d0778e 100644 +--- a/xbmc/addons/GUIDialogAddonInfo.h ++++ b/xbmc/addons/GUIDialogAddonInfo.h +@@ -20,14 +20,13 @@ + * + */ + +-#include +-#include +-#include +- + #include "guilib/GUIDialog.h" + #include "addons/IAddon.h" ++#include "utils/Job.h" + +-class CGUIDialogAddonInfo : public CGUIDialog ++class CGUIDialogAddonInfo : ++ public CGUIDialog, ++ public IJobCallback + { + public: + CGUIDialogAddonInfo(void); +@@ -40,6 +39,9 @@ public: + + static bool ShowForItem(const CFileItemPtr& item); + ++ // job callback ++ void OnJobComplete(unsigned int jobID, bool success, CJob* job); ++ + private: + void OnInitWindow(); + +@@ -55,6 +57,7 @@ private: + void OnUninstall(); + void OnEnableDisable(); + void OnSettings(); ++ void OnChangeLog(); + void OnSelect(); + void OnToggleAutoUpdates(); + int AskForVersion(std::vector>& versions); +@@ -80,5 +83,7 @@ private: + CFileItemPtr m_item; + ADDON::AddonPtr m_localAddon; + bool m_addonEnabled; ++ unsigned int m_jobid; ++ bool m_changelog; + }; + +diff --git a/xbmc/addons/GUIDialogAddonSettings.cpp b/xbmc/addons/GUIDialogAddonSettings.cpp +index 1c9a05e..b7b1c12 100644 +--- a/xbmc/addons/GUIDialogAddonSettings.cpp ++++ b/xbmc/addons/GUIDialogAddonSettings.cpp +@@ -244,7 +244,7 @@ bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) + const std::string id = XMLUtils::GetAttribute(setting, "id"); + const std::string type = XMLUtils::GetAttribute(setting, "type"); + +- //! @todo Refactor me. Special handling for actions: does not require id attribute. ++ //Special handling for actions: does not require id attribute. TODO: refactor me. + if (control && control->GetControlType() == CGUIControl::GUICONTROL_BUTTON && type == "action") + { + const char *option = setting->Attribute("option"); +diff --git a/xbmc/addons/GUIDialogAddonSettings.h b/xbmc/addons/GUIDialogAddonSettings.h +index be85195..2b25c53 100644 +--- a/xbmc/addons/GUIDialogAddonSettings.h ++++ b/xbmc/addons/GUIDialogAddonSettings.h +@@ -19,10 +19,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "dialogs/GUIDialogBoxBase.h" + #include "IAddon.h" + +diff --git a/xbmc/addons/GUIWindowAddonBrowser.h b/xbmc/addons/GUIWindowAddonBrowser.h +index 0831fd9..894d3f2 100644 +--- a/xbmc/addons/GUIWindowAddonBrowser.h ++++ b/xbmc/addons/GUIWindowAddonBrowser.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "addons/Addon.h" + #include "windows/GUIMediaWindow.h" + #include "ThumbLoader.h" +diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h +index fcabb6a..3d913ba 100644 +--- a/xbmc/addons/IAddon.h ++++ b/xbmc/addons/IAddon.h +@@ -114,8 +114,6 @@ namespace ADDON + virtual CDateTime InstallDate() const =0; + virtual CDateTime LastUpdated() const =0; + virtual CDateTime LastUsed() const =0; +- virtual std::string Origin() const =0; +- virtual uint64_t PackageSize() const =0; + virtual const InfoMap &ExtraInfo() const =0; + virtual bool HasSettings() =0; + virtual void SaveSettings() =0; +diff --git a/xbmc/addons/InputStream.cpp b/xbmc/addons/InputStream.cpp +index 9d093b8..b4d3561 100644 +--- a/xbmc/addons/InputStream.cpp ++++ b/xbmc/addons/InputStream.cpp +@@ -34,19 +34,16 @@ std::unique_ptr CInputStream::FromExtension(AddonProps props, cons + { + std::string listitemprops = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@listitemprops"); + std::string extensions = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@extension"); +- std::string protocols = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@protocols"); + std::string name(ext->plugin->identifier); +- std::unique_ptr istr(new CInputStream(props, name, listitemprops, +- extensions, protocols)); ++ std::unique_ptr istr(new CInputStream(std::move(props), ++ std::move(name), ++ std::move(listitemprops), ++ std::move(extensions))); + istr->CheckConfig(); + return istr; + } + +-CInputStream::CInputStream(const AddonProps& props, +- const std::string& name, +- const std::string& listitemprops, +- const std::string& extensions, +- const std::string& protocols) ++CInputStream::CInputStream(AddonProps props, std::string name, std::string listitemprops, std::string extensions) + : InputStreamDll(std::move(props)) + { + m_fileItemProps = StringUtils::Tokenize(listitemprops, "|"); +@@ -61,12 +58,6 @@ CInputStream::CInputStream(const AddonProps& props, + { + StringUtils::Trim(ext); + } +- +- m_protocolsList = StringUtils::Tokenize(protocols, "|"); +- for (auto &ext : m_protocolsList) +- { +- StringUtils::Trim(ext); +- } + } + + void CInputStream::SaveSettings() +@@ -165,15 +156,6 @@ bool CInputStream::Supports(const CFileItem &fileitem) + return true; + } + +- // check protocols +- std::string protocol = fileitem.GetURL().GetProtocol(); +- if (!protocol.empty()) +- { +- if (std::find(m_protocolsList.begin(), +- m_protocolsList.end(), protocol) != m_protocolsList.end()) +- return true; +- } +- + // check paths + CSingleLock lock(m_parentSection); + auto it = m_configMap.find(ID()); +@@ -376,7 +358,7 @@ void CInputStream::UpdateStreams() + } + else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_SUBTITLE) + { +- //! @todo needs identifier in INPUTSTREAM_INFO ++ // TODO needs identifier in INPUTSTREAM_INFO + continue; + } + else +diff --git a/xbmc/addons/InputStream.h b/xbmc/addons/InputStream.h +index 61273a9..4912ee1 100644 +--- a/xbmc/addons/InputStream.h ++++ b/xbmc/addons/InputStream.h +@@ -42,11 +42,7 @@ namespace ADDON + explicit CInputStream(AddonProps props) + : InputStreamDll(std::move(props)) + {}; +- CInputStream(const AddonProps& props, +- const std::string& name, +- const std::string& listitemprops, +- const std::string& extensions, +- const std::string& protocols); ++ CInputStream(AddonProps props, std::string name, std::string listitemprops, std::string extensions); + virtual ~CInputStream() {} + + virtual void SaveSettings() override; +@@ -99,7 +95,6 @@ namespace ADDON + + std::vector m_fileItemProps; + std::vector m_extensionsList; +- std::vector m_protocolsList; + INPUTSTREAM_CAPABILITIES m_caps; + std::map m_streams; + +diff --git a/xbmc/addons/LanguageResource.cpp b/xbmc/addons/LanguageResource.cpp +index 91b6355..33c9ed4 100644 +--- a/xbmc/addons/LanguageResource.cpp ++++ b/xbmc/addons/LanguageResource.cpp +@@ -195,7 +195,7 @@ bool CLanguageResource::FindLanguageAddonByName(const std::string &legacyLanguag + VECADDONS addons; + if (!languageAddons.empty()) + addons = languageAddons; +- else if (!CAddonMgr::GetInstance().GetInstalledAddons(addons, ADDON_RESOURCE_LANGUAGE) || addons.empty()) ++ else if (!CAddonMgr::GetInstance().GetAddons(addons, ADDON_RESOURCE_LANGUAGE) || addons.empty()) + return false; + + // try to find a language that matches the old language in name or id +diff --git a/xbmc/addons/PVRClient.cpp b/xbmc/addons/PVRClient.cpp +index e617adb..bc44db6 100644 +--- a/xbmc/addons/PVRClient.cpp ++++ b/xbmc/addons/PVRClient.cpp +@@ -166,7 +166,7 @@ ADDON_STATUS CPVRClient::Create(int iClientId) + + /* initialise the add-on */ + bool bReadyToUse(false); +- CLog::Log(LOGDEBUG, "PVR - %s - creating PVR add-on instance '%s'", __FUNCTION__, Name().c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - creating PVR add-on instance '%s'", __FUNCTION__, Name().c_str()); + try + { + if ((status = CAddonDll::Create()) == ADDON_STATUS_OK) +@@ -193,7 +193,7 @@ void CPVRClient::Destroy(void) + m_bReadyToUse = false; + + /* reset 'ready to use' to false */ +- CLog::Log(LOGDEBUG, "PVR - %s - destroying PVR add-on '%s'", __FUNCTION__, GetFriendlyName().c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - destroying PVR add-on '%s'", __FUNCTION__, GetFriendlyName().c_str()); + + /* destroy the add-on */ + try { CAddonDll::Destroy(); } +@@ -889,7 +889,7 @@ PVR_ERROR CPVRClient::GetChannelGroupMembers(CPVRChannelGroup *group) + PVR_CHANNEL_GROUP tag; + WriteClientGroupInfo(*group, tag); + +- CLog::Log(LOGDEBUG, "PVR - %s - get group members for group '%s' from add-on '%s'", ++ CLog::Log(LOGPVR, "PVR - %s - get group members for group '%s' from add-on '%s'", + __FUNCTION__, tag.strGroupName, GetFriendlyName().c_str()); + retVal = m_pStruct->GetChannelGroupMembers(&handle, tag); + +@@ -1739,11 +1739,11 @@ bool CPVRClient::OpenStream(const CPVRChannelPtr &channel, bool bIsSwitchingChan + + if(!CanPlayChannel(channel)) + { +- CLog::Log(LOGDEBUG, "add-on '%s' can not play channel '%s'", GetFriendlyName().c_str(), channel->ChannelName().c_str()); ++ CLog::Log(LOGPVR, "add-on '%s' can not play channel '%s'", GetFriendlyName().c_str(), channel->ChannelName().c_str()); + } + else if (!channel->StreamURL().empty()) + { +- CLog::Log(LOGDEBUG, "opening live stream on url '%s'", channel->StreamURL().c_str()); ++ CLog::Log(LOGPVR, "opening live stream on url '%s'", channel->StreamURL().c_str()); + bReturn = true; + + // the Njoy N7 sometimes doesn't switch channels, but opens a stream to the previous channel +@@ -1759,7 +1759,7 @@ bool CPVRClient::OpenStream(const CPVRChannelPtr &channel, bool bIsSwitchingChan + } + else + { +- CLog::Log(LOGDEBUG, "opening live stream for channel '%s'", channel->ChannelName().c_str()); ++ CLog::Log(LOGPVR, "opening live stream for channel '%s'", channel->ChannelName().c_str()); + PVR_CHANNEL tag; + WriteClientChannelInfo(channel, tag); + +@@ -1982,14 +1982,14 @@ bool CPVRClient::Autoconfigure(void) + { + // %s service found at %s + std::string strLogLine(StringUtils::Format(g_localizeStrings.Get(19689).c_str(), (*it).GetName().c_str(), (*it).GetIP().c_str())); +- CLog::Log(LOGDEBUG, "%s - %s", __FUNCTION__, strLogLine.c_str()); ++ CLog::Log(LOGPVR, "%s - %s", __FUNCTION__, strLogLine.c_str()); + + if (DialogResponse::YES != + HELPERS::ShowYesNoDialogLines(CVariant{19688}, // Scanning for PVR services + CVariant{strLogLine}, + CVariant{19690})) // Do you want to use this service? + { +- CLog::Log(LOGDEBUG, "%s - %s service found but not enabled by the user", __FUNCTION__, (*it).GetName().c_str()); ++ CLog::Log(LOGPVR, "%s - %s service found but not enabled by the user", __FUNCTION__, (*it).GetName().c_str()); + m_rejectedAvahiHosts.push_back(*it); + } + else +diff --git a/xbmc/addons/PVRClient.h b/xbmc/addons/PVRClient.h +index 5eef0eb..5d27f17 100644 +--- a/xbmc/addons/PVRClient.h ++++ b/xbmc/addons/PVRClient.h +@@ -19,16 +19,13 @@ + * + */ + +-#include +-#include +-#include +- + #include "addons/Addon.h" + #include "addons/AddonDll.h" + #include "addons/DllPVRClient.h" + #include "network/ZeroconfBrowser.h" + + #include "pvr/channels/PVRChannel.h" ++#include "pvr/recordings/PVRRecordings.h" + + namespace EPG + { +diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp +index 3de88c0..dcb196d 100644 +--- a/xbmc/addons/Repository.cpp ++++ b/xbmc/addons/Repository.cpp +@@ -192,12 +192,15 @@ bool CRepository::Parse(const DirInfo& dir, VECADDONS& addons) + std::string file = StringUtils::Format("%s/%s-%s.zip", addon->ID().c_str(), addon->ID().c_str(), addon->Version().asString().c_str()); + addon->Props().path = URIUtils::AddFileToFolder(dir.datadir,file); + SET_IF_NOT_EMPTY(addon->Props().icon,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/icon.png")) ++ file = StringUtils::Format("%s/changelog-%s.txt", addon->ID().c_str(), addon->Version().asString().c_str()); ++ SET_IF_NOT_EMPTY(addon->Props().changelog,URIUtils::AddFileToFolder(dir.datadir,file)) + SET_IF_NOT_EMPTY(addon->Props().fanart,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/fanart.jpg")) + } + else + { + addon->Props().path = URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/"); + SET_IF_NOT_EMPTY(addon->Props().icon,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/icon.png")) ++ SET_IF_NOT_EMPTY(addon->Props().changelog,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/changelog.txt")) + SET_IF_NOT_EMPTY(addon->Props().fanart,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/fanart.jpg")) + } + } +@@ -258,7 +261,7 @@ bool CRepositoryUpdateJob::DoWork() + textureDB.CommitMultipleExecute(); + } + +- database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons); ++ database.UpdateRepositoryContent(m_repo->ID(), addons, newChecksum, m_repo->Version()); + + //Update broken status + database.BeginMultipleExecute(); +@@ -282,7 +285,7 @@ bool CRepositoryUpdateJob::DoWork() + + if (localAddon) + { +- bool brokenInDb = database.IsAddonBroken(addon->ID()); ++ bool brokenInDb = !database.IsAddonBroken(addon->ID()).empty(); + if (!broken.empty() && !brokenInDb) + { + //newly broken +diff --git a/xbmc/addons/Repository.h b/xbmc/addons/Repository.h +index 5ceabc4..b3cac90 100644 +--- a/xbmc/addons/Repository.h ++++ b/xbmc/addons/Repository.h +@@ -19,10 +19,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "Addon.h" + #include "utils/Job.h" + #include "utils/ProgressJob.h" +diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp +index 63e0191..567db49 100644 +--- a/xbmc/addons/Scraper.cpp ++++ b/xbmc/addons/Scraper.cpp +@@ -358,9 +358,9 @@ bool CScraper::Load() + bool result=m_parser.Load(LibPath()); + if (result) + { +- //! @todo this routine assumes that deps are a single level, and assumes the dep is installed. +- //! 1. Does it make sense to have recursive dependencies? +- //! 2. Should we be checking the dep versions or do we assume it is ok? ++ // TODO: this routine assumes that deps are a single level, and assumes the dep is installed. ++ // 1. Does it make sense to have recursive dependencies? ++ // 2. Should we be checking the dep versions or do we assume it is ok? + ADDONDEPS deps = GetDeps(); + ADDONDEPS::iterator itr = deps.begin(); + while (itr != deps.end()) +diff --git a/xbmc/addons/Scraper.h b/xbmc/addons/Scraper.h +index 081aace..2e9357b 100644 +--- a/xbmc/addons/Scraper.h ++++ b/xbmc/addons/Scraper.h +@@ -18,11 +18,6 @@ + * . + * + */ +- +-#include +-#include +-#include +- + #include "addons/Addon.h" + #include "XBDateTime.h" + #include "utils/ScraperUrl.h" +diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp +index c57ee3a..7975cea 100644 +--- a/xbmc/addons/Skin.cpp ++++ b/xbmc/addons/Skin.cpp +@@ -311,8 +311,8 @@ bool CSkinInfo::LoadStartupWindows(const cp_extension_t *ext) + m_startupWindows.emplace_back(WINDOW_RADIO_CHANNELS, "19183"); + m_startupWindows.emplace_back(WINDOW_PROGRAMS, "0"); + m_startupWindows.emplace_back(WINDOW_PICTURES, "1"); +- m_startupWindows.emplace_back(WINDOW_MUSIC_NAV, "2"); +- m_startupWindows.emplace_back(WINDOW_VIDEO_NAV, "3"); ++ m_startupWindows.emplace_back(WINDOW_MUSIC, "2"); ++ m_startupWindows.emplace_back(WINDOW_VIDEOS, "3"); + m_startupWindows.emplace_back(WINDOW_FILES, "7"); + m_startupWindows.emplace_back(WINDOW_SETTINGS_MENU, "5"); + m_startupWindows.emplace_back(WINDOW_WEATHER, "8"); +diff --git a/xbmc/addons/Visualisation.h b/xbmc/addons/Visualisation.h +index f5aee2f..10bcb64 100644 +--- a/xbmc/addons/Visualisation.h ++++ b/xbmc/addons/Visualisation.h +@@ -29,7 +29,6 @@ + #include + #include + #include +-#include + + #define AUDIO_BUFFER_SIZE 512 // MUST BE A POWER OF 2!!! + #define MAX_AUDIO_BUFFERS 16 +diff --git a/xbmc/addons/binary/interfaces/AddonInterfaces.cpp b/xbmc/addons/binary/interfaces/AddonInterfaces.cpp +index b8d55a8..e317b4f 100644 +--- a/xbmc/addons/binary/interfaces/AddonInterfaces.cpp ++++ b/xbmc/addons/binary/interfaces/AddonInterfaces.cpp +@@ -316,7 +316,7 @@ void CAddonInterfaces::OnApplicationMessage(ThreadMessage* pMsg) + case TMSG_GUI_ADDON_DIALOG: + { + if (pMsg->lpVoid) +- { //! @todo This is ugly - really these binary add-on dialogs should just be normal Kodi dialogs ++ { // TODO: This is ugly - really these binary add-on dialogs should just be normal Kodi dialogs + switch (pMsg->param1) + { + case 1: +diff --git a/xbmc/addons/binary/interfaces/api1/AudioDSP/AddonCallbacksAudioDSP.cpp b/xbmc/addons/binary/interfaces/api1/AudioDSP/AddonCallbacksAudioDSP.cpp +index c0e3e40..a12c804 100644 +--- a/xbmc/addons/binary/interfaces/api1/AudioDSP/AddonCallbacksAudioDSP.cpp ++++ b/xbmc/addons/binary/interfaces/api1/AudioDSP/AddonCallbacksAudioDSP.cpp +@@ -20,8 +20,8 @@ + + #include "Application.h" + #include "cores/AudioEngine/AEFactory.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h" + #include "cores/AudioEngine/Interfaces/AESound.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "settings/AdvancedSettings.h" +diff --git a/xbmc/addons/binary/interfaces/api1/GUI/AddonGUIWindow.cpp b/xbmc/addons/binary/interfaces/api1/GUI/AddonGUIWindow.cpp +index 891dafa..92cef20 100644 +--- a/xbmc/addons/binary/interfaces/api1/GUI/AddonGUIWindow.cpp ++++ b/xbmc/addons/binary/interfaces/api1/GUI/AddonGUIWindow.cpp +@@ -25,7 +25,6 @@ + #include "addons/Addon.h" + #include "guilib/GUIWindowManager.h" + #include "guilib/TextureManager.h" +-#include "input/Key.h" + #include "messaging/ApplicationMessenger.h" + #include "utils/log.h" + #include "utils/URIUtils.h" +@@ -78,9 +77,9 @@ bool CGUIAddonWindow::OnAction(const CAction &action) + + bool CGUIAddonWindow::OnMessage(CGUIMessage& message) + { +- //! @todo We shouldn't be dropping down to CGUIWindow in any of this ideally. +- //! We have to make up our minds about what python should be doing and +- //! what this side of things should be doing ++ // TODO: We shouldn't be dropping down to CGUIWindow in any of this ideally. ++ // We have to make up our minds about what python should be doing and ++ // what this side of things should be doing + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: +diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/dlfcn-win32.cpp b/xbmc/addons/kodi-addon-dev-kit/include/kodi/dlfcn-win32.cpp +index 2e182a1..5839921 100644 +--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/dlfcn-win32.cpp ++++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/dlfcn-win32.cpp +@@ -36,7 +36,7 @@ static HMODULE global_objects[MAX_OBJECTS]; + + /* This function adds an object to the list of global objects. + * The implementation is very simple and slow. +- * @todo should failing this function be enough to fail the call to dlopen( )? ++ * TODO: should failing this function be enough to fail the call to dlopen( )? + */ + static void global_object_add( HMODULE hModule ) + { +diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h +index 31433a4..591afcc 100644 +--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h ++++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h +@@ -22,7 +22,7 @@ + + #include "kodi_peripheral_types.h" + +-#define PERIPHERAL_ADDON_JOYSTICKS //! @todo ++#define PERIPHERAL_ADDON_JOYSTICKS // TODO + + #ifdef __cplusplus + extern "C" +diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h +index f81ee74..85e2363 100644 +--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h ++++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h +@@ -268,7 +268,7 @@ extern "C" + } ATTRIBUTE_PACKED JOYSTICK_FEATURE; + ///} + +- //! @todo Mouse, light gun, multitouch ++ // TODO: Mouse, light gun, multitouch + + /*! + * @brief Structure to transfer the methods from kodi_peripheral_dll.h to the frontend +diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h +index 516bb86..700f912 100644 +--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h ++++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h +@@ -36,7 +36,7 @@ + + #define DVD_TIME_BASE 1000000 + +-//! @todo original definition is in DVDClock.h ++//TODO original definition is in DVDClock.h + #define DVD_NOPTS_VALUE 0xFFF0000000000000 + + class CHelper_libXBMC_pvr +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index 0a97616..c234148 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -45,6 +45,7 @@ + #define LOGSAMBA (1 << (LOGMASKBIT + 0)) + #define LOGCURL (1 << (LOGMASKBIT + 1)) + #define LOGFFMPEG (1 << (LOGMASKBIT + 2)) ++#define LOGRTMP (1 << (LOGMASKBIT + 3)) + #define LOGDBUS (1 << (LOGMASKBIT + 4)) + #define LOGJSONRPC (1 << (LOGMASKBIT + 5)) + #define LOGAUDIO (1 << (LOGMASKBIT + 6)) +@@ -53,6 +54,7 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGWEBSERVER (1 << (LOGMASKBIT + 11)) ++#define LOGPVR (1 << (LOGMASKBIT + 12)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp +index 97f22e2..13a6393 100644 +--- a/xbmc/cores/AudioEngine/AESinkFactory.cpp ++++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp +@@ -30,7 +30,7 @@ + #include "Sinks/AESinkALSA.h" + #if defined(HAS_PULSEAUDIO) + #include "Sinks/AESinkPULSE.h" +- #endif ++ #endif + #elif defined(TARGET_DARWIN_IOS) + #include "Sinks/AESinkDARWINIOS.h" + #elif defined(TARGET_DARWIN_OSX) +@@ -278,9 +278,7 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) + info.m_sinkName = "ALSA"; + CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force); + if(!info.m_deviceInfoList.empty()) +- { + list.push_back(info); +- } + #endif + + #if defined(HAS_PULSEAUDIO) +@@ -288,10 +286,7 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) + info.m_sinkName = "PULSE"; + CAESinkPULSE::EnumerateDevicesEx(info.m_deviceInfoList, force); + if(!info.m_deviceInfoList.empty()) +- { + list.push_back(info); +- return; +- } + #endif + + info.m_deviceInfoList.clear(); +diff --git a/xbmc/cores/AudioEngine/CMakeLists.txt b/xbmc/cores/AudioEngine/CMakeLists.txt +index 41190ad..1bced66 100644 +--- a/xbmc/cores/AudioEngine/CMakeLists.txt ++++ b/xbmc/cores/AudioEngine/CMakeLists.txt +@@ -1,11 +1,11 @@ + set(SOURCES AEFactory.cpp + AEResampleFactory.cpp + AESinkFactory.cpp +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.cpp +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPAddon.cpp +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPDatabase.cpp +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.cpp +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp ++ DSPAddons/ActiveAEDSP.cpp ++ DSPAddons/ActiveAEDSPAddon.cpp ++ DSPAddons/ActiveAEDSPDatabase.cpp ++ DSPAddons/ActiveAEDSPMode.cpp ++ DSPAddons/ActiveAEDSPProcess.cpp + Encoders/AEEncoderFFmpeg.cpp + Engines/ActiveAE/ActiveAE.cpp + Engines/ActiveAE/ActiveAEBuffer.cpp +@@ -25,11 +25,11 @@ set(SOURCES AEFactory.cpp + set(HEADERS AEFactory.h + AEResampleFactory.h + AESinkFactory.h +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPAddon.h +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPDatabase.h +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.h +- Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h ++ DSPAddons/ActiveAEDSP.h ++ DSPAddons/ActiveAEDSPAddon.h ++ DSPAddons/ActiveAEDSPDatabase.h ++ DSPAddons/ActiveAEDSPMode.h ++ DSPAddons/ActiveAEDSPProcess.h + Encoders/AEEncoderFFmpeg.h + Engines/ActiveAE/ActiveAE.h + Engines/ActiveAE/ActiveAEBuffer.h +@@ -95,7 +95,7 @@ if(CORE_SYSTEM_NAME STREQUAL rbpi) + Sinks/AESinkPi.h) + endif() + +-if(CORE_SYSTEM_NAME STREQUAL osx) ++if(CORE_SYSTEM_NAME STREQUAL darwin) + list(APPEND SOURCES Sinks/AESinkDARWINOSX.cpp + Sinks/osx/AEDeviceEnumerationOSX.cpp + Sinks/osx/CoreAudioChannelLayout.cpp +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp +new file mode 100644 +index 0000000..5dce177 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp +@@ -0,0 +1,935 @@ ++/* ++ * Copyright (C) 2010-2015 Team Kodi ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Kodi; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ActiveAEDSP.h" ++ ++#include ++#include ++ ++extern "C" { ++#include "libavutil/channel_layout.h" ++} ++ ++#include "ActiveAEDSPProcess.h" ++#include "addons/AddonInstaller.h" ++#include "addons/AddonSystemSettings.h" ++#include "addons/GUIDialogAddonSettings.h" ++#include "Application.h" ++#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" ++#include "cores/AudioEngine/Interfaces/AEResample.h" ++#include "cores/AudioEngine/Utils/AEUtil.h" ++#include "cores/IPlayer.h" ++#include "dialogs/GUIDialogKaiToast.h" ++#include "dialogs/GUIDialogOK.h" ++#include "dialogs/GUIDialogSelect.h" ++#include "guiinfo/GUIInfoLabels.h" ++#include "guilib/GUIWindowManager.h" ++#include "GUIUserMessages.h" ++#include "messaging/ApplicationMessenger.h" ++#include "messaging/helpers/DialogHelper.h" ++#include "settings/AdvancedSettings.h" ++#include "settings/dialogs/GUIDialogAudioDSPManager.h" ++#include "settings/MediaSettings.h" ++#include "settings/MediaSourceSettings.h" ++#include "settings/Settings.h" ++#include "utils/JobManager.h" ++#include "utils/StringUtils.h" ++ ++ ++using namespace ADDON; ++using namespace ActiveAE; ++using namespace KODI::MESSAGING; ++ ++using KODI::MESSAGING::HELPERS::DialogResponse; ++ ++#define MIN_DSP_ARRAY_SIZE 4096 ++ ++/*! @name Master audio dsp control class */ ++//@{ ++CActiveAEDSP::CActiveAEDSP() ++ : m_isActive(false) ++ , m_usedProcessesCnt(0) ++ , m_activeProcessId(-1) ++ , m_isValidAudioDSPSettings(false) ++{ ++ Cleanup(); ++} ++ ++CActiveAEDSP::~CActiveAEDSP() ++{ ++ Deactivate(); ++ CAddonMgr::GetInstance().UnregisterAddonMgrCallback(ADDON_ADSPDLL); ++ CSettings::GetInstance().UnregisterCallback(this); ++ CLog::Log(LOGDEBUG, "ActiveAE DSP - destroyed"); ++} ++ ++void CActiveAEDSP::Init(void) ++{ ++ std::set settingSet; ++ settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_DSPADDONSENABLED); ++ settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_DSPSETTINGS); ++ settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_DSPRESETDB); ++ CSettings::GetInstance().RegisterCallback(this, settingSet); ++ ++ CAddonMgr::GetInstance().RegisterAddonMgrCallback(ADDON_ADSPDLL, this); ++ ++ if (CSettings::GetInstance().GetBool(CSettings::SETTING_AUDIOOUTPUT_DSPADDONSENABLED)) ++ Activate(); ++} ++//@} ++ ++/*! @name initialization and configuration methods */ ++//@{ ++void CActiveAEDSP::Activate(void) ++{ ++ /* first stop and remove any audio dsp add-on's */ ++ Deactivate(); ++ ++ CSingleLock lock(m_critSection); ++ ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - starting"); ++ ++ UpdateAddons(); ++ m_isActive = true; ++} ++ ++class CActiveAEDSPModeUpdateJob : public CJob ++{ ++public: ++ CActiveAEDSPModeUpdateJob() {} ++ ~CActiveAEDSPModeUpdateJob(void) {} ++ ++ bool DoWork(void) ++ { ++ CServiceBroker::GetADSP().TriggerModeUpdate(false); ++ return true; ++ } ++}; ++ ++void CActiveAEDSP::TriggerModeUpdate(bool bAsync /* = true */) ++{ ++ if (bAsync) ++ { ++ CActiveAEDSPModeUpdateJob *job = new CActiveAEDSPModeUpdateJob(); ++ CJobManager::GetInstance().AddJob(job, NULL); ++ return; ++ } ++ ++ CLog::Log(LOGINFO, "ActiveAE DSP - %s - Update mode selections", __FUNCTION__); ++ ++ if (!m_databaseDSP.IsOpen()) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - failed to open the database"); ++ return; ++ } ++ ++ for (unsigned int i = 0; i < AE_DSP_MODE_TYPE_MAX; ++i) ++ { ++ m_modes[i].clear(); ++ m_databaseDSP.GetModes(m_modes[i], i); ++ } ++ ++ /* ++ * if any dsp processing is active restart playback ++ */ ++ if (m_usedProcessesCnt > 0) ++ { ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - restarting playback after disabled dsp system"); ++ CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_RESTART); ++ } ++} ++ ++void CActiveAEDSP::Deactivate(void) ++{ ++ /* check whether the audio dsp is loaded */ ++ if (!m_isActive) ++ return; ++ ++ CSingleLock lock(m_critSection); ++ ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - stopping"); ++ ++ m_addonMap.clear(); ++ ++ /* unload all data */ ++ Cleanup(); ++ ++ /* close database */ ++ if (m_databaseDSP.IsOpen()) ++ m_databaseDSP.Close(); ++} ++ ++void CActiveAEDSP::Cleanup(void) ++{ ++ CActiveAEDSPProcessPtr tmp; ++ for (unsigned int i = 0; i < AE_DSP_STREAM_MAX_STREAMS; ++i) ++ m_usedProcesses[i] = tmp; ++ ++ m_isActive = false; ++ m_usedProcessesCnt = 0; ++ m_isValidAudioDSPSettings = false; ++ ++ for (unsigned int i = 0; i < AE_DSP_MODE_TYPE_MAX; ++i) ++ m_modes[i].clear(); ++} ++ ++bool CActiveAEDSP::InstallAddonAllowed(const std::string &strAddonId) const ++{ ++ return !m_isActive || ++ !IsInUse(strAddonId) || ++ m_usedProcessesCnt == 0; ++} ++ ++void CActiveAEDSP::ResetDatabase(void) ++{ ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - clearing the audio DSP database"); ++ ++ if (IsProcessing()) ++ { ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - stopping playback"); ++ CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_STOP); ++ } ++ ++ /* stop the system */ ++ Deactivate(); ++ ++ if (m_databaseDSP.Open()) ++ { ++ m_databaseDSP.DeleteModes(); ++ m_databaseDSP.DeleteActiveDSPSettings(); ++ m_databaseDSP.DeleteAddons(); ++ ++ m_databaseDSP.Close(); ++ } ++ ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - database cleared"); ++ ++ CLog::Log(LOGNOTICE, "ActiveAE DSP - restarting the audio DSP handler"); ++ m_databaseDSP.Open(); ++ Cleanup(); ++ Activate(); ++} ++//@} ++ ++/*! @name Settings and action callback methods (OnAction currently unused */ ++//@{ ++void CActiveAEDSP::OnSettingAction(const CSetting *setting) ++{ ++ if (setting == NULL) ++ return; ++ ++ const std::string &settingId = setting->GetId(); ++ ++ if (settingId == CSettings::SETTING_AUDIOOUTPUT_DSPSETTINGS) ++ { ++ if (!IsActivated() || !HasAvailableModes()) ++ { ++ CGUIDialogOK::ShowAndGetInput(14117, 0, 15065, 0); ++ return; ++ } ++ ++ CGUIDialogAudioDSPManager *dialog = (CGUIDialogAudioDSPManager *)g_windowManager.GetWindow(WINDOW_DIALOG_AUDIO_DSP_MANAGER); ++ if (dialog) ++ dialog->Open(); ++ } ++ else if (settingId == CSettings::SETTING_AUDIOOUTPUT_DSPRESETDB) ++ { ++ if (HELPERS::ShowYesNoDialogLines(CVariant{19098}, CVariant{36440}, CVariant{750}) == ++ DialogResponse::YES) ++ { ++ CDateTime::ResetTimezoneBias(); ++ ResetDatabase(); ++ } ++ } ++} ++//@} ++ ++/*! @name addon installation callback methods */ ++//@{ ++bool CActiveAEDSP::RequestRestart(AddonPtr addon, bool bDataChanged) ++{ ++ return StopAudioDSPAddon(addon, true); ++} ++ ++bool CActiveAEDSP::RequestRemoval(AddonPtr addon) ++{ ++ return StopAudioDSPAddon(addon, false); ++} ++ ++bool CActiveAEDSP::IsInUse(const std::string &strAddonId) const ++{ ++ CSingleLock lock(m_critSection); ++ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(citr->second->ID()) && citr->second->ID() == strAddonId) ++ return true; ++ return false; ++} ++ ++bool CActiveAEDSP::IsKnownAudioDSPAddon(const AddonPtr &addon) const ++{ ++ // database IDs start at 1 ++ return GetAudioDSPAddonId(addon) > 0; ++} ++ ++int CActiveAEDSP::GetAudioDSPAddonId(const AddonPtr &addon) const ++{ ++ CSingleLock lock(m_critUpdateSection); ++ ++ for (auto &entry : m_addonMap) ++ { ++ if (entry.second->ID() == addon->ID()) ++ { ++ return entry.first; ++ } ++ } ++ ++ return -1; ++} ++//@} ++ ++/*! @name GUIInfoManager calls */ ++//@{ ++bool CActiveAEDSP::TranslateBoolInfo(DWORD dwInfo) const ++{ ++ bool bReturn(false); ++ ++ CSingleLock lock(m_critSection); ++ ++ if (dwInfo == ADSP_HAS_MODES) ++ return HasAvailableModes(); ++ ++ if (!IsProcessing() || !m_usedProcesses[m_activeProcessId]) ++ return bReturn; ++ ++ switch (dwInfo) ++ { ++ case ADSP_IS_ACTIVE: ++ bReturn = true; ++ break; ++ case ADSP_HAS_INPUT_RESAMPLE: ++ bReturn = m_usedProcesses[m_activeProcessId]->HasActiveModes(AE_DSP_MODE_TYPE_INPUT_RESAMPLE); ++ break; ++ case ADSP_HAS_PRE_PROCESS: ++ bReturn = m_usedProcesses[m_activeProcessId]->HasActiveModes(AE_DSP_MODE_TYPE_PRE_PROCESS); ++ break; ++ case ADSP_HAS_MASTER_PROCESS: ++ bReturn = m_usedProcesses[m_activeProcessId]->HasActiveModes(AE_DSP_MODE_TYPE_MASTER_PROCESS); ++ break; ++ case ADSP_HAS_POST_PROCESS: ++ bReturn = m_usedProcesses[m_activeProcessId]->HasActiveModes(AE_DSP_MODE_TYPE_POST_PROCESS); ++ break; ++ case ADSP_HAS_OUTPUT_RESAMPLE: ++ bReturn = m_usedProcesses[m_activeProcessId]->HasActiveModes(AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); ++ break; ++ case ADSP_MASTER_ACTIVE: ++ bReturn = m_usedProcesses[m_activeProcessId]->GetActiveMasterMode() != NULL; ++ break; ++ default: ++ break; ++ }; ++ ++ return bReturn; ++} ++ ++bool CActiveAEDSP::TranslateCharInfo(DWORD dwInfo, std::string &strValue) const ++{ ++ bool bReturn(true); ++ ++ CSingleLock lock(m_critSection); ++ ++ if (!IsProcessing() || !m_usedProcesses[m_activeProcessId]) ++ return false; ++ ++ CActiveAEDSPModePtr activeMaster = m_usedProcesses[m_activeProcessId]->GetActiveMasterMode(); ++ if (activeMaster == NULL) ++ return false; ++ ++ switch (dwInfo) ++ { ++ case ADSP_ACTIVE_STREAM_TYPE: ++ strValue = g_localizeStrings.Get(GetStreamTypeName(m_usedProcesses[m_activeProcessId]->GetUsedStreamType())); ++ break; ++ case ADSP_DETECTED_STREAM_TYPE: ++ strValue = g_localizeStrings.Get(GetStreamTypeName(m_usedProcesses[m_activeProcessId]->GetDetectedStreamType())); ++ break; ++ case ADSP_MASTER_NAME: ++ { ++ AE_DSP_ADDON addon; ++ int modeId = activeMaster->ModeID(); ++ if (modeId == AE_DSP_MASTER_MODE_ID_PASSOVER || modeId >= AE_DSP_MASTER_MODE_ID_INTERNAL_TYPES) ++ strValue = g_localizeStrings.Get(activeMaster->ModeName()); ++ else if (CServiceBroker::GetADSP().GetAudioDSPAddon(activeMaster->AddonID(), addon)) ++ strValue = g_localizeStrings.GetAddonString(addon->ID(), activeMaster->ModeName()); ++ } ++ break; ++ case ADSP_MASTER_INFO: ++ bReturn = m_usedProcesses[m_activeProcessId]->GetMasterModeStreamInfoString(strValue); ++ break; ++ case ADSP_MASTER_OWN_ICON: ++ strValue = activeMaster->IconOwnModePath(); ++ break; ++ case ADSP_MASTER_OVERRIDE_ICON: ++ strValue = activeMaster->IconOverrideModePath(); ++ break; ++ default: ++ strValue.clear(); ++ bReturn = false; ++ break; ++ }; ++ ++ return bReturn; ++} ++//@} ++ ++/*! @name Current processing streams control function methods */ ++//@{ ++CAEChannelInfo CActiveAEDSP::GetInternalChannelLayout(AEStdChLayout stdLayout) ++{ ++ uint64_t channelLayoutOut; ++ switch (stdLayout) ++ { ++ default: ++ case AE_CH_LAYOUT_2_0: ++ channelLayoutOut = AV_CH_LAYOUT_STEREO; ++ break; ++ case AE_CH_LAYOUT_2_1: ++ channelLayoutOut = AV_CH_LAYOUT_2POINT1; ++ break; ++ case AE_CH_LAYOUT_3_0: ++ channelLayoutOut = AV_CH_LAYOUT_SURROUND; ++ break; ++ case AE_CH_LAYOUT_3_1: ++ channelLayoutOut = AV_CH_LAYOUT_3POINT1; ++ break; ++ case AE_CH_LAYOUT_4_0: ++ channelLayoutOut = AV_CH_LAYOUT_2_2; ++ break; ++ case AE_CH_LAYOUT_4_1: ++ channelLayoutOut = AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY; ++ break; ++ case AE_CH_LAYOUT_5_0: ++ channelLayoutOut = AV_CH_LAYOUT_5POINT0; ++ break; ++ case AE_CH_LAYOUT_5_1: ++ channelLayoutOut = AV_CH_LAYOUT_5POINT1; ++ break; ++ case AE_CH_LAYOUT_7_0: ++ channelLayoutOut = AV_CH_LAYOUT_7POINT0; ++ break; ++ case AE_CH_LAYOUT_7_1: ++ channelLayoutOut = AV_CH_LAYOUT_7POINT1; ++ break; ++ } ++ return CAEUtil::GetAEChannelLayout(channelLayoutOut); ++} ++ ++bool CActiveAEDSP::CreateDSPs(unsigned int &streamId, CActiveAEDSPProcessPtr &process, const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, ++ AEQuality quality, enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, ++ int profile, bool wasActive) ++{ ++ if (!IsActivated() || m_usedProcessesCnt >= AE_DSP_STREAM_MAX_STREAMS) ++ return false; ++ ++ CSingleLock lock(m_critSection); ++ ++ AE_DSP_STREAMTYPE requestedStreamType = LoadCurrentAudioSettings(); ++ ++ CActiveAEDSPProcessPtr usedProc; ++ if (wasActive && streamId != (unsigned int)-1 && streamId < AE_DSP_STREAM_MAX_STREAMS) ++ { ++ if (m_usedProcesses[streamId] != NULL) ++ { ++ usedProc = m_usedProcesses[streamId]; ++ } ++ } ++ else ++ { ++ for (unsigned int i = 0; i < AE_DSP_STREAM_MAX_STREAMS; ++i) ++ { ++ /* find a free position */ ++ if (m_usedProcesses[i] == NULL) ++ { ++ usedProc = CActiveAEDSPProcessPtr(new CActiveAEDSPProcess(i)); ++ streamId = i; ++ break; ++ } ++ } ++ } ++ ++ if (usedProc == NULL) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - can't find active processing class", __FUNCTION__); ++ return false; ++ } ++ ++ if (!usedProc->Create(inputFormat, outputFormat, upmix, quality, requestedStreamType, matrix_encoding, audio_service_type, profile)) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - Creation of processing class failed", __FUNCTION__); ++ return false; ++ } ++ ++ if (!wasActive) ++ { ++ process = usedProc; ++ m_activeProcessId = streamId; ++ m_usedProcesses[streamId] = usedProc; ++ m_usedProcessesCnt++; ++ } ++ return true; ++} ++ ++void CActiveAEDSP::DestroyDSPs(unsigned int streamId) ++{ ++ CSingleLock lock(m_critSection); ++ ++ if (streamId != (unsigned int)-1 && m_usedProcesses[streamId] != NULL) ++ { ++ m_usedProcesses[streamId]->Destroy(); ++ m_usedProcesses[streamId] = CActiveAEDSPProcessPtr(); ++ --m_usedProcessesCnt; ++ } ++ if (m_usedProcessesCnt == 0) ++ { ++ m_activeProcessId = -1; ++ } ++} ++ ++CActiveAEDSPProcessPtr CActiveAEDSP::GetDSPProcess(unsigned int streamId) ++{ ++ CSingleLock lock(m_critSection); ++ ++ if (streamId != (unsigned int)-1 && m_usedProcesses[streamId]) ++ return m_usedProcesses[streamId]; ++ return CActiveAEDSPProcessPtr(); ++} ++ ++unsigned int CActiveAEDSP::GetProcessingStreamsAmount(void) ++{ ++ CSingleLock lock(m_critSection); ++ return m_usedProcessesCnt; ++} ++ ++unsigned int CActiveAEDSP::GetActiveStreamId(void) ++{ ++ CSingleLock lock(m_critSection); ++ ++ return m_activeProcessId; ++} ++ ++bool CActiveAEDSP::HasAvailableModes(void) const ++{ ++ CSingleLock lock(m_critSection); ++ ++ for (unsigned int i = 0; i < AE_DSP_MODE_TYPE_MAX; ++i) ++ { ++ if (!m_modes[i].empty()) ++ return true; ++ } ++ ++ return false; ++} ++ ++const AE_DSP_MODELIST &CActiveAEDSP::GetAvailableModes(AE_DSP_MODE_TYPE modeType) ++{ ++ static AE_DSP_MODELIST emptyArray; ++ if (modeType < 0 || modeType >= AE_DSP_MODE_TYPE_MAX) ++ return emptyArray; ++ ++ CSingleLock lock(m_critSection); ++ return m_modes[modeType]; ++} ++ ++/*! @name addon update process methods */ ++//@{ ++bool CActiveAEDSP::StopAudioDSPAddon(AddonPtr addon, bool bRestart) ++{ ++ CSingleLock lock(m_critSection); ++ ++ int iId = GetAudioDSPAddonId(addon); ++ AE_DSP_ADDON mappedAddon; ++ if (GetReadyAudioDSPAddon(iId, mappedAddon)) ++ { ++ if (bRestart) ++ mappedAddon->ReCreate(); ++ else ++ mappedAddon->Destroy(); ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++void CActiveAEDSP::UpdateAddons() ++{ ++ VECADDONS addons; ++ AE_DSP_ADDON dspAddon; ++ ++ CAddonMgr::GetInstance().GetAddons(addons, ADDON_ADSPDLL); ++ ++ if (addons.empty()) ++ return; ++ ++ for (auto &addon : addons) ++ { ++ bool bEnabled = !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()); ++ if (bEnabled && (!IsKnownAudioDSPAddon(addon) || !IsReadyAudioDSPAddon(addon))) ++ { ++ std::hash hasher; ++ int iAddonId = static_cast(hasher(addon->ID())); ++ if (iAddonId < 0) ++ iAddonId = -iAddonId; ++ ++ /* create and open database */ ++ if (!m_databaseDSP.IsOpen()) ++ m_databaseDSP.Open(); ++ ++ if (IsKnownAudioDSPAddon(addon)) ++ { ++ AE_DSP_ADDON dspAddon; ++ GetAudioDSPAddon(iAddonId, dspAddon); ++ dspAddon->Create(iAddonId); ++ } ++ else ++ { ++ AE_DSP_ADDON dspAddon = std::dynamic_pointer_cast(addon); ++ if (!dspAddon) ++ { ++ CLog::Log(LOGERROR, "CActiveAEDSP::UpdateAndInitialiseAddons - severe error, incorrect add type"); ++ continue; ++ } ++ ++ dspAddon.get()->Create(iAddonId); ++ // register the add-on ++ if (m_addonMap.find(iAddonId) == m_addonMap.end()) ++ { ++ m_addonMap.insert(std::make_pair(iAddonId, dspAddon)); ++ m_addonNameIds.insert(make_pair(addon->ID(), iAddonId)); ++ } ++ } ++ } ++ } ++ ++ TriggerModeUpdate(); ++} ++//@} ++ ++/*! @name Played source settings methods ++ * @note for save of settings see CSaveFileStateJob */ ++//@{ ++AE_DSP_STREAMTYPE CActiveAEDSP::LoadCurrentAudioSettings(void) ++{ ++ CSingleLock lock(m_critSection); ++ ++ AE_DSP_STREAMTYPE type = AE_DSP_ASTREAM_INVALID; ++ ++ if (g_application.m_pPlayer->HasPlayer()) ++ { ++ CFileItem currentFile(g_application.CurrentFileItem()); ++ ++ /* load the persisted audio settings and set them as current */ ++ CAudioSettings loadedAudioSettings = CMediaSettings::GetInstance().GetDefaultAudioSettings(); ++ m_databaseDSP.GetActiveDSPSettings(currentFile, loadedAudioSettings); ++ ++ CMediaSettings::GetInstance().GetCurrentAudioSettings() = loadedAudioSettings; ++ type = (AE_DSP_STREAMTYPE) loadedAudioSettings.m_MasterStreamTypeSel; ++ ++ /* settings can be saved on next audio stream change */ ++ m_isValidAudioDSPSettings = true; ++ } ++ return type; ++} ++//@} ++ ++/*! @name Backend methods */ ++//@{ ++ ++bool CActiveAEDSP::IsProcessing(void) const ++{ ++ return m_isActive && m_usedProcessesCnt > 0; ++} ++ ++bool CActiveAEDSP::IsActivated(void) const ++{ ++ return m_isActive; ++} ++ ++int CActiveAEDSP::EnabledAudioDSPAddonAmount(void) const ++{ ++ int iReturn(0); ++ CSingleLock lock(m_critUpdateSection); ++ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(citr->second->ID())) ++ ++iReturn; ++ } ++ ++ return iReturn; ++} ++ ++bool CActiveAEDSP::HasEnabledAudioDSPAddons(void) const ++{ ++ return EnabledAudioDSPAddonAmount() > 0; ++} ++ ++int CActiveAEDSP::GetEnabledAudioDSPAddons(AE_DSP_ADDONMAP &addons) const ++{ ++ int iReturn(0); ++ CSingleLock lock(m_critUpdateSection); ++ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(citr->second->ID())) ++ { ++ addons.insert(std::make_pair(citr->second->GetID(), citr->second)); ++ ++iReturn; ++ } ++ } ++ ++ return iReturn; ++} ++ ++int CActiveAEDSP::ReadyAudioDSPAddonAmount(void) const ++{ ++ int iReturn(0); ++ CSingleLock lock(m_critUpdateSection); ++ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (citr->second->ReadyToUse()) ++ ++iReturn; ++ } ++ ++ return iReturn; ++} ++ ++bool CActiveAEDSP::HasReadyAudioDSPAddons(void) const ++{ ++ return ReadyAudioDSPAddonAmount() > 0; ++} ++ ++bool CActiveAEDSP::IsReadyAudioDSPAddon(int iAddonId) const ++{ ++ AE_DSP_ADDON addon; ++ return GetReadyAudioDSPAddon(iAddonId, addon); ++} ++ ++bool CActiveAEDSP::IsReadyAudioDSPAddon(const AddonPtr &addon) ++{ ++ CSingleLock lock(m_critUpdateSection); ++ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (citr->second->ID() == addon->ID()) ++ return citr->second->ReadyToUse(); ++ } ++ ++ return false; ++} ++ ++int CActiveAEDSP::GetAddonId(const std::string& strId) const ++{ ++ CSingleLock lock(m_critSection); ++ std::map::const_iterator it = m_addonNameIds.find(strId); ++ return it != m_addonNameIds.end() ? it->second : -1; ++} ++ ++bool CActiveAEDSP::GetReadyAudioDSPAddon(int iAddonId, AE_DSP_ADDON &addon) const ++{ ++ if (GetAudioDSPAddon(iAddonId, addon)) ++ return addon->ReadyToUse(); ++ return false; ++} ++ ++bool CActiveAEDSP::GetAudioDSPAddonName(int iAddonId, std::string &strName) const ++{ ++ bool bReturn(false); ++ AE_DSP_ADDON addon; ++ if ((bReturn = GetReadyAudioDSPAddon(iAddonId, addon)) == true) ++ strName = addon->GetAudioDSPName(); ++ ++ return bReturn; ++} ++ ++bool CActiveAEDSP::GetAudioDSPAddon(int iAddonId, AE_DSP_ADDON &addon) const ++{ ++ bool bReturn(false); ++ if (iAddonId <= AE_DSP_INVALID_ADDON_ID) ++ return bReturn; ++ ++ CSingleLock lock(m_critUpdateSection); ++ ++ AE_DSP_ADDONMAP_CITR citr = m_addonMap.find(iAddonId); ++ if (citr != m_addonMap.end()) ++ { ++ addon = citr->second; ++ bReturn = true; ++ } ++ ++ return bReturn; ++} ++ ++bool CActiveAEDSP::GetAudioDSPAddon(const std::string &strId, AddonPtr &addon) const ++{ ++ CSingleLock lock(m_critUpdateSection); ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (citr->second->ID() == strId) ++ { ++ addon = citr->second; ++ return true; ++ } ++ } ++ return false; ++} ++//@} ++ ++/*! @name Menu hook methods */ ++//@{ ++bool CActiveAEDSP::HaveMenuHooks(AE_DSP_MENUHOOK_CAT cat, int iDSPAddonID) ++{ ++ for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) ++ { ++ if (citr->second->ReadyToUse()) ++ { ++ if (citr->second->HaveMenuHooks(cat)) ++ { ++ if (iDSPAddonID > 0 && citr->second->GetID() == iDSPAddonID) ++ return true; ++ else if (iDSPAddonID < 0) ++ return true; ++ } ++ else if (cat == AE_DSP_MENUHOOK_SETTING) ++ { ++ AddonPtr addon; ++ if (CAddonMgr::GetInstance().GetAddon(citr->second->ID(), addon) && addon->HasSettings()) ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++bool CActiveAEDSP::GetMenuHooks(int iDSPAddonID, AE_DSP_MENUHOOK_CAT cat, AE_DSP_MENUHOOKS &hooks) ++{ ++ bool bReturn(false); ++ ++ if (iDSPAddonID < 0) ++ return bReturn; ++ ++ AE_DSP_ADDON addon; ++ if (GetReadyAudioDSPAddon(iDSPAddonID, addon) && addon->HaveMenuHooks(cat)) ++ { ++ AE_DSP_MENUHOOKS *addonhooks = addon->GetMenuHooks(); ++ for (unsigned int i = 0; i < addonhooks->size(); ++i) ++ { ++ if (cat == AE_DSP_MENUHOOK_ALL || addonhooks->at(i).category == cat) ++ { ++ hooks.push_back(addonhooks->at(i)); ++ bReturn = true; ++ } ++ } ++ } ++ ++ return bReturn; ++} ++//@} ++ ++/*! @name General helper functions */ ++//@{ ++enum AEChannel CActiveAEDSP::GetKODIChannel(AE_DSP_CHANNEL channel) ++{ ++ switch (channel) ++ { ++ case AE_DSP_CH_FL: return AE_CH_FL; ++ case AE_DSP_CH_FR: return AE_CH_FR; ++ case AE_DSP_CH_FC: return AE_CH_FC; ++ case AE_DSP_CH_LFE: return AE_CH_LFE; ++ case AE_DSP_CH_BL: return AE_CH_BL; ++ case AE_DSP_CH_BR: return AE_CH_BR; ++ case AE_DSP_CH_FLOC: return AE_CH_FLOC; ++ case AE_DSP_CH_FROC: return AE_CH_FROC; ++ case AE_DSP_CH_BC: return AE_CH_BC; ++ case AE_DSP_CH_SL: return AE_CH_SL; ++ case AE_DSP_CH_SR: return AE_CH_SR; ++ case AE_DSP_CH_TC: return AE_CH_TC; ++ case AE_DSP_CH_TFL: return AE_CH_TFL; ++ case AE_DSP_CH_TFC: return AE_CH_TFC; ++ case AE_DSP_CH_TFR: return AE_CH_TFR; ++ case AE_DSP_CH_TBL: return AE_CH_TBL; ++ case AE_DSP_CH_TBC: return AE_CH_TBC; ++ case AE_DSP_CH_TBR: return AE_CH_TBR; ++ default: ++ return AE_CH_NULL; ++ } ++} ++ ++AE_DSP_CHANNEL CActiveAEDSP::GetDSPChannel(enum AEChannel channel) ++{ ++ switch (channel) ++ { ++ case AE_CH_FL: return AE_DSP_CH_FL; ++ case AE_CH_FR: return AE_DSP_CH_FR; ++ case AE_CH_FC: return AE_DSP_CH_FC; ++ case AE_CH_LFE: return AE_DSP_CH_LFE; ++ case AE_CH_BL: return AE_DSP_CH_BL; ++ case AE_CH_BR: return AE_DSP_CH_BR; ++ case AE_CH_FLOC: return AE_DSP_CH_FLOC; ++ case AE_CH_FROC: return AE_DSP_CH_FROC; ++ case AE_CH_BC: return AE_DSP_CH_BC; ++ case AE_CH_SL: return AE_DSP_CH_SL; ++ case AE_CH_SR: return AE_DSP_CH_SR; ++ case AE_CH_TC: return AE_DSP_CH_TC; ++ case AE_CH_TFL: return AE_DSP_CH_TFL; ++ case AE_CH_TFC: return AE_DSP_CH_TFC; ++ case AE_CH_TFR: return AE_DSP_CH_TFR; ++ case AE_CH_TBL: return AE_DSP_CH_TBL; ++ case AE_CH_TBC: return AE_DSP_CH_TBC; ++ case AE_CH_TBR: return AE_DSP_CH_TBR; ++ default: ++ return AE_DSP_CH_INVALID; ++ } ++} ++ ++/*! ++ * Contains string name id's related to the AE_DSP_ASTREAM_ values ++ */ ++const int CActiveAEDSP::m_StreamTypeNameTable[] = ++{ ++ 15004, //!< "Basic" ++ 249, //!< "Music" ++ 157, //!< "Video" ++ 15016, //!< "Games" ++ 15005, //!< "Application" ++ 15006, //!< "Phone" ++ 15007, //!< "Message" ++ 14061 //!< "Auto" ++}; ++ ++int CActiveAEDSP::GetStreamTypeName(unsigned int streamType) ++{ ++ if (streamType > AE_DSP_ASTREAM_AUTO) ++ return -1; ++ return m_StreamTypeNameTable[streamType]; ++} ++//@} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h +new file mode 100644 +index 0000000..9631847 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h +@@ -0,0 +1,413 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ServiceBroker.h" ++#include "cores/AudioEngine/Utils/AEAudioFormat.h" ++#include "cores/AudioEngine/Interfaces/AE.h" ++#include "threads/CriticalSection.h" ++#include "threads/Thread.h" ++#include "utils/Observer.h" ++#include "messaging/IMessageTarget.h" ++ ++#include "ActiveAEDSPAddon.h" ++#include "ActiveAEDSPDatabase.h" ++#include "ActiveAEDSPMode.h" ++ ++#define ACTIVE_AE_DSP_STATE_OFF 0 ++#define ACTIVE_AE_DSP_STATE_ON 1 ++ ++#define ACTIVE_AE_DSP_SYNC_ACTIVATE 0 ++#define ACTIVE_AE_DSP_ASYNC_ACTIVATE 1 ++ ++extern "C" { ++#include "libavcodec/avcodec.h" ++} ++ ++class CAction; ++ ++namespace ActiveAE ++{ ++ class CActiveAEDSPProcess; ++ class CActiveAEDSPAddon; ++ ++ typedef std::shared_ptr CActiveAEDSPProcessPtr; ++ typedef std::map< int, AE_DSP_ADDON > AE_DSP_ADDONMAP; ++ typedef std::map< int, AE_DSP_ADDON >::iterator AE_DSP_ADDONMAP_ITR; ++ typedef std::map< int, AE_DSP_ADDON >::const_iterator AE_DSP_ADDONMAP_CITR; ++ ++ //@{ ++ /*! ++ * Static dsp handling class ++ */ ++ class CActiveAEDSP : public ADDON::IAddonMgrCallback, ++ public ISettingCallback ++ { ++ /*! @name Master audio dsp control class */ ++ //@{ ++ public: ++ /*! ++ * @brief Create a new CActiveAEDSP instance, which handles all audio DSP related operations in KODI. ++ */ ++ CActiveAEDSP(void); ++ ++ /*! ++ * @brief Stop the ActiveAEDSP and destroy all objects it created. ++ */ ++ virtual ~CActiveAEDSP(); ++ ++ void Init(void); ++ //@} ++ ++ /*! @name initialization and configuration methods */ ++ //@{ ++ /*! ++ * @brief Activate the addon dsp processing. ++ */ ++ void Activate(void); ++ ++ /*! ++ * @brief Stops dsp processing and the backend info update thread. ++ */ ++ void Deactivate(void); ++ ++ /*! ++ * @brief Delete all objects and processing classes. ++ */ ++ void Cleanup(void); ++ ++ /*! ++ * @brief Reset the audio dsp database to it's initial state and delete all the data inside. ++ */ ++ void ResetDatabase(void); ++ ++ /*! ++ * @brief Check whether an add-on can be upgraded or installed without restarting the audio dsp, when the add-on is in use ++ * @param strAddonId The add-on to check. ++ * @return True when the add-on can be installed, false otherwise. ++ */ ++ bool InstallAddonAllowed(const std::string& strAddonId) const; ++ ++ /*! ++ * @brief Get the audio dsp database pointer. ++ * @return The audio dsp database. ++ */ ++ CActiveAEDSPDatabase *GetADSPDatabase(void) { return &m_databaseDSP; } ++ //@} ++ ++ /*! @name Settings and action callback methods */ ++ //@{ ++ virtual void OnSettingAction(const CSetting *setting) override; ++ //@} ++ ++ /*! @name Backend methods */ ++ //@{ ++ /*! ++ * @return True when processing is possible ++ */ ++ bool IsActivated(void) const; ++ ++ /*! ++ * @return True when processing is active ++ */ ++ bool IsProcessing(void) const; ++ //@} ++ ++ /*! @name addon installation callback methods */ ++ //@{ ++ /*! ++ * @brief Restart a single audio dsp addon add-on. ++ * @param addon The add-on to restart. ++ * @param bDataChanged True if the addon's data changed, false otherwise (unused). ++ * @return True if the audio dsp addon was found and restarted, false otherwise. ++ */ ++ virtual bool RequestRestart(ADDON::AddonPtr addon, bool bDataChanged) override; ++ ++ /*! ++ * @brief Remove a single audio dsp add-on. ++ * @param addon The add-on to remove. ++ * @return True if it was found and removed, false otherwise. ++ */ ++ virtual bool RequestRemoval(ADDON::AddonPtr addon) override; ++ ++ /*! ++ * @brief Checks whether an add-on is loaded ++ * @param strAddonId The add-on id to check ++ * @return True when in use, false otherwise ++ */ ++ bool IsInUse(const std::string& strAddonId) const; ++ ++ /*! ++ * @brief Stop a audio dsp addon. ++ * @param addon The dsp addon to stop. ++ * @param bRestart If true, restart the addon. ++ * @return True if the it was found, false otherwise. ++ */ ++ bool StopAudioDSPAddon(ADDON::AddonPtr addon, bool bRestart); ++ ++ /*! ++ * @return The amount of enabled audio dsp addons. ++ */ ++ int EnabledAudioDSPAddonAmount(void) const; ++ ++ /*! ++ * @return True when at least one audio dsp addon is known and enabled, false otherwise. ++ */ ++ bool HasEnabledAudioDSPAddons(void) const; ++ ++ /*! ++ * @brief Get all enabled audio dsp addons. ++ * @param addons Store the enabled addons in this map. ++ * @return The amount of enabled audio addons. ++ */ ++ int GetEnabledAudioDSPAddons(AE_DSP_ADDONMAP &addons) const; ++ ++ /*! ++ * @return The amount of ready audio dsp addons on current stream. ++ */ ++ int ReadyAudioDSPAddonAmount(void) const; ++ ++ /*! ++ * @brief Check whether there are any ready audio dsp addons. ++ * @return True if at least one audio dsp addon is ready. ++ */ ++ bool HasReadyAudioDSPAddons(void) const; ++ ++ /*! ++ * @brief Check whether a audio dsp addon ID points to a valid and ready add-on. ++ * @param iAddonId The addon ID. ++ * @return True when the addon ID is valid and ready, false otherwise. ++ */ ++ bool IsReadyAudioDSPAddon(int iAddonId) const; ++ ++ /*! ++ * @brief Check whether a audio dsp addon pointer points to a valid and ready add-on. ++ * @param addon The addon addon pointer. ++ * @return True when the addon pointer is valid and ready, false otherwise. ++ */ ++ bool IsReadyAudioDSPAddon(const ADDON::AddonPtr& addon); ++ ++ /*! ++ * @brief Get the instance of the audio dsp addon. ++ * @param strId The string id of the addon to get. ++ * @param addon The audio dsp addon. ++ * @return True if the addon was found, false otherwise. ++ */ ++ bool GetAudioDSPAddon(const std::string &strId, ADDON::AddonPtr &addon) const; ++ ++ /*! ++ * @brief Get the instance of the audio dsp addon. ++ * @param iAddonId The id of the addon to get. ++ * @param addon The audio dsp addon. ++ * @return True if the addon was found, false otherwise. ++ */ ++ bool GetAudioDSPAddon(int iAddonId, AE_DSP_ADDON &addon) const; ++ ++ /*! ++ * @brief Get the friendly name for the audio dsp addon with the given id. ++ * @param iAddonId The id of the addon. ++ * @param strName The friendly name of the audio dsp addon or an empty string when it wasn't found. ++ * @return True if it was found, false otherwise. ++ */ ++ bool GetAudioDSPAddonName(int iAddonId, std::string &strName) const; ++ ++ /*! ++ * @brief Update add-ons from the AddonManager ++ */ ++ void UpdateAddons(void); ++ ++ int GetAddonId(const std::string& strId) const; ++ //@} ++ ++ /*! @name GUIInfoManager calls */ ++ //@{ ++ /*! ++ * @brief Get a GUIInfoManager boolean. ++ * @param dwInfo The boolean to get. ++ * @return The requested boolean or false if it wasn't found. ++ */ ++ bool TranslateBoolInfo(DWORD dwInfo) const; ++ ++ /*! ++ * @brief Get a GUIInfoManager character string. ++ * @param dwInfo The string to get. ++ * @return The requested string or an empty one if it wasn't found. ++ */ ++ bool TranslateCharInfo(DWORD dwInfo, std::string &strValue) const; ++ //@} ++ ++ /*! @name Current processing streams control function methods */ ++ //@{ ++ /*!> ++ * Get the channel position defination for given channel layout ++ * @param stdLayout The layout identifier ++ * @return the from given identifier set channel information class ++ */ ++ CAEChannelInfo GetInternalChannelLayout(AEStdChLayout stdLayout); ++ ++ /*!> ++ * Create the dsp processing with check of all addons about the used input and output audio format. ++ * @param streamId The id of this stream ++ * @param inputFormat The used audio stream input format ++ * @param outputFormat Audio output format which is needed to send to the sinks ++ * @param quality The requested quality from settings ++ * @param wasActive if it is true a recreation of present stream control becomes performed (process class becomes not deleted) ++ * @return True if the dsp processing becomes available ++ */ ++ bool CreateDSPs(unsigned int &streamId, CActiveAEDSPProcessPtr &process, const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, ++ bool upmix, AEQuality quality, enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, ++ int profile, bool wasActive = false); ++ ++ /*!> ++ * Destroy all allocated dsp addons for this stream id and stops the processing. ++ * @param streamId The id of this stream ++ */ ++ void DestroyDSPs(unsigned int streamId); ++ ++ /*!> ++ * Get the dsp processing class of given stream id ++ * @param streamId The id of this stream ++ */ ++ CActiveAEDSPProcessPtr GetDSPProcess(unsigned int streamId); ++ ++ /*!> ++ * Get the amount of used dsp process stream handlers ++ * @return Returns amount of processes ++ */ ++ unsigned int GetProcessingStreamsAmount(void); ++ ++ /*!> ++ * Get the currently active processing stream id ++ * @return Stream id, or max unsigned int value (-1) if not active ++ */ ++ unsigned int GetActiveStreamId(void); ++ ++ /*! ++ * @brief Check for available modes present from add-ons ++ * ++ * @return true if one or more modes are available ++ */ ++ bool HasAvailableModes(void) const; ++ ++ /*!> ++ * Used to get all available modes on currently enabled add-ons ++ * It is used from CActiveAEDSPProcess to get a sorted modes list for a processing ++ * over the add-ons, several call to the same addon is possible with different mode id's. ++ * @param modeType The type to get ++ * @return modes Pointer to a buffer array where all available modes of type written in ++ */ ++ const AE_DSP_MODELIST &GetAvailableModes(AE_DSP_MODE_TYPE modeType); ++ ++ /*! ++ * @brief Load the settings for the current audio from the database. ++ * @return If it was present inside settings it return the type of this settings ++ */ ++ AE_DSP_STREAMTYPE LoadCurrentAudioSettings(void); ++ ++ /*! ++ * @brief Perfoms a update of all processing calls over the add-ons ++ * @param bAsync if true the update becomes performed on background ++ */ ++ void TriggerModeUpdate(bool bAsync = true); ++ //@} ++ ++ /*! @name Menu hook methods */ ++ //@{ ++ /*! ++ * @brief Check whether a audio dsp addon has any audio DSP specific menu entries. ++ * @param cat The category to know ++ * @param iAddonId The ID of the addon to get the menu entries for. Get the menu for the active channel if iAddonId < 0. ++ * @return True if the dsp addon has any menu hooks, false otherwise. ++ * @note The main usage for this method is to have bigger modifiable addon setting dialogs which make the usage of ++ * standard addon settings dialog as option to it ++ * see kodi_adsp_types.h for available types ++ */ ++ bool HaveMenuHooks(AE_DSP_MENUHOOK_CAT cat, int iAddonId = -1); ++ ++ /*! ++ * @brief Get the menu hooks for a dsp addon. ++ * @param iDSPAddonID The dsp addon to get the hooks for. ++ * @param cat The requested menu category ++ * @param hooks The container to add the hooks to. ++ * @return True if the hooks were added successfully (if any), false otherwise. ++ * @note The main usage for this method is to have bigger modifiable addon setting dialogs, the basic addon settings dialog ++ * can't be opened with it (is only in the menu list from ProcessMenuHooks) ++ * see kodi_adsp_types.h for available types ++ */ ++ bool GetMenuHooks(int iDSPAddonID, AE_DSP_MENUHOOK_CAT cat, AE_DSP_MENUHOOKS &hooks); ++ //@} ++ ++ /*! @name General helper functions */ ++ //@{ ++ /*! ++ * @brief Translate audio dsp channel flag to KODI channel flag ++ */ ++ static enum AEChannel GetKODIChannel(AE_DSP_CHANNEL channel); ++ ++ /*! ++ * @brief Translate KODI channel flag to audio dsp channel flag ++ */ ++ static AE_DSP_CHANNEL GetDSPChannel(enum AEChannel channel); ++ ++ /*! ++ * @brief Get name label id to given stream type id ++ */ ++ static int GetStreamTypeName(unsigned int streamType); ++ //@} ++ ++ protected: ++ /*! ++ * @brief Check whether a dsp addon is registered. ++ * @param addon The dsp addon to check. ++ * @return True if this addon is registered, false otherwise. ++ */ ++ bool IsKnownAudioDSPAddon(const ADDON::AddonPtr& addon) const; ++ ++ /*! ++ * @brief Get the instance of the dsp addon, if it's ready. ++ * @param iAddonId The id of the dsp addon to get. ++ * @param addon The addon data pointer. ++ * @return True if the addon is ready, false otherwise. ++ */ ++ bool GetReadyAudioDSPAddon(int iAddonId, AE_DSP_ADDON &addon) const; ++ ++ /*! ++ * @brief Get the dsp related Id for selected addon ++ * @param addon The addon class pointer. ++ * @return the id of the asked addon, -1 if not available ++ */ ++ int GetAudioDSPAddonId(const ADDON::AddonPtr& addon) const; ++ ++ ++ static const int m_StreamTypeNameTable[]; /*!< Table for stream type strings related to type id */ ++ bool m_isActive; /*!< set to true if all available dsp addons are loaded */ ++ AE_DSP_ADDONMAP m_addonMap; /*!< a map of all known audio dsp addons */ ++ CActiveAEDSPDatabase m_databaseDSP; /*!< the database for all audio DSP related data */ ++ CCriticalSection m_critSection; /*!< Critical lock for control functions */ ++ CCriticalSection m_critUpdateSection; /*!< Critical lock for update thread related functions */ ++ unsigned int m_usedProcessesCnt; /*!< the amount of used addon processes */ ++ CActiveAEDSPProcessPtr m_usedProcesses[AE_DSP_STREAM_MAX_STREAMS]; /*!< Pointer to active process performing classes */ ++ unsigned int m_activeProcessId; /*!< The currently active audio stream id of a playing file source */ ++ bool m_isValidAudioDSPSettings; /*!< if settings load was successfull it becomes true */ ++ AE_DSP_MODELIST m_modes[AE_DSP_MODE_TYPE_MAX]; /*!< list of currently used dsp processing calls */ ++ std::map m_addonNameIds; /*!< map add-on names to IDs */ ++ }; ++ //@} ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp +new file mode 100644 +index 0000000..bccc4d1 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp +@@ -0,0 +1,871 @@ ++/* ++ * Copyright (C) 2010-2015 Team Kodi ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Kodi; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include ++#include "Application.h" ++#include "ActiveAEDSPAddon.h" ++#include "ActiveAEDSP.h" ++#include "addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h" ++#include "commons/Exception.h" ++#include "settings/AdvancedSettings.h" ++#include "settings/Settings.h" ++#include "utils/log.h" ++#include "utils/StringUtils.h" ++ ++using namespace ADDON; ++using namespace ActiveAE; ++ ++#define DEFAULT_INFO_STRING_VALUE "unknown" ++ ++CActiveAEDSPAddon::CActiveAEDSPAddon(AddonProps props) : ++ CAddonDll(std::move(props)), ++ m_apiVersion("0.0.0") ++{ ++ ResetProperties(); ++} ++ ++CActiveAEDSPAddon::~CActiveAEDSPAddon(void) ++{ ++ Destroy(); ++ SAFE_DELETE(m_pInfo); ++} ++ ++void CActiveAEDSPAddon::OnDisabled() ++{ ++ CServiceBroker::GetADSP().UpdateAddons(); ++} ++ ++void CActiveAEDSPAddon::OnEnabled() ++{ ++ CServiceBroker::GetADSP().UpdateAddons(); ++} ++ ++AddonPtr CActiveAEDSPAddon::GetRunningInstance() const ++{ ++ if (CServiceBroker::GetADSP().IsActivated()) ++ { ++ AddonPtr adspAddon; ++ if (CServiceBroker::GetADSP().GetAudioDSPAddon(ID(), adspAddon)) ++ return adspAddon; ++ } ++ return CAddon::GetRunningInstance(); ++} ++ ++void CActiveAEDSPAddon::OnPreInstall() ++{ ++ CServiceBroker::GetADSP().UpdateAddons(); ++} ++ ++void CActiveAEDSPAddon::OnPostInstall(bool restart, bool update) ++{ ++ CServiceBroker::GetADSP().UpdateAddons(); ++} ++ ++void CActiveAEDSPAddon::OnPreUnInstall() ++{ ++ // stop the ADSP manager, so running ADSP add-ons are stopped and closed ++ CServiceBroker::GetADSP().Deactivate(); ++} ++ ++void CActiveAEDSPAddon::OnPostUnInstall() ++{ ++ CServiceBroker::GetADSP().UpdateAddons(); ++} ++ ++void CActiveAEDSPAddon::ResetProperties(int iClientId /* = AE_DSP_INVALID_ADDON_ID */) ++{ ++ /* initialise members */ ++ SAFE_DELETE(m_pInfo); ++ m_pInfo = new AE_DSP_PROPERTIES; ++ m_strUserPath = CSpecialProtocol::TranslatePath(Profile()); ++ m_pInfo->strUserPath = m_strUserPath.c_str(); ++ m_strAddonPath = CSpecialProtocol::TranslatePath(Path()); ++ m_pInfo->strAddonPath = m_strAddonPath.c_str(); ++ m_menuhooks.clear(); ++ m_bReadyToUse = false; ++ m_isInUse = false; ++ m_iClientId = iClientId; ++ m_strAudioDSPVersion = DEFAULT_INFO_STRING_VALUE; ++ m_strFriendlyName = DEFAULT_INFO_STRING_VALUE; ++ m_strAudioDSPName = DEFAULT_INFO_STRING_VALUE; ++ memset(&m_addonCapabilities, 0, sizeof(m_addonCapabilities)); ++ m_apiVersion = AddonVersion("0.0.0"); ++} ++ ++ADDON_STATUS CActiveAEDSPAddon::Create(int iClientId) ++{ ++ ADDON_STATUS status(ADDON_STATUS_UNKNOWN); ++ if (iClientId <= AE_DSP_INVALID_ADDON_ID) ++ return status; ++ ++ /* ensure that a previous instance is destroyed */ ++ Destroy(); ++ ++ /* reset all properties to defaults */ ++ ResetProperties(iClientId); ++ ++ /* initialise the add-on */ ++ bool bReadyToUse(false); ++ CLog::Log(LOGDEBUG, "ActiveAE DSP - %s - creating audio dsp add-on instance '%s'", __FUNCTION__, Name().c_str()); ++ try ++ { ++ if ((status = CAddonDll::Create()) == ADDON_STATUS_OK) ++ bReadyToUse = GetAddonProperties(); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ m_bReadyToUse = bReadyToUse; ++ ++ return status; ++} ++ ++bool CActiveAEDSPAddon::DllLoaded(void) const ++{ ++ try ++ { ++ return CAddonDll::DllLoaded(); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ } ++ ++ return false; ++} ++ ++void CActiveAEDSPAddon::Destroy(void) ++{ ++ /* reset 'ready to use' to false */ ++ if (!m_bReadyToUse) ++ return; ++ m_bReadyToUse = false; ++ ++ CLog::Log(LOGDEBUG, "ActiveAE DSP - %s - destroying audio dsp add-on '%s'", __FUNCTION__, GetFriendlyName().c_str()); ++ ++ /* destroy the add-on */ ++ try ++ { ++ CAddonDll::Destroy(); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ /* reset all properties to defaults */ ++ ResetProperties(); ++} ++ ++void CActiveAEDSPAddon::ReCreate(void) ++{ ++ int iClientID(m_iClientId); ++ Destroy(); ++ ++ /* recreate the instance */ ++ Create(iClientID); ++} ++ ++bool CActiveAEDSPAddon::ReadyToUse(void) const ++{ ++ return m_bReadyToUse; ++} ++ ++int CActiveAEDSPAddon::GetID(void) const ++{ ++ return m_iClientId; ++} ++ ++bool CActiveAEDSPAddon::IsInUse() const ++{ ++ return m_isInUse; ++}; ++ ++bool CActiveAEDSPAddon::IsCompatibleAPIVersion(const ADDON::AddonVersion &minVersion, const ADDON::AddonVersion &version) ++{ ++ AddonVersion myMinVersion = AddonVersion(KODI_AE_DSP_MIN_API_VERSION); ++ AddonVersion myVersion = AddonVersion(KODI_AE_DSP_API_VERSION); ++ return (version >= myMinVersion && minVersion <= myVersion); ++} ++ ++bool CActiveAEDSPAddon::IsCompatibleGUIAPIVersion(const ADDON::AddonVersion &minVersion, const ADDON::AddonVersion &version) ++{ ++ AddonVersion myMinVersion = AddonVersion(KODI_GUILIB_MIN_API_VERSION); ++ AddonVersion myVersion = AddonVersion(KODI_GUILIB_API_VERSION); ++ return (version >= myMinVersion && minVersion <= myVersion); ++} ++ ++bool CActiveAEDSPAddon::CheckAPIVersion(void) ++{ ++ /* check the API version */ ++ AddonVersion minVersion = AddonVersion(KODI_AE_DSP_MIN_API_VERSION); ++ try ++ { ++ m_apiVersion = AddonVersion(m_pStruct->GetAudioDSPAPIVersion()); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException("GetAudioDSPAPIVersion()"); ++ return false; ++ } ++ ++ if (!IsCompatibleAPIVersion(minVersion, m_apiVersion)) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - Add-on '%s' is using an incompatible API version. KODI minimum API version = '%s', add-on API version '%s'", Name().c_str(), minVersion.asString().c_str(), m_apiVersion.asString().c_str()); ++ return false; ++ } ++ ++ /* check the GUI API version */ ++ AddonVersion guiVersion = AddonVersion("0.0.0"); ++ minVersion = AddonVersion(KODI_GUILIB_MIN_API_VERSION); ++ try ++ { ++ guiVersion = AddonVersion(m_pStruct->GetGUIAPIVersion()); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException("GetGUIAPIVersion()"); ++ return false; ++ } ++ ++ if (!IsCompatibleGUIAPIVersion(minVersion, guiVersion)) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - Add-on '%s' is using an incompatible GUI API version. KODI minimum GUI API version = '%s', add-on GUI API version '%s'", Name().c_str(), minVersion.asString().c_str(), guiVersion.asString().c_str()); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool CActiveAEDSPAddon::GetAddonProperties(void) ++{ ++ std::string strDSPName, strFriendlyName, strAudioDSPVersion; ++ AE_DSP_ADDON_CAPABILITIES addonCapabilities; ++ ++ /* get the capabilities */ ++ try ++ { ++ memset(&addonCapabilities, 0, sizeof(addonCapabilities)); ++ AE_DSP_ERROR retVal = m_pStruct->GetAddonCapabilities(&addonCapabilities); ++ if (retVal != AE_DSP_ERROR_NO_ERROR) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - couldn't get the capabilities for add-on '%s'. Please contact the developer of this add-on: %s", GetFriendlyName().c_str(), Author().c_str()); ++ return false; ++ } ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException("GetAddonCapabilities()"); ++ return false; ++ } ++ ++ /* get the name of the dsp addon */ ++ try ++ { ++ strDSPName = m_pStruct->GetDSPName(); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException("GetDSPName()"); ++ return false; ++ } ++ ++ /* display name = backend name string */ ++ strFriendlyName = StringUtils::Format("%s", strDSPName.c_str()); ++ ++ /* backend version number */ ++ try ++ { ++ strAudioDSPVersion = m_pStruct->GetDSPVersion(); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException("GetDSPVersion()"); ++ return false; ++ } ++ ++ /* update the members */ ++ m_strAudioDSPName = strDSPName; ++ m_strFriendlyName = strFriendlyName; ++ m_strAudioDSPVersion = strAudioDSPVersion; ++ m_addonCapabilities = addonCapabilities; ++ ++ return true; ++} ++ ++AE_DSP_ADDON_CAPABILITIES CActiveAEDSPAddon::GetAddonCapabilities(void) const ++{ ++ AE_DSP_ADDON_CAPABILITIES addonCapabilities(m_addonCapabilities); ++ return addonCapabilities; ++} ++ ++const std::string &CActiveAEDSPAddon::GetAudioDSPName(void) const ++{ ++ return m_strAudioDSPName; ++} ++ ++const std::string &CActiveAEDSPAddon::GetAudioDSPVersion(void) const ++{ ++ return m_strAudioDSPVersion; ++} ++ ++const std::string &CActiveAEDSPAddon::GetFriendlyName(void) const ++{ ++ return m_strFriendlyName; ++} ++ ++bool CActiveAEDSPAddon::HaveMenuHooks(AE_DSP_MENUHOOK_CAT cat) const ++{ ++ if (m_bReadyToUse && !m_menuhooks.empty()) ++ { ++ for (unsigned int i = 0; i < m_menuhooks.size(); ++i) ++ { ++ if (m_menuhooks[i].category == cat || m_menuhooks[i].category == AE_DSP_MENUHOOK_ALL) ++ return true; ++ } ++ } ++ return false; ++} ++ ++AE_DSP_MENUHOOKS *CActiveAEDSPAddon::GetMenuHooks(void) ++{ ++ return &m_menuhooks; ++} ++ ++void CActiveAEDSPAddon::CallMenuHook(const AE_DSP_MENUHOOK &hook, AE_DSP_MENUHOOK_DATA &hookData) ++{ ++ if (!m_bReadyToUse || hookData.category == AE_DSP_MENUHOOK_UNKNOWN) ++ return; ++ ++ try ++ { ++ m_pStruct->MenuHook(hook, hookData); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++} ++ ++AE_DSP_ERROR CActiveAEDSPAddon::StreamCreate(const AE_DSP_SETTINGS *addonSettings, const AE_DSP_STREAM_PROPERTIES* pProperties, ADDON_HANDLE handle) ++{ ++ AE_DSP_ERROR retVal(AE_DSP_ERROR_UNKNOWN); ++ ++ try ++ { ++ retVal = m_pStruct->StreamCreate(addonSettings, pProperties, handle); ++ if (retVal == AE_DSP_ERROR_NO_ERROR) ++ m_isInUse = true; ++ LogError(retVal, __FUNCTION__); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return retVal; ++} ++ ++void CActiveAEDSPAddon::StreamDestroy(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ m_pStruct->StreamDestroy(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ m_isInUse = false; ++} ++ ++bool CActiveAEDSPAddon::StreamIsModeSupported(const ADDON_HANDLE handle, AE_DSP_MODE_TYPE type, unsigned int addon_mode_id, int unique_db_mode_id) ++{ ++ try ++ { ++ AE_DSP_ERROR retVal = m_pStruct->StreamIsModeSupported(handle, type, addon_mode_id, unique_db_mode_id); ++ if (retVal == AE_DSP_ERROR_NO_ERROR) ++ return true; ++ else if (retVal != AE_DSP_ERROR_IGNORE_ME) ++ LogError(retVal, __FUNCTION__); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return false; ++} ++ ++AE_DSP_ERROR CActiveAEDSPAddon::StreamInitialize(const ADDON_HANDLE handle, const AE_DSP_SETTINGS *addonSettings) ++{ ++ AE_DSP_ERROR retVal(AE_DSP_ERROR_UNKNOWN); ++ ++ try ++ { ++ retVal = m_pStruct->StreamInitialize(handle, addonSettings); ++ LogError(retVal, __FUNCTION__); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return retVal; ++} ++ ++bool CActiveAEDSPAddon::InputProcess(const ADDON_HANDLE handle, const float **array_in, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->InputProcess(handle, array_in, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++unsigned int CActiveAEDSPAddon::InputResampleProcessNeededSamplesize(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->InputResampleProcessNeededSamplesize(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++unsigned int CActiveAEDSPAddon::InputResampleProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->InputResampleProcess(handle, array_in, array_out, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++int CActiveAEDSPAddon::InputResampleSampleRate(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->InputResampleSampleRate(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return -1; ++} ++ ++float CActiveAEDSPAddon::InputResampleGetDelay(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->InputResampleGetDelay(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0.0f; ++} ++ ++unsigned int CActiveAEDSPAddon::PreProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id) ++{ ++ try ++ { ++ return m_pStruct->PreProcessNeededSamplesize(handle, mode_id); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++float CActiveAEDSPAddon::PreProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id) ++{ ++ try ++ { ++ return m_pStruct->PreProcessGetDelay(handle, mode_id); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0.0f; ++} ++ ++unsigned int CActiveAEDSPAddon::PreProcess(const ADDON_HANDLE handle, unsigned int mode_id, float **array_in, float **array_out, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->PostProcess(handle, mode_id, array_in, array_out, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++AE_DSP_ERROR CActiveAEDSPAddon::MasterProcessSetMode(const ADDON_HANDLE handle, AE_DSP_STREAMTYPE type, unsigned int mode_id, int unique_db_mode_id) ++{ ++ AE_DSP_ERROR retVal(AE_DSP_ERROR_UNKNOWN); ++ ++ try ++ { ++ retVal = m_pStruct->MasterProcessSetMode(handle, type, mode_id, unique_db_mode_id); ++ LogError(retVal, __FUNCTION__); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return retVal; ++} ++ ++unsigned int CActiveAEDSPAddon::MasterProcessNeededSamplesize(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->MasterProcessNeededSamplesize(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++float CActiveAEDSPAddon::MasterProcessGetDelay(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->MasterProcessGetDelay(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0.0f; ++} ++ ++int CActiveAEDSPAddon::MasterProcessGetOutChannels(const ADDON_HANDLE handle, unsigned long &out_channel_present_flags) ++{ ++ try ++ { ++ return m_pStruct->MasterProcessGetOutChannels(handle, out_channel_present_flags); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return -1; ++} ++ ++unsigned int CActiveAEDSPAddon::MasterProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->MasterProcess(handle, array_in, array_out, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++std::string CActiveAEDSPAddon::MasterProcessGetStreamInfoString(const ADDON_HANDLE handle) ++{ ++ std::string strReturn; ++ ++ if (!m_bReadyToUse) ++ return strReturn; ++ ++ try ++ { ++ strReturn = m_pStruct->MasterProcessGetStreamInfoString(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return strReturn; ++} ++ ++unsigned int CActiveAEDSPAddon::PostProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id) ++{ ++ try ++ { ++ return m_pStruct->PostProcessNeededSamplesize(handle, mode_id); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++float CActiveAEDSPAddon::PostProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id) ++{ ++ try ++ { ++ return m_pStruct->PostProcessGetDelay(handle, mode_id); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0.0f; ++} ++ ++unsigned int CActiveAEDSPAddon::PostProcess(const ADDON_HANDLE handle, unsigned int mode_id, float **array_in, float **array_out, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->PostProcess(handle, mode_id, array_in, array_out, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++unsigned int CActiveAEDSPAddon::OutputResampleProcessNeededSamplesize(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->OutputResampleProcessNeededSamplesize(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++unsigned int CActiveAEDSPAddon::OutputResampleProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples) ++{ ++ try ++ { ++ return m_pStruct->OutputResampleProcess(handle, array_in, array_out, samples); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0; ++} ++ ++int CActiveAEDSPAddon::OutputResampleSampleRate(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->OutputResampleSampleRate(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return -1; ++} ++ ++float CActiveAEDSPAddon::OutputResampleGetDelay(const ADDON_HANDLE handle) ++{ ++ try ++ { ++ return m_pStruct->OutputResampleGetDelay(handle); ++ } ++ XBMCCOMMONS_HANDLE_UNCHECKED ++ catch (...) ++ { ++ LogUnhandledException(__FUNCTION__); ++ Destroy(); ++ } ++ ++ return 0.0f; ++} ++ ++bool CActiveAEDSPAddon::SupportsInputInfoProcess(void) const ++{ ++ return m_addonCapabilities.bSupportsInputProcess; ++} ++ ++bool CActiveAEDSPAddon::SupportsInputResample(void) const ++{ ++ return m_addonCapabilities.bSupportsInputResample; ++} ++ ++bool CActiveAEDSPAddon::SupportsPreProcess(void) const ++{ ++ return m_addonCapabilities.bSupportsPreProcess; ++} ++ ++bool CActiveAEDSPAddon::SupportsMasterProcess(void) const ++{ ++ return m_addonCapabilities.bSupportsMasterProcess; ++} ++ ++bool CActiveAEDSPAddon::SupportsPostProcess(void) const ++{ ++ return m_addonCapabilities.bSupportsPostProcess; ++} ++ ++bool CActiveAEDSPAddon::SupportsOutputResample(void) const ++{ ++ return m_addonCapabilities.bSupportsOutputResample; ++} ++ ++const char *CActiveAEDSPAddon::ToString(const AE_DSP_ERROR error) ++{ ++ switch (error) ++ { ++ case AE_DSP_ERROR_NO_ERROR: ++ return "no error"; ++ case AE_DSP_ERROR_NOT_IMPLEMENTED: ++ return "not implemented"; ++ case AE_DSP_ERROR_REJECTED: ++ return "rejected by the backend"; ++ case AE_DSP_ERROR_INVALID_PARAMETERS: ++ return "invalid parameters for this method"; ++ case AE_DSP_ERROR_INVALID_SAMPLERATE: ++ return "invalid samplerate for this method"; ++ case AE_DSP_ERROR_INVALID_IN_CHANNELS: ++ return "invalid input channel layout for this method"; ++ case AE_DSP_ERROR_INVALID_OUT_CHANNELS: ++ return "invalid output channel layout for this method"; ++ case AE_DSP_ERROR_FAILED: ++ return "the command failed"; ++ case AE_DSP_ERROR_UNKNOWN: ++ default: ++ return "unknown error"; ++ } ++} ++ ++bool CActiveAEDSPAddon::LogError(const AE_DSP_ERROR error, const char *strMethod) const ++{ ++ if (error != AE_DSP_ERROR_NO_ERROR && error != AE_DSP_ERROR_IGNORE_ME) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon '%s' returned an error: %s", ++ strMethod, GetFriendlyName().c_str(), ToString(error)); ++ return false; ++ } ++ return true; ++} ++ ++void CActiveAEDSPAddon::LogUnhandledException(const char *strFunctionName) const ++{ ++ CLog::Log(LOGERROR, "ActiveAE DSP - Unhandled exception caught while trying to call '%s' on add-on '%s', becomes diabled. Please contact the developer of this add-on: %s", strFunctionName, GetFriendlyName().c_str(), Author().c_str()); ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h +new file mode 100644 +index 0000000..4210394 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h +@@ -0,0 +1,424 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "addons/Addon.h" ++#include "addons/AddonDll.h" ++#include "addons/DllAudioDSP.h" ++ ++namespace ActiveAE ++{ ++ class CActiveAEDSPAddon; ++ ++ typedef std::vector AE_DSP_MENUHOOKS; ++ typedef std::shared_ptr AE_DSP_ADDON; ++ ++ #define AE_DSP_INVALID_ADDON_ID (-1) ++ ++ /*! ++ * Interface from KODI to a Audio DSP add-on. ++ * ++ * Also translates KODI's C++ structures to the addon's C structures. ++ */ ++ class CActiveAEDSPAddon : public ADDON::CAddonDll ++ { ++ public: ++ explicit CActiveAEDSPAddon(ADDON::AddonProps props); ++ ~CActiveAEDSPAddon(void); ++ ++ virtual void OnDisabled(); ++ virtual void OnEnabled(); ++ virtual ADDON::AddonPtr GetRunningInstance() const; ++ virtual void OnPreInstall(); ++ virtual void OnPostInstall(bool restart, bool update); ++ virtual void OnPreUnInstall(); ++ virtual void OnPostUnInstall(); ++ ++ /** @name Audio DSP add-on methods */ ++ //@{ ++ /*! ++ * @brief Initialise the instance of this add-on. ++ * @param iClientId The ID of this add-on. ++ */ ++ ADDON_STATUS Create(int iClientId); ++ ++ /*! ++ * @return True when the dll for this add-on was loaded, false otherwise (e.g. unresolved symbols) ++ */ ++ bool DllLoaded(void) const; ++ ++ /*! ++ * @brief Destroy the instance of this add-on. ++ */ ++ void Destroy(void); ++ ++ /*! ++ * @brief Destroy and recreate this add-on. ++ */ ++ void ReCreate(void); ++ ++ /*! ++ * @return True if this instance is initialised, false otherwise. ++ */ ++ bool ReadyToUse(void) const; ++ ++ /*! ++ * @return The ID of this instance. ++ */ ++ int GetID(void) const; ++ ++ /*! ++ * @return The false if this addon is currently not used. ++ */ ++ virtual bool IsInUse() const; ++ //@} ++ ++ /** @name Audio DSP processing methods */ ++ //@{ ++ /*! ++ * @brief Query this add-on's capabilities. ++ * @return pCapabilities The add-on's capabilities. ++ */ ++ AE_DSP_ADDON_CAPABILITIES GetAddonCapabilities(void) const; ++ ++ /*! ++ * @return The name reported by the backend. ++ */ ++ const std::string &GetAudioDSPName(void) const; ++ ++ /*! ++ * @return The version string reported by the backend. ++ */ ++ const std::string &GetAudioDSPVersion(void) const; ++ ++ /*! ++ * @return A friendly name for this add-on that can be used in log messages. ++ */ ++ const std::string &GetFriendlyName(void) const; ++ ++ /*! ++ * @return True if this add-on has menu hooks, false otherwise. ++ */ ++ bool HaveMenuHooks(AE_DSP_MENUHOOK_CAT cat) const; ++ ++ /*! ++ * @return The menu hooks for this add-on. ++ */ ++ AE_DSP_MENUHOOKS *GetMenuHooks(void); ++ ++ /*! ++ * @brief Call one of the menu hooks of this addon. ++ * @param hook The hook to call. ++ * @param item The selected file item for which the hook was called. ++ */ ++ void CallMenuHook(const AE_DSP_MENUHOOK &hook, AE_DSP_MENUHOOK_DATA &hookData); ++ ++ /*! ++ * Set up Audio DSP with selected audio settings (use the basic present audio stream data format) ++ * Used to detect available addons for present stream, as example stereo surround upmix not needed on 5.1 audio stream ++ * @param addonSettings The add-on's audio settings. ++ * @param pProperties The properties of the currently playing stream. ++ * @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully and data can be performed. AE_DSP_ERROR_IGNORE_ME if format is not supported, but without fault. ++ */ ++ AE_DSP_ERROR StreamCreate(const AE_DSP_SETTINGS *addonSettings, const AE_DSP_STREAM_PROPERTIES* pProperties, ADDON_HANDLE handle); ++ ++ /*! ++ * Remove the selected id from currently used dsp processes ++ * @param id The stream id ++ */ ++ void StreamDestroy(const ADDON_HANDLE handle); ++ ++ /*! ++ * @brief Ask the addon about a requested processing mode that it is supported on the current ++ * stream. Is called about every addon mode after successed StreamCreate. ++ * @param id The stream id ++ * @param addon_mode_id The mode inside addon which must be performed on call. Id is set from addon by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * @param unique_mode_id The Mode unique id generated from dsp database. ++ * @return true if supported ++ */ ++ bool StreamIsModeSupported(const ADDON_HANDLE handle, AE_DSP_MODE_TYPE type, unsigned int addon_mode_id, int unique_db_mode_id); ++ ++ /*! ++ * Set up Audio DSP with selected audio settings (detected on data of first present audio packet) ++ * @param addonSettings The add-on's audio settings. ++ * @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully. ++ */ ++ AE_DSP_ERROR StreamInitialize(const ADDON_HANDLE handle, const AE_DSP_SETTINGS *addonSettings); ++ ++ /*! ++ * @brief DSP input processing ++ * Can be used to have unchanged stream.. ++ * All DSP add-ons allowed to-do this. ++ * @param id The stream id ++ * @param array_in Pointer to data memory ++ * @param samples Amount of samples inside array_in ++ * @return true if work was OK ++ * @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with GetAddonCapabilities ++ */ ++ bool InputProcess(const ADDON_HANDLE handle, const float **array_in, unsigned int samples); ++ ++ /*! ++ * If the add-on operate with buffered arrays and the output size can be higher as the input ++ * it becomes asked about needed size before any InputResampleProcess call. ++ * @param id The stream id ++ * @return The needed size of output array or 0 if no changes within it ++ */ ++ unsigned int InputResampleProcessNeededSamplesize(const ADDON_HANDLE handle); ++ ++ /*! ++ * @brief DSP re sample processing before master Here a high quality resample can be performed. ++ * Only one DSP add-on is allowed to-do this! ++ * @param id The stream id ++ * @param array_in Pointer to input data memory ++ * @param array_out Pointer to output data memory ++ * @param samples Amount of samples inside array_in ++ * @return Amount of samples processed ++ */ ++ unsigned int InputResampleProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples); ++ ++ /*! ++ * Returns the re-sampling generated new sample rate used before the master process ++ * @param id The stream id ++ * @return The new sample rate ++ */ ++ int InputResampleSampleRate(const ADDON_HANDLE handle); ++ ++ /*! ++ * Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @param id The stream id ++ * @return the delay in seconds ++ */ ++ float InputResampleGetDelay(const ADDON_HANDLE handle); ++ ++ /*! ++ * If the addon operate with buffered arrays and the output size can be higher as the input ++ * it becomes asked about needed size before any PreProcess call. ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @return The needed size of output array or 0 if no changes within it ++ */ ++ unsigned int PreProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id); ++ ++ /*! ++ * Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @return the delay in seconds ++ */ ++ float PreProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id); ++ ++ /*! ++ * @brief DSP preprocessing ++ * All DSP add-ons allowed to-do this. ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @param array_in Pointer to input data memory ++ * @param array_out Pointer to output data memory ++ * @param samples Amount of samples inside array_in ++ * @return Amount of samples processed ++ */ ++ unsigned int PreProcess(const ADDON_HANDLE handle, unsigned int mode_id, float **array_in, float **array_out, unsigned int samples); ++ ++ /*! ++ * @brief Set the active master process mode ++ * @param id The stream id ++ * @param type Requested stream type for the selected master mode ++ * @param mode_id The Mode identifier. ++ * @param unique_mode_id The Mode unique id generated from DSP database. ++ * @return AE_DSP_ERROR_NO_ERROR if the setup was successful ++ */ ++ AE_DSP_ERROR MasterProcessSetMode(const ADDON_HANDLE handle, AE_DSP_STREAMTYPE type, unsigned int mode_id, int unique_db_mode_id); ++ ++ /*! ++ * @brief If the add-on operate with buffered arrays and the output size can be higher as the input ++ * it becomes asked about needed size before any MasterProcess call. ++ * @param id The stream id ++ * @return The needed size of output array or 0 if no changes within it ++ */ ++ unsigned int MasterProcessNeededSamplesize(const ADDON_HANDLE handle); ++ ++ /*! ++ * @brief Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @param id The stream id ++ * @return the delay in seconds ++ */ ++ float MasterProcessGetDelay(const ADDON_HANDLE handle); ++ ++ /*! ++ * @brief Returns the from selected master mode performed channel alignment ++ * @param id The stream id ++ * @retval out_channel_present_flags the exact channel present flags after performed up-/downmix ++ * @return the amount channels ++ */ ++ int MasterProcessGetOutChannels(const ADDON_HANDLE handle, unsigned long &out_channel_present_flags); ++ ++ /*! ++ * @brief Master processing becomes performed with it ++ * Here a channel up-mix/down-mix for stereo surround sound can be performed ++ * Only one DSP add-on is allowed to-do this! ++ * @param id The stream id ++ * @param array_in Pointer to input data memory ++ * @param array_out Pointer to output data memory ++ * @param samples Amount of samples inside array_in ++ * @return Amount of samples processed ++ */ ++ unsigned int MasterProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples); ++ ++ /*! ++ * @brief Get a from addon generated information string ++ * @param id The stream id ++ * @return Info string ++ */ ++ std::string MasterProcessGetStreamInfoString(const ADDON_HANDLE handle); ++ ++ /*! ++ * If the add-on operate with buffered arrays and the output size can be higher as the input ++ * it becomes asked about needed size before any PostProcess call. ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @return The needed size of output array or 0 if no changes within it ++ */ ++ unsigned int PostProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id); ++ ++ /*! ++ * Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @return the delay in seconds ++ */ ++ float PostProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id); ++ ++ /*! ++ * @brief DSP post processing ++ * @param id The stream id ++ * @param mode_id The mode inside add-on which must be performed on call. Id is set from add-on by iModeNumber on AE_DSP_MODE structure during RegisterMode callback, ++ * and can be defined from add-on as a structure pointer or anything else what is needed to find it. ++ * @param array_in Pointer to input data memory ++ * @param array_out Pointer to output data memory ++ * @param samples Amount of samples inside array_in ++ * @return Amount of samples processed ++ */ ++ unsigned int PostProcess(const ADDON_HANDLE handle, unsigned int mode_id, float **array_in, float **array_out, unsigned int samples); ++ ++ /*! ++ * @brief If the add-on operate with buffered arrays and the output size can be higher as the input ++ * it becomes asked about needed size before any OutputResampleProcess call. ++ * @param id The stream id ++ * @return The needed size of output array or 0 if no changes within it ++ */ ++ unsigned int OutputResampleProcessNeededSamplesize(const ADDON_HANDLE handle); ++ ++ /*! ++ * @brief Re-sampling after master processing becomes performed with it if needed, only ++ * one add-on can perform it. ++ * @param id The stream id ++ * @param array_in Pointer to input data memory ++ * @param array_out Pointer to output data memory ++ * @param samples Amount of samples inside array_in ++ * @return Amount of samples processed ++ */ ++ unsigned int OutputResampleProcess(const ADDON_HANDLE handle, float **array_in, float **array_out, unsigned int samples); ++ ++ /*! ++ * Returns the re-sampling generated new sample rate used after the master process ++ * @param id The stream id ++ * @return The new sample rate ++ */ ++ int OutputResampleSampleRate(const ADDON_HANDLE handle); ++ ++ /*! ++ * Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @param id The stream id ++ * @return the delay in seconds ++ */ ++ float OutputResampleGetDelay(const ADDON_HANDLE handle); ++ ++ bool SupportsInputInfoProcess(void) const; ++ bool SupportsPreProcess(void) const; ++ bool SupportsInputResample(void) const; ++ bool SupportsMasterProcess(void) const; ++ bool SupportsPostProcess(void) const; ++ bool SupportsOutputResample(void) const; ++ ++ static const char *ToString(const AE_DSP_ERROR error); ++ ++ private: ++ /*! ++ * @brief Checks whether the provided API version is compatible with KODI ++ * @param minVersion The add-on's KODI_AE_DSP_MIN_API_VERSION version ++ * @param version The add-on's KODI_AE_DSP_API_VERSION version ++ * @return True when compatible, false otherwise ++ */ ++ static bool IsCompatibleAPIVersion(const ADDON::AddonVersion &minVersion, const ADDON::AddonVersion &version); ++ ++ /*! ++ * @brief Checks whether the provided GUI API version is compatible with KODI ++ * @param minVersion The add-on's KODI_GUILIB_MIN_API_VERSION version ++ * @param version The add-on's KODI_GUILIB_API_VERSION version ++ * @return True when compatible, false otherwise ++ */ ++ static bool IsCompatibleGUIAPIVersion(const ADDON::AddonVersion &minVersion, const ADDON::AddonVersion &version); ++ ++ /*! ++ * @brief Request the API version from the add-on, and check if it's compatible ++ * @return True when compatible, false otherwise. ++ */ ++ bool CheckAPIVersion(void); ++ ++ /*! ++ * @brief Resets all class members to their defaults. Called by the constructors. ++ */ ++ void ResetProperties(int iClientId = AE_DSP_INVALID_ADDON_ID); ++ ++ bool GetAddonProperties(void); ++ ++ bool LogError(const AE_DSP_ERROR error, const char *strMethod) const; ++ void LogUnhandledException(const char *strFunctionName) const; ++ ++ bool m_bReadyToUse; /*!< true if this add-on is connected to the audio DSP, false otherwise */ ++ bool m_isInUse; /*!< true if this add-on currentyl processing data */ ++ AE_DSP_MENUHOOKS m_menuhooks; /*!< the menu hooks for this add-on */ ++ int m_iClientId; /*!< database ID of the audio DSP */ ++ ++ /* cached data */ ++ std::string m_strAudioDSPName; /*!< the cached audio DSP version */ ++ std::string m_strAudioDSPVersion; /*!< the cached audio DSP version */ ++ std::string m_strFriendlyName; /*!< the cached friendly name */ ++ AE_DSP_ADDON_CAPABILITIES m_addonCapabilities; /*!< the cached add-on capabilities */ ++ ++ /* stored strings to make sure const char* members in AE_DSP_PROPERTIES stay valid */ ++ std::string m_strUserPath; /*!< @brief translated path to the user profile */ ++ std::string m_strAddonPath ; /*!< @brief translated path to this add-on */ ++ ++ CCriticalSection m_critSection; ++ ++ ADDON::AddonVersion m_apiVersion; ++ }; ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.cpp +new file mode 100644 +index 0000000..0ec4094 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.cpp +@@ -0,0 +1,545 @@ ++/* ++ * Copyright (C) 2012-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ActiveAEDSPDatabase.h" ++#include "ActiveAEDSP.h" ++ ++#include "URL.h" ++#include "dbwrappers/dataset.h" ++#include "settings/AdvancedSettings.h" ++#include "settings/MediaSettings.h" ++#include "utils/log.h" ++#include "utils/StringUtils.h" ++ ++using namespace dbiplus; ++using namespace ActiveAE; ++using namespace ADDON; ++ ++#define ADSPDB_DEBUGGING 0 ++ ++bool CActiveAEDSPDatabase::Open() ++{ ++ return CDatabase::Open(g_advancedSettings.m_databaseADSP); ++} ++ ++void CActiveAEDSPDatabase::CreateTables() ++{ ++ BeginTransaction(); ++ CLog::Log(LOGINFO, "Audio DSP - %s - creating tables", __FUNCTION__); ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - creating table 'addons'", __FUNCTION__); ++ m_pDS->exec( ++ "CREATE TABLE addons (" ++ "idAddon integer primary key, " ++ "sName varchar(64), " ++ "sUid varchar(32)" ++ ")" ++ ); ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - creating table 'modes'", __FUNCTION__); ++ m_pDS->exec( ++ "CREATE TABLE modes (" ++ "idMode integer primary key, " ++ "iType integer, " ++ "iPosition integer, " ++ "iStreamTypeFlags integer, " ++ "iBaseType integer, " ++ "bIsEnabled bool, " ++ "sOwnIconPath varchar(255), " ++ "sOverrideIconPath varchar(255), " ++ "iModeName integer, " ++ "iModeSetupName integer, " ++ "iModeHelp integer, " ++ "iModeDescription integer, " ++ "sAddonModeName varchar(64), " ++ "iAddonId integer, " ++ "iAddonModeNumber integer, " ++ "bHasSettings bool" ++ ")" ++ ); ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - create settings table", __FUNCTION__); ++ m_pDS->exec( ++ "CREATE TABLE settings (" ++ "id integer primary key, " ++ "strPath varchar(255), " ++ "strFileName varchar(255), " ++ "MasterStreamTypeSel integer, " ++ "MasterStreamType integer, " ++ "MasterBaseType integer, " ++ "MasterModeId integer" ++ ")" ++ ); ++ ++ // disable all Audio DSP add-on when started the first time ++ ADDON::VECADDONS addons; ++ if (CAddonMgr::GetInstance().GetAddons(addons, ADDON_ADSPDLL)) ++ { ++ for (IVECADDONS it = addons.begin(); it != addons.end(); ++it) ++ CAddonMgr::GetInstance().DisableAddon(it->get()->ID()); ++ } ++} ++ ++void CActiveAEDSPDatabase::CreateAnalytics() ++{ ++ CLog::Log(LOGINFO, "Audio DSP - %s - creating indices", __FUNCTION__); ++ m_pDS->exec("CREATE UNIQUE INDEX idx_mode_iAddonId_iAddonModeNumber on modes(iAddonId, iAddonModeNumber);"); ++ m_pDS->exec("CREATE UNIQUE INDEX ix_settings ON settings ( id )\n"); ++} ++ ++void CActiveAEDSPDatabase::UpdateTables(int iVersion) ++{ ++} ++ ++/********** Mode methods **********/ ++ ++bool CActiveAEDSPDatabase::ContainsModes(int modeType) ++{ ++ return !GetSingleValue(PrepareSQL("SELECT 1 FROM modes WHERE modes.iType='%i'", modeType)).empty(); ++} ++ ++bool CActiveAEDSPDatabase::DeleteModes(void) ++{ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting all modes from the database", __FUNCTION__); ++ return DeleteValues("modes"); ++} ++ ++bool CActiveAEDSPDatabase::DeleteModes(int modeType) ++{ ++ /* invalid addon Id */ ++ if (modeType <= 0) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - invalid mode type id: %i", __FUNCTION__, modeType); ++ return false; ++ } ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting all modes from type '%i' from the database", __FUNCTION__, modeType); ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("iType = %u", modeType)); ++ ++ return DeleteValues("modes", filter); ++} ++ ++bool CActiveAEDSPDatabase::DeleteAddonModes(int addonId) ++{ ++ /* invalid addon Id */ ++ if (addonId <= 0) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - invalid add-on id: %i", __FUNCTION__, addonId); ++ return false; ++ } ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting all modes from add-on '%i' from the database", __FUNCTION__, addonId); ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("iAddonId = %u", addonId)); ++ ++ return DeleteValues("modes", filter); ++} ++ ++bool CActiveAEDSPDatabase::DeleteMode(const CActiveAEDSPMode &mode) ++{ ++ /* invalid mode */ ++ if (mode.ModeID() <= 0) ++ return false; ++ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting mode '%s' from the database", __FUNCTION__, mode.AddonModeName().c_str()); ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("idMode = %u", mode.ModeID())); ++ ++ return DeleteValues("modes", filter); ++} ++ ++bool CActiveAEDSPDatabase::PersistModes(std::vector &modes, int modeType) ++{ ++ bool bReturn(true); ++ ++ for (unsigned int iModePtr = 0; iModePtr < modes.size(); ++iModePtr) ++ { ++ CActiveAEDSPModePtr member = modes.at(iModePtr); ++ if (!member->IsInternal() && (member->IsChanged() || member->IsNew())) ++ { ++ bReturn &= AddUpdateMode(*member); ++ } ++ } ++ ++ bReturn &= CommitInsertQueries(); ++ ++ return bReturn; ++} ++ ++bool CActiveAEDSPDatabase::UpdateMode(int modeType, bool active, int addonId, int addonModeNumber, int listNumber) ++{ ++ return ExecuteQuery(PrepareSQL("UPDATE modes SET iPosition=%i,bIsEnabled=%i WHERE modes.iAddonId=%i AND modes.iAddonModeNumber=%i AND modes.iType=%i", ++ listNumber, ++ (active ? 1 : 0), ++ addonId, ++ addonModeNumber, ++ modeType)); ++} ++ ++bool CActiveAEDSPDatabase::AddUpdateMode(CActiveAEDSPMode &mode) ++{ ++ bool bReturn(true); ++ ++ try ++ { ++ if (mode.IsInternal()) ++ return false; ++ ++ if (NULL == m_pDB.get()) return false; ++ if (NULL == m_pDS.get()) return false; ++ std::string strSQL = PrepareSQL("SELECT * FROM modes WHERE modes.iAddonId=%i AND modes.iAddonModeNumber=%i AND modes.iType=%i", mode.AddonID(), mode.AddonModeNumber(), mode.ModeType()); ++ ++ m_pDS->query( strSQL ); ++ if (m_pDS->num_rows() > 0) ++ { ++ /* get user selected settings */ ++ mode.m_iModeId = m_pDS->fv("idMode").get_asInt(); ++ mode.m_iModePosition = m_pDS->fv("iPosition").get_asInt(); ++ mode.m_iBaseType = (AE_DSP_BASETYPE)m_pDS->fv("iBaseType").get_asInt(); ++ mode.m_bIsEnabled = m_pDS->fv("bIsEnabled").get_asBool(); ++ m_pDS->close(); ++ ++ /* update addon related settings */ ++ strSQL = PrepareSQL( ++ "UPDATE modes set " ++ "iStreamTypeFlags=%i, " ++ "sOwnIconPath='%s', " ++ "sOverrideIconPath='%s', " ++ "iModeName=%i, " ++ "iModeSetupName=%i, " ++ "iModeHelp=%i, " ++ "iModeDescription=%i, " ++ "sAddonModeName='%s', " ++ "bHasSettings=%i " ++ "WHERE modes.iAddonId=%i AND modes.iAddonModeNumber=%i AND modes.iType=%i", ++ mode.StreamTypeFlags(), ++ mode.IconOwnModePath().c_str(), ++ mode.IconOverrideModePath().c_str(), ++ mode.ModeName(), ++ mode.ModeSetupName(), ++ mode.ModeHelp(), ++ mode.ModeDescription(), ++ mode.AddonModeName().c_str(), ++ (mode.HasSettingsDialog() ? 1 : 0), ++ mode.AddonID(), mode.AddonModeNumber(), mode.ModeType()); ++ bReturn = m_pDS->exec(strSQL); ++ } ++ else ++ { // add the items ++ m_pDS->close(); ++ strSQL = PrepareSQL( ++ "INSERT INTO modes (" ++ "iType, " ++ "iPosition, " ++ "iStreamTypeFlags, " ++ "iBaseType, " ++ "bIsEnabled, " ++ "sOwnIconPath, " ++ "sOverrideIconPath, " ++ "iModeName, " ++ "iModeSetupName, " ++ "iModeHelp, " ++ "iModeDescription, " ++ "sAddonModeName, " ++ "iAddonId, " ++ "iAddonModeNumber, " ++ "bHasSettings) " ++ "VALUES (%i, %i, %i, %i, %i, '%s', '%s', %i, %i, %i, %i, '%s', %i, %i, %i)", ++ mode.ModeType(), ++ mode.ModePosition(), ++ mode.StreamTypeFlags(), ++ mode.BaseType(), ++ (mode.IsEnabled() ? 1 : 0), ++ mode.IconOwnModePath().c_str(), ++ mode.IconOverrideModePath().c_str(), ++ mode.ModeName(), ++ mode.ModeSetupName(), ++ mode.ModeHelp(), ++ mode.ModeDescription(), ++ mode.AddonModeName().c_str(), ++ mode.AddonID(), ++ mode.AddonModeNumber(), ++ (mode.HasSettingsDialog() ? 1 : 0)); ++ bReturn = m_pDS->exec(strSQL); ++ } ++ } ++ catch (...) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - (Addon='%i', Mode='%i', Name: %s) failed", __FUNCTION__, mode.AddonID(), mode.AddonModeNumber(), mode.AddonModeName().c_str()); ++ } ++ return bReturn; ++} ++ ++int CActiveAEDSPDatabase::GetModeId(const CActiveAEDSPMode &mode) ++{ ++ std::string id = GetSingleValue(PrepareSQL("SELECT * from modes WHERE modes.iAddonId=%i and modes.iAddonModeNumber=%i and modes.iType=%i", mode.AddonID(), mode.AddonModeNumber(), mode.ModeType())); ++ if (id.empty()) ++ return -1; ++ return strtol(id.c_str(), NULL, 10); ++} ++ ++int CActiveAEDSPDatabase::GetModes(AE_DSP_MODELIST &results, int modeType) ++{ ++ int iReturn(0); ++ ++ std::string strQuery=PrepareSQL("SELECT * FROM modes WHERE modes.iType=%i ORDER BY iPosition", modeType); ++ ++ m_pDS->query( strQuery ); ++ if (m_pDS->num_rows() > 0) ++ { ++ try ++ { ++ while (!m_pDS->eof()) ++ { ++ CActiveAEDSPModePtr mode = CActiveAEDSPModePtr(new CActiveAEDSPMode()); ++ ++ mode->m_iModeId = m_pDS->fv("idMode").get_asInt(); ++ mode->m_iModeType = (AE_DSP_MODE_TYPE)m_pDS->fv("iType").get_asInt(); ++ mode->m_iModePosition = m_pDS->fv("iPosition").get_asInt(); ++ mode->m_iStreamTypeFlags = m_pDS->fv("iStreamTypeFlags").get_asInt(); ++ mode->m_iBaseType = (AE_DSP_BASETYPE)m_pDS->fv("iBaseType").get_asInt(); ++ mode->m_bIsEnabled = m_pDS->fv("bIsEnabled").get_asBool(); ++ mode->m_strOwnIconPath = m_pDS->fv("sOwnIconPath").get_asString(); ++ mode->m_strOverrideIconPath = m_pDS->fv("sOverrideIconPath").get_asString(); ++ mode->m_iModeName = m_pDS->fv("iModeName").get_asInt(); ++ mode->m_iModeSetupName = m_pDS->fv("iModeSetupName").get_asInt(); ++ mode->m_iModeHelp = m_pDS->fv("iModeHelp").get_asInt(); ++ mode->m_iModeDescription = m_pDS->fv("iModeDescription").get_asInt(); ++ mode->m_strModeName = m_pDS->fv("sAddonModeName").get_asString(); ++ mode->m_iAddonId = m_pDS->fv("iAddonId").get_asInt(); ++ mode->m_iAddonModeNumber = m_pDS->fv("iAddonModeNumber").get_asInt(); ++ mode->m_bHasSettingsDialog = m_pDS->fv("bHasSettings").get_asBool(); ++ ++#ifdef ADSPDB_DEBUGGING ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - mode '%s' loaded from the database", __FUNCTION__, mode->m_strModeName.c_str()); ++#endif ++ AE_DSP_ADDON addon; ++ if (CServiceBroker::GetADSP().GetAudioDSPAddon(mode->m_iAddonId, addon)) ++ results.push_back(AE_DSP_MODEPAIR(mode, addon)); ++ ++ m_pDS->next(); ++ ++iReturn; ++ } ++ m_pDS->close(); ++ } ++ catch (...) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - couldn't load modes from the database", __FUNCTION__); ++ } ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - query failed", __FUNCTION__); ++ } ++ ++ m_pDS->close(); ++ return iReturn; ++} ++ ++/********** Settings methods **********/ ++ ++bool CActiveAEDSPDatabase::DeleteActiveDSPSettings() ++{ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting all active dsp settings from the database", __FUNCTION__); ++ return DeleteValues("settings"); ++} ++ ++bool CActiveAEDSPDatabase::DeleteActiveDSPSettings(const CFileItem &item) ++{ ++ std::string strPath, strFileName; ++ URIUtils::Split(item.GetPath(), strPath, strFileName); ++ return ExecuteQuery(PrepareSQL("DELETE FROM settings WHERE settings.strPath='%s' and settings.strFileName='%s'", strPath.c_str() , strFileName.c_str())); ++} ++ ++bool CActiveAEDSPDatabase::GetActiveDSPSettings(const CFileItem &item, CAudioSettings &settings) ++{ ++ try ++ { ++ if (NULL == m_pDB.get()) return false; ++ if (NULL == m_pDS.get()) return false; ++ std::string strPath, strFileName; ++ URIUtils::Split(item.GetPath(), strPath, strFileName); ++ std::string strSQL=PrepareSQL("SELECT * FROM settings WHERE settings.strPath='%s' and settings.strFileName='%s'", strPath.c_str() , strFileName.c_str()); ++ ++ m_pDS->query( strSQL ); ++ if (m_pDS->num_rows() > 0) ++ { // get the audio dsp settings info ++ settings.m_MasterStreamTypeSel = m_pDS->fv("MasterStreamTypeSel").get_asInt(); ++ int type = m_pDS->fv("MasterStreamType").get_asInt(); ++ int base = m_pDS->fv("MasterBaseType").get_asInt(); ++ settings.m_MasterStreamType = type; ++ settings.m_MasterStreamBase = base; ++ settings.m_MasterModes[type][base] = m_pDS->fv("MasterModeId").get_asInt(); ++ ++ /*! if auto mode is selected, copy the identifier of previous used processor to the auto mode entry */ ++ settings.m_MasterModes[settings.m_MasterStreamTypeSel][base] = settings.m_MasterModes[type][base]; ++ ++ m_pDS->close(); ++ return true; ++ } ++ m_pDS->close(); ++ } ++ catch (...) ++ { ++ CLog::Log(LOGERROR, "%s failed", __FUNCTION__); ++ } ++ return false; ++} ++ ++void CActiveAEDSPDatabase::SetActiveDSPSettings(const CFileItem &item, const CAudioSettings &setting) ++{ ++ try ++ { ++ if (NULL == m_pDB.get()) return ; ++ if (NULL == m_pDS.get()) return ; ++ std::string strPath, strFileName; ++ URIUtils::Split(item.GetPath(), strPath, strFileName); ++ std::string strSQL = StringUtils::Format("select * from settings WHERE settings.strPath='%s' and settings.strFileName='%s'", strPath.c_str() , strFileName.c_str()); ++ m_pDS->query( strSQL ); ++ if (m_pDS->num_rows() > 0) ++ { ++ m_pDS->close(); ++ // update the item ++ strSQL=PrepareSQL( ++ "update settings set " ++ "MasterStreamTypeSel=%i," ++ "MasterStreamType=%i," ++ "MasterBaseType=%i," ++ "MasterModeId=%i," ++ "WHERE settings.strPath='%s' and settings.strFileName='%s'\n", ++ setting.m_MasterStreamTypeSel, ++ setting.m_MasterStreamType, ++ setting.m_MasterStreamBase, ++ setting.m_MasterModes[setting.m_MasterStreamType][setting.m_MasterStreamBase], ++ strPath.c_str(), ++ strFileName.c_str()); ++ m_pDS->exec(strSQL); ++ return ; ++ } ++ else ++ { // add the items ++ m_pDS->close(); ++ strSQL= "INSERT INTO settings (" ++ "id, " ++ "strPath," ++ "strFileName," ++ "MasterStreamTypeSel," ++ "MasterStreamType," ++ "MasterBaseType," ++ "MasterModeId) " ++ "VALUES "; ++ strSQL += PrepareSQL("(NULL,'%s','%s',%i,%i,%i,%i)", ++ strPath.c_str(), ++ strFileName.c_str(), ++ setting.m_MasterStreamTypeSel, ++ setting.m_MasterStreamType, ++ setting.m_MasterStreamBase, ++ setting.m_MasterModes[setting.m_MasterStreamType][setting.m_MasterStreamBase]); ++ m_pDS->exec(strSQL); ++ } ++ } ++ catch (...) ++ { ++ CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, item.GetPath().c_str()); ++ } ++} ++ ++void CActiveAEDSPDatabase::EraseActiveDSPSettings() ++{ ++ CLog::Log(LOGINFO, "Deleting dsp settings information for all files"); ++ ExecuteQuery(PrepareSQL("DELETE from settings")); ++} ++ ++void CActiveAEDSPDatabase::SplitPath(const std::string& strFileNameAndPath, std::string& strPath, std::string& strFileName) ++{ ++ if (URIUtils::IsStack(strFileNameAndPath) || StringUtils::StartsWithNoCase(strFileNameAndPath, "rar://") || StringUtils::StartsWithNoCase(strFileNameAndPath, "zip://")) ++ { ++ URIUtils::GetParentPath(strFileNameAndPath,strPath); ++ strFileName = strFileNameAndPath; ++ } ++ else if (URIUtils::IsPlugin(strFileNameAndPath)) ++ { ++ CURL url(strFileNameAndPath); ++ strPath = url.GetWithoutFilename(); ++ strFileName = strFileNameAndPath; ++ } ++ else ++ URIUtils::Split(strFileNameAndPath,strPath, strFileName); ++} ++ ++/********** Audio DSP add-on methods **********/ ++ ++bool CActiveAEDSPDatabase::DeleteAddons() ++{ ++ CLog::Log(LOGDEBUG, "Audio DSP - %s - deleting all add-on's from the database", __FUNCTION__); ++ ++ return DeleteValues("addons"); ++} ++ ++bool CActiveAEDSPDatabase::Delete(const std::string &strAddonUid) ++{ ++ /* invalid addon uid */ ++ if (strAddonUid.empty()) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - invalid addon uid", __FUNCTION__); ++ return false; ++ } ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("sUid = '%s'", strAddonUid.c_str())); ++ ++ return DeleteValues("addons", filter); ++} ++ ++int CActiveAEDSPDatabase::GetAudioDSPAddonId(const std::string &strAddonUid) ++{ ++ std::string strWhereClause = PrepareSQL("sUid = '%s'", strAddonUid.c_str()); ++ std::string strValue = GetSingleValue("addons", "idAddon", strWhereClause); ++ ++ if (strValue.empty()) ++ return -1; ++ ++ return strtol(strValue.c_str(), NULL, 10); ++} ++ ++int CActiveAEDSPDatabase::Persist(const AddonPtr& addon) ++{ ++ int iReturn(-1); ++ ++ /* invalid addon uid or name */ ++ if (addon->Name().empty() || addon->ID().empty()) ++ { ++ CLog::Log(LOGERROR, "Audio DSP - %s - invalid add-on uid or name", __FUNCTION__); ++ return iReturn; ++ } ++ ++ std::string strQuery = PrepareSQL("REPLACE INTO addons (sName, sUid) VALUES ('%s', '%s');", ++ addon->Name().c_str(), addon->ID().c_str()); ++ ++ if (ExecuteQuery(strQuery)) ++ iReturn = (int) m_pDS->lastinsertid(); ++ ++ return iReturn; ++} ++ +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.h +new file mode 100644 +index 0000000..e2c9ecb +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.h +@@ -0,0 +1,216 @@ ++#pragma once ++/* ++ * Copyright (C) 2012-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ActiveAEDSPMode.h" ++ ++class CAudioSettings; ++ ++namespace ActiveAE ++{ ++ class CActiveAEDSPAddon; ++ class CActiveAEDSPProcess; ++ ++ /** The audio DSP database */ ++ ++ class CActiveAEDSPDatabase : public CDatabase ++ { ++ public: ++ /*! ++ * @brief Create a new instance of the audio DSP database. ++ */ ++ CActiveAEDSPDatabase(void) {}; ++ virtual ~CActiveAEDSPDatabase(void) {}; ++ ++ /*! ++ * @brief Open the database. ++ * @return True if it was opened successfully, false otherwise. ++ */ ++ virtual bool Open(); ++ ++ /*! ++ * @brief Get the minimal database version that is required to operate correctly. ++ * @return The minimal database version. ++ */ ++ virtual int GetMinVersion() const { return 1; }; ++ ++ /*! ++ * @brief Get the default sqlite database filename. ++ * @return The default filename. ++ */ ++ const char *GetBaseDBName() const { return "ADSP"; }; ++ ++ /*! @name mode methods */ ++ //@{ ++ /*! ++ * @brief Used to check for present mode types ++ * @param modeType The mode type identfier ++ * @return True if modes present of given type ++ */ ++ bool ContainsModes(int modeType); ++ ++ /*! ++ * @brief Remove all modes from the database. ++ * @return True if all modes were removed, false otherwise. ++ */ ++ bool DeleteModes(void); ++ ++ /*! ++ * @brief Remove all modes from the database of a type. ++ * @param modeType The mode type identfier of functions to delete. ++ * @return True if the modes were deleted, false otherwise. ++ */ ++ bool DeleteModes(int modeType); ++ ++ /*! ++ * @brief Remove all modes from a add-on from the database. ++ * @param addonId The add-on identifier to delete the modes for. ++ * @return True if the modes were deleted, false otherwise. ++ */ ++ bool DeleteAddonModes(int addonId); ++ ++ /*! ++ * @brief Remove a mode entry from the database ++ * @param mode The mode to remove. ++ * @return True if the mode was removed, false otherwise. ++ */ ++ bool DeleteMode(const CActiveAEDSPMode &mode); ++ ++ /*! ++ * @brief Add or update mode entries in the database ++ * @param modes The modes to persist. ++ * @param modeType If true, don't write immediately ++ * @return True when persisted or queued, false otherwise. ++ */ ++ bool PersistModes(std::vector &modes, int modeType); ++ ++ /*! ++ * @brief Update user selectable mode settings inside database ++ * @param modeType the mode type to get ++ * @param active true if the mode is enabled ++ * @param addonId the addon id of this mode ++ * @param addonModeNumber the from addon set mode number ++ * @param listNumber the list number on processing chain ++ * @return True if the modes were updated, false otherwise. ++ */ ++ bool UpdateMode(int modeType, bool active, int addonId, int addonModeNumber, int listNumber); ++ ++ /*! ++ * @brief Add or if present update mode inside database ++ * @param addon The add-on to check the modes for. ++ * @return True if the modes were updated or added, false otherwise. ++ */ ++ bool AddUpdateMode(CActiveAEDSPMode &mode); ++ ++ /*! ++ * @brief Get id of mode inside database ++ * @param mode The mode to check for inside the database ++ * @return The id or -1 if not found ++ */ ++ int GetModeId(const CActiveAEDSPMode &mode); ++ ++ /*! ++ * @brief Get the list of modes from type on database ++ * @param results The mode group to store the results in. ++ * @param modeType the mode type to get ++ * @return The amount of modes that were added. ++ */ ++ int GetModes(AE_DSP_MODELIST &results, int modeType); ++ //@} ++ ++ /*! @name Add-on methods */ ++ //@{ ++ /*! ++ * @brief Remove all add-on information from the database. ++ * @return True if all add-on's were removed successfully. ++ */ ++ bool DeleteAddons(); ++ ++ /*! ++ * @brief Remove a add-on from the database ++ * @param strAddonUid The unique ID of the add-on. ++ * @return True if the add-on was removed successfully, false otherwise. ++ */ ++ bool Delete(const std::string &strAddonUid); ++ ++ /*! ++ * @brief Get the database ID of a add-on. ++ * @param strAddonUid The unique ID of the add-on. ++ * @return The database ID of the add-on or -1 if it wasn't found. ++ */ ++ int GetAudioDSPAddonId(const std::string &strAddonUid); ++ ++ /*! ++ * @brief Add a add-on to the database if it's not already in there. ++ * @param addon The pointer to the addon class ++ * @return The database ID of the client. ++ */ ++ int Persist(const ADDON::AddonPtr &addon); ++ //@} ++ ++ /*! @name Settings methods */ ++ //@{ ++ ++ /*! ++ * @brief Remove all active dsp settings from the database. ++ * @return True if all dsp data were removed successfully, false if not. ++ */ ++ bool DeleteActiveDSPSettings(); ++ ++ /*! ++ * @brief Remove active dsp settings from the database for file. ++ * @return True if dsp data were removed successfully, false if not. ++ */ ++ bool DeleteActiveDSPSettings(const CFileItem &item); ++ ++ /*! ++ * @brief GetVideoSettings() obtains any saved video settings for the current file. ++ * @return Returns true if the settings exist, false otherwise. ++ */ ++ bool GetActiveDSPSettings(const CFileItem &item, CAudioSettings &settings); ++ ++ /*! ++ * @brief Sets the settings for a particular used file ++ */ ++ void SetActiveDSPSettings(const CFileItem &item, const CAudioSettings &settings); ++ ++ /*! ++ * @brief EraseActiveDSPSettings() Erases the dsp Settings table and reconstructs it ++ */ ++ void EraseActiveDSPSettings(); ++ //@} ++ ++ private: ++ /*! ++ * @brief Create the audio DSP database tables. ++ */ ++ virtual void CreateTables(); ++ virtual void CreateAnalytics(); ++ ++ /*! ++ * @brief Update an old version of the database. ++ * @param version The version to update the database from. ++ */ ++ virtual void UpdateTables(int version); ++ virtual int GetSchemaVersion() const { return 0; } ++ ++ void SplitPath(const std::string& strFileNameAndPath, std::string& strPath, std::string& strFileName); ++ }; ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.cpp +new file mode 100644 +index 0000000..738e494 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.cpp +@@ -0,0 +1,430 @@ ++/* ++ * Copyright (C) 2010-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ActiveAEDSPMode.h" ++#include "ActiveAEDSPDatabase.h" ++#include "ActiveAEDSP.h" ++#include "utils/StringUtils.h" ++ ++using namespace ActiveAE; ++ ++bool CActiveAEDSPMode::operator==(const CActiveAEDSPMode &right) const ++{ ++ return (m_iModeId == right.m_iModeId && ++ m_iAddonId == right.m_iAddonId && ++ m_iAddonModeNumber == right.m_iAddonModeNumber && ++ m_iModeType == right.m_iModeType && ++ m_iModePosition == right.m_iModePosition); ++} ++ ++bool CActiveAEDSPMode::operator!=(const CActiveAEDSPMode &right) const ++{ ++ return !(*this == right); ++} ++ ++CActiveAEDSPMode::CActiveAEDSPMode() ++{ ++ m_iModeType = AE_DSP_MODE_TYPE_UNDEFINED; ++ m_iModeId = -1; ++ m_iModePosition = -1; ++ m_bIsEnabled = false; ++ m_strOwnIconPath = ""; ++ m_strOverrideIconPath = ""; ++ m_iStreamTypeFlags = 0; ++ m_iBaseType = AE_DSP_ABASE_INVALID; ++ m_iModeName = -1; ++ m_iModeSetupName = -1; ++ m_iModeDescription = -1; ++ m_iModeHelp = -1; ++ m_bChanged = false; ++ m_bIsInternal = false; ++ m_bHasSettingsDialog = false; ++ ++ m_fCPUUsage = 0.0f; ++ ++ m_iAddonId = -1; ++ m_iAddonModeNumber = -1; ++ m_strModeName = ""; ++} ++ ++CActiveAEDSPMode::CActiveAEDSPMode(int modeId, const AE_DSP_BASETYPE baseType) ++{ ++ m_iModeType = AE_DSP_MODE_TYPE_MASTER_PROCESS; ++ m_iModeId = modeId; ++ m_iModePosition = 0; ++ m_bIsEnabled = true; ++ m_strOwnIconPath = ""; ++ m_strOverrideIconPath = ""; ++ m_iStreamTypeFlags = AE_DSP_PRSNT_ASTREAM_BASIC | ++ AE_DSP_PRSNT_ASTREAM_MUSIC | ++ AE_DSP_PRSNT_ASTREAM_MOVIE/* | ++ AE_DSP_PRSNT_ASTREAM_GAME | ++ AE_DSP_PRSNT_ASTREAM_APP | ++ AE_DSP_PRSNT_ASTREAM_PHONE | ++ AE_DSP_PRSNT_ASTREAM_MESSAGE*/; ++ m_iBaseType = baseType; ++ ++ switch (modeId) ++ { ++ case AE_DSP_MASTER_MODE_ID_PASSOVER: ++ m_iModeName = 16039; ++ m_iModeDescription = -1; ++ m_iModeHelp = -1; ++ m_iModeSetupName = -1; ++ m_strModeName = "Passover"; ++ break; ++ case AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX: ++ m_iModeName = 252; ++ m_iModeDescription = 36364; ++ m_iModeHelp = -1; ++ m_iModeSetupName = -1; ++ m_strModeName = "Stereo Upmix"; ++ break; ++ default: ++ m_iModeName = 16039; ++ m_iModeDescription = -1; ++ m_iModeHelp = -1; ++ m_iModeSetupName = -1; ++ m_strModeName = "Unknown"; ++ break; ++ }; ++ ++ m_bChanged = false; ++ m_bIsInternal = true; ++ m_bHasSettingsDialog = false; ++ ++ m_fCPUUsage = 0.0f; ++ ++ m_iAddonId = -1; ++ m_iAddonModeNumber = -1; ++} ++ ++CActiveAEDSPMode::CActiveAEDSPMode(const AE_DSP_MODES::AE_DSP_MODE &mode, int iAddonId) ++{ ++ m_iModeType = mode.iModeType; ++ m_iModePosition = -1; ++ m_iModeId = mode.iUniqueDBModeId; ++ m_iAddonId = iAddonId; ++ m_iBaseType = AE_DSP_ABASE_INVALID; ++ m_bIsEnabled = m_iModeType == AE_DSP_MODE_TYPE_MASTER_PROCESS ? !mode.bIsDisabled : false; ++ m_strOwnIconPath = mode.strOwnModeImage; ++ m_strOverrideIconPath = mode.strOverrideModeImage; ++ m_iStreamTypeFlags = mode.iModeSupportTypeFlags; ++ m_iModeName = mode.iModeName; ++ m_iModeSetupName = mode.iModeSetupName; ++ m_iModeDescription = mode.iModeDescription; ++ m_iModeHelp = mode.iModeHelp; ++ m_iAddonModeNumber = mode.iModeNumber; ++ m_strModeName = mode.strModeName; ++ m_bHasSettingsDialog = mode.bHasSettingsDialog; ++ m_bChanged = false; ++ m_bIsInternal = false; ++ ++ m_fCPUUsage = 0.0f; ++ ++ if (m_strModeName.empty()) ++ m_strModeName = StringUtils::Format("%s %d", g_localizeStrings.Get(15023).c_str(), m_iModeId); ++} ++ ++CActiveAEDSPMode::CActiveAEDSPMode(const CActiveAEDSPMode &mode) ++{ ++ *this = mode; ++} ++ ++CActiveAEDSPMode &CActiveAEDSPMode::operator=(const CActiveAEDSPMode &mode) ++{ ++ m_iModeId = mode.m_iModeId; ++ m_iModeType = mode.m_iModeType; ++ m_iModePosition = mode.m_iModePosition; ++ m_bIsEnabled = mode.m_bIsEnabled; ++ m_strOwnIconPath = mode.m_strOwnIconPath; ++ m_strOverrideIconPath = mode.m_strOverrideIconPath; ++ m_iStreamTypeFlags = mode.m_iStreamTypeFlags; ++ m_iBaseType = mode.m_iBaseType; ++ m_iModeName = mode.m_iModeName; ++ m_iModeSetupName = mode.m_iModeSetupName; ++ m_iModeDescription = mode.m_iModeDescription; ++ m_iModeHelp = mode.m_iModeHelp; ++ m_iAddonId = mode.m_iAddonId; ++ m_iAddonModeNumber = mode.m_iAddonModeNumber; ++ m_strModeName = mode.m_strModeName; ++ m_bChanged = mode.m_bChanged; ++ m_bIsInternal = mode.m_bIsInternal; ++ m_bHasSettingsDialog = mode.m_bHasSettingsDialog; ++ m_fCPUUsage = mode.m_fCPUUsage; ++ ++ return *this; ++} ++ ++/********** General mode related functions **********/ ++ ++bool CActiveAEDSPMode::IsNew(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeId <= 0; ++} ++ ++bool CActiveAEDSPMode::IsChanged(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bChanged; ++} ++ ++ ++bool CActiveAEDSPMode::IsInternal(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bIsInternal; ++} ++ ++bool CActiveAEDSPMode::IsEnabled(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bIsEnabled; ++} ++ ++bool CActiveAEDSPMode::SetEnabled(bool bIsEnabled) ++{ ++ CSingleLock lock(m_critSection); ++ ++ if (m_bIsEnabled != bIsEnabled) ++ { ++ /* update the Enabled flag */ ++ m_bIsEnabled = bIsEnabled; ++ SetChanged(); ++ m_bChanged = true; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++int CActiveAEDSPMode::ModePosition(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModePosition; ++} ++ ++bool CActiveAEDSPMode::SetModePosition(int iModePosition) ++{ ++ CSingleLock lock(m_critSection); ++ if (m_iModePosition != iModePosition) ++ { ++ /* update the type */ ++ m_iModePosition = iModePosition; ++ SetChanged(); ++ m_bChanged = true; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++bool CActiveAEDSPMode::SupportStreamType(AE_DSP_STREAMTYPE streamType, unsigned int flags) ++{ ++ if (streamType == AE_DSP_ASTREAM_BASIC && (flags & AE_DSP_PRSNT_ASTREAM_BASIC)) return true; ++ else if (streamType == AE_DSP_ASTREAM_MUSIC && (flags & AE_DSP_PRSNT_ASTREAM_MUSIC)) return true; ++ else if (streamType == AE_DSP_ASTREAM_MOVIE && (flags & AE_DSP_PRSNT_ASTREAM_MOVIE)) return true; ++ else if (streamType == AE_DSP_ASTREAM_GAME && (flags & AE_DSP_PRSNT_ASTREAM_GAME)) return true; ++ else if (streamType == AE_DSP_ASTREAM_APP && (flags & AE_DSP_PRSNT_ASTREAM_APP)) return true; ++ else if (streamType == AE_DSP_ASTREAM_PHONE && (flags & AE_DSP_PRSNT_ASTREAM_PHONE)) return true; ++ else if (streamType == AE_DSP_ASTREAM_MESSAGE && (flags & AE_DSP_PRSNT_ASTREAM_MESSAGE)) return true; ++ return false; ++} ++ ++bool CActiveAEDSPMode::SupportStreamType(AE_DSP_STREAMTYPE streamType) const ++{ ++ return SupportStreamType(streamType, m_iStreamTypeFlags); ++} ++ ++/********** Mode user interface related data functions **********/ ++ ++int CActiveAEDSPMode::ModeName(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeName; ++} ++ ++int CActiveAEDSPMode::ModeSetupName(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeSetupName; ++} ++ ++int CActiveAEDSPMode::ModeDescription(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeDescription; ++} ++ ++int CActiveAEDSPMode::ModeHelp(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeHelp; ++} ++ ++const std::string &CActiveAEDSPMode::IconOwnModePath(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_strOwnIconPath; ++} ++ ++const std::string &CActiveAEDSPMode::IconOverrideModePath(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_strOverrideIconPath; ++} ++ ++ ++/********** Master mode type related functions **********/ ++ ++bool CActiveAEDSPMode::SetBaseType(AE_DSP_BASETYPE baseType) ++{ ++ CSingleLock lock(m_critSection); ++ if (m_iBaseType != baseType) ++ { ++ /* update the mode base */ ++ m_iBaseType = baseType; ++ SetChanged(); ++ m_bChanged = true; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++AE_DSP_BASETYPE CActiveAEDSPMode::BaseType(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iBaseType; ++} ++ ++ ++/********** Audio DSP database related functions **********/ ++ ++int CActiveAEDSPMode::ModeID(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeId; ++} ++ ++int CActiveAEDSPMode::AddUpdate(bool force) ++{ ++ if (!force) ++ { ++ // not changed ++ CSingleLock lock(m_critSection); ++ if (!m_bChanged && m_iModeId > 0) ++ return m_iModeId; ++ } ++ ++ CActiveAEDSPDatabase *database = CServiceBroker::GetADSP().GetADSPDatabase(); ++ if (!database || !database->IsOpen()) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - failed to open the database"); ++ return -1; ++ } ++ ++ database->AddUpdateMode(*this); ++ m_iModeId = database->GetModeId(*this); ++ ++ return m_iModeId; ++} ++ ++bool CActiveAEDSPMode::Delete(void) ++{ ++ CActiveAEDSPDatabase *database = CServiceBroker::GetADSP().GetADSPDatabase(); ++ if (!database || !database->IsOpen()) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - failed to open the database"); ++ return false; ++ } ++ ++ return database->DeleteMode(*this); ++} ++ ++bool CActiveAEDSPMode::IsKnown(void) const ++{ ++ CActiveAEDSPDatabase *database = CServiceBroker::GetADSP().GetADSPDatabase(); ++ if (!database || !database->IsOpen()) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - failed to open the database"); ++ return false; ++ } ++ ++ return database->GetModeId(*this) > 0; ++} ++ ++ ++/********** Dynamic processing related data methods **********/ ++ ++void CActiveAEDSPMode::SetCPUUsage(float percent) ++{ ++ CSingleLock lock(m_critSection); ++ m_fCPUUsage = percent; ++} ++ ++float CActiveAEDSPMode::CPUUsage(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_fCPUUsage; ++} ++ ++ ++/********** Fixed addon related Mode methods **********/ ++ ++int CActiveAEDSPMode::AddonID(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iAddonId; ++} ++ ++unsigned int CActiveAEDSPMode::AddonModeNumber(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iAddonModeNumber; ++} ++ ++AE_DSP_MODE_TYPE CActiveAEDSPMode::ModeType(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iModeType; ++} ++ ++const std::string &CActiveAEDSPMode::AddonModeName(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_strModeName; ++} ++ ++bool CActiveAEDSPMode::HasSettingsDialog(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bHasSettingsDialog; ++} ++ ++unsigned int CActiveAEDSPMode::StreamTypeFlags(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_iStreamTypeFlags; ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h +new file mode 100644 +index 0000000..a6ded93 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h +@@ -0,0 +1,325 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include ++ ++#include "ActiveAEDSPAddon.h" ++#include "threads/CriticalSection.h" ++#include "utils/Observer.h" ++ ++namespace ActiveAE ++{ ++ class CActiveAEDSPMode; ++ class CActiveAEDSPDatabase; ++ ++ typedef std::shared_ptr CActiveAEDSPModePtr; ++ typedef std::pair AE_DSP_MODEPAIR; ++ typedef std::vector AE_DSP_MODELIST; ++ ++ #define AE_DSP_MASTER_MODE_ID_INTERNAL_TYPES 0xFF00 ++ #define AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX (AE_DSP_MASTER_MODE_ID_INTERNAL_TYPES) /*!< Used to for internal stereo upmix over ffmpeg */ ++ #define AE_DSP_MASTER_MODE_ID_PASSOVER 0 /*!< Used to ignore master processing */ ++ #define AE_DSP_MASTER_MODE_ID_INVALID -1 ++ ++ /*! ++ * DSP Mode information class ++ */ ++ //@{ ++ class CActiveAEDSPMode : public Observable ++ { ++ public: ++ /*! @brief Create a new mode */ ++ CActiveAEDSPMode(); ++ ++ /*! ++ * @brief Create a KODI internal processing mode infomation class ++ * @param modeId internal processing mode identifier ++ * @param baseType the used base of this internal mode ++ * @note this creation is only used to get a internal bypass mode (no addon call process mode) ++ */ ++ CActiveAEDSPMode(int modeId, const AE_DSP_BASETYPE baseType); ++ ++ /*! ++ * @brief Create the class about from addon given values ++ * @param mode the from addon set identification structure ++ * @param iAddonId the addon identification of the given data ++ */ ++ CActiveAEDSPMode(const AE_DSP_MODES::AE_DSP_MODE &mode, int iAddonId); ++ ++ /*! ++ * @brief Create a new class about given class ++ * @param mode the parent mode to copy data from ++ */ ++ CActiveAEDSPMode(const CActiveAEDSPMode &mode); ++ ++ bool operator ==(const CActiveAEDSPMode &right) const; ++ bool operator !=(const CActiveAEDSPMode &right) const; ++ CActiveAEDSPMode &operator=(const CActiveAEDSPMode &mode); ++ ++ /*! @name General mode related functions ++ * @note changes are not written inside database and must be performed with AddUpdate call ++ */ ++ //@{ ++ /*! ++ * @brief Check this mode as known or new one ++ * @return true if this mode is new and not stored inside database ++ */ ++ bool IsNew(void) const; ++ ++ /*! ++ * @brief Check this mode about data changes ++ * @return true if anything becomes changed on the mode data ++ */ ++ bool IsChanged(void) const; ++ ++ /*! ++ * @brief Check this mode about source ++ * @return true if internal KODI mode ++ */ ++ bool IsInternal(void) const; ++ ++ /*! ++ * @brief Check this mode is enabled for usage ++ * @return true if enabled ++ */ ++ bool IsEnabled(void) const; ++ ++ /*! ++ * @brief Enable or disable the usage of this mode ++ * @param bIsEnabled true to enable ++ * @return true if set was successful ++ */ ++ bool SetEnabled(bool bIsEnabled); ++ ++ /*! ++ * @brief Get the mode process chain position inside his mode type ++ * @return the mode process position or -1 not set ++ */ ++ int ModePosition(void) const; ++ ++ /*! ++ * @brief Set the mode process chain position inside his mode type ++ * @param iModePosition the process chain position ++ * @return true if the position becomes set and a database update becomes required ++ */ ++ bool SetModePosition(int iModePosition); ++ ++ /*! ++ * @brief Ask about stream type to given flags ++ * @param streamType the type to ask ++ * @param flags the stream types flags to check in accordance with AE_DSP_ASTREAM_PRESENT ++ * @return true if the mode is set as enabled under the flags ++ */ ++ static bool SupportStreamType(AE_DSP_STREAMTYPE streamType, unsigned int flags); ++ ++ /*! ++ * @brief Ask this mode about stream type ++ * @param streamType the type to ask ++ * @return true if the mode is set as enabled of this mode ++ */ ++ bool SupportStreamType(AE_DSP_STREAMTYPE streamType) const; ++ //@} ++ ++ /*! @name Mode user interface related data functions ++ */ ++ //@{ ++ /*! ++ * @brief Get the mode name string identification code ++ * @return the identifier code on addon strings or -1 if unset ++ */ ++ int ModeName(void) const; ++ ++ /*! ++ * @brief Get the mode name string identification code used on setup entries ++ * @return the identifier code on addon strings or -1 if unset ++ */ ++ int ModeSetupName(void) const; ++ ++ /*! ++ * @brief Get the mode help string identification code used as help text on dsp manager helper dialog ++ * @return the identifier code on addon strings or -1 if unset ++ */ ++ int ModeHelp(void) const; ++ ++ /*! ++ * @brief Get the mode description string identification code used as small help text on dsp manager dialog ++ * @return the identifier code on addon strings or -1 if unset ++ */ ++ int ModeDescription(void) const; ++ ++ /*! ++ * @brief Get the path to a from addon set mode identification image ++ * @return the path to the image or empty if not present ++ */ ++ const std::string &IconOwnModePath(void) const; ++ ++ /*! ++ * @brief Get the path to a from addon set mode identification image to overirde the from KODI used one, e.g. Dolby Digital with Dolby Digital EX ++ * @return the path to the image or empty if not present ++ */ ++ const std::string &IconOverrideModePath(void) const; ++ //@} ++ ++ /*! @name Master mode type related functions ++ */ ++ //@{ ++ /*! ++ * @brief Get the used base type of this mode ++ * @return the base type ++ */ ++ AE_DSP_BASETYPE BaseType(void) const; ++ ++ /*! ++ * @brief Set the used base type of this mode ++ * @return baseType the base type to set ++ * @return true if the position becomes set and a database update becomes required ++ */ ++ bool SetBaseType(AE_DSP_BASETYPE baseType); ++ //@} ++ ++ /*! @name Audio DSP database related functions ++ */ ++ //@{ ++ /*! ++ * @brief Get the identifier of this mode used on database ++ * @return the mode identifier or -1 if unknown and not safed to database ++ */ ++ int ModeID(void) const; ++ ++ /*! ++ * @brief Add or update this mode to the audio DSP database ++ * @param force if it is false it write only to the database on uknown id or if a change was inside the mode ++ * @return the database identifier of this mode, or -1 if a error was occurred ++ */ ++ int AddUpdate(bool force = false); ++ ++ /*! ++ * @brief Delete this mode from the audio dsp database ++ * @return true if deletion was successful ++ */ ++ bool Delete(void); ++ ++ /*! ++ * @brief Ask database about this mode that it is alread known ++ * @return true if present inside database ++ */ ++ bool IsKnown(void) const; ++ //@} ++ ++ /*! @name Dynamic processing related functions ++ */ ++ //@{ ++ /*! ++ * @brief Get the cpu usage of this mode ++ * @return percent The percent value (0.0 - 100.0) ++ * @note only be usable if mode is active in process chain ++ */ ++ float CPUUsage(void) const; ++ ++ /*! ++ * @brief Set the cpu usage of this mode if active and in process list ++ * @param percent The percent value (0.0 - 100.0) ++ */ ++ void SetCPUUsage(float percent); ++ //@} ++ ++ /*! @name Fixed audio dsp add-on related mode functions ++ */ ++ //@{ ++ /*! ++ * @brief Get the addon identifier ++ * @return returns the inside addon database used identifier of this mode based addon ++ */ ++ int AddonID(void) const; ++ ++ /*! ++ * @brief Get the addon processing mode identifier ++ * @return returns the from addon itself set identifier of this mode ++ */ ++ unsigned int AddonModeNumber(void) const; ++ ++ /*! ++ * @brief The processing mode type identifier of this mode ++ * @return returns the mode type, it should be never AE_DSP_MODE_TYPE_UNDEFINED ++ */ ++ AE_DSP_MODE_TYPE ModeType(void) const; ++ ++ /*! ++ * @brief Get the addon mode name ++ * @return returns the from addon set name of this mode, used for log messages ++ */ ++ const std::string &AddonModeName(void) const; ++ ++ /*! ++ * @brief Have this mode settings dialogs ++ * @return returns true if one or more dialogs are available to this mode ++ * @note if it is true the addon menu hook database can be checked with the addon mode identifier ++ */ ++ bool HasSettingsDialog(void) const; ++ ++ /*! ++ * @brief Get the from addon mode supported stream type flags ++ * @return returns the flags in accordance with AE_DSP_ASTREAM_PRESENT ++ */ ++ unsigned int StreamTypeFlags(void) const; ++ //@} ++ ++ private: ++ friend class CActiveAEDSPDatabase; ++ ++ /*! @name KODI related mode data ++ */ ++ //@{ ++ AE_DSP_MODE_TYPE m_iModeType; /*!< the processing mode type */ ++ int m_iModePosition; /*!< the processing mode position */ ++ int m_iModeId; /*!< the identifier given to this mode by the DSP database */ ++ AE_DSP_BASETYPE m_iBaseType; /*!< The stream source coding format */ ++ bool m_bIsEnabled; /*!< true if this mode is enabled, false if not */ ++ std::string m_strOwnIconPath; /*!< the path to the icon for this mode */ ++ std::string m_strOverrideIconPath; /*!< the path to the icon for this mode */ ++ int m_iModeName; /*!< the name id for this mode used by KODI */ ++ int m_iModeSetupName; /*!< the name id for this mode inside settings used by KODI */ ++ int m_iModeDescription; /*!< the description id for this mode used by KODI */ ++ int m_iModeHelp; /*!< the help id for this mode used by KODI */ ++ bool m_bChanged; /*!< true if anything in this entry was changed that needs to be persisted */ ++ bool m_bIsInternal; /*!< true if this mode is an internal KODI mode */ ++ std::string m_strModeName; /*!< the log name of this mode on the Addon or inside KODI */ ++ //@} ++ ++ /*! @name Dynamic processing related data ++ */ ++ //@{ ++ float m_fCPUUsage; /*!< if mode is active the used cpu force in percent is set here */ ++ //@} ++ ++ /*! @name Audio dsp add-on related mode data ++ */ ++ //@{ ++ int m_iAddonId; /*!< the identifier of the Addon that serves this mode */ ++ unsigned int m_iAddonModeNumber; /*!< the mode number on the Addon */ ++ bool m_bHasSettingsDialog; /*!< the mode have a own settings dialog */ ++ unsigned int m_iStreamTypeFlags; /*!< The stream content type flags in accordance with AE_DSP_ASTREAM_PRESENT */ ++ //@} ++ ++ CCriticalSection m_critSection; ++ }; ++ //@} ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.cpp +new file mode 100644 +index 0000000..2ec15df +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.cpp +@@ -0,0 +1,1801 @@ ++/* ++ * Copyright (C) 2010-2015 Team Kodi ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with Kodi; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "ActiveAEDSPProcess.h" ++ ++#include ++ ++extern "C" { ++#include "libavutil/channel_layout.h" ++#include "libavutil/opt.h" ++} ++ ++#include "ActiveAEDSPMode.h" ++#include "Application.h" ++#include "cores/AudioEngine/AEResampleFactory.h" ++#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" ++#include "cores/AudioEngine/Utils/AEUtil.h" ++#include "cores/IPlayer.h" ++#include "settings/MediaSettings.h" ++#include "utils/TimeUtils.h" ++ ++using namespace ADDON; ++using namespace ActiveAE; ++ ++#define MIN_DSP_ARRAY_SIZE 4096 ++ ++CActiveAEDSPProcess::CActiveAEDSPProcess(AE_DSP_STREAM_ID streamId) ++ : m_streamId(streamId) ++{ ++ m_channelLayoutIn = 0; /* Undefined input channel layout */ ++ m_channelLayoutOut = 0; /* Undefined output channel layout */ ++ m_streamTypeUsed = AE_DSP_ASTREAM_INVALID; ++ m_NewStreamType = AE_DSP_ASTREAM_INVALID; ++ m_NewMasterMode = AE_DSP_MASTER_MODE_ID_INVALID; ++ m_forceInit = false; ++ m_resamplerDSPProcessor = NULL; ++ m_convertInput = NULL; ++ m_convertOutput = NULL; ++ m_iLastProcessTime = 0; ++ ++ /*! ++ * Create predefined process arrays on every supported channel for audio dsp's. ++ * All are set if used or not for safety reason and unsued ones can be used from ++ * dsp addons as buffer arrays. ++ * If a bigger size is neeeded it becomes reallocated during DSP processing. ++ */ ++ m_processArraySize = MIN_DSP_ARRAY_SIZE; ++ for (int i = 0; i < AE_DSP_CH_MAX; ++i) ++ { ++ m_processArray[0][i] = (float*)calloc(m_processArraySize, sizeof(float)); ++ m_processArray[1][i] = (float*)calloc(m_processArraySize, sizeof(float)); ++ } ++} ++ ++CActiveAEDSPProcess::~CActiveAEDSPProcess() ++{ ++ ResetStreamFunctionsSelection(); ++ ++ if (m_resamplerDSPProcessor) ++ { ++ delete m_resamplerDSPProcessor; ++ m_resamplerDSPProcessor = NULL; ++ } ++ ++ /* Clear the buffer arrays */ ++ for (int i = 0; i < AE_DSP_CH_MAX; ++i) ++ { ++ if(m_processArray[0][i]) ++ free(m_processArray[0][i]); ++ if(m_processArray[1][i]) ++ free(m_processArray[1][i]); ++ } ++ ++ swr_free(&m_convertInput); ++ swr_free(&m_convertOutput); ++} ++ ++void CActiveAEDSPProcess::ResetStreamFunctionsSelection() ++{ ++ m_NewMasterMode = AE_DSP_MASTER_MODE_ID_INVALID; ++ m_NewStreamType = AE_DSP_ASTREAM_INVALID; ++ m_addon_InputResample.Clear(); ++ m_addon_OutputResample.Clear(); ++ ++ m_addons_InputProc.clear(); ++ m_addons_PreProc.clear(); ++ m_addons_MasterProc.clear(); ++ m_addons_PostProc.clear(); ++ m_usedMap.clear(); ++} ++ ++bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, AEQuality quality, AE_DSP_STREAMTYPE iStreamType, ++ enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, int profile) ++{ ++ m_inputFormat = inputFormat; /*!< Input format of processed stream */ ++ m_outputFormat = outputFormat; /*!< Output format of required stream (set from ADSP system on startup, to have ffmpeg compatible format */ ++ m_outputSamplerate = m_inputFormat.m_sampleRate; /*!< If no resampler addon is present output samplerate is the same as input */ ++ m_outputFrames = m_inputFormat.m_frames; ++ m_streamQuality = quality; /*!< from KODI on settings selected resample quality, also passed to addons to support different quality */ ++ m_dataFormat = AE_FMT_FLOAT; /*!< the base stream format, hard set to float */ ++ m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; /*!< Reset the pointer for m_MasterModes about active master process, set here during mode selection */ ++ m_ffMpegMatrixEncoding = matrix_encoding; ++ m_ffMpegAudioServiceType= audio_service_type; ++ m_ffMpegProfile = profile; ++ ++ CSingleLock lock(m_restartSection); ++ ++ CLog::Log(LOGDEBUG, "ActiveAE DSP - %s - Audio DSP processing id %d created:", __FUNCTION__, m_streamId); ++ ++ m_convertInput = swr_alloc_set_opts(m_convertInput, ++ CAEUtil::GetAVChannelLayout(m_inputFormat.m_channelLayout), ++ AV_SAMPLE_FMT_FLTP, ++ m_inputFormat.m_sampleRate, ++ CAEUtil::GetAVChannelLayout(m_inputFormat.m_channelLayout), ++ CAEUtil::GetAVSampleFormat(m_inputFormat.m_dataFormat), ++ m_inputFormat.m_sampleRate, ++ 0, NULL); ++ if (m_convertInput == NULL) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - DSP input convert with data format '%s' not supported!", __FUNCTION__, CAEUtil::DataFormatToStr(inputFormat.m_dataFormat)); ++ return false; ++ } ++ ++ if (swr_init(m_convertInput) < 0) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - DSP input convert failed", __FUNCTION__); ++ return false; ++ } ++ ++ m_convertOutput = swr_alloc_set_opts(m_convertOutput, ++ CAEUtil::GetAVChannelLayout(m_outputFormat.m_channelLayout), ++ CAEUtil::GetAVSampleFormat(m_outputFormat.m_dataFormat), ++ m_outputFormat.m_sampleRate, ++ CAEUtil::GetAVChannelLayout(m_outputFormat.m_channelLayout), ++ AV_SAMPLE_FMT_FLTP, ++ m_outputFormat.m_sampleRate, ++ 0, NULL); ++ if (m_convertOutput == NULL) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - DSP output convert with data format '%s' not supported!", __FUNCTION__, CAEUtil::DataFormatToStr(outputFormat.m_dataFormat)); ++ return false; ++ } ++ ++ if (swr_init(m_convertOutput) < 0) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - DSP output convert failed", __FUNCTION__); ++ return false; ++ } ++ ++ ResetStreamFunctionsSelection(); ++ ++ CFileItem currentFile(g_application.CurrentFileItem()); ++ ++ m_streamTypeDetected = DetectStreamType(¤tFile); ++ ++ if (iStreamType == AE_DSP_ASTREAM_AUTO) ++ m_streamTypeUsed = m_streamTypeDetected; ++ else if (iStreamType >= AE_DSP_ASTREAM_BASIC || iStreamType < AE_DSP_ASTREAM_AUTO) ++ m_streamTypeUsed = iStreamType; ++ else ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - Unknown audio stream type, falling back to basic", __FUNCTION__); ++ m_streamTypeUsed = AE_DSP_ASTREAM_BASIC; ++ } ++ ++ /*! ++ * Set general stream information about the processed stream ++ */ ++ ++ if (g_application.m_pPlayer->GetAudioStreamCount() > 0) ++ { ++ int identifier = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_AudioStream; ++ if(identifier < 0) ++ identifier = g_application.m_pPlayer->GetAudioStream(); ++ if (identifier < 0) ++ identifier = 0; ++ ++ SPlayerAudioStreamInfo info; ++ g_application.m_pPlayer->GetAudioStreamInfo(identifier, info); ++ ++ m_addonStreamProperties.strName = info.name.c_str(); ++ m_addonStreamProperties.strLanguage = info.language.c_str(); ++ m_addonStreamProperties.strCodecId = info.audioCodecName.c_str(); ++ m_addonStreamProperties.iIdentifier = identifier; ++ m_addonStreamProperties.iSampleRate = info.samplerate; ++ m_addonStreamProperties.iChannels = info.channels; ++ } ++ else ++ { ++ m_addonStreamProperties.strName = "Unknown"; ++ m_addonStreamProperties.strLanguage = ""; ++ m_addonStreamProperties.strCodecId = ""; ++ m_addonStreamProperties.iIdentifier = m_streamId; ++ m_addonStreamProperties.iSampleRate = m_inputFormat.m_sampleRate; ++ m_addonStreamProperties.iChannels = m_inputFormat.m_channelLayout.Count(); ++ } ++ ++ m_addonStreamProperties.iStreamID = m_streamId; ++ m_addonStreamProperties.iStreamType = m_streamTypeUsed; ++ m_addonStreamProperties.iBaseType = GetBaseType(&m_addonStreamProperties); ++ ++ /*! ++ * Create the profile about additional stream related data, e.g. the different Dolby Digital stream flags ++ */ ++ CreateStreamProfile(); ++ ++ /*! ++ * Set exact input and output format settings ++ */ ++ m_addonSettings.iStreamID = m_streamId; ++ m_addonSettings.iStreamType = m_streamTypeUsed; ++ m_addonSettings.lInChannelPresentFlags = 0; /*!< Reset input channel present flags, becomes set on next steps */ ++ m_addonSettings.iInChannels = m_inputFormat.m_channelLayout.Count();/*!< The from stream given channel amount */ ++ m_addonSettings.iInFrames = m_inputFormat.m_frames; /*!< Input frames given */ ++ m_addonSettings.iInSamplerate = m_inputFormat.m_sampleRate; /*!< The basic input samplerate from stream source */ ++ m_addonSettings.iProcessFrames = m_inputFormat.m_frames; /*!< Default the same as input frames, if input resampler is present it becomes corrected */ ++ m_addonSettings.iProcessSamplerate = m_inputFormat.m_sampleRate; /*!< Default the same as input samplerate, if input resampler is present it becomes corrected */ ++ m_addonSettings.lOutChannelPresentFlags = 0; /*!< Reset output channel present flags, becomes set on next steps */ ++ m_addonSettings.iOutChannels = m_outputFormat.m_channelLayout.Count(); /*!< The for output required amount of channels */ ++ m_addonSettings.iOutFrames = m_outputFormat.m_frames; /*! Output frames requested */ ++ m_addonSettings.iOutSamplerate = m_outputFormat.m_sampleRate; /*!< The required sample rate for pass over resampling on ActiveAEResample */ ++ m_addonSettings.bStereoUpmix = upmix; /*! Stereo upmix value given from KODI settings */ ++ m_addonSettings.bInputResamplingActive = false; /*! Becomes true if input resampling is in use */ ++ m_addonSettings.iQualityLevel = m_streamQuality; /*! Requested stream processing quality, is optional and can be from addon ignored */ ++ ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_LFE)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FLOC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FROC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_SL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_SR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BLOC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; ++ if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BROC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; ++ ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_LFE)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FLOC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FROC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_SL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_SR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BLOC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; ++ if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BROC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; ++ ++ /*! ++ * Setup off mode, used if dsp master processing is set off, required to have data ++ * for stream information functions. ++ */ ++ sDSPProcessHandle internalMode; ++ internalMode.Clear(); ++ internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_PASSOVER; ++ internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); ++ internalMode.iLastTime = 0; ++ m_addons_MasterProc.push_back(internalMode); ++ m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; ++ ++ if (upmix && m_addonSettings.iInChannels <= 2) ++ { ++ internalMode.Clear(); ++ internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX; ++ internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); ++ internalMode.iLastTime = 0; ++ m_addons_MasterProc.push_back(internalMode); ++ } ++ ++ /*! ++ * Load all selected processing types, stored in a database and available from addons ++ */ ++ AE_DSP_ADDONMAP addonMap; ++ if (CServiceBroker::GetADSP().GetEnabledAudioDSPAddons(addonMap) > 0) ++ { ++ int foundInputResamplerId = -1; /*!< Used to prevent double call of StreamCreate if input stream resampling is together with outer processing types */ ++ ++ /*! ++ * First find input resample addon to become information about processing sample rate and ++ * load one allowed before master processing & final resample addon ++ */ ++ CLog::Log(LOGDEBUG, " ---- DSP input resample addon ---"); ++ const AE_DSP_MODELIST listInputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_INPUT_RESAMPLE); ++ if (listInputResample.empty()) ++ CLog::Log(LOGDEBUG, " | - no input resample addon present or enabled"); ++ for (unsigned int i = 0; i < listInputResample.size(); ++i) ++ { ++ /// For resample only one call is allowed. Use first one and ignore everything else. ++ CActiveAEDSPModePtr pMode = listInputResample[i].first; ++ AE_DSP_ADDON addon = listInputResample[i].second; ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsInputResample() && pMode->IsEnabled()) ++ { ++ ADDON_HANDLE_STRUCT handle; ++ AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); ++ if (err == AE_DSP_ERROR_NO_ERROR) ++ { ++ if (addon->StreamIsModeSupported(&handle, pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) ++ { ++ int processSamplerate = addon->InputResampleSampleRate(&handle); ++ if (processSamplerate == (int)m_inputFormat.m_sampleRate) ++ { ++ CLog::Log(LOGDEBUG, " | - input resample addon %s ignored, input sample rate %i the same as process rate", addon->GetFriendlyName().c_str(), m_inputFormat.m_sampleRate); ++ } ++ else if (processSamplerate > 0) ++ { ++ CLog::Log(LOGDEBUG, " | - %s with resampling from %i to %i", addon->GetAudioDSPName().c_str(), m_inputFormat.m_sampleRate, processSamplerate); ++ ++ m_outputSamplerate = processSamplerate; /*!< overwrite output sample rate with the new rate */ ++ m_outputFrames = (int) ceil((1.0 * processSamplerate) / m_addonSettings.iInSamplerate * m_addonSettings.iInFrames); ++ m_addonSettings.iProcessSamplerate = m_outputSamplerate; /*!< the processing sample rate required for all behind called processes */ ++ m_addonSettings.iProcessFrames = m_outputFrames; ++ m_addonSettings.bInputResamplingActive = true; ++ ++ m_addon_InputResample.iAddonModeNumber = pMode->AddonModeNumber(); ++ m_addon_InputResample.pMode = pMode; ++ m_addon_InputResample.pAddon = addon; ++ m_addon_InputResample.iLastTime = 0; ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); ++ } ++ ++ unsigned int id = addon->GetID(); ++ m_addon_Handles[id] = handle; ++ foundInputResamplerId = id; ++ m_usedMap.insert(std::make_pair(id, addon)); ++ } ++ } ++ else if (err != AE_DSP_ERROR_IGNORE_ME) ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); ++ break; ++ } ++ } ++ ++ /*! ++ * Now init all other dsp relavant addons ++ */ ++ for (AE_DSP_ADDONMAP_ITR itr = addonMap.begin(); itr != addonMap.end(); ++itr) ++ { ++ AE_DSP_ADDON addon = itr->second; ++ int id = addon->GetID(); ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && id != foundInputResamplerId) ++ { ++ ADDON_HANDLE_STRUCT handle; ++ AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); ++ if (err == AE_DSP_ERROR_NO_ERROR) ++ { ++ m_addon_Handles[id] = handle; ++ m_usedMap.insert(std::make_pair(id, addon)); ++ } ++ else if (err == AE_DSP_ERROR_IGNORE_ME) ++ continue; ++ else ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); ++ } ++ } ++ ++ for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) ++ { ++ AE_DSP_ADDON addon = itr->second; ++ if (addon->SupportsInputInfoProcess()) ++ { ++ sDSPProcessHandle modeHandle; ++ modeHandle.pAddon = addon; ++ modeHandle.handle = m_addon_Handles[addon->GetID()]; ++ m_addons_InputProc.push_back(modeHandle); ++ } ++ } ++ ++ /*! ++ * Load all required pre process dsp addon functions ++ */ ++ CLog::Log(LOGDEBUG, " ---- DSP active pre process modes ---"); ++ const AE_DSP_MODELIST listPreProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_PRE_PROCESS); ++ for (unsigned int i = 0; i < listPreProcess.size(); ++i) ++ { ++ CActiveAEDSPModePtr pMode = listPreProcess[i].first; ++ AE_DSP_ADDON addon = listPreProcess[i].second; ++ int id = addon->GetID(); ++ ++ if (m_usedMap.find(id) == m_usedMap.end()) ++ continue; ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPreProcess() && pMode->IsEnabled() && ++ addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) ++ { ++ CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); ++ ++ sDSPProcessHandle modeHandle; ++ modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); ++ modeHandle.pMode = pMode; ++ modeHandle.pAddon = addon; ++ modeHandle.iLastTime = 0; ++ modeHandle.handle = m_addon_Handles[id]; ++ m_addons_PreProc.push_back(modeHandle); ++ } ++ } ++ if (m_addons_PreProc.empty()) ++ CLog::Log(LOGDEBUG, " | - no pre processing addon's present or enabled"); ++ ++ /*! ++ * Load all available master modes from addons and put together with database ++ */ ++ CLog::Log(LOGDEBUG, " ---- DSP active master process modes ---"); ++ const AE_DSP_MODELIST listMasterProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_MASTER_PROCESS); ++ for (unsigned int i = 0; i < listMasterProcess.size(); ++i) ++ { ++ CActiveAEDSPModePtr pMode = listMasterProcess[i].first; ++ AE_DSP_ADDON addon = listMasterProcess[i].second; ++ int id = addon->GetID(); ++ ++ if (m_usedMap.find(id) == m_usedMap.end()) ++ continue; ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsMasterProcess() && pMode->IsEnabled() && ++ addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) ++ { ++ CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); ++ ++ sDSPProcessHandle modeHandle; ++ modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); ++ modeHandle.pMode = pMode; ++ modeHandle.pAddon = addon; ++ modeHandle.iLastTime = 0; ++ modeHandle.handle = m_addon_Handles[id]; ++ modeHandle.pMode->SetBaseType((AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType); ++ m_addons_MasterProc.push_back(modeHandle); ++ } ++ } ++ if (m_addons_MasterProc.empty()) ++ CLog::Log(LOGDEBUG, " | - no master processing addon's present or enabled"); ++ ++ /*! ++ * Get selected source for current input ++ */ ++ int modeID = CMediaSettings::GetInstance().GetCurrentAudioSettings().m_MasterModes[m_addonStreamProperties.iStreamType][m_addonStreamProperties.iBaseType]; ++ if (modeID == AE_DSP_MASTER_MODE_ID_INVALID) ++ modeID = AE_DSP_MASTER_MODE_ID_PASSOVER; ++ ++ for (unsigned int ptr = 0; ptr < m_addons_MasterProc.size(); ++ptr) ++ { ++ CActiveAEDSPModePtr mode = m_addons_MasterProc.at(ptr).pMode; ++ if (mode->ModeID() == modeID) ++ { ++ m_activeMode = (int)ptr; ++ CLog::Log(LOGDEBUG, " | -- %s (selected)", mode->AddonModeName().c_str()); ++ break; ++ } ++ } ++ ++ /*! ++ * Setup the one allowed master processing addon and inform about selected mode ++ */ ++ m_activeModeOutChannels = -1; ++ if (m_addons_MasterProc[m_activeMode].pAddon) ++ { ++ AE_DSP_ERROR err = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessSetMode(&m_addons_MasterProc[m_activeMode].handle, m_addonStreamProperties.iStreamType, m_addons_MasterProc[m_activeMode].pMode->AddonModeNumber(), m_addons_MasterProc[m_activeMode].pMode->ModeID()); ++ if (err != AE_DSP_ERROR_NO_ERROR) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon master mode selection failed on %s with Mode '%s' with %s", ++ __FUNCTION__, ++ m_addons_MasterProc[m_activeMode].pAddon->GetAudioDSPName().c_str(), ++ m_addons_MasterProc[m_activeMode].pMode->AddonModeName().c_str(), ++ CActiveAEDSPAddon::ToString(err)); ++ m_addons_MasterProc.erase(m_addons_MasterProc.begin()+m_activeMode); ++ m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; ++ } ++ else ++ m_activeModeOutChannels = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetOutChannels(&m_addons_MasterProc[m_activeMode].handle, m_activeModeOutChannelsPresent); ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, " | -- No master process selected!"); ++ } ++ ++ /*! ++ * Load all required post process dsp addon functions ++ */ ++ CLog::Log(LOGDEBUG, " ---- DSP active post process modes ---"); ++ const AE_DSP_MODELIST listPostProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_POST_PROCESS); ++ for (unsigned int i = 0; i < listPostProcess.size(); ++i) ++ { ++ CActiveAEDSPModePtr pMode = listPostProcess[i].first; ++ AE_DSP_ADDON addon = listPostProcess[i].second; ++ int id = addon->GetID(); ++ ++ if (m_usedMap.find(id) == m_usedMap.end()) ++ continue; ++ ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPostProcess() && pMode->IsEnabled() && ++ addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) ++ { ++ CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); ++ ++ sDSPProcessHandle modeHandle; ++ modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); ++ modeHandle.pMode = pMode; ++ modeHandle.pAddon = addon; ++ modeHandle.iLastTime = 0; ++ modeHandle.handle = m_addon_Handles[id]; ++ m_addons_PostProc.push_back(modeHandle); ++ } ++ } ++ if (m_addons_PostProc.empty()) ++ CLog::Log(LOGDEBUG, " | - no post processing addon's present or enabled"); ++ ++ /*! ++ * Load one allowed addon for resampling after final post processing ++ */ ++ CLog::Log(LOGDEBUG, " ---- DSP post resample addon ---"); ++ if (m_addonSettings.iProcessSamplerate != m_outputFormat.m_sampleRate) ++ { ++ const AE_DSP_MODELIST listOutputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); ++ if (listOutputResample.empty()) ++ CLog::Log(LOGDEBUG, " | - no final post resample addon present or enabled, becomes performed by KODI"); ++ for (unsigned int i = 0; i < listOutputResample.size(); ++i) ++ { ++ /// For resample only one call is allowed. Use first one and ignore everything else. ++ CActiveAEDSPModePtr pMode = listOutputResample[i].first; ++ AE_DSP_ADDON addon = listOutputResample[i].second; ++ int id = addon->GetID(); ++ ++ if (m_usedMap.find(id) != m_usedMap.end() && ++ !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsOutputResample() && pMode->IsEnabled() && ++ addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) ++ { ++ int outSamplerate = addon->OutputResampleSampleRate(&m_addon_Handles[id]); ++ if (outSamplerate > 0) ++ { ++ CLog::Log(LOGDEBUG, " | - %s with resampling to %i", addon->GetAudioDSPName().c_str(), outSamplerate); ++ ++ m_outputSamplerate = outSamplerate; ++ m_outputFrames = (int) ceil((1.0 * outSamplerate) / m_addonSettings.iProcessSamplerate * m_addonSettings.iProcessFrames); ++ ++ m_addon_OutputResample.iAddonModeNumber = pMode->AddonModeNumber(); ++ m_addon_OutputResample.pMode = pMode; ++ m_addon_OutputResample.pAddon = addon; ++ m_addon_OutputResample.iLastTime = 0; ++ m_addon_OutputResample.handle = m_addon_Handles[id]; ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - post resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); ++ } ++ break; ++ } ++ } ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, " | - no final resampling needed, process and final samplerate the same"); ++ } ++ } ++ ++ /*! ++ * Initialize fallback matrix mixer ++ */ ++ InitFFMpegDSPProcessor(); ++ ++ if (CLog::GetLogLevel() == LOGDEBUG) // Speed improve ++ { ++ CLog::Log(LOGDEBUG, " ---- Input stream ----"); ++ CLog::Log(LOGDEBUG, " | Identifier : %d", m_addonStreamProperties.iIdentifier); ++ CLog::Log(LOGDEBUG, " | Stream Type : %s", m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_BASIC ? "Basic" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_MUSIC ? "Music" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_MOVIE ? "Movie" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_GAME ? "Game" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_APP ? "App" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_PHONE ? "Phone" : ++ m_addonStreamProperties.iStreamType == AE_DSP_ASTREAM_MESSAGE ? "Message" : ++ "Unknown"); ++ CLog::Log(LOGDEBUG, " | Name : %s", m_addonStreamProperties.strName); ++ CLog::Log(LOGDEBUG, " | Language : %s", m_addonStreamProperties.strLanguage); ++ CLog::Log(LOGDEBUG, " | Codec : %s", m_addonStreamProperties.strCodecId); ++ CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_addonStreamProperties.iSampleRate); ++ CLog::Log(LOGDEBUG, " | Channels : %d", m_addonStreamProperties.iChannels); ++ CLog::Log(LOGDEBUG, " ---- Input format ----"); ++ CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_addonSettings.iInSamplerate); ++ CLog::Log(LOGDEBUG, " | Sample Format : %s", CAEUtil::DataFormatToStr(m_inputFormat.m_dataFormat)); ++ CLog::Log(LOGDEBUG, " | Channel Count : %d", m_inputFormat.m_channelLayout.Count()); ++ CLog::Log(LOGDEBUG, " | Channel Layout : %s", ((std::string)m_inputFormat.m_channelLayout).c_str()); ++ CLog::Log(LOGDEBUG, " | Frames : %d", m_addonSettings.iInFrames); ++ CLog::Log(LOGDEBUG, " ---- Process format ----"); ++ CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_addonSettings.iProcessSamplerate); ++ CLog::Log(LOGDEBUG, " | Sample Format : %s", "AE_FMT_FLOATP"); ++ CLog::Log(LOGDEBUG, " | Frames : %d", m_addonSettings.iProcessFrames); ++ CLog::Log(LOGDEBUG, " | Internal processing : %s", m_resamplerDSPProcessor ? "yes" : "no"); ++ CLog::Log(LOGDEBUG, " ---- Output format ----"); ++ CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_outputSamplerate); ++ CLog::Log(LOGDEBUG, " | Sample Format : %s", CAEUtil::DataFormatToStr(m_outputFormat.m_dataFormat)); ++ CLog::Log(LOGDEBUG, " | Channel Count : %d", m_outputFormat.m_channelLayout.Count()); ++ CLog::Log(LOGDEBUG, " | Channel Layout : %s", ((std::string)m_outputFormat.m_channelLayout).c_str()); ++ CLog::Log(LOGDEBUG, " | Frames : %d", m_outputFrames); ++ } ++ ++ m_forceInit = true; ++ return true; ++} ++ ++void CActiveAEDSPProcess::InitFFMpegDSPProcessor() ++{ ++ /*! ++ * If ffmpeg resampler is already present delete it first to create it from new ++ */ ++ if (m_resamplerDSPProcessor) ++ { ++ delete m_resamplerDSPProcessor; ++ m_resamplerDSPProcessor = NULL; ++ } ++ ++ /*! ++ * if the amount of input channels is higher as output and the active master mode gives more channels out or if it is not set of it ++ * a forced channel downmix becomes enabled. ++ */ ++ bool upmix = m_addonSettings.bStereoUpmix && m_addons_MasterProc[m_activeMode].pMode->ModeID() == AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX ? true : false; ++ if (upmix || (m_addonSettings.iInChannels > m_addonSettings.iOutChannels && (m_activeModeOutChannels <= 0 || m_activeModeOutChannels > m_addonSettings.iOutChannels))) ++ { ++ m_resamplerDSPProcessor = CAEResampleFactory::Create(); ++ if (!m_resamplerDSPProcessor->Init(CAEUtil::GetAVChannelLayout(m_outputFormat.m_channelLayout), ++ m_outputFormat.m_channelLayout.Count(), ++ m_addonSettings.iProcessSamplerate, ++ AV_SAMPLE_FMT_FLTP, sizeof(float) << 3, 0, ++ CAEUtil::GetAVChannelLayout(m_inputFormat.m_channelLayout), ++ m_inputFormat.m_channelLayout.Count(), ++ m_addonSettings.iProcessSamplerate, ++ AV_SAMPLE_FMT_FLTP, sizeof(float) << 3, 0, ++ upmix, ++ true, ++ NULL, ++ m_streamQuality, ++ true)) ++ { ++ delete m_resamplerDSPProcessor; ++ m_resamplerDSPProcessor = NULL; ++ ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - Initialize of channel mixer failed", __FUNCTION__); ++ } ++ } ++} ++ ++bool CActiveAEDSPProcess::CreateStreamProfile() ++{ ++ bool ret = true; ++ ++ switch (m_addonStreamProperties.iBaseType) ++ { ++ case AE_DSP_ABASE_AC3: ++ case AE_DSP_ABASE_EAC3: ++ { ++ unsigned int iProfile; ++ switch (m_ffMpegMatrixEncoding) ++ { ++ case AV_MATRIX_ENCODING_DOLBY: ++ iProfile = AE_DSP_PROFILE_DOLBY_SURROUND; ++ break; ++ case AV_MATRIX_ENCODING_DPLII: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLII; ++ break; ++ case AV_MATRIX_ENCODING_DPLIIX: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLIIX; ++ break; ++ case AV_MATRIX_ENCODING_DPLIIZ: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLIIZ; ++ break; ++ case AV_MATRIX_ENCODING_DOLBYEX: ++ iProfile = AE_DSP_PROFILE_DOLBY_EX; ++ break; ++ case AV_MATRIX_ENCODING_DOLBYHEADPHONE: ++ iProfile = AE_DSP_PROFILE_DOLBY_HEADPHONE; ++ break; ++ case AV_MATRIX_ENCODING_NONE: ++ default: ++ iProfile = AE_DSP_PROFILE_DOLBY_NONE; ++ break; ++ } ++ ++ unsigned int iServiceType; ++ switch (m_ffMpegAudioServiceType) ++ { ++ case AV_AUDIO_SERVICE_TYPE_EFFECTS: ++ iServiceType = AE_DSP_SERVICE_TYPE_EFFECTS; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED: ++ iServiceType = AE_DSP_SERVICE_TYPE_VISUALLY_IMPAIRED; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED: ++ iServiceType = AE_DSP_SERVICE_TYPE_HEARING_IMPAIRED; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_DIALOGUE: ++ iServiceType = AE_DSP_SERVICE_TYPE_DIALOGUE; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_COMMENTARY: ++ iServiceType = AE_DSP_SERVICE_TYPE_COMMENTARY; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_EMERGENCY: ++ iServiceType = AE_DSP_SERVICE_TYPE_EMERGENCY; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_VOICE_OVER: ++ iServiceType = AE_DSP_SERVICE_TYPE_VOICE_OVER; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_KARAOKE: ++ iServiceType = AE_DSP_SERVICE_TYPE_KARAOKE; ++ break; ++ case AV_AUDIO_SERVICE_TYPE_MAIN: ++ default: ++ iServiceType = AE_DSP_SERVICE_TYPE_MAIN; ++ break; ++ } ++ m_addonStreamProperties.Profile.ac3_eac3.iProfile = iProfile; ++ m_addonStreamProperties.Profile.ac3_eac3.iServiceType = iServiceType; ++ break; ++ } ++ case AE_DSP_ABASE_DTS: ++ case AE_DSP_ABASE_DTSHD_HRA: ++ case AE_DSP_ABASE_DTSHD_MA: ++ { ++ ++ unsigned int iProfile; ++ switch (m_ffMpegProfile) ++ { ++ case FF_PROFILE_DTS_ES: ++ iProfile = AE_DSP_PROFILE_DTS_ES; ++ break; ++ case FF_PROFILE_DTS_96_24: ++ iProfile = AE_DSP_PROFILE_DTS_96_24; ++ break; ++ case FF_PROFILE_DTS_HD_HRA: ++ iProfile = AE_DSP_PROFILE_DTS_HD_HRA; ++ break; ++ case FF_PROFILE_DTS_HD_MA: ++ iProfile = AE_DSP_PROFILE_DTS_HD_MA; ++ break; ++ case FF_PROFILE_DTS: ++ default: ++ iProfile = AE_DSP_PROFILE_DTS; ++ break; ++ } ++ ++ m_addonStreamProperties.Profile.dts_dtshd.iProfile = iProfile; ++ m_addonStreamProperties.Profile.dts_dtshd.bSurroundMatrix = m_ffMpegMatrixEncoding == AV_MATRIX_ENCODING_DOLBY ? true : false; ++ break; ++ } ++ case AE_DSP_ABASE_TRUEHD: ++ case AE_DSP_ABASE_MLP: ++ { ++ unsigned int iProfile; ++ switch (m_ffMpegMatrixEncoding) ++ { ++ case AV_MATRIX_ENCODING_DOLBY: ++ iProfile = AE_DSP_PROFILE_DOLBY_SURROUND; ++ break; ++ case AV_MATRIX_ENCODING_DPLII: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLII; ++ break; ++ case AV_MATRIX_ENCODING_DPLIIX: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLIIX; ++ break; ++ case AV_MATRIX_ENCODING_DPLIIZ: ++ iProfile = AE_DSP_PROFILE_DOLBY_PLIIZ; ++ break; ++ case AV_MATRIX_ENCODING_DOLBYEX: ++ iProfile = AE_DSP_PROFILE_DOLBY_EX; ++ break; ++ case AV_MATRIX_ENCODING_DOLBYHEADPHONE: ++ iProfile = AE_DSP_PROFILE_DOLBY_HEADPHONE; ++ break; ++ case AV_MATRIX_ENCODING_NONE: ++ default: ++ iProfile = AE_DSP_PROFILE_DOLBY_NONE; ++ break; ++ } ++ ++ m_addonStreamProperties.Profile.mlp_truehd.iProfile = iProfile; ++ break; ++ } ++ case AE_DSP_ABASE_FLAC: ++ break; ++ default: ++ ret = false; ++ break; ++ } ++ ++ return ret; ++} ++ ++void CActiveAEDSPProcess::Destroy() ++{ ++ CSingleLock lock(m_restartSection); ++ ++ if (!CServiceBroker::GetADSP().IsActivated()) ++ return; ++ ++ for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) ++ { ++ itr->second->StreamDestroy(&m_addon_Handles[itr->first]); ++ } ++ ++ ResetStreamFunctionsSelection(); ++} ++ ++void CActiveAEDSPProcess::ForceReinit() ++{ ++ CSingleLock lock(m_restartSection); ++ m_forceInit = true; ++} ++ ++AE_DSP_STREAMTYPE CActiveAEDSPProcess::DetectStreamType(const CFileItem *item) ++{ ++ AE_DSP_STREAMTYPE detected = AE_DSP_ASTREAM_BASIC; ++ if (item->HasMusicInfoTag()) ++ detected = AE_DSP_ASTREAM_MUSIC; ++ else if (item->HasVideoInfoTag() || g_application.m_pPlayer->HasVideo()) ++ detected = AE_DSP_ASTREAM_MOVIE; ++// else if (item->HasVideoInfoTag()) ++// detected = AE_DSP_ASTREAM_GAME; ++// else if (item->HasVideoInfoTag()) ++// detected = AE_DSP_ASTREAM_APP; ++// else if (item->HasVideoInfoTag()) ++// detected = AE_DSP_ASTREAM_MESSAGE; ++// else if (item->HasVideoInfoTag()) ++// detected = AE_DSP_ASTREAM_PHONE; ++ else ++ detected = AE_DSP_ASTREAM_BASIC; ++ ++ return detected; ++} ++ ++AE_DSP_STREAM_ID CActiveAEDSPProcess::GetStreamId() const ++{ ++ return m_streamId; ++} ++ ++unsigned int CActiveAEDSPProcess::GetInputChannels() ++{ ++ return m_inputFormat.m_channelLayout.Count(); ++} ++ ++std::string CActiveAEDSPProcess::GetInputChannelNames() ++{ ++ return m_inputFormat.m_channelLayout; ++} ++ ++unsigned int CActiveAEDSPProcess::GetInputSamplerate() ++{ ++ return m_inputFormat.m_sampleRate; ++} ++ ++unsigned int CActiveAEDSPProcess::GetProcessSamplerate() ++{ ++ return m_addonSettings.iProcessSamplerate; ++} ++ ++unsigned int CActiveAEDSPProcess::GetOutputChannels() ++{ ++ return m_outputFormat.m_channelLayout.Count(); ++} ++ ++std::string CActiveAEDSPProcess::GetOutputChannelNames() ++{ ++ return m_outputFormat.m_channelLayout; ++} ++ ++unsigned int CActiveAEDSPProcess::GetOutputSamplerate() ++{ ++ return m_outputSamplerate; ++} ++ ++unsigned int CActiveAEDSPProcess::GetOutputFrames() ++{ ++ return m_outputFrames; ++} ++ ++float CActiveAEDSPProcess::GetCPUUsage(void) const ++{ ++ return m_fLastProcessUsage; ++} ++ ++CAEChannelInfo CActiveAEDSPProcess::GetChannelLayout() ++{ ++ return m_outputFormat.m_channelLayout; ++} ++ ++AEDataFormat CActiveAEDSPProcess::GetDataFormat() ++{ ++ return m_dataFormat; ++} ++ ++AEAudioFormat CActiveAEDSPProcess::GetInputFormat() ++{ ++ return m_inputFormat; ++} ++ ++AE_DSP_STREAMTYPE CActiveAEDSPProcess::GetDetectedStreamType() ++{ ++ return m_streamTypeDetected; ++} ++ ++AE_DSP_STREAMTYPE CActiveAEDSPProcess::GetUsedStreamType() ++{ ++ return m_streamTypeUsed; ++} ++ ++AE_DSP_BASETYPE CActiveAEDSPProcess::GetBaseType(AE_DSP_STREAM_PROPERTIES *props) ++{ ++ if (!strcmp(props->strCodecId, "ac3")) ++ return AE_DSP_ABASE_AC3; ++ else if (!strcmp(props->strCodecId, "eac3")) ++ return AE_DSP_ABASE_EAC3; ++ else if (!strcmp(props->strCodecId, "dca") || !strcmp(props->strCodecId, "dts")) ++ return AE_DSP_ABASE_DTS; ++ else if (!strcmp(props->strCodecId, "dtshd_hra")) ++ return AE_DSP_ABASE_DTSHD_HRA; ++ else if (!strcmp(props->strCodecId, "dtshd_ma")) ++ return AE_DSP_ABASE_DTSHD_MA; ++ else if (!strcmp(props->strCodecId, "truehd")) ++ return AE_DSP_ABASE_TRUEHD; ++ else if (!strcmp(props->strCodecId, "mlp")) ++ return AE_DSP_ABASE_MLP; ++ else if (!strcmp(props->strCodecId, "flac")) ++ return AE_DSP_ABASE_FLAC; ++ else if (props->iChannels > 2) ++ return AE_DSP_ABASE_MULTICHANNEL; ++ else if (props->iChannels == 2) ++ return AE_DSP_ABASE_STEREO; ++ else ++ return AE_DSP_ABASE_MONO; ++} ++ ++AE_DSP_BASETYPE CActiveAEDSPProcess::GetUsedBaseType() ++{ ++ return GetBaseType(&m_addonStreamProperties); ++} ++ ++bool CActiveAEDSPProcess::GetMasterModeStreamInfoString(std::string &strInfo) ++{ ++ if (m_activeMode <= AE_DSP_MASTER_MODE_ID_PASSOVER) ++ { ++ strInfo = ""; ++ return true; ++ } ++ ++ if (m_activeMode < 0 || !m_addons_MasterProc[m_activeMode].pAddon) ++ return false; ++ ++ strInfo = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetStreamInfoString(&m_addons_MasterProc[m_activeMode].handle); ++ ++ return true; ++} ++ ++bool CActiveAEDSPProcess::GetMasterModeTypeInformation(AE_DSP_STREAMTYPE &streamTypeUsed, AE_DSP_BASETYPE &baseType, int &iModeID) ++{ ++ streamTypeUsed = (AE_DSP_STREAMTYPE)m_addonStreamProperties.iStreamType; ++ ++ if (m_activeMode < 0) ++ return false; ++ ++ baseType = m_addons_MasterProc[m_activeMode].pMode->BaseType(); ++ iModeID = m_addons_MasterProc[m_activeMode].pMode->ModeID(); ++ return true; ++} ++ ++const char *CActiveAEDSPProcess::GetStreamTypeName(AE_DSP_STREAMTYPE iStreamType) ++{ ++ return iStreamType == AE_DSP_ASTREAM_BASIC ? "Basic" : ++ iStreamType == AE_DSP_ASTREAM_MUSIC ? "Music" : ++ iStreamType == AE_DSP_ASTREAM_MOVIE ? "Movie" : ++ iStreamType == AE_DSP_ASTREAM_GAME ? "Game" : ++ iStreamType == AE_DSP_ASTREAM_APP ? "App" : ++ iStreamType == AE_DSP_ASTREAM_PHONE ? "Phone" : ++ iStreamType == AE_DSP_ASTREAM_MESSAGE ? "Message" : ++ iStreamType == AE_DSP_ASTREAM_AUTO ? "Automatic" : ++ "Unknown"; ++} ++ ++bool CActiveAEDSPProcess::MasterModeChange(int iModeID, AE_DSP_STREAMTYPE iStreamType) ++{ ++ bool bReturn = false; ++ bool bSwitchStreamType = iStreamType != AE_DSP_ASTREAM_INVALID; ++ ++ /* The Mode is already used and need not to set up again */ ++ if (m_addons_MasterProc[m_activeMode].pMode->ModeID() == iModeID && !bSwitchStreamType) ++ return true; ++ ++ CSingleLock lock(m_restartSection); ++ ++ CLog::Log(LOGDEBUG, "ActiveAE DSP - %s - Audio DSP processing id %d mode change:", __FUNCTION__, m_streamId); ++ if (bSwitchStreamType && m_streamTypeUsed != iStreamType) ++ { ++ AE_DSP_STREAMTYPE old = m_streamTypeUsed; ++ CLog::Log(LOGDEBUG, " ---- Input stream ----"); ++ if (iStreamType == AE_DSP_ASTREAM_AUTO) ++ m_streamTypeUsed = m_streamTypeDetected; ++ else if (iStreamType >= AE_DSP_ASTREAM_BASIC || iStreamType < AE_DSP_ASTREAM_AUTO) ++ m_streamTypeUsed = iStreamType; ++ else ++ { ++ CLog::Log(LOGWARNING, "ActiveAE DSP - %s - Unknown audio stream type, falling back to basic", __FUNCTION__); ++ m_streamTypeUsed = AE_DSP_ASTREAM_BASIC; ++ } ++ ++ CLog::Log(LOGDEBUG, " | Stream Type change : From '%s' to '%s'", GetStreamTypeName(old), GetStreamTypeName(m_streamTypeUsed)); ++ } ++ ++ /*! ++ * Set the new stream type to the addon settings and properties structures. ++ * If the addon want to use another stream type, it can be becomes written inside ++ * the m_addonStreamProperties.iStreamType. ++ */ ++ m_addonStreamProperties.iStreamType = m_streamTypeUsed; ++ m_addonSettings.iStreamType = m_streamTypeUsed; ++ m_activeModeOutChannels = -1; ++ ++ if (iModeID <= AE_DSP_MASTER_MODE_ID_PASSOVER) ++ { ++ CLog::Log(LOGINFO, "ActiveAE DSP - Switching master mode off"); ++ m_activeMode = 0; ++ bReturn = true; ++ } ++ else ++ { ++ CActiveAEDSPModePtr mode; ++ for (unsigned int ptr = 0; ptr < m_addons_MasterProc.size(); ++ptr) ++ { ++ mode = m_addons_MasterProc.at(ptr).pMode; ++ if (mode->ModeID() == iModeID && mode->IsEnabled()) ++ { ++ if (m_addons_MasterProc[ptr].pAddon) ++ { ++ AE_DSP_ERROR err = m_addons_MasterProc[ptr].pAddon->MasterProcessSetMode(&m_addons_MasterProc[ptr].handle, m_addonStreamProperties.iStreamType, mode->AddonModeNumber(), mode->ModeID()); ++ if (err != AE_DSP_ERROR_NO_ERROR) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon master mode selection failed on %s with Mode '%s' with %s", ++ __FUNCTION__, ++ m_addons_MasterProc[ptr].pAddon->GetAudioDSPName().c_str(), ++ mode->AddonModeName().c_str(), ++ CActiveAEDSPAddon::ToString(err)); ++ } ++ else ++ { ++ CLog::Log(LOGINFO, "ActiveAE DSP - Switching master mode to '%s' as '%s' on '%s'", ++ mode->AddonModeName().c_str(), ++ GetStreamTypeName((AE_DSP_STREAMTYPE)m_addonStreamProperties.iStreamType), ++ m_addons_MasterProc[ptr].pAddon->GetAudioDSPName().c_str()); ++ ++ m_activeMode = (int)ptr; ++ m_activeModeOutChannels = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetOutChannels(&m_addons_MasterProc[ptr].handle, m_activeModeOutChannelsPresent); ++ bReturn = true; ++ } ++ } ++ else if (mode->ModeID() >= AE_DSP_MASTER_MODE_ID_INTERNAL_TYPES) ++ { ++ CLog::Log(LOGINFO, "ActiveAE DSP - Switching master mode to internal '%s' as '%s'", ++ mode->AddonModeName().c_str(), ++ GetStreamTypeName((AE_DSP_STREAMTYPE)m_addonStreamProperties.iStreamType)); ++ ++ m_activeMode = (int)ptr; ++ m_activeModeOutChannels = -1; ++ bReturn = true; ++ } ++ break; ++ } ++ } ++ } ++ ++ /*! ++ * Initialize fallback matrix mixer ++ */ ++ InitFFMpegDSPProcessor(); ++ ++ return bReturn; ++} ++ ++void CActiveAEDSPProcess::ClearArray(float **array, unsigned int samples) ++{ ++ unsigned int presentFlag = 1; ++ for (int i = 0; i < AE_DSP_CH_MAX; ++i) ++ { ++ if (m_addonSettings.lOutChannelPresentFlags & presentFlag) ++ memset(array[i], 0, samples*sizeof(float)); ++ presentFlag <<= 1; ++ } ++} ++ ++bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) ++{ ++ CSingleLock lock(m_restartSection); ++ ++ bool needDSPAddonsReinit = m_forceInit; ++ uint64_t iTime = static_cast(XbmcThreads::SystemClockMillis()) * 10000; ++ int64_t hostFrequency = CurrentHostFrequency(); ++ unsigned int frames = in->pkt->nb_samples; ++ ++ /* Detect interleaved input stream channel positions if unknown or changed */ ++ if (m_channelLayoutIn != in->pkt->config.channel_layout) ++ { ++ m_channelLayoutIn = in->pkt->config.channel_layout; ++ ++ m_idx_in[AE_CH_FL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_LEFT); ++ m_idx_in[AE_CH_FR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_RIGHT); ++ m_idx_in[AE_CH_FC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_CENTER); ++ m_idx_in[AE_CH_LFE] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_LOW_FREQUENCY); ++ m_idx_in[AE_CH_BL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_BACK_LEFT); ++ m_idx_in[AE_CH_BR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_BACK_RIGHT); ++ m_idx_in[AE_CH_FLOC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_LEFT_OF_CENTER); ++ m_idx_in[AE_CH_FROC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_RIGHT_OF_CENTER); ++ m_idx_in[AE_CH_BC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_BACK_CENTER); ++ m_idx_in[AE_CH_SL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_SIDE_LEFT); ++ m_idx_in[AE_CH_SR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_SIDE_RIGHT); ++ m_idx_in[AE_CH_TC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_CENTER); ++ m_idx_in[AE_CH_TFL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_FRONT_LEFT); ++ m_idx_in[AE_CH_TFC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_FRONT_CENTER); ++ m_idx_in[AE_CH_TFR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_FRONT_RIGHT); ++ m_idx_in[AE_CH_TBL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_BACK_LEFT); ++ m_idx_in[AE_CH_TBC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_BACK_CENTER); ++ m_idx_in[AE_CH_TBR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_TOP_BACK_RIGHT); ++ m_idx_in[AE_CH_BLOC] = -1; // manually disable these channels because ffmpeg does not support them ++ m_idx_in[AE_CH_BROC] = -1; ++ ++ needDSPAddonsReinit = true; ++ } ++ ++ /* Detect also interleaved output stream channel positions if unknown or changed */ ++ if (m_channelLayoutOut != out->pkt->config.channel_layout) ++ { ++ m_channelLayoutOut = out->pkt->config.channel_layout; ++ ++ m_idx_out[AE_CH_FL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_LEFT); ++ m_idx_out[AE_CH_FR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_RIGHT); ++ m_idx_out[AE_CH_FC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_CENTER); ++ m_idx_out[AE_CH_LFE] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_LOW_FREQUENCY); ++ m_idx_out[AE_CH_BL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_BACK_LEFT); ++ m_idx_out[AE_CH_BR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_BACK_RIGHT); ++ m_idx_out[AE_CH_FLOC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_LEFT_OF_CENTER); ++ m_idx_out[AE_CH_FROC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_RIGHT_OF_CENTER); ++ m_idx_out[AE_CH_BC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_BACK_CENTER); ++ m_idx_out[AE_CH_SL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_SIDE_LEFT); ++ m_idx_out[AE_CH_SR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_SIDE_RIGHT); ++ m_idx_out[AE_CH_TC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_CENTER); ++ m_idx_out[AE_CH_TFL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_FRONT_LEFT); ++ m_idx_out[AE_CH_TFC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_FRONT_CENTER); ++ m_idx_out[AE_CH_TFR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_FRONT_RIGHT); ++ m_idx_out[AE_CH_TBL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_BACK_LEFT); ++ m_idx_out[AE_CH_TBC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_BACK_CENTER); ++ m_idx_out[AE_CH_TBR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_TOP_BACK_RIGHT); ++ m_idx_out[AE_CH_BLOC] = -1; // manually disable these channels because ffmpeg does not support them ++ m_idx_out[AE_CH_BROC] = -1; ++ ++ needDSPAddonsReinit = true; ++ } ++ ++ if (needDSPAddonsReinit) ++ { ++ m_addonSettings.lInChannelPresentFlags = 0; ++ if (m_idx_in[AE_CH_FL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; ++ if (m_idx_in[AE_CH_FR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; ++ if (m_idx_in[AE_CH_FC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; ++ if (m_idx_in[AE_CH_LFE] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; ++ if (m_idx_in[AE_CH_BL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; ++ if (m_idx_in[AE_CH_BR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; ++ if (m_idx_in[AE_CH_FLOC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; ++ if (m_idx_in[AE_CH_FROC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; ++ if (m_idx_in[AE_CH_BC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; ++ if (m_idx_in[AE_CH_SL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; ++ if (m_idx_in[AE_CH_SR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; ++ if (m_idx_in[AE_CH_TFL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; ++ if (m_idx_in[AE_CH_TFR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; ++ if (m_idx_in[AE_CH_TFC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; ++ if (m_idx_in[AE_CH_TC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; ++ if (m_idx_in[AE_CH_TBL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; ++ if (m_idx_in[AE_CH_TBR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; ++ if (m_idx_in[AE_CH_TBC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; ++ if (m_idx_in[AE_CH_TBR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; ++ if (m_idx_in[AE_CH_BLOC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; ++ if (m_idx_in[AE_CH_BROC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; ++ ++ m_addonSettings.lOutChannelPresentFlags = 0; ++ if (m_idx_out[AE_CH_FL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; ++ if (m_idx_out[AE_CH_FR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; ++ if (m_idx_out[AE_CH_FC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; ++ if (m_idx_out[AE_CH_LFE] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; ++ if (m_idx_out[AE_CH_BL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; ++ if (m_idx_out[AE_CH_BR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; ++ if (m_idx_out[AE_CH_FLOC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; ++ if (m_idx_out[AE_CH_FROC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; ++ if (m_idx_out[AE_CH_BC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; ++ if (m_idx_out[AE_CH_SL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; ++ if (m_idx_out[AE_CH_SR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; ++ if (m_idx_out[AE_CH_TFL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; ++ if (m_idx_out[AE_CH_TFR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; ++ if (m_idx_out[AE_CH_TFC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; ++ if (m_idx_out[AE_CH_TC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; ++ if (m_idx_out[AE_CH_TBL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; ++ if (m_idx_out[AE_CH_TBR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; ++ if (m_idx_out[AE_CH_TBC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; ++ if (m_idx_out[AE_CH_BLOC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; ++ if (m_idx_out[AE_CH_BROC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; ++ ++ m_addonSettings.iStreamID = m_streamId; ++ m_addonSettings.iInChannels = in->pkt->config.channels; ++ m_addonSettings.iOutChannels = out->pkt->config.channels; ++ m_addonSettings.iInSamplerate = in->pkt->config.sample_rate; ++ m_addonSettings.iProcessSamplerate = m_addon_InputResample.pAddon ? m_addon_InputResample.pAddon->InputResampleSampleRate(&m_addon_InputResample.handle) : m_addonSettings.iInSamplerate; ++ m_addonSettings.iOutSamplerate = m_addon_OutputResample.pAddon ? m_addon_OutputResample.pAddon->OutputResampleSampleRate(&m_addon_OutputResample.handle) : m_addonSettings.iProcessSamplerate; ++ ++ if (m_NewMasterMode >= 0) ++ { ++ MasterModeChange(m_NewMasterMode, m_NewStreamType); ++ m_NewMasterMode = AE_DSP_MASTER_MODE_ID_INVALID; ++ m_NewStreamType = AE_DSP_ASTREAM_INVALID; ++ } ++ ++ for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) ++ { ++ AE_DSP_ERROR err = itr->second->StreamInitialize(&m_addon_Handles[itr->first], &m_addonSettings); ++ if (err != AE_DSP_ERROR_NO_ERROR) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon initialize failed on %s with %s", __FUNCTION__, itr->second->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); ++ } ++ } ++ ++ RecheckProcessArray(frames); ++ ClearArray(m_processArray[0], m_processArraySize); ++ ClearArray(m_processArray[1], m_processArraySize); ++ ++ m_forceInit = false; ++ m_iLastProcessTime = static_cast(XbmcThreads::SystemClockMillis()) * 10000; ++ m_iLastProcessUsage = 0; ++ m_fLastProcessUsage = 0.0f; ++ ++ /** ++ * Setup ffmpeg convert array for input stream ++ */ ++ SetFFMpegDSPProcessorArray(m_ffMpegConvertArray, m_processArray[0], NULL); ++ } ++ ++ int64_t startTime; ++ float **lastOutArray = m_processArray[0]; ++ unsigned int togglePtr = 1; ++ ++ /** ++ * Convert to required planar float format inside dsp system ++ */ ++ if (swr_convert(m_convertInput, (uint8_t **)m_ffMpegConvertArray[0], m_processArraySize, (const uint8_t **)in->pkt->data , frames) < 0) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - input audio convert failed", __FUNCTION__); ++ return false; ++ } ++ ++ /**********************************************/ ++ /** DSP Processing Algorithms following here **/ ++ /**********************************************/ ++ ++ /** ++ * DSP input processing ++ * Can be used to have unchanged input stream.. ++ * All DSP addons allowed todo this. ++ */ ++ for (unsigned int i = 0; i < m_addons_InputProc.size(); ++i) ++ { ++ if (!m_addons_InputProc[i].pAddon->InputProcess(&m_addons_InputProc[i].handle, (const float **)lastOutArray, frames)) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - input process failed on addon No. %i", __FUNCTION__, i); ++ return false; ++ } ++ } ++ ++ /** ++ * DSP resample processing before master ++ * Here a high quality resample can be performed. ++ * Only one DSP addon is allowed todo this! ++ */ ++ if (m_addon_InputResample.pAddon) ++ { ++ startTime = CurrentHostCounter(); ++ ++ frames = m_addon_InputResample.pAddon->InputResampleProcess(&m_addon_InputResample.handle, lastOutArray, m_processArray[togglePtr], frames); ++ if (frames == 0) ++ return false; ++ ++ m_addon_InputResample.iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * DSP pre processing ++ * All DSP addons allowed todo this and order of it set on settings. ++ */ ++ for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) ++ { ++ startTime = CurrentHostCounter(); ++ ++ frames = m_addons_PreProc[i].pAddon->PreProcess(&m_addons_PreProc[i].handle, m_addons_PreProc[i].iAddonModeNumber, lastOutArray, m_processArray[togglePtr], frames); ++ if (frames == 0) ++ return false; ++ ++ m_addons_PreProc[i].iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * DSP master processing ++ * Here a channel upmix/downmix for stereo surround sound can be performed ++ * Only one DSP addon is allowed todo this! ++ */ ++ if (m_addons_MasterProc[m_activeMode].pAddon) ++ { ++ startTime = CurrentHostCounter(); ++ ++ frames = m_addons_MasterProc[m_activeMode].pAddon->MasterProcess(&m_addons_MasterProc[m_activeMode].handle, lastOutArray, m_processArray[togglePtr], frames); ++ if (frames == 0) ++ return false; ++ ++ m_addons_MasterProc[m_activeMode].iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * Perform fallback channel mixing if input channel alignment is different ++ * from output and not becomes processed by active master processing mode or ++ * perform ffmpeg related internal master processes. ++ */ ++ if (m_resamplerDSPProcessor) ++ { ++ startTime = CurrentHostCounter(); ++ ++ if (needDSPAddonsReinit) ++ SetFFMpegDSPProcessorArray(m_ffMpegProcessArray, lastOutArray, m_processArray[togglePtr]); ++ ++ frames = m_resamplerDSPProcessor->Resample((uint8_t**)m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_OUT], frames, (uint8_t**)m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_IN], frames, 1.0); ++ if (frames <= 0) ++ { ++ CLog::Log(LOGERROR, "CActiveAEResample::Resample - resample failed"); ++ return false; ++ } ++ ++ m_addons_MasterProc[m_activeMode].iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * DSP post processing ++ * On the post processing can be things performed with additional channel upmix like 6.1 to 7.1 ++ * or frequency/volume corrections, speaker distance handling, equalizer... . ++ * All DSP addons allowed todo this and order of it set on settings. ++ */ ++ for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) ++ { ++ startTime = CurrentHostCounter(); ++ ++ frames = m_addons_PostProc[i].pAddon->PostProcess(&m_addons_PostProc[i].handle, m_addons_PostProc[i].iAddonModeNumber, lastOutArray, m_processArray[togglePtr], frames); ++ if (frames == 0) ++ return false; ++ ++ m_addons_PostProc[i].iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * DSP resample processing behind master ++ * Here a high quality resample can be performed. ++ * Only one DSP addon is allowed todo this! ++ */ ++ if (m_addon_OutputResample.pAddon) ++ { ++ startTime = CurrentHostCounter(); ++ ++ frames = m_addon_OutputResample.pAddon->OutputResampleProcess(&m_addon_OutputResample.handle, lastOutArray, m_processArray[togglePtr], frames); ++ if (frames == 0) ++ return false; ++ ++ m_addon_OutputResample.iLastTime += 1000 * 10000 * (CurrentHostCounter() - startTime) / hostFrequency; ++ ++ lastOutArray = m_processArray[togglePtr]; ++ togglePtr ^= 1; ++ } ++ ++ /** ++ * Setup ffmpeg convert array for output stream, performed here to now last array ++ */ ++ if (needDSPAddonsReinit) ++ SetFFMpegDSPProcessorArray(m_ffMpegConvertArray, NULL, lastOutArray); ++ ++ /** ++ * Convert back to required output format ++ */ ++ if (swr_convert(m_convertOutput, (uint8_t **)out->pkt->data, m_processArraySize, (const uint8_t **)m_ffMpegConvertArray[1], frames) < 0) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - output audio convert failed", __FUNCTION__); ++ return false; ++ } ++ out->pkt->nb_samples = frames; ++ ++ /** ++ * Update cpu process percent usage values for modes and total (every second) ++ */ ++ if (iTime >= m_iLastProcessTime + 1000*10000) ++ CalculateCPUUsage(iTime); ++ ++ return true; ++} ++ ++bool CActiveAEDSPProcess::RecheckProcessArray(unsigned int inputFrames) ++{ ++ /* Check for big enough array */ ++ unsigned int framesNeeded; ++ unsigned int framesOut = m_processArraySize; ++ ++ if (inputFrames > framesOut) ++ framesOut = inputFrames; ++ ++ if (m_addon_InputResample.pAddon) ++ { ++ framesNeeded = m_addon_InputResample.pAddon->InputResampleProcessNeededSamplesize(&m_addon_InputResample.handle); ++ if (framesNeeded > framesOut) ++ framesOut = framesNeeded; ++ } ++ ++ for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) ++ { ++ framesNeeded = m_addons_PreProc[i].pAddon->PreProcessNeededSamplesize(&m_addons_PreProc[i].handle, m_addons_PreProc[i].iAddonModeNumber); ++ if (framesNeeded > framesOut) ++ framesOut = framesNeeded; ++ } ++ ++ if (m_addons_MasterProc[m_activeMode].pAddon) ++ { ++ framesNeeded = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessNeededSamplesize(&m_addons_MasterProc[m_activeMode].handle); ++ if (framesNeeded > framesOut) ++ framesOut = framesNeeded; ++ } ++ ++ for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) ++ { ++ framesNeeded = m_addons_PostProc[i].pAddon->PostProcessNeededSamplesize(&m_addons_PostProc[i].handle, m_addons_PostProc[i].iAddonModeNumber); ++ if (framesNeeded > framesOut) ++ framesOut = framesNeeded; ++ } ++ ++ if (m_addon_OutputResample.pAddon) ++ { ++ framesNeeded = m_addon_OutputResample.pAddon->OutputResampleProcessNeededSamplesize(&m_addon_OutputResample.handle); ++ if (framesNeeded > framesOut) ++ framesOut = framesNeeded; ++ } ++ ++ if (framesOut > m_processArraySize) ++ { ++ if (!ReallocProcessArray(framesOut)) ++ return false; ++ ++ m_processArraySize = framesOut; ++ } ++ return true; ++} ++ ++bool CActiveAEDSPProcess::ReallocProcessArray(unsigned int requestSize) ++{ ++ m_processArraySize = requestSize + MIN_DSP_ARRAY_SIZE / 10; ++ for (int i = 0; i < AE_DSP_CH_MAX; ++i) ++ { ++ m_processArray[0][i] = (float*)realloc(m_processArray[0][i], m_processArraySize*sizeof(float)); ++ m_processArray[1][i] = (float*)realloc(m_processArray[1][i], m_processArraySize*sizeof(float)); ++ if (m_processArray[0][i] == NULL || m_processArray[1][i] == NULL) ++ { ++ CLog::Log(LOGERROR, "ActiveAE DSP - %s - realloc of process data array failed", __FUNCTION__); ++ return false; ++ } ++ } ++ return true; ++} ++ ++// in this function the usage for each adsp-mode in percent is calculated ++void CActiveAEDSPProcess::CalculateCPUUsage(uint64_t iTime) ++{ ++ int64_t iUsage = CThread::GetCurrentThread()->GetAbsoluteUsage(); ++ ++ if (iTime != m_iLastProcessTime) ++ { ++ // calculate usage only if we don't divide by zero ++ if (m_iLastProcessUsage > 0 && m_iLastProcessTime > 0) ++ { ++ m_fLastProcessUsage = (float)(iUsage - m_iLastProcessUsage) / (float)(iTime - m_iLastProcessTime) * 100.0f; ++ } ++ ++ float dTFactor = 100.0f / (float)(iTime - m_iLastProcessTime); ++ ++ if(m_addon_InputResample.pMode) ++ { ++ m_addon_InputResample.pMode->SetCPUUsage((float)(m_addon_InputResample.iLastTime)*dTFactor); ++ m_addon_InputResample.iLastTime = 0; ++ } ++ ++ for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) ++ { ++ m_addons_PreProc[i].pMode->SetCPUUsage((float)(m_addons_PreProc[i].iLastTime)*dTFactor); ++ m_addons_PreProc[i].iLastTime = 0; ++ } ++ ++ if (m_addons_MasterProc[m_activeMode].pMode) ++ { ++ m_addons_MasterProc[m_activeMode].pMode->SetCPUUsage((float)(m_addons_MasterProc[m_activeMode].iLastTime)*dTFactor); ++ m_addons_MasterProc[m_activeMode].iLastTime = 0; ++ } ++ ++ for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) ++ { ++ m_addons_PostProc[i].pMode->SetCPUUsage((float)(m_addons_PostProc[i].iLastTime)*dTFactor); ++ m_addons_PostProc[i].iLastTime = 0; ++ } ++ ++ if (m_addon_OutputResample.pMode) ++ { ++ m_addon_OutputResample.pMode->SetCPUUsage((float)(m_addon_OutputResample.iLastTime)*dTFactor); ++ m_addon_OutputResample.iLastTime = 0; ++ } ++ } ++ ++ m_iLastProcessUsage = iUsage; ++ m_iLastProcessTime = iTime; ++} ++ ++void CActiveAEDSPProcess::SetFFMpegDSPProcessorArray(float *array_ffmpeg[2][AE_DSP_CH_MAX], float **array_in, float **array_out) ++{ ++ /*! ++ * Setup ffmpeg resampler channel setup, this way is not my favorite but it works to become ++ * the correct channel alignment on the given input and output signal. ++ * The problem is, the process array of ffmpeg is not fixed and for every selected channel setup ++ * the positions are different. For this case a translation from the fixed dsp stream format to ++ * ffmpeg format must be performed. It use a separate process array table which becomes set by ++ * already present channel memory storage. ++ */ ++ ++ //! Initialize input channel alignmment for ffmpeg process array ++ if (array_in) ++ { ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FL]] = array_in[AE_DSP_CH_FL]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FR]] = array_in[AE_DSP_CH_FR]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FC]] = array_in[AE_DSP_CH_FC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_LFE) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_LFE]] = array_in[AE_DSP_CH_LFE]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BL]] = array_in[AE_DSP_CH_BL]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BR]] = array_in[AE_DSP_CH_BR]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FLOC]] = array_in[AE_DSP_CH_FLOC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FROC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FROC]] = array_in[AE_DSP_CH_FROC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BC]] = array_in[AE_DSP_CH_BC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_SL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_SL]] = array_in[AE_DSP_CH_SL]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_SR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_SR]] = array_in[AE_DSP_CH_SR]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFL]] = array_in[AE_DSP_CH_TFL]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFR]] = array_in[AE_DSP_CH_TFR]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFC]] = array_in[AE_DSP_CH_TFC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TC]] = array_in[AE_DSP_CH_TC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBL]] = array_in[AE_DSP_CH_TBL]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBR]] = array_in[AE_DSP_CH_TBR]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBC]] = array_in[AE_DSP_CH_TBC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BLOC]] = array_in[AE_DSP_CH_BLOC]; ++ if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BROC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BROC]] = array_in[AE_DSP_CH_BROC]; ++ } ++ ++ //! Initialize output channel alignmment for ffmpeg process array ++ if (array_out) ++ { ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FL]] = array_out[AE_DSP_CH_FL]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FR]] = array_out[AE_DSP_CH_FR]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FC]] = array_out[AE_DSP_CH_FC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_LFE) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_LFE]] = array_out[AE_DSP_CH_LFE]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BL]] = array_out[AE_DSP_CH_BL]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BR]] = array_out[AE_DSP_CH_BR]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FLOC]] = array_out[AE_DSP_CH_FLOC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FROC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FROC]] = array_out[AE_DSP_CH_FROC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BC]] = array_out[AE_DSP_CH_BC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_SL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_SL]] = array_out[AE_DSP_CH_SL]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_SR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_SR]] = array_out[AE_DSP_CH_SR]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFL]] = array_out[AE_DSP_CH_TFL]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFR]] = array_out[AE_DSP_CH_TFR]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFC]] = array_out[AE_DSP_CH_TFC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TC]] = array_out[AE_DSP_CH_TC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBL]] = array_out[AE_DSP_CH_TBL]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBR]] = array_out[AE_DSP_CH_TBR]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBC]] = array_out[AE_DSP_CH_TBC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BLOC]] = array_out[AE_DSP_CH_BLOC]; ++ if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BROC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BROC]] = array_out[AE_DSP_CH_BROC]; ++ } ++} ++ ++float CActiveAEDSPProcess::GetDelay() ++{ ++ float delay = 0.0f; ++ ++ CSingleLock lock(m_critSection); ++ ++ if (m_addon_InputResample.pAddon) ++ delay += m_addon_InputResample.pAddon->InputResampleGetDelay(&m_addon_InputResample.handle); ++ ++ for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) ++ delay += m_addons_PreProc[i].pAddon->PreProcessGetDelay(&m_addons_PreProc[i].handle, m_addons_PreProc[i].iAddonModeNumber); ++ ++ if (m_addons_MasterProc[m_activeMode].pAddon) ++ delay += m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetDelay(&m_addons_MasterProc[m_activeMode].handle); ++ ++ for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) ++ delay += m_addons_PostProc[i].pAddon->PostProcessGetDelay(&m_addons_PostProc[i].handle, m_addons_PostProc[i].iAddonModeNumber); ++ ++ if (m_addon_OutputResample.pAddon) ++ delay += m_addon_OutputResample.pAddon->OutputResampleGetDelay(&m_addon_OutputResample.handle); ++ ++ return delay; ++} ++ ++bool CActiveAEDSPProcess::HasActiveModes(AE_DSP_MODE_TYPE type) ++{ ++ bool bReturn(false); ++ ++ CSingleLock lock(m_critSection); ++ ++ switch (type) ++ { ++ case AE_DSP_MODE_TYPE_INPUT_RESAMPLE: ++ if (m_addon_InputResample.pAddon != NULL) ++ bReturn = true; ++ break; ++ case AE_DSP_MODE_TYPE_PRE_PROCESS: ++ if (!m_addons_PreProc.empty()) ++ bReturn = true; ++ break; ++ case AE_DSP_MODE_TYPE_MASTER_PROCESS: ++ if (!m_addons_MasterProc.empty()) ++ bReturn = true; ++ break; ++ case AE_DSP_MODE_TYPE_POST_PROCESS: ++ if (!m_addons_PostProc.empty()) ++ bReturn = true; ++ break; ++ case AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE: ++ if (m_addon_OutputResample.pAddon != NULL) ++ bReturn = true; ++ break; ++ default: ++ break; ++ }; ++ ++ return bReturn; ++} ++ ++void CActiveAEDSPProcess::GetActiveModes(AE_DSP_MODE_TYPE type, std::vector &modes) ++{ ++ CSingleLock lock(m_critSection); ++ ++ if (m_addon_InputResample.pAddon != NULL && (type == AE_DSP_MODE_TYPE_UNDEFINED || type == AE_DSP_MODE_TYPE_INPUT_RESAMPLE)) ++ modes.push_back(m_addon_InputResample.pMode); ++ ++ if (type == AE_DSP_MODE_TYPE_UNDEFINED || type == AE_DSP_MODE_TYPE_PRE_PROCESS) ++ for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) ++ modes.push_back(m_addons_PreProc[i].pMode); ++ ++ if (m_addons_MasterProc[m_activeMode].pAddon != NULL && (type == AE_DSP_MODE_TYPE_UNDEFINED || type == AE_DSP_MODE_TYPE_MASTER_PROCESS)) ++ modes.push_back(m_addons_MasterProc[m_activeMode].pMode); ++ ++ if (type == AE_DSP_MODE_TYPE_UNDEFINED || type == AE_DSP_MODE_TYPE_POST_PROCESS) ++ for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) ++ modes.push_back(m_addons_PostProc[i].pMode); ++ ++ if (m_addon_OutputResample.pAddon != NULL && (type == AE_DSP_MODE_TYPE_UNDEFINED || type == AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE)) ++ modes.push_back(m_addon_OutputResample.pMode); ++} ++ ++void CActiveAEDSPProcess::GetAvailableMasterModes(AE_DSP_STREAMTYPE streamType, std::vector &modes) ++{ ++ CSingleLock lock(m_critSection); ++ ++ for (unsigned int i = 0; i < m_addons_MasterProc.size(); ++i) ++ { ++ if (m_addons_MasterProc[i].pMode->SupportStreamType(streamType)) ++ modes.push_back(m_addons_MasterProc[i].pMode); ++ } ++} ++ ++int CActiveAEDSPProcess::GetActiveMasterModeID() ++{ ++ CSingleLock lock(m_critSection); ++ ++ return m_activeMode < 0 ? AE_DSP_MASTER_MODE_ID_INVALID : m_addons_MasterProc[m_activeMode].pMode->ModeID(); ++} ++ ++CActiveAEDSPModePtr CActiveAEDSPProcess::GetActiveMasterMode() const ++{ ++ CSingleLock lock(m_critSection); ++ ++ CActiveAEDSPModePtr mode; ++ ++ if (m_activeMode < 0) ++ return mode; ++ ++ mode = m_addons_MasterProc[m_activeMode].pMode; ++ return mode; ++} ++ ++bool CActiveAEDSPProcess::SetMasterMode(AE_DSP_STREAMTYPE streamType, int iModeID, bool bSwitchStreamType) ++{ ++ /*! ++ * if the unique master mode id is already used a reinit is not needed ++ */ ++ if (m_addons_MasterProc[m_activeMode].pMode->ModeID() == iModeID && !bSwitchStreamType) ++ return true; ++ ++ CSingleLock lock(m_restartSection); ++ ++ m_NewMasterMode = iModeID; ++ m_NewStreamType = bSwitchStreamType ? streamType : AE_DSP_ASTREAM_INVALID; ++ m_forceInit = true; ++ return true; ++} ++ ++bool CActiveAEDSPProcess::IsMenuHookModeActive(AE_DSP_MENUHOOK_CAT category, int iAddonId, unsigned int iModeNumber) ++{ ++ std::vector *addons = NULL; ++ ++ switch (category) ++ { ++ case AE_DSP_MENUHOOK_MASTER_PROCESS: ++ addons = &m_addons_MasterProc; ++ break; ++ case AE_DSP_MENUHOOK_PRE_PROCESS: ++ addons = &m_addons_PreProc; ++ break; ++ case AE_DSP_MENUHOOK_POST_PROCESS: ++ addons = &m_addons_PostProc; ++ break; ++ case AE_DSP_MENUHOOK_RESAMPLE: ++ { ++ if (m_addon_InputResample.iAddonModeNumber > 0 && ++ m_addon_InputResample.pMode && ++ m_addon_InputResample.pMode->AddonID() == iAddonId && ++ m_addon_InputResample.pMode->AddonModeNumber() == iModeNumber) ++ return true; ++ ++ if (m_addon_OutputResample.iAddonModeNumber > 0 && ++ m_addon_OutputResample.pMode && ++ m_addon_OutputResample.pMode->AddonID() == iAddonId && ++ m_addon_OutputResample.pMode->AddonModeNumber() == iModeNumber) ++ return true; ++ } ++ default: ++ break; ++ } ++ ++ if (addons) ++ { ++ for (unsigned int i = 0; i < addons->size(); ++i) ++ { ++ if (addons->at(i).iAddonModeNumber > 0 && ++ addons->at(i).pMode->AddonID() == iAddonId && ++ addons->at(i).pMode->AddonModeNumber() == iModeNumber) ++ return true; ++ } ++ } ++ return false; ++} +diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h +new file mode 100644 +index 0000000..10de3a1 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h +@@ -0,0 +1,353 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2014 Team KODI ++ * http://kodi.tv ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with KODI; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include ++ ++#include "ActiveAEDSP.h" ++ ++extern "C" { ++#include "libavcodec/avcodec.h" ++#include "libswresample/swresample.h" ++} ++ ++namespace ActiveAE ++{ ++ class CSampleBuffer; ++ class IAEResample; ++ class CActiveAEResample; ++ ++ //@{ ++ /*! ++ * Individual DSP Processing class ++ */ ++ class CActiveAEDSPProcess ++ { ++ public: ++ CActiveAEDSPProcess(AE_DSP_STREAM_ID streamId); ++ virtual ~CActiveAEDSPProcess(); ++ ++ //@{ ++ /*!> ++ * Create the dsp processing with check of all addons about the used input and output audio format. ++ * @param inputFormat The used audio stream input format ++ * @param outputFormat Audio output format which is needed to send to the sinks ++ * @param upmix stereo upmix value from KODI settings is passed in with it ++ * @param quality The requested quality from settings ++ * @param streamType The input stream type to find allowed master process dsp addons for it, e.g. AE_DSP_ASTREAM_MUSIC ++ * @return True if the dsp processing becomes available ++ */ ++ bool Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, AEQuality quality, AE_DSP_STREAMTYPE streamType, ++ enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, int profile); ++ ++ /*!> ++ * Destroy all allocated dsp addons for this stream id and stops the processing. ++ */ ++ void Destroy(); ++ ++ /*!> ++ * Force processing function (Process(...)) to perform a reinitialization of addons and data ++ */ ++ void ForceReinit(); ++ ++ /*!> ++ * Get the stream id for this processing class ++ */ ++ AE_DSP_STREAM_ID GetStreamId() const; ++ ++ /*!> ++ * Get the currently used input stream format ++ * @note used to have a fallback to normal operation without dsp ++ */ ++ AEAudioFormat GetInputFormat(); ++ ++ /*!> ++ * Get the incoming channels amount for this class ++ */ ++ unsigned int GetInputChannels(); ++ ++ /*!> ++ * Get the incoming sample rate for this class ++ */ ++ unsigned int GetInputSamplerate(); ++ ++ /*!> ++ * Get the incoming channel names as string ++ */ ++ std::string GetInputChannelNames(); ++ ++ /*!> ++ * Get the inside addons used samplerate for this class ++ */ ++ unsigned int GetProcessSamplerate(); ++ ++ /*!> ++ * Get the outgoing channels amount for this class ++ */ ++ unsigned int GetOutputChannels(); ++ ++ /*!> ++ * Get the outgoing channel names ++ */ ++ std::string GetOutputChannelNames(); ++ ++ /*!> ++ * Get the used output samplerate for this class ++ */ ++ unsigned int GetOutputSamplerate(); ++ ++ /*!> ++ * Get the used output frames for this class ++ */ ++ unsigned int GetOutputFrames(); ++ ++ /*!> ++ * Get the amount of percent what the cpu need to process complete dsp stream ++ * @return The current cpu usage ++ */ ++ float GetCPUUsage(void) const; ++ ++ /*!> ++ * Get the channel layout which is passed out from it ++ * @return Channel information class ++ */ ++ CAEChannelInfo GetChannelLayout(); ++ ++ /*!> ++ * Get the currently used output data fromat ++ * @note Is normally float ++ */ ++ AEDataFormat GetDataFormat(); ++ ++ /*!> ++ * It returns the on input source detected stream type, not always the active one. ++ */ ++ AE_DSP_STREAMTYPE GetDetectedStreamType(); ++ ++ /*!> ++ * Get the currently on addons processed audio stream type which is set from KODI, ++ * it is user selectable or if auto mode is enabled it becomes detected upon the ++ * stream input source, eg. Movie, Music... ++ */ ++ AE_DSP_STREAMTYPE GetUsedStreamType(); ++ ++ /*!> ++ * Get the currently on addons processed audio base type which is detected from KODI. ++ * The base type is relevant to the type of input source, eg. Mono, Stereo, Dolby Digital... ++ */ ++ AE_DSP_BASETYPE GetUsedBaseType(); ++ ++ /*!> ++ * Used to check for active modes to given type on running stream id ++ * @param type The type to get, AE_DSP_MODE_TYPE_UNDEFINED to get from all types ++ * @return true if any of selected type is present ++ */ ++ bool HasActiveModes(AE_DSP_MODE_TYPE type); ++ ++ /*!> ++ * Used to get all active mode classes to given type on running stream id ++ * @param type The type to get, AE_DSP_MODE_TYPE_UNDEFINED to get from all types ++ * @retval modes The active modes classes in process chain list ++ */ ++ void GetActiveModes(AE_DSP_MODE_TYPE type, std::vector &modes); ++ ++ /*!> ++ * Used to get all available Master modes on current stream and base type. ++ * It is used to get informations about selectable modes and can be used as information ++ * for the gui to make the mode selection available. ++ * @param streamType the stream type to check about available master modes, e.g. AE_DSP_ASTREAM_MUSIC ++ * @retval modes Pointer to a buffer array where all available master mode written in ++ */ ++ void GetAvailableMasterModes(AE_DSP_STREAMTYPE streamType, std::vector &modes); ++ ++ /*!> ++ * Get the 32 bit individual identification code of the running master mode ++ * @return The identification code, or 0 if no master process is running ++ */ ++ int GetActiveMasterModeID(); ++ ++ /*!> ++ * Returns the information class from the currently used dsp addon ++ * @return pointer to the info class, or unitialized class if no master processing present ++ */ ++ CActiveAEDSPModePtr GetActiveMasterMode() const; ++ ++ /*!> ++ * Change master mode with the 32 bit individual identification code, the change ++ * is not directly performed in this function, is changed on next processing ++ * calls and must be observed that it becomes changed. ++ * @param streamType Stream type on the selection of the master mode ++ * @param iModeID The database identification code of the mode ++ * @param bSwitchStreamType force switching to given stream type ++ * @return True if the mode is allowed and can become changed ++ */ ++ bool SetMasterMode(AE_DSP_STREAMTYPE streamType, int iModeID, bool bSwitchStreamType = false); ++ ++ /*!> ++ * Read a description string from currently processed audio dsp master mode. ++ * It can be used to show additional stream information as string on the skin. ++ * The addon can have more stream information. ++ * @retval strInfo Pointer to a string where it is written in ++ * @return Returns false if no master processing is enabled ++ */ ++ bool GetMasterModeStreamInfoString(std::string &strInfo); ++ ++ /*!> ++ * Get all dsp addon relavant information to detect processing mode type and base values. ++ * @retval streamTypeUsed The current stream type processed by addon ++ * @retval baseType The current base type type processed by addon ++ * @retval iModeID The database identification code of the mode ++ * @return Returns false if no master processing is enabled ++ */ ++ bool GetMasterModeTypeInformation(AE_DSP_STREAMTYPE &streamTypeUsed, AE_DSP_BASETYPE &baseType, int &iModeID); ++ ++ /*!> ++ * Used check that asked addon with his mode id is used on given stream identifier ++ * @param category The type to get ++ * @param iAddonId The ID of the addon to get the menu entries for it ++ * @param iModeNumber From addon defined identifier of the mode ++ * @return true if in use ++ */ ++ bool IsMenuHookModeActive(AE_DSP_MENUHOOK_CAT category, int iAddonId, unsigned int iModeNumber); ++ ++ protected: ++ friend class CActiveAEBufferPoolResample; ++ ++ /*!> ++ * Master processing ++ * @param in the ActiveAE input samples ++ * @param out the processed ActiveAE output samples ++ * @return true if processing becomes performed correct ++ */ ++ bool Process(CSampleBuffer *in, CSampleBuffer *out); ++ ++ /*!> ++ * Returns the time in seconds that it will take ++ * for the next added packet to be heard from the speakers. ++ * @return seconds ++ */ ++ float GetDelay(); ++ //@} ++ private: ++ //@{ ++ /*! ++ * Helper functions ++ */ ++ void InitFFMpegDSPProcessor(); ++ bool CreateStreamProfile(); ++ void ResetStreamFunctionsSelection(); ++ AE_DSP_STREAMTYPE DetectStreamType(const CFileItem *item); ++ const char *GetStreamTypeName(AE_DSP_STREAMTYPE iStreamType); ++ void ClearArray(float **array, unsigned int samples); ++ bool MasterModeChange(int iModeID, AE_DSP_STREAMTYPE iStreamType = AE_DSP_ASTREAM_INVALID); ++ AE_DSP_BASETYPE GetBaseType(AE_DSP_STREAM_PROPERTIES *props); ++ bool RecheckProcessArray(unsigned int inputFrames); ++ bool ReallocProcessArray(unsigned int requestSize); ++ void CalculateCPUUsage(uint64_t iTime); ++ void SetFFMpegDSPProcessorArray(float *array_ffmpeg[2][AE_DSP_CH_MAX], float **array_in, float **array_out); ++ //@} ++ //@{ ++ /*! ++ * Data ++ */ ++ const AE_DSP_STREAM_ID m_streamId; /*!< stream id of this class, is a increase/decrease number of the amount of process streams */ ++ AE_DSP_STREAMTYPE m_streamTypeDetected; /*! The detected stream type of the stream from the source of it */ ++ AE_DSP_STREAMTYPE m_streamTypeUsed; /*!< The currently used stream type */ ++ bool m_forceInit; /*!< if set to true the process function perform a reinitialization of addons and data */ ++ AE_DSP_ADDONMAP m_usedMap; /*!< a map of all currently used audio dsp add-on's */ ++ AEAudioFormat m_inputFormat; /*!< the used input stream format */ ++ AEAudioFormat m_outputFormat; /*!< the from XBMX requested output format */ ++ unsigned int m_outputSamplerate; /*!< the currently active output samplerate can be become changed from addon resamplers */ ++ unsigned int m_outputFrames; /*!< the maximum present output frames */ ++ AEQuality m_streamQuality; /*!< from KODI requested stream quality, based also to addons */ ++ enum AEDataFormat m_dataFormat; /*!< The inside addon system used data format, currently fixed to float */ ++ AE_DSP_SETTINGS m_addonSettings; /*!< the current stream's settings passed to dsp add-ons */ ++ AE_DSP_STREAM_PROPERTIES m_addonStreamProperties; /*!< the current stream's properties (eg. stream type) passed to dsp add-ons */ ++ int m_NewMasterMode; /*!< if master mode is changed it set here and handled by process function */ ++ AE_DSP_STREAMTYPE m_NewStreamType; /*!< if stream type is changed it set here and handled by process function */ ++ enum AVMatrixEncoding m_ffMpegMatrixEncoding; ++ enum AVAudioServiceType m_ffMpegAudioServiceType; ++ int m_ffMpegProfile; ++ SwrContext *m_convertInput; ++ SwrContext *m_convertOutput; ++ ++ CCriticalSection m_critSection; ++ CCriticalSection m_restartSection; ++ ++ /*!> ++ * Selected dsp addon functions ++ */ ++ struct sDSPProcessHandle ++ { ++ void Clear() ++ { ++ iAddonModeNumber = -1; ++ iLastTime = 0; ++ } ++ unsigned int iAddonModeNumber; /*!< The identifier, send from addon during mode registration and can be used from addon to select mode from a function table */ ++ CActiveAEDSPModePtr pMode; /*!< Processing mode information data */ ++ AE_DSP_ADDON pAddon; /*!< Addon control class */ ++ ADDON_HANDLE_STRUCT handle; ++ uint64_t iLastTime; /*!< last processing time of the mode */ ++ }; ++ std::vector m_addons_InputProc; /*!< Input processing list, called to all enabled dsp addons with the basic unchanged input stream, is read only. */ ++ sDSPProcessHandle m_addon_InputResample; /*!< Input stream resampling over one on settings enabled input resample function only on one addon */ ++ std::vector m_addons_PreProc; /*!< Input stream preprocessing function calls set and aligned from dsp settings stored inside database */ ++ std::vector m_addons_MasterProc; /*!< The current from user selected master processing function on addon */ ++ int m_activeMode; /*!< the current used master mode, is a pointer to m_addons_MasterProc */ ++ int m_activeModeOutChannels; /*!< Amount of channels given from active master mode or -1 if unhandled */ ++ unsigned long m_activeModeOutChannelsPresent; /*! The exact present flags of output processing channels from active master mode */ ++ std::vector m_addons_PostProc; /*!< Output stream postprocessing function calls set and aligned from dsp settings stored inside database */ ++ sDSPProcessHandle m_addon_OutputResample; /*!< Output stream resampling over one on settings enabled output resample function only on one addon */ ++ std::map m_addon_Handles; /*!< Handle identifier for the called dsp functions */ ++ ++ /*!> ++ * Process arrays ++ */ ++ float *m_processArray[2][AE_DSP_CH_MAX]; ++ unsigned int m_processArraySize; ++ ++ /*!> ++ * CPU usage data ++ */ ++ uint64_t m_iLastProcessTime; ++ uint64_t m_iLastProcessUsage; ++ float m_fLastProcessUsage; ++ ++ /*!> ++ * Internal ffmpeg process data ++ */ ++ #define FFMPEG_PROC_ARRAY_IN 0 ++ #define FFMPEG_PROC_ARRAY_OUT 1 ++ IAEResample *m_resamplerDSPProcessor; /*!< ffmpeg resampler usage for down mix of input stream to required output channel alignment or internal processing*/ ++ float *m_ffMpegConvertArray[2][AE_DSP_CH_MAX]; /*!< the process array memory pointers for ffmpeg used for format convert. No own memory only addresses taken from m_processArray in correct ffmpeg channel alignment */ ++ float *m_ffMpegProcessArray[2][AE_DSP_CH_MAX]; /*!< the process array memory pointers for ffmpeg. No own memory only addresses taken from m_processArray in correct ffmpeg channel alignment */ ++ ++ /*!> ++ * Index pointers for interleaved audio streams to detect correct channel alignment ++ */ ++ int m_idx_in[AE_CH_MAX]; ++ uint64_t m_channelLayoutIn; ++ int m_idx_out[AE_CH_MAX]; ++ uint64_t m_channelLayoutOut; ++ //@} ++ }; ++ //@} ++} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index f61e387..c3e7ff6 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -23,8 +23,8 @@ + using namespace ActiveAE; + #include "ActiveAESound.h" + #include "ActiveAEStream.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h" + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "cores/AudioEngine/Utils/AEStreamInfo.h" + #include "cores/AudioEngine/AEResampleFactory.h" +@@ -297,7 +297,9 @@ CActiveAE::~CActiveAE() + + void CActiveAE::Dispose() + { ++#if defined(HAS_GLX) || defined(TARGET_DARWIN) + g_Windowing.Unregister(this); ++#endif + + m_bStop = true; + m_outMsgEvent.Set(); +@@ -1213,7 +1215,7 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt) + format.m_streamInfo.m_channels = 2; + format.m_streamInfo.m_sampleRate = 48000; + format.m_streamInfo.m_ac3FrameSize = m_encoderFormat.m_frames; +- //! @todo implement ++ // TODO + if (m_encoderBuffers && initSink) + { + m_discardBufferPools.push_back(m_encoderBuffers); +@@ -1249,7 +1251,7 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt) + uint64_t avlayout = CAEUtil::GetAVChannelLayout(outputFormat.m_channelLayout); + outputFormat.m_channelLayout = CAEUtil::GetAEChannelLayout(avlayout); + +- //! @todo adjust to decoder ++ // TODO: adjust to decoder + sinkInputFormat = outputFormat; + } + m_internalFormat = outputFormat; +@@ -1323,7 +1325,7 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt) + + // resample buffers + m_vizBuffers = new CActiveAEBufferPoolResample(m_internalFormat, vizFormat, m_settings.resampleQuality); +- //! @todo use cache of sync + water level ++ // TODO use cache of sync + water level + m_vizBuffers->Create(2000, false, false); + m_vizInitialized = false; + } +@@ -1904,7 +1906,8 @@ bool CActiveAE::RunStages() + CActiveAEStream *slave = (CActiveAEStream*)((*it)->m_streamSlave); + slave->m_paused = false; + +- //! @todo find better solution for this gapless bites audiophile ++ // TODO: find better solution for this ++ // gapless bites audiophile + if (m_settings.config == AE_CONFIG_MATCH) + Configure(&slave->m_format); + +@@ -2327,7 +2330,7 @@ CSampleBuffer* CActiveAE::SyncStream(CActiveAEStream *stream) + double threshold = 100; + if (stream->m_resampleMode) + { +- if (stream->m_pClock && stream->m_pClock->GetClockSpeed() > 1.1) ++ if (stream->m_pClock->GetClockSpeed() > 1.1) + threshold *= 10; + else + threshold *= 2; +@@ -2339,8 +2342,7 @@ CSampleBuffer* CActiveAE::SyncStream(CActiveAEStream *stream) + if (newerror && fabs(error) > threshold && stream->m_syncState == CAESyncInfo::AESyncState::SYNC_INSYNC) + { + stream->m_syncState = CAESyncInfo::AESyncState::SYNC_ADJUST; +- stream->m_resampleBuffers->m_resampleRatio = 1.0; +- stream->m_resampleIntegral = 0; ++ stream->m_resampleBuffers->m_resampleRatio = stream->GetResampleRatio(); + stream->m_lastSyncError = error; + CLog::Log(LOGDEBUG,"ActiveAE::SyncStream - average error %f above threshold of %f", error, threshold); + } +@@ -2449,6 +2451,7 @@ CSampleBuffer* CActiveAE::SyncStream(CActiveAEStream *stream) + } + } + ++ static double lerr; + if (fabs(error) < 30) + { + if (stream->m_lastSyncError > threshold * 2) +@@ -2460,13 +2463,18 @@ CSampleBuffer* CActiveAE::SyncStream(CActiveAEStream *stream) + } + else + { ++ lerr = threshold; + stream->m_syncState = CAESyncInfo::AESyncState::SYNC_INSYNC; + stream->m_syncError.Flush(1000); +- stream->m_resampleIntegral = 0; +- stream->m_resampleBuffers->m_resampleRatio = 1.0; + CLog::Log(LOGDEBUG,"ActiveAE::SyncStream - average error %f below threshold of %f", error, 30.0); + } + } ++ else ++ { ++ if (lerr && fabs(error) < lerr) ++ stream->m_resampleBuffers->m_resampleRatio = (1.0 / stream->m_pClock->GetClockSpeed() + stream->GetResampleRatio()) / 2; ++ lerr = fabs(error); ++ } + + return ret; + } +@@ -2479,6 +2487,7 @@ CSampleBuffer* CActiveAE::SyncStream(CActiveAEStream *stream) + if (stream->m_resampleBuffers) + { + stream->m_resampleBuffers->m_resampleRatio = stream->CalcResampleRatio(error); ++ stream->SetResampleRatio(stream->m_resampleBuffers->m_resampleRatio); + } + } + else if (stream->m_resampleBuffers) +@@ -2615,7 +2624,9 @@ bool CActiveAE::Initialize() + } + + // hook into windowing for receiving display reset events ++#if defined(HAS_GLX) || defined(TARGET_DARWIN) + g_Windowing.Register(this); ++#endif + + m_inMsgEvent.Reset(); + return true; +@@ -3211,7 +3222,7 @@ IAEStream *CActiveAE::MakeStream(AEAudioFormat &audioFormat, unsigned int option + if (IsSuspended()) + return NULL; + +- //! @todo pass number of samples in audio packet ++ //TODO: pass number of samples in audio packet + + AEAudioFormat format = audioFormat; + format.m_frames = format.m_sampleRate / 10; +@@ -3284,7 +3295,7 @@ void CActiveAE::FlushStream(CActiveAEStream *stream) + + void CActiveAE::PauseStream(CActiveAEStream *stream, bool pause) + { +- //! @todo pause sink, needs api change ++ // TODO pause sink, needs api change + if (pause) + m_controlPort.SendOutMessage(CActiveAEControlProtocol::PAUSESTREAM, + &stream, sizeof(CActiveAEStream*)); +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h +index 2a31a6e..f0c0eac 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h +@@ -19,10 +19,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "system.h" + #include "threads/Thread.h" + +@@ -220,7 +216,11 @@ protected: + std::vector m_streamStats; + }; + ++#if defined(HAS_GLX) || defined(TARGET_DARWIN) + class CActiveAE : public IAE, public IDispResource, private CThread ++#else ++class CActiveAE : public IAE, private CThread ++#endif + { + protected: + friend class ::CAEFactory; +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp +index bc49ce2..a64ee31 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp +@@ -20,7 +20,7 @@ + + #include "ActiveAEBuffer.h" + #include "cores/AudioEngine/AEFactory.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h" + #include "cores/AudioEngine/Engines/ActiveAE/ActiveAE.h" + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "cores/AudioEngine/AEResampleFactory.h" +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h +index 3bb7990..aadbb0d 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h +@@ -21,7 +21,7 @@ + + #include "cores/AudioEngine/Utils/AEAudioFormat.h" + #include "cores/AudioEngine/Interfaces/AE.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include + + extern "C" { +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp +index 8961d66..fde70b1 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp +@@ -271,10 +271,10 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg) + { + SinkReply reply; + reply.format = m_sinkFormat; +- //! @todo +- //! use max raw packet size, for now use max size of an IEC packed packet +- //! maxIECPpacket > maxRawPacket +- //! for raw packets frameSize is set to 1 ++ // TODO ++ // use max raw packet size, for now use max size of an IEC packed packet ++ // maxIECPpacket > maxRawPacket ++ // for raw packets frameSize is set to 1 + if (m_requestedFormat.m_dataFormat == AE_FMT_RAW) + { + reply.format.m_frames = 61440; +@@ -818,7 +818,7 @@ void CActiveAESink::OpenSink() + } + + // open NULL sink +- //! @todo should not be required by ActiveAE ++ // TODO: should not be required by ActiveAE + if (!m_sink) + { + device = "NULL:NULL"; +@@ -1005,28 +1005,15 @@ unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples) + { + maxFrames = std::min(frames, m_sinkFormat.m_frames); + written = m_sink->AddPackets(buffer, maxFrames, totalFrames - frames); +- if (written == 0) ++ if (written == 0 && retry++ < 4) + { + Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate); +- retry++; +- if (retry > 4) +- { +- m_extError = true; +- CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed"); +- status.SetDelay(0); +- framesOrPackets = frames; +- if (m_requestedFormat.m_dataFormat == AE_FMT_RAW) +- framesOrPackets = 1; +- m_stats->UpdateSinkDelay(status, samples->pool ? framesOrPackets : 0); +- return 0; +- } +- else +- continue; ++ continue; + } +- else if (written > maxFrames) ++ else if (!written || written > maxFrames) + { + m_extError = true; +- CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error"); ++ CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - %s", written ? "sink returned error" : "failed"); + status.SetDelay(0); + framesOrPackets = frames; + if (m_requestedFormat.m_dataFormat == AE_FMT_RAW) +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.cpp +index e6aaf6a..50073e7 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.cpp +@@ -68,7 +68,7 @@ void CActiveAESound::Stop() + + bool CActiveAESound::IsPlaying() + { +- //! @todo implement ++ // TODO + return false; + } + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +index 1d58691..f95e54a 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +@@ -200,11 +200,14 @@ void CActiveAEStream::RemapBuffer() + + double CActiveAEStream::CalcResampleRatio(double error) + { ++ const double maxDiff = 0.02; ++ static double retLast; ++ + //reset the integral on big errors, failsafe + if (fabs(error) > 1000) + m_resampleIntegral = 0; + else if (fabs(error) > 5) +- m_resampleIntegral += error / 1000 / 50; ++ m_resampleIntegral += error / 1000 / 100; + + double proportional = 0.0; + +@@ -215,7 +218,15 @@ double CActiveAEStream::CalcResampleRatio(double error) + if (m_pClock) + clockspeed = m_pClock->GetClockSpeed(); + +- double ret = 1.0 / clockspeed + proportional + m_resampleIntegral; ++ double ret = proportional + m_resampleIntegral; ++ ++ if (ret - retLast > maxDiff) ++ ret = retLast + maxDiff; ++ else if (retLast - ret > maxDiff) ++ ret = retLast - maxDiff; ++ ++ retLast = ret; ++ ret += 1.0 / clockspeed; + //CLog::Log(LOGNOTICE,"----- error: %f, rr: %f, prop: %f, int: %f", + // error, ret, proportional, m_resampleIntegral); + return ret; +diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in +index 4167eec..7aab111 100644 +--- a/xbmc/cores/AudioEngine/Makefile.in ++++ b/xbmc/cores/AudioEngine/Makefile.in +@@ -57,11 +57,11 @@ SRCS += Sinks/AESinkPULSE.cpp + endif + endif + +-SRCS += Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.cpp +-SRCS += Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.cpp +-SRCS += Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPAddon.cpp +-SRCS += Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPDatabase.cpp +-SRCS += Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp ++SRCS += DSPAddons/ActiveAEDSP.cpp ++SRCS += DSPAddons/ActiveAEDSPMode.cpp ++SRCS += DSPAddons/ActiveAEDSPAddon.cpp ++SRCS += DSPAddons/ActiveAEDSPDatabase.cpp ++SRCS += DSPAddons/ActiveAEDSPProcess.cpp + + SRCS += Utils/AEChannelInfo.cpp + SRCS += Utils/AEBuffer.cpp +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index 6a9066b..d77707f 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -351,8 +351,8 @@ snd_pcm_chmap_t* CAESinkALSA::CopyALSAchmap(snd_pcm_chmap_t* alsaMap) + std::string CAESinkALSA::ALSAchmapToString(snd_pcm_chmap_t* alsaMap) + { + char buf[128] = { 0 }; +- //! @bug ALSA bug - buffer overflow by a factor of 2 is possible +- //! http://mailman.alsa-project.org/pipermail/alsa-devel/2014-December/085815.html ++ // ALSA bug - buffer overflow by a factor of 2 is possible ++ // http://mailman.alsa-project.org/pipermail/alsa-devel/2014-December/085815.html + int err = snd_pcm_chmap_print(alsaMap, sizeof(buf) / 2, buf); + if (err < 0) + return "Error"; +@@ -926,50 +926,43 @@ unsigned int CAESinkALSA::AddPackets(uint8_t **data, unsigned int frames, unsign + unsigned int amount = 0; + int64_t data_left = (int64_t) frames; + int frames_written = 0; ++ int ret = 0; + +- while (data_left > 0) ++ snd_pcm_nonblock(m_pcm, 0); ++ while (data_left > 0 && HandleError(__func__, ret)) + { + if (m_fragmented) + amount = std::min((unsigned int) data_left, m_originalPeriodSize); + else // take care as we can come here a second time if the sink does not eat all data + amount = (unsigned int) data_left; + +- int ret = snd_pcm_writei(m_pcm, buffer, amount); +- if (ret < 0) +- { +- CLog::Log(LOGERROR, "CAESinkALSA - snd_pcm_writei(%d) %s - trying to recover", ret, snd_strerror(ret)); +- ret = snd_pcm_recover(m_pcm, ret, 1); +- if(ret < 0) +- { +- HandleError("snd_pcm_writei(1)", ret); +- ret = snd_pcm_writei(m_pcm, buffer, amount); +- if (ret < 0) +- { +- HandleError("snd_pcm_writei(2)", ret); +- ret = 0; +- } +- } +- } ++ ret = snd_pcm_writei(m_pcm, buffer, amount); + +- if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED) ++ if (ret < 0) ++ continue; ++ else if (ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED) + snd_pcm_start(m_pcm); + +- if (ret <= 0) +- break; +- + frames_written += ret; + data_left -= ret; + buffer = data[0]+offset*m_format.m_frameSize + frames_written*m_format.m_frameSize; + } ++ + return frames_written; + } + +-void CAESinkALSA::HandleError(const char* name, int err) ++inline ++int CAESinkALSA::HandleError(const char* name, int err) + { ++ static int recoveries; ++ ++ if (err >= 0) ++ recoveries = -2; ++ + switch(err) + { + case -EPIPE: +- CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - underrun", name); ++ CLog::Log(LOGDEBUG, "CAESinkALSA::HandleError(%s) - underrun", name); + if ((err = snd_pcm_prepare(m_pcm)) < 0) + CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_prepare returned %d (%s)", name, err, snd_strerror(err)); + break; +@@ -988,9 +981,11 @@ void CAESinkALSA::HandleError(const char* name, int err) + break; + + default: +- CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_writei returned %d (%s)", name, err, snd_strerror(err)); + break; + } ++ ++ snd_pcm_avail_update(m_pcm); ++ return recoveries++; + } + + void CAESinkALSA::Drain() +@@ -1027,7 +1022,7 @@ bool CAESinkALSA::TryDevice(const std::string &name, snd_pcm_t **pcmp, snd_confi + int err = snd_pcm_open_lconf(pcmp, name.c_str(), SND_PCM_STREAM_PLAYBACK, ALSA_OPTIONS, lconf); + if (err < 0) + { +- CLog::Log(LOGINFO, "CAESinkALSA - Unable to open device \"%s\" for playback", name.c_str()); ++ CLog::Log(LOGINFO, "CAESinkALSA - Unable to open device \"%s\" for playback (error: %s)", name.c_str(), snd_strerror(err)); + } + + return err == 0; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +index 4ca5941..8de0318 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +@@ -73,7 +73,7 @@ private: + #endif + + void GetAESParams(const AEAudioFormat& format, std::string& params); +- void HandleError(const char* name, int err); ++ int HandleError(const char* name, int err); + + std::string m_initDevice; + AEAudioFormat m_initFormat; +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp +index 1ae3f1f..31f7946 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp +@@ -293,7 +293,7 @@ bool CAESinkDARWINOSX::Initialize(AEAudioFormat &format, std::string &device) + // update the channel map based on the new stream format + devEnum.GetAEChannelMap(format.m_channelLayout, numOutputChannels); + +- //! @todo Should we use the virtual format to determine our data format? ++ /* TODO: Should we use the virtual format to determine our data format? */ + format.m_frameSize = format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3); + format.m_frames = m_device.GetBufferSize(); + +@@ -315,14 +315,14 @@ bool CAESinkDARWINOSX::Initialize(AEAudioFormat &format, std::string &device) + + void CAESinkDARWINOSX::SetHogMode(bool on) + { +- //! @todo Auto hogging sets this for us. Figure out how/when to turn it off or use it +- //! It appears that leaving this set will aslo restore the previous stream format when the +- //! Application exits. If auto hogging is set and we try to set hog mode, we will deadlock +- //! From the SDK docs: "If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc." +- //! +- //! Lock down the device. This MUST be done PRIOR to switching to a non-mixable format, if it is done at all +- //! If it is attempted after the format change, there is a high likelihood of a deadlock +- //! We may need to do this sooner to enable mix-disable (i.e. before setting the stream format) ++ // TODO: Auto hogging sets this for us. Figure out how/when to turn it off or use it ++ // It appears that leaving this set will aslo restore the previous stream format when the ++ // Application exits. If auto hogging is set and we try to set hog mode, we will deadlock ++ // From the SDK docs: "If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc." ++ ++ // Lock down the device. This MUST be done PRIOR to switching to a non-mixable format, if it is done at all ++ // If it is attempted after the format change, there is a high likelihood of a deadlock ++ // We may need to do this sooner to enable mix-disable (i.e. before setting the stream format) + if (on) + { + // Auto-Hog does not always un-hog the device when changing back to a mixable mode. +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp +index 4cdbf5a..aa0a357 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp +@@ -125,7 +125,7 @@ void CAESinkNULL::Process() + { + if (m_draining) + { +- //! @todo is it correct to not take data at the appropriate rate while draining? ++ // TODO: is it correct to not take data at the appropriate rate while draining? + m_sinkbuffer_level = 0; + m_draining = false; + } +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp +index 583f559..043d0d5 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp +@@ -579,13 +579,9 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device) + return false; + } + +- // Pulse can resample everything between 1 hz and 192000 hz / 384000 hz (starting with 9.0) ++ // Pulse can resample everything between 1 hz and 192000 hz + // Make sure we are in the range that we originally added +- unsigned int max_pulse_sample_rate = 192000U; +-#if PA_CHECK_VERSION(9,0,0) +- max_pulse_sample_rate = 384000U; +-#endif +- format.m_sampleRate = std::max(5512U, std::min(format.m_sampleRate, max_pulse_sample_rate)); ++ format.m_sampleRate = std::max(5512U, std::min(format.m_sampleRate, 192000U)); + + pa_format_info *info[1]; + info[0] = pa_format_info_new(); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +index e3e0895..534c383 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +@@ -105,12 +105,11 @@ struct sampleFormat + AEDataFormat subFormatType; + }; + +-//! @todo +-//! Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */ +-//! versions of Kodi before 14.0 had a bug which made S24NE4MSB the first format selected +-//! this bug worked around some driver bug of some IEC958 devices which report S32 but can't handle it +-//! correctly. So far I have never seen and WASAPI device using S32 and don't think probing S24 before +-//! S32 has any negative impact. ++/* Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */ ++// versions of Kodi before 14.0 had a bug which made S24NE4MSB the first format selected ++// this bug worked around some driver bug of some IEC958 devices which report S32 but can't handle it ++// correctly. So far I have never seen and WASAPI device using S32 and don't think probing S24 before ++// S32 has any negative impact. + static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT}, + {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4MSB}, + {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE}, +diff --git a/xbmc/cores/AudioEngine/Sinks/osx/AEDeviceEnumerationOSX.h b/xbmc/cores/AudioEngine/Sinks/osx/AEDeviceEnumerationOSX.h +index defd18d..7f12391 100644 +--- a/xbmc/cores/AudioEngine/Sinks/osx/AEDeviceEnumerationOSX.h ++++ b/xbmc/cores/AudioEngine/Sinks/osx/AEDeviceEnumerationOSX.h +@@ -19,10 +19,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "cores/AudioEngine/Utils/AEDeviceInfo.h" + #include "cores/AudioEngine/Sinks/osx/CoreAudioDevice.h" + +diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h +index 68cde14..331b876 100644 +--- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h ++++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h +@@ -23,9 +23,7 @@ + + #if defined(TARGET_DARWIN_OSX) + +-#include + #include +-#include + + #include "cores/AudioEngine/Sinks/osx/CoreAudioStream.h" + +diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp +index c9169f1..d280e2f 100644 +--- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp +@@ -59,8 +59,8 @@ bool CCoreAudioStream::Open(AudioStreamID streamId) + return true; + } + +-//! @todo Should it even be possible to change both the +-//! physical and virtual formats, since the devices do it themselves? ++// TODO: Should it even be possible to change both the ++// physical and virtual formats, since the devices do it themselves? + void CCoreAudioStream::Close(bool restore) + { + if (!m_StreamId) +diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h +index 3f01060..3fb01c1 100644 +--- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h ++++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h +@@ -28,7 +28,6 @@ + #include + + #include +-#include + + // not defined in 10.6 sdk + #ifndef kIOAudioDeviceTransportTypeThunderbolt +diff --git a/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp b/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp +index 29c645d..69171cf 100644 +--- a/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp ++++ b/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp +@@ -191,7 +191,7 @@ void CAEELDParser::Parse(const uint8_t *data, size_t length, CAEDeviceInfo& info + AEDataFormat fmt = AE_FMT_INVALID; + switch (formatCode) + { +- //! @todo implement ++ // TODO + case CEA_861_FORMAT_AC3 : fmt = AE_FMT_RAW ; break; + case CEA_861_FORMAT_DTS : fmt = AE_FMT_RAW ; break; + case CEA_861_FORMAT_DTSHD: fmt = AE_FMT_RAW ; break; +diff --git a/xbmc/cores/DllLoader/DllLoader.cpp b/xbmc/cores/DllLoader/DllLoader.cpp +index 6438705..01f8e9a 100644 +--- a/xbmc/cores/DllLoader/DllLoader.cpp ++++ b/xbmc/cores/DllLoader/DllLoader.cpp +@@ -383,8 +383,8 @@ int DllLoader::LoadExports() + PrintExportTable(ExportDirTable); + #endif + +- //! @todo Validate all pointers are valid. Is a zero RVA valid or not? I'd guess not as it would +- //! point to the coff file header, thus not right. ++ // TODO - Validate all pointers are valid. Is a zero RVA valid or not? I'd guess not as it would ++ // point to the coff file header, thus not right. + + unsigned long *ExportAddressTable = (unsigned long*)RVA2Data(ExportDirTable->ExportAddressTable_RVA); + unsigned long *NamePointerTable = (unsigned long*)RVA2Data(ExportDirTable->NamePointerTable_RVA); +diff --git a/xbmc/cores/DllLoader/Win32DllLoader.cpp b/xbmc/cores/DllLoader/Win32DllLoader.cpp +index 9db3216..050b358 100644 +--- a/xbmc/cores/DllLoader/Win32DllLoader.cpp ++++ b/xbmc/cores/DllLoader/Win32DllLoader.cpp +@@ -372,7 +372,7 @@ bool FunctionNeedsWrapping(Export *exports, const char *functionName, void **fix + while (exp->name) + { + if (strcmp(exp->name, functionName) == 0) +- { //! @todo Should we be tracking stuff? ++ { // TODO: Should we be tracking stuff? + if (0) + *fixup = exp->track_function; + else +@@ -395,7 +395,7 @@ bool Win32DllLoader::ResolveOrdinal(const char *dllName, unsigned long ordinal, + while (exp->name) + { + if (exp->ordinal == ordinal) +- { //! @todo Should we be tracking stuff? ++ { // TODO: Should we be tracking stuff? + if (0) + *fixup = exp->track_function; + else +diff --git a/xbmc/cores/DllLoader/exports/CMakeLists.txt b/xbmc/cores/DllLoader/exports/CMakeLists.txt +index 71b470a..32e612f 100644 +--- a/xbmc/cores/DllLoader/exports/CMakeLists.txt ++++ b/xbmc/cores/DllLoader/exports/CMakeLists.txt +@@ -8,7 +8,7 @@ set(HEADERS emu_dummy.h + + core_add_library(dllexports) + +-if(APPLE) ++if(CORE_SYSTEM_NAME STREQUAL darwin OR CORE_SYSTEM_NAME STREQUAL ios) + add_library(wrapper OBJECT wrapper.c) + add_custom_target(wrapper.def ALL ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/wrapper_mach_alias wrapper.def) + add_dependencies(wrapper.def wrapper) +@@ -19,8 +19,8 @@ elseif(NOT CORE_SYSTEM_NAME STREQUAL windows) + add_custom_target(wrapper.def ALL nm ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/wrapper.dir/wrapper.c.o | grep __wrap | awk '{ printf(\"%s \", \$\$3) }' | sed \"s/___wrap_/__wrap_/g\" | sed \"s/__wrap_/-Wl,-wrap,/g\" > wrapper.def) + + if(CORE_SYSTEM_NAME STREQUAL android) +- add_custom_command(TARGET wrapper.def COMMAND echo \"-l$\" >> wrapper.def) +- add_dependencies(wrapper.def ${APP_NAME_LC}) ++ add_custom_target(patchdef ALL echo \"-L${CMAKE_INSTALL_PREFIX}/lib/dummy-libxbmc/ -lxbmc\" >> wrapper.def) ++ add_dependencies(patchdef wrapper.def xbmc) + endif() + + add_dependencies(wrapper.def wrapper) +diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +index 44578fe..c8e17b3 100644 +--- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp ++++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +@@ -877,6 +877,11 @@ extern "C" + while ((iDirSlot < MAX_OPEN_DIRS) && (vecDirsOpen[iDirSlot].curr_index != -1)) iDirSlot++; + if (iDirSlot >= MAX_OPEN_DIRS) + return -1; // no free slots ++ if (url.IsProtocol("filereader")) ++ { ++ CURL url2(url.GetFileName()); ++ url = url2; ++ } + strURL = url.Get(); + bVecDirsInited = true; + vecDirsOpen[iDirSlot].items.Clear(); +@@ -997,6 +1002,12 @@ extern "C" + return NULL; // no free slots + } + ++ if (url.IsProtocol("filereader")) ++ { ++ CURL url2(url.GetFileName()); ++ url = url2; ++ } ++ + bVecDirsInited = true; + vecDirsOpen[iDirSlot].items.Clear(); + +diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h +index 771355c..4b07b4e 100644 +--- a/xbmc/cores/IPlayer.h ++++ b/xbmc/cores/IPlayer.h +@@ -22,7 +22,6 @@ + + #include "system.h" // until we get sane int types used here + #include +-#include + #include "IPlayerCallback.h" + #include "guilib/Geometry.h" + #include "guilib/Resolution.h" +@@ -174,6 +173,10 @@ enum EINTERLACEMETHOD + + VS_INTERLACEMETHOD_IMX_FASTMOTION = 29, + VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE = 30, ++ VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE_INVERTED = 31, ++ VS_INTERLACEMETHOD_IMX_ADVMOTION = 32, ++ VS_INTERLACEMETHOD_IMX_ADVMOTION_DOUBLE = 33, ++ VS_INTERLACEMETHOD_IMX_WEAVE = 34, + + VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. + }; +diff --git a/xbmc/cores/VideoPlayer/DVDClock.cpp b/xbmc/cores/VideoPlayer/DVDClock.cpp +index bcf9cc7..7d0b84c 100644 +--- a/xbmc/cores/VideoPlayer/DVDClock.cpp ++++ b/xbmc/cores/VideoPlayer/DVDClock.cpp +@@ -34,7 +34,6 @@ CDVDClock::CDVDClock() + + m_pauseClock = 0; + m_bReset = true; +- m_paused = false; + m_iDisc = 0; + m_maxspeedadjust = 0.0; + m_systemAdjust = 0; +@@ -101,41 +100,14 @@ double CDVDClock::GetVsyncAdjust() + return m_vSyncAdjust; + } + +-void CDVDClock::Pause(bool pause) +-{ +- CSingleLock lock(m_critSection); +- +- if (pause && !m_paused) +- { +- if (!m_pauseClock) +- m_speedAfterPause = m_systemFrequency * DVD_PLAYSPEED_NORMAL / m_systemUsed; +- else +- m_speedAfterPause = DVD_PLAYSPEED_PAUSE; +- +- SetSpeed(DVD_PLAYSPEED_PAUSE); +- m_paused = true; +- } +- else if (!pause && m_paused) +- { +- m_paused = false; +- SetSpeed(m_speedAfterPause); +- } +-} +- + void CDVDClock::SetSpeed(int iSpeed) + { + // this will sometimes be a little bit of due to rounding errors, ie clock might jump abit when changing speed + CSingleLock lock(m_critSection); + +- if (m_paused) +- { +- m_speedAfterPause = iSpeed; +- return; +- } +- +- if (iSpeed == DVD_PLAYSPEED_PAUSE) ++ if(iSpeed == DVD_PLAYSPEED_PAUSE) + { +- if (!m_pauseClock) ++ if(!m_pauseClock) + m_pauseClock = m_videoRefClock->GetTime(); + return; + } +@@ -144,7 +116,7 @@ void CDVDClock::SetSpeed(int iSpeed) + int64_t newfreq = m_systemFrequency * DVD_PLAYSPEED_NORMAL / iSpeed; + + current = m_videoRefClock->GetTime(); +- if (m_pauseClock) ++ if( m_pauseClock ) + { + m_startClock += current - m_pauseClock; + m_pauseClock = 0; +@@ -212,6 +184,7 @@ void CDVDClock::Discontinuity(double clock, double absolute) + m_bReset = false; + m_systemAdjust = 0; + m_speedAdjust = 0; ++ m_vSyncAdjust = 0; + } + + void CDVDClock::SetMaxSpeedAdjust(double speed) +@@ -255,6 +228,11 @@ int CDVDClock::UpdateFramerate(double fps, double* interval /*= NULL*/) + return rate; + } + ++double CDVDClock::GetRefreshRate() ++{ ++ return m_videoRefClock->GetRefreshRate(); ++} ++ + bool CDVDClock::GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const + { + return m_videoRefClock->GetClockInfo(MissedVblanks, ClockSpeed, RefreshRate); +diff --git a/xbmc/cores/VideoPlayer/DVDClock.h b/xbmc/cores/VideoPlayer/DVDClock.h +index 931ee68..b1fde18 100644 +--- a/xbmc/cores/VideoPlayer/DVDClock.h ++++ b/xbmc/cores/VideoPlayer/DVDClock.h +@@ -70,12 +70,11 @@ public: + double GetAbsoluteClock(bool interpolated = true); + double GetFrequency() { return (double)m_systemFrequency ; } + ++ double GetRefreshRate(); + bool GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const; + void SetVsyncAdjust(double adjustment); + double GetVsyncAdjust(); + +- void Pause(bool pause); +- + protected: + double SystemToAbsolute(int64_t system); + int64_t AbsoluteToSystem(double absolute); +@@ -87,8 +86,6 @@ protected: + int64_t m_pauseClock; + double m_iDisc; + bool m_bReset; +- bool m_paused; +- int m_speedAfterPause; + std::unique_ptr m_videoRefClock; + + int64_t m_systemFrequency; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +index 3a080d0..c793ff4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +@@ -45,11 +45,6 @@ CDVDOverlayCodecFFmpeg::~CDVDOverlayCodecFFmpeg() + + bool CDVDOverlayCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + { +- +- // decoding of this kind of subs does not work reliable +- if (hints.codec == AV_CODEC_ID_EIA_608) +- return false; +- + AVCodec* pCodec = avcodec_find_decoder(hints.codec); + if (!pCodec) + { +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder708.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder708.cpp +index 4c5d524..61a3acf 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder708.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder708.cpp +@@ -31,7 +31,7 @@ unsigned char get_internal_from_G1 (unsigned char g1_char) + return g1_char; + } + +-//! @todo Probably not right ++// TODO: Probably not right + // G2: Extended Control Code Set 1 + unsigned char get_internal_from_G2 (unsigned char g2_char) + { +@@ -46,7 +46,7 @@ unsigned char get_internal_from_G2 (unsigned char g2_char) + return 0x20; + } + +-//! @todo Probably not right ++// TODO: Probably not right + // G3: Future Characters and Icon Expansion + unsigned char get_internal_from_G3 (unsigned char g3_char) + { +@@ -314,7 +314,7 @@ void rollupWindow(cc708_service_decoder *decoder, int window) + how many bytes would be consumed if these codes were supported, as defined in the specs. + Note: EXT1 not included */ + // C2: Extended Miscellaneous Control Codes +-//! @todo This code is completely untested due to lack of samples. Just following specs! ++// TODO: This code is completely untested due to lack of samples. Just following specs! + int handle_708_C2 (cc708_service_decoder *decoder, unsigned char *data, int data_length) + { + if (data[0]<=0x07) // 00-07... +@@ -338,7 +338,7 @@ int handle_708_C3 (cc708_service_decoder *decoder, unsigned char *data, int data + + // These are variable length commands, that can even span several segments + // (they allow even downloading fonts or graphics). +- //! @todo Implemen if a sample ever appears ++ // TODO: Implemen if a sample ever appears + return 0; // Unreachable, but otherwise there's compilers warnings + } + +@@ -346,7 +346,7 @@ int handle_708_C3 (cc708_service_decoder *decoder, unsigned char *data, int data + // G2 (20-7F) => Mostly unmapped, except for a few characters. + // G3 (A0-FF) => A0 is the CC symbol, everything else reserved for future expansion in EIA708-B + // C2 (00-1F) => Reserved for future extended misc. control and captions command codes +-//! @todo This code is completely untested due to lack of samples. Just following specs! ++// TODO: This code is completely untested due to lack of samples. Just following specs! + // Returns number of used bytes, usually 1 (since EXT1 is not counted). + int handle_708_extended_char (cc708_service_decoder *decoder, unsigned char *data, int data_length) + { +@@ -368,7 +368,7 @@ int handle_708_extended_char (cc708_service_decoder *decoder, unsigned char *dat + else if (code>=0x80 && code<=0x9F) + { + used=handle_708_C3 (decoder, data, data_length); +- //! @todo Something ++ // TODO: Something + } + // Group G3 + else +@@ -429,10 +429,10 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data + process_cr (decoder); + break; + case 0x0e: // HCR (Horizontal Carriage Return) +- //! @todo Process HDR ++ // TODO: Process HDR + break; + case 0x0c: // FF (Form Feed) +- //! @todo Process FF ++ // TODO: Process FF + break; + } + len=1; +@@ -448,7 +448,7 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data + // Only PE16 is defined. + if (data[0]==0x18) // PE16 + { +- ; //! @todo Handle PE16 ++ ; // TODO: Handle PE16 + } + len=3; + } +@@ -460,7 +460,7 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data + { + return -1; + } +- //! @todo Do something useful eventually ++ // TODO: Do something useful eventually + return len; + } + +@@ -505,7 +505,7 @@ void process_character (cc708_service_decoder *decoder, unsigned char internal_c + // G0 - Code Set - ASCII printable characters + int handle_708_G0 (cc708_service_decoder *decoder, unsigned char *data, int data_length) + { +- //! @todo Substitution of the music note character for the ASCII DEL character ++ // TODO: Substitution of the music note character for the ASCII DEL character + unsigned char c=get_internal_from_G0 (data[0]); + process_character (decoder, c); + return 1; +@@ -603,7 +603,7 @@ void handle_708_HDW_HideWindows (cc708_service_decoder *decoder, int windows_bit + changes=1; + decoder->windows[i].visible=0; + } +- //! @todo Actually Hide Window ++ // TODO: Actually Hide Window + } + windows_bitmap>>=1; + } +@@ -672,7 +672,7 @@ void handle_708_DFx_DefineWindow (cc708_service_decoder *decoder, int window, un + { + // If the window is being created, all character positions in the window + // are set to the fill color... +- //! @todo COLORS ++ // TODO: COLORS + // ...and the pen location is set to (0,0) + decoder->windows[window].pen_column=0; + decoder->windows[window].pen_row=0; +@@ -687,7 +687,7 @@ void handle_708_DFx_DefineWindow (cc708_service_decoder *decoder, int window, un + decoder->current_window=-1; + for (int j=0;jwindows[window].rows[j]); +- return; //! @todo Warn somehow ++ return; // TODO: Warn somehow + } + } + decoder->windows[window].memory_reserved=1; +@@ -745,7 +745,7 @@ void deleteWindow (cc708_service_decoder *decoder, int window) + // or DefineWindow command. + decoder->current_window=-1; + } +- //! @todo Do the actual deletion (remove from display if needed, etc), mark as ++ // TODO: Do the actual deletion (remove from display if needed, etc), mark as + // not defined, etc + if (decoder->windows[window].is_defined) + { +@@ -843,13 +843,13 @@ void handle_708_SPL_SetPenLocation (cc708_service_decoder *decoder, unsigned cha + ------------------------------------------------------- */ + void handle_708_DLY_Delay (cc708_service_decoder *decoder, int tenths_of_sec) + { +- //! @todo Probably ask for the current FTS and wait for this time before resuming - ++ // TODO: Probably ask for the current FTS and wait for this time before resuming - + // not sure it's worth it though + } + + void handle_708_DLC_DelayCancel (cc708_service_decoder *decoder) + { +- //! @todo See above ++ // TODO: See above + } + + // C1 Code Set - Captioning Commands Control Codes +@@ -959,7 +959,7 @@ void process_service_block (cc708_service_decoder *decoder, unsigned char *data, + used=handle_708_G1 (decoder,data+i,data_length-i); + if (used==-1) + { +- //! @todo Not sure if a local reset is going to be helpful here. ++ // TODO: Not sure if a local reset is going to be helpful here. + cc708_service_reset (decoder); + return; + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index ae0abee..392cb26 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -54,49 +54,12 @@ extern "C" { + #include + #include + #include +-#include + + // amcodec include + extern "C" { + #include + } // extern "C" + +-class PosixFile +-{ +-public: +- PosixFile() : +- m_fd(-1) +- { +- } +- +- PosixFile(int fd) : +- m_fd(fd) +- { +- } +- +- ~PosixFile() +- { +- if (m_fd >= 0) +- close(m_fd); +- } +- +- bool Open(const std::string &pathName, int flags) +- { +- m_fd = open(pathName.c_str(), flags); +- return m_fd >= 0; +- } +- +- int GetDescriptor() const { return m_fd; } +- +- int IOControl(unsigned long request, void *param) +- { +- return ioctl(m_fd, request, param); +- } +- +-private: +- int m_fd; +-}; +- + typedef struct { + bool noblock; + int video_pid; +@@ -401,6 +364,27 @@ void dumpfile_write(am_private_t *para, void* buf, int bufsiz) + write(para->dumpfile, buf, bufsiz); + } + ++/*************************************************************************/ ++/*************************************************************************/ ++static int64_t get_pts_video() ++{ ++ int fd = open("/sys/class/tsync/pts_video", O_RDONLY); ++ if (fd >= 0) ++ { ++ char pts_str[16]; ++ int size = read(fd, pts_str, sizeof(pts_str)); ++ close(fd); ++ if (size > 0) ++ { ++ unsigned long pts = strtoul(pts_str, NULL, 16); ++ return pts; ++ } ++ } ++ ++ CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error"); ++ return -1; ++} ++ + static int set_pts_pcrscr(int64_t value) + { + int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY); +@@ -1434,6 +1418,9 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_speed = DVD_PLAYSPEED_NORMAL; + m_1st_pts = 0; + m_cur_pts = 0; ++ m_player_pts = 0; ++ m_cur_pictcnt = 0; ++ m_old_pictcnt = 0; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; + m_contrast = -1; +@@ -1443,12 +1430,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_start_pts = 0; + m_hints = hints; + +- if (!OpenAmlVideo(hints)) +- { +- CLog::Log(LOGERROR, "CAMLCodec::OpenDecoder - cannot open amlvideo device"); +- return false; +- } +- + ShowMainVideo(false); + + am_packet_init(&am_private->am_pkt); +@@ -1471,7 +1452,12 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den; + + // handle video rate +- if (hints.fpsrate > 0 && hints.fpsscale != 0) ++ if (hints.rfpsrate > 0 && hints.rfpsscale != 0) ++ { ++ // check ffmpeg r_frame_rate 1st ++ am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate; ++ } ++ else if (hints.fpsrate > 0 && hints.fpsscale != 0) + { + // then ffmpeg avg_frame_rate next + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate; +@@ -1539,8 +1525,8 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder " + "hints.width(%d), hints.height(%d), hints.codec(%d), hints.codec_tag(%d)", + hints.width, hints.height, hints.codec, hints.codec_tag); +- CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), video_rate(%d)", +- hints.fpsrate, hints.fpsscale, am_private->video_rate); ++ CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)", ++ hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", + hints.aspect, video_ratio.num, video_ratio.den); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)", +@@ -1631,7 +1617,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + am_private->dumpdemux = false; + dumpfile_open(am_private); + +- //! @bug make sure we are not stuck in pause (amcodec bug) ++ // make sure we are not stuck in pause (amcodec bug) + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + +@@ -1671,53 +1657,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + return true; + } + +-bool CAMLCodec::OpenAmlVideo(const CDVDStreamInfo &hints) +-{ +- PosixFilePtr amlVideoFile = std::make_shared(); +- if (!amlVideoFile->Open("/dev/video10", O_RDONLY | O_NONBLOCK)) +- { +- CLog::Log(LOGERROR, "CAMLCodec::OpenAmlVideo - cannot open V4L amlvideo device /dev/video10: %s", strerror(errno)); +- return false; +- } +- +- m_amlVideoFile = amlVideoFile; +- +- m_defaultVfmMap = GetVfmMap("default"); +- SetVfmMap("default", "decoder ppmgr deinterlace amlvideo amvideo"); +- +- SysfsUtils::SetInt("/sys/module/amlvideodri/parameters/freerun_mode", 1); +- +- return true; +-} +- +-std::string CAMLCodec::GetVfmMap(const std::string &name) +-{ +- std::string vfmMap; +- SysfsUtils::GetString("/sys/class/vfm/map", vfmMap); +- std::vector sections = StringUtils::Split(vfmMap, '\n'); +- std::string sectionMap; +- for (size_t i = 0; i < sections.size(); ++i) +- { +- if (StringUtils::StartsWith(sections[i], name + " {")) +- { +- sectionMap = sections[i]; +- break; +- } +- } +- +- int openingBracePos = sectionMap.find('{') + 1; +- sectionMap = sectionMap.substr(openingBracePos, sectionMap.size() - openingBracePos - 1); +- StringUtils::Replace(sectionMap, "(0)", ""); +- +- return sectionMap; +-} +- +-void CAMLCodec::SetVfmMap(const std::string &name, const std::string &map) +-{ +- SysfsUtils::SetString("/sys/class/vfm/map", "rm " + name); +- SysfsUtils::SetString("/sys/class/vfm/map", "add " + name + " " + map); +-} +- + void CAMLCodec::CloseDecoder() + { + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); +@@ -1740,14 +1679,6 @@ void CAMLCodec::CloseDecoder() + SysfsUtils::SetInt("/sys/class/tsync/enable", 1); + + ShowMainVideo(false); +- +- CloseAmlVideo(); +-} +- +-void CAMLCodec::CloseAmlVideo() +-{ +- m_amlVideoFile.reset(); +- SetVfmMap("default", m_defaultVfmMap); + } + + void CAMLCodec::Reset() +@@ -1785,7 +1716,8 @@ void CAMLCodec::Reset() + // reset some interal vars + m_1st_pts = 0; + m_cur_pts = 0; +- m_ptsQueue.clear(); ++ m_cur_pictcnt = 0; ++ m_old_pictcnt = 0; + SetSpeed(m_speed); + } + +@@ -1796,6 +1728,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + if (pData) + { ++ m_player_pts = pts; + am_private->am_pkt.data = pData; + am_private->am_pkt.data_size = iSize; + +@@ -1816,6 +1749,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avpts -= m_start_pts; + ++ + // handle dts, including 31bit wrap, aml can only handle 31 + // bit dts as it uses an int in kernel. + if (dts == DVD_NOPTS_VALUE) +@@ -1872,22 +1806,28 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (iSize < 20) + target_timesize = 2.0; + +- int rtn = 0; +- + // keep hw buffered demux above 1 second +- if (GetTimeSize() < target_timesize) +- rtn |= VC_BUFFER; ++ if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL) ++ return VC_BUFFER; + + // wait until we get a new frame or 25ms, +- if (m_ptsQueue.size() == 0) ++ if (m_old_pictcnt == m_cur_pictcnt) + m_ready_event.WaitMSec(25); + +- if (m_ptsQueue.size() > 0) ++ // we must return VC_BUFFER or VC_PICTURE, ++ // default to VC_BUFFER. ++ int rtn = VC_BUFFER; ++ m_player_pts = DVD_NOPTS_VALUE; ++ if (m_old_pictcnt != m_cur_pictcnt) + { +- CSingleLock lock(m_ptsQueueMutex); +- m_cur_pts = m_ptsQueue.front(); +- m_ptsQueue.pop_front(); +- rtn |= VC_PICTURE; ++ m_old_pictcnt++; ++ rtn = VC_PICTURE; ++ m_player_pts = pts; ++ // we got a new pict, try and keep hw buffered demux above 2 seconds. ++ // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds. ++ // we also check to make sure we keep from filling hw buffer. ++ if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3) ++ rtn |= VC_BUFFER; + } + /* + CLog::Log(LOGDEBUG, "CAMLCodec::Decode: " +@@ -1897,36 +1837,6 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + return rtn; + } + +-int CAMLCodec::DequeueBuffer(int &pts) +-{ +- v4l2_buffer vbuf = { 0 }; +- vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- +- if (m_amlVideoFile->IOControl(VIDIOC_DQBUF, &vbuf) < 0) +- { +- if (errno != EAGAIN) +- CLog::Log(LOGERROR, "CAMLCodec::DequeueBuffer - VIDIOC_DQBUF failed: %s", strerror(errno)); +- return -errno; +- } +- +- // Since kernel 3.14 Amlogic changed length and units of PTS values reported here. +- // To differentiate such PTS values we check for existence of omx_pts_interval_lower +- // parameter, because it was introduced since kernel 3.14. +- if (access("/sys/module/amvideo/parameters/omx_pts_interval_lower", F_OK) != -1) +- { +- int64_t pts64 = vbuf.timestamp.tv_sec & 0xFFFFFFFF; +- pts64 <<= 32; +- pts64 += vbuf.timestamp.tv_usec & 0xFFFFFFFF; +- pts = (int)((pts64 * PTS_FREQ) / DVD_TIME_BASE); +- } +- else +- { +- pts = vbuf.timestamp.tv_usec; +- } +- +- return 0; +-} +- + bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + { + if (!m_opened) +@@ -1938,7 +1848,7 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + if (m_speed == DVD_PLAYSPEED_NORMAL) +- pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; ++ pDvdVideoPicture->pts = m_player_pts; + else + { + if (m_cur_pts == 0) +@@ -2021,25 +1931,40 @@ void CAMLCodec::Process() + { + CLog::Log(LOGDEBUG, "CAMLCodec::Process Started"); + ++ // bump our priority to be level with SoftAE ++ SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); + while (!m_bStop) + { +- if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0) ++ int64_t pts_video = 0; ++ if (am_private->am_pkt.lastpts > 0) + { +- CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed"); +- Sleep(10); +- } ++ // this is a blocking poll that returns every vsync. ++ // since we are running at a higher priority, make sure ++ // we sleep if the call fails or does a timeout. ++ if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0) ++ { ++ CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed"); ++ Sleep(10); ++ } + +- { +- CSingleLock lock(m_ptsQueueMutex); +- int pts = 0; +- if (DequeueBuffer(pts) == 0) ++ pts_video = get_pts_video(); ++ if (m_cur_pts != pts_video) + { +- m_ptsQueue.push_back(pts); ++ //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)", ++ // pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ)); ++ ++ // other threads look at these, do them first ++ m_cur_pts = pts_video; ++ m_cur_pictcnt++; + m_ready_event.Set(); + } + } ++ else ++ { ++ Sleep(100); ++ } + } +- ++ SetPriority(THREAD_PRIORITY_NORMAL); + CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped"); + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 813b913..5b9ee4f 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -25,15 +25,11 @@ + #include "guilib/Geometry.h" + #include "rendering/RenderSystem.h" + #include "threads/Thread.h" +-#include + + typedef struct am_private_t am_private_t; + + class DllLibAmCodec; + +-class PosixFile; +-typedef std::shared_ptr PosixFilePtr; +- + class CAMLCodec : public CThread + { + public: +@@ -51,7 +47,6 @@ public: + int GetDataSize(); + double GetTimeSize(); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); +- int64_t GetCurPts() const { return m_cur_pts; } + + protected: + virtual void Process(); +@@ -65,11 +60,6 @@ private: + void SetVideoSaturation(const int saturation); + void SetVideo3dMode(const int mode3d); + std::string GetStereoMode(); +- bool OpenAmlVideo(const CDVDStreamInfo &hints); +- void CloseAmlVideo(); +- std::string GetVfmMap(const std::string &name); +- void SetVfmMap(const std::string &name, const std::string &map); +- int DequeueBuffer(int &pts); + + DllLibAmCodec *m_dll; + bool m_opened; +@@ -78,6 +68,8 @@ private: + volatile int m_speed; + volatile int64_t m_1st_pts; + volatile int64_t m_cur_pts; ++ volatile int64_t m_cur_pictcnt; ++ volatile int64_t m_old_pictcnt; + volatile double m_timesize; + volatile int64_t m_vbufsize; + int64_t m_start_dts; +@@ -94,8 +86,5 @@ private: + int m_contrast; + int m_brightness; + +- PosixFilePtr m_amlVideoFile; +- std::string m_defaultVfmMap; +- std::deque m_ptsQueue; +- CCriticalSection m_ptsQueueMutex; ++ double m_player_pts; + }; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt +index 491ee8a..be28f08 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt +@@ -40,7 +40,7 @@ if(VAAPI_FOUND) + list(APPEND HEADERS VAAPI.h) + endif() + +-if(APPLE) ++if(CORE_SYSTEM_NAME STREQUAL darwin OR CORE_SYSTEM_NAME STREQUAL ios) + list(APPEND SOURCES VTB.cpp) + list(APPEND HEADERS DllVideoToolBox.h + VTB.h) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h +index a2da9de..99d2bb3 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -311,6 +311,8 @@ public: + */ + virtual void Reopen() {}; + ++ virtual bool GetInterlaced() { return false; } ++ + protected: + CProcessInfo &m_processInfo; + }; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index 80f25dd..43ca555 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -91,7 +91,9 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + m_mpeg2_sequence->width = m_hints.width; + m_mpeg2_sequence->height = m_hints.height; + m_mpeg2_sequence->ratio = m_hints.aspect; +- if (m_hints.fpsrate > 0 && m_hints.fpsscale != 0) ++ if (m_hints.rfpsrate > 0 && m_hints.rfpsscale != 0) ++ m_mpeg2_sequence->rate = (float)m_hints.rfpsrate / m_hints.rfpsscale; ++ else if (m_hints.fpsrate > 0 && m_hints.fpsscale != 0) + m_mpeg2_sequence->rate = (float)m_hints.fpsrate / m_hints.fpsscale; + else + m_mpeg2_sequence->rate = 1.0; +@@ -294,7 +296,7 @@ bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) + m_Codec->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + +- CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, (int)m_Codec->GetCurPts()); ++ CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec); + + { + CSingleLock lock(m_secure); +@@ -440,41 +442,43 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double + { + default: + case 0x01: +- m_hints.fpsrate = 24000.0; +- m_hints.fpsscale = 1001.0; ++ m_hints.rfpsrate = 24000.0; ++ m_hints.rfpsscale = 1001.0; + break; + case 0x02: +- m_hints.fpsrate = 24000.0; +- m_hints.fpsscale = 1000.0; ++ m_hints.rfpsrate = 24000.0; ++ m_hints.rfpsscale = 1000.0; + break; + case 0x03: +- m_hints.fpsrate = 25000.0; +- m_hints.fpsscale = 1000.0; ++ m_hints.rfpsrate = 25000.0; ++ m_hints.rfpsscale = 1000.0; + break; + case 0x04: +- m_hints.fpsrate = 30000.0; +- m_hints.fpsscale = 1001.0; ++ m_hints.rfpsrate = 30000.0; ++ m_hints.rfpsscale = 1001.0; + break; + case 0x05: +- m_hints.fpsrate = 30000.0; +- m_hints.fpsscale = 1000.0; ++ m_hints.rfpsrate = 30000.0; ++ m_hints.rfpsscale = 1000.0; + break; + case 0x06: +- m_hints.fpsrate = 50000.0; +- m_hints.fpsscale = 1000.0; ++ m_hints.rfpsrate = 50000.0; ++ m_hints.rfpsscale = 1000.0; + break; + case 0x07: +- m_hints.fpsrate = 60000.0; +- m_hints.fpsscale = 1001.0; ++ m_hints.rfpsrate = 60000.0; ++ m_hints.rfpsscale = 1001.0; + break; + case 0x08: +- m_hints.fpsrate = 60000.0; +- m_hints.fpsscale = 1000.0; ++ m_hints.rfpsrate = 60000.0; ++ m_hints.rfpsscale = 1000.0; + break; + } + m_hints.width = m_mpeg2_sequence->width; + m_hints.height = m_mpeg2_sequence->height; + m_hints.aspect = m_mpeg2_sequence->ratio; ++ m_hints.fpsrate = m_hints.rfpsrate; ++ m_hints.fpsscale = m_hints.rfpsscale; + } + return; + } +@@ -573,11 +577,10 @@ void CDVDVideoCodecAmlogic::RemoveInfo(CDVDAmlogicInfo *info) + m_inflight.erase(m_inflight.find(info)); + } + +-CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts) ++CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec) + : m_refs(0) + , m_codec(codec) + , m_amlCodec(amlcodec) +- , m_omxPts(omxPts) + { + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index a4cc25c..c15238b 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -36,14 +36,13 @@ class CDVDVideoCodecAmlogic; + class CDVDAmlogicInfo + { + public: +- CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts); ++ CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec); + + // reference counting + CDVDAmlogicInfo* Retain(); + long Release(); + + CAMLCodec *getAmlCodec() const; +- int GetOmxPts() const { return m_omxPts; } + void invalidate(); + + protected: +@@ -52,7 +51,6 @@ protected: + + CDVDVideoCodecAmlogic* m_codec; + CAMLCodec* m_amlCodec; +- int m_omxPts; + }; + + class CDVDVideoCodecAmlogic : public CDVDVideoCodec +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 0414d85..86f476a 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -28,7 +28,9 @@ + #include "DVDClock.h" + #include "DVDCodecs/DVDCodecs.h" + #include "DVDCodecs/DVDCodecUtils.h" ++#if defined(TARGET_POSIX) || defined(TARGET_WINDOWS) + #include "utils/CPUInfo.h" ++#endif + #include "settings/AdvancedSettings.h" + #include "settings/Settings.h" + #include "settings/VideoSettings.h" +@@ -300,9 +302,9 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + } + else + { +- int num_threads = g_cpuInfo.getCPUCount() * 3 / 2; +- num_threads = std::max(1, std::min(num_threads, 16)); +- m_pCodecContext->thread_count = num_threads; ++ int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount()); ++ if( num_threads > 1) ++ m_pCodecContext->thread_count = num_threads; + m_pCodecContext->thread_safe_callbacks = 1; + m_decoderState = STATE_SW_MULTI; + CLog::Log(LOGDEBUG, "CDVDVideoCodecFFmpeg - open frame threaded with %d threads", num_threads); +@@ -334,7 +336,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + } + + // advanced setting override for skip loop filter (see avcodec.h for valid options) +- //! @todo allow per video setting? ++ // TODO: allow per video setting? + if (g_advancedSettings.m_iSkipLoopFilter != 0) + { + m_pCodecContext->skip_loop_filter = (AVDiscard)g_advancedSettings.m_iSkipLoopFilter; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index e6f46c5..711b071 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -22,11 +22,16 @@ + + #include "settings/AdvancedSettings.h" + #include "threads/SingleLock.h" +-#include "threads/Atomics.h" + #include "utils/log.h" +-#include "DVDClock.h" + #include "windowing/WindowingFactory.h" + #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" ++#include "guilib/GraphicContext.h" ++#include "utils/StringUtils.h" ++#include "settings/MediaSettings.h" ++#include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h" ++ ++#include "linux/imx/IMX.h" ++#include "libavcodec/avcodec.h" + + #include + #include +@@ -36,33 +41,76 @@ + #include + #include + #include ++#include ++#include ++ ++#define FRAME_ALIGN 16 ++#define MEDIAINFO 1 ++#define RENDER_QUEUE_SIZE NUM_BUFFERS ++#define DECODE_OUTPUT_SIZE 15 ++#define IN_DECODER_SET -1 + +-#define IMX_VDI_MAX_WIDTH 968 +-#define FRAME_ALIGN 16 +-#define MEDIAINFO 1 +-#define RENDER_QUEUE_SIZE 3 + #define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) + #define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align)) + #define Align2(ptr,align) (((unsigned int)ptr)/(align)*(align)) ++#define ALIGN Align ++ ++#define BIT(nr) (1UL << (nr)) ++#define SZ_4K 4*1024 ++ ++#ifdef TRACE_FRAMES ++unsigned char CDVDVideoCodecIMXBuffer::i = 0; ++#endif + ++CIMXContext g_IMXContext; ++std::shared_ptr g_IMXCodec; + +-// Global instance +-CIMXContext g_IMXContext; ++std::list m_recycleBuffers; + + // Number of fb pages used for paning +-const int CIMXContext::m_fbPages = 2; ++const int CIMXContext::m_fbPages = 3; + + // Experiments show that we need at least one more (+1) VPU buffer than the min value returned by the VPU +-const int CDVDVideoCodecIMX::m_extraVpuBuffers = 1+RENDER_QUEUE_SIZE+2; +-const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; +-CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; ++const unsigned int CIMXCodec::m_extraVpuBuffers = 2 + RENDER_QUEUE_SIZE; ++ ++CDVDVideoCodecIMX::~CDVDVideoCodecIMX() ++{ ++ m_IMXCodec.reset(); ++ if (g_IMXCodec.use_count() == 1) ++ g_IMXCodec.reset(); ++} ++ ++bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) ++{ ++ if (!g_IMXCodec) ++ { ++ m_IMXCodec.reset(new CIMXCodec); ++ g_IMXCodec = m_IMXCodec; ++ } ++ else ++ m_IMXCodec = g_IMXCodec; + +-bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) ++ return g_IMXCodec->Open(hints, options, m_pFormatName); ++} ++ ++unsigned CDVDVideoCodecIMX::GetAllowedReferences() ++{ ++ return RENDER_QUEUE_SIZE; ++} ++ ++bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++ if (pDvdVideoPicture) ++ SAFE_RELEASE(pDvdVideoPicture->IMXBuffer); ++ ++ return true; ++} ++ ++bool CIMXCodec::VpuAllocBuffers(VpuMemInfo *pMemBlock) + { + int i, size; + void* ptr; + VpuMemDesc vpuMem; +- VpuDecRetCode ret; + + for(i=0; inSubBlockNum; i++) + { +@@ -72,9 +120,10 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) + ptr = malloc(size); + if(ptr == NULL) + { +- CLog::Log(LOGERROR, "%s - Unable to malloc %d bytes.\n", __FUNCTION__, size); +- goto AllocFailure; ++ ExitError("%s - Unable to malloc %d bytes.\n", size); ++ return false; + } ++ + pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(ptr, pMemBlock->MemSubBlock[i].nAlignment); + + m_decMemInfo.nVirtNum++; +@@ -84,48 +133,27 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) + else + { // Allocate contigous mem for DMA + vpuMem.nSize = size; +- ret = VPU_DecGetMem(&vpuMem); +- if(ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - Unable alloc %d bytes of physical memory (%d).\n", __FUNCTION__, size, ret); +- goto AllocFailure; +- } ++ if(!VpuAlloc(&vpuMem)) ++ return false; ++ + pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(vpuMem.nVirtAddr, pMemBlock->MemSubBlock[i].nAlignment); + pMemBlock->MemSubBlock[i].pPhyAddr = (unsigned char*)Align(vpuMem.nPhyAddr, pMemBlock->MemSubBlock[i].nAlignment); +- +- m_decMemInfo.nPhyNum++; +- m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = size; + } + } + + return true; +- +-AllocFailure: +- VpuFreeBuffers(); +- return false; +-} +- +-int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) +-{ +- for (int i=0; i=m_decMemInfo.nPhyNum - freePhyNum; i--) + { + vpuMem.nPhyAddr = m_decMemInfo.phyMem[i].nPhyAddr; + vpuMem.nVirtAddr = m_decMemInfo.phyMem[i].nVirtAddr; +@@ -152,24 +181,31 @@ bool CDVDVideoCodecIMX::VpuFreeBuffers() + { + CLog::Log(LOGERROR, "%s - Error while trying to free physical memory (%d).\n", __FUNCTION__, ret); + ret = false; ++ break; + } ++ else ++ released++; ++ } ++ ++ m_decMemInfo.nPhyNum -= released; ++ if (!m_decMemInfo.nPhyNum) ++ { ++ free(m_decMemInfo.phyMem); ++ m_decMemInfo.phyMem = NULL; + } +- free(m_decMemInfo.phyMem); +- m_decMemInfo.phyMem = NULL; +- m_decMemInfo.nPhyNum = 0; + } + ++ m_vpuFrameBuffers.clear(); + return ret; + } + + +-bool CDVDVideoCodecIMX::VpuOpen() ++bool CIMXCodec::VpuOpen() + { + VpuDecRetCode ret; + VpuVersionInfo vpuVersion; + VpuMemInfo memInfo; +- VpuDecConfig config; +- int param; ++ int param; + + memset(&memInfo, 0, sizeof(VpuMemInfo)); + ret = VPU_DecLoad(); +@@ -207,7 +243,6 @@ bool CDVDVideoCodecIMX::VpuOpen() + #else + m_decOpenParam.nChromaInterleave = 1; + #endif +- m_decOpenParam.nMapType = 0; + m_decOpenParam.nTiled2LinearEnable = 0; + m_decOpenParam.nEnableFileMode = 0; + +@@ -218,44 +253,8 @@ bool CDVDVideoCodecIMX::VpuOpen() + goto VpuOpenError; + } + +- config = VPU_DEC_CONF_SKIPMODE; +- param = VPU_DEC_SKIPNONE; +- ret = VPU_DecConfig(m_vpuHandle, config, ¶m); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - iMX VPU set skip mode failed (%d).\n", __FUNCTION__, ret); +- goto VpuOpenError; +- } +- +- config = VPU_DEC_CONF_BUFDELAY; + param = 0; +- ret = VPU_DecConfig(m_vpuHandle, config, ¶m); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - iMX VPU set buffer delay failed (%d).\n", __FUNCTION__, ret); +- goto VpuOpenError; +- } +- +- config = VPU_DEC_CONF_INPUTTYPE; +- param = VPU_DEC_IN_NORMAL; +- ret = VPU_DecConfig(m_vpuHandle, config, ¶m); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - iMX VPU configure input type failed (%d).\n", __FUNCTION__, ret); +- goto VpuOpenError; +- } +- +- // Note that libvpufsl (file vpu_wrapper.c) associates VPU_DEC_CAP_FRAMESIZE +- // capability to the value of nDecFrameRptEnabled which is in fact directly +- // related to the ability to generate VPU_DEC_ONE_FRM_CONSUMED even if the +- // naming is misleading... +- ret = VPU_DecGetCapability(m_vpuHandle, VPU_DEC_CAP_FRAMESIZE, ¶m); +- m_frameReported = (param != 0); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - iMX VPU get framesize capability failed (%d).\n", __FUNCTION__, ret); +- m_frameReported = false; +- } ++ SetVPUParams(VPU_DEC_CONF_BUFDELAY, ¶m); + + return true; + +@@ -264,7 +263,26 @@ VpuOpenError: + return false; + } + +-bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() ++bool CIMXCodec::VpuAlloc(VpuMemDesc *vpuMem) ++{ ++ VpuDecRetCode ret = VPU_DecGetMem(vpuMem); ++ if (ret) ++ { ++ CLog::Log(LOGERROR, "%s: vpu malloc frame buf of size %d failure: ret=%d \r\n",__FUNCTION__, vpuMem->nSize, ret); ++ return false; ++ } ++ ++ m_decMemInfo.nPhyNum++; ++ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem->nPhyAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem->nVirtAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem->nCpuAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem->nSize; ++ ++ return true; ++} ++ ++bool CIMXCodec::VpuAllocFrameBuffers() + { + int totalSize = 0; + int ySize = 0; +@@ -274,14 +292,12 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() + int yStride = 0; + int uvStride = 0; + +- VpuDecRetCode ret; + VpuMemDesc vpuMem; + unsigned char* ptr; + unsigned char* ptrVirt; + int nAlign; + +- m_vpuFrameBufferNum = m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers; +- m_vpuFrameBuffers = new VpuFrameBuffer[m_vpuFrameBufferNum]; ++ int nrBuf = std::min(m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers + DECODE_OUTPUT_SIZE, (unsigned int)30); + + yStride = Align(m_initInfo.nPicWidth,FRAME_ALIGN); + if(m_initInfo.nInterlace) +@@ -309,7 +325,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() + uSize = vSize = mvSize = ySize; + break; + default: +- CLog::Log(LOGERROR, "%s: invalid source format in init info\n",__FUNCTION__,ret); ++ CLog::Log(LOGERROR, "%s: invalid source format in init info\n",__FUNCTION__); + return false; + } + +@@ -329,27 +345,18 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() + mvSize = Align(mvSize, nAlign); + } + +- m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; +- +- for (int i=0 ; i < m_vpuFrameBufferNum; i++) ++ totalSize = ySize + uSize + vSize + mvSize + nAlign; ++ for (int i=0 ; i < nrBuf; i++) + { +- totalSize = ySize + uSize + vSize + mvSize + nAlign; +- + vpuMem.nSize = totalSize; +- ret = VPU_DecGetMem(&vpuMem); +- if(ret != VPU_DEC_RET_SUCCESS) ++ if(!VpuAlloc(&vpuMem)) + { +- CLog::Log(LOGERROR, "%s: vpu malloc frame buf failure: ret=%d \r\n",__FUNCTION__,ret); +- return false; +- } ++ if (m_vpuFrameBuffers.size() < m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers) ++ return false; + +- //record memory info for release +- m_decMemInfo.nPhyNum++; +- m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; +- m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem.nSize; ++ CLog::Log(LOGWARNING, "%s: vpu can't allocate sufficient extra buffers. specify bigger CMA e.g. cma=320M.\r\n",__FUNCTION__); ++ break; ++ } + + //fill frameBuf + ptr = (unsigned char*)vpuMem.nPhyAddr; +@@ -362,6 +369,9 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() + ptrVirt = (unsigned char*)Align(ptrVirt,nAlign); + } + ++ VpuFrameBuffer vpuFrameBuffer; ++ m_vpuFrameBuffers.push_back(vpuFrameBuffer); ++ + // fill stride info + m_vpuFrameBuffers[i].nStrideY = yStride; + m_vpuFrameBuffers[i].nStrideC = uvStride; +@@ -390,53 +400,66 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() + m_vpuFrameBuffers[i].pbufCb_tilebot = 0; + m_vpuFrameBuffers[i].pbufVirtY_tilebot = 0; + m_vpuFrameBuffers[i].pbufVirtCb_tilebot = 0; +- +-#ifdef TRACE_FRAMES +- m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); +-#else +- m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer; +-#endif +- // Those buffers are ours so lock them to prevent destruction +- m_outputBuffers[i]->Lock(); + } + ++ if (VPU_DEC_RET_SUCCESS != VPU_DecRegisterFrameBuffer(m_vpuHandle, &m_vpuFrameBuffers[0], m_vpuFrameBuffers.size())) ++ return false; ++ ++ m_decOutput.setquotasize(m_vpuFrameBuffers.size() - m_initInfo.nMinFrameBufferCount - m_extraVpuBuffers); + return true; + } + +-CDVDVideoCodecIMX::CDVDVideoCodecIMX(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo) ++CIMXCodec::CIMXCodec() ++ : CThread("iMX VPU") ++ , m_dropped(0) ++ , m_lastPTS(DVD_NOPTS_VALUE) ++ , m_codecControlFlags(0) ++ , m_decSignal(0) ++ , m_threadID(0) ++ , m_decRet(VPU_DEC_INPUT_NOT_USED) ++ , m_fps(-1) + { +- m_pFormatName = "iMX-xxx"; + m_vpuHandle = 0; +- m_vpuFrameBuffers = NULL; +- m_outputBuffers = NULL; +- m_lastBuffer = NULL; +- m_currentBuffer = NULL; +- m_extraMem = NULL; +- m_vpuFrameBufferNum = 0; +- m_dropState = false; +- m_convert_bitstream = false; +- m_frameCounter = 0; +- m_usePTS = true; +- if (getenv("IMX_NOPTS") != NULL) +- { +- m_usePTS = false; +- } + m_converter = NULL; +- m_convert_bitstream = false; +- m_bytesToBeConsumed = 0; +- m_previousPts = DVD_NOPTS_VALUE; + #ifdef DUMP_STREAM + m_dump = NULL; + #endif ++ m_drainMode = VPU_DEC_IN_NORMAL; ++ m_skipMode = VPU_DEC_SKIPNONE; ++ ++ m_decOutput.setquotasize(1); ++ m_decInput.setquotasize(20); ++ m_loaded.Reset(); + } + +-CDVDVideoCodecIMX::~CDVDVideoCodecIMX() ++CIMXCodec::~CIMXCodec() + { +- Dispose(); ++ StopThread(false); ++ ProcessSignals(SIGNAL_SIGNAL); ++ SetDrainMode(VPU_DEC_IN_DRAIN); ++ StopThread(); + } + +-bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) ++void CIMXCodec::DisposeDecQueues() ++{ ++ m_decInput.signal(); ++ m_decInput.for_each(Release); ++ m_decOutput.signal(); ++ m_decOutput.for_each(Release); ++} ++ ++void CIMXCodec::Reset() ++{ ++ m_queuesLock.lock(); ++ DisposeDecQueues(); ++ ProcessSignals(SIGNAL_FLUSH); ++ CLog::Log(LOGVIDEO, "iMX VPU : queues cleared ===== in/out %d/%d =====\n", m_decInput.size(), m_decOutput.size()); ++} ++ ++bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::string &m_pFormatName) + { ++ CSingleLock lk(m_openLock); ++ + if (hints.software) + { + CLog::Log(LOGNOTICE, "iMX VPU : software decoding requested.\n"); +@@ -447,7 +470,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + CLog::Log(LOGNOTICE, "iMX VPU : software decoding forced - video dimensions out of spec: %d %d.", hints.width, hints.height); + return false; + } +- else if (hints.stills) ++ else if (hints.stills && hints.dvd) + return false; + + #ifdef DUMP_STREAM +@@ -468,24 +491,25 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + #endif + + m_hints = hints; +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "Let's decode with iMX VPU\n"); ++ CLog::Log(LOGVIDEO, "Let's decode with iMX VPU\n"); ++ ++ int param = 0; ++ SetVPUParams(VPU_DEC_CONF_INPUTTYPE, ¶m); ++ SetVPUParams(VPU_DEC_CONF_SKIPMODE, ¶m); + + #ifdef MEDIAINFO +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: fpsrate %d / fpsscale %d\n", m_hints.fpsrate, m_hints.fpsscale); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: CodecID %d \n", m_hints.codec); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: StreamType %d \n", m_hints.type); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Level %d \n", m_hints.level); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Profile %d \n", m_hints.profile); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: PTS_invalid %d \n", m_hints.ptsinvalid); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag %d \n", m_hints.codec_tag); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %dx%d \n", m_hints.width, m_hints.height); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: fpsrate %d / fpsscale %d\n", m_hints.fpsrate, m_hints.fpsscale); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: CodecID %d \n", m_hints.codec); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: StreamType %d \n", m_hints.type); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: Level %d \n", m_hints.level); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: Profile %d \n", m_hints.profile); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: PTS_invalid %d \n", m_hints.ptsinvalid); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: Tag %d \n", m_hints.codec_tag); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: %dx%d \n", m_hints.width, m_hints.height); + } +- { uint8_t *pb = (uint8_t*)&m_hints.codec_tag; +- if ((isalnum(pb[0]) && isalnum(pb[1]) && isalnum(pb[2]) && isalnum(pb[3])) && g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag fourcc %c%c%c%c\n", pb[0], pb[1], pb[2], pb[3]); ++ { char str_tag[128]; av_get_codec_tag_string(str_tag, sizeof(str_tag), m_hints.codec_tag); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: Tag fourcc %s\n", str_tag); + } + if (m_hints.extrasize) + { +@@ -494,18 +518,13 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + for (unsigned int i=0; i < m_hints.extrasize; i++) + sprintf(buf+i*2, "%02x", ((uint8_t*)m_hints.extradata)[i]); + +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: extradata %d %s\n", m_hints.extrasize, buf); +- } +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- { +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %d / %d \n", m_hints.width, m_hints.height); +- CLog::Log(LOGDEBUG, "Decode: aspect %f - forced aspect %d\n", m_hints.aspect, m_hints.forced_aspect); ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: extradata %d %s\n", m_hints.extrasize, buf); + } ++ CLog::Log(LOGVIDEO, "Decode: MEDIAINFO: %d / %d \n", m_hints.width, m_hints.height); ++ CLog::Log(LOGVIDEO, "Decode: aspect %f - forced aspect %d\n", m_hints.aspect, m_hints.forced_aspect); + #endif + + m_warnOnce = true; +- m_convert_bitstream = false; + switch(m_hints.codec) + { + case AV_CODEC_ID_MPEG1VIDEO: +@@ -524,8 +543,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + case AV_CODEC_ID_H264: + { + // Test for VPU unsupported profiles to revert to sw decoding +- if ((m_hints.profile == 110) || //hi10p +- (m_hints.profile == 578 && m_hints.level == 30)) //quite uncommon h264 profile with Main 3.0 ++ if (m_hints.profile == 110) + { + CLog::Log(LOGNOTICE, "i.MX6 VPU is not able to decode AVC profile %d level %d", m_hints.profile, m_hints.level); + return false; +@@ -536,8 +554,16 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + { + if ( *(char*)hints.extradata == 1 ) + { +- m_converter = new CBitstreamConverter(); +- m_convert_bitstream = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); ++ m_converter = new CBitstreamConverter(); ++ if (!m_converter->Open(hints.codec, (uint8_t *)m_hints.extradata, m_hints.extrasize, true)) ++ { ++ SAFE_DELETE(m_converter); ++ break; ++ } ++ std::free(m_hints.extradata); ++ m_hints.extrasize = m_converter->GetExtraSize(); ++ m_hints.extradata = std::malloc(m_hints.extrasize); ++ std::memcpy(m_hints.extradata, m_converter->GetExtraData(), m_hints.extrasize); + } + } + break; +@@ -570,6 +596,12 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + switch(m_hints.codec_tag) + { + case _4CC('D','I','V','X'): ++ // Test for VPU unsupported profiles to revert to sw decoding ++ if (m_hints.profile == -99 && m_hints.level == -99) ++ { ++ CLog::Log(LOGNOTICE, "i.MX6 iMX-divx4 profile %d level %d - sw decoding", m_hints.profile, m_hints.level); ++ return false; ++ } + m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX4 + m_pFormatName = "iMX-divx4"; + break; +@@ -598,7 +630,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + return true; + } + +-void CDVDVideoCodecIMX::Dispose() ++void CIMXCodec::Dispose() + { + #ifdef DUMP_STREAM + if (m_dump) +@@ -608,66 +640,29 @@ void CDVDVideoCodecIMX::Dispose() + } + #endif + +- g_IMXContext.Clear(); +- + VpuDecRetCode ret; + bool VPU_loaded = m_vpuHandle; + +- // Release last buffer +- SAFE_RELEASE(m_lastBuffer); +- SAFE_RELEASE(m_currentBuffer); +- +- Enter(); +- +- // Invalidate output buffers to prevent the renderer from mapping this memory +- for (int i=0; iReleaseFramebuffer(&m_vpuHandle); +- SAFE_RELEASE(m_outputBuffers[i]); +- } +- +- Leave(); ++ RecycleFrameBuffers(); + + if (m_vpuHandle) + { +- ret = VPU_DecFlushAll(m_vpuHandle); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); +- } + ret = VPU_DecClose(m_vpuHandle); + if (ret != VPU_DEC_RET_SUCCESS) +- { + CLog::Log(LOGERROR, "%s - VPU close failed with error code %d.\n", __FUNCTION__, ret); +- } +- m_vpuHandle = 0; +- } +- +- m_frameCounter = 0; ++ else ++ CLog::Log(LOGVIDEO, "%s - VPU closed.", __FUNCTION__); + +- // Release memory +- if (m_outputBuffers != NULL) +- { +- delete m_outputBuffers; +- m_outputBuffers = NULL; ++ m_vpuHandle = 0; + } + + VpuFreeBuffers(); +- m_vpuFrameBufferNum = 0; +- +- if (m_vpuFrameBuffers != NULL) +- { +- delete m_vpuFrameBuffers; +- m_vpuFrameBuffers = NULL; +- } + + if (VPU_loaded) + { + ret = VPU_DecUnLoad(); + if (ret != VPU_DEC_RET_SUCCESS) +- { + CLog::Log(LOGERROR, "%s - VPU unload failed with error code %d.\n", __FUNCTION__, ret); +- } + } + + if (m_converter) +@@ -675,620 +670,539 @@ void CDVDVideoCodecIMX::Dispose() + m_converter->Close(); + SAFE_DELETE(m_converter); + } ++} + +- return; ++void CIMXCodec::SetVPUParams(VpuDecConfig InDecConf, void* pInParam) ++{ ++ if (m_vpuHandle) ++ if (VPU_DEC_RET_SUCCESS != VPU_DecConfig(m_vpuHandle, InDecConf, pInParam)) ++ CLog::Log(LOGERROR, "%s - iMX VPU set dec param failed (%d).\n", __FUNCTION__, (int)InDecConf); + } + +-int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) ++void CIMXCodec::SetDrainMode(VpuDecInputType drain) + { +- VpuDecFrameLengthInfo frameLengthInfo; +- VpuBufferNode inData; +- VpuDecRetCode ret; +- int decRet = 0; +- int retStatus = 0; +- int demuxer_bytes = iSize; +- uint8_t *demuxer_content = pData; +- int retries = 0; +- int idx; ++ if (m_drainMode == drain) ++ return; + +-#ifdef IMX_PROFILE +- static unsigned long long previous, current; +-#endif +-#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) +- unsigned long long before_dec; +-#endif ++ m_drainMode = drain; ++ VpuDecInputType config = drain == IN_DECODER_SET ? VPU_DEC_IN_DRAIN : drain; ++ SetVPUParams(VPU_DEC_CONF_INPUTTYPE, &config); ++ if (drain == VPU_DEC_IN_DRAIN && !EOS()) ++ ProcessSignals(SIGNAL_SIGNAL); ++} + +-#ifdef DUMP_STREAM +- if (m_dump != NULL) ++void CIMXCodec::SetSkipMode(VpuDecSkipMode skip) ++{ ++ if (m_skipMode == skip) ++ return; ++ ++ m_skipMode = skip; ++ VpuDecSkipMode config = skip == IN_DECODER_SET ? VPU_DEC_SKIPB : skip; ++ SetVPUParams(VPU_DEC_CONF_SKIPMODE, &config); ++} ++ ++bool CIMXCodec::GetCodecStats(double &pts, int &droppedFrames, int &skippedPics) ++{ ++ droppedFrames = m_dropped; ++ skippedPics = -1; ++ m_dropped = 0; ++ pts = m_lastPTS; ++ return true; ++} ++ ++void CIMXCodec::SetCodecControl(int flags) ++{ ++ if (!FBRegistered()) ++ return; ++ ++ m_codecControlFlags = flags; ++ ++ //SetSkipMode(m_codecControlFlags & DVD_CODEC_CTRL_DROP ? VPU_DEC_ISEARCH : VPU_DEC_SKIPNONE); ++ SetDrainMode(m_codecControlFlags & DVD_CODEC_CTRL_DRAIN && !m_decInput.size() ? VPU_DEC_IN_DRAIN : VPU_DEC_IN_NORMAL); ++} ++ ++bool CIMXCodec::getOutputFrame(VpuDecOutFrameInfo *frm) ++{ ++ VpuDecRetCode ret = VPU_DecGetOutputFrame(m_vpuHandle, frm); ++ if(VPU_DEC_RET_SUCCESS != ret) ++ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); ++ return ret == VPU_DEC_RET_SUCCESS; ++} ++ ++int CIMXCodec::Decode(BYTE *pData, int iSize, double dts, double pts) ++{ ++ if (EOS() && m_drainMode && !m_decOutput.size()) ++ return VC_BUFFER; ++ ++ int ret = 0; ++ if (!g_IMXCodec->IsRunning()) + { +- if (pData) ++ static double pattern; ++ if (!m_decInput.full()) ++ { ++ ret |= VC_BUFFER; ++ if (dts != DVD_NOPTS_VALUE) ++ { ++ static double last; ++ if (last != 0.0) ++ pattern = (pattern + dts - last) / 2; ++ last = dts; ++ } ++ } ++ else + { +- fwrite(&dts, sizeof(double), 1, m_dump); +- fwrite(&pts, sizeof(double), 1, m_dump); +- fwrite(&iSize, sizeof(int), 1, m_dump); +- fwrite(pData, 1, iSize, m_dump); ++ if (pattern > 0.01) ++ m_fps = (double)DVD_TIME_BASE/pattern; ++ else ++ m_fps = m_hints.fpsscale ? (double)m_hints.fpsrate / m_hints.fpsscale : 60; ++ m_decOpenParam.nMapType = 1; ++ ++ g_IMXCodec->Create(); ++ g_IMXCodec->WaitStartup(); + } + } +-#endif + +- SAFE_RELEASE(m_currentBuffer); ++ if (pData) ++ m_decInput.push(new VPUTask({ pData, iSize, 0, 0, 0, pts, dts, 0, 0 }, m_converter)); + +- if (!m_vpuHandle) ++ if (!IsDraining() && ++ (m_decInput.size() < m_decInput.getquotasize() -1)) + { +- VpuOpen(); +- if (!m_vpuHandle) +- return VC_ERROR; ++ ret |= VC_BUFFER; ++ if (!(m_codecControlFlags & DVD_CODEC_CTRL_HURRY) && (m_decInput.size() < m_decInput.getquotasize() /2)) ++ return ret; + } + +- for (int i=0; i < m_vpuFrameBufferNum; i++) ++ if ((m_decOutput.size() >= m_decOutput.getquotasize() /2 || ++ m_drainMode || (m_codecControlFlags & DVD_CODEC_CTRL_HURRY)) && m_decOutput.size()) ++ ret |= VC_PICTURE; ++ ++#ifdef IMX_PROFILE ++ CLog::Log(LOGVIDEO, "%s - demux size: %d dts : %f - pts : %f - addr : 0x%x, return %d ===== in/out %d/%d =====\n", ++ __FUNCTION__, iSize, recalcPts(dts), recalcPts(pts), (uint)pData, ret, m_decInput.size(), m_decOutput.size()); ++#endif ++ ++ if (!ret || m_drainMode) ++ Sleep(5); ++ ++ return ret; ++} ++ ++void CIMXCodec::ReleaseFramebuffer(VpuFrameBuffer* fb) ++{ ++ m_recycleBuffers.push_back(fb); ++} ++ ++void CIMXCodec::RecycleFrameBuffers() ++{ ++ while(!m_recycleBuffers.empty()) + { +- if (m_outputBuffers[i]->Rendered()) +- { +- ret = m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); +- if(ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); +- } +- } ++ m_pts[m_recycleBuffers.front()] = DVD_NOPTS_VALUE; ++ VPU_DecOutFrameDisplayed(m_vpuHandle, m_recycleBuffers.front()); ++ m_recycleBuffers.pop_front(); + } ++} ++ ++inline ++void CIMXCodec::AddExtraData(VpuBufferNode *bn, bool force) ++{ ++ if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || ++ (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| ++ (m_decOpenParam.CodecFormat == VPU_V_XVID) || ++ (force)) ++ bn->sCodecData = { (unsigned char *)m_hints.extradata, m_hints.extrasize }; ++ else ++ bn->sCodecData = { nullptr, 0 }; ++} + ++void CIMXCodec::Process() ++{ ++ VpuDecFrameLengthInfo frameLengthInfo; ++ VpuBufferNode inData; ++ VpuBufferNode dummy; ++ VpuDecRetCode ret; ++ int retStatus; ++ VPUTask *task = nullptr; + #ifdef IMX_PROFILE +- current = XbmcThreads::SystemClockMillis(); +- CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); +- previous = current; ++ static unsigned long long previous, current; ++ int freeInfo; + #endif + +- if ((pData && iSize) || +- (m_bytesToBeConsumed)) ++ m_threadID = GetCurrentThreadId(); ++ ++ m_recycleBuffers.clear(); ++ m_pts.clear(); ++ m_loaded.Set(); ++ ++ memset(&dummy, 0, sizeof(dummy)); ++ AddExtraData(&dummy); ++ inData = dummy; ++ ++ VpuOpen(); ++ ++ while (!m_bStop && m_vpuHandle) + { +- //printf("D %f %d\n", pts, iSize); +- if ((m_convert_bitstream) && (iSize)) +- { +- // convert demuxer packet from bitstream to bytestream (AnnexB) +- if (m_converter->Convert(demuxer_content, demuxer_bytes)) +- { +- demuxer_content = m_converter->GetConvertBuffer(); +- demuxer_bytes = m_converter->GetConvertSize(); +- } +- else +- CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); +- } ++ RecycleFrameBuffers(); ++ SAFE_DELETE(task); ++ if (!(task = m_decInput.pop())) ++ task = new VPUTask(); ++ ++#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) ++ unsigned long long before_dec; ++#ifdef IMX_PROFILE ++ current = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGVIDEO, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f - addr : 0x%x\n", ++ __FUNCTION__, current - previous, task->demux.iSize, recalcPts(task->demux.dts), recalcPts(task->demux.pts), (uint)task->demux.pData); ++ previous = current; ++#endif ++#endif + +- inData.nSize = demuxer_bytes; ++ inData.nSize = task->demux.iSize; + inData.pPhyAddr = NULL; +- inData.pVirAddr = demuxer_content; +- if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || +- (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| +- (m_decOpenParam.CodecFormat == VPU_V_XVID)) +- { +- inData.sCodecData.pData = (unsigned char *)m_hints.extradata; +- inData.sCodecData.nSize = m_hints.extrasize; +- } +- else +- { +- inData.sCodecData.pData = NULL; +- inData.sCodecData.nSize = 0; +- } ++ inData.pVirAddr = task->demux.pData; ++ ++ // some streams have problem with getting intial info after seek into (during playback start). ++ // feeding VPU with extra data helps ++ if (!m_vpuFrameBuffers.size() && m_converter && !task->IsEmpty() && m_decRet & VPU_DEC_NO_ENOUGH_INBUF) ++ AddExtraData(&inData, true); + + #ifdef IMX_PROFILE_BUFFERS + static unsigned long long dec_time = 0; + #endif + +- while (true) // Decode as long as the VPU consumes data ++ while (!m_bStop) // Decode as long as the VPU consumes data + { ++ RecycleFrameBuffers(); ++ ProcessSignals(); ++ ++ retStatus = m_decRet & VPU_DEC_SKIP ? VC_USERDATA : 0; ++ + #if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) + before_dec = XbmcThreads::SystemClockMillis(); + #endif +- if (m_frameReported) +- m_bytesToBeConsumed += inData.nSize; +- +- ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); ++ ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &m_decRet); + #ifdef IMX_PROFILE_BUFFERS + unsigned long long dec_single_call = XbmcThreads::SystemClockMillis()-before_dec; + dec_time += dec_single_call; + #endif + #ifdef IMX_PROFILE +- CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec); ++ VPU_DecGetNumAvailableFrameBuffers(m_vpuHandle, &freeInfo); ++ CLog::Log(LOGVIDEO, "%s - VPU ret %d dec 0x%x decode takes : %lld free: %d\n\n", __FUNCTION__, ret, m_decRet, XbmcThreads::SystemClockMillis() - before_dec, freeInfo); + #endif + +- if (ret == VPU_DEC_RET_WRONG_CALL_SEQUENCE && +- decRet & VPU_DEC_RESOLUTION_CHANGED) +- { +- VpuFreeBuffers(); +- } +- else if (ret != VPU_DEC_RET_SUCCESS) ++ if (m_drainMode == IN_DECODER_SET) + { +- CLog::Log(LOGERROR, "%s - VPU decode failed with error code %d (0x%x).\n", __FUNCTION__, ret, decRet); +- goto out_error; ++ AddExtraData(&inData); ++ SetDrainMode(VPU_DEC_IN_NORMAL); + } + +- if (decRet & VPU_DEC_INIT_OK || decRet & VPU_DEC_RESOLUTION_CHANGED) +- // VPU decoding init OK : We can retrieve stream info +- { +- ret = VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo); +- if (ret == VPU_DEC_RET_SUCCESS) +- { +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- { +- CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ +- " - Align : %d bytes - crop : %d %d %d %d - Q16Ratio : %x\n", __FUNCTION__, +- m_initInfo.nPicWidth, m_initInfo.nPicHeight, m_initInfo.nInterlace, m_initInfo.nMinFrameBufferCount, +- m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, +- m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio); +- } +- if (VpuAllocFrameBuffers()) +- { +- ret = VPU_DecRegisterFrameBuffer(m_vpuHandle, m_vpuFrameBuffers, m_vpuFrameBufferNum); +- if (ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - VPU error while registering frame buffers (%d).\n", __FUNCTION__, ret); +- goto out_error; +- } +- } +- else +- { +- goto out_error; +- } ++ if (m_decRet & VPU_DEC_OUTPUT_EOS) ++ break; + +- } +- else +- { +- CLog::Log(LOGERROR, "%s - VPU get initial info failed (%d).\n", __FUNCTION__, ret); +- goto out_error; +- } +- } //VPU_DEC_INIT_OK ++ if (ret != VPU_DEC_RET_SUCCESS && ret != VPU_DEC_RET_FAILURE_TIMEOUT) ++ ExitError("VPU decode failed with error code %d (0x%x).\n", ret, m_decRet); + +- if (decRet & VPU_DEC_ONE_FRM_CONSUMED) ++ if (m_decRet & VPU_DEC_INIT_OK || m_decRet & VPU_DEC_RESOLUTION_CHANGED) ++ // VPU decoding init OK : We can retrieve stream info + { +- ret = VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo); +- if (ret != VPU_DEC_RET_SUCCESS) ++ m_decOutput.setquotasize(1); ++ if (m_decRet & VPU_DEC_RESOLUTION_CHANGED && m_decOutput.size()) + { +- CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); ++ int returning = m_decOutput.size() + RENDER_QUEUE_SIZE; ++ while (m_recycleBuffers.size() < returning) ++ std::this_thread::yield(); + } +- m_bytesToBeConsumed -= (frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength); +- if (frameLengthInfo.pFrame) ++ ++ if (VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo) != VPU_DEC_RET_SUCCESS) ++ ExitError("VPU get initial info failed"); ++ ++ CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ ++ " - Align : %d bytes - crop : %d %d %d %d - Q16Ratio : %x\n", __FUNCTION__, ++ m_initInfo.nPicWidth, m_initInfo.nPicHeight, m_initInfo.nInterlace, m_initInfo.nMinFrameBufferCount, ++ m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, ++ m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio); ++ ++ if (!VpuFreeBuffers(false) || !VpuAllocFrameBuffers()) ++ ExitError("VPU error while registering frame buffers"); ++ ++ if (m_initInfo.nInterlace && m_fps >= 50 && !m_converter && m_decOpenParam.nMapType == 1) + { +- idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); +- if (m_bytesToBeConsumed < 50) +- m_bytesToBeConsumed = 0; +- if (idx != -1) +- { +- if (m_previousPts != DVD_NOPTS_VALUE) +- { +- m_outputBuffers[idx]->SetPts(m_previousPts); +- m_previousPts = DVD_NOPTS_VALUE; +- } +- else +- m_outputBuffers[idx]->SetPts(pts); +- } +- else +- CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); ++ m_decOpenParam.nMapType = 0; ++ Dispose(); ++ VpuOpen(); ++ continue; + } +- } //VPU_DEC_ONE_FRM_CONSUMED + +- if (decRet & VPU_DEC_OUTPUT_DIS) +- // Frame ready to be displayed +- { +- if (retStatus & VC_PICTURE) +- CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); ++ m_decInput.setquotasize(m_initInfo.nMinFrameBufferCount*7); + +- ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); +- if(ret != VPU_DEC_RET_SUCCESS) ++ if (m_decOpenParam.CodecFormat != VPU_V_MPEG2) + { +- CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); +- goto out_error; ++ SetDrainMode((VpuDecInputType)IN_DECODER_SET); ++ inData = dummy; ++ continue; + } ++ } ++ ++ if (m_decRet & VPU_DEC_ONE_FRM_CONSUMED) ++ if (!VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo) && frameLengthInfo.pFrame) ++ m_pts[frameLengthInfo.pFrame] = task->demux.pts; + ++ if (m_decRet & CLASS_PICTURE && getOutputFrame(&m_frameInfo)) ++ { + // Some codecs (VC1?) lie about their frame size (mod 16). Adjust... + m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); + m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); + +- idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); +- if (idx != -1) +- { +- CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ CDVDVideoCodecIMXBuffer *buffer = new CDVDVideoCodecIMXBuffer(&m_frameInfo, m_fps, m_decOpenParam.nMapType); + +- /* quick & dirty fix to get proper timestamping for VP8 codec */ +- if (m_decOpenParam.CodecFormat == VPU_V_VP8) +- buffer->SetPts(pts); ++ /* quick & dirty fix to get proper timestamping for VP8 codec */ ++ if (m_decOpenParam.CodecFormat == VPU_V_VP8) ++ buffer->SetPts(task->demux.pts); ++ else ++ buffer->SetPts(m_pts[m_frameInfo.pDisplayFrameBuf]); + +- buffer->Lock(); +- buffer->SetDts(dts); +- buffer->Queue(&m_frameInfo, m_lastBuffer); ++ buffer->SetDts(task->demux.dts); + + #ifdef IMX_PROFILE_BUFFERS +- CLog::Log(LOGNOTICE, "+D %f %lld\n", buffer->GetPts(), dec_time); +- dec_time = 0; ++ CLog::Log(LOGVIDEO, "+D %f %lld\n", recalcPts(buffer->GetPts()), dec_time); ++ dec_time = 0; + #endif +- + #ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, dts, pts); +- CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, buffer->GetDts(), buffer->GetPts()); ++ CLog::Log(LOGVIDEO, "+ 0x%x dts %f pts %f (VPU)\n", buffer->GetIdx(), recalcPts(task->demux.dts), recalcPts(buffer->GetPts())); + #endif + +- if (!m_usePTS) +- { +- buffer->SetPts(DVD_NOPTS_VALUE); +- buffer->SetDts(DVD_NOPTS_VALUE); +- } +- +- // Save last buffer +- SAFE_RELEASE(m_lastBuffer); +- m_lastBuffer = buffer; +- m_lastBuffer->Lock(); +- + #ifdef IMX_PROFILE_BUFFERS +- static unsigned long long lastD = 0; +- unsigned long long current = XbmcThreads::SystemClockMillis(), tmp; +- CLog::Log(LOGNOTICE, "+V %f %lld\n", buffer->GetPts(), current-lastD); +- lastD = current; ++ static unsigned long long lastD = 0; ++ unsigned long long current = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGVIDEO, "+V %f %lld\n", recalcPts(buffer->GetPts()), current-lastD); ++ lastD = current; + #endif + +- m_currentBuffer = buffer; ++ if (m_decRet & VPU_DEC_OUTPUT_DIS) ++ buffer->SetFlags(DVP_FLAG_ALLOCATED); + +- if (m_currentBuffer) +- { +- retStatus |= VC_PICTURE; +- } +- } +- } //VPU_DEC_OUTPUT_DIS ++ if (!m_decOutput.push(buffer)) ++ SAFE_RELEASE(buffer); ++ else ++ m_lastPTS = buffer->GetPts(); + +- // According to libfslvpuwrap: If this flag is set then the frame should +- // be dropped. It is just returned to gather decoder information but not +- // for display. +- else if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS) +- { +- ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); +- if(ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); +- goto out_error; +- } ++ } ++ else if (m_decRet & CLASS_DROP) ++ m_dropped++; + +- // Display frame +- ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); +- if(ret != VPU_DEC_RET_SUCCESS) +- { +- CLog::Log(LOGERROR, "%s: VPU Clear frame display failure(%d)\n",__FUNCTION__,ret); +- goto out_error; +- } +- } //VPU_DEC_OUTPUT_MOSAIC_DIS ++ if (m_decRet & VPU_DEC_SKIP) ++ m_dropped++; + +- else if (decRet & VPU_DEC_OUTPUT_REPEAT) +- { +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); +- m_dropState = true; +- } +- else if (decRet & VPU_DEC_NO_ENOUGH_BUF) ++ if (m_decRet & VPU_DEC_NO_ENOUGH_BUF && m_decOutput.size()) + { +- CLog::Log(LOGERROR, "%s - No frame buffer available.\n", __FUNCTION__); +- } +- else if (decRet & VPU_DEC_SKIP) +- { +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); +- } +- else if (decRet & VPU_DEC_FLUSH) +- { +- CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); +- Reset(); +- retStatus = VC_FLUSHED; +- } +- else if (decRet & VPU_DEC_OUTPUT_EOS) +- { +- CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); ++ m_decOutput.pop()->Release(); ++ FlushVPU(); ++ continue; + } + +- if (decRet & (VPU_DEC_NO_ENOUGH_INBUF | +- VPU_DEC_OUTPUT_REPEAT | VPU_DEC_OUTPUT_DIS)) +- { +- // We are done with VPU decoder that time +- break; +- } ++ ProcessSignals(); + +- retries++; +- if (retries >= m_maxVpuDecodeLoops) +- { +- CLog::Log(LOGERROR, "%s - Leaving VPU decoding loop after %d iterations\n", __FUNCTION__, m_maxVpuDecodeLoops); ++ if (retStatus & VC_USERDATA) ++ continue; ++ ++ if (m_decRet & CLASS_FORCEBUF) + break; +- } + +- if (!(decRet & VPU_DEC_INPUT_USED)) +- { +- CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); +- } ++ if (!(m_drainMode || ++ m_decRet & (CLASS_NOBUF | CLASS_DROP))) ++ break; + +- // Let's process again as VPU_DEC_NO_ENOUGH_INBUF was not set +- // and we don't have an image ready if we reach that point +- inData.pVirAddr = NULL; +- inData.nSize = 0; ++ inData = dummy; + } // Decode loop +- } //(pData && iSize) + +- if (!retStatus) +- retStatus |= VC_BUFFER; +- +- if (m_bytesToBeConsumed > 0) +- { +- // Remember the current pts because the data which has just +- // been sent to the VPU has not yet been consumed. +- // This pts is related to the frame that will be consumed +- // at next call... +- m_previousPts = pts; +- } +- +-#ifdef IMX_PROFILE +- CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); +-#endif +- return retStatus; ++ task->Release(); ++ } // Process() main loop + +-out_error: +- return VC_ERROR; ++ ProcessSignals(SIGNAL_RESET | SIGNAL_DISPOSE); + } + +-void CDVDVideoCodecIMX::Reset() ++void CIMXCodec::ProcessSignals(int signal) + { +- int ret; +- +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); ++ if (signal & SIGNAL_SIGNAL) ++ { ++ m_decInput.signal(); ++ m_decOutput.signal(); ++ } ++ if (!(m_decSignal | signal)) ++ return; + +- // Release last buffer +- SAFE_RELEASE(m_lastBuffer); +- SAFE_RELEASE(m_currentBuffer); ++ CSingleLock lk(m_signalLock); ++ m_decSignal |= signal & ~SIGNAL_SIGNAL; + +- // Invalidate all buffers +- for(int i=0; i < m_vpuFrameBufferNum; i++) +- m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); ++ if (!IsCurrentThread()) ++ return; + +- m_frameCounter = 0; +- m_bytesToBeConsumed = 0; +- m_previousPts = DVD_NOPTS_VALUE; ++ int process = m_decSignal; ++ m_decSignal = 0; + +- // Flush VPU +- ret = VPU_DecFlushAll(m_vpuHandle); +- if (ret != VPU_DEC_RET_SUCCESS) ++ if (process & SIGNAL_FLUSH) + { +- CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); ++ FlushVPU(); ++ m_queuesLock.unlock(); + } ++ if (process & SIGNAL_RESET) ++ DisposeDecQueues(); ++ if (process & SIGNAL_DISPOSE) ++ Dispose(); + } + +-unsigned CDVDVideoCodecIMX::GetAllowedReferences() ++void CIMXCodec::FlushVPU() + { +- return RENDER_QUEUE_SIZE; ++ int ret = VPU_DecFlushAll(m_vpuHandle); ++ if (ret != VPU_DEC_RET_SUCCESS && ret != VPU_DEC_RET_INVALID_HANDLE) ++ CLog::Log(LOGERROR, "%s: VPU flush failed with error code %d.\n", __FUNCTION__, ret); + } + +-bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++inline ++void CIMXCodec::ExitError(const char *msg, ...) + { +- if (pDvdVideoPicture) +- { +- SAFE_RELEASE(pDvdVideoPicture->IMXBuffer); +- } ++ va_list va; ++ va_start(va, msg); ++ CLog::Log(LOGERROR, "%s: %s", __FUNCTION__, StringUtils::FormatV(msg, va).c_str()); ++ va_end(va); + +- return true; ++ StopThread(false); + } + +-bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) ++bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + { ++ pDvdVideoPicture->IMXBuffer = m_decOutput.pop(); ++ assert(pDvdVideoPicture->IMXBuffer); ++ + #ifdef IMX_PROFILE + static unsigned int previous = 0; + unsigned int current; + + current = XbmcThreads::SystemClockMillis(); +- CLog::Log(LOGDEBUG, "%s tm:%03d\n", __FUNCTION__, current - previous); ++ CLog::Log(LOGDEBUG | LOGVIDEO, "+G 0x%x %f/%f tm:%03d : Interlaced 0x%x\n", pDvdVideoPicture->IMXBuffer->GetIdx(), ++ recalcPts(pDvdVideoPicture->IMXBuffer->GetDts()), recalcPts(pDvdVideoPicture->IMXBuffer->GetPts()), current - previous, ++ m_initInfo.nInterlace ? pDvdVideoPicture->IMXBuffer->GetFieldType() : 0); + previous = current; + #endif + +- if (m_dropState) +- { +- pDvdVideoPicture->iFlags = DVP_FLAG_DROPPED; +- m_dropState = false; +- } +- +- if (m_frameCounter++ && pDvdVideoPicture->iFlags == DVP_FLAG_DROPPED) +- { +- SAFE_RELEASE(m_currentBuffer); +- return true; +- } +- +- pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; ++ pDvdVideoPicture->iFlags = pDvdVideoPicture->IMXBuffer->GetFlags(); + + if (m_initInfo.nInterlace) + { +- if (m_currentBuffer->GetFieldType() == VPU_FIELD_NONE && m_warnOnce) ++ if (pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_NONE && m_warnOnce) + { + m_warnOnce = false; + CLog::Log(LOGWARNING, "Interlaced content reported by VPU, but full frames detected - Please turn off deinterlacing manually."); + } +- else if (m_currentBuffer->GetFieldType() == VPU_FIELD_TB || m_currentBuffer->GetFieldType() == VPU_FIELD_TOP) ++ else if (pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_TB || pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_TOP) + pDvdVideoPicture->iFlags |= DVP_FLAG_TOP_FIELD_FIRST; + + pDvdVideoPicture->iFlags |= DVP_FLAG_INTERLACED; + } + + pDvdVideoPicture->format = RENDER_FMT_IMXMAP; +- pDvdVideoPicture->iWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; +- pDvdVideoPicture->iHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; ++ pDvdVideoPicture->iWidth = pDvdVideoPicture->IMXBuffer->m_pctWidth; ++ pDvdVideoPicture->iHeight = pDvdVideoPicture->IMXBuffer->m_pctHeight; + + pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + +- // Current buffer is locked already -> hot potato +- pDvdVideoPicture->pts = m_currentBuffer->GetPts(); +- pDvdVideoPicture->dts = m_currentBuffer->GetDts(); ++ pDvdVideoPicture->pts = pDvdVideoPicture->IMXBuffer->GetPts(); ++ pDvdVideoPicture->dts = pDvdVideoPicture->IMXBuffer->GetDts(); + +- pDvdVideoPicture->IMXBuffer = m_currentBuffer; +- m_currentBuffer = NULL; ++ if (pDvdVideoPicture->iFlags & DVP_FLAG_DROPPED) ++ SAFE_RELEASE(pDvdVideoPicture->IMXBuffer); + + return true; + } + +-void CDVDVideoCodecIMX::SetDropState(bool bDrop) ++void CIMXCodec::SetDropState(bool bDrop) + { + return; +- // We are fast enough to continue to really decode every frames +- // and avoid artefacts... +- // (Of course these frames won't be rendered but only decoded) +- + if (bDrop) + { +-#ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "%s : %d\n", __FUNCTION__, bDrop); +-#endif ++ if (m_decOutput.size() && !m_bStop) ++ { ++ m_decOutput.pop()->Release(); ++ ++m_dropped; ++ } ++ else if (m_skipMode < 1 && m_speed != DVD_PLAYSPEED_PAUSE) ++ SetSkipMode((VpuDecSkipMode)IN_DECODER_SET); + } + } + +-void CDVDVideoCodecIMX::Enter() ++bool CIMXCodec::IsCurrentThread() const + { +- m_codecBufferLock.lock(); ++ return CThread::IsCurrentThread(m_threadID); + } + +-void CDVDVideoCodecIMX::Leave() ++std::string CIMXCodec::GetPlayerInfo() + { +- m_codecBufferLock.unlock(); ++ std::ostringstream s; ++ s << "buf In/Out: " << m_decInput.size() << "/" << m_decOutput.size(); ++ return s.str(); + } + + /*******************************************/ +-#ifdef TRACE_FRAMES +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) +- : m_idx(idx) +- , +-#else +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() +- : +-#endif +- m_pts(DVD_NOPTS_VALUE) +- , m_dts(DVD_NOPTS_VALUE) +- , m_frameBuffer(NULL) +- , m_rendered(false) +- , m_previousBuffer(NULL) ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int map) ++ : m_dts(DVD_NOPTS_VALUE) ++ , m_fieldType(frameInfo->eFieldType) ++ , m_frameBuffer(frameInfo->pDisplayFrameBuf) ++ , m_iFlags(DVP_FLAG_DROPPED) ++ , m_convBuffer(nullptr) + { +-} + +-void CDVDVideoCodecIMXBuffer::SetPts(double pts) +-{ +- m_pts = pts; +-} ++ m_pctWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; ++ m_pctHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; ++ iWidth = frameInfo->pExtInfo->nFrmWidth; ++ iHeight = frameInfo->pExtInfo->nFrmHeight; ++ pVirtAddr = m_frameBuffer->pbufVirtY; ++ pPhysAddr = (int)m_frameBuffer->pbufY; + +-void CDVDVideoCodecIMXBuffer::SetDts(double dts) +-{ +- m_dts = dts; ++#ifdef IMX_INPUT_FORMAT_I420 ++ iFormat = _4CC('I', '4', '2', '0'); ++#else ++ iFormat = map == 1 ? _4CC('T', 'N', 'V', 'P'): ++ map == 0 ? _4CC('N', 'V', '1', '2'): ++ _4CC('T', 'N', 'V', 'F'); ++#endif ++ m_fps = fps; ++#ifdef TRACE_FRAMES ++ m_idx = i++; ++#endif ++ Lock(); + } + + void CDVDVideoCodecIMXBuffer::Lock() + { ++ long count = ++m_iRefs; + #ifdef TRACE_FRAMES +- long count = AtomicIncrement(&m_iRefs); +- CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); +-#else +- AtomicIncrement(&m_iRefs); ++ CLog::Log(LOGVIDEO, "R+ 0x%x - ref : %ld (VPU)\n", m_idx, count); + #endif + } + + long CDVDVideoCodecIMXBuffer::Release() + { +- long count = AtomicDecrement(&m_iRefs); ++ long count = --m_iRefs; + #ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "R- %02d - ref : %d (VPU)\n", m_idx, count); ++ CLog::Log(LOGVIDEO, "R- 0x%x - ref : %ld (VPU)\n", m_idx, count); + #endif +- if (count == 2) +- { +- // Only referenced by the codec and its next frame, release the previous +- SAFE_RELEASE(m_previousBuffer); +- } +- else if (count == 1) +- { +- // If count drops to 1 then the only reference is being held by the codec +- // that it can be released in the next Decode call. +- if(m_frameBuffer != NULL) +- { +- m_rendered = true; +- SAFE_RELEASE(m_previousBuffer); +-#ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); +-#endif +- } +- } +- else if (count == 0) +- { +- delete this; +- } +- +- return count; +-} + +-bool CDVDVideoCodecIMXBuffer::IsValid() +-{ +- return m_frameBuffer != NULL; +-} +- +-void CDVDVideoCodecIMXBuffer::BeginRender() +-{ +- CDVDVideoCodecIMX::Enter(); +-} ++ if (count) ++ return count; + +-void CDVDVideoCodecIMXBuffer::EndRender() +-{ +- CDVDVideoCodecIMX::Leave(); +-} ++ CIMXCodec::ReleaseFramebuffer(m_frameBuffer); ++ if (m_convBuffer) ++ g2d_free(m_convBuffer); + +-bool CDVDVideoCodecIMXBuffer::Rendered() const +-{ +- return m_rendered; +-} +- +-void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXBuffer *previous) +-{ +- // No lock necessary because at this time there is definitely no +- // thread still holding a reference +- m_frameBuffer = frameInfo->pDisplayFrameBuf; +- m_rendered = false; +- m_previousBuffer = previous; +- if (m_previousBuffer) +- m_previousBuffer->Lock(); +- +-#ifdef IMX_INPUT_FORMAT_I420 +- iFormat = _4CC('I', '4', '2', '0'); +-#else +- iFormat = _4CC('N', 'V', '1', '2'); +-#endif +- iWidth = frameInfo->pExtInfo->nFrmWidth; +- iHeight = frameInfo->pExtInfo->nFrmHeight; +- pVirtAddr = m_frameBuffer->pbufVirtY; +- pPhysAddr = (int)m_frameBuffer->pbufY; +- m_fieldType = frameInfo->eFieldType; +-} +- +-VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) +-{ +- // Again no lock required because this is only issued after the last +- // external reference was released +- VpuDecRetCode ret = VPU_DEC_RET_FAILURE; +- +- if((m_frameBuffer != NULL) && *handle) +- { +- ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); +- if(ret != VPU_DEC_RET_SUCCESS) +- CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); +- } +-#ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); +-#endif +- m_rendered = false; +- m_frameBuffer = NULL; +- SetPts(DVD_NOPTS_VALUE); +- SAFE_RELEASE(m_previousBuffer); +- +- return ret; ++ delete this; ++ return 0; + } + + CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() + { +- assert(m_iRefs == 0); + #ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); ++ CLog::Log(LOGVIDEO, "~ 0x%x (VPU)\n", m_idx); + #endif + } + +@@ -1304,39 +1218,77 @@ CIMXContext::CIMXContext() + , m_bFbIsConfigured(false) + , m_g2dHandle(NULL) + , m_bufferCapture(NULL) ++ , m_CaptureDone(true) + , m_deviceName("/dev/fb1") + { +- // Limit queue to 2 +- m_input.resize(2); +- m_beginInput = m_endInput = m_bufferedInput = 0; ++ m_input.clear(); ++ m_input.setquotasize(m_fbPages); + m_pageCrops = new CRectInt[m_fbPages]; +- CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); ++ CLog::Log(LOGVIDEO, "iMX : Allocated %d render buffers\n", m_fbPages); + + SetBlitRects(CRectInt(), CRectInt()); + +- // Start the ipu thread ++ g2dOpenDevices(); + Create(); + } + + CIMXContext::~CIMXContext() + { +- StopThread(false); ++ Stop(false); + Dispose(); + CloseDevices(); ++ g2dCloseDevices(); ++} ++ ++bool CIMXContext::GetFBInfo(const std::string &fbdev, struct fb_var_screeninfo *fbVar) ++{ ++ int fb = open(fbdev.c_str(), O_RDONLY, 0); ++ if (fb < 0) ++ { ++ CLog::Log(LOGWARNING, "iMX : Failed to open /dev/fb0\n"); ++ return false; ++ } ++ ++ int err = ioctl(fb, FBIOGET_VSCREENINFO, fbVar); ++ if (err < 0) ++ CLog::Log(LOGWARNING, "iMX : Failed to query variable screen info at %s\n", fbdev.c_str()); ++ ++ close(fb); ++ return err >= 0; + } + ++void CIMXContext::MemMap(struct fb_fix_screeninfo *fb_fix) ++{ ++ if (m_fbVirtAddr && m_fbPhysSize) ++ { ++ munmap(m_fbVirtAddr, m_fbPhysSize); ++ m_fbVirtAddr = NULL; ++ m_fbPhysAddr = 0; ++ } ++ else if (fb_fix) ++ { ++ m_fbLineLength = fb_fix->line_length; ++ m_fbPhysSize = fb_fix->smem_len; ++ m_fbPageSize = m_fbLineLength * m_fbVar.yres_virtual / m_fbPages; ++ m_fbPhysAddr = fb_fix->smem_start; ++ m_fbVirtAddr = (uint8_t*)mmap(0, m_fbPhysSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fbHandle, 0); ++ m_fbCurrentPage = 0; ++ Clear(); ++ } ++} + +-bool CIMXContext::Configure() ++bool CIMXContext::AdaptScreen(bool allocate) + { + +- if(m_ipuHandle) { ++ if(m_ipuHandle) ++ { + close(m_ipuHandle); + m_ipuHandle = 0; + } + + MemMap(); + +- if(!m_fbHandle) ++ if(!m_fbHandle && !OpenDevices()) + goto Err; + + struct fb_var_screeninfo fbVar; +@@ -1345,8 +1297,10 @@ bool CIMXContext::Configure() + + CLog::Log(LOGNOTICE, "iMX : Changing framebuffer parameters\n"); + +- m_fbWidth = fbVar.xres; +- m_fbHeight = fbVar.yres; ++ m_fbWidth = allocate ? 1920 : fbVar.xres; ++ m_fbHeight = allocate ? 1080 : fbVar.yres; ++ ++ m_fbInterlaced = g_graphicsContext.GetResInfo().dwFlags & D3DPRESENTFLAG_INTERLACED; + + if (!GetFBInfo(m_deviceName, &m_fbVar)) + goto Err; +@@ -1354,9 +1308,9 @@ bool CIMXContext::Configure() + m_fbVar.xoffset = 0; + m_fbVar.yoffset = 0; + +- if (m_currentFieldFmt) ++ if (!allocate && (fbVar.bits_per_pixel == 16 || m_currentFieldFmt || m_fbHeight >= 1080 && m_fps >= 49)) + { +- m_fbVar.nonstd = _4CC('U', 'Y', 'V', 'Y'); ++ m_fbVar.nonstd = _4CC('Y', 'U', 'Y', 'V'); + m_fbVar.bits_per_pixel = 16; + } + else +@@ -1367,29 +1321,37 @@ bool CIMXContext::Configure() + m_fbVar.activate = FB_ACTIVATE_NOW; + m_fbVar.xres = m_fbWidth; + m_fbVar.yres = m_fbHeight; +- // One additional line that is required for deinterlacing +- m_fbVar.yres_virtual = (m_fbVar.yres+1) * m_fbPages; ++ ++ if (m_fbInterlaced) ++ m_fbVar.vmode |= FB_VMODE_INTERLACED; ++ else ++ m_fbVar.vmode &= ~FB_VMODE_INTERLACED; ++ ++ m_fbVar.yres_virtual = (m_fbVar.yres + 1) * m_fbPages; + m_fbVar.xres_virtual = m_fbVar.xres; + + Blank(); + + struct fb_fix_screeninfo fb_fix; +- bool bErr; +- +- if ((bErr = ioctl(m_fbHandle, FBIOPUT_VSCREENINFO, &m_fbVar) < 0)) +- CLog::Log(LOGWARNING, "iMX : Failed to setup %s\n", m_deviceName.c_str()); +- else if ((bErr = ioctl(m_fbHandle, FBIOGET_FSCREENINFO, &fb_fix) < 0)) +- CLog::Log(LOGWARNING, "iMX : Failed to query fixed screen info at %s\n", m_deviceName.c_str()); + +- if (bErr) ++ if (ioctl(m_fbHandle, FBIOPUT_VSCREENINFO, &m_fbVar) == -1) ++ { ++ CLog::Log(LOGWARNING, "iMX : Failed to setup %s (%s)\n", m_deviceName.c_str(), strerror(errno)); ++ goto Err; ++ } ++ else if (ioctl(m_fbHandle, FBIOGET_FSCREENINFO, &fb_fix) == -1) ++ { ++ CLog::Log(LOGWARNING, "iMX : Failed to query fixed screen info at %s (%s)\n", m_deviceName.c_str(), strerror(errno)); + goto Err; ++ } + + MemMap(&fb_fix); + +- if (m_currentFieldFmt) ++ if (m_fbVar.bits_per_pixel == 16 || !RENDER_USE_G2D) + m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); + + Unblank(); ++ + return true; + + Err: +@@ -1397,59 +1359,23 @@ Err: + return false; + } + +-bool CIMXContext::GetFBInfo(const std::string &fbdev, struct fb_var_screeninfo *fbVar) +-{ +- int fb = open(fbdev.c_str(), O_RDONLY, 0); +- if (fb < 0) +- { +- CLog::Log(LOGWARNING, "iMX : Failed to open /dev/fb0\n"); +- return false; +- } +- +- int err = ioctl(fb, FBIOGET_VSCREENINFO, fbVar); +- if (err < 0) +- CLog::Log(LOGWARNING, "iMX : Failed to query variable screen info at %s\n", fbdev.c_str()); +- +- close(fb); +- return err >= 0; +-} +- +-void CIMXContext::MemMap(struct fb_fix_screeninfo *fb_fix) +-{ +- if (m_fbVirtAddr && m_fbPhysSize) +- { +- munmap(m_fbVirtAddr, m_fbPhysSize); +- m_fbVirtAddr = NULL; +- m_fbPhysAddr = 0; +- } +- else if (fb_fix) +- { +- m_fbLineLength = fb_fix->line_length; +- m_fbPhysSize = fb_fix->smem_len; +- m_fbPageSize = m_fbLineLength * m_fbVar.yres_virtual / m_fbPages; +- m_fbPhysAddr = fb_fix->smem_start; +- m_fbVirtAddr = (uint8_t*)mmap(0, m_fbPhysSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fbHandle, 0); +- m_fbCurrentPage = 0; +- Clear(); +- } +-} +- + void CIMXContext::OnResetDisplay() + { + CSingleLock lk(m_pageSwapLock); ++ ++ CLog::Log(LOGDEBUG, "iMX : %s - going to change screen parameters\n", __FUNCTION__); + m_bFbIsConfigured = false; +- Configure(); ++ AdaptScreen(); + } + + bool CIMXContext::TaskRestart() + { + CLog::Log(LOGINFO, "iMX : %s - restarting IMX rendererer\n", __FUNCTION__); + // Stop the ipu thread +- StopThread(); ++ Stop(); + MemMap(); + CloseDevices(); + +- // Start the ipu thread + Create(); + return true; + } +@@ -1475,7 +1401,27 @@ bool CIMXContext::OpenDevices() + return m_fbHandle > 0; + } + +-bool CIMXContext::CloseDevices() ++void CIMXContext::g2dOpenDevices() ++{ ++ // open g2d here to ensure all g2d fucntions are called from the same thread ++ if (!g2d_open(&m_g2dHandle)) ++ return; ++ ++ m_g2dHandle = NULL; ++ CLog::Log(LOGERROR, "%s - Error while trying open G2D\n", __FUNCTION__); ++} ++ ++void CIMXContext::g2dCloseDevices() ++{ ++ // close g2d here to ensure all g2d fucntions are called from the same thread ++ if (m_bufferCapture && !g2d_free(m_bufferCapture)) ++ m_bufferCapture = NULL; ++ ++ if (m_g2dHandle && !g2d_close(m_g2dHandle)) ++ m_g2dHandle = NULL; ++} ++ ++void CIMXContext::CloseDevices() + { + CLog::Log(LOGINFO, "iMX : Closing devices\n"); + +@@ -1490,40 +1436,23 @@ bool CIMXContext::CloseDevices() + close(m_ipuHandle); + m_ipuHandle = 0; + } +- +- return true; +-} +- +-bool CIMXContext::GetPageInfo(CIMXBuffer *info, int page) +-{ +- if (page < 0 || page >= m_fbPages) +- return false; +- +- info->iWidth = m_fbWidth; +- info->iHeight = m_fbHeight; +- info->iFormat = m_fbVar.nonstd; +- info->pPhysAddr = m_fbPhysAddr + page*m_fbPageSize; +- info->pVirtAddr = m_fbVirtAddr + page*m_fbPageSize; +- +- return true; + } + + bool CIMXContext::Blank() + { + if (!m_fbHandle) return false; + +- CSingleLock lk(m_pageSwapLock); + m_bFbIsConfigured = false; +- return ioctl(m_fbHandle, FBIOBLANK, 1) == 0; ++ return ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_NORMAL) == 0; + } + + bool CIMXContext::Unblank() + { + if (!m_fbHandle) return false; + +- CSingleLock lk(m_pageSwapLock); ++ int ret = ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_UNBLANK); + m_bFbIsConfigured = true; +- return ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_UNBLANK) == 0; ++ return ret == 0; + } + + bool CIMXContext::SetVSync(bool enable) +@@ -1539,83 +1468,140 @@ void CIMXContext::SetBlitRects(const CRect &srcRect, const CRect &dstRect) + } + + inline +-void CIMXContext::SetFieldData(uint8_t fieldFmt) ++void CIMXContext::SetFieldData(uint8_t fieldFmt, double fps) + { + if (m_bStop || !IsRunning()) + return; + ++ fieldFmt &= -!m_fbInterlaced; ++ ++ bool dr = IsDoubleRate(); + bool deint = !!m_currentFieldFmt; + m_currentFieldFmt = fieldFmt; +- if (!!fieldFmt == deint) ++ ++ if (!!fieldFmt != deint || ++ dr != IsDoubleRate()|| ++ fps != m_fps) ++ m_bFbIsConfigured = false; ++ ++ if (m_bFbIsConfigured) + return; + +- CLog::Log(LOGDEBUG, "iMX : Deinterlacing parameters changed (%s) %s\n", !!fieldFmt ? "active" : "not active", IsDoubleRate() ? "DR" : ""); ++ m_fps = fps; ++ CLog::Log(LOGDEBUG, "iMX : Output parameters changed - deinterlace %s%s, fps: %.3f\n", !!fieldFmt ? "active" : "not active", IsDoubleRate() ? " DR" : "", m_fps); + + CSingleLock lk(m_pageSwapLock); +- m_bFbIsConfigured = false; +- Configure(); ++ AdaptScreen(); + } + +-bool CIMXContext::Blit(int page, CIMXBuffer *source_p, CIMXBuffer *source, uint8_t fieldFmt) ++#define MASK1 (IPU_DEINTERLACE_RATE_FRAME1 | RENDER_FLAG_TOP) ++#define MASK2 (IPU_DEINTERLACE_RATE_FRAME1 | RENDER_FLAG_BOT) ++#define VAL1 MASK1 ++#define VAL2 RENDER_FLAG_BOT ++ ++inline ++bool checkIPUStrideOffset(struct ipu_deinterlace *d) + { +- if (page < 0 || page >= m_fbPages) +- return false; ++ switch (d->motion) ++ { ++ case HIGH_MOTION: ++ return ((d->field_fmt & MASK1) == VAL1) || ((d->field_fmt & MASK2) == VAL2); ++ case MED_MOTION: ++ return ((d->field_fmt & MASK2) == VAL1); ++ default: ++ return true; ++ } ++} + +- IPUTask ipu; ++inline ++int setIPUMotion(bool hasPrev, EINTERLACEMETHOD imethod) ++{ ++ if (hasPrev && imethod == VS_INTERLACEMETHOD_IMX_WEAVE) ++ return LOW_MOTION; ++ else if (hasPrev && imethod >= VS_INTERLACEMETHOD_IMX_ADVMOTION) ++ return MED_MOTION; + +- SetFieldData(fieldFmt); +- PrepareTask(ipu, source_p, source); +- return DoTask(ipu, page); ++ return HIGH_MOTION; + } + +-bool CIMXContext::BlitAsync(CIMXBuffer *source_p, CIMXBuffer *source, uint8_t fieldFmt, CRect *dest) ++void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, uint8_t fieldFmt, int page, CRect *dest) + { +- IPUTask ipu; ++ static int pg; ++ ++ if (likely(page == RENDER_TASK_AUTOPAGE)) ++ page = pg; ++ else if (page == RENDER_TASK_CAPTURE) ++ m_CaptureDone = false; ++ else if (page < 0 && page >= m_fbPages) ++ return; + +- SetFieldData(fieldFmt); ++ pg = ++pg % m_fbPages; ++ ++ IPUTask *ipu = new IPUTask; ++ ++ SetFieldData(fieldFmt, source->m_fps); + PrepareTask(ipu, source_p, source, dest); +- return PushTask(ipu); ++ ++ ipu->page = page; ++#ifdef IMX_PROFILE_BUFFERS ++ unsigned long long before = XbmcThreads::SystemClockMillis(); ++#endif ++ if (!DoTask(ipu)) ++ { ++ delete ipu; ++ return; ++ } ++#ifdef IMX_PROFILE_BUFFERS ++ unsigned long long after = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGVIDEO, "+P 0x%x@%d %d\n", ((CDVDVideoCodecIMXBuffer*)ipu->current)->GetIdx(), ipu->page, (int)(after-before)); ++#endif ++ ++ CSingleLock lk(m_pageSwapLock); ++ if (ipu->task.output.width) ++ m_input.push(ipu); ++ else ++ delete ipu; + } + + bool CIMXContext::PushCaptureTask(CIMXBuffer *source, CRect *dest) + { +- IPUTask ipu; +- m_CaptureDone = false; +- PrepareTask(ipu, NULL, source, dest); +- return PushTask(ipu); ++ Blit(NULL, source, RENDER_TASK_CAPTURE, 0, dest); ++ return true; + } + + bool CIMXContext::ShowPage(int page, bool shift) + { +- if (!m_fbHandle) return false; +- if (page < 0 || page >= m_fbPages) return false; +- if (!m_bFbIsConfigured) return false; ++#if defined(TRACE_FRAMES) && defined(IMX_PROFILE_BUFFERS) ++ unsigned long long pgstart = XbmcThreads::SystemClockMillis(); ++#endif ++ if (!m_fbHandle || !m_bFbIsConfigured) return false; + + // Protect page swapping from screen capturing that does read the current + // front buffer. This is actually not done very frequently so the lock + // does not hurt. ++ + CSingleLock lk(m_pageSwapLock); + ++ m_fbCurrentPage = page; + m_fbVar.activate = FB_ACTIVATE_VBL; +- + m_fbVar.yoffset = (m_fbVar.yres + 1) * page + !shift; + if (ioctl(m_fbHandle, FBIOPAN_DISPLAY, &m_fbVar) < 0) + { + CLog::Log(LOGWARNING, "Panning failed: %s\n", strerror(errno)); + return false; + } +- m_fbCurrentPage = page; + +- // Wait for sync +- if (m_vsync) ++ // Wait for flip ++ if (m_vsync && ioctl(m_fbHandle, FBIO_WAITFORVSYNC, 0) < 0) + { +- if (ioctl(m_fbHandle, FBIO_WAITFORVSYNC, 0) < 0) +- { +- CLog::Log(LOGWARNING, "Vsync failed: %s\n", strerror(errno)); +- return false; +- } ++ CLog::Log(LOGWARNING, "Vsync failed: %s\n", strerror(errno)); ++ return false; + } + ++#if defined(TRACE_FRAMES) && defined(IMX_PROFILE_BUFFERS) ++ unsigned long long pgend = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGVIDEO, "NP(@%d) - pgswap: %d\n", m_fbCurrentPage, (int)(pgend - pgstart)); ++#endif + return true; + } + +@@ -1643,21 +1629,17 @@ void CIMXContext::Clear(int page) + + if (m_fbVar.nonstd == _4CC('R', 'G', 'B', '4')) + memset(tmp_buf, 0, bytes); +- else if (m_fbVar.nonstd == _4CC('U', 'Y', 'V', 'Y')) ++ else if (m_fbVar.nonstd == _4CC('Y', 'U', 'Y', 'V')) + { ++ uint16_t clr = 128 << 8 | 16; + int pixels = bytes / 2; + for (int i = 0; i < pixels; ++i, tmp_buf += 2) +- { +- tmp_buf[0] = 128; +- tmp_buf[1] = 16; +- } ++ memcpy(tmp_buf, &clr, 2); + } + else + CLog::Log(LOGERROR, "iMX Clear fb error : Unexpected format"); + } + +-#define clamp_byte(x) (x<0?0:(x>255?255:x)) +- + void CIMXContext::CaptureDisplay(unsigned char *buffer, int iWidth, int iHeight) + { + if ((m_fbVar.nonstd != _4CC('R', 'G', 'B', '4')) && +@@ -1688,7 +1670,7 @@ void CIMXContext::CaptureDisplay(unsigned char *buffer, int iWidth, int iHeight) + } + else //_4CC('U', 'Y', 'V', 'Y'))) + { +- int r,g,b,a; ++ uint8_t r,g,b,a; + int u, y0, v, y1; + int iStride = m_fbWidth*2; + int oStride = iWidth*4; +@@ -1706,8 +1688,8 @@ void CIMXContext::CaptureDisplay(unsigned char *buffer, int iWidth, int iHeight) + + for (int y = 0; y < iHeight; ++y, display += iStride, buffer += oStride) + { +- unsigned char *iLine = display; +- unsigned char *oLine = buffer; ++ uint8_t *iLine = display; ++ uint8_t *oLine = buffer; + + for (int x = 0; x < iWidth; ++x, iLine += 4, oLine += 8 ) + { +@@ -1721,9 +1703,9 @@ void CIMXContext::CaptureDisplay(unsigned char *buffer, int iWidth, int iHeight) + g = (cy*y0 + cb2*u + cr2*v) >> 16; + b = (cy*y0 + cb3*u + cr3*v) >> 16; + +- oLine[0] = (clamp_byte(b)*a + oLine[0]*oLine[3])/255; +- oLine[1] = (clamp_byte(g)*a + oLine[1]*oLine[3])/255; +- oLine[2] = (clamp_byte(r)*a + oLine[2]*oLine[3])/255; ++ oLine[0] = (b*a + oLine[0]*oLine[3])/255; ++ oLine[1] = (g*a + oLine[1]*oLine[3])/255; ++ oLine[2] = (r*a + oLine[2]*oLine[3])/255; + oLine[3] = 255; + + a = 255-oLine[7]; +@@ -1731,64 +1713,26 @@ void CIMXContext::CaptureDisplay(unsigned char *buffer, int iWidth, int iHeight) + g = (cy*y0 + cb2*u + cr2*v) >> 16; + b = (cy*y0 + cb3*u + cr3*v) >> 16; + +- oLine[4] = (clamp_byte(b)*a + oLine[4]*oLine[7])/255; +- oLine[5] = (clamp_byte(g)*a + oLine[5]*oLine[7])/255; +- oLine[6] = (clamp_byte(r)*a + oLine[6]*oLine[7])/255; ++ oLine[4] = (b*a + oLine[4]*oLine[7])/255; ++ oLine[5] = (g*a + oLine[5]*oLine[7])/255; ++ oLine[6] = (r*a + oLine[6]*oLine[7])/255; + oLine[7] = 255; + } + } + } + } + +-bool CIMXContext::PushTask(const IPUTask &task) +-{ +- if (!task.current) +- return false; +- +- CSingleLock lk(m_monitor); +- +- if (m_bStop) +- { +- m_inputNotEmpty.notifyAll(); +- return false; +- } +- +- // If the input queue is full, wait for a free slot +- while ((m_bufferedInput == m_input.size()) && !m_bStop) +- m_inputNotFull.wait(lk); +- +- if (m_bStop) +- { +- m_inputNotEmpty.notifyAll(); +- return false; +- } +- +- // Store the value +- if (task.previous) task.previous->Lock(); +- task.current->Lock(); +- +- memcpy(&m_input[m_endInput], &task, sizeof(IPUTask)); +- m_endInput = (m_endInput+1) % m_input.size(); +- ++m_bufferedInput; +- m_inputNotEmpty.notifyAll(); +- +- return true; +-} +- + void CIMXContext::WaitCapture() + { +- CSingleLock lk(m_monitor); +- while (!m_CaptureDone) +- m_inputNotFull.wait(lk); + } + +-void CIMXContext::PrepareTask(IPUTask &ipu, CIMXBuffer *source_p, CIMXBuffer *source, ++void CIMXContext::PrepareTask(IPUTask *ipu, CIMXBuffer *source_p, CIMXBuffer *source, + CRect *dest) + { + // Fill with zeros +- ipu.Zero(); +- ipu.previous = source_p; +- ipu.current = source; ++ ipu->Zero(); ++ ipu->previous = source_p; ++ ipu->current = source; + + CRect srcRect = m_srcRect; + CRect dstRect; +@@ -1840,76 +1784,144 @@ void CIMXContext::PrepareTask(IPUTask &ipu, CIMXBuffer *source_p, CIMXBuffer *so + iDstRect.x2 = Align2((int)dstRect.x2,8); + iDstRect.y2 = Align2((int)dstRect.y2,8); + +- ipu.task.input.crop.pos.x = iSrcRect.x1; +- ipu.task.input.crop.pos.y = iSrcRect.y1; +- ipu.task.input.crop.w = iSrcRect.Width(); +- ipu.task.input.crop.h = iSrcRect.Height(); ++ ipu->task.input.crop.pos.x = iSrcRect.x1; ++ ipu->task.input.crop.pos.y = iSrcRect.y1; ++ ipu->task.input.crop.w = iSrcRect.Width(); ++ ipu->task.input.crop.h = iSrcRect.Height(); + +- ipu.task.output.crop.pos.x = iDstRect.x1; +- ipu.task.output.crop.pos.y = iDstRect.y1; +- ipu.task.output.crop.w = iDstRect.Width(); +- ipu.task.output.crop.h = iDstRect.Height(); ++ ipu->task.output.crop.pos.x = iDstRect.x1; ++ ipu->task.output.crop.pos.y = iDstRect.y1; ++ ipu->task.output.crop.w = iDstRect.Width(); ++ ipu->task.output.crop.h = iDstRect.Height(); + + // If dest is set it means we do not want to blit to frame buffer + // but to a capture buffer and we state this capture buffer dimensions + if (dest) + { + // Populate partly output block +- ipu.task.output.crop.pos.x = 0; +- ipu.task.output.crop.pos.y = 0; +- ipu.task.output.crop.w = iDstRect.Width(); +- ipu.task.output.crop.h = iDstRect.Height(); +- ipu.task.output.width = iDstRect.Width(); +- ipu.task.output.height = iDstRect.Height(); ++ ipu->task.output.crop.pos.x = 0; ++ ipu->task.output.crop.pos.y = 0; ++ ipu->task.output.crop.w = iDstRect.Width(); ++ ipu->task.output.crop.h = iDstRect.Height(); ++ ipu->task.output.width = iDstRect.Width(); ++ ipu->task.output.height = iDstRect.Height(); + } + else + { + // Setup deinterlacing if enabled + if (m_currentFieldFmt) + { +- ipu.task.input.deinterlace.enable = 1; +- /* +- if (source_p) ++ ipu->task.input.deinterlace.enable = 1; ++ ipu->task.input.deinterlace.motion = setIPUMotion(ipu->previous, CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod); ++ ipu->task.input.deinterlace.field_fmt = m_currentFieldFmt; ++ } ++ } ++} ++ ++bool CIMXContext::TileTask(IPUTask *ipu) ++{ ++ int pad = ipu->task.input.height == 1080 && ipu->current->iHeight>ipu->task.input.height ? 8*ipu->current->iWidth : 0; ++ ++ if (ipu->current->iFormat != _4CC('T', 'N', 'V', 'F') && ipu->current->iFormat != _4CC('T', 'N', 'V', 'P')) ++ { ++ if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION) + { +- task.input.deinterlace.motion = MED_MOTION; +- task.input.paddr = source_p->pPhysAddr; +- task.input.paddr_n = source->pPhysAddr; ++ ipu->task.input.paddr_n = ipu->task.input.paddr; ++ ipu->task.input.paddr = ipu->previous->pPhysAddr + pad; + } + else +- */ +- ipu.task.input.deinterlace.motion = HIGH_MOTION; +- ipu.task.input.deinterlace.field_fmt = m_currentFieldFmt; ++ ipu->task.input.paddr += pad; ++ return true; ++ } ++ ++ // Use band mode directly to FB, as no transformations needed (eg cropping) ++ if (m_fps >= 49 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable && m_CaptureDone) ++ { ++ ipu->task.output.crop.pos.x = ipu->task.input.crop.pos.x = 0; ++ ipu->task.output.crop.pos.y = ipu->task.input.crop.pos.y = 0; ++ ipu->task.output.crop.h = ipu->task.input.height = ipu->task.input.crop.h = ipu->current->iHeight; ++ ipu->task.output.paddr += m_fbLineLength * (m_fbHeight - ipu->task.input.crop.h)/2; ++ ++ return true; ++ } ++ ++ // rasterize from tile (frame) ++ struct ipu_task vdoa; ++ ++ memset(&vdoa, 0, sizeof(ipu->task)); ++ vdoa.input.width = vdoa.output.width = ipu->current->iWidth; ++ vdoa.input.height = vdoa.output.height = ipu->current->iHeight; ++ vdoa.input.format = ipu->current->iFormat; ++ ++ // check for 3-field deinterlace (no HIGH_MOTION allowed) from tile field format ++ if (ipu->previous && ipu->current->iFormat == _4CC('T', 'N', 'V', 'F')) ++ { ++ memcpy(&vdoa.input.deinterlace, &ipu->task.input.deinterlace, sizeof(ipu->task.input.deinterlace)); ++ memset(&ipu->task.input.deinterlace, 0, sizeof(ipu->task.input.deinterlace)); ++ vdoa.input.paddr_n = ipu->current->pPhysAddr; ++ } ++ ++ struct g2d_buf *conv = g2d_alloc(ipu->current->iWidth *ipu->current->iHeight * 2, 0); ++ if (!conv) ++ { ++ CLog::Log(LOGERROR, "iMX: can't allocate crop buffer"); ++ return false; ++ } ++ ++ ((CDVDVideoCodecIMXBuffer*)ipu->current)->m_convBuffer = conv; ++ ++ vdoa.input.paddr = vdoa.input.paddr_n ? ipu->previous->pPhysAddr : ipu->current->pPhysAddr; ++ vdoa.output.format = m_fbVar.bits_per_pixel == 16 && m_CaptureDone ? _4CC('Y', 'U', 'Y', 'V') : _4CC('N', 'V', '1', '2'); ++ vdoa.output.paddr = conv->buf_paddr; ++ ++ if (int ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &vdoa)) ++ { ++ CLog::Log(LOGERROR, "IPU conversion from tiled failed %d at #%d", ret, __LINE__); ++ return false; + } ++ if (ioctl(m_ipuHandle, IPU_QUEUE_TASK, &vdoa) < 0) ++ return false; ++ ++ ipu->task.input.paddr = vdoa.output.paddr + pad; ++ ipu->task.input.format = vdoa.output.format; ++ if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION && ipu->previous) ++ { ++ ipu->task.input.paddr_n = ipu->task.input.paddr; ++ ipu->task.input.paddr = ipu->previous->pPhysAddr; + } ++ ipu->current->iFormat = vdoa.output.format; ++ ipu->current->pPhysAddr = vdoa.output.paddr; ++ ++ return true; + } + +-bool CIMXContext::DoTask(IPUTask &ipu, int targetPage) ++bool CIMXContext::DoTask(IPUTask *ipu) + { + bool swapColors = false; + + // Clear page if cropping changes +- CRectInt dstRect(ipu.task.output.crop.pos.x, ipu.task.output.crop.pos.y, +- ipu.task.output.crop.pos.x + ipu.task.output.crop.w, +- ipu.task.output.crop.pos.y + ipu.task.output.crop.h); ++ CRectInt dstRect(ipu->task.output.crop.pos.x, ipu->task.output.crop.pos.y, ++ ipu->task.output.crop.pos.x + ipu->task.output.crop.w, ++ ipu->task.output.crop.pos.y + ipu->task.output.crop.h); + + // Populate input block +- ipu.task.input.width = ipu.current->iWidth; +- ipu.task.input.height = ipu.current->iHeight; +- ipu.task.input.format = ipu.current->iFormat; +- ipu.task.input.paddr = ipu.current->pPhysAddr; ++ ipu->task.input.width = ipu->current->iWidth; ++ ipu->task.input.height = std::min(ipu->current->iHeight, (unsigned int)1080); ++ ipu->task.input.format = ipu->current->iFormat; ++ ipu->task.input.paddr = ipu->current->pPhysAddr; + + // Populate output block if it has not already been filled +- if (ipu.task.output.width == 0) ++ if (ipu->task.output.width == 0) + { +- ipu.task.output.width = m_fbWidth; +- ipu.task.output.height = m_fbHeight; +- ipu.task.output.format = m_fbVar.nonstd; +- ipu.task.output.paddr = m_fbPhysAddr + targetPage*m_fbPageSize; ++ ipu->task.output.width = m_fbWidth; ++ ipu->task.output.height = m_fbHeight; ++ ipu->task.output.format = m_fbVar.nonstd; ++ ipu->task.output.paddr = m_fbPhysAddr + ipu->page*m_fbPageSize; + +- if (m_pageCrops[targetPage] != dstRect) ++ if (m_pageCrops[ipu->page] != dstRect) + { +- m_pageCrops[targetPage] = dstRect; +- Clear(targetPage); ++ m_pageCrops[ipu->page] = dstRect; ++ Clear(ipu->page); + } + } + else +@@ -1917,7 +1929,7 @@ bool CIMXContext::DoTask(IPUTask &ipu, int targetPage) + // If we have already set dest dimensions we want to use capture buffer + // Note we allocate this capture buffer as late as this function because + // all g2d functions have to be called from the same thread +- int size = ipu.task.output.width * ipu.task.output.height * 4; ++ int size = ipu->task.output.width * ipu->task.output.height * 4; + if ((m_bufferCapture) && (size != m_bufferCapture->buf_size)) + { + if (g2d_free(m_bufferCapture)) +@@ -1931,72 +1943,55 @@ bool CIMXContext::DoTask(IPUTask &ipu, int targetPage) + if (m_bufferCapture == NULL) + CLog::Log(LOGERROR, "iMX : Error allocating capture buffer\n"); + } +- ipu.task.output.paddr = m_bufferCapture->buf_paddr; ++ ipu->task.output.paddr = m_bufferCapture->buf_paddr; + swapColors = true; + } + +- if ((ipu.task.input.crop.w <= 0) || (ipu.task.input.crop.h <= 0) +- || (ipu.task.output.crop.w <= 0) || (ipu.task.output.crop.h <= 0)) ++ if ((ipu->task.input.crop.w <= 0) || (ipu->task.input.crop.h <= 0) ++ || (ipu->task.output.crop.w <= 0) || (ipu->task.output.crop.h <= 0)) + return false; + +-#ifdef IMX_PROFILE_BUFFERS +- unsigned long long before = XbmcThreads::SystemClockMillis(); +-#endif ++ if (!TileTask(ipu)) ++ return false; + +- if (ipu.task.input.deinterlace.enable) ++ if (m_CaptureDone && (m_fbVar.bits_per_pixel == 16 || !RENDER_USE_G2D)) + { + //We really use IPU only if we have to deinterlace (using VDIC) + int ret = IPU_CHECK_ERR_INPUT_CROP; + while (ret > IPU_CHECK_ERR_MIN) + { +- ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &ipu.task); ++ ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &ipu->task); + switch (ret) + { + case IPU_CHECK_OK: + break; + case IPU_CHECK_ERR_SPLIT_INPUTW_OVER: +- ipu.task.input.crop.w -= 8; ++ ipu->task.input.crop.w -= 8; + break; + case IPU_CHECK_ERR_SPLIT_INPUTH_OVER: +- ipu.task.input.crop.h -= 8; ++ ipu->task.input.crop.h -= 8; + break; + case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER: +- ipu.task.output.crop.w -= 8; ++ ipu->task.output.crop.w -= 8; + break; + case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER: +- ipu.task.output.crop.h -= 8; ++ ipu->task.output.crop.h -= 8; + break; + // deinterlacing setup changing, m_ipuHandle is closed + case -1: + return true; + default: +- CLog::Log(LOGWARNING, "iMX : unhandled IPU check error: %d\n", ret); ++ CLog::Log(LOGWARNING, "iMX : unhandled IPU check error: %d", ret); + return false; + } + } + +- // Need to find another interface to protect ipu.current from disposing +- // in CDVDVideoCodecIMX::Dispose. CIMXContext must not have knowledge +- // about CDVDVideoCodecIMX. +- ipu.current->BeginRender(); +- if (ipu.current->IsValid()) +- ret = ioctl(m_ipuHandle, IPU_QUEUE_TASK, &ipu.task); +- else +- ret = 0; +- ipu.current->EndRender(); +- ++ ret = ioctl(m_ipuHandle, IPU_QUEUE_TASK, &ipu->task); + if (ret < 0) + { +- CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); ++ CLog::Log(LOGERROR, "IPU task failed: %s at #%d\n", strerror(errno), __LINE__); + return false; + } +- +- // Duplicate 2nd scandline if double rate is active +- if (IsDoubleRate()) +- { +- uint8_t *pageAddr = m_fbVirtAddr + targetPage*m_fbPageSize; +- memcpy(pageAddr, pageAddr+m_fbLineLength, m_fbLineLength); +- } + } + else + { +@@ -2006,64 +2001,50 @@ bool CIMXContext::DoTask(IPUTask &ipu, int targetPage) + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + +- ipu.current->BeginRender(); +- if (ipu.current->IsValid()) + { +- if (ipu.current->iFormat == _4CC('I', '4', '2', '0')) ++ if (ipu->current->iFormat == _4CC('I', '4', '2', '0')) + { + src.format = G2D_I420; +- src.planes[0] = ipu.current->pPhysAddr; +- src.planes[1] = src.planes[0] + Align(ipu.current->iWidth * ipu.current->iHeight, 64); +- src.planes[2] = src.planes[1] + Align((ipu.current->iWidth * ipu.current->iHeight) / 2, 64); ++ src.planes[0] = ipu->current->pPhysAddr; ++ src.planes[1] = src.planes[0] + Align(ipu->current->iWidth * ipu->current->iHeight, 64); ++ src.planes[2] = src.planes[1] + Align((ipu->current->iWidth * ipu->current->iHeight) / 2, 64); + } + else //_4CC('N', 'V', '1', '2'); + { + src.format = G2D_NV12; +- src.planes[0] = ipu.current->pPhysAddr; +- src.planes[1] = src.planes[0] + Align(ipu.current->iWidth * ipu.current->iHeight, 64); ++ src.planes[0] = ipu->current->pPhysAddr; ++ src.planes[1] = src.planes[0] + Align(ipu->current->iWidth * ipu->current->iHeight, 64); + } + +- src.left = ipu.task.input.crop.pos.x; +- src.right = ipu.task.input.crop.w + src.left ; +- src.top = ipu.task.input.crop.pos.y; +- src.bottom = ipu.task.input.crop.h + src.top; +- src.stride = ipu.current->iWidth; +- src.width = ipu.current->iWidth; +- src.height = ipu.current->iHeight; ++ src.left = ipu->task.input.crop.pos.x; ++ src.right = ipu->task.input.crop.w + src.left ; ++ src.top = ipu->task.input.crop.pos.y; ++ src.bottom = ipu->task.input.crop.h + src.top; ++ src.stride = ipu->current->iWidth; ++ src.width = ipu->current->iWidth; ++ src.height = ipu->current->iHeight; + src.rot = G2D_ROTATION_0; +- /*printf("src planes :%x -%x -%x \n",src.planes[0], src.planes[1], src.planes[2] ); +- printf("src left %d right %d top %d bottom %d stride %d w : %d h %d rot : %d\n", +- src.left, src.right, src.top, src.bottom, src.stride, src.width, src.height, src.rot);*/ +- +- dst.planes[0] = ipu.task.output.paddr; +- dst.left = ipu.task.output.crop.pos.x; +- dst.top = ipu.task.output.crop.pos.y; +- dst.right = ipu.task.output.crop.w + dst.left; +- dst.bottom = ipu.task.output.crop.h + dst.top; +- +- dst.stride = ipu.task.output.width; +- dst.width = ipu.task.output.width; +- dst.height = ipu.task.output.height; ++ ++ dst.planes[0] = ipu->task.output.paddr; ++ dst.left = ipu->task.output.crop.pos.x; ++ dst.top = ipu->task.output.crop.pos.y; ++ dst.right = ipu->task.output.crop.w + dst.left; ++ dst.bottom = ipu->task.output.crop.h + dst.top; ++ ++ dst.stride = ipu->task.output.width; ++ dst.width = ipu->task.output.width; ++ dst.height = ipu->task.output.height; + dst.rot = G2D_ROTATION_0; + dst.format = swapColors ? G2D_BGRA8888 : G2D_RGBA8888; +- /*printf("dst planes :%x -%x -%x \n",dst.planes[0], dst.planes[1], dst.planes[2] ); +- printf("dst left %d right %d top %d bottom %d stride %d w : %d h %d rot : %d format %d\n", +- dst.left, dst.right, dst.top, dst.bottom, dst.stride, dst.width, dst.height, dst.rot, dst.format);*/ + + // Launch synchronous blit + g2d_blit(m_g2dHandle, &src, &dst); + g2d_finish(m_g2dHandle); +- if ((m_bufferCapture) && (ipu.task.output.paddr == m_bufferCapture->buf_paddr)) ++ if ((m_bufferCapture) && (ipu->task.output.paddr == m_bufferCapture->buf_paddr)) + m_CaptureDone = true; + } +- ipu.current->EndRender(); + } + +-#ifdef IMX_PROFILE_BUFFERS +- unsigned long long after = XbmcThreads::SystemClockMillis(); +- CLog::Log(LOGNOTICE, "+P %f %d\n", ((CDVDVideoCodecIMXBuffer*)ipu.current)->GetPts(), (int)(after-before)); +-#endif +- + return true; + } + +@@ -2071,7 +2052,9 @@ void CIMXContext::OnStartup() + { + OpenDevices(); + +- Configure(); ++ AdaptScreen(true); ++ AdaptScreen(); ++ + g_Windowing.Register(this); + CLog::Log(LOGNOTICE, "iMX : IPU thread started"); + } +@@ -2082,98 +2065,32 @@ void CIMXContext::OnExit() + CLog::Log(LOGNOTICE, "iMX : IPU thread terminated"); + } + +-void CIMXContext::StopThread(bool bWait /*= true*/) ++void CIMXContext::Stop(bool bWait /*= true*/) + { + if (!IsRunning()) + return; + +- Blank(); + CThread::StopThread(false); +- m_inputNotFull.notifyAll(); +- m_inputNotEmpty.notifyAll(); ++ m_input.signal(); ++ Blank(); + if (bWait && IsRunning()) + CThread::StopThread(true); + } + +-#define MASK1 (IPU_DEINTERLACE_RATE_FRAME1 | RENDER_FLAG_TOP) +-#define MASK2 (IPU_DEINTERLACE_RATE_FRAME1 | RENDER_FLAG_BOT) +-#define VAL1 MASK1 +-#define VAL2 RENDER_FLAG_BOT +- +-inline +-bool checkIPUStrideOffset(struct ipu_deinterlace *d) +-{ +- return ((d->field_fmt & MASK1) == VAL1) || +- ((d->field_fmt & MASK2) == VAL2); +-} +- + void CIMXContext::Process() + { +- bool ret; +- +- // open g2d here to ensure all g2d fucntions are called from the same thread +- if (m_g2dHandle == NULL) +- { +- if (g2d_open(&m_g2dHandle) != 0) +- { +- m_g2dHandle = NULL; +- CLog::Log(LOGERROR, "%s - Error while trying open G2D\n", __FUNCTION__); +- } +- } +- + while (!m_bStop) + { +- IPUTask *task; +- { +- CSingleLock lk(m_monitor); +- while (!m_bufferedInput && !m_bStop) +- m_inputNotEmpty.wait(lk); ++ IPUTask *ipu = m_input.pop(); + +- task = &m_input[m_beginInput]; +- } +- if (m_bStop) +- break; +- +- ret = DoTask(*task, (1-m_fbCurrentPage) & m_vsync); +- bool shift = checkIPUStrideOffset(&task->task.input.deinterlace); ++ if (!ipu) ++ continue; + +- // Free resources +- task->Done(); +- +- { +- CSingleLock lk(m_monitor); +- m_beginInput = (m_beginInput+1) % m_input.size(); +- --m_bufferedInput; +- m_inputNotFull.notifyAll(); +- } ++ ipu->shift = checkIPUStrideOffset(&ipu->task.input.deinterlace); + + // Show back buffer +- if (task->task.output.width && ret) +- ShowPage(1-m_fbCurrentPage, shift); +- } +- +- // Mark all pending jobs as done +- CSingleLock lk(m_monitor); +- while (m_bufferedInput > 0) +- { +- m_input[m_beginInput].Done(); +- m_beginInput = (m_beginInput+1) % m_input.size(); +- --m_bufferedInput; +- } ++ ShowPage(ipu->page, ipu->shift); + +- // close g2d here to ensure all g2d fucntions are called from the same thread +- if (m_bufferCapture) +- { +- if (g2d_free(m_bufferCapture)) +- CLog::Log(LOGERROR, "iMX : Failed to free capture buffers\n"); +- m_bufferCapture = NULL; +- } +- if (m_g2dHandle) +- { +- if (g2d_close(m_g2dHandle)) +- CLog::Log(LOGERROR, "iMX : Error while closing G2D\n"); +- m_g2dHandle = NULL; ++ delete ipu; + } +- +- return; + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index b0286e2..5b64310 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -19,6 +19,8 @@ + * + */ + ++#include "linux/imx/IMX.h" ++ + #include "threads/CriticalSection.h" + #include "threads/Condition.h" + #include "threads/Thread.h" +@@ -27,13 +29,17 @@ + #include "DVDVideoCodec.h" + #include "DVDStreamInfo.h" + #include "guilib/DispResource.h" ++#include "DVDClock.h" ++#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h" + +-#include + #include + #include + #include + #include + ++#include ++#include ++#include + + // The decoding format of the VPU buffer. Comment this to decode + // as NV12. The VPU works faster with NV12 in combination with +@@ -49,43 +55,42 @@ + // priorities to those subsystems can result in a very different user + // experience. With that setting enabled we can build some statistics, + // as numbers are always better than "feelings" +-//#define IMX_PROFILE_BUFFERS ++#define IMX_PROFILE_BUFFERS ++ ++#define IMX_PROFILE ++#define TRACE_FRAMES + +-//#define IMX_PROFILE +-//#define TRACE_FRAMES ++#define RENDER_USE_G2D 0 + + // If uncommented a file "stream.dump" will be created in the current + // directory whenever a new stream is started. This is only for debugging + // and performance tests. This define must never be active in distributions. + //#define DUMP_STREAM + ++inline ++double recalcPts(double pts) ++{ ++ return (double)(pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6); ++} + +-/*>> TO BE MOVED TO A MORE CENTRAL PLACE IN THE SOURCE DIR >>>>>>>>>>>>>>>>>>>*/ +-// Generell description of a buffer used by +-// the IMX context, e.g. for blitting +-class CIMXBuffer { +-public: +- CIMXBuffer() : m_iRefs(0) {} +- +- // Shared pointer interface +- virtual void Lock() = 0; +- virtual long Release() = 0; +- virtual bool IsValid() = 0; +- +- virtual void BeginRender() = 0; +- virtual void EndRender() = 0; +- +-public: +- uint32_t iWidth; +- uint32_t iHeight; +- int pPhysAddr; +- uint8_t *pVirtAddr; +- int iFormat; ++enum SIGNALS ++{ ++ SIGNAL_RESET = (1 << 0), ++ SIGNAL_DISPOSE = (1 << 1), ++ SIGNAL_SIGNAL = (1 << 2), ++ SIGNAL_FLUSH = (1 << 3), ++}; + +-protected: +- long m_iRefs; ++enum RENDER_TASK ++{ ++ RENDER_TASK_AUTOPAGE = -1, ++ RENDER_TASK_CAPTURE = -2, + }; + ++#define CLASS_PICTURE (VPU_DEC_OUTPUT_DIS | VPU_DEC_OUTPUT_MOSAIC_DIS) ++#define CLASS_NOBUF (VPU_DEC_OUTPUT_NODIS | VPU_DEC_NO_ENOUGH_BUF | VPU_DEC_OUTPUT_REPEAT) ++#define CLASS_FORCEBUF (VPU_DEC_OUTPUT_EOS | VPU_DEC_NO_ENOUGH_INBUF) ++#define CLASS_DROP (VPU_DEC_OUTPUT_DROPPED | VPU_DEC_SKIP) + + // iMX context class that handles all iMX hardware + // related stuff +@@ -95,46 +100,34 @@ public: + CIMXContext(); + ~CIMXContext(); + +- bool Configure(); ++ bool AdaptScreen(bool allocate = false); + bool TaskRestart(); +- bool CloseDevices(); ++ void CloseDevices(); ++ void g2dCloseDevices(); ++ void g2dOpenDevices(); + bool OpenDevices(); + + bool Blank(); + bool Unblank(); + bool SetVSync(bool enable); + +- bool IsValid() const { return IsRunning() && m_bFbIsConfigured; } +- +- // Populates a CIMXBuffer with attributes of a page +- bool GetPageInfo(CIMXBuffer *info, int page); +- + // Blitter configuration + bool IsDoubleRate() const { return m_currentFieldFmt & IPU_DEINTERLACE_RATE_EN; } + + void SetBlitRects(const CRect &srcRect, const CRect &dstRect); + +- // Blits a buffer to a particular page. ++ // Blits a buffer to a particular page (-1 for auto page) + // source_p (previous buffer) is required for de-interlacing + // modes LOW_MOTION and MED_MOTION. +- bool Blit(int targetPage, CIMXBuffer *source_p, +- CIMXBuffer *source, +- uint8_t fieldFmt = 0); +- +- // Same as blit but runs in another thread and returns after the task has +- // been queued. BlitAsync renders always to the current backbuffer and +- // swaps the pages. +- bool BlitAsync(CIMXBuffer *source_p, CIMXBuffer *source, +- uint8_t fieldFmt = 0, CRect *dest = NULL); ++ void Blit(CIMXBuffer *source_p, CIMXBuffer *source, ++ uint8_t fieldFmt = 0, int targetPage = RENDER_TASK_AUTOPAGE, ++ CRect *dest = NULL); + + // Shows a page vsynced + bool ShowPage(int page, bool shift = false); + +- // Returns the visible page +- int GetCurrentPage() const { return m_fbCurrentPage; } +- + // Clears the pages or a single page with 'black' +- void Clear(int page = -1); ++ void Clear(int page = RENDER_TASK_AUTOPAGE); + + // Captures the current visible frame buffer page and blends it into + // the passed overlay. The buffer format is BGRA (4 byte) +@@ -143,8 +136,11 @@ public: + void *GetCaptureBuffer() const { if (m_bufferCapture) return m_bufferCapture->buf_vaddr; else return NULL; } + void WaitCapture(); + ++ void RendererAllowed(bool yes); + void OnResetDisplay(); + ++ static const int m_fbPages; ++ + private: + struct IPUTask + { +@@ -154,44 +150,42 @@ private: + memset(&task, 0, sizeof(task)); + } + +- void Done() +- { +- SAFE_RELEASE(previous); +- SAFE_RELEASE(current); +- } +- + // Kept for reference + CIMXBuffer *previous; + CIMXBuffer *current; + + // The actual task + struct ipu_task task; +- }; ++ ++ int page; ++ int shift; ++ } IPUTask_t; + + bool GetFBInfo(const std::string &fbdev, struct fb_var_screeninfo *fbVar); + +- bool PushTask(const IPUTask &); +- void PrepareTask(IPUTask &ipu, CIMXBuffer *source_p, CIMXBuffer *source, ++ void PrepareTask(IPUTask *ipu, CIMXBuffer *source_p, CIMXBuffer *source, + CRect *dest = NULL); +- bool DoTask(IPUTask &ipu, int targetPage); ++ bool DoTask(IPUTask *ipu); ++ bool TileTask(IPUTask *ipu); + +- void SetFieldData(uint8_t fieldFmt); ++ void SetFieldData(uint8_t fieldFmt, double fps); + +- void MemMap(struct fb_fix_screeninfo *fb_fix = NULL); + void Dispose(); ++ void MemMap(struct fb_fix_screeninfo *fb_fix = NULL); ++ void Stop(bool bWait = true); + + virtual void OnStartup(); + virtual void OnExit(); +- virtual void StopThread(bool bWait = true); + virtual void Process(); + + private: +- typedef std::vector TaskQueue; ++ lkFIFO m_input; + + int m_fbHandle; + int m_fbCurrentPage; + int m_fbWidth; + int m_fbHeight; ++ bool m_fbInterlaced; + int m_fbLineLength; + int m_fbPageSize; + int m_fbPhysSize; +@@ -203,31 +197,28 @@ private: + bool m_vsync; + CRect m_srcRect; + CRect m_dstRect; +- CRectInt m_inputRect; +- CRectInt m_outputRect; + CRectInt *m_pageCrops; + bool m_bFbIsConfigured; + + CCriticalSection m_pageSwapLock; +- TaskQueue m_input; +- volatile int m_beginInput, m_endInput; +- volatile size_t m_bufferedInput; +- XbmcThreads::ConditionVariable m_inputNotEmpty; +- XbmcThreads::ConditionVariable m_inputNotFull; +- mutable CCriticalSection m_monitor; +- +- void *m_g2dHandle; +- struct g2d_buf *m_bufferCapture; ++public: ++ void *m_g2dHandle; ++ struct g2d_buf *m_bufferCapture; + bool m_CaptureDone; +- static const int m_fbPages; + + std::string m_deviceName; ++ int m_speed; ++ ++ double m_fps; + }; + + + extern CIMXContext g_IMXContext; ++ + /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + ++class CDVDVideoCodecIMX; ++class CIMXCodec; + + class CDecMemInfo + { +@@ -248,111 +239,216 @@ public: + VpuMemDesc *phyMem; + }; + +- + // Base class of IMXVPU and IMXIPU buffer +-class CDVDVideoCodecIMXBuffer : public CIMXBuffer { ++class CDVDVideoCodecIMXBuffer : public CIMXBuffer ++{ ++friend class CIMXCodec; ++friend class CIMXContext; + public: +-#ifdef TRACE_FRAMES +- CDVDVideoCodecIMXBuffer(int idx); +-#else +- CDVDVideoCodecIMXBuffer(); +-#endif ++ CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int map); ++ virtual ~CDVDVideoCodecIMXBuffer(); + + // reference counting + virtual void Lock(); + virtual long Release(); +- virtual bool IsValid(); + +- virtual void BeginRender(); +- virtual void EndRender(); ++ void SetPts(double pts) { m_pts = pts; } ++ double GetPts() const { return m_pts; } + +- void SetPts(double pts); +- double GetPts() const { return m_pts; } ++ void SetDts(double dts) { m_dts = dts; } ++ double GetDts() const { return m_dts; } + +- void SetDts(double dts); +- double GetDts() const { return m_dts; } ++ void SetFlags(int flags) { m_iFlags = flags; } ++ int GetFlags() const { return m_iFlags; } + +- bool Rendered() const; +- void Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXBuffer *previous); +- VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); +- CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const { return m_previousBuffer; } +- VpuFieldType GetFieldType() const { return m_fieldType; } +- +-private: +- // private because we are reference counted +- virtual ~CDVDVideoCodecIMXBuffer(); ++#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) ++ int GetIdx() { return m_idx; } ++#endif ++ VpuFieldType GetFieldType() const { return m_fieldType; } + + protected: +-#ifdef TRACE_FRAMES +- int m_idx; +-#endif ++ unsigned int m_pctWidth; ++ unsigned int m_pctHeight; + + private: + double m_pts; + double m_dts; + VpuFieldType m_fieldType; + VpuFrameBuffer *m_frameBuffer; +- bool m_rendered; +- CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds the reference counted previous buffer +-}; ++ int m_iFlags; ++#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) ++ unsigned char m_idx; ++ static unsigned char i; ++#endif + ++public: ++ struct g2d_buf *m_convBuffer; ++}; + +-class CDVDVideoCodecIMX : public CDVDVideoCodec ++class CIMXCodec : public CThread + { + public: +- CDVDVideoCodecIMX(CProcessInfo &processInfo); +- virtual ~CDVDVideoCodecIMX(); ++ CIMXCodec(); ++ ~CIMXCodec(); + +- // Methods from CDVDVideoCodec which require overrides +- virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); +- virtual int Decode(BYTE *pData, int iSize, double dts, double pts); +- virtual void Reset(); +- virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); +- virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); +- virtual void SetDropState(bool bDrop); +- virtual const char* GetName() { return (const char*)m_pFormatName; } +- virtual unsigned GetAllowedReferences(); +- +- static void Enter(); +- static void Leave(); ++ bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::string &m_pFormatName); ++ int Decode(BYTE *pData, int iSize, double dts, double pts); ++ ++ void SetDropState(bool bDrop); ++ ++ void Reset(); ++ ++ void SetSpeed(int iSpeed) { m_speed = iSpeed; } ++ void WaitStartup() { m_loaded.Wait(); } ++ ++ bool GetPicture(DVDVideoPicture *pDvdVideoPicture); ++ ++ bool GetCodecStats(double &pts, int &droppedFrames, int &skippedPics); ++ void SetCodecControl(int flags); ++ ++ virtual void Process() override; ++ ++ static void ReleaseFramebuffer(VpuFrameBuffer* fb); ++ ++ virtual bool GetInterlaced() { return m_initInfo.nInterlace; } ++ std::string GetPlayerInfo(); + + protected: ++ class VPUTask ++ { ++ public: ++ VPUTask(DemuxPacket pkg = { nullptr, 0, 0, 0, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE, 0, 0 }, ++ CBitstreamConverter *cnv = nullptr) : demux(pkg) ++ { ++ if (IsEmpty()) ++ return; ++ ++ bool cok = false; ++ if (cnv && (cok = cnv->Convert(pkg.pData, pkg.iSize))) ++ demux.iSize = cnv->GetConvertSize(); ++ ++ posix_memalign((void**)&demux.pData, 1024, demux.iSize); ++ std::memcpy(demux.pData, cok ? cnv->GetConvertBuffer() : pkg.pData, demux.iSize); ++ } ++ ++ void Release() ++ { ++ if (!IsEmpty()) ++ free(demux.pData); ++ demux.pData = nullptr; ++ } ++ ++ bool IsEmpty() { return !demux.pData; } ++ ++ DemuxPacket demux; ++ }; ++ + bool VpuOpen(); + bool VpuAllocBuffers(VpuMemInfo *); +- bool VpuFreeBuffers(); ++ bool VpuFreeBuffers(bool dispose = true); + bool VpuAllocFrameBuffers(); +- int VpuFindBuffer(void *frameAddr); +- void Dispose(); + +- static const int m_extraVpuBuffers; // Number of additional buffers for VPU +- static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop ++ void SetVPUParams(VpuDecConfig InDecConf, void* pInParam); ++ void SetDrainMode(VpuDecInputType drop); ++ void SetSkipMode(VpuDecSkipMode skip); ++ ++ void RecycleFrameBuffers(); ++ ++ static void Release(VPUTask *&t) { SAFE_RELEASE(t); } ++ static void Release(CDVDVideoCodecIMXBuffer *&t) { SAFE_RELEASE(t); } ++ static bool noDTS(VPUTask *&t) { return t->demux.dts == 0.0; } ++ ++ lkFIFO m_decInput; ++ lkFIFO ++ m_decOutput; ++ ++ static const unsigned int m_extraVpuBuffers; // Number of additional buffers for VPU + // by both decoding and rendering threads +- static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled + CDVDStreamInfo m_hints; // Hints from demuxer at stream opening +- const char *m_pFormatName; // Current decoder format name ++ + VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen + CDecMemInfo m_decMemInfo; // VPU dedicated memory description + VpuDecHandle m_vpuHandle; // Handle for VPU library calls + VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start +- bool m_dropRequest; // Current drop request +- bool m_dropState; // Actual drop result +- int m_vpuFrameBufferNum; // Total number of allocated frame buffers +- VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description +- CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers +- CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) +- CDVDVideoCodecIMXBuffer *m_currentBuffer; +- VpuMemDesc *m_extraMem; // Table of allocated extra Memory +- int m_frameCounter; // Decoded frames counter +- bool m_usePTS; // State whether pts out of decoding process should be used ++ VpuDecSkipMode m_skipMode; // Current drop state ++ VpuDecInputType m_drainMode; ++ int m_dropped; ++ ++ std::vector m_vpuFrameBuffers; // Table of VPU frame buffers description ++ std::unordered_map ++ m_pts; ++ double m_lastPTS; + VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info + CBitstreamConverter *m_converter; // H264 annex B converter +- bool m_convert_bitstream; // State whether bitstream conversion is required +- int m_bytesToBeConsumed; // Remaining bytes in VPU +- double m_previousPts; // Enable to keep pts when needed +- bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu + bool m_warnOnce; // Track warning messages to only warn once ++ int m_codecControlFlags; ++ int m_speed; ++ CCriticalSection m_signalLock; ++ CCriticalSection m_queuesLock; + #ifdef DUMP_STREAM + FILE *m_dump; + #endif ++ ++private: ++ bool IsDraining() { return m_drainMode || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN; } ++ bool EOS() { return m_decRet & VPU_DEC_OUTPUT_EOS; } ++ bool FBRegistered() { return m_vpuFrameBuffers.size(); } ++ ++ bool getOutputFrame(VpuDecOutFrameInfo *frm); ++ void ProcessSignals(int signal = 0); ++ void AddExtraData(VpuBufferNode *bn, bool force = false); ++ ++ bool VpuAlloc(VpuMemDesc *vpuMem); ++ ++ void DisposeDecQueues(); ++ void FlushVPU(); ++ ++ void Dispose(); ++ ++ unsigned int m_decSignal; ++ ThreadIdentifier m_threadID; ++ CEvent m_loaded; ++ int m_decRet; ++ double m_fps; ++ ++private: ++ void ExitError(const char *msg, ...); ++ bool IsCurrentThread() const; ++ ++ CCriticalSection m_openLock; ++}; ++ ++class CDVDVideoCodecIMX : public CDVDVideoCodec ++{ ++public: ++ CDVDVideoCodecIMX(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo), m_pFormatName("iMX-xxx") {} ++ virtual ~CDVDVideoCodecIMX(); ++ ++ // Methods from CDVDVideoCodec which require overrides ++ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); ++ virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); ++ ++ virtual int Decode(BYTE *pData, int iSize, double dts, double pts) { return m_IMXCodec->Decode(pData, iSize, dts, pts); } ++ ++ virtual void Reset() { m_IMXCodec->Reset(); } ++ virtual const char* GetName() { return (const char*)m_pFormatName.c_str(); } ++ ++ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture) { return m_IMXCodec->GetPicture(pDvdVideoPicture); } ++ virtual void SetDropState(bool bDrop) { m_IMXCodec->SetDropState(bDrop); } ++ virtual unsigned GetAllowedReferences(); ++ ++ virtual bool GetCodecStats(double &pts, int &droppedFrames, int &skippedPics) override ++ { return m_IMXCodec->GetCodecStats(pts, droppedFrames, skippedPics); } ++ virtual void SetCodecControl(int flags) override { m_IMXCodec->SetCodecControl(flags); } ++ virtual void SetSpeed(int iSpeed) { m_IMXCodec->SetSpeed(iSpeed); } ++ ++ virtual bool GetInterlaced() { return m_IMXCodec->GetInterlaced(); } ++ ++ std::string GetPlayerInfo() { return m_IMXCodec ? m_IMXCodec->GetPlayerInfo() : ""; } ++ ++private: ++ std::shared_ptr m_IMXCodec; ++ ++ std::string m_pFormatName; // Current decoder format name + }; ++ +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp +index fd15bf5..47e2ecc 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp +@@ -192,7 +192,7 @@ bool CDVDVideoCodecOpenMax::GetPicture(DVDVideoPicture* pDvdVideoPicture) + m_omx_decoder->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + +- //! @todo what's going on here? bool is required as return value. ++ // TODO what's going on here? bool is required as return value. + return VC_PICTURE | VC_BUFFER; + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp +index 3d026cd..dbc24af 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp +@@ -51,12 +51,10 @@ using namespace KODI::MESSAGING; + + #define CLASSNAME "CMMALVideoBuffer" + +-#define VERBOSE 0 +- + CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv) + : m_omv(omv) + { +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); + mmal_buffer = NULL; + m_width = 0; +@@ -71,7 +69,7 @@ CMMALVideoBuffer::~CMMALVideoBuffer() + { + if (mmal_buffer) + mmal_buffer_header_release(mmal_buffer); +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); + } + +@@ -108,7 +106,6 @@ CMMALVideo::CMMALVideo(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo) + m_codingType = 0; + + m_es_format = mmal_format_alloc(); +- m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; + m_fps = 0.0f; + m_num_decoded = 0; +@@ -220,8 +217,6 @@ void CMMALVideo::dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buff + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); + mmal_buffer_header_release(buffer); +- CSingleLock lock(m_output_mutex); +- m_output_cond.notifyAll(); + } + + static void dec_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +@@ -729,7 +724,6 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + return false; + + Prime(); +- m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; + + return true; +@@ -847,12 +841,9 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + bool full = queued > DVD_MSEC_TO_TIME(1000); + int ret = 0; + +- unsigned int pics = m_output_ready.size(); +- if (m_preroll && (pics >= GetAllowedReferences() || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) +- m_preroll = false; +- if (pics > 0 && !m_preroll) ++ if (!m_output_ready.empty()) + ret |= VC_PICTURE; +- if ((m_preroll || pics <= 1) && mmal_queue_length(m_dec_input_pool->queue) > 0 && !(m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !(m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) + ret |= VC_BUFFER; + + bool slept = false; +@@ -861,22 +852,20 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + slept = true; + { + // otherwise we busy spin +- lock.Leave(); +- CSingleLock output_lock(m_output_mutex); +- m_output_cond.wait(output_lock, 30); +- lock.Enter(); ++ CSingleExit unlock(m_sharedSection); ++ CSingleLock lock(m_output_mutex); ++ m_output_cond.wait(lock, 30); + } +- unsigned int pics = m_output_ready.size(); +- if (m_preroll && (pics >= GetAllowedReferences() || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) +- m_preroll = false; +- if (pics > 0 && !m_preroll) ++ if (!m_output_ready.empty()) + ret |= VC_PICTURE; +- if ((m_preroll || pics <= 1) && (mmal_queue_length(m_dec_input_pool->queue) > 0 || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !(m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) ++ ret |= VC_BUFFER; ++ else if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN && !ret) + ret |= VC_BUFFER; + } + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x) preroll(%d)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), slept, queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags, m_preroll); ++ CLog::Log(LOGDEBUG, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), slept, queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags); + + return ret; + } +@@ -885,12 +874,9 @@ void CMMALVideo::Prime() + { + MMAL_BUFFER_HEADER_T *buffer; + assert(m_renderer); +- if (!m_pool) +- m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, AV_PIX_FMT_YUV420P, true); +- assert(m_pool); +- MMAL_POOL_T *render_pool = m_pool->Get(); ++ MMAL_POOL_T *render_pool = m_renderer->GetPool(RENDER_FMT_MMAL, true); + assert(render_pool); +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - queue(%p)", CLASSNAME, __func__, render_pool); + while (buffer = mmal_queue_get(render_pool->queue), buffer) + Recycle(buffer); +@@ -949,7 +935,6 @@ void CMMALVideo::Reset(void) + m_demuxerPts = DVD_NOPTS_VALUE; + m_codecControlFlags = 0; + m_dropState = false; +- m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -963,7 +948,7 @@ void CMMALVideo::SetSpeed(int iSpeed) + void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) + { + CSingleLock lock(m_sharedSection); +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, buffer); + + if (m_finished) +@@ -975,7 +960,7 @@ void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) + MMAL_STATUS_T status; + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p ready_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, + m_output_ready.size()); + status = mmal_port_send_buffer(m_dec_output, buffer); +@@ -1022,8 +1007,8 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) + } + + // timestamp is in microseconds +- pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts; +- pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; ++ pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->dts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts; ++ pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->pts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; + + pDvdVideoPicture->MMALBuffer->Acquire(); + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; +@@ -1049,9 +1034,9 @@ bool CMMALVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) + CSingleLock lock(m_sharedSection); + if (pDvdVideoPicture->format == RENDER_FMT_MMAL) + { +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - %p (%p)", CLASSNAME, __func__, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer); +- SAFE_RELEASE(pDvdVideoPicture->MMALBuffer); ++ pDvdVideoPicture->MMALBuffer->Release(); + } + memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); + return true; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h +index d008c6c..a84d4b3 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h +@@ -57,7 +57,6 @@ public: + + class CMMALVideo; + class CMMALRenderer; +-class CMMALPool; + + // a mmal video frame + class CMMALVideoBuffer : public CMMALBuffer +@@ -133,7 +132,6 @@ protected: + int m_speed; + int m_codecControlFlags; + bool m_dropState; +- bool m_preroll; + + CCriticalSection m_sharedSection; + MMAL_COMPONENT_T *m_dec; +@@ -141,7 +139,6 @@ protected: + MMAL_PORT_T *m_dec_output; + MMAL_POOL_T *m_dec_input_pool; + CMMALRenderer *m_renderer; +- std::shared_ptr m_pool; + + MMAL_ES_FORMAT_T *m_es_format; + MMAL_COMPONENT_T *m_deint; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp +index 3825e4c..6d7b0a0 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp +@@ -45,7 +45,6 @@ using namespace MMAL; + CMMALYUVBuffer::CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height) + : m_dec(dec) + { +- unsigned int size_pic = 0; + dec->Acquire(); + m_width = width; + m_height = height; +@@ -53,13 +52,7 @@ CMMALYUVBuffer::CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int h + m_aligned_height = aligned_height; + m_aspect_ratio = 0.0f; + mmal_buffer = nullptr; +- if (dec->m_fmt == AV_PIX_FMT_YUV420P) +- size_pic = (m_aligned_width * m_aligned_height * 3) >> 1; +- else if (dec->m_fmt == AV_PIX_FMT_BGR0) +- size_pic = (m_aligned_width << 2) * m_aligned_height; +- else if (dec->m_fmt == AV_PIX_FMT_RGB565LE) +- size_pic = (m_aligned_width << 1) * m_aligned_height; +- else assert(0); ++ unsigned int size_pic = (m_aligned_width * m_aligned_height * 3) >> 1; + gmem = m_dec->AllocateBuffer(size_pic); + if (gmem) + gmem->m_opaque = (void *)this; +@@ -89,8 +82,6 @@ CGPUMEM *CDecoder::AllocateBuffer(unsigned int size_pic) + m_freeBuffers.pop_front(); + if (gmem->m_numbytes == size_pic) + return gmem; +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s discarding gmem:%p size %d/%d", CLASSNAME, __FUNCTION__, gmem, gmem->m_numbytes, size_pic); + delete gmem; + } + +@@ -102,7 +93,6 @@ CGPUMEM *CDecoder::AllocateBuffer(unsigned int size_pic) + + void CDecoder::ReleaseBuffer(CGPUMEM *gmem) + { +- CSingleLock lock(m_section); + if (m_closing) + delete gmem; + else +@@ -209,9 +199,9 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags) + CDVDVideoCodecFFmpeg *ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque; + CDecoder *dec = (CDecoder*)ctx->GetHardware(); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG,"%s::%s %dx%d format:%x:%x flags:%x", CLASSNAME, __FUNCTION__, frame->width, frame->height, frame->format, dec->m_fmt, flags); ++ CLog::Log(LOGDEBUG,"%s::%s %dx%d format:%x flags:%x", CLASSNAME, __FUNCTION__, frame->width, frame->height, frame->format, flags); + +- if ((avctx->codec && (avctx->codec->capabilities & AV_CODEC_CAP_DR1) == 0) || frame->format != dec->m_fmt) ++ if ((avctx->codec->capabilities & AV_CODEC_CAP_DR1) == 0 || frame->format != AV_PIX_FMT_YUV420P) + { + assert(0); + return avcodec_default_get_buffer2(avctx, frame, flags); +@@ -237,29 +227,13 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags) + frame->linesize[i] = 0; + } + +- if (dec->m_fmt == AV_PIX_FMT_YUV420P) +- { +- frame->buf[0] = buf; +- frame->linesize[0] = YUVBuffer->m_aligned_width; +- frame->linesize[1] = YUVBuffer->m_aligned_width>>1; +- frame->linesize[2] = YUVBuffer->m_aligned_width>>1; +- frame->data[0] = (uint8_t *)gmem->m_arm; +- frame->data[1] = frame->data[0] + YUVBuffer->m_aligned_width * YUVBuffer->m_aligned_height; +- frame->data[2] = frame->data[1] + (YUVBuffer->m_aligned_width>>1) * (YUVBuffer->m_aligned_height>>1); +- } +- else if (dec->m_fmt == AV_PIX_FMT_BGR0) +- { +- frame->buf[0] = buf; +- frame->linesize[0] = YUVBuffer->m_aligned_width << 2; +- frame->data[0] = (uint8_t *)gmem->m_arm; +- } +- else if (dec->m_fmt == AV_PIX_FMT_RGB565LE) +- { +- frame->buf[0] = buf; +- frame->linesize[0] = YUVBuffer->m_aligned_width << 1; +- frame->data[0] = (uint8_t *)gmem->m_arm; +- } +- else assert(0); ++ frame->buf[0] = buf; ++ frame->linesize[0] = YUVBuffer->m_aligned_width; ++ frame->linesize[1] = YUVBuffer->m_aligned_width>>1; ++ frame->linesize[2] = YUVBuffer->m_aligned_width>>1; ++ frame->data[0] = (uint8_t *)gmem->m_arm; ++ frame->data[1] = frame->data[0] + YUVBuffer->m_aligned_width * YUVBuffer->m_aligned_height; ++ frame->data[2] = frame->data[1] + (YUVBuffer->m_aligned_width>>1) * (YUVBuffer->m_aligned_height>>1); + frame->extended_data = frame->data; + // Leave extended buf alone + +@@ -289,7 +263,6 @@ bool CDecoder::Open(AVCodecContext *avctx, AVCodecContext* mainctx, enum AVPixel + mainctx->get_buffer2 = CDecoder::FFGetBuffer; + + m_avctx = mainctx; +- m_fmt = fmt; + return true; + } + +@@ -307,11 +280,7 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) + + MMAL_BUFFER_HEADER_T *CDecoder::GetMmal() + { +- if (!m_pool) +- m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, m_fmt, false); +- +- assert(m_pool); +- MMAL_POOL_T *render_pool = m_pool->Get(); ++ MMAL_POOL_T *render_pool = m_renderer->GetPool(RENDER_FMT_MMAL, false); + assert(render_pool); + MMAL_BUFFER_HEADER_T *mmal_buffer = mmal_queue_timedwait(render_pool->queue, 500); + if (!mmal_buffer) +@@ -334,8 +303,7 @@ bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture + if (!ret) + return false; + +- if ((frame->format != AV_PIX_FMT_YUV420P && frame->format != AV_PIX_FMT_BGR0 && frame->format != AV_PIX_FMT_RGB565LE) || +- frame->buf[1] != nullptr || frame->buf[0] == nullptr) ++ if (frame->format != AV_PIX_FMT_YUV420P || frame->buf[1] != nullptr || frame->buf[0] == nullptr) + return false; + + MMAL_BUFFER_HEADER_T *mmal_buffer = GetMmal(); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h +index e0ae5ed..a2c3555 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h +@@ -27,7 +27,6 @@ + #include "MMALCodec.h" + + class CMMALRenderer; +-class CMMALPool; + struct MMAL_BUFFER_HEADER_T; + class CGPUMEM; + +@@ -70,14 +69,12 @@ public: + CGPUMEM *AllocateBuffer(unsigned int numbytes); + void ReleaseBuffer(CGPUMEM *gmem); + unsigned sizeFree() { return m_freeBuffers.size(); } +- enum AVPixelFormat m_fmt; + protected: + MMAL_BUFFER_HEADER_T *GetMmal(); + AVCodecContext *m_avctx; + unsigned int m_shared; + CCriticalSection m_section; + CMMALRenderer *m_renderer; +- std::shared_ptr m_pool; + std::deque m_freeBuffers; + bool m_closing; + }; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMax.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMax.h +index ef6da1b..a659191 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMax.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMax.h +@@ -26,8 +26,6 @@ + #include "threads/Event.h" + + #include +-#include +-#include + #include + #include + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.cpp +index 3d5744b..420831e 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.cpp +@@ -55,8 +55,8 @@ using namespace KODI::MESSAGING; + + #define CLASSNAME "COpenMaxVideo" + +-//! @todo These are Nvidia Tegra2 dependent, need to dynamiclly find the +-//! right codec matched to video format. ++// TODO: These are Nvidia Tegra2 dependent, need to dynamiclly find the ++// right codec matched to video format. + #define OMX_H264BASE_DECODER "OMX.Nvidia.h264.decode" + // OMX.Nvidia.h264ext.decode segfaults, not sure why. + //#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264ext.decode" +@@ -95,6 +95,8 @@ do \ + (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \ + (a).nVersion.s.nStep = OMX_VERSION_STEP + ++#undef OMX_DEBUG_VERBOSE ++ + pthread_mutex_t m_omx_queue_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + + COpenMaxVideo::COpenMaxVideo() +@@ -168,7 +170,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints) + decoder_name = OMX_MPEG4_DECODER; + break; + /* +- @todo what mpeg4 formats are "ext" ???? ++ TODO: what mpeg4 formats are "ext" ???? + case NvxStreamType_MPEG4Ext: + // (role name) video_decoder.mpeg4 + // MPEG-4, DivX 4/5 and Xvid compatible +@@ -197,9 +199,9 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints) + return false; + } + +- //! @todo Find component from role name. +- //! Get the port information. This will obtain information about the +- //! number of ports and index of the first port. ++ // TODO: Find component from role name. ++ // Get the port information. This will obtain information about the ++ // number of ports and index of the first port. + OMX_PORT_PARAM_TYPE port_param; + OMX_INIT_STRUCTURE(port_param); + omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamVideoInit, &port_param); +@@ -216,7 +218,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints) + CLASSNAME, __func__, m_omx_decoder, m_omx_input_port, m_omx_output_port); + #endif + +- //! @todo Set role for the component because components could have multiple roles. ++ // TODO: Set role for the component because components could have multiple roles. + //QueryCodec(); + + // Component will be in OMX_StateLoaded now so we can alloc omx input/output buffers. +@@ -357,7 +359,7 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + demux_packet.pts = pts; + + demux_packet.size = demuxer_bytes; +- //! @todo memory leak? where does this memory get does get freed? ++ // TODO memory leak? where does this memory get does get freed? + demux_packet.buff = new OMX_U8[demuxer_bytes]; + memcpy(demux_packet.buff, demuxer_content, demuxer_bytes); + +@@ -422,7 +424,7 @@ void COpenMaxVideo::Reset(void) + + StartDecoder(); + +- //! @todo error checking? ++ // TODO error checking? + } + ::Sleep(100); + } +@@ -441,7 +443,7 @@ void COpenMaxVideo::ReleaseBuffer(OpenMaxVideoBuffer* releaseBuffer) + if (!releaseBuffer) + return; + +- //! @todo this is NOT multithreading safe. Buffer lifetime managment needs to be adopted. ++ // TODO this is NOT multithreading safe. Buffer lifetime managment needs to be adopted. + + pthread_mutex_lock(&m_omx_queue_mutex); + OpenMaxVideoBuffer *buffer = releaseBuffer; +@@ -1211,7 +1213,7 @@ void OpenMaxVideoBuffer::ReleaseTexture() + DeleteImageInfo *deleteInfo = new DeleteImageInfo; + + // add egl resources to deletion info +- //! @todo delete from constructor! ++ // TODO delete from constructor! + deleteInfo->egl_image = egl_image; + deleteInfo->egl_sync = eglSync; + deleteInfo->texture_id = texture_id; +@@ -1222,7 +1224,7 @@ void OpenMaxVideoBuffer::ReleaseTexture() + } + else + { +- //! @todo put the callbackData pointer into userptr so that it can be delete afterwards ++ // TODO put the callbackData pointer into userptr so that it can be delete afterwards + deleteInfo->callback.callback = &OpenMaxDeleteTextures; + deleteInfo->callback.userptr = (void *)deleteInfo; + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h +index cf569c0..a235a01 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h +@@ -20,8 +20,6 @@ + */ + + #if defined(HAVE_LIBOPENMAX) +-#include +-#include + + #include "OpenMax.h" + #include +@@ -116,7 +114,7 @@ protected: + static void CallbackAllocOMXEGLTextures(void*); + OMX_ERRORTYPE AllocOMXOutputEGLTextures(void); + +- //! @todo Those should move into the base class. After start actions can be executed by callbacks. ++ // TODO Those should move into the base class. After start actions can be executed by callbacks. + OMX_ERRORTYPE StartDecoder(void); + OMX_ERRORTYPE StopDecoder(void); + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h +index cc744c7..6f74a72 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + #include "linux/sse4/DllLibSSE4.h" + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h +index 56601a1..8cc4683 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h +@@ -57,10 +57,8 @@ + #include "threads/Thread.h" + #include "utils/ActorProtocol.h" + #include "guilib/Geometry.h" +-#include + #include + #include +-#include + + extern "C" { + #include "libavutil/avutil.h" +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h +index 23cd50c..7d778e6 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h +@@ -148,6 +148,8 @@ public: + { + iFpsScale = 0; + iFpsRate = 0; ++ irFpsScale = 0; ++ irFpsRate = 0; + iHeight = 0; + iWidth = 0; + fAspect = 0.0; +@@ -162,6 +164,8 @@ public: + virtual ~CDemuxStreamVideo() {} + int iFpsScale; // scale of 1000 and a rate of 29970 will result in 29.97 fps + int iFpsRate; ++ int irFpsScale; ++ int irFpsRate; + int iHeight; // height of the stream reported by the demuxer + int iWidth; // width of the stream reported by the demuxer + float fAspect; // display aspect of stream +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +index ec96daf..041fd8a 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +@@ -383,7 +383,6 @@ void CDVDDemuxClient::RequestStreams() + streamAudio->iBitsPerSample = source->iBitsPerSample; + if (source->ExtraSize > 0 && source->ExtraData) + { +- delete[] streamAudio->ExtraData; + streamAudio->ExtraData = new uint8_t[source->ExtraSize]; + streamAudio->ExtraSize = source->ExtraSize; + for (unsigned int j=0; jExtraSize; j++) +@@ -417,15 +416,14 @@ void CDVDDemuxClient::RequestStreams() + streamVideo->m_parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + } + +- streamVideo->iFpsScale = source->iFpsScale; +- streamVideo->iFpsRate = source->iFpsRate; ++ streamVideo->iFpsScale = source->irFpsScale; ++ streamVideo->iFpsRate = source->irFpsRate; + streamVideo->iHeight = source->iHeight; + streamVideo->iWidth = source->iWidth; + streamVideo->fAspect = source->fAspect; + streamVideo->stereo_mode = "mono"; + if (source->ExtraSize > 0 && source->ExtraData) + { +- delete[] streamVideo->ExtraData; + streamVideo->ExtraData = new uint8_t[source->ExtraSize]; + streamVideo->ExtraSize = source->ExtraSize; + for (unsigned int j=0; jExtraSize; j++) +@@ -460,7 +458,6 @@ void CDVDDemuxClient::RequestStreams() + + if (source->ExtraSize == 4) + { +- delete[] streamSubtitle->ExtraData; + streamSubtitle->ExtraData = new uint8_t[4]; + streamSubtitle->ExtraSize = 4; + for (int j=0; j<4; j++) +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h +index af6a599..e6c9bfd 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h +@@ -21,7 +21,6 @@ + + #include "DVDDemux.h" + #include +-#include + + extern "C" { + #include "libavcodec/avcodec.h" +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index b76e248..fd041c1 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -419,7 +419,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo, bool filein + bool isBluray = pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY); + if (iformat && (strcmp(iformat->name, "mpegts") == 0) && !fileinfo && !isBluray) + { +- av_opt_set_int(m_pFormatContext, "analyzeduration", 500000, 0); ++ av_opt_set_int(m_pFormatContext, "analyzeduration", 1000000, 0); + m_checkvideo = true; + skipCreateStreams = true; + } +@@ -1228,9 +1228,21 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx) + st->iFpsScale = 0; + } + +- if (pStream->codec_info_nb_frames > 0 && +- pStream->codec_info_nb_frames <= 2 && +- m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) ++ // added for aml hw decoder, mkv frame-rate can be wrong. ++ if (r_frame_rate.den && r_frame_rate.num) ++ { ++ st->irFpsRate = r_frame_rate.num; ++ st->irFpsScale = r_frame_rate.den; ++ } ++ else ++ { ++ st->irFpsRate = 0; ++ st->irFpsScale = 0; ++ } ++ ++ if (pStream->codec_info_nb_frames > 0 ++ && pStream->codec_info_nb_frames <= 2 ++ && m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) + { + CLog::Log(LOGDEBUG, "%s - fps may be unreliable since ffmpeg decoded only %d frame(s)", __FUNCTION__, pStream->codec_info_nb_frames); + st->iFpsRate = 0; +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp +index 807ad89..84c3276 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp +@@ -30,8 +30,7 @@ + #include "DVDDemuxClient.h" + #include "DemuxMultiSource.h" + #include "pvr/PVRManager.h" +-#include "utils/log.h" +-#include "utils/URIUtils.h" ++#include "pvr/addons/PVRClients.h" + + using namespace PVR; + +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt +index 9de5f14..70d4153 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt +@@ -5,6 +5,7 @@ set(SOURCES DVDFactoryInputStream.cpp + DVDInputStreamMemory.cpp + DVDInputStreamNavigator.cpp + DVDInputStreamPVRManager.cpp ++ DVDInputStreamRTMP.cpp + DVDInputStreamStack.cpp + DVDStateSerializer.cpp + InputStreamAddon.cpp +@@ -17,9 +18,11 @@ set(HEADERS DVDFactoryInputStream.h + DVDInputStreamMemory.h + DVDInputStreamNavigator.h + DVDInputStreamPVRManager.h ++ DVDInputStreamRTMP.h + DVDInputStreamStack.h + DVDStateSerializer.h + DllDvdNav.h ++ DllLibRTMP.h + InputStreamAddon.h + InputStreamMultiStreams.h + InputStreamMultiSource.h) +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp +index fc782b2..bbb1fc3 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp +@@ -25,6 +25,7 @@ + #include "DVDInputStreamNavigator.h" + #include "DVDInputStreamFFmpeg.h" + #include "DVDInputStreamPVRManager.h" ++#include "DVDInputStreamRTMP.h" + #include "InputStreamAddon.h" + #include "InputStreamMultiSource.h" + #ifdef HAVE_LIBBLURAY +@@ -76,10 +77,6 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer + ADDON_STATUS status = addon->Create(); + if (status == ADDON_STATUS_OK) + { +- unsigned int videoWidth, videoHeight; +- pPlayer->GetVideoResolution(videoWidth, videoHeight); +- addon->SetVideoResolution(videoWidth, videoHeight); +- + return new CInputStreamAddon(fileitem, addon); + } + } +@@ -131,6 +128,14 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer + else if(file.substr(0, 8) == "stack://") + return new CDVDInputStreamStack(fileitem); + #endif ++#ifdef HAS_LIBRTMP ++ else if(file.substr(0, 7) == "rtmp://" ++ || file.substr(0, 8) == "rtmpt://" ++ || file.substr(0, 8) == "rtmpe://" ++ || file.substr(0, 9) == "rtmpte://" ++ || file.substr(0, 8) == "rtmps://") ++ return new CDVDInputStreamRTMP(fileitem); ++#endif + else if (fileitem.IsInternetStream()) + { + if (fileitem.IsType(".m3u8")) +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.h +index 65e57e7..2f2b43e 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.h ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.h +@@ -21,8 +21,6 @@ + */ + + #include +-#include +- + #include "FileItem.h" + + class CDVDInputStream; +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h +index 1049855..4807012 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h +@@ -38,6 +38,7 @@ enum DVDStreamType + DVDSTREAM_TYPE_MEMORY = 4, + DVDSTREAM_TYPE_FFMPEG = 5, + DVDSTREAM_TYPE_TV = 6, ++ DVDSTREAM_TYPE_RTMP = 7, + DVDSTREAM_TYPE_MPLS = 10, + DVDSTREAM_TYPE_BLURAY = 11, + DVDSTREAM_TYPE_PVRMANAGER = 12, +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp +index 6ccd9a8..f37668e 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp +@@ -78,7 +78,7 @@ int DllLibbluray::file_eof(BD_FILE_H *file) + + int64_t DllLibbluray::file_read(BD_FILE_H *file, uint8_t *buf, int64_t size) + { +- return static_cast(file->internal)->Read(buf, size); //! @todo fix size cast ++ return static_cast(file->internal)->Read(buf, size); // TODO: fix size cast + } + + int64_t DllLibbluray::file_write(BD_FILE_H *file, const uint8_t *buf, int64_t size) +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.cpp +index df78857..ec03c9d 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.cpp ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.cpp +@@ -29,7 +29,6 @@ + #include "pvr/addons/PVRClients.h" + #include "pvr/channels/PVRChannelGroupsContainer.h" + #include "pvr/recordings/PVRRecordingsPath.h" +-#include "pvr/recordings/PVRRecordings.h" + #include "settings/Settings.h" + #include "cores/VideoPlayer/DVDDemuxers/DVDDemux.h" + +@@ -419,9 +418,9 @@ bool CDVDInputStreamPVRManager::IsRecording() + return g_PVRClients->IsRecordingOnPlayingChannel(); + } + +-void CDVDInputStreamPVRManager::Record(bool bOnOff) ++bool CDVDInputStreamPVRManager::Record(bool bOnOff) + { +- g_PVRManager.StartRecordingOnPlayingChannel(bOnOff); ++ return g_PVRManager.StartRecordingOnPlayingChannel(bOnOff); + } + + bool CDVDInputStreamPVRManager::CanPause() +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.h +index a86b5a8..d037b19 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.h ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamPVRManager.h +@@ -70,7 +70,7 @@ public: + + bool CanRecord(); + bool IsRecording(); +- void Record(bool bOnOff); ++ bool Record(bool bOnOff); + bool CanSeek() override; + bool CanPause() override; + void Pause(bool bPaused); +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.cpp +new file mode 100644 +index 0000000..9a4b889 +--- /dev/null ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.cpp +@@ -0,0 +1,265 @@ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) ++ #include "config.h" ++#endif ++#ifdef TARGET_WINDOWS ++#include "system.h" // just for HAS_LIBRTMP ++#endif ++ ++#ifdef HAS_LIBRTMP ++#include "settings/AdvancedSettings.h" ++#include "DVDInputStreamRTMP.h" ++#include "threads/SingleLock.h" ++#include "utils/log.h" ++#include "utils/Variant.h" ++ ++#include ++ ++using namespace XFILE; ++ ++static int RTMP_level=0; ++extern "C" ++{ ++ static void CDVDInputStreamRTMP_Log(int level, const char *fmt, va_list args) ++ { ++ char buf[2048]; ++ ++ if (level > RTMP_level) ++ return; ++ ++ switch(level) ++ { ++ default: ++ case RTMP_LOGCRIT: level = LOGFATAL; break; ++ case RTMP_LOGERROR: level = LOGERROR; break; ++ case RTMP_LOGWARNING: level = LOGWARNING; break; ++ case RTMP_LOGINFO: level = LOGNOTICE; break; ++ case RTMP_LOGDEBUG: level = LOGINFO; break; ++ case RTMP_LOGDEBUG2: level = LOGDEBUG; break; ++ } ++ ++ vsnprintf(buf, sizeof(buf), fmt, args); ++ CLog::Log(level, "%s", buf); ++ } ++} ++ ++CDVDInputStreamRTMP::CDVDInputStreamRTMP(const CFileItem &fileitem) ++ : CDVDInputStream(DVDSTREAM_TYPE_RTMP, fileitem) ++ , m_canSeek(true) ++ , m_canPause(true) ++{ ++ if (m_libRTMP.Load()) ++ { ++ CLog::Log(LOGINFO,"%s: Using external libRTMP",__FUNCTION__); ++ RTMP_LogLevel level; ++ ++ m_libRTMP.LogSetCallback(CDVDInputStreamRTMP_Log); ++ switch (g_advancedSettings.m_logLevel) ++ { ++ case LOG_LEVEL_DEBUG_FREEMEM: ++ case LOG_LEVEL_DEBUG: level = RTMP_LOGDEBUG; break; ++ case LOG_LEVEL_NORMAL: level = RTMP_LOGINFO; break; ++ default: level = RTMP_LOGCRIT; break; ++ } ++ ++ if (g_advancedSettings.CanLogComponent(LOGRTMP)) ++ level = RTMP_LOGDEBUG2; ++ ++ m_libRTMP.LogSetLevel(level); ++ RTMP_level = level; ++ ++ m_rtmp = m_libRTMP.Alloc(); ++ m_libRTMP.Init(m_rtmp); ++ } ++ else ++ { ++ m_rtmp = NULL; ++ } ++ ++ m_eof = true; ++ m_bPaused = false; ++ m_sStreamPlaying = NULL; ++} ++ ++CDVDInputStreamRTMP::~CDVDInputStreamRTMP() ++{ ++ free(m_sStreamPlaying); ++ m_sStreamPlaying = NULL; ++ ++ Close(); ++ if (m_rtmp) ++ m_libRTMP.Free(m_rtmp); ++ m_rtmp = NULL; ++ m_bPaused = false; ++} ++ ++bool CDVDInputStreamRTMP::IsEOF() ++{ ++ return m_eof; ++} ++ ++#define SetAVal(av, cstr) av.av_val = (char *)cstr.c_str(); av.av_len = cstr.length() ++#undef AVC ++#define AVC(str) {(char *)str,sizeof(str)-1} ++ ++/* librtmp option names are slightly different */ ++static const struct { ++ const char *name; ++ AVal key; ++} options[] = { ++ { "SWFPlayer", AVC("swfUrl") }, ++ { "PageURL", AVC("pageUrl") }, ++ { "PlayPath", AVC("playpath") }, ++ { "TcUrl", AVC("tcUrl") }, ++ { "IsLive", AVC("live") }, ++ { NULL } ++}; ++ ++bool CDVDInputStreamRTMP::Open() ++{ ++ if (m_sStreamPlaying) ++ { ++ free(m_sStreamPlaying); ++ m_sStreamPlaying = NULL; ++ } ++ ++ m_item.SetMimeType("video/x-flv"); ++ if (!m_rtmp || !CDVDInputStream::Open()) ++ return false; ++ ++ CSingleLock lock(m_RTMPSection); ++ ++ // libRTMP can and will alter strFile, so take a copy of it ++ m_sStreamPlaying = (char*)calloc(strlen(m_item.GetPath().c_str())+1,sizeof(char)); ++ strcpy(m_sStreamPlaying, m_item.GetPath().c_str()); ++ ++ if (!m_libRTMP.SetupURL(m_rtmp, m_sStreamPlaying)) ++ return false; ++ ++ /* Look for protocol options in the URL. ++ * Options are added to the URL in space separated key=value pairs. ++ * We are only interested in the "live" option to disable seeking, ++ * the rest is handled by librtmp internally ++ * ++ * example URL suitable for use with RTMP_SetupURL(): ++ * "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1 live=1" ++ * details: https://rtmpdump.mplayerhq.hu/librtmp.3.html ++ */ ++ std::string url = m_item.GetPath(); ++ size_t iPosBlank = url.find(' '); ++ if (iPosBlank != std::string::npos && (url.find("live=true") != std::string::npos || url.find("live=1") != std::string::npos)) ++ { ++ m_canSeek = false; ++ m_canPause = false; ++ m_realtime = true; ++ } ++ CLog::Log(LOGDEBUG, "RTMP canseek: %s", m_canSeek ? "true" : "false"); ++ ++ /* SetOpt and SetAVal copy pointers to the value. librtmp doesn't use the values until the Connect() call, ++ * so value objects must stay allocated until then. To be extra safe, keep the values around until Close(), ++ * in case librtmp needs them again. ++ */ ++ m_optionvalues.clear(); ++ for (int i=0; options[i].name; i++) ++ { ++ std::string tmp = m_item.GetProperty(options[i].name).asString(); ++ if (!tmp.empty()) ++ { ++ m_optionvalues.push_back(tmp); ++ AVal av_tmp; ++ SetAVal(av_tmp, m_optionvalues.back()); ++ m_libRTMP.SetOpt(m_rtmp, &options[i].key, &av_tmp); ++ } ++ } ++ ++ if (!m_libRTMP.Connect(m_rtmp, NULL) || !m_libRTMP.ConnectStream(m_rtmp, 0)) ++ return false; ++ ++ m_eof = false; ++ ++ return true; ++} ++ ++// close file and reset everything ++void CDVDInputStreamRTMP::Close() ++{ ++ CSingleLock lock(m_RTMPSection); ++ CDVDInputStream::Close(); ++ ++ if (m_rtmp) ++ m_libRTMP.Close(m_rtmp); ++ ++ m_optionvalues.clear(); ++ m_eof = true; ++ m_bPaused = false; ++} ++ ++int CDVDInputStreamRTMP::Read(uint8_t* buf, int buf_size) ++{ ++ if (!m_rtmp) ++ return -1; ++ ++ int i = m_libRTMP.Read(m_rtmp, (char *)buf, buf_size); ++ if (i < 0) ++ m_eof = true; ++ ++ return i; ++} ++ ++int64_t CDVDInputStreamRTMP::Seek(int64_t offset, int whence) ++{ ++ if (whence == SEEK_POSSIBLE) ++ return 0; ++ else ++ return -1; ++} ++ ++bool CDVDInputStreamRTMP::PosTime(int iTimeInMsec) ++{ ++ CLog::Log(LOGNOTICE, "RTMP Seek to %i requested", iTimeInMsec); ++ CSingleLock lock(m_RTMPSection); ++ ++ if (m_rtmp && m_libRTMP.SendSeek(m_rtmp, iTimeInMsec)) ++ return true; ++ ++ return false; ++} ++ ++int64_t CDVDInputStreamRTMP::GetLength() ++{ ++ return -1; ++} ++ ++bool CDVDInputStreamRTMP::Pause(double dTime) ++{ ++ CSingleLock lock(m_RTMPSection); ++ ++ m_bPaused = !m_bPaused; ++ ++ CLog::Log(LOGNOTICE, "RTMP Pause %s requested", m_bPaused ? "TRUE" : "FALSE"); ++ ++ if (m_rtmp) ++ m_libRTMP.Pause(m_rtmp, m_bPaused); ++ ++ return true; ++} ++#endif +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.h +new file mode 100644 +index 0000000..5af246a +--- /dev/null ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamRTMP.h +@@ -0,0 +1,61 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifdef HAS_LIBRTMP ++ ++#include "DVDInputStream.h" ++#include "DllLibRTMP.h" ++ ++class CDVDInputStreamRTMP ++ : public CDVDInputStream ++ , public CDVDInputStream::IPosTime ++{ ++public: ++ CDVDInputStreamRTMP(const CFileItem &fileitem); ++ virtual ~CDVDInputStreamRTMP(); ++ virtual bool Open(); ++ virtual void Close(); ++ virtual int Read(uint8_t* buf, int buf_size); ++ virtual int64_t Seek(int64_t offset, int whence); ++ bool PosTime(int iTimeInMsec); ++ bool CanSeek() { return m_canSeek; } ++ bool CanPause() { return m_canPause; } ++ virtual bool Pause(double dTime); ++ virtual bool IsEOF(); ++ virtual int64_t GetLength(); ++ ++ CDVDInputStream::IPosTime* GetIPosTime() override { return this; } ++ ++ CCriticalSection m_RTMPSection; ++ ++protected: ++ bool m_eof; ++ bool m_bPaused; ++ bool m_canSeek; ++ bool m_canPause; ++ char* m_sStreamPlaying; ++ std::vector m_optionvalues; ++ ++ RTMP *m_rtmp; ++ DllLibRTMP m_libRTMP; ++}; ++ ++#endif +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.h +index 3ff964e..a00fed4 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.h ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamStack.h +@@ -22,7 +22,6 @@ + + #include "DVDInputStream.h" + #include +-#include + + class CDVDInputStreamStack : public CDVDInputStream + { +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DllLibRTMP.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DllLibRTMP.h +new file mode 100644 +index 0000000..ac58132 +--- /dev/null ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DllLibRTMP.h +@@ -0,0 +1,79 @@ ++#pragma once ++ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "DynamicDll.h" ++ ++#include ++#include ++ ++class DllLibRTMPInterface ++{ ++public: ++ virtual ~DllLibRTMPInterface() {} ++ virtual void LogSetLevel(int level)=0; ++ virtual void LogSetCallback(RTMP_LogCallback* cb)=0; ++ virtual RTMP *Alloc(void)=0; ++ virtual void Free(RTMP* r)=0; ++ virtual void Init(RTMP* r)=0; ++ virtual void Close(RTMP* r)=0; ++ virtual bool SetupURL(RTMP* r, char* url)=0; ++ virtual bool SetOpt(RTMP* r, const AVal* opt, AVal* arg)=0; ++ virtual bool Connect(RTMP* r, RTMPPacket* cp)=0; ++ virtual bool ConnectStream(RTMP* r, int seekTime)=0; ++ virtual int Read(RTMP* r, char* buf, int size)=0; ++ virtual bool SendSeek(RTMP*r, int dTime)=0; ++ virtual bool Pause(RTMP* r, bool DoPause)=0; ++}; ++ ++class DllLibRTMP : public DllDynamic, DllLibRTMPInterface ++{ ++ DECLARE_DLL_WRAPPER(DllLibRTMP, DLL_PATH_LIBRTMP) ++ DEFINE_METHOD1(void, LogSetLevel, (int p1)) ++ DEFINE_METHOD1(void, LogSetCallback, (RTMP_LogCallback* p1)) ++ DEFINE_METHOD0(RTMP *, Alloc ) ++ DEFINE_METHOD1(void, Free, (RTMP* p1)) ++ DEFINE_METHOD1(void, Init, (RTMP* p1)) ++ DEFINE_METHOD1(void, Close, (RTMP* p1)) ++ DEFINE_METHOD2(bool, SetupURL, (RTMP* p1, char* p2)) ++ DEFINE_METHOD3(bool, SetOpt, (RTMP* p1, const AVal* p2, AVal* p3)) ++ DEFINE_METHOD2(bool, Connect, (RTMP* p1, RTMPPacket* p2)) ++ DEFINE_METHOD2(bool, ConnectStream, (RTMP* p1, int p2)) ++ DEFINE_METHOD3(int, Read, (RTMP* p1, char* p2, int p3)) ++ DEFINE_METHOD2(bool, SendSeek, (RTMP* p1, int p2)) ++ DEFINE_METHOD2(bool, Pause, (RTMP* p1, bool p2)) ++ BEGIN_METHOD_RESOLVE() ++ RESOLVE_METHOD_RENAME(RTMP_LogSetLevel,LogSetLevel) ++ RESOLVE_METHOD_RENAME(RTMP_LogSetCallback,LogSetCallback) ++ RESOLVE_METHOD_RENAME(RTMP_Alloc,Alloc) ++ RESOLVE_METHOD_RENAME(RTMP_Free,Free) ++ RESOLVE_METHOD_RENAME(RTMP_Init,Init) ++ RESOLVE_METHOD_RENAME(RTMP_Close,Close) ++ RESOLVE_METHOD_RENAME(RTMP_SetupURL,SetupURL) ++ RESOLVE_METHOD_RENAME(RTMP_SetOpt,SetOpt) ++ RESOLVE_METHOD_RENAME(RTMP_Connect,Connect) ++ RESOLVE_METHOD_RENAME(RTMP_ConnectStream,ConnectStream) ++ RESOLVE_METHOD_RENAME(RTMP_Read,Read) ++ RESOLVE_METHOD_RENAME(RTMP_SendSeek,SendSeek) ++ RESOLVE_METHOD_RENAME(RTMP_Pause,Pause) ++ END_METHOD_RESOLVE() ++}; ++ +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h +index 57fb887..f0d0d49 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h +@@ -20,9 +20,6 @@ + + #pragma once + +-#include +-#include +- + #include "DVDInputStream.h" + #include "addons/InputStream.h" + +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/Makefile b/xbmc/cores/VideoPlayer/DVDInputStreams/Makefile +index 2cd0f71..1809e63 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/Makefile ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/Makefile +@@ -8,6 +8,7 @@ SRCS= DVDFactoryInputStream.cpp \ + DVDInputStreamFile.cpp \ + DVDInputStreamMemory.cpp \ + DVDInputStreamNavigator.cpp \ ++ DVDInputStreamRTMP.cpp \ + DVDInputStreamPVRManager.cpp \ + DVDInputStreamStack.cpp \ + InputStreamAddon.cpp \ +diff --git a/xbmc/cores/VideoPlayer/DVDMessage.h b/xbmc/cores/VideoPlayer/DVDMessage.h +index dadc640..20bfd94 100644 +--- a/xbmc/cores/VideoPlayer/DVDMessage.h ++++ b/xbmc/cores/VideoPlayer/DVDMessage.h +@@ -48,12 +48,12 @@ public: + GENERAL_RESYNC, // + GENERAL_FLUSH, // flush all buffers + GENERAL_RESET, // reset codecs for new data +- GENERAL_PAUSE, + GENERAL_STREAMCHANGE, // + GENERAL_SYNCHRONIZE, // + GENERAL_GUI_ACTION, // gui action of some sort + GENERAL_EOF, // eof of stream + ++ + // player core related messages (cVideoPlayer.cpp) + + PLAYER_SET_AUDIOSTREAM, // +diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp +index e59c84c..db1a651 100644 +--- a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp ++++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp +@@ -54,6 +54,8 @@ void CDVDStreamInfo::Clear() + + fpsscale = 0; + fpsrate = 0; ++ rfpsscale= 0; ++ rfpsrate = 0; + height = 0; + width = 0; + aspect = 0.0; +@@ -98,6 +100,8 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) + // VIDEO + if( fpsscale != right.fpsscale + || fpsrate != right.fpsrate ++ || rfpsscale!= right.rfpsscale ++ || rfpsrate != right.rfpsrate + || height != right.height + || width != right.width + || stills != right.stills +@@ -162,6 +166,8 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) + // VIDEO + fpsscale = right.fpsscale; + fpsrate = right.fpsrate; ++ rfpsscale= right.rfpsscale; ++ rfpsrate = right.rfpsrate; + height = right.height; + width = right.width; + aspect = right.aspect; +@@ -224,6 +230,8 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) + const CDemuxStreamVideo *stream = static_cast(&right); + fpsscale = stream->iFpsScale; + fpsrate = stream->iFpsRate; ++ rfpsscale = stream->irFpsScale; ++ rfpsrate = stream->irFpsRate; + height = stream->iHeight; + width = stream->iWidth; + aspect = stream->fAspect; +diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.h b/xbmc/cores/VideoPlayer/DVDStreamInfo.h +index f141708..2252d65 100644 +--- a/xbmc/cores/VideoPlayer/DVDStreamInfo.h ++++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.h +@@ -61,6 +61,8 @@ public: + // VIDEO + int fpsscale; // scale of 1001 and a rate of 60000 will result in 59.94 fps + int fpsrate; ++ int rfpsscale; ++ int rfpsrate; + int height; // height of the stream reported by the demuxer + int width; // width of the stream reported by the demuxer + float aspect; // display aspect as reported by demuxer +diff --git a/xbmc/cores/VideoPlayer/Edl.cpp b/xbmc/cores/VideoPlayer/Edl.cpp +index ca60764..1775eac 100644 +--- a/xbmc/cores/VideoPlayer/Edl.cpp ++++ b/xbmc/cores/VideoPlayer/Edl.cpp +@@ -98,7 +98,8 @@ bool CEdl::ReadEditDecisionLists(const std::string& strMovie, const float fFrame + */ + if ((URIUtils::IsHD(strMovie) || + URIUtils::IsSmb(strMovie) || +- URIUtils::IsNfs(strMovie)) && ++ URIUtils::IsNfs(strMovie) || ++ URIUtils::IsAfp(strMovie)) && + !URIUtils::IsPVRRecording(strMovie) && + !URIUtils::IsInternetStream(strMovie)) + { +@@ -749,8 +750,8 @@ int CEdl::RemoveCutTime(int iSeek) const + if (!HasCut()) + return iSeek; + +- /** +- * @todo Consider an optimisation of using the (now unused) total cut time if the seek time ++ /* ++ * TODO: Consider an optimisation of using the (now unused) total cut time if the seek time + * requested is later than the end of the last recorded cut. For example, when calculating the + * total duration for display. + */ +diff --git a/xbmc/cores/VideoPlayer/IVideoPlayer.h b/xbmc/cores/VideoPlayer/IVideoPlayer.h +index aa9033a..6cd95bb 100644 +--- a/xbmc/cores/VideoPlayer/IVideoPlayer.h ++++ b/xbmc/cores/VideoPlayer/IVideoPlayer.h +@@ -20,10 +20,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "DVDClock.h" + + #define VideoPlayer_AUDIO 1 +@@ -107,7 +103,6 @@ class IVideoPlayer + { + public: + virtual int OnDVDNavResult(void* pData, int iMessage) = 0; +- virtual void GetVideoResolution(unsigned int &width, unsigned int &height) = 0; + virtual ~IVideoPlayer() { } + }; + +diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp +index 9ed9176..fc3746c 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp +@@ -895,7 +895,7 @@ void CVideoPlayer::OpenDefaultStreams(bool reset) + + // open video stream + valid = false; +- ++ + for (const auto &stream : m_SelectionStreams.Get(STREAM_VIDEO, PredicateVideoPriority)) + { + if(OpenStream(m_CurrentVideo, stream.demuxerId, stream.id, stream.source, reset)) +@@ -2369,10 +2369,10 @@ void CVideoPlayer::SynchronizePlayers(unsigned int sources) + + if (m_CurrentVideo.id >= 0) + m_VideoPlayerVideo->SendMessage(message->Acquire()); +-//! @todo we have to rewrite the sync class, to not require +-//! all other players waiting for subtitle, should only +-//! be the oposite way +-/* if (m_CurrentSubtitle.id >= 0) ++/* TODO - we have to rewrite the sync class, to not require ++ all other players waiting for subtitle, should only ++ be the oposite way ++ if (m_CurrentSubtitle.id >= 0) + m_VideoPlayerSubtitle->SendMessage(message->Acquire()); + */ + message->Release(); +@@ -2485,11 +2485,11 @@ void CVideoPlayer::HandleMessages() + int time = msg.GetRestore() ? m_Edl.RestoreCutTime(msg.GetTime()) : msg.GetTime(); + + // if input stream doesn't support ISeekTime, convert back to pts +- //! @todo +- //! After demuxer we add an offset to input pts so that displayed time and clock are +- //! increasing steadily. For seeking we need to determine the boundaries and offset +- //! of the desired segment. With the current approach calculated time may point +- //! to nirvana ++ // TODO: ++ // After demuxer we add an offset to input pts so that displayed time and clock are ++ // increasing steadily. For seeking we need to determine the boundaries and offset ++ // of the desired segment. With the current approach calculated time may point ++ // to nirvana + if (m_pInputStream->GetIPosTime() == nullptr) + time -= DVD_TIME_TO_MSEC(m_State.time_offset); + +@@ -2738,8 +2738,8 @@ void CVideoPlayer::HandleMessages() + { + FlushBuffers(false); + CDVDInputStreamPVRManager* input = dynamic_cast(m_pInputStream); +- //! @todo find a better solution for the "otherStreaHack" +- //! a stream is not sopposed to be terminated before demuxer ++ // TODO find a better solution for the "otherStreaHack" ++ // a stream is not sopposed to be terminated before demuxer + if (input && input->IsOtherStreamHack()) + { + SAFE_DELETE(m_pDemuxer); +@@ -3714,7 +3714,12 @@ bool CVideoPlayer::OpenVideoStream(CDVDStreamInfo& hint, bool reset) + m_SelectionStreams.Clear(STREAM_NONE, STREAM_SOURCE_VIDEOMUX); + } + ++ // TODO desired resolution needs to come from somewhere else ++ RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); ++ m_pDemuxer->SetVideoResolution(res.iWidth, res.iHeight); ++ + return true; ++ + } + + bool CVideoPlayer::OpenSubtitleStream(CDVDStreamInfo& hint) +@@ -4135,13 +4140,6 @@ int CVideoPlayer::OnDVDNavResult(void* pData, int iMessage) + return NAVRESULT_NOP; + } + +-void CVideoPlayer::GetVideoResolution(unsigned int &width, unsigned int &height) +-{ +- RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); +- width = res.iWidth; +- height = res.iHeight; +-} +- + bool CVideoPlayer::ShowPVRChannelInfo(void) + { + bool bReturn(false); +@@ -5024,17 +5022,11 @@ void CVideoPlayer::GetDebugInfo(std::string &audio, std::string &video, std::str + void CVideoPlayer::OnLostDisplay() + { + CLog::Log(LOGNOTICE, "VideoPlayer: OnLostDisplay received"); +- m_VideoPlayerAudio->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, true), 1); +- m_VideoPlayerVideo->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, true), 1); +- m_clock.Pause(true); + m_displayLost = true; + } + + void CVideoPlayer::OnResetDisplay() + { + CLog::Log(LOGNOTICE, "VideoPlayer: OnResetDisplay received"); +- m_VideoPlayerAudio->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, false), 1); +- m_VideoPlayerVideo->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, false), 1); +- m_clock.Pause(false); + m_displayLost = false; + } +diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h +index 560b975..40573c6 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayer.h ++++ b/xbmc/cores/VideoPlayer/VideoPlayer.h +@@ -22,7 +22,6 @@ + + #include + #include +-#include + #include "cores/IPlayer.h" + #include "cores/VideoPlayer/VideoRenderers/RenderManager.h" + #include "threads/Thread.h" +@@ -350,8 +349,7 @@ public: + virtual bool IsCaching() const { return m_caching > CACHESTATE_DONE && m_caching < CACHESTATE_PLAY; } + virtual int GetCacheLevel() const ; + +- virtual int OnDVDNavResult(void* pData, int iMessage) override; +- void GetVideoResolution(unsigned int &width, unsigned int &height) override; ++ virtual int OnDVDNavResult(void* pData, int iMessage); + + virtual bool ControlsVolume() {return m_omxplayer_mode;} + +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp +index fb1d993..39c23ca 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp +@@ -67,7 +67,6 @@ CVideoPlayerAudio::CVideoPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent + m_audioClock = 0; + m_speed = DVD_PLAYSPEED_NORMAL; + m_stalled = true; +- m_paused = false; + m_syncState = IDVDStreamPlayer::SYNC_STARTING; + m_silence = false; + m_synctype = SYNC_DISCON; +@@ -250,12 +249,9 @@ void CVideoPlayerAudio::Process() + if (m_syncState == IDVDStreamPlayer::SYNC_WAITSYNC) + priority = 1; + +- if (m_paused) +- priority = 1; +- + // consider stream stalled if queue is empty + // we can't sync audio to clock with an empty queue +- if (ALLOW_AUDIO(m_speed) && !m_stalled && !m_paused) ++ if (ALLOW_AUDIO(m_speed) && !m_stalled) + { + timeout = 0; + } +@@ -359,11 +355,6 @@ void CVideoPlayerAudio::Process() + OpenStream(msg->m_hints, msg->m_codec); + msg->m_codec = NULL; + } +- else if (pMsg->IsType(CDVDMsg::GENERAL_PAUSE)) +- { +- m_paused = static_cast(pMsg)->m_value; +- CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_PAUSE: %d", m_paused); +- } + else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) + { + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); +@@ -494,6 +485,8 @@ void CVideoPlayerAudio::Process() + } + } + } ++ ++ UpdatePlayerInfo(); + } + + // guess next pts +@@ -545,9 +538,10 @@ bool CVideoPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + { + double syncerror = m_dvdAudio.GetSyncError(); + +- if (m_synctype == SYNC_DISCON && fabs(syncerror) > DVD_MSEC_TO_TIME(10)) ++ if (m_synctype == SYNC_DISCON) + { +- double correction = m_pClock->ErrorAdjust(syncerror, "CVideoPlayerAudio::OutputPacket"); ++ double error = syncerror; ++ double correction = m_pClock->ErrorAdjust(error, "CVideoPlayerAudio::OutputPacket"); + if (correction != 0) + { + m_dvdAudio.SetSyncErrorCorrection(-correction); +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerAudio.h b/xbmc/cores/VideoPlayer/VideoPlayerAudio.h +index d1653e0..f6b5003 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerAudio.h ++++ b/xbmc/cores/VideoPlayer/VideoPlayerAudio.h +@@ -99,7 +99,6 @@ protected: + int m_speed; + bool m_stalled; + bool m_silence; +- bool m_paused; + IDVDStreamPlayer::ESyncState m_syncState; + XbmcThreads::EndTime m_syncTimer; + +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerTeletext.cpp b/xbmc/cores/VideoPlayer/VideoPlayerTeletext.cpp +index 89c8365..dea99c7 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerTeletext.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayerTeletext.cpp +@@ -609,7 +609,7 @@ void CDVDTeletextData::Process() + case 2: /* page key */ + break; /* ignore */ + case 3: /* types of PTUs in DRCS */ +- break; //! @todo implement ++ break; /* TODO */ + case 4: /* CLUTs 0/1, only level 3.5 */ + break; /* ignore */ + default: +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +index 8e5d33d..7ee8702 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +@@ -38,6 +38,9 @@ + #include + #include + #include "utils/log.h" ++#ifdef HAS_IMXVPU ++#include "DVDCodecs/Video/DVDVideoCodecIMX.h" ++#endif + + using namespace RenderManager; + +@@ -77,7 +80,6 @@ CVideoPlayerVideo::CVideoPlayerVideo(CDVDClock* pClock + + m_bRenderSubs = false; + m_stalled = false; +- m_paused = false; + m_syncState = IDVDStreamPlayer::SYNC_STARTING; + m_iSubtitleDelay = 0; + m_iLateFrames = 0; +@@ -260,9 +262,6 @@ void CVideoPlayerVideo::Process() + if (m_syncState == IDVDStreamPlayer::SYNC_WAITSYNC) + iPriority = 1; + +- if (m_paused) +- iPriority = 1; +- + CDVDMsg* pMsg; + MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, iQueueTimeOut, iPriority); + +@@ -345,7 +344,7 @@ void CVideoPlayerVideo::Process() + + m_pullupCorrection.Flush(); + //we need to recalculate the framerate +- //! @todo this needs to be set on a streamchange instead ++ //TODO: this needs to be set on a streamchange instead + ResetFrameRateCalc(); + m_droppingStats.Reset(); + +@@ -400,11 +399,6 @@ void CVideoPlayerVideo::Process() + break; + } + } +- else if (pMsg->IsType(CDVDMsg::GENERAL_PAUSE)) +- { +- m_paused = static_cast(pMsg)->m_value; +- CLog::Log(LOGDEBUG, "CVideoPlayerVideo - CDVDMsg::GENERAL_PAUSE: %d", m_paused); +- } + else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) + { + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); +@@ -617,8 +611,8 @@ bool CVideoPlayerVideo::ProcessDecoderOutput(int &decoderState, double &frametim + m_syncState = IDVDStreamPlayer::SYNC_WAITSYNC; + SStartMsg msg; + msg.player = VideoPlayer_VIDEO; +- msg.cachetime = DVD_MSEC_TO_TIME(50); //! @todo implement +- msg.cachetotal = DVD_MSEC_TO_TIME(100); //! @todo implement ++ msg.cachetime = DVD_MSEC_TO_TIME(50); // TODO ++ msg.cachetotal = DVD_MSEC_TO_TIME(100); // TODO + msg.timestamp = hasTimestamp ? pts : DVD_NOPTS_VALUE; + m_messageParent.Put(new CDVDMsgType(CDVDMsg::PLAYER_STARTED, msg)); + } +@@ -778,6 +772,7 @@ int CVideoPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + } + + flags |= stereo_flags; ++ flags |= GetInterlacedModeFlag(m_pVideoCodec->GetInterlaced()); + + if(!m_renderManager.Configure(picture, + config_framerate, +@@ -799,8 +794,7 @@ int CVideoPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + } + + //try to calculate the framerate +- if (!m_stalled) +- CalcFrameRate(); ++ CalcFrameRate(); + + // signal to clock what our framerate is, it may want to adjust it's + // speed to better match with our video renderer's output speed +@@ -917,6 +911,9 @@ std::string CVideoPlayerVideo::GetPlayerInfo() + s << ", pc:" << pc; + else + s << ", pc:none"; ++#ifdef HAS_IMXVPU ++ s << ", " << ((CDVDVideoCodecIMX*)m_pVideoCodec)->GetPlayerInfo(); ++#endif + + return s.str(); + } +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.h b/xbmc/cores/VideoPlayer/VideoPlayerVideo.h +index 8ada932..4dff792 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.h ++++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.h +@@ -130,7 +130,6 @@ protected: + float m_fForcedAspectRatio; + int m_speed; + bool m_stalled; +- bool m_paused; + IDVDStreamPlayer::ESyncState m_syncState; + std::atomic_bool m_bAbortOutput; + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp +index f18c671..60224b6 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp +@@ -22,6 +22,7 @@ + + #include // std::abs(int) prototype + #include ++#include + #include "BaseRenderer.h" + #include "settings/DisplaySettings.h" + #include "settings/MediaSettings.h" +@@ -34,6 +35,7 @@ + #include "utils/SystemInfo.h" + #include "settings/AdvancedSettings.h" + #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" ++#include "cores/VideoPlayer/VideoRenderers/RenderManager.h" + + + CBaseRenderer::CBaseRenderer() +@@ -220,6 +222,14 @@ void CBaseRenderer::CalcNormalRenderRect(float offsetX, float offsetY, float wid + return; + } + ++#if defined(HAS_IMXVPU) ++ if (g_graphicsContext.GetResInfo().dwFlags & D3DPRESENTFLAG_INTERLACED) ++ { ++ inputFrameRatio = (float) width / height; ++ zoomAmount = 1.0f; ++ } ++#endif ++ + // scale up image as much as possible + // and keep the aspect ratio (introduces with black bars) + // calculate the correct output frame ratio (using the users pixel ratio setting +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt +index 91260dc..47e8212 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt +@@ -13,7 +13,7 @@ if(VDPAU_FOUND) + list(APPEND HEADERS RendererVDPAU.h) + endif() + +-if(CORE_SYSTEM_NAME STREQUAL osx) ++if(CORE_SYSTEM_NAME STREQUAL darwin) + list(APPEND SOURCES RendererVTBGL.cpp) + list(APPEND HEADERS RendererVTBGL.h) + endif() +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp +index cd57312..8097c65 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp +@@ -37,14 +37,12 @@ + + #define CLASSNAME "CMMALRenderer" + +-#define VERBOSE 0 + +-std::shared_ptr CMMALRenderer::GetPool(ERenderFormat format, AVPixelFormat pixfmt, bool opaque) ++MMAL_POOL_T *CMMALRenderer::GetPool(ERenderFormat format, bool opaque) + { + CSingleLock lock(m_sharedSection); +- bool formatChanged = m_format != format || m_opaque != opaque; +- if (!m_bMMALConfigured || formatChanged) +- m_bMMALConfigured = init_vout(format, pixfmt, opaque); ++ if (!m_bMMALConfigured) ++ m_bMMALConfigured = init_vout(format, opaque); + + return m_vout_input_pool; + } +@@ -55,7 +53,7 @@ CRenderInfo CMMALRenderer::GetRenderInfo() + CRenderInfo info; + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s opaque:%p", CLASSNAME, __func__, this); ++ CLog::Log(LOGDEBUG, "%s::%s cookie:%p", CLASSNAME, __func__, (void *)m_vout_input_pool); + + info.max_buffer_size = NUM_BUFFERS; + info.optimal_buffer_size = NUM_BUFFERS; +@@ -69,8 +67,8 @@ void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T * + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)); + buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER2; + CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data; +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s port:%p omvb:%p mmal:%p:%p len:%d cmd:%x flags:%x flight:%d", CLASSNAME, __func__, port, omvb, buffer, omvb->mmal_buffer, buffer->length, buffer->cmd, buffer->flags, m_inflight); ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "%s::%s YUV port:%p omvb:%p mmal:%p:%p len:%d cmd:%x flags:%x flight:%d", CLASSNAME, __func__, port, omvb, buffer, omvb->mmal_buffer, buffer->length, buffer->cmd, buffer->flags, m_inflight); + assert(buffer == omvb->mmal_buffer); + m_inflight--; + omvb->Release(); +@@ -82,78 +80,21 @@ static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *b + mmal->vout_input_port_cb(port, buffer); + } + +-static struct { +- uint32_t encoding; +- AVPixelFormat pixfmt; +-} pixfmt_to_encoding_table[] = +-{ +- {MMAL_ENCODING_I420, AV_PIX_FMT_YUV420P}, +- {MMAL_ENCODING_I422, AV_PIX_FMT_YUV422P}, +- {MMAL_ENCODING_I420, AV_PIX_FMT_YUVJ420P}, // FIXME +- {MMAL_ENCODING_I422, AV_PIX_FMT_YUVJ422P}, // FIXME +- {MMAL_ENCODING_RGB16, AV_PIX_FMT_RGB565}, +- {MMAL_ENCODING_RGB16, AV_PIX_FMT_RGB565LE}, +- {MMAL_ENCODING_BGR16, AV_PIX_FMT_BGR565}, +- {MMAL_ENCODING_RGB24, AV_PIX_FMT_RGB24}, +- {MMAL_ENCODING_BGR24, AV_PIX_FMT_BGR24}, +- {MMAL_ENCODING_ARGB, AV_PIX_FMT_ARGB}, +- {MMAL_ENCODING_RGBA, AV_PIX_FMT_RGBA}, +- {MMAL_ENCODING_ABGR, AV_PIX_FMT_ABGR}, +- {MMAL_ENCODING_BGRA, AV_PIX_FMT_BGRA}, +- {MMAL_ENCODING_BGRA, AV_PIX_FMT_BGR0}, +- {MMAL_ENCODING_UNKNOWN, AV_PIX_FMT_NONE} +-}; +- +-static uint32_t pixfmt_to_encoding(AVPixelFormat pixfmt) +-{ +- unsigned int i; +- for (i = 0; pixfmt_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++) +- if (pixfmt_to_encoding_table[i].pixfmt == pixfmt) +- break; +- return pixfmt_to_encoding_table[i].encoding; +-} +- +-CMMALPool::CMMALPool(MMAL_PORT_T *input, uint32_t num_buffers, uint32_t buffer_size) +-{ +- m_input = input; +- m_pool = mmal_port_pool_create(input, num_buffers, buffer_size); +- if (!m_pool) +- CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port", CLASSNAME, __func__); +- else +- CLog::Log(LOGDEBUG, "%s::%s Created pool %p of size %d x %d", CLASSNAME, __func__, m_pool, num_buffers, buffer_size); +-} +- +-CMMALPool::~CMMALPool() +-{ +- CLog::Log(LOGDEBUG, "%s::%s destroying pool (%p)", CLASSNAME, __func__, m_pool); +- mmal_port_pool_destroy(m_input, m_pool); +- m_pool = nullptr; +- m_input = nullptr; +-} +- +-bool CMMALRenderer::init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool opaque) ++bool CMMALRenderer::init_vout(ERenderFormat format, bool opaque) + { + CSingleLock lock(m_sharedSection); +- bool formatChanged = m_format != format || m_opaque != opaque || m_pixfmt != pixfmt; ++ bool formatChanged = m_format != format || m_opaque != opaque; + MMAL_STATUS_T status; +- uint32_t encoding = pixfmt_to_encoding(pixfmt); + +- CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d pixfmt %x->%x opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_pixfmt, pixfmt, m_opaque, opaque); ++ CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_opaque, opaque); + + if (m_bMMALConfigured && formatChanged) + UnInitMMAL(); + +- if (m_bMMALConfigured || format == RENDER_FMT_BYPASS) ++ if (m_bMMALConfigured || format != RENDER_FMT_MMAL) + return true; + +- if (format != RENDER_FMT_MMAL || encoding == MMAL_ENCODING_UNKNOWN) +- { +- CLog::Log(LOGERROR, "%s::%s Unsupported format", CLASSNAME, __func__); +- return false; +- } +- + m_format = format; +- m_pixfmt = pixfmt; + m_opaque = opaque; + + /* Create video renderer */ +@@ -181,7 +122,7 @@ bool CMMALRenderer::init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool o + es_format->es->video.width = m_sourceWidth; + es_format->es->video.height = m_sourceHeight; + +- es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : encoding; ++ es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : MMAL_ENCODING_I420; + + status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); + if (status != MMAL_SUCCESS) +@@ -211,7 +152,13 @@ bool CMMALRenderer::init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool o + return false; + } + +- m_vout_input_pool = std::make_shared(m_vout_input, m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0); ++ CLog::Log(LOGDEBUG, "%s::%s Created pool of size %d x %d", CLASSNAME, __func__, m_vout_input->buffer_num, m_vout_input->buffer_size); ++ m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0); ++ if (!m_vout_input_pool) ++ { ++ CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); ++ return false; ++ } + if (!CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock")) + { + m_queue = mmal_queue_create(); +@@ -229,7 +176,6 @@ CMMALRenderer::CMMALRenderer() : CThread("MMALRenderer") + memset(m_buffers, 0, sizeof m_buffers); + m_iFlags = 0; + m_format = RENDER_FMT_NONE; +- m_pixfmt = AV_PIX_FMT_YUV420P; + m_opaque = true; + m_bConfigured = false; + m_bMMALConfigured = false; +@@ -300,7 +246,7 @@ void CMMALRenderer::AddVideoPictureHW(DVDVideoPicture& pic, int index) + + CMMALBuffer *buffer = pic.MMALBuffer; + assert(buffer); +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s MMAL - %p (%p) %i", CLASSNAME, __func__, buffer, buffer->mmal_buffer, index); + + m_buffers[index] = buffer->Acquire(); +@@ -334,7 +280,7 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned + SetViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode); + ManageRenderArea(); + +- m_bMMALConfigured = init_vout(format, m_pixfmt, m_opaque); ++ m_bMMALConfigured = init_vout(format, m_opaque); + m_bConfigured = m_bMMALConfigured; + assert(m_bConfigured); + return m_bConfigured; +@@ -364,7 +310,7 @@ void CMMALRenderer::ReleaseBuffer(int idx) + } + + CMMALBuffer *omvb = m_buffers[idx]; +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - MMAL: source:%d omvb:%p mmal:%p flight:%d", CLASSNAME, __func__, idx, omvb, omvb ? omvb->mmal_buffer:NULL, m_inflight); + if (omvb) + SAFE_RELEASE(m_buffers[idx]); +@@ -477,7 +423,7 @@ void CMMALRenderer::FlipPage(int source) + return; + } + +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - source:%d", CLASSNAME, __func__, source); + + m_iYV12RenderBuffer = source; +@@ -504,7 +450,7 @@ void CMMALRenderer::PreInit() + + void CMMALRenderer::ReleaseBuffers() + { +- if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + for (int i=0; iGet() : nullptr); ++ CLog::Log(LOGDEBUG, "%s::%s pool(%p)", CLASSNAME, __func__, m_vout_input_pool); + if (m_queue) + { + StopThread(true); +@@ -533,8 +479,11 @@ void CMMALRenderer::UnInitMMAL() + + ReleaseBuffers(); + +- m_vout_input_pool = NULL; +- ++ if (m_vout_input_pool) ++ { ++ mmal_port_pool_destroy(m_vout_input, m_vout_input_pool); ++ m_vout_input_pool = NULL; ++ } + m_vout_input = NULL; + + if (m_vout) +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h +index e2c0223..d29bbef 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h +@@ -20,8 +20,6 @@ + * + */ + +-#include +- + #include "guilib/GraphicContext.h" + #include "../RenderFlags.h" + #include "../RenderFormats.h" +@@ -45,17 +43,6 @@ class CMMALBuffer; + + struct DVDVideoPicture; + +-class CMMALPool +-{ +-public: +- CMMALPool(MMAL_PORT_T *input, uint32_t num_buffers, uint32_t buffer_size); +- ~CMMALPool(); +- MMAL_POOL_T *Get() { return m_pool; } +-protected: +- MMAL_POOL_T *m_pool; +- MMAL_PORT_T *m_input; +-}; +- + class CMMALRenderer : public CBaseRenderer, public CThread + { + public: +@@ -96,7 +83,7 @@ public: + virtual bool IsGuiLayer() { return false; } + + void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); +- std::shared_ptr GetPool(ERenderFormat format, AVPixelFormat pixfmt, bool opaque); ++ MMAL_POOL_T *GetPool(ERenderFormat format, bool opaque); + protected: + int m_iYV12RenderBuffer; + int m_NumYV12Buffers; +@@ -116,16 +103,15 @@ protected: + bool m_StereoInvert; + int m_inflight; + bool m_opaque; +- AVPixelFormat m_pixfmt; + + CCriticalSection m_sharedSection; + MMAL_COMPONENT_T *m_vout; + MMAL_PORT_T *m_vout_input; +- std::shared_ptr m_vout_input_pool; ++ MMAL_POOL_T *m_vout_input_pool; + MMAL_QUEUE_T *m_queue; + double m_error; + +- bool init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool opaque); ++ bool init_vout(ERenderFormat format, bool opaque); + void ReleaseBuffers(); + void UnInitMMAL(); + }; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index d0baa27..f6b7bb1 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -27,18 +27,18 @@ + #include "cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h" + #include "utils/log.h" + #include "utils/GLUtils.h" +-#include "utils/SysfsUtils.h" + #include "settings/MediaSettings.h" + #include "windowing/WindowingFactory.h" + #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h" + + CRendererAML::CRendererAML() + { +- m_prevPts = -1; ++ + } + + CRendererAML::~CRendererAML() + { ++ + } + + bool CRendererAML::RenderCapture(CRenderCapture* capture) +@@ -118,7 +118,7 @@ bool CRendererAML::LoadShadersHook() + { + CLog::Log(LOGNOTICE, "GL: Using AML render method"); + m_textureTarget = GL_TEXTURE_2D; +- m_renderMethod = RENDER_BYPASS; ++ m_renderMethod = RENDER_FMT_AML; + return false; + } + +@@ -132,19 +132,15 @@ bool CRendererAML::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + ManageRenderArea(); + + CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iYV12RenderBuffer].hwDec); +- if (amli && amli->GetOmxPts() != m_prevPts) ++ if (amli) + { +- m_prevPts = amli->GetOmxPts(); +- SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", amli->GetOmxPts()); +- + CAMLCodec *amlcodec = amli->getAmlCodec(); + if (amlcodec) + amlcodec->SetVideoRect(m_sourceRect, m_destRect); + } + +- usleep(10000); +- + return true; + } + + #endif ++ +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +index 819f6e3..deea29b 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +@@ -55,9 +55,6 @@ protected: + virtual bool RenderHook(int index); + virtual int GetImageHook(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); + virtual bool RenderUpdateVideoHook(bool clear, DWORD flags = 0, DWORD alpha = 255); +- +-private: +- int m_prevPts; + }; + + #endif +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index ed5b643..ffd807d 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -30,10 +30,12 @@ + #include "windowing/WindowingFactory.h" + #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h" + #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" ++#include "linux/imx/IMX.h" + + #define RENDER_FLAG_FIELDS (RENDER_FLAG_FIELD0 | RENDER_FLAG_FIELD1) + + CRendererIMX::CRendererIMX() ++ : buffer_p(nullptr) + { + + } +@@ -41,6 +43,9 @@ CRendererIMX::CRendererIMX() + CRendererIMX::~CRendererIMX() + { + UnInit(); ++ SAFE_RELEASE(buffer_p); ++ g_IMXContext.Clear(); ++ g_IMX.Deinitialize(); + } + + bool CRendererIMX::RenderCapture(CRenderCapture* capture) +@@ -86,8 +91,12 @@ bool CRendererIMX::Supports(EINTERLACEMETHOD method) + if(method == VS_INTERLACEMETHOD_AUTO) + return true; + +- if(method == VS_INTERLACEMETHOD_IMX_FASTMOTION +- || method == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE) ++ if(method == VS_INTERLACEMETHOD_IMX_ADVMOTION ++ || method == VS_INTERLACEMETHOD_IMX_WEAVE ++ || method == VS_INTERLACEMETHOD_IMX_FASTMOTION ++ || method == VS_INTERLACEMETHOD_IMX_ADVMOTION_DOUBLE ++ || method == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE ++ || method == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE_INVERTED) + return true; + else + return false; +@@ -105,12 +114,12 @@ bool CRendererIMX::Supports(EDEINTERLACEMODE mode) + + bool CRendererIMX::Supports(ESCALINGMETHOD method) + { +- return false; ++ return method == VS_SCALINGMETHOD_AUTO; + } + + EINTERLACEMETHOD CRendererIMX::AutoInterlaceMethod() + { +- return VS_INTERLACEMETHOD_IMX_FASTMOTION; ++ return VS_INTERLACEMETHOD_IMX_ADVMOTION_DOUBLE; + } + + CRenderInfo CRendererIMX::GetRenderInfo() +@@ -138,6 +147,9 @@ bool CRendererIMX::RenderHook(int index) + + bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + { ++ static int bufPrev; ++ static DWORD flagsPrev; ++ + #if 0 + static unsigned long long previous = 0; + unsigned long long current = XbmcThreads::SystemClockMillis(); +@@ -145,8 +157,17 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + previous = current; + #endif + CDVDVideoCodecIMXBuffer *buffer = static_cast(m_buffers[m_iYV12RenderBuffer].hwDec); +- if (buffer != NULL && buffer->IsValid()) ++ if (buffer) + { ++ if (!(bufPrev ^ m_iYV12RenderBuffer | flagsPrev ^ flags)) ++ { ++ g_IMX.WaitVsync(); ++ return true; ++ } ++ ++ bufPrev = m_iYV12RenderBuffer; ++ flagsPrev = flags; ++ + // this hack is needed to get the 2D mode of a 3D movie going + RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode(); + if (stereo_mode) +@@ -178,25 +199,29 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + //CLog::Log(LOGDEBUG, "BLIT RECTS: source x1 %f x2 %f y1 %f y2 %f dest x1 %f x2 %f y1 %f y2 %f", srcRect.x1, srcRect.x2, srcRect.y1, srcRect.y2, dstRect.x1, dstRect.x2, dstRect.y1, dstRect.y2); + g_IMXContext.SetBlitRects(srcRect, dstRect); + +- uint8_t fieldFmt = 0; +- if (g_graphicsContext.IsFullScreenVideo()) ++ uint8_t fieldFmt = flags & RENDER_FLAG_FIELDMASK; ++ if (flags & RENDER_FLAG_FIELDS && g_graphicsContext.IsFullScreenVideo()) + { +- fieldFmt |= flags & RENDER_FLAG_FIELDMASK; +- if (flags & RENDER_FLAG_FIELDS) ++ fieldFmt |= IPU_DEINTERLACE_RATE_EN; ++ if (flags & RENDER_FLAG_FIELD1) + { +- fieldFmt |= IPU_DEINTERLACE_RATE_EN; +- if (flags & RENDER_FLAG_FIELD1) +- { +- fieldFmt |= IPU_DEINTERLACE_RATE_FRAME1; +- // CXBMCRenderManager::PresentFields() is swapping field flag for frame1 +- // this makes IPU render same picture as before, just shifted one line. +- // let's correct this +- fieldFmt ^= RENDER_FLAG_FIELDMASK; +- } ++ fieldFmt |= IPU_DEINTERLACE_RATE_FRAME1; ++ // CXBMCRenderManager::PresentFields() is swapping field flag for frame1 ++ // this makes IPU render same picture as before, just shifted one line. ++ // let's correct this ++ fieldFmt ^= RENDER_FLAG_FIELDMASK; + } + } + +- g_IMXContext.BlitAsync(NULL, buffer, fieldFmt); ++ g_IMXContext.Blit(buffer_p, buffer, fieldFmt); ++ ++ if (flags & RENDER_FLAG_FIELDMASK && !(flags & RENDER_FLAG_FIELD0)) ++ { ++ SAFE_RELEASE(buffer_p); ++ ++ buffer_p = buffer; ++ buffer_p->Lock(); ++ } + } + + #if 0 +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +index 22b1ed0..74f6888 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +@@ -60,6 +60,8 @@ protected: + virtual bool RenderHook(int index); + virtual int GetImageHook(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); + virtual bool RenderUpdateVideoHook(bool clear, DWORD flags = 0, DWORD alpha = 255); ++ ++ CDVDVideoCodecIMXBuffer *buffer_p; + }; + + #endif +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp +index 976dd36..95c6fea 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp +@@ -61,10 +61,9 @@ extern "C" { + #include "platform/darwin/DarwinUtils.h" + #endif + +-//! @bug +-//! due to a bug on osx nvidia, using gltexsubimage2d with a pbo bound and a null pointer +-//! screws up the alpha, an offset fixes this, there might still be a problem if stride + PBO_OFFSET +-//! is a multiple of 128 and deinterlacing is on ++//due to a bug on osx nvidia, using gltexsubimage2d with a pbo bound and a null pointer ++//screws up the alpha, an offset fixes this, there might still be a problem if stride + PBO_OFFSET ++//is a multiple of 128 and deinterlacing is on + #define PBO_OFFSET 16 + + using namespace Shaders; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h +index e92010b..41a696d 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h +@@ -23,8 +23,6 @@ + #include "system.h" + + #ifdef HAS_GL +-#include +- + #include "system_gl.h" + + #include "FrameBufferObject.h" +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp +index 3760970..30c686d 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp +@@ -940,7 +940,7 @@ void CLinuxRendererGLES::RenderSinglePass(int index, int field) + + void CLinuxRendererGLES::RenderMultiPass(int index, int field) + { +- //! @todo Multipass rendering does not currently work! FIX! ++ // TODO: Multipass rendering does not currently work! FIX! + CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!"); + return; + +@@ -996,7 +996,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) + m_pYUVProgShader->SetField(0); + + VerifyGLState(); +-//! @todo implement section ++//TODO + // glPushAttrib(GL_VIEWPORT_BIT); + // glPushAttrib(GL_SCISSOR_BIT); + glMatrixModview.Push(); +@@ -1017,7 +1017,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) + } + + // 1st Pass to video frame size +-//! @todo implement section ++//TODO + // float imgwidth = planes[0].rect.x2 - planes[0].rect.x1; + // float imgheight = planes[0].rect.y2 - planes[0].rect.y1; + // if (m_textureTarget == GL_TEXTURE_2D) +@@ -1056,7 +1056,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) + glMatrixModview.PopLoad(); + glMatrixProject.PopLoad(); + +-//! @todo implement section ++//TODO + // glPopAttrib(); // pop scissor + // glPopAttrib(); // pop viewport + VerifyGLState(); +@@ -1091,7 +1091,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) + + VerifyGLState(); + +-//! @todo implement section ++//TODO + // imgwidth /= m_sourceWidth; + // imgheight /= m_sourceHeight; + // +@@ -1200,6 +1200,12 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) + return; + } + ++ bool deinterlacing = false; ++ if (m_currentField == FIELD_FULL) ++ deinterlacing = false; ++ else ++ deinterlacing = true; ++ + glEnable(m_textureTarget); + VerifyGLState(); + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h +index afc130e..8af1ad3 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h +@@ -22,7 +22,6 @@ + */ + + #if HAS_GLES == 2 +-#include + + #include "system_gl.h" + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGUI.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGUI.cpp +index e6b92e4..d308029 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGUI.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGUI.cpp +@@ -159,11 +159,6 @@ void COverlayText::PrepareRender(const std::string &font, int color, int height, + if (!m_layout) + m_layout = GetFontLayout(font, color, height, style, fontcache, fontbordercache); + +- if (m_layout == NULL) +- { +- CLog::Log(LOGERROR, "COverlayText::PrepareRender - GetFontLayout failed for font %s", font.c_str()); +- return; +- } + RESOLUTION_INFO res = g_graphicsContext.GetResInfo(); + float width_max = (float)res.Overscan.right - res.Overscan.left; + m_layout->Update(m_text, width_max * 0.9f, false, true); // true to force LTR reading order (most Hebrew subs are this format) +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.cpp +index 809766a..b4c6586 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.cpp +@@ -108,6 +108,11 @@ namespace RenderManager { + return convert[mode]; + } + ++ unsigned int GetInterlacedModeFlag(bool interlaced) ++ { ++ return interlaced ? CONF_FLAGS_INTERLACED : 0; ++ } ++ + std::string GetStereoModeInvert(const std::string& mode) + { + static std::map convert; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h +index f65d4b2..39e4743 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h +@@ -79,7 +79,9 @@ + #define CONF_FLAGS_STEREO_CADANCE_LEFT_RIGHT 0x000000 + #define CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT 0x008000 + +- ++/* defines interlaced modes */ ++#define CONF_FLAGS_INTERLACED 0x010000 ++#define CONF_FLAGS_INTERLACED_MODE_MASK(a) ((a) & CONF_FLAGS_INTERLACED) + + namespace RenderManager { + +@@ -88,6 +90,7 @@ namespace RenderManager { + unsigned int GetFlagsColorPrimaries(unsigned int color_primaries); + unsigned int GetFlagsColorTransfer(unsigned int color_transfer); + unsigned int GetStereoModeFlags(const std::string& mode); ++ unsigned int GetInterlacedModeFlag(bool interlaced); + std::string GetStereoModeInvert(const std::string& mode); + + } +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp +index 93f8d6f..9e0b81d 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp +@@ -799,6 +799,9 @@ void CRenderManager::FlipPage(volatile std::atomic_bool& bStop, double pts /* = + EDEINTERLACEMODE deinterlacemode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode; + EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod); + ++ if(g_advancedSettings.m_videoDisableBackgroundDeinterlace && !g_graphicsContext.IsFullScreenVideo()) ++ deinterlacemode = VS_DEINTERLACEMODE_OFF; ++ + if (deinterlacemode == VS_DEINTERLACEMODE_OFF) + { + presentmethod = PRESENT_METHOD_SINGLE; +@@ -811,32 +814,22 @@ void CRenderManager::FlipPage(volatile std::atomic_bool& bStop, double pts /* = + else + { + bool invert = false; +- if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) +- presentmethod = PRESENT_METHOD_BLEND; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) +- presentmethod = PRESENT_METHOD_WEAVE; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) +- { +- presentmethod = PRESENT_METHOD_WEAVE; +- invert = true; +- } +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) +- presentmethod = PRESENT_METHOD_BOB; +- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) +- { +- presentmethod = PRESENT_METHOD_BOB; +- invert = true; +- } +- else if (interlacemethod == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE) +- presentmethod = PRESENT_METHOD_BOB; +- else +- presentmethod = PRESENT_METHOD_SINGLE; ++ if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) presentmethod = PRESENT_METHOD_BLEND; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) presentmethod = PRESENT_METHOD_WEAVE; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; } ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) presentmethod = PRESENT_METHOD_BOB; ++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; } ++ else if (interlacemethod == VS_INTERLACEMETHOD_IMX_ADVMOTION_DOUBLE) presentmethod = PRESENT_METHOD_BOB; ++ else if (interlacemethod == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE) presentmethod = PRESENT_METHOD_BOB; ++ else if (interlacemethod == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE_INVERTED) ++ { presentmethod = PRESENT_METHOD_BOB; invert = true; } ++ else presentmethod = PRESENT_METHOD_SINGLE; + + if (presentmethod != PRESENT_METHOD_SINGLE) + { + /* default to odd field if we want to deinterlace and don't know better */ + if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && sync == FS_NONE) +- sync = FS_TOP; ++ sync = FS_TOP; + + /* invert present field */ + if (invert) +@@ -881,11 +874,22 @@ RESOLUTION CRenderManager::GetResolution() + return res; + + if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) != ADJUST_REFRESHRATE_OFF) +- res = CResolutionUtils::ChooseBestResolution(m_fps, m_width, CONF_FLAGS_STEREO_MODE_MASK(m_flags)); ++ res = CResolutionUtils::ChooseBestResolution(m_fps, m_width, m_height, CONF_FLAGS_STEREO_MODE_MASK(m_flags), CONF_FLAGS_INTERLACED_MODE_MASK(m_flags)); + + return res; + } + ++float CRenderManager::GetMaximumFPS() ++{ ++ float fps; ++ ++ fps = (float)m_dvdClock.GetRefreshRate(); ++ if (fps <= 0) ++ fps = g_graphicsContext.GetFPS(); ++ ++ return fps; ++} ++ + void CRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui) + { + CSingleExit exitLock(g_graphicsContext); +@@ -1076,7 +1080,7 @@ void CRenderManager::UpdateResolution() + { + if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) != ADJUST_REFRESHRATE_OFF && m_fps > 0.0f) + { +- RESOLUTION res = CResolutionUtils::ChooseBestResolution(m_fps, m_width, CONF_FLAGS_STEREO_MODE_MASK(m_flags)); ++ RESOLUTION res = CResolutionUtils::ChooseBestResolution(m_fps, m_width, m_height, CONF_FLAGS_STEREO_MODE_MASK(m_flags), CONF_FLAGS_INTERLACED_MODE_MASK(m_flags)); + g_graphicsContext.SetVideoResolution(res); + UpdateDisplayLatency(); + +@@ -1307,7 +1311,7 @@ void CRenderManager::PrepareNextRender() + } + + double frameOnScreen = m_dvdClock.GetClock(); +- double frametime = 1.0 / g_graphicsContext.GetFPS() * DVD_TIME_BASE; ++ double frametime = 1.0 / GetMaximumFPS() * DVD_TIME_BASE; + + // correct display latency + // internal buffers of driver, assume that driver lets us go one frame in advance +@@ -1333,10 +1337,6 @@ void CRenderManager::PrepareNextRender() + } + renderPts += frametime / 2 - m_clockSync.m_syncOffset; + } +- else +- { +- m_dvdClock.SetVsyncAdjust(0); +- } + + if (renderPts >= nextFramePts) + { +@@ -1403,6 +1403,12 @@ bool CRenderManager::GetStats(int &lateframes, double &pts, int &queued, int &di + + void CRenderManager::CheckEnableClockSync() + { ++ if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK)) ++ { ++ m_clockSync.m_enabled = true; ++ return; ++ } ++ + // refresh rate can be a multiple of video fps + double diff = 1.0; + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h +index bce8892..894e9c2 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h +@@ -96,6 +96,7 @@ public: + bool Supports(ESCALINGMETHOD method); + EINTERLACEMETHOD AutoInterlaceMethod(EINTERLACEMETHOD mInt); + ++ float GetMaximumFPS(); + int GetSkippedFrames() { return m_QueueSkip; } + + // Functions called from mplayer +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp +index 72ffa0d..b6cd2e2 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp +@@ -72,7 +72,7 @@ void GLSLOutput::OnCompiledAndLinked(GLuint programHandle) + + if (m_dither) + { +- //! @todo create a dither pattern ++ // TODO: create a dither pattern + + // create a dither texture + glGenTextures(1, &m_tDitherTex); +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h +index f349cf7..554dda2 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h +@@ -21,8 +21,6 @@ + */ + + #ifdef HAS_DX +-#include +-#include + + #include "../../guilib/Geometry.h" + #include "../WinRenderer.h" +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h +index e7adc1c..d4f3984 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h +@@ -21,7 +21,6 @@ + */ + + #if !defined(TARGET_POSIX) && !defined(HAS_GL) +-#include + + #include "BaseRenderer.h" + #include "HwDecRender/DXVAHD.h" +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index d2560aa..7c689a8 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1545,7 +1545,7 @@ bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned + } + } + +- //! @todo jpeg decoder can decimate by factors of 2 ++ // TODO: jpeg decoder can decimate by factors of 2 + port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; + if (m_omx_resize.IsInitialized()) + port_def.format.image.nSliceHeight = 16; +@@ -2004,7 +2004,7 @@ bool COMXTexture::HandlePortSettingChange(unsigned int resize_width, unsigned in + return false; + } + +- //! @todo jpeg decoder can decimate by factors of 2 ++ // TODO: jpeg decoder can decimate by factors of 2 + port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; + port_def.format.image.nSliceHeight = 16; + port_def.format.image.nStride = 0; +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 236f1b3..b0f5ae1 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -475,8 +475,8 @@ void OMXPlayerVideo::Process() + m_syncState = IDVDStreamPlayer::SYNC_WAITSYNC; + SStartMsg msg; + msg.player = VideoPlayer_VIDEO; +- msg.cachetime = DVD_MSEC_TO_TIME(50); //! @todo implement +- msg.cachetotal = DVD_MSEC_TO_TIME(100); //! @todo implement ++ msg.cachetime = DVD_MSEC_TO_TIME(50); // TODO ++ msg.cachetotal = DVD_MSEC_TO_TIME(100); // TODO + msg.timestamp = pts; + m_messageParent.Put(new CDVDMsgType(CDVDMsg::PLAYER_STARTED, msg)); + } +diff --git a/xbmc/cores/paplayer/AudioDecoder.cpp b/xbmc/cores/paplayer/AudioDecoder.cpp +index ae7a88c..5b286bd 100644 +--- a/xbmc/cores/paplayer/AudioDecoder.cpp ++++ b/xbmc/cores/paplayer/AudioDecoder.cpp +@@ -298,7 +298,7 @@ int CAudioDecoder::ReadSamples(int numsamples) + int result = m_codec->ReadRaw(&m_rawBuffer, &m_rawBufferSize); + if (result == READ_SUCCESS && m_rawBufferSize) + { +- //! @todo trash this useless ringbuffer ++ // TODO, trash this useless ringbuffer + if (m_status == STATUS_QUEUING) + { + m_status = STATUS_QUEUED; +diff --git a/xbmc/cores/paplayer/ICodec.h b/xbmc/cores/paplayer/ICodec.h +index baae3d0..89e1795 100644 +--- a/xbmc/cores/paplayer/ICodec.h ++++ b/xbmc/cores/paplayer/ICodec.h +@@ -52,8 +52,9 @@ public: + // Init(filename) + // This routine should handle any initialization necessary. At a minimum it needs to: + // 1. Load any dlls and make sure any buffers etc. are allocated. +- // 2. Load the file (or at least attempt to load it) +- // 3. Fill in the m_TotalTime, m_SampleRate, m_BitsPerSample and m_Channels parameters. ++ // 2. If it's using a filereader, initialize it with the appropriate cache size. ++ // 3. Load the file (or at least attempt to load it) ++ // 4. Fill in the m_TotalTime, m_SampleRate, m_BitsPerSample and m_Channels parameters. + virtual bool Init(const CFileItem &file, unsigned int filecache)=0; + + // DeInit() +diff --git a/xbmc/cores/paplayer/PAPlayer.h b/xbmc/cores/paplayer/PAPlayer.h +index b82a874..5c85f2e 100644 +--- a/xbmc/cores/paplayer/PAPlayer.h ++++ b/xbmc/cores/paplayer/PAPlayer.h +@@ -21,7 +21,6 @@ + */ + + #include +-#include + + #include "cores/IPlayer.h" + #include "threads/Thread.h" +diff --git a/xbmc/cores/paplayer/VideoPlayerCodec.cpp b/xbmc/cores/paplayer/VideoPlayerCodec.cpp +index 9056cf8..7c25d82 100644 +--- a/xbmc/cores/paplayer/VideoPlayerCodec.cpp ++++ b/xbmc/cores/paplayer/VideoPlayerCodec.cpp +@@ -102,8 +102,8 @@ bool VideoPlayerCodec::Init(const CFileItem &file, unsigned int filecache) + return false; + } + +- //! @todo +- //! convey CFileItem::ContentLookup() into Open() ++ // TODO: ++ // convey CFileItem::ContentLookup() into Open() + if (!m_pInputStream->Open()) + { + CLog::Log(LOGERROR, "%s: Error opening file %s", __FUNCTION__, strFileToOpen.c_str()); +diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.h b/xbmc/cores/playercorefactory/PlayerSelectionRule.h +index 536cea6..c7cf3eb 100644 +--- a/xbmc/cores/playercorefactory/PlayerSelectionRule.h ++++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.h +@@ -19,9 +19,6 @@ + * + */ + +-#include +-#include +- + #include "FileItem.h" + #include "PlayerCoreFactory.h" + +diff --git a/xbmc/dbwrappers/Database.cpp b/xbmc/dbwrappers/Database.cpp +index 4dc71c5..a590487 100644 +--- a/xbmc/dbwrappers/Database.cpp ++++ b/xbmc/dbwrappers/Database.cpp +@@ -532,6 +532,9 @@ bool CDatabase::UpdateVersion(const std::string &dbName) + } + else if (version < GetSchemaVersion()) + { ++ CLog::Log(LOGNOTICE, "XBian: notifying Upstart (doing DB upgrades)"); ++ system("sudo /sbin/start -n -q xbmc-loaded"); ++ + CLog::Log(LOGNOTICE, "Attempting to update the database %s from version %i to %i", dbName.c_str(), version, GetSchemaVersion()); + bool success = true; + BeginTransaction(); +diff --git a/xbmc/dbwrappers/dataset.h b/xbmc/dbwrappers/dataset.h +index 133b63a..101ea5a 100644 +--- a/xbmc/dbwrappers/dataset.h ++++ b/xbmc/dbwrappers/dataset.h +@@ -29,10 +29,9 @@ + **********************************************************************/ + + #include +-#include +-#include + #include +-#include ++#include ++#include + #include "qry_dat.h" + #include + +diff --git a/xbmc/dbwrappers/mysqldataset.cpp b/xbmc/dbwrappers/mysqldataset.cpp +index b304d88..527bd1d 100644 +--- a/xbmc/dbwrappers/mysqldataset.cpp ++++ b/xbmc/dbwrappers/mysqldataset.cpp +@@ -1520,7 +1520,7 @@ int MysqlDataset::exec(const std::string &sql) { + } + else + { +- //! @todo collect results and store in exec_res ++ // TODO: collect results and store in exec_res + return res; + } + } +diff --git a/xbmc/dialogs/GUIDialogContextMenu.cpp b/xbmc/dialogs/GUIDialogContextMenu.cpp +index 19b1dc5..9d8d5a0 100644 +--- a/xbmc/dialogs/GUIDialogContextMenu.cpp ++++ b/xbmc/dialogs/GUIDialogContextMenu.cpp +@@ -42,10 +42,10 @@ + #include "filesystem/File.h" + #include "guilib/LocalizeStrings.h" + #include "TextureCache.h" ++#include "video/windows/GUIWindowVideoBase.h" + #include "URL.h" + #include "utils/StringUtils.h" + #include "utils/Variant.h" +-#include "addons/Scraper.h" + + #define BACKGROUND_IMAGE 999 + #define GROUP_LIST 996 +@@ -208,7 +208,7 @@ float CGUIDialogContextMenu::GetWidth() const + + bool CGUIDialogContextMenu::SourcesMenu(const std::string &strType, const CFileItemPtr& item, float posX, float posY) + { +- //! @todo This should be callable even if we don't have any valid items ++ // TODO: This should be callable even if we don't have any valid items + if (!item) + return false; + +@@ -246,7 +246,7 @@ void CGUIDialogContextMenu::GetContextButtons(const std::string &type, const CFi + if (share) + { + // Note. from now on, remove source & disable plugin should mean the same thing +- //! @todo might be smart to also combine editing source & plugin settings into one concept/dialog ++ //TODO might be smart to also combine editing source & plugin settings into one concept/dialog + // Note. Temporarily disabled ability to remove plugin sources until installer is operational + + CURL url(share->strPath); +@@ -621,9 +621,9 @@ void CGUIDialogContextMenu::SwitchMedia(const std::string& strType, const std::s + // create menu + CContextButtons choices; + if (strType != "music") +- choices.Add(WINDOW_MUSIC_NAV, 2); ++ choices.Add(WINDOW_MUSIC_FILES, 2); + if (strType != "video") +- choices.Add(WINDOW_VIDEO_NAV, 3); ++ choices.Add(WINDOW_VIDEO_FILES, 3); + if (strType != "pictures") + choices.Add(WINDOW_PICTURES, 1); + if (strType != "files") +diff --git a/xbmc/dialogs/GUIDialogContextMenu.h b/xbmc/dialogs/GUIDialogContextMenu.h +index 5c3316c..4c4a140 100644 +--- a/xbmc/dialogs/GUIDialogContextMenu.h ++++ b/xbmc/dialogs/GUIDialogContextMenu.h +@@ -20,9 +20,7 @@ + * + */ + +-#include + #include +-#include + + #include "guilib/GUIDialog.h" + +diff --git a/xbmc/dialogs/GUIDialogExtendedProgressBar.h b/xbmc/dialogs/GUIDialogExtendedProgressBar.h +index 24759b7..59a1692 100644 +--- a/xbmc/dialogs/GUIDialogExtendedProgressBar.h ++++ b/xbmc/dialogs/GUIDialogExtendedProgressBar.h +@@ -19,9 +19,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/GUIDialog.h" + + class CGUIDialogProgressBarHandle +diff --git a/xbmc/dialogs/GUIDialogFileBrowser.cpp b/xbmc/dialogs/GUIDialogFileBrowser.cpp +index 2f96c1f..2f5d034 100644 +--- a/xbmc/dialogs/GUIDialogFileBrowser.cpp ++++ b/xbmc/dialogs/GUIDialogFileBrowser.cpp +@@ -575,7 +575,7 @@ bool CGUIDialogFileBrowser::HaveDiscOrConnection( int iDriveType ) + } + else if ( iDriveType == CMediaSource::SOURCE_TYPE_REMOTE ) + { +- //! @todo Handle not connected to a remote share ++ // TODO: Handle not connected to a remote share + if ( !g_application.getNetwork().IsConnected() ) + { + CGUIDialogOK::ShowAndGetInput(CVariant{220}, CVariant{221}); +diff --git a/xbmc/dialogs/GUIDialogFileBrowser.h b/xbmc/dialogs/GUIDialogFileBrowser.h +index 1850a64..d4788e0 100644 +--- a/xbmc/dialogs/GUIDialogFileBrowser.h ++++ b/xbmc/dialogs/GUIDialogFileBrowser.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/GUIDialog.h" + #include "filesystem/VirtualDirectory.h" + #include "filesystem/DirectoryHistory.h" +diff --git a/xbmc/dialogs/GUIDialogGamepad.cpp b/xbmc/dialogs/GUIDialogGamepad.cpp +index de8afd0..9d8f6f3 100644 +--- a/xbmc/dialogs/GUIDialogGamepad.cpp ++++ b/xbmc/dialogs/GUIDialogGamepad.cpp +@@ -208,7 +208,7 @@ bool CGUIDialogGamepad::ShowAndVerifyNewPassword(std::string& strNewPassword) + std::string strUserInput; + if (ShowAndVerifyInput(strUserInput, "12340", "12330", "12331", "", true, true)) + { +- //! @todo Show error to user saying the password entry was blank ++ // TODO: Show error to user saying the password entry was blank + CGUIDialogOK::ShowAndGetInput(CVariant{12357}, CVariant{12358}); // Password is empty/blank + return false; + } +@@ -220,7 +220,7 @@ bool CGUIDialogGamepad::ShowAndVerifyNewPassword(std::string& strNewPassword) + // Prompt again for password input, this time sending previous input as the password to verify + if (!ShowAndVerifyInput(strUserInput, "12341", "12330", "12331", "", false, true)) + { +- //! @todo Show error to user saying the password re-entry failed ++ // TODO: Show error to user saying the password re-entry failed + CGUIDialogOK::ShowAndGetInput(CVariant{12357}, CVariant{12344}); // Password do not match + return false; + } +diff --git a/xbmc/dialogs/GUIDialogKeyboardGeneric.h b/xbmc/dialogs/GUIDialogKeyboardGeneric.h +index 1694733..356abeb 100644 +--- a/xbmc/dialogs/GUIDialogKeyboardGeneric.h ++++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.h +@@ -20,9 +20,6 @@ + + #pragma once + +-#include +-#include +- + #include "guilib/GUIKeyboard.h" + #include "guilib/GUIDialog.h" + #include "input/KeyboardLayout.h" +diff --git a/xbmc/dialogs/GUIDialogMediaFilter.h b/xbmc/dialogs/GUIDialogMediaFilter.h +index 6995fe3..b6f5647 100644 +--- a/xbmc/dialogs/GUIDialogMediaFilter.h ++++ b/xbmc/dialogs/GUIDialogMediaFilter.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + + #include "dbwrappers/Database.h" + #include "dbwrappers/DatabaseQuery.h" +diff --git a/xbmc/dialogs/GUIDialogMediaSource.h b/xbmc/dialogs/GUIDialogMediaSource.h +index 2694a41..66ec95a 100644 +--- a/xbmc/dialogs/GUIDialogMediaSource.h ++++ b/xbmc/dialogs/GUIDialogMediaSource.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/GUIDialog.h" + + class CFileItemList; +diff --git a/xbmc/dialogs/GUIDialogSelect.h b/xbmc/dialogs/GUIDialogSelect.h +index 9b4c1f4..eabd9fe 100644 +--- a/xbmc/dialogs/GUIDialogSelect.h ++++ b/xbmc/dialogs/GUIDialogSelect.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "GUIDialogBoxBase.h" + #include "view/GUIViewControl.h" + +diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +index b06d510..09f0a8b 100644 +--- a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp ++++ b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +@@ -342,7 +342,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() + iLabel = 20459; + } + else +- { //! @todo Add browseability in here. ++ { // TODO: Add browseability in here. + assert(false); + } + +diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp +index b8e09b8..a1ba577 100644 +--- a/xbmc/epg/Epg.cpp ++++ b/xbmc/epg/Epg.cpp +@@ -111,6 +111,17 @@ void CEpg::SetName(const std::string &strName) + } + } + ++void CEpg::SetScraperName(const std::string &strScraperName) ++{ ++ CSingleLock lock(m_critSection); ++ ++ if (m_strScraperName != strScraperName) ++ { ++ m_bChanged = true; ++ m_strScraperName = strScraperName; ++ } ++} ++ + void CEpg::SetUpdatePending(bool bUpdatePending /* = true */) + { + { +@@ -242,6 +253,18 @@ bool CEpg::CheckPlayingEvent(void) + return false; + } + ++CEpgInfoTagPtr CEpg::GetTag(const CDateTime &StartTime) const ++{ ++ CSingleLock lock(m_critSection); ++ std::map::const_iterator it = m_tags.find(StartTime); ++ if (it != m_tags.end()) ++ { ++ return it->second; ++ } ++ ++ return CEpgInfoTagPtr(); ++} ++ + CEpgInfoTagPtr CEpg::GetTagByBroadcastId(unsigned int iUniqueBroadcastId) const + { + if (iUniqueBroadcastId != EPG_TAG_INVALID_UID) +@@ -268,23 +291,16 @@ CEpgInfoTagPtr CEpg::GetTagBetween(const CDateTime &beginTime, const CDateTime & + return CEpgInfoTagPtr(); + } + +-std::vector CEpg::GetTagsBetween(const CDateTime &beginTime, const CDateTime &endTime) const ++CEpgInfoTagPtr CEpg::GetTagAround(const CDateTime &time) const + { +- std::vector epgTags; +- + CSingleLock lock(m_critSection); +- for (const auto &infoTag : m_tags) ++ for (std::map::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it) + { +- if (infoTag.second->StartAsUTC() >= beginTime) +- { +- if (infoTag.second->EndAsUTC() <= endTime) +- epgTags.emplace_back(infoTag.second); +- else +- break; // done. +- } ++ if ((it->second->StartAsUTC() < time) && (it->second->EndAsUTC() > time)) ++ return it->second; + } + +- return epgTags; ++ return CEpgInfoTagPtr(); + } + + void CEpg::AddEntry(const CEpgInfoTag &tag) +@@ -386,7 +402,7 @@ bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, std: + auto it = (eit == m_tags.end()) ? m_tags.find(tag->StartAsUTC()) : eit; + if (it == m_tags.end()) + { +- // It is not guaranteed that the deleted tag contains valid start time. search sequential. ++ // not guranteed that deleted tag contains valid start time. search sequential. + for (it = m_tags.begin(); it != m_tags.end(); ++it) + { + if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID()) +@@ -396,16 +412,11 @@ bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, std: + + if (it != m_tags.end()) + { +- // Respect epg linger time. +- const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0)); +- if (it->second->EndAsUTC() < cleanupTime) +- { +- if (bUpdateDatabase) +- m_deletedTags.insert(std::make_pair(it->second->UniqueBroadcastID(), it->second)); ++ it->second->ClearTimer(); ++ m_tags.erase(it); + +- it->second->ClearTimer(); +- m_tags.erase(it); +- } ++ if (bUpdateDatabase) ++ m_deletedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag)); + } + else + { +@@ -447,13 +458,13 @@ bool CEpg::Load(void) + int iEntriesLoaded = database->Get(*this); + if (iEntriesLoaded <= 0) + { +- CLog::Log(LOGDEBUG, "EPG - %s - no database entries found for table '%s'.", __FUNCTION__, m_strName.c_str()); ++ CLog::Log(LOGPVR, "EPG - %s - no database entries found for table '%s'.", __FUNCTION__, m_strName.c_str()); + } + else + { + m_lastScanTime = GetLastScanTime(); + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - %d entries loaded for table '%s'.", __FUNCTION__, (int) m_tags.size(), m_strName.c_str()); ++ CLog::Log(LOGPVR, "EPG - %s - %d entries loaded for table '%s'.", __FUNCTION__, (int) m_tags.size(), m_strName.c_str()); + #endif + bReturn = true; + } +@@ -467,19 +478,19 @@ bool CEpg::UpdateEntries(const CEpg &epg, bool bStoreInDb /* = true */) + { + CSingleLock lock(m_critSection); + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - %" PRIuS" entries in memory before merging", __FUNCTION__, m_tags.size()); ++ CLog::Log(LOGPVR, "EPG - %s - %" PRIuS" entries in memory before merging", __FUNCTION__, m_tags.size()); + #endif + /* copy over tags */ + for (std::map::const_iterator it = epg.m_tags.begin(); it != epg.m_tags.end(); ++it) + UpdateEntry(it->second, false, bStoreInDb); + + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - %" PRIuS" entries in memory after merging and before fixing", __FUNCTION__, m_tags.size()); ++ CLog::Log(LOGPVR, "EPG - %s - %" PRIuS" entries in memory after merging and before fixing", __FUNCTION__, m_tags.size()); + #endif + FixOverlappingEvents(bStoreInDb); + + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - %" PRIuS" entries in memory after fixing", __FUNCTION__, m_tags.size()); ++ CLog::Log(LOGPVR, "EPG - %s - %" PRIuS" entries in memory after fixing", __FUNCTION__, m_tags.size()); + #endif + /* update the last scan time of this table */ + m_lastScanTime = CDateTime::GetCurrentDateTime().GetAsUTCDateTime(); +@@ -610,7 +621,7 @@ bool CEpg::Persist(void) + return true; + + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "persist table '%s' (#%d) changed=%d deleted=%d", Name().c_str(), m_iEpgID, m_changedTags.size(), m_deletedTags.size()); ++ CLog::Log(LOGPVR, "persist table '%s' (#%d) changed=%d deleted=%d", Name().c_str(), m_iEpgID, m_changedTags.size(), m_deletedTags.size()); + #endif + + CEpgDatabase *database = g_EpgContainer.GetDatabase(); +@@ -731,24 +742,24 @@ bool CEpg::UpdateFromScraper(time_t start, time_t end) + else if (!channel->EPGEnabled()) + { + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - EPG updating disabled in the channel configuration", __FUNCTION__); ++ CLog::Log(LOGPVR, "EPG - %s - EPG updating disabled in the channel configuration", __FUNCTION__); + #endif + bGrabSuccess = true; + } + else if (channel->IsHidden()) + { + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "EPG - %s - channel '%s' on client '%i' is hidden", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); ++ CLog::Log(LOGPVR, "EPG - %s - channel '%s' on client '%i' is hidden", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); + #endif + bGrabSuccess = true; + } + else if (!g_PVRClients->SupportsEPG(channel->ClientID())) + { +- CLog::Log(LOGDEBUG, "EPG - %s - the backend for channel '%s' on client '%i' does not support EPGs", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); ++ CLog::Log(LOGPVR, "EPG - %s - the backend for channel '%s' on client '%i' does not support EPGs", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); + } + else + { +- CLog::Log(LOGDEBUG, "EPG - %s - updating EPG for channel '%s' from client '%i'", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); ++ CLog::Log(LOGPVR, "EPG - %s - updating EPG for channel '%s' from client '%i'", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); + bGrabSuccess = (g_PVRClients->GetEPGForChannel(channel, this, start, end) == PVR_ERROR_NO_ERROR); + } + } +@@ -758,7 +769,7 @@ bool CEpg::UpdateFromScraper(time_t start, time_t end) + { + CLog::Log(LOGINFO, "EPG - %s - updating EPG table '%s' with scraper '%s'", __FUNCTION__, m_strName.c_str(), m_strScraperName.c_str()); + CLog::Log(LOGWARNING, "loading the EPG via scraper has not been implemented yet"); +- //! @todo Add Support for Web EPG Scrapers here ++ // TODO: Add Support for Web EPG Scrapers here + } + + return bGrabSuccess; +@@ -814,6 +825,17 @@ const std::string &CEpg::ConvertGenreIdToString(int iID, int iSubID) + return g_localizeStrings.Get(iLabelId); + } + ++bool CEpg::IsRadio(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_pvrChannel ? m_pvrChannel->IsRadio() : false; ++} ++ ++bool CEpg::IsRemovableTag(const CEpgInfoTag &tag) const ++{ ++ return !tag.HasTimer(); ++} ++ + bool CEpg::LoadFromClients(time_t start, time_t end) + { + bool bReturn(false); +@@ -845,6 +867,20 @@ CEpgInfoTagPtr CEpg::GetNextEvent(const CEpgInfoTag& tag) const + return retVal; + } + ++CEpgInfoTagPtr CEpg::GetPreviousEvent(const CEpgInfoTag& tag) const ++{ ++ CSingleLock lock(m_critSection); ++ std::map::const_iterator it = m_tags.find(tag.StartAsUTC()); ++ if (it != m_tags.end() && it != m_tags.begin()) ++ { ++ --it; ++ return it->second; ++ } ++ ++ CEpgInfoTagPtr retVal; ++ return retVal; ++} ++ + CPVRChannelPtr CEpg::Channel(void) const + { + CSingleLock lock(m_critSection); +@@ -857,6 +893,18 @@ int CEpg::ChannelID(void) const + return m_pvrChannel ? m_pvrChannel->ChannelID() : -1; + } + ++int CEpg::ChannelNumber(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_pvrChannel ? m_pvrChannel->ChannelNumber() : -1; ++} ++ ++int CEpg::SubChannelNumber(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_pvrChannel ? m_pvrChannel->SubChannelNumber() : -1; ++} ++ + void CEpg::SetChannel(const PVR::CPVRChannelPtr &channel) + { + CSingleLock lock(m_critSection); +@@ -873,6 +921,12 @@ void CEpg::SetChannel(const PVR::CPVRChannelPtr &channel) + } + } + ++bool CEpg::HasPVRChannel(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_pvrChannel != NULL; ++} ++ + bool CEpg::UpdatePending(void) const + { + CSingleLock lock(m_critSection); +diff --git a/xbmc/epg/Epg.h b/xbmc/epg/Epg.h +index d47c8d0..1280a55 100644 +--- a/xbmc/epg/Epg.h ++++ b/xbmc/epg/Epg.h +@@ -82,6 +82,8 @@ namespace EPG + PVR::CPVRChannelPtr Channel(void) const; + + int ChannelID(void) const; ++ int ChannelNumber(void) const; ++ int SubChannelNumber(void) const; + + /*! + * @brief Channel the channel tag linked to this EPG table. +@@ -96,6 +98,12 @@ namespace EPG + const std::string &ScraperName(void) const { return m_strScraperName; } + + /*! ++ * @brief Change the name of the scraper to use. ++ * @param strScraperName The new scraper. ++ */ ++ void SetScraperName(const std::string &strScraperName); ++ ++ /*! + * @brief Specify if EPG should be manually updated on the next cycle + * @param bUpdatePending True if EPG should be manually updated + */ +@@ -137,6 +145,11 @@ namespace EPG + bool HasValidEntries(void) const; + + /*! ++ * @return True if this EPG has a PVR channel set, false otherwise. ++ */ ++ bool HasPVRChannel(void) const; ++ ++ /*! + * @brief Remove all entries from this EPG that finished before the given time + * and that have no timers set. + * @param Time Delete entries with an end time before this time in UTC. +@@ -167,6 +180,13 @@ namespace EPG + CEpgInfoTagPtr GetTagNext() const; + + /*! ++ * @brief Get the event that occurs at the given time. ++ * @param time The time in UTC to find the event for. ++ * @return The found tag or NULL if it wasn't found. ++ */ ++ CEpgInfoTagPtr GetTagAround(const CDateTime &time) const; ++ ++ /*! + * Get the event that occurs between the given begin and end time. + * @param beginTime Minimum start time in UTC of the event. + * @param endTime Maximum end time in UTC of the event. +@@ -175,12 +195,15 @@ namespace EPG + CEpgInfoTagPtr GetTagBetween(const CDateTime &beginTime, const CDateTime &endTime) const; + + /*! +- * Get all events occuring between the given begin and end time. +- * @param beginTime Minimum start time in UTC of the event. +- * @param endTime Maximum end time in UTC of the event. +- * @return The tags found or an empty vector if none was found. ++ * @brief Get the infotag with the given begin time. ++ * ++ * Get the infotag with the given ID. ++ * If it wasn't found, try finding the event with the given start time ++ * ++ * @param beginTime The start time in UTC of the event to find if it wasn't found by it's unique ID. ++ * @return The found tag or an empty tag if it wasn't found. + */ +- std::vector GetTagsBetween(const CDateTime &beginTime, const CDateTime &endTime) const; ++ CEpgInfoTagPtr GetTag(const CDateTime &beginTime) const; + + /*! + * @brief Get the event matching the given unique broadcast id +@@ -276,7 +299,13 @@ namespace EPG + */ + bool UpdateEntry(const EPG_TAG *data, bool bUpdateDatabase = false); + ++ /*! ++ * @return True if this is an EPG table for a radio channel, false otherwise. ++ */ ++ bool IsRadio(void) const; ++ + CEpgInfoTagPtr GetNextEvent(const CEpgInfoTag& tag) const; ++ CEpgInfoTagPtr GetPreviousEvent(const CEpgInfoTag& tag) const; + + size_t Size(void) const; + +@@ -302,7 +331,7 @@ namespace EPG + + /*! + * @brief Update the EPG from a scraper set in the channel tag. +- * @todo not implemented yet for non-pvr EPGs ++ * TODO: not implemented yet for non-pvr EPGs + * @param start Get entries with a start date after this time. + * @param end Get entries with an end date before this time. + * @return True if the update was successful, false otherwise. +@@ -338,6 +367,8 @@ namespace EPG + */ + bool UpdateEntries(const CEpg &epg, bool bStoreInDb = true); + ++ bool IsRemovableTag(const EPG::CEpgInfoTag &tag) const; ++ + std::map m_tags; + std::map m_changedTags; + std::map m_deletedTags; +diff --git a/xbmc/epg/EpgContainer.cpp b/xbmc/epg/EpgContainer.cpp +index 023aa7d..08fc87b 100644 +--- a/xbmc/epg/EpgContainer.cpp ++++ b/xbmc/epg/EpgContainer.cpp +@@ -31,7 +31,6 @@ + #include "pvr/channels/PVRChannelGroupsContainer.h" + #include "pvr/PVRManager.h" + #include "pvr/recordings/PVRRecordings.h" +-#include "pvr/timers/PVRTimerInfoTag.h" + #include "settings/AdvancedSettings.h" + #include "settings/lib/Setting.h" + #include "settings/Settings.h" +@@ -240,21 +239,18 @@ void CEpgContainer::LoadFromDB(void) + if (m_database.IsOpen()) + { + { +- //! @bug +- //! unlock m_critSection before calling ShowProgressDialog() - +- //! this is not legal, but works around a deadlock bug (because +- //! ShowProgressDialog() calls functions which lock +- //! g_graphicsContext); note that ShowProgressDialog() is +- //! sometimes called with m_critSection locked and sometimes +- //! without; this is a major bug that must be addressed +- //! eventually ++ /* unlock m_critSection before calling ShowProgressDialog() - ++ this is not legal, but works around a deadlock bug (because ++ ShowProgressDialog() calls functions which lock ++ g_graphicsContext); note that ShowProgressDialog() is ++ sometimes called with m_critSection locked and sometimes ++ without; this is a major bug that must be addressed ++ eventually */ + CSingleExit exit(m_critSection); + ShowProgressDialog(false); + } + +- const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - +- CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0)); +- m_database.DeleteEpgEntries(cleanupTime); ++ m_database.DeleteOldEpgEntries(); + m_database.Get(*this); + + for (const auto &epgEntry : m_epgs) +@@ -273,6 +269,14 @@ void CEpgContainer::LoadFromDB(void) + m_bLoaded = bLoaded; + } + ++bool CEpgContainer::PersistTables(void) ++{ ++ m_critSection.lock(); ++ auto copy = m_epgs; ++ m_critSection.unlock(); ++ return m_database.Persist(copy); ++} ++ + bool CEpgContainer::PersistAll(void) + { + bool bReturn(true); +@@ -311,7 +315,7 @@ void CEpgContainer::Process(void) + m_bIsInitialising = false; + + /* clean up old entries */ +- if (!m_bStop && iNow >= m_iLastEpgCleanup + g_advancedSettings.m_iEpgCleanupInterval) ++ if (!m_bStop && iNow >= m_iLastEpgCleanup) + RemoveOldEntries(); + + /* check for pending manual EPG updates */ +@@ -390,20 +394,16 @@ CEpgInfoTagPtr CEpgContainer::GetTagById(const CPVRChannelPtr &channel, unsigned + return retval; + } + +-std::vector CEpgContainer::GetEpgTagsForTimer(const CPVRTimerInfoTagPtr &timer) const ++CEpgPtr CEpgContainer::GetByChannel(const CPVRChannel &channel) const + { +- CPVRChannelPtr channel(timer->ChannelTag()); +- +- if (!channel) +- channel = timer->UpdateChannel(); +- +- if (channel) ++ CSingleLock lock(m_critSection); ++ for (const auto &epgEntry : m_epgs) + { +- const CEpgPtr epg(channel->GetEPG()); +- if (epg) +- return epg->GetTagsBetween(timer->StartAsUTC(), timer->EndAsUTC()); ++ if (channel.ChannelID() == epgEntry.second->ChannelID()) ++ return epgEntry.second; + } +- return std::vector(); ++ ++ return CEpgPtr(); + } + + void CEpgContainer::InsertFromDatabase(int iEpgID, const std::string &strName, const std::string &strScraperName) +@@ -432,7 +432,7 @@ void CEpgContainer::InsertFromDatabase(int iEpgID, const std::string &strName, c + } + } + +-CEpgPtr CEpgContainer::CreateChannelEpg(const CPVRChannelPtr &channel) ++CEpgPtr CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel) + { + if (!channel) + return CEpgPtr(); +@@ -480,19 +480,20 @@ bool CEpgContainer::LoadSettings(void) + + bool CEpgContainer::RemoveOldEntries(void) + { +- const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - +- CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0)); ++ CDateTime now = CDateTime::GetUTCDateTime() - ++ CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0); + + /* call Cleanup() on all known EPG tables */ + for (const auto &epgEntry : m_epgs) +- epgEntry.second->Cleanup(cleanupTime); ++ epgEntry.second->Cleanup(now); + + /* remove the old entries from the database */ + if (!m_bIgnoreDbForClient && m_database.IsOpen()) +- m_database.DeleteEpgEntries(cleanupTime); ++ m_database.DeleteOldEpgEntries(); + + CSingleLock lock(m_critSection); + CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iLastEpgCleanup); ++ m_iLastEpgCleanup += g_advancedSettings.m_iEpgCleanupInterval; + + return true; + } +@@ -508,7 +509,7 @@ bool CEpgContainer::DeleteEpg(const CEpg &epg, bool bDeleteFromDatabase /* = fal + if (epgEntry == m_epgs.end()) + return false; + +- CLog::Log(LOGDEBUG, "deleting EPG table %s (%d)", epg.Name().c_str(), epg.EpgID()); ++ CLog::Log(LOGPVR, "deleting EPG table %s (%d)", epg.Name().c_str(), epg.EpgID()); + if (bDeleteFromDatabase && !m_bIgnoreDbForClient && m_database.IsOpen()) + m_database.Delete(*epgEntry->second); + +@@ -695,6 +696,17 @@ bool CEpgContainer::UpdateEPG(bool bOnlyPending /* = false */) + return !bInterrupted; + } + ++int CEpgContainer::GetEPGAll(CFileItemList &results) ++{ ++ int iInitialSize = results.Size(); ++ ++ CSingleLock lock(m_critSection); ++ for (const auto &epgEntry : m_epgs) ++ epgEntry.second->Get(results); ++ ++ return results.Size() - iInitialSize; ++} ++ + const CDateTime CEpgContainer::GetFirstEPGDate(void) + { + CDateTime returnValue; +@@ -780,6 +792,12 @@ bool CEpgContainer::CheckPlayingEvents(void) + return bReturn; + } + ++bool CEpgContainer::IsInitialising(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bIsInitialising; ++} ++ + void CEpgContainer::SetHasPendingUpdates(bool bHasPendingUpdates /* = true */) + { + CSingleLock lock(m_critSection); +diff --git a/xbmc/epg/EpgContainer.h b/xbmc/epg/EpgContainer.h +index 5c0bfb9..006fd07 100644 +--- a/xbmc/epg/EpgContainer.h ++++ b/xbmc/epg/EpgContainer.h +@@ -76,29 +76,29 @@ namespace EPG + * @brief Start the EPG update thread. + * @param bAsync Should the EPG container starts asynchronously + */ +- void Start(bool bAsync); ++ virtual void Start(bool bAsync); + + /*! + * @brief Stop the EPG update thread. + * @return + */ +- bool Stop(void); ++ virtual bool Stop(void); + + /*! + * @brief Clear all EPG entries. + * @param bClearDb Clear the database too if true. + */ +- void Clear(bool bClearDb = false); ++ virtual void Clear(bool bClearDb = false); + + /*! + * @brief Stop the update thread and unload all data. + */ +- void Unload(void); ++ virtual void Unload(void); + + /*! + * @brief Clear the EPG and all it's database entries. + */ +- void Reset(void) { Clear(true); } ++ virtual void Reset(void) { Clear(true); } + + /*! + * @brief Check whether the EpgContainer has fully started. +@@ -112,7 +112,7 @@ namespace EPG + * @param bDeleteFromDatabase Delete this table from the database too if true. + * @return + */ +- bool DeleteEpg(const CEpg &epg, bool bDeleteFromDatabase = false); ++ virtual bool DeleteEpg(const CEpg &epg, bool bDeleteFromDatabase = false); + + /*! + * @brief Process a notification from an observable. +@@ -123,7 +123,7 @@ namespace EPG + + virtual void OnSettingChanged(const CSetting *setting) override; + +- CEpgPtr CreateChannelEpg(const PVR::CPVRChannelPtr &channel); ++ CEpgPtr CreateChannelEpg(PVR::CPVRChannelPtr channel); + + /*! + * @brief Get all EPG tables and apply a filter. +@@ -131,26 +131,33 @@ namespace EPG + * @param filter The filter to apply. + * @return The amount of entries that were added. + */ +- int GetEPGSearch(CFileItemList &results, const EpgSearchFilter &filter); ++ virtual int GetEPGSearch(CFileItemList &results, const EpgSearchFilter &filter); ++ ++ /*! ++ * @brief Get all EPG tables. ++ * @param results The fileitem list to store the results in. ++ * @return The amount of entries that were added. ++ */ ++ virtual int GetEPGAll(CFileItemList &results); + + /*! + * @brief Get the start time of the first entry. + * @return The start time. + */ +- const CDateTime GetFirstEPGDate(void); ++ virtual const CDateTime GetFirstEPGDate(void); + + /*! + * @brief Get the end time of the last entry. + * @return The end time. + */ +- const CDateTime GetLastEPGDate(void); ++ virtual const CDateTime GetLastEPGDate(void); + + /*! + * @brief Get an EPG table given it's ID. + * @param iEpgId The database ID of the table. + * @return The table or NULL if it wasn't found. + */ +- CEpgPtr GetById(int iEpgId) const; ++ virtual CEpgPtr GetById(int iEpgId) const; + + /*! + * @brief Get the EPG event with the given event id +@@ -158,20 +165,20 @@ namespace EPG + * @param iBroadcastId The event id to get + * @return The requested event, or an empty tag when not found + */ +- CEpgInfoTagPtr GetTagById(const PVR::CPVRChannelPtr &channel, unsigned int iBroadcastId) const; ++ virtual CEpgInfoTagPtr GetTagById(const PVR::CPVRChannelPtr &channel, unsigned int iBroadcastId) const; + + /*! +- * @brief Get the EPG events matching the given timer +- * @param timer The timer to get the matching events for. +- * @return The matching events, or an empty vector when no matching tag was found ++ * @brief Get an EPG table given a PVR channel. ++ * @param channel The channel to get the EPG table for. ++ * @return The table or NULL if it wasn't found. + */ +- std::vector GetEpgTagsForTimer(const PVR::CPVRTimerInfoTagPtr &timer) const; ++ virtual CEpgPtr GetByChannel(const PVR::CPVRChannel &channel) const; + + /*! + * @brief Notify EPG table observers when the currently active tag changed. + * @return True if the check was done, false if it was not the right time to check + */ +- bool CheckPlayingEvents(void); ++ virtual bool CheckPlayingEvents(void); + + /*! + * @brief The next EPG ID to be given to a table when the db isn't being used. +@@ -182,13 +189,13 @@ namespace EPG + /*! + * @brief Close the progress bar if it's visible. + */ +- void CloseProgressDialog(void); ++ virtual void CloseProgressDialog(void); + + /*! + * @brief Show the progress bar + * @param bUpdating True if updating epg entries, false if just loading them from db + */ +- void ShowProgressDialog(bool bUpdating = true); ++ virtual void ShowProgressDialog(bool bUpdating = true); + + /*! + * @brief Update the progress bar. +@@ -196,12 +203,12 @@ namespace EPG + * @param iMax The maximum position. + * @param strText The text to display. + */ +- void UpdateProgressDialog(int iCurrent, int iMax, const std::string &strText); ++ virtual void UpdateProgressDialog(int iCurrent, int iMax, const std::string &strText); + + /*! + * @return True to not to store EPG entries in the database. + */ +- bool IgnoreDB(void) const { return m_bIgnoreDbForClient; } ++ virtual bool IgnoreDB(void) const { return m_bIgnoreDbForClient; } + + /*! + * @brief Wait for an EPG update to finish. +@@ -222,11 +229,18 @@ namespace EPG + void SetHasPendingUpdates(bool bHasPendingUpdates = true); + + /*! ++ * @return True while being initialised. ++ */ ++ bool IsInitialising(void) const; ++ ++ /*! + * @brief Call Persist() on each table + * @return True when they all were persisted, false otherwise. + */ + bool PersistAll(void); + ++ bool PersistTables(void); ++ + /*! + * @brief client can trigger an update request for a channel + */ +@@ -237,25 +251,25 @@ namespace EPG + * @brief Load the EPG settings. + * @return True if the settings were loaded successfully, false otherwise. + */ +- bool LoadSettings(void); ++ virtual bool LoadSettings(void); + + /*! + * @brief Remove old EPG entries. + * @return True if the old entries were removed successfully, false otherwise. + */ +- bool RemoveOldEntries(void); ++ virtual bool RemoveOldEntries(void); + + /*! + * @brief Load and update the EPG data. + * @param bOnlyPending Only check and update EPG tables with pending manual updates + * @return True if the update has not been interrupted, false otherwise. + */ +- bool UpdateEPG(bool bOnlyPending = false); ++ virtual bool UpdateEPG(bool bOnlyPending = false); + + /*! + * @return True if a running update should be interrupted, false otherwise. + */ +- bool InterruptUpdate(void) const; ++ virtual bool InterruptUpdate(void) const; + + /*! + * @brief EPG update thread +diff --git a/xbmc/epg/EpgDatabase.cpp b/xbmc/epg/EpgDatabase.cpp +index 6b5049f..a9bd1d0 100644 +--- a/xbmc/epg/EpgDatabase.cpp ++++ b/xbmc/epg/EpgDatabase.cpp +@@ -42,7 +42,7 @@ void CEpgDatabase::CreateTables(void) + { + CLog::Log(LOGINFO, "EpgDB - %s - creating tables", __FUNCTION__); + +- CLog::Log(LOGDEBUG, "EpgDB - %s - creating table 'epg'", __FUNCTION__); ++ CLog::Log(LOGPVR, "EpgDB - %s - creating table 'epg'", __FUNCTION__); + m_pDS->exec( + "CREATE TABLE epg (" + "idEpg integer primary key, " +@@ -51,7 +51,7 @@ void CEpgDatabase::CreateTables(void) + ")" + ); + +- CLog::Log(LOGDEBUG, "EpgDB - %s - creating table 'epgtags'", __FUNCTION__); ++ CLog::Log(LOGPVR, "EpgDB - %s - creating table 'epgtags'", __FUNCTION__); + m_pDS->exec( + "CREATE TABLE epgtags (" + "idBroadcast integer primary key, " +@@ -83,7 +83,7 @@ void CEpgDatabase::CreateTables(void) + "iFlags integer" + ")" + ); +- CLog::Log(LOGDEBUG, "EpgDB - %s - creating table 'lastepgscan'", __FUNCTION__); ++ CLog::Log(LOGPVR, "EpgDB - %s - creating table 'lastepgscan'", __FUNCTION__); + m_pDS->exec("CREATE TABLE lastepgscan (" + "idEpg integer primary key, " + "sLastScan varchar(20)" +@@ -93,7 +93,7 @@ void CEpgDatabase::CreateTables(void) + + void CEpgDatabase::CreateAnalytics() + { +- CLog::Log(LOGDEBUG, "%s - creating indices", __FUNCTION__); ++ CLog::Log(LOGPVR, "%s - creating indices", __FUNCTION__); + m_pDS->exec("CREATE UNIQUE INDEX idx_epg_idEpg_iStartTime on epgtags(idEpg, iStartTime desc);"); + m_pDS->exec("CREATE INDEX idx_epg_iEndTime on epgtags(iEndTime);"); + } +@@ -125,7 +125,7 @@ void CEpgDatabase::UpdateTables(int iVersion) + bool CEpgDatabase::DeleteEpg(void) + { + bool bReturn(false); +- CLog::Log(LOGDEBUG, "EpgDB - %s - deleting all EPG data from the database", __FUNCTION__); ++ CLog::Log(LOGPVR, "EpgDB - %s - deleting all EPG data from the database", __FUNCTION__); + + bReturn = DeleteValues("epg") || bReturn; + bReturn = DeleteValues("epgtags") || bReturn; +@@ -149,13 +149,15 @@ bool CEpgDatabase::Delete(const CEpg &table) + return DeleteValues("epg", filter); + } + +-bool CEpgDatabase::DeleteEpgEntries(const CDateTime &maxEndTime) ++bool CEpgDatabase::DeleteOldEpgEntries(void) + { +- time_t iMaxEndTime; +- maxEndTime.GetAsTime(iMaxEndTime); ++ time_t iCleanupTime; ++ CDateTime cleanupTime = CDateTime::GetCurrentDateTime().GetAsUTCDateTime() - ++ CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0); ++ cleanupTime.GetAsTime(iCleanupTime); + + Filter filter; +- filter.AppendWhere(PrepareSQL("iEndTime < %u", iMaxEndTime)); ++ filter.AppendWhere(PrepareSQL("iEndTime < %u", iCleanupTime)); + + return DeleteValues("epgtags", filter); + } +diff --git a/xbmc/epg/EpgDatabase.h b/xbmc/epg/EpgDatabase.h +index b25ac20..19ac90f 100644 +--- a/xbmc/epg/EpgDatabase.h ++++ b/xbmc/epg/EpgDatabase.h +@@ -84,11 +84,10 @@ namespace EPG + virtual bool Delete(const CEpg &table); + + /*! +- * @brief Erase all EPG entries with an end time less than the given time. +- * @param maxEndTime The maximum allowed end time. ++ * @brief Erase all EPG entries older than 1 day. + * @return True if the entries were removed successfully, false otherwise. + */ +- virtual bool DeleteEpgEntries(const CDateTime &maxEndTime); ++ virtual bool DeleteOldEpgEntries(void); + + /*! + * @brief Remove a single EPG entry. +diff --git a/xbmc/epg/EpgInfoTag.cpp b/xbmc/epg/EpgInfoTag.cpp +index d69b469..aa3b2a3 100644 +--- a/xbmc/epg/EpgInfoTag.cpp ++++ b/xbmc/epg/EpgInfoTag.cpp +@@ -134,6 +134,8 @@ CEpgInfoTag::CEpgInfoTag(const EPG_TAG &data) : + + CEpgInfoTag::~CEpgInfoTag() + { ++ ClearTimer(); ++ ClearRecording(); + } + + bool CEpgInfoTag::operator ==(const CEpgInfoTag& right) const +@@ -288,6 +290,11 @@ CEpgInfoTagPtr CEpgInfoTag::GetNextEvent(void) const + return GetTable()->GetNextEvent(*this); + } + ++CEpgInfoTagPtr CEpgInfoTag::GetPreviousEvent(void) const ++{ ++ return GetTable()->GetPreviousEvent(*this); ++} ++ + void CEpgInfoTag::SetUniqueBroadcastID(unsigned int iUniqueBroadcastID) + { + m_iUniqueBroadcastID = iUniqueBroadcastID; +@@ -669,7 +676,7 @@ bool CEpgInfoTag::Persist(bool bSingleUpdate /* = true */) + bool bReturn = false; + + #if EPG_DEBUGGING +- CLog::Log(LOGDEBUG, "Epg - %s - Infotag '%s' %s, persisting...", __FUNCTION__, m_strTitle.c_str(), m_iBroadcastId > 0 ? "has changes" : "is new"); ++ CLog::Log(LOGPVR, "Epg - %s - Infotag '%s' %s, persisting...", __FUNCTION__, m_strTitle.c_str(), m_iBroadcastId > 0 ? "has changes" : "is new"); + #endif + + CEpgDatabase *database = g_EpgContainer.GetDatabase(); +diff --git a/xbmc/epg/EpgInfoTag.h b/xbmc/epg/EpgInfoTag.h +index cabc86c..3f5d080 100644 +--- a/xbmc/epg/EpgInfoTag.h ++++ b/xbmc/epg/EpgInfoTag.h +@@ -21,7 +21,6 @@ + + #include + #include +-#include + + #include "XBDateTime.h" + #include "addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h" +@@ -68,8 +67,17 @@ namespace EPG + */ + CEpgInfoTag(CEpg *epg, PVR::CPVRChannelPtr pvrChannel, const std::string &strTableName = "", const std::string &strIconPath = ""); + +- CEpgInfoTag(const CEpgInfoTag &tag) = delete; +- CEpgInfoTag &operator =(const CEpgInfoTag &other) = delete; ++ // Prevent copy construction, even for CEpgInfoTag instances and friends. ++ // Note: Only declared, but intentionally not implemented ++ // to prevent compiler generated copy ctor and to force ++ // a linker error in case somebody tries to call it. ++ CEpgInfoTag(const CEpgInfoTag &tag); ++ ++ // Prevent copy by assignment, even for CEpgInfoTag instances and friends. ++ // Note: Only declared, but intentionally not implemented ++ // to prevent compiler generated assignment operator and to force ++ // a linker error in case somebody tries to call it. ++ CEpgInfoTag &operator =(const CEpgInfoTag &other); + + public: + virtual ~CEpgInfoTag(); +@@ -112,6 +120,12 @@ namespace EPG + CEpgInfoTagPtr GetNextEvent(void) const; + + /*! ++ * @brief Get a pointer to the previous event. Set by CEpg in a call to Sort() ++ * @return A pointer to the previous event or NULL if it's not set. ++ */ ++ CEpgInfoTagPtr GetPreviousEvent(void) const; ++ ++ /*! + * @brief The table this event belongs to + * @return The table this event belongs to + */ +diff --git a/xbmc/epg/EpgSearchFilter.cpp b/xbmc/epg/EpgSearchFilter.cpp +index f87d3e4..e706334 100644 +--- a/xbmc/epg/EpgSearchFilter.cpp ++++ b/xbmc/epg/EpgSearchFilter.cpp +@@ -191,3 +191,75 @@ bool EpgSearchFilter::MatchChannelGroup(const CEpgInfoTag &tag) const + + return bReturn; + } ++ ++int EpgSearchFilter::FilterRecordings(CFileItemList &results) ++{ ++ int iRemoved(0); ++ if (!g_PVRManager.IsStarted()) ++ return iRemoved; ++ ++ CFileItemList recordings; ++ g_PVRRecordings->GetAll(recordings); ++ ++ // TODO inefficient! ++ CPVRRecordingPtr recording; ++ for (int iRecordingPtr = 0; iRecordingPtr < recordings.Size(); iRecordingPtr++) ++ { ++ recording = recordings.Get(iRecordingPtr)->GetPVRRecordingInfoTag(); ++ if (!recording) ++ continue; ++ ++ for (int iResultPtr = 0; iResultPtr < results.Size(); iResultPtr++) ++ { ++ const CEpgInfoTagPtr epgentry(results.Get(iResultPtr)->GetEPGInfoTag()); ++ ++ /* no match */ ++ if (!epgentry || ++ epgentry->Title() != recording->m_strTitle || ++ epgentry->Plot() != recording->m_strPlot) ++ continue; ++ ++ results.Remove(iResultPtr); ++ iResultPtr--; ++ ++iRemoved; ++ } ++ } ++ ++ return iRemoved; ++} ++ ++int EpgSearchFilter::FilterTimers(CFileItemList &results) ++{ ++ int iRemoved(0); ++ if (!g_PVRManager.IsStarted()) ++ return iRemoved; ++ ++ std::vector timers = g_PVRTimers->GetActiveTimers(); ++ // TODO inefficient! ++ for (unsigned int iTimerPtr = 0; iTimerPtr < timers.size(); iTimerPtr++) ++ { ++ CFileItemPtr fileItem = timers.at(iTimerPtr); ++ if (!fileItem || !fileItem->HasPVRTimerInfoTag()) ++ continue; ++ ++ CPVRTimerInfoTagPtr timer = fileItem->GetPVRTimerInfoTag(); ++ if (!timer) ++ continue; ++ ++ for (int iResultPtr = 0; iResultPtr < results.Size(); iResultPtr++) ++ { ++ const CEpgInfoTagPtr epgentry(results.Get(iResultPtr)->GetEPGInfoTag()); ++ if (!epgentry || ++ *epgentry->ChannelTag() != *timer->ChannelTag() || ++ epgentry->StartAsUTC() < timer->StartAsUTC() || ++ epgentry->EndAsUTC() > timer->EndAsUTC()) ++ continue; ++ ++ results.Remove(iResultPtr); ++ iResultPtr--; ++ ++iRemoved; ++ } ++ } ++ ++ return iRemoved; ++} +diff --git a/xbmc/epg/EpgSearchFilter.h b/xbmc/epg/EpgSearchFilter.h +index c6132e6..8d85f4e 100644 +--- a/xbmc/epg/EpgSearchFilter.h ++++ b/xbmc/epg/EpgSearchFilter.h +@@ -33,6 +33,9 @@ namespace EPG + + struct EpgSearchFilter + { ++ static int FilterRecordings(CFileItemList &results); ++ static int FilterTimers(CFileItemList &results); ++ + /*! + * @brief Clear this filter. + */ +diff --git a/xbmc/epg/GUIEPGGridContainer.cpp b/xbmc/epg/GUIEPGGridContainer.cpp +index 162ef94..5f05163 100644 +--- a/xbmc/epg/GUIEPGGridContainer.cpp ++++ b/xbmc/epg/GUIEPGGridContainer.cpp +@@ -510,7 +510,7 @@ void CGUIEPGGridContainer::UpdateItems() + } + else // "gap" tag seleceted + { +- const GridItem *prevItem(GetPrevItem(m_channelCursor)); ++ const GridItemsPtr *prevItem(GetPrevItem(m_channelCursor)); + if (prevItem) + { + const CEpgInfoTagPtr tag(prevItem->item->GetEPGInfoTag()); +@@ -1037,9 +1037,9 @@ std::string CGUIEPGGridContainer::GetLabel(int info) const + return label; + } + +-GridItem *CGUIEPGGridContainer::GetClosestItem(int channel) ++GridItemsPtr *CGUIEPGGridContainer::GetClosestItem(int channel) + { +- GridItem *closest = GetItem(channel); ++ GridItemsPtr *closest = GetItem(channel); + + if (!closest) + return nullptr; +@@ -1071,7 +1071,7 @@ GridItem *CGUIEPGGridContainer::GetClosestItem(int channel) + return m_gridModel->GetGridItemPtr(channel + m_channelOffset, m_blockCursor - left + m_blockOffset); + } + +-int CGUIEPGGridContainer::GetItemSize(GridItem *item) ++int CGUIEPGGridContainer::GetItemSize(GridItemsPtr *item) + { + if (!item) + return MathUtils::round_int(m_blockSize); // stops it crashing +@@ -1098,7 +1098,7 @@ int CGUIEPGGridContainer::GetRealBlock(const CGUIListItemPtr &item, int channel) + return block; + } + +-GridItem *CGUIEPGGridContainer::GetNextItem(int channel) ++GridItemsPtr *CGUIEPGGridContainer::GetNextItem(int channel) + { + int channelIndex = channel + m_channelOffset; + int blockIndex = m_blockCursor + m_blockOffset; +@@ -1116,7 +1116,7 @@ GridItem *CGUIEPGGridContainer::GetNextItem(int channel) + return m_gridModel->GetGridItemPtr(channelIndex, i + m_blockOffset); + } + +-GridItem *CGUIEPGGridContainer::GetPrevItem(int channel) ++GridItemsPtr *CGUIEPGGridContainer::GetPrevItem(int channel) + { + int channelIndex = channel + m_channelOffset; + int blockIndex = m_blockCursor + m_blockOffset; +@@ -1131,7 +1131,7 @@ GridItem *CGUIEPGGridContainer::GetPrevItem(int channel) + return m_gridModel->GetGridItemPtr(channelIndex, i + m_blockOffset); + } + +-GridItem *CGUIEPGGridContainer::GetItem(int channel) ++GridItemsPtr *CGUIEPGGridContainer::GetItem(int channel) + { + int channelIndex = channel + m_channelOffset; + int blockIndex = m_blockCursor + m_blockOffset; +@@ -1803,7 +1803,7 @@ void CGUIEPGGridContainer::HandleProgrammeGrid(bool bRender, unsigned int curren + + bool focused = (channel == m_channelOffset + m_channelCursor) && (item == m_gridModel->GetGridItem(m_channelOffset + m_channelCursor, m_blockOffset + m_blockCursor)); + +- if (bRender) //! @todo Why the functional difference wrt truncate here? ++ if (bRender) // @@@ TODO why the functional difference wrt truncate here? + { + // reset to grid start position if first item is out of grid view + if (posA2 < posA) +diff --git a/xbmc/epg/GUIEPGGridContainer.h b/xbmc/epg/GUIEPGGridContainer.h +index e867f16..1064013 100644 +--- a/xbmc/epg/GUIEPGGridContainer.h ++++ b/xbmc/epg/GUIEPGGridContainer.h +@@ -19,9 +19,6 @@ + * + */ + +-#include +-#include +- + #include "XBDateTime.h" + #include "FileItem.h" + #include "guilib/GUIControl.h" +@@ -30,7 +27,7 @@ + + namespace EPG + { +- struct GridItem; ++ class GridItemsPtr; + class CGUIEPGGridContainerModel; + + class CGUIEPGGridContainer : public IGUIContainer +@@ -95,12 +92,12 @@ namespace EPG + void ValidateOffset(); + void UpdateLayout(); + +- GridItem *GetItem(int channel); +- GridItem *GetNextItem(int channel); +- GridItem *GetPrevItem(int channel); +- GridItem *GetClosestItem(int channel); ++ GridItemsPtr *GetItem(int channel); ++ GridItemsPtr *GetNextItem(int channel); ++ GridItemsPtr *GetPrevItem(int channel); ++ GridItemsPtr *GetClosestItem(int channel); + +- int GetItemSize(GridItem *item); ++ int GetItemSize(GridItemsPtr *item); + int GetBlock(const CGUIListItemPtr &item, int channel); + int GetRealBlock(const CGUIListItemPtr &item, int channel); + void MoveToRow(int row); +@@ -198,6 +195,6 @@ namespace EPG + std::unique_ptr m_updatedGridModel; + std::unique_ptr m_outdatedGridModel; + +- GridItem *m_item; ++ GridItemsPtr *m_item; + }; + } +diff --git a/xbmc/epg/GUIEPGGridContainerModel.cpp b/xbmc/epg/GUIEPGGridContainerModel.cpp +index 6434edd..be75067 100644 +--- a/xbmc/epg/GUIEPGGridContainerModel.cpp ++++ b/xbmc/epg/GUIEPGGridContainerModel.cpp +@@ -147,7 +147,7 @@ void CGUIEPGGridContainerModel::Refresh(const std::unique_ptr &it + m_blocks = MAXBLOCKS; + + m_gridIndex.reserve(m_channelItems.size()); +- const std::vector blocks(m_blocks); ++ const std::vector blocks(m_blocks); + + for (size_t channel = 0; channel < m_channelItems.size(); ++channel) + { +diff --git a/xbmc/epg/GUIEPGGridContainerModel.h b/xbmc/epg/GUIEPGGridContainerModel.h +index 4d5b21f..794d280 100644 +--- a/xbmc/epg/GUIEPGGridContainerModel.h ++++ b/xbmc/epg/GUIEPGGridContainerModel.h +@@ -31,14 +31,14 @@ class CFileItemList; + + namespace EPG + { +- struct GridItem ++ struct GridItemsPtr + { + CFileItemPtr item; + float originWidth; + float width; + int progIndex; + +- GridItem() : originWidth(0.0f), width(0.0f), progIndex(-1) {} ++ GridItemsPtr() : originWidth(0.0), width(0.0), progIndex(-1) {} + }; + + class CGUIEPGGridContainerModel +@@ -72,7 +72,7 @@ namespace EPG + + int GetBlockCount() const { return m_blocks; } + bool HasGridItems() const { return !m_gridIndex.empty(); } +- GridItem *GetGridItemPtr(int iChannel, int iBlock) { return &m_gridIndex[iChannel][iBlock]; } ++ GridItemsPtr *GetGridItemPtr(int iChannel, int iBlock) { return &m_gridIndex[iChannel][iBlock]; } + CFileItemPtr GetGridItem(int iChannel, int iBlock) const { return m_gridIndex[iChannel][iBlock].item; } + float GetGridItemWidth(int iChannel, int iBlock) const { return m_gridIndex[iChannel][iBlock].width; } + float GetGridItemOriginWidth(int iChannel, int iBlock) const { return m_gridIndex[iChannel][iBlock].originWidth; } +@@ -100,7 +100,7 @@ namespace EPG + std::vector m_channelItems; + std::vector m_rulerItems; + std::vector m_epgItemsPtr; +- std::vector > m_gridIndex; ++ std::vector > m_gridIndex; + + int m_blocks; + }; +diff --git a/xbmc/events/MediaLibraryEvent.cpp b/xbmc/events/MediaLibraryEvent.cpp +index 2915537..964a685 100644 +--- a/xbmc/events/MediaLibraryEvent.cpp ++++ b/xbmc/events/MediaLibraryEvent.cpp +@@ -83,12 +83,15 @@ bool CMediaLibraryEvent::Execute() const + } + else + { +- //! @todo remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it ++ // TODO: remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it + if (m_mediaType == MediaTypeMovie || m_mediaType == MediaTypeMusicVideo || m_mediaType == MediaTypeEpisode) + path = URIUtils::GetDirectory(path); + } + +- windowId = WINDOW_VIDEO_NAV; ++ if (URIUtils::IsVideoDb(path)) ++ windowId = WINDOW_VIDEO_NAV; ++ else ++ windowId = WINDOW_VIDEO_FILES; + } + else if (m_mediaType == MediaTypeMusic || m_mediaType == MediaTypeArtist || + m_mediaType == MediaTypeAlbum || m_mediaType == MediaTypeSong) +@@ -106,12 +109,15 @@ bool CMediaLibraryEvent::Execute() const + } + else + { +- //! @todo remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it ++ // TODO: remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it + if (m_mediaType == MediaTypeSong) + path = URIUtils::GetDirectory(path); + } + +- windowId = WINDOW_MUSIC_NAV; ++ if (URIUtils::IsMusicDb(path)) ++ windowId = WINDOW_MUSIC_NAV; ++ else ++ windowId = WINDOW_MUSIC_FILES; + } + + if (windowId < 0) +diff --git a/xbmc/events/windows/GUIWindowEventLog.h b/xbmc/events/windows/GUIWindowEventLog.h +index 4808397..0bd9f3e 100644 +--- a/xbmc/events/windows/GUIWindowEventLog.h ++++ b/xbmc/events/windows/GUIWindowEventLog.h +@@ -28,7 +28,7 @@ public: + virtual ~CGUIWindowEventLog(); + + // specialization of CGUIControl +- virtual bool OnMessage(CGUIMessage& message) override; ++ virtual bool OnMessage(CGUIMessage& message); + + protected: + // specialization of CGUIMediaWindow +diff --git a/xbmc/filesystem/AFPDirectory.cpp b/xbmc/filesystem/AFPDirectory.cpp +new file mode 100644 +index 0000000..a9a7b0a +--- /dev/null ++++ b/xbmc/filesystem/AFPDirectory.cpp +@@ -0,0 +1,326 @@ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#if defined(HAS_FILESYSTEM_AFP) ++#include "AFPDirectory.h" ++#include "AFPFile.h" ++#include "Util.h" ++#include "guilib/LocalizeStrings.h" ++#include "Application.h" ++#include "FileItem.h" ++#include "settings/AdvancedSettings.h" ++#include "utils/StringUtils.h" ++#include "utils/log.h" ++#include "utils/URIUtils.h" ++#include "threads/SingleLock.h" ++#include "PasswordManager.h" ++#include "DllLibAfp.h" ++ ++#include "linux/XTimeUtils.cpp" ++ ++struct CachedDirEntry ++{ ++ unsigned int type; ++ std::string name; ++}; ++ ++using namespace XFILE; ++using namespace std; ++ ++CAFPDirectory::CAFPDirectory(void) ++{ ++ gAfpConnection.AddActiveConnection(); ++} ++ ++CAFPDirectory::~CAFPDirectory(void) ++{ ++ gAfpConnection.AddIdleConnection(); ++} ++ ++bool CAFPDirectory::ResolveSymlink( const std::string &dirName, const std::string &fileName, ++ struct stat *stat, CURL &resolvedUrl) ++{ ++ CSingleLock lock(gAfpConnection); ++ int ret = 0; ++ bool retVal = true; ++ char resolvedLink[MAX_PATH]; ++ std::string fullpath = dirName; ++ URIUtils::AddSlashAtEnd(fullpath); ++ fullpath += fileName; ++ ++ CPasswordManager::GetInstance().AuthenticateURL(resolvedUrl); ++ resolvedUrl.SetProtocol("afp"); ++ resolvedUrl.SetHostName(gAfpConnection.GetConnectedIp()); ++ ++ ret = gAfpConnection.GetImpl()->afp_wrap_readlink(gAfpConnection.GetVolume(), fullpath.c_str(), resolvedLink, MAX_PATH); ++ ++ if(ret == 0) ++ { ++ fullpath = dirName; ++ URIUtils::AddSlashAtEnd(fullpath); ++ fullpath.append(resolvedLink); ++ ++ if(resolvedLink[0] == '/') ++ { ++ //use the special stat function for using an extra context ++ //because we are inside of a dir traversation ++ //and just can't change the global nfs context here ++ //without destroying something... ++ fullpath = resolvedLink; ++ fullpath.erase(0, 1); ++ resolvedUrl.SetFileName(fullpath); ++ ret = gAfpConnection.stat(resolvedUrl, stat); ++ if(ret < 0) ++ { ++ URIUtils::AddSlashAtEnd(fullpath); ++ resolvedUrl.SetFileName(fullpath); ++ ret = gAfpConnection.stat(resolvedUrl, stat); ++ } ++ } ++ else ++ { ++ ret = gAfpConnection.GetImpl()->afp_wrap_getattr(gAfpConnection.GetVolume(), fullpath.c_str(), stat); ++ resolvedUrl.SetFileName(gAfpConnection.GetUrl()->volumename + fullpath); ++ } ++ ++ if (ret != 0) ++ { ++ CLog::Log(LOGERROR, "AFP: Failed to stat(%s) on link resolve %s\n", fullpath.c_str(), strerror(errno)); ++ retVal = false;; ++ } ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "Failed to readlink(%s) %s\n", fullpath.c_str(), strerror(errno)); ++ retVal = false; ++ } ++ return retVal; ++} ++ ++ ++bool CAFPDirectory::GetDirectory(const CURL& url, CFileItemList &items) ++{ ++ // We accept afp://[[user[:password@]]server[/share[/path[/file]]]] ++ // silence gdb breaking on signal SIGUSR2 with "handle SIGUSR2 nostop noprint" ++ bool bListVolumes = false; ++ FILETIME fileTime, localTime; ++ ++ CSingleLock lock(gAfpConnection); ++ CAfpConnection::afpConnnectError afpError = gAfpConnection.Connect(url); ++ ++ if (afpError != CAfpConnection::AfpOk || (!url.GetShareName().empty() && !gAfpConnection.GetVolume())) ++ { ++ if (afpError == CAfpConnection::AfpAuth) ++ { ++ if (m_flags & DIR_FLAG_ALLOW_PROMPT) ++ { ++ RequireAuthentication(url); ++ } ++ } ++ return false; ++ } ++ std::string strDirName = gAfpConnection.GetPath(url); ++ ++ vector vecEntries; ++ struct afp_file_info *dirEnt = NULL; ++ struct afp_file_info *curDirPtr = NULL; ++ ++ // if no share name in url - try to fetch the volumes on the server and treat them like folders ++ if (url.GetShareName().empty()) ++ { ++ bListVolumes = true; ++ struct afp_server *serv = gAfpConnection.GetServer(); ++ for (int i = 0; i < serv->num_volumes; i++) ++ { ++ CachedDirEntry aDir; ++ aDir.type = 1; ++ aDir.name = serv->volumes[i].volume_name; ++ vecEntries.push_back(aDir); ++ } ++ } ++ ++ // if we not only list volumes - read the dir ++ if (!bListVolumes) ++ { ++ if (gAfpConnection.GetImpl()->afp_wrap_readdir(gAfpConnection.GetVolume(), strDirName.c_str(), &dirEnt)) ++ return false; ++ lock.Leave(); ++ ++ for (curDirPtr = dirEnt; curDirPtr; curDirPtr = curDirPtr->next) ++ { ++ CachedDirEntry aDir; ++ aDir.type = curDirPtr->isdir; ++#ifdef USE_CVS_AFPFS ++ aDir.name = curDirPtr->basic.name; ++#else ++ aDir.name = curDirPtr->name; ++#endif ++ vecEntries.push_back(aDir); ++ } ++ gAfpConnection.GetImpl()->afp_ml_filebase_free(&dirEnt); ++ } ++ ++ std::string myStrPath(url.Get()); ++ URIUtils::AddSlashAtEnd(myStrPath); //be sure the dir ends with a slash ++ for (size_t i = 0; i < vecEntries.size(); i++) ++ { ++ CachedDirEntry aDir = vecEntries[i]; ++ // We use UTF-8 internally, as does AFP ++ std::string strFile = aDir.name; ++ std::string path(myStrPath + strFile); ++ ++ if (strFile != "." && strFile != ".." && strFile != "lost+found") ++ { ++ int64_t iSize = 0; ++ bool bIsDir = aDir.type; ++ int64_t lTimeDate = 0; ++ ++ // if we not only list volumes - stat the files in folder ++ if (!bListVolumes) ++ { ++ struct stat info = {0}; ++ ++ if ((m_flags & DIR_FLAG_NO_FILE_INFO)==0 && g_advancedSettings.m_sambastatfiles) ++ { ++ // make sure we use the authenticated path wich contains any default username ++ std::string strFullName = strDirName + strFile; ++ ++ lock.Enter(); ++ ++ if (gAfpConnection.GetImpl()->afp_wrap_getattr(gAfpConnection.GetVolume(), strFullName.c_str(), &info) == 0) ++ { ++ //resolve symlinks ++ if(S_ISLNK(info.st_mode)) ++ { ++ CURL linkUrl(url); ++ if(!ResolveSymlink(strDirName, strFile, &info, linkUrl)) ++ { ++ lock.Leave(); ++ continue; ++ } ++ path = linkUrl.Get(); ++ bIsDir = S_ISDIR(info.st_mode); ++ } ++ lTimeDate = info.st_mtime; ++ if (lTimeDate == 0) // if modification date is missing, use create date ++ lTimeDate = info.st_ctime; ++ iSize = info.st_size; ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "%s - Failed to stat file %s (%s)", __FUNCTION__, strFullName.c_str(),strerror(errno)); ++ } ++ ++ lock.Leave(); ++ } ++ LONGLONG ll = Int32x32To64(lTimeDate & 0xffffffff, 10000000) + 116444736000000000ll; ++ fileTime.dwLowDateTime = (DWORD)(ll & 0xffffffff); ++ fileTime.dwHighDateTime = (DWORD)(ll >> 32); ++ FileTimeToLocalFileTime(&fileTime, &localTime); ++ } ++ else ++ { ++ bIsDir = true; ++ localTime.dwHighDateTime = 0; ++ localTime.dwLowDateTime = 0; ++ } ++ ++ CFileItemPtr pItem(new CFileItem(strFile)); ++ pItem->m_dateTime = localTime; ++ pItem->m_dwSize = iSize; ++ ++ if (bIsDir) ++ { ++ URIUtils::AddSlashAtEnd(path); ++ pItem->m_bIsFolder = true; ++ } ++ else ++ { ++ pItem->m_bIsFolder = false; ++ } ++ ++ if (!aDir.name.empty() && aDir.name[0] == '.') ++ { ++ pItem->SetProperty("file:hidden", true); ++ } ++ ++ pItem->SetPath(path); ++ items.Add(pItem); ++ } ++ } ++ ++ return true; ++} ++ ++bool CAFPDirectory::Create(const CURL& url) ++{ ++ CSingleLock lock(gAfpConnection); ++ ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ std::string strFilename = gAfpConnection.GetPath(url); ++ ++ int result = gAfpConnection.GetImpl()->afp_wrap_mkdir(gAfpConnection.GetVolume(), strFilename.c_str(), 0); ++ ++ if (result != 0) ++ CLog::Log(LOGERROR, "%s - Error( %s )", __FUNCTION__, strerror(errno)); ++ ++ return (result == 0 || EEXIST == result); ++} ++ ++bool CAFPDirectory::Remove(const CURL& url) ++{ ++ CSingleLock lock(gAfpConnection); ++ ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ std::string strFileName = gAfpConnection.GetPath(url); ++ ++ int result = gAfpConnection.GetImpl()->afp_wrap_rmdir(gAfpConnection.GetVolume(), strFileName.c_str()); ++ ++ if (result != 0 && errno != ENOENT) ++ { ++ CLog::Log(LOGERROR, "%s - Error( %s )", __FUNCTION__, strerror(errno)); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool CAFPDirectory::Exists(const CURL& url) ++{ ++ CSingleLock lock(gAfpConnection); ++ ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ std::string strFileName(gAfpConnection.GetPath(url)); ++ ++ struct stat info; ++ if (gAfpConnection.GetImpl()->afp_wrap_getattr(gAfpConnection.GetVolume(), strFileName.c_str(), &info) != 0) ++ return false; ++ ++ return S_ISDIR(info.st_mode); ++} ++#endif +diff --git a/xbmc/filesystem/AFPDirectory.h b/xbmc/filesystem/AFPDirectory.h +new file mode 100644 +index 0000000..7fa3734 +--- /dev/null ++++ b/xbmc/filesystem/AFPDirectory.h +@@ -0,0 +1,47 @@ ++#pragma once ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "IDirectory.h" ++#include "MediaSource.h" ++#include "URL.h" ++ ++struct afp_file_info; ++ ++namespace XFILE ++{ ++class CAFPDirectory : public IDirectory ++{ ++public: ++ CAFPDirectory(void); ++ virtual ~CAFPDirectory(void); ++ virtual bool GetDirectory(const CURL& url, CFileItemList &items); ++ virtual DIR_CACHE_TYPE GetCacheType(const CURL& url) const { return DIR_CACHE_ONCE; }; ++ virtual bool Create(const CURL& url); ++ virtual bool Exists(const CURL& url); ++ virtual bool Remove(const CURL& url); ++ ++ afp_file_info *Open(const CURL &url); ++private: ++ afp_file_info *OpenDir(const CURL &url, std::string& strAuth); ++ bool ResolveSymlink( const std::string &dirName, const std::string &fileName, ++ struct stat *stat, CURL &resolvedUrl); ++}; ++} +diff --git a/xbmc/filesystem/AFPFile.cpp b/xbmc/filesystem/AFPFile.cpp +new file mode 100644 +index 0000000..a4de580 +--- /dev/null ++++ b/xbmc/filesystem/AFPFile.cpp +@@ -0,0 +1,728 @@ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++// FileAFP.cpp: implementation of the CAFPFile class. ++// ++////////////////////////////////////////////////////////////////////// ++#ifdef TARGET_POSIX ++#include "system.h" ++ ++#if defined(HAS_FILESYSTEM_AFP) ++#include "AFPFile.h" ++#include "PasswordManager.h" ++#include "AFPDirectory.h" ++#include "Util.h" ++#include "settings/AdvancedSettings.h" ++#include "threads/SingleLock.h" ++#include "utils/log.h" ++#include "utils/StringUtils.h" ++#include "utils/TimeUtils.h" ++ ++using namespace XFILE; ++ ++#define AFP_MAX_READ_SIZE 131072 ++ ++void AfpConnectionLog(void *priv, enum loglevels loglevel, int logtype, const char *message) ++{ ++ if (!message) return; ++ std::string msg = "LIBAFPCLIENT: " + std::string(message); ++ ++ switch(logtype) ++ { ++ case LOG_WARNING: ++ CLog::Log(LOGWARNING, "%s", msg.c_str()); ++ break; ++ case LOG_ERR: ++ CLog::Log(LOGERROR, "%s", msg.c_str()); ++ break; ++ default: ++ CLog::Log(LOGDEBUG, "%s", msg.c_str()); ++ break; ++ } ++} ++ ++CAfpConnection::CAfpConnection() ++ : m_OpenConnections(0) ++ , m_IdleTimeout(0) ++ , m_pAfpServer(NULL) ++ , m_pAfpVol(NULL) ++ , m_pAfpUrl((struct afp_url*)malloc(sizeof(struct afp_url))) ++ , m_pAfpClient((struct libafpclient*)malloc(sizeof(struct libafpclient))) ++ , m_pLibAfp(new DllLibAfp()) ++ , m_bDllInited(false) ++{ ++} ++ ++CAfpConnection::~CAfpConnection() ++{ ++ Disconnect(); ++ free(m_pAfpClient); ++ free(m_pAfpUrl); ++ if (m_pLibAfp->IsLoaded()) ++ m_pLibAfp->Unload(); ++ delete m_pLibAfp; ++} ++ ++bool CAfpConnection::initLib() ++{ ++ if (!m_bDllInited) ++ { ++ if (m_pLibAfp->Load()) ++ { ++ m_pAfpClient->unmount_volume = NULL; ++ m_pAfpClient->log_for_client = AfpConnectionLog; ++ m_pAfpClient->forced_ending_hook = NULL; ++ m_pAfpClient->scan_extra_fds = NULL; ++ m_pAfpClient->loop_started = NULL; ++ ++ m_pLibAfp->libafpclient_register(m_pAfpClient); ++ m_pLibAfp->init_uams(); ++ m_pLibAfp->afp_main_quick_startup(NULL); ++ CLog::Log(LOGDEBUG, "AFP: Supported UAMs: %s", m_pLibAfp->get_uam_names_list()); ++ m_bDllInited = true; ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "AFP: Error loading afpclient lib."); ++ } ++ } ++ ++ return m_bDllInited; ++} ++ ++//only unmount here - afpclient lib is not ++//stoppable (no afp_main_quick_shutdown as counter part ++//for afp_main_quick_startup) ++void CAfpConnection::Deinit() ++{ ++ if(m_pAfpVol && m_pLibAfp->IsLoaded()) ++ { ++ disconnectVolume(); ++ Disconnect(); ++ m_pAfpUrl->servername[0] = '\0'; ++ } ++} ++ ++void CAfpConnection::Disconnect() ++{ ++ CSingleLock lock(*this); ++ m_pAfpServer = NULL; ++} ++ ++void CAfpConnection::disconnectVolume() ++{ ++ if (m_pAfpVol) ++ { ++ // afp_unmount_volume(m_pAfpVol); ++ m_pLibAfp->afp_unmount_all_volumes(m_pAfpServer); ++ m_pAfpVol = NULL; ++ } ++} ++ ++// taken from cmdline tool ++bool CAfpConnection::connectVolume(const char *volumename, struct afp_volume *&pVolume) ++{ ++ bool ret = false; ++ if (strlen(volumename) != 0) ++ { ++ // Ah, we're not connected to a volume ++ unsigned int len = 0; ++ char mesg[1024]; ++ ++ if ((pVolume = m_pLibAfp->find_volume_by_name(m_pAfpServer, volumename)) == NULL) ++ { ++ CLog::Log(LOGDEBUG, "AFP: Could not find a volume called %s\n", volumename); ++ } ++ else ++ { ++ pVolume->mapping = AFP_MAPPING_LOGINIDS; ++ pVolume->extra_flags |= VOLUME_EXTRA_FLAGS_NO_LOCKING; ++ ++ if (m_pLibAfp->afp_connect_volume(pVolume, m_pAfpServer, mesg, &len, 1024 )) ++ { ++ CLog::Log(LOGDEBUG, "AFP: Could not access volume %s (error: %s)\n", pVolume->volume_name, mesg); ++ pVolume = NULL; ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, "AFP: Connected to volume %s\n", pVolume->volume_name_printable); ++ ret = true; ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++CURL CAfpConnection::getAuthenticatedPath(const CURL &url) ++{ ++ CURL authURL(url); ++ CPasswordManager::GetInstance().AuthenticateURL(authURL); ++ return authURL; ++} ++ ++CAfpConnection::afpConnnectError CAfpConnection::Connect(const CURL& url) ++{ ++ CSingleLock lock(*this); ++ struct afp_connection_request *conn_req = NULL; ++ struct afp_url tmpurl; ++ CURL nonConstUrl(getAuthenticatedPath(url)); // we need a editable copy of the url ++ bool serverChanged=false; ++ ++ if (!initLib()) ++ return AfpFailed; ++ ++ m_pLibAfp->afp_default_url(&tmpurl); ++ ++ // if hostname has changed - assume server changed ++ if (nonConstUrl.GetHostName() != m_pAfpUrl->servername || (m_pAfpServer && m_pAfpServer->connect_state == 0)) ++ { ++ serverChanged = true; ++ Disconnect(); ++ } ++ ++ // if volume changed - also assume server changed (afpclient can't reuse old servobject it seems) ++ if (nonConstUrl.GetShareName() != m_pAfpUrl->volumename) ++ { ++ // no reusing of old server object possible with libafpclient it seems... ++ serverChanged = true; ++ Disconnect(); ++ } ++ ++ // first, try to parse the URL ++ if (m_pLibAfp->afp_parse_url(&tmpurl, nonConstUrl.Get().c_str(), 0) != 0) ++ { ++ // Okay, this isn't a real URL ++ CLog::Log(LOGDEBUG, "AFP: Could not parse url: %s!\n", nonConstUrl.Get().c_str()); ++ return AfpFailed; ++ } ++ else // parsed successfully ++ { ++ // this is our current url object whe are connected to (at least we try) ++ *m_pAfpUrl = tmpurl; ++ } ++ ++ // if no username and password is set - use no user authent uam ++ if (strlen(m_pAfpUrl->password) == 0 && strlen(m_pAfpUrl->username) == 0) ++ { ++ // try anonymous ++ strncpy(m_pAfpUrl->uamname, "No User Authent", sizeof(m_pAfpUrl->uamname)); ++ CLog::Log(LOGDEBUG, "AFP: Using anonymous authentication."); ++ } ++ else if ((nonConstUrl.GetPassWord().empty() || nonConstUrl.GetUserName().empty()) && serverChanged) ++ { ++ // this is our current url object whe are connected to (at least we try) ++ return AfpAuth; ++ } ++ ++ // we got a password in the url ++ if (!nonConstUrl.GetPassWord().empty()) ++ { ++ // copy password because afp_parse_url just puts garbage into the password field :( ++ strncpy(m_pAfpUrl->password, nonConstUrl.GetPassWord().c_str(), 127); ++ } ++ ++ // whe are not connected or we want to connect to another server ++ if (!m_pAfpServer || serverChanged) ++ { ++ // code from cmdline tool ++ conn_req = (struct afp_connection_request*)malloc(sizeof(struct afp_connection_request)); ++ memset(conn_req, 0, sizeof(struct afp_connection_request)); ++ ++ conn_req->url = *m_pAfpUrl; ++ conn_req->url.requested_version = 31; ++ ++ if (strlen(m_pAfpUrl->uamname)>0) ++ { ++ if ((conn_req->uam_mask = m_pLibAfp->find_uam_by_name(m_pAfpUrl->uamname)) == 0) ++ { ++ CLog::Log(LOGDEBUG, "AFP:I don't know about UAM %s\n", m_pAfpUrl->uamname); ++ m_pAfpUrl->volumename[0] = '\0'; ++ m_pAfpUrl->servername[0] = '\0'; ++ free(conn_req); ++ return AfpFailed; ++ } ++ } ++ else ++ { ++ conn_req->uam_mask = m_pLibAfp->default_uams_mask(); ++ } ++ ++ // try to connect ++#ifdef USE_CVS_AFPFS ++ if ((m_pAfpServer = m_pLibAfp->afp_wrap_server_full_connect(NULL, conn_req, NULL)) == NULL) ++#else ++ if ((m_pAfpServer = m_pLibAfp->afp_wrap_server_full_connect(NULL, conn_req)) == NULL) ++#endif ++ { ++ m_pAfpUrl->volumename[0] = '\0'; ++ m_pAfpUrl->servername[0] = '\0'; ++ free(conn_req); ++ CLog::Log(LOGERROR, "AFP: Error connecting to %s", url.Get().c_str()); ++ return AfpFailed; ++ } ++ // success! ++ CLog::Log(LOGDEBUG, "AFP: Connected to server %s using UAM \"%s\"\n", ++ m_pAfpServer->server_name, m_pLibAfp->uam_bitmap_to_string(m_pAfpServer->using_uam)); ++ // we don't need it after here ... ++ free(conn_req); ++ } ++ ++ // if server changed reconnect volume ++ if (serverChanged) ++ { ++ connectVolume(m_pAfpUrl->volumename, m_pAfpVol); // connect new volume ++ } ++ return AfpOk; ++} ++ ++int CAfpConnection::stat(const CURL &url, struct stat *statbuff) ++{ ++ CSingleLock lock(*this); ++ std::string strPath = gAfpConnection.GetPath(url); ++ struct afp_volume *pTmpVol = NULL; ++ struct afp_url tmpurl; ++ int iResult = -1; ++ CURL nonConstUrl(getAuthenticatedPath(url)); // we need a editable copy of the url ++ ++ if (!initLib() || !m_pAfpServer) ++ return -1; ++ ++ m_pLibAfp->afp_default_url(&tmpurl); ++ ++ // first, try to parse the URL ++ if (m_pLibAfp->afp_parse_url(&tmpurl, nonConstUrl.Get().c_str(), 0) != 0) ++ { ++ // Okay, this isn't a real URL ++ CLog::Log(LOGDEBUG, "AFP: Could not parse url: %s!\n", nonConstUrl.Get().c_str()); ++ return -1; ++ } ++ ++ // if no username and password is set - use no user authent uam ++ if (strlen(tmpurl.password) == 0 && strlen(tmpurl.username) == 0) ++ { ++ // try anonymous ++ strncpy(tmpurl.uamname, "No User Authent", sizeof(tmpurl.uamname)); ++ CLog::Log(LOGDEBUG, "AFP: Using anonymous authentication."); ++ } ++ else if ((nonConstUrl.GetPassWord().empty() || nonConstUrl.GetUserName().empty())) ++ { ++ // this is our current url object whe are connected to (at least we try) ++ return -1; ++ } ++ ++ // we got a password in the url ++ if (!nonConstUrl.GetPassWord().empty()) ++ { ++ // copy password because afp_parse_url just puts garbage into the password field :( ++ strncpy(tmpurl.password, nonConstUrl.GetPassWord().c_str(), 127); ++ } ++ ++ // connect new volume ++ if(connectVolume(tmpurl.volumename, pTmpVol) && pTmpVol) ++ { ++ iResult = m_pLibAfp->afp_wrap_getattr(pTmpVol, strPath.c_str(), statbuff); ++ //unmount single volume crashs ++ //we will get rid of the mounted volume ++ //once the context is changed in connect function ++ //ppppooooorrrr!! ++ //m_pLibAfp->afp_unmount_volume(pTmpVol); ++ } ++ return iResult; ++} ++ ++ ++/* This is called from CApplication::ProcessSlow() and is used to tell if afp have been idle for too long */ ++void CAfpConnection::CheckIfIdle() ++{ ++ /* We check if there are open connections. This is done without a lock to not halt the mainthread. It should be thread safe as ++ worst case scenario is that m_OpenConnections could read 0 and then changed to 1 if this happens it will enter the if wich will lead to another check, wich is locked. */ ++ if (m_OpenConnections == 0 && m_pAfpVol != NULL) ++ { /* I've set the the maxiumum IDLE time to be 1 min and 30 sec. */ ++ CSingleLock lock(*this); ++ if (m_OpenConnections == 0 /* check again - when locked */) ++ { ++ if (m_IdleTimeout > 0) ++ { ++ m_IdleTimeout--; ++ } ++ else ++ { ++ CLog::Log(LOGNOTICE, "AFP is idle. Closing the remaining connections."); ++ gAfpConnection.Deinit(); ++ } ++ } ++ } ++} ++ ++/* The following two function is used to keep track on how many Opened files/directories there are. ++needed for unloading the dylib*/ ++void CAfpConnection::AddActiveConnection() ++{ ++ CSingleLock lock(*this); ++ m_OpenConnections++; ++} ++ ++void CAfpConnection::AddIdleConnection() ++{ ++ CSingleLock lock(*this); ++ m_OpenConnections--; ++ /* If we close a file we reset the idle timer so that we don't have any wierd behaviours if a user ++ leaves the movie paused for a long while and then press stop */ ++ m_IdleTimeout = 180; ++} ++ ++std::string CAfpConnection::GetPath(const CURL &url) ++{ ++ struct afp_url tmpurl; ++ std::string ret; ++ ++ m_pLibAfp->afp_default_url(&tmpurl); ++ ++ // First, try to parse the URL ++ if (m_pLibAfp->afp_parse_url(&tmpurl, url.Get().c_str(), 0) != 0 ) ++ { ++ // Okay, this isn't a real URL ++ CLog::Log(LOGDEBUG, "AFP: Could not parse url.\n"); ++ } ++ else ++ { ++ ret = tmpurl.path; ++ } ++ return ret; ++} ++ ++CAfpConnection gAfpConnection; ++ ++CAFPFile::CAFPFile() ++ : m_fileSize(0) ++ , m_fileOffset(0) ++ , m_pFp(NULL) ++ , m_pAfpVol(NULL) ++{ ++ gAfpConnection.AddActiveConnection(); ++} ++ ++CAFPFile::~CAFPFile() ++{ ++ gAfpConnection.AddIdleConnection(); ++ Close(); ++} ++ ++int64_t CAFPFile::GetPosition() ++{ ++ if (m_pFp == NULL) return 0; ++ return m_fileOffset; ++} ++ ++int64_t CAFPFile::GetLength() ++{ ++ if (m_pFp == NULL) return 0; ++ return m_fileSize; ++} ++ ++bool CAFPFile::Open(const CURL& url) ++{ ++ Close(); ++ // we can't open files like afp://file.f or afp://server/file.f ++ // if a file matches the if below return false, it can't exist on a afp share. ++ if (!IsValidFile(url.GetFileName())) ++ { ++ CLog::Log(LOGNOTICE, "FileAfp: Bad URL : '%s'", url.GetFileName().c_str()); ++ return false; ++ } ++ ++ CSingleLock lock(gAfpConnection); ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ m_pAfpVol = gAfpConnection.GetVolume(); ++ ++ std::string strPath = gAfpConnection.GetPath(url); ++ ++ if (gAfpConnection.GetImpl()->afp_wrap_open(m_pAfpVol, strPath.c_str(), O_RDONLY, &m_pFp)) ++ { ++ if (gAfpConnection.GetImpl()->afp_wrap_open(m_pAfpVol, CURL::Encode(strPath.c_str()).c_str(), O_RDONLY, &m_pFp)) ++ { ++ // write error to logfile ++ CLog::Log(LOGINFO, "CAFPFile::Open: Unable to open file : '%s'\nunix_err:'%x' error : '%s'", strPath.c_str(), errno, strerror(errno)); ++ return false; ++ } ++ } ++ ++ CLog::Log(LOGDEBUG,"CAFPFile::Open - opened %s, fd=%d",url.GetFileName().c_str(), m_pFp ? m_pFp->fileid:-1); ++ m_url = url; ++ ++#ifdef TARGET_POSIX ++ struct __stat64 tmpBuffer; ++#else ++ struct stat tmpBuffer; ++#endif ++ if(Stat(&tmpBuffer)) ++ { ++ m_url.Reset(); ++ Close(); ++ return false; ++ } ++ ++ m_fileSize = tmpBuffer.st_size; ++ m_fileOffset = 0; ++ // We've successfully opened the file! ++ return true; ++} ++ ++ ++bool CAFPFile::Exists(const CURL& url) ++{ ++ return Stat(url, NULL) == 0; ++} ++ ++int CAFPFile::Stat(struct __stat64* buffer) ++{ ++ if (m_pFp == NULL) ++ return -1; ++ return Stat(m_url, buffer); ++} ++ ++// TODO - maybe check returncode! ++int CAFPFile::Stat(const CURL& url, struct __stat64* buffer) ++{ ++ CSingleLock lock(gAfpConnection); ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return -1; ++ ++ std::string strPath = gAfpConnection.GetPath(url); ++ ++ struct stat tmpBuffer = {0}; ++ int iResult = gAfpConnection.GetImpl()->afp_wrap_getattr(gAfpConnection.GetVolume(), strPath.c_str(), &tmpBuffer); ++ ++ if (buffer) ++ { ++ memset(buffer, 0, sizeof(struct __stat64)); ++ buffer->st_dev = tmpBuffer.st_dev; ++ buffer->st_ino = tmpBuffer.st_ino; ++ buffer->st_mode = tmpBuffer.st_mode; ++ buffer->st_nlink = tmpBuffer.st_nlink; ++ buffer->st_uid = tmpBuffer.st_uid; ++ buffer->st_gid = tmpBuffer.st_gid; ++ buffer->st_rdev = tmpBuffer.st_rdev; ++ buffer->st_size = tmpBuffer.st_size; ++ buffer->st_atime = tmpBuffer.st_atime; ++ buffer->st_mtime = tmpBuffer.st_mtime; ++ buffer->st_ctime = tmpBuffer.st_ctime; ++ } ++ ++ return iResult; ++} ++ ++ssize_t CAFPFile::Read(void *lpBuf, size_t uiBufSize) ++{ ++ CSingleLock lock(gAfpConnection); ++ if (m_pFp == NULL || !m_pAfpVol) ++ return -1; ++ ++ if (uiBufSize > AFP_MAX_READ_SIZE) ++ uiBufSize = AFP_MAX_READ_SIZE; ++ ++#ifdef USE_CVS_AFPFS ++ char *name = m_pFp->basename; ++#else ++ char *name = m_pFp->name; ++ if (strlen(name) == 0) ++ name = m_pFp->basename; ++ ++#endif ++ int eof = 0; ++ ssize_t bytesRead = gAfpConnection.GetImpl()->afp_wrap_read(m_pAfpVol, ++ name, (char *)lpBuf,(size_t)uiBufSize, m_fileOffset, m_pFp, &eof); ++ if (bytesRead > 0) ++ m_fileOffset += bytesRead; ++ ++ if (bytesRead < 0) ++ { ++ CLog::Log(LOGERROR, "%s - Error( %d, %d, %s )", __FUNCTION__, bytesRead, errno, strerror(errno)); ++ return -1; ++ } ++ ++ return bytesRead; ++} ++ ++int64_t CAFPFile::Seek(int64_t iFilePosition, int iWhence) ++{ ++ off_t newOffset = m_fileOffset; ++ if (m_pFp == NULL) return -1; ++ ++ switch(iWhence) ++ { ++ case SEEK_SET: ++ newOffset = iFilePosition; ++ break; ++ case SEEK_END: ++ newOffset = m_fileSize+iFilePosition; ++ break; ++ case SEEK_CUR: ++ newOffset += iFilePosition; ++ break; ++ } ++ ++ if ( newOffset < 0 || newOffset > m_fileSize) ++ { ++ CLog::Log(LOGERROR, "%s - Error( %" PRId64")", __FUNCTION__, newOffset); ++ return -1; ++ } ++ ++ m_fileOffset = newOffset; ++ return (int64_t)m_fileOffset; ++} ++ ++void CAFPFile::Close() ++{ ++ CSingleLock lock(gAfpConnection); ++ if (m_pFp != NULL && m_pAfpVol) ++ { ++ CLog::Log(LOGDEBUG, "CAFPFile::Close closing fd %d", m_pFp->fileid); ++#ifdef USE_CVS_AFPFS ++ char *name = m_pFp->basename; ++#else ++ char *name = m_pFp->name; ++ if (strlen(name) == 0) ++ name = m_pFp->basename; ++#endif ++ gAfpConnection.GetImpl()->afp_wrap_close(m_pAfpVol, name, m_pFp); ++ delete m_pFp; ++ m_pFp = NULL; ++ m_pAfpVol = NULL; ++ } ++} ++ ++ssize_t CAFPFile::Write(const void* lpBuf, size_t uiBufSize) ++{ ++ CSingleLock lock(gAfpConnection); ++ if (m_pFp == NULL || !m_pAfpVol) ++ return -1; ++ ++ ssize_t numberOfBytesWritten = 0; ++ uid_t uid; ++ gid_t gid; ++ ++ // FIXME need a better way to get server's uid/gid ++ uid = getuid(); ++ gid = getgid(); ++#ifdef USE_CVS_AFPFS ++ char *name = m_pFp->basename; ++#else ++ char *name = m_pFp->name; ++ if (strlen(name) == 0) ++ name = m_pFp->basename; ++#endif ++ numberOfBytesWritten = gAfpConnection.GetImpl()->afp_wrap_write(m_pAfpVol, ++ name, (const char *)lpBuf, uiBufSize, m_fileOffset, m_pFp, uid, gid); ++ ++ if (numberOfBytesWritten > 0) ++ m_fileOffset += numberOfBytesWritten; ++ ++ return numberOfBytesWritten; ++} ++ ++bool CAFPFile::Delete(const CURL& url) ++{ ++ CSingleLock lock(gAfpConnection); ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ std::string strPath = gAfpConnection.GetPath(url); ++ ++ int result = gAfpConnection.GetImpl()->afp_wrap_unlink(gAfpConnection.GetVolume(), strPath.c_str()); ++ ++ if (result != 0) ++ CLog::Log(LOGERROR, "%s - Error( %s )", __FUNCTION__, strerror(errno)); ++ ++ return (result == 0); ++} ++ ++bool CAFPFile::Rename(const CURL& url, const CURL& urlnew) ++{ ++ CSingleLock lock(gAfpConnection); ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ std::string strFile = gAfpConnection.GetPath(url); ++ std::string strFileNew = gAfpConnection.GetPath(urlnew); ++ ++ int result = gAfpConnection.GetImpl()->afp_wrap_rename(gAfpConnection.GetVolume(), strFile.c_str(), strFileNew.c_str()); ++ ++ if (result != 0) ++ CLog::Log(LOGERROR, "%s - Error( %s )", __FUNCTION__, strerror(errno)); ++ ++ return (result == 0); ++} ++ ++bool CAFPFile::OpenForWrite(const CURL& url, bool bOverWrite) ++{ ++ ++ int ret = 0; ++ m_fileSize = 0; ++ m_fileOffset = 0; ++ ++ Close(); ++ CSingleLock lock(gAfpConnection); ++ if (gAfpConnection.Connect(url) != CAfpConnection::AfpOk || !gAfpConnection.GetVolume()) ++ return false; ++ ++ // we can't open files like afp://file.f or afp://server/file.f ++ // if a file matches the if below return false, it can't exist on a afp share. ++ if (!IsValidFile(url.GetFileName())) ++ return false; ++ ++ m_pAfpVol = gAfpConnection.GetVolume(); ++ ++ std::string strPath = gAfpConnection.GetPath(url); ++ ++ if (bOverWrite) ++ { ++ CLog::Log(LOGWARNING, "FileAFP::OpenForWrite() called with overwriting enabled! - %s", strPath.c_str()); ++ ret = gAfpConnection.GetImpl()->afp_wrap_creat(m_pAfpVol, strPath.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); ++ } ++ ++ ret = gAfpConnection.GetImpl()->afp_wrap_open(m_pAfpVol, strPath.c_str(), O_RDWR, &m_pFp); ++ ++ if (ret || m_pFp == NULL) ++ { ++ // write error to logfile ++ CLog::Log(LOGERROR, "CAFPFile::Open: Unable to open file : '%s'\nunix_err:'%x' error : '%s'", strPath.c_str(), errno, strerror(errno)); ++ return false; ++ } ++ ++ // We've successfully opened the file! ++ return true; ++} ++ ++bool CAFPFile::IsValidFile(const std::string& strFileName) ++{ ++ if (strFileName.find('/') == std::string::npos || // doesn't have sharename ++ StringUtils::EndsWith(strFileName, "/.") || // not current folder ++ StringUtils::EndsWith(strFileName, "/..")) // not parent folder ++ { ++ return false; ++ } ++ ++ return true; ++} ++#endif // HAS_FILESYSTEM_AFP ++#endif // TARGET_POSIX +diff --git a/xbmc/filesystem/AFPFile.h b/xbmc/filesystem/AFPFile.h +new file mode 100644 +index 0000000..9880b26 +--- /dev/null ++++ b/xbmc/filesystem/AFPFile.h +@@ -0,0 +1,134 @@ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++// FileAFP.h: interface for the CAFPFile class. ++#ifndef FILEAFP_H_ ++#define FILEAFP_H_ ++ ++ ++#ifdef TARGET_POSIX ++ ++#include "IFile.h" ++#include "URL.h" ++#include "threads/CriticalSection.h" ++#include "DllLibAfp.h" ++ ++// libafpclient includes ++#ifdef __cplusplus ++extern "C" { ++#endif ++#ifdef __cplusplus ++} ++#endif ++ ++class CAfpConnection : public CCriticalSection ++{ ++public: ++ enum eAfpConnectError ++ { ++ AfpOk = 0, ++ AfpFailed = 1, ++ AfpAuth = 2, ++ }; ++ typedef enum eAfpConnectError afpConnnectError; ++ ++ CAfpConnection(); ++ ~CAfpConnection(); ++ ++ afpConnnectError Connect(const CURL &url); ++ void Disconnect(void); ++ struct afp_server *GetServer() {return m_pAfpServer;} ++ struct afp_volume *GetVolume() {return m_pAfpVol;}; ++ struct afp_url *GetUrl() {return m_pAfpUrl;}; ++ std::string GetPath(const CURL &url); ++ DllLibAfp *GetImpl() {return m_pLibAfp;} ++ ++ const char *GetConnectedIp() const { if(m_pAfpUrl) return m_pAfpUrl->servername;else return "";} ++ ++ //special stat which uses its own context ++ //needed for getting intervolume symlinks to work ++ //it uses the same global server connection ++ //but its own volume ++ int stat(const CURL &url, struct stat *statbuff); ++ ++ void AddActiveConnection(); ++ void AddIdleConnection(); ++ void CheckIfIdle(); ++ void Deinit(); ++ ++private: ++ bool initLib(void); ++ bool connectVolume(const char *volumename, struct afp_volume *&pVolume); ++ void disconnectVolume(void); ++ CURL getAuthenticatedPath(const CURL &url); ++ ++ int m_OpenConnections; ++ int m_IdleTimeout; ++ struct afp_server *m_pAfpServer; ++ struct afp_volume *m_pAfpVol; ++ struct afp_url *m_pAfpUrl; ++ struct libafpclient *m_pAfpClient; ++ DllLibAfp *m_pLibAfp; ++ bool m_bDllInited; ++}; ++ ++extern CAfpConnection gAfpConnection; ++ ++namespace XFILE ++{ ++class CAFPFile : public IFile ++{ ++public: ++ CAFPFile(); ++ virtual ~CAFPFile(); ++ virtual void Close(); ++ virtual int64_t Seek(int64_t iFilePosition, int iWhence = SEEK_SET); ++ virtual ssize_t Read(void* lpBuf, size_t uiBufSize); ++ virtual bool Open(const CURL& url); ++ virtual bool Exists(const CURL& url); ++ virtual int Stat(const CURL& url, struct __stat64* buffer); ++ virtual int Stat(struct __stat64* buffer); ++ virtual int64_t GetLength(); ++ virtual int64_t GetPosition(); ++ virtual ssize_t Write(const void* lpBuf, size_t uiBufSize); ++ ++ virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false); ++ virtual bool Delete(const CURL& url); ++ virtual bool Rename(const CURL& url, const CURL& urlnew); ++ virtual int GetChunkSize() {return 1;} ++ // implement iocontrol for seek_possible for preventing the stat in File class for ++ // getting this info ... ++ virtual int IoControl(EIoControl request, void* param) ++ { if (request == IOCTRL_SEEK_POSSIBLE) return 1; ++ return -1; ++ }; ++ ++protected: ++ bool IsValidFile(const std::string& strFileName); ++ ++ CURL m_url; ++ int64_t m_fileSize; ++ off_t m_fileOffset; // current SEEK pointer ++ struct afp_file_info *m_pFp; ++ struct afp_volume *m_pAfpVol; ++}; ++} ++#endif // TARGET_POSIX ++#endif // FILEAFP_H_ +diff --git a/xbmc/filesystem/APKDirectory.cpp b/xbmc/filesystem/APKDirectory.cpp +index 7c29421..c2a133b 100644 +--- a/xbmc/filesystem/APKDirectory.cpp ++++ b/xbmc/filesystem/APKDirectory.cpp +@@ -96,7 +96,7 @@ bool CAPKDirectory::GetDirectory(const CURL& url, CFileItemList &items) + + bool CAPKDirectory::ContainsFiles(const CURL& url) + { +- //! @todo why might we need this ? ++ // TODO: why might we need this ? + return false; + } + +diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp +index f176161..db98719 100644 +--- a/xbmc/filesystem/AddonsDirectory.cpp ++++ b/xbmc/filesystem/AddonsDirectory.cpp +@@ -348,7 +348,6 @@ static bool Browse(const CURL& path, CFileItemList &items) + const std::string repo = path.GetHostName(); + + VECADDONS addons; +- items.SetPath(path.Get()); + if (repo == "all") + { + CAddonDatabase database; +@@ -654,7 +653,7 @@ CFileItemPtr CAddonsDirectory::FileItemFromAddon(const AddonPtr &addon, + if (URIUtils::IsInternetStream(addon->FanArt()) || CFile::Exists(addon->FanArt())) + item->SetArt("fanart", addon->FanArt()); + +- //! @todo fix hacks that depends on these ++ //TODO: fix hacks that depends on these + item->SetProperty("Addon.ID", addon->ID()); + item->SetProperty("Addon.Name", addon->Name()); + const auto it = addon->ExtraInfo().find("language"); +diff --git a/xbmc/filesystem/CMakeLists.txt b/xbmc/filesystem/CMakeLists.txt +index 6818acf..da0f782 100644 +--- a/xbmc/filesystem/CMakeLists.txt ++++ b/xbmc/filesystem/CMakeLists.txt +@@ -18,6 +18,7 @@ set(SOURCES AddonsDirectory.cpp + File.cpp + FileDirectoryFactory.cpp + FileFactory.cpp ++ FileReaderFile.cpp + FTPDirectory.cpp + FTPParse.cpp + HTTPDirectory.cpp +@@ -99,6 +100,7 @@ set(HEADERS AddonsDirectory.h + FileCache.h + FileDirectoryFactory.h + FileFactory.h ++ FileReaderFile.h + HTTPDirectory.h + IDirectory.h + IFile.h +diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp +index bb116dd..ee1ad20 100644 +--- a/xbmc/filesystem/CurlFile.cpp ++++ b/xbmc/filesystem/CurlFile.cpp +@@ -18,6 +18,8 @@ + * + */ + ++#include "network/Network.h" ++#include "Application.h" + #include "CurlFile.h" + #include "utils/URIUtils.h" + #include "Util.h" +@@ -235,7 +237,7 @@ size_t CCurlFile::CReadState::WriteCallback(char *buffer, size_t size, size_t ni + { + // CLog::Log(LOGDEBUG, "CCurlFile::WriteCallback(%p) not enough free space for %i bytes", (void*)this, amount); + +- //! @todo Limit max. amount of the overflowbuffer ++ // TODO: Limit max. amount of the overflowbuffer + m_overflowBuffer = (char*)realloc_simple(m_overflowBuffer, amount + m_overflowSize); + if(m_overflowBuffer == NULL) + { +@@ -648,11 +650,10 @@ void CCurlFile::SetCommonOptions(CReadState* state) + g_curlInterface.easy_setopt(h, CURLOPT_LOW_SPEED_TIME, m_lowspeedtime); + + if (m_skipshout) +- //! @todo +- //! For shoutcast file, content-length should not be set, and in libcurl there is a bug, if the +- //! cast file was 302 redirected then getinfo of CURLINFO_CONTENT_LENGTH_DOWNLOAD will return +- //! the 302 response's body length, which cause the next read request failed, so we ignore +- //! content-length for shoutcast file to workaround this. ++ // For shoutcast file, content-length should not be set, and in libcurl there is a bug, if the ++ // cast file was 302 redirected then getinfo of CURLINFO_CONTENT_LENGTH_DOWNLOAD will return ++ // the 302 response's body length, which cause the next read request failed, so we ignore ++ // content-length for shoutcast file to workaround this. + g_curlInterface.easy_setopt(h, CURLOPT_IGNORE_CONTENT_LENGTH, 1); + + // Setup allowed TLS/SSL ciphers. New versions of cURL may deprecate things that are still in use. +@@ -732,7 +733,7 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) + if (url2.GetProtocolOption("utf8") == "0") + g_charsetConverter.utf8ToStringCharset(filename); + +- //! @todo create a tokenizer that doesn't skip empty's ++ /* TODO: create a tokenizer that doesn't skip empty's */ + StringUtils::Tokenize(filename, array, "/"); + filename.clear(); + for(std::vector::iterator it = array.begin(); it != array.end(); it++) +@@ -918,13 +919,13 @@ bool CCurlFile::Download(const std::string& strURL, const std::string& strFileNa + // Detect whether we are "online" or not! Very simple and dirty! + bool CCurlFile::IsInternet() + { +- CURL url("http://www.msftncsi.com/ncsi.txt"); ++ CURL url(StringUtils::Format("http://%s.msftncsi.com/ncsi.txt", g_application.getNetwork().GetFirstConnectedFamily() == AF_INET6 ? "ipv6" : "www")); + bool found = Exists(url); + if (!found) + { + // fallback + Close(); +- url.Parse("http://www.w3.org/"); ++ url.Parse(StringUtils::Format("http://%s.w3.org/", g_application.getNetwork().GetFirstConnectedFamily() == AF_INET6 ? "ipv6" : "www")); + found = Exists(url); + } + Close(); +@@ -1291,7 +1292,7 @@ int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) + SetCommonOptions(m_state); + + /* caller might have changed some headers (needed for daap)*/ +- //! @todo daap is gone. is this needed for something else? ++ // TODO: daap is gone. is this needed for something else? + SetRequestHeaders(m_state); + + m_state->m_filePos = nextPos; +diff --git a/xbmc/filesystem/Directory.cpp b/xbmc/filesystem/Directory.cpp +index 05a3e43..1a713dc 100644 +--- a/xbmc/filesystem/Directory.cpp ++++ b/xbmc/filesystem/Directory.cpp +@@ -217,7 +217,7 @@ bool CDirectory::GetDirectory(const CURL& url, CFileItemList &items, const CHint + } + } + // filter hidden files +- //! @todo we shouldn't be checking the gui setting here, callers should use getHidden instead ++ // TODO: we shouldn't be checking the gui setting here, callers should use getHidden instead + if (!CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_SHOWHIDDEN) && !(hints.flags & DIR_FLAG_GET_HIDDEN)) + { + for (int i = 0; i < items.Size(); ++i) +diff --git a/xbmc/filesystem/DirectoryFactory.cpp b/xbmc/filesystem/DirectoryFactory.cpp +index 662b63b..c87cb63 100644 +--- a/xbmc/filesystem/DirectoryFactory.cpp ++++ b/xbmc/filesystem/DirectoryFactory.cpp +@@ -91,6 +91,9 @@ + #ifdef HAS_FILESYSTEM_NFS + #include "NFSDirectory.h" + #endif ++#ifdef HAS_FILESYSTEM_AFP ++#include "AFPDirectory.h" ++#endif + #ifdef HAVE_LIBBLURAY + #include "BlurayDirectory.h" + #endif +@@ -157,6 +160,11 @@ IDirectory* CDirectoryFactory::Create(const CURL& url) + if (url.IsProtocol("videodb")) return new CVideoDatabaseDirectory(); + if (url.IsProtocol("library")) return new CLibraryDirectory(); + if (url.IsProtocol("favourites")) return new CFavouritesDirectory(); ++ if (url.IsProtocol("filereader")) ++ { ++ CURL url2(url.GetFileName()); ++ return CDirectoryFactory::Create(url2); ++ } + #if defined(TARGET_ANDROID) + if (url.IsProtocol("androidapp")) return new CAndroidAppDirectory(); + #endif +@@ -166,7 +174,7 @@ IDirectory* CDirectoryFactory::Create(const CURL& url) + if (url.IsProtocol("resource")) return new CResourceDirectory(); + if (url.IsProtocol("events")) return new CEventsDirectory(); + +- bool networkAvailable = g_application.getNetwork().IsAvailable(); ++ bool networkAvailable = g_application.getNetwork().IsConnected(); + if (networkAvailable) + { + if (url.IsProtocol("ftp") || url.IsProtocol("ftps")) return new CFTPDirectory(); +@@ -197,6 +205,9 @@ IDirectory* CDirectoryFactory::Create(const CURL& url) + #ifdef HAS_FILESYSTEM_NFS + if (url.IsProtocol("nfs")) return new CNFSDirectory(); + #endif ++#ifdef HAS_FILESYSTEM_AFP ++ if (url.IsProtocol("afp")) return new CAFPDirectory(); ++#endif + } + + CLog::Log(LOGWARNING, "%s - %sunsupported protocol(%s) in %s", __FUNCTION__, networkAvailable ? "" : "Network down or ", url.GetProtocol().c_str(), url.GetRedacted().c_str() ); +diff --git a/xbmc/filesystem/DllLibAfp.h b/xbmc/filesystem/DllLibAfp.h +new file mode 100644 +index 0000000..c87d920 +--- /dev/null ++++ b/xbmc/filesystem/DllLibAfp.h +@@ -0,0 +1,214 @@ ++#pragma once ++ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "DynamicDll.h" ++ ++//libafpclient includes ++#ifdef __cplusplus ++extern "C" { ++#endif ++#include ++#include ++#include ++#ifdef __cplusplus ++} ++#endif ++ ++ ++//#define USE_CVS_AFPFS ++#ifdef USE_CVS_AFPFS ++#define afp_wrap_open afp_ml_open ++#define afp_wrap_close afp_ml_close ++#define afp_wrap_read afp_ml_read ++#define afp_wrap_write afp_ml_write ++#define afp_wrap_getattr afp_ml_getattr ++#define afp_wrap_server_full_connect afp_server_full_connect ++#define afp_wrap_unlink afp_ml_unlink ++#define afp_wrap_rename afp_ml_rename ++#define afp_wrap_creat afp_ml_creat ++#define afp_wrap_readdir afp_ml_readdir ++#define afp_wrap_readlink afp_ml_readlink ++#define afp_wrap_mkdir afp_ml_mkdir ++#define afp_wrap_rmdir afp_ml_rmdir ++#else ++#define afp_wrap_open ml_open ++#define afp_wrap_close ml_close ++#define afp_wrap_read ml_read ++#define afp_wrap_write ml_write ++#define afp_wrap_getattr ml_getattr ++#define afp_wrap_server_full_connect afp_server_full_connect ++#define afp_wrap_unlink ml_unlink ++#define afp_wrap_rename ml_rename ++#define afp_wrap_creat ml_creat ++#define afp_wrap_readdir ml_readdir ++#define afp_wrap_readlink ml_readlink ++#define afp_wrap_mkdir ml_mkdir ++#define afp_wrap_rmdir ml_rmdir ++#endif ++ ++ ++class DllLibAfpInterface ++{ ++public: ++ virtual ~DllLibAfpInterface() {} ++ ++ virtual void libafpclient_register(struct libafpclient * tmpclient)=0; ++ virtual int init_uams(void)=0; ++ virtual int afp_main_quick_startup(pthread_t * thread)=0; ++ virtual int afp_unmount_all_volumes(struct afp_server * server)=0; ++ virtual int afp_unmount_volume(struct afp_volume * volume)=0; ++ virtual struct afp_volume * find_volume_by_name(struct afp_server * server, const char * volname)=0; ++ virtual int afp_connect_volume(struct afp_volume * volume, struct afp_server * server, char * mesg, unsigned int * l, unsigned int max)=0; ++ virtual int afp_parse_url(struct afp_url * url, const char * toparse, int verbose)=0; ++ virtual unsigned int find_uam_by_name(const char * name)=0; ++ virtual unsigned int default_uams_mask(void)=0; ++ virtual char * uam_bitmap_to_string(unsigned int bitmap)=0; ++ virtual void afp_default_url(struct afp_url *url)=0; ++ virtual char * get_uam_names_list(void)=0; ++ virtual void afp_ml_filebase_free(struct afp_file_info **filebase)=0; ++ ++#ifdef USE_CVS_AFPFS ++ virtual struct afp_server * afp_server_full_connect(void * priv, struct afp_connection_request * req, int * error)=0; ++ virtual int afp_ml_open(struct afp_volume * volume, const char *path, int flags, struct afp_file_info **newfp)=0; ++ virtual int afp_ml_close(struct afp_volume * volume, const char * path, struct afp_file_info * fp)=0; ++ virtual int afp_ml_read(struct afp_volume * volume, const char *path, char *buf, size_t size, off_t offset, struct afp_file_info *fp, int * eof)=0; ++ virtual int afp_ml_write(struct afp_volume * volume, const char * path, const char *data, size_t size, off_t offset, struct afp_file_info * fp, uid_t uid, gid_t gid)=0; ++ virtual int afp_ml_getattr(struct afp_volume * volume, const char *path, struct stat *stbuf)=0; ++ virtual int afp_ml_unlink(struct afp_volume * vol, const char *path)=0; ++ virtual int afp_ml_rename(struct afp_volume * vol, const char * path_from, const char * path_to)=0; ++ virtual int afp_ml_creat(struct afp_volume * volume, const char *path, mode_t mode)=0; ++ virtual int afp_ml_readdir(struct afp_volume * volume, const char *path, struct afp_file_info **base)=0; ++ virtual int afp_ml_readlink(struct afp_volume * vol, const char * path, char *buf, size_t size)=0; ++ virtual int afp_ml_mkdir(struct afp_volume * vol, const char * path, mode_t mode)=0; ++ virtual int afp_ml_rmdir(struct afp_volume * vol, const char *path)=0; ++ ++#else ++ virtual struct afp_server * afp_server_full_connect(void * priv, struct afp_connection_request * req)=0; ++ virtual int ml_open(struct afp_volume * volume, const char *path, int flags, struct afp_file_info **newfp)=0; ++ virtual int ml_close(struct afp_volume * volume, const char * path, struct afp_file_info * fp)=0; ++ virtual int ml_read(struct afp_volume * volume, const char *path, char *buf, size_t size, off_t offset, struct afp_file_info *fp, int * eof)=0; ++ virtual int ml_write(struct afp_volume * volume, const char * path, const char *data, size_t size, off_t offset, struct afp_file_info * fp, uid_t uid, gid_t gid)=0; ++ virtual int ml_getattr(struct afp_volume * volume, const char *path, struct stat *stbuf)=0; ++ virtual int ml_unlink(struct afp_volume * vol, const char *path)=0; ++ virtual int ml_rename(struct afp_volume * vol, const char * path_from, const char * path_to)=0; ++ virtual int ml_creat(struct afp_volume * volume, const char *path, mode_t mode)=0; ++ virtual int ml_readdir(struct afp_volume * volume, const char *path, struct afp_file_info **base)=0; ++ virtual int ml_readlink(struct afp_volume * vol, const char * path, char *buf, size_t size)=0; ++ virtual int ml_mkdir(struct afp_volume * vol, const char * path, mode_t mode)=0; ++ virtual int ml_rmdir(struct afp_volume * vol, const char *path)=0; ++ ++#endif ++ ++}; ++ ++class DllLibAfp : public DllDynamic, DllLibAfpInterface ++{ ++ DECLARE_DLL_WRAPPER(DllLibAfp, DLL_PATH_LIBAFP) ++ DEFINE_METHOD0(int, init_uams) ++ DEFINE_METHOD0(unsigned int, default_uams_mask) ++ DEFINE_METHOD0(char *, get_uam_names_list) ++ ++ DEFINE_METHOD1(void, libafpclient_register, (struct libafpclient *p1)) ++ DEFINE_METHOD1(int, afp_main_quick_startup, (pthread_t *p1)) ++ DEFINE_METHOD1(int, afp_unmount_all_volumes, (struct afp_server *p1)) ++ DEFINE_METHOD1(int, afp_unmount_volume, (struct afp_volume *p1)) ++ DEFINE_METHOD1(unsigned int, find_uam_by_name, (const char *p1)) ++ DEFINE_METHOD1(char *, uam_bitmap_to_string, (unsigned int p1)) ++ DEFINE_METHOD1(void, afp_default_url, (struct afp_url *p1)) ++ DEFINE_METHOD1(void, afp_ml_filebase_free, (struct afp_file_info **p1)) ++ ++#ifdef USE_CVS_AFPFS ++ DEFINE_METHOD3(struct afp_server *, afp_wrap_server_full_connect, (void *p1, struct afp_connection_request *p2, int *p3)) ++#else ++ DEFINE_METHOD2(struct afp_server *, afp_wrap_server_full_connect, (void *p1, struct afp_connection_request *p2)) ++#endif ++ ++ DEFINE_METHOD2(struct afp_volume *, find_volume_by_name, (struct afp_server *p1, const char *p2)) ++ DEFINE_METHOD2(int, afp_wrap_unlink, (struct afp_volume *p1, const char *p2)) ++ DEFINE_METHOD2(int, afp_wrap_rmdir, (struct afp_volume *p1, const char *p2)) ++ ++ DEFINE_METHOD3(int, afp_parse_url, (struct afp_url *p1, const char *p2, int p3)) ++ DEFINE_METHOD3(int, afp_wrap_close, (struct afp_volume *p1, const char *p2, struct afp_file_info *p3)) ++ DEFINE_METHOD3(int, afp_wrap_getattr, (struct afp_volume *p1, const char *p2, struct stat *p3)) ++ DEFINE_METHOD3(int, afp_wrap_rename, (struct afp_volume *p1, const char *p2, const char *p3)) ++ DEFINE_METHOD3(int, afp_wrap_creat, (struct afp_volume *p1, const char *p2, mode_t p3)) ++ DEFINE_METHOD3(int, afp_wrap_readdir, (struct afp_volume *p1, const char *p2, struct afp_file_info **p3)) ++ DEFINE_METHOD3(int, afp_wrap_mkdir, (struct afp_volume *p1, const char *p2, mode_t p3)) ++ ++ DEFINE_METHOD4(int, afp_wrap_open, (struct afp_volume *p1, const char *p2, int p3, struct afp_file_info **p4)) ++ DEFINE_METHOD4(int, afp_wrap_readlink, (struct afp_volume *p1, const char *p2, char *p3, size_t p4)) ++ ++ DEFINE_METHOD5(int, afp_connect_volume, (struct afp_volume *p1, struct afp_server *p2, char *p3, unsigned int *p4, unsigned int p5)) ++ ++ DEFINE_METHOD7(int, afp_wrap_read, (struct afp_volume *p1, const char *p2, char *p3, size_t p4, off_t p5, struct afp_file_info *p6, int *p7)) ++ ++ DEFINE_METHOD8(int, afp_wrap_write, (struct afp_volume *p1, const char *p2, const char *p3, size_t p4, off_t p5, struct afp_file_info *p6, uid_t p7, gid_t p8)) ++ ++ ++ ++ BEGIN_METHOD_RESOLVE() ++ RESOLVE_METHOD_RENAME(init_uams,init_uams) ++ RESOLVE_METHOD_RENAME(libafpclient_register, libafpclient_register) ++ RESOLVE_METHOD_RENAME(afp_main_quick_startup, afp_main_quick_startup) ++ RESOLVE_METHOD_RENAME(afp_unmount_all_volumes, afp_unmount_all_volumes) ++ RESOLVE_METHOD_RENAME(afp_unmount_all_volumes, afp_unmount_all_volumes) ++ RESOLVE_METHOD_RENAME(find_volume_by_name, find_volume_by_name) ++ RESOLVE_METHOD_RENAME(afp_connect_volume, afp_connect_volume) ++ RESOLVE_METHOD_RENAME(afp_parse_url, afp_parse_url) ++ RESOLVE_METHOD_RENAME(find_uam_by_name, find_uam_by_name) ++ RESOLVE_METHOD_RENAME(default_uams_mask, default_uams_mask) ++ RESOLVE_METHOD_RENAME(uam_bitmap_to_string, uam_bitmap_to_string) ++ RESOLVE_METHOD_RENAME(afp_default_url, afp_default_url) ++ RESOLVE_METHOD_RENAME(get_uam_names_list, get_uam_names_list) ++ RESOLVE_METHOD_RENAME(afp_ml_filebase_free, afp_ml_filebase_free) ++ ++#ifdef USE_CVS_AFPFS ++ RESOLVE_METHOD_RENAME(afp_server_full_connect, afp_server_full_connect) ++ RESOLVE_METHOD_RENAME(afp_ml_open, afp_ml_open) ++ RESOLVE_METHOD_RENAME(afp_ml_close, afp_ml_close) ++ RESOLVE_METHOD_RENAME(afp_ml_read, afp_ml_read) ++ RESOLVE_METHOD_RENAME(afp_ml_write, afp_ml_write) ++ RESOLVE_METHOD_RENAME(afp_ml_getattr, afp_ml_getattr) ++ RESOLVE_METHOD_RENAME(afp_ml_unlink, afp_ml_unlink) ++ RESOLVE_METHOD_RENAME(afp_ml_rename, afp_ml_rename) ++ RESOLVE_METHOD_RENAME(afp_ml_creat, afp_ml_creat) ++ RESOLVE_METHOD_RENAME(afp_ml_readdir, afp_ml_readdir) ++ RESOLVE_METHOD_RENAME(afp_ml_readlink, afp_ml_readlink) ++ RESOLVE_METHOD_RENAME(afp_ml_mkdir, afp_ml_mkdir) ++ RESOLVE_METHOD_RENAME(afp_ml_rmdir, afp_ml_rmdir) ++#else ++ RESOLVE_METHOD_RENAME(afp_server_full_connect, afp_server_full_connect) ++ RESOLVE_METHOD_RENAME(ml_open, ml_open) ++ RESOLVE_METHOD_RENAME(ml_close, ml_close) ++ RESOLVE_METHOD_RENAME(ml_read, ml_read) ++ RESOLVE_METHOD_RENAME(ml_write, ml_write) ++ RESOLVE_METHOD_RENAME(ml_getattr, ml_getattr) ++ RESOLVE_METHOD_RENAME(ml_unlink, ml_unlink) ++ RESOLVE_METHOD_RENAME(ml_rename, ml_rename) ++ RESOLVE_METHOD_RENAME(ml_creat, ml_creat) ++ RESOLVE_METHOD_RENAME(ml_readdir, ml_readdir) ++ RESOLVE_METHOD_RENAME(ml_readlink, ml_readlink) ++ RESOLVE_METHOD_RENAME(ml_mkdir, ml_mkdir) ++ RESOLVE_METHOD_RENAME(ml_rmdir, ml_rmdir) ++#endif ++ END_METHOD_RESOLVE() ++}; +diff --git a/xbmc/filesystem/FavouritesDirectory.cpp b/xbmc/filesystem/FavouritesDirectory.cpp +index 94a133e..bd83428 100644 +--- a/xbmc/filesystem/FavouritesDirectory.cpp ++++ b/xbmc/filesystem/FavouritesDirectory.cpp +@@ -190,7 +190,7 @@ std::string CFavouritesDirectory::GetExecutePath(const CFileItem &item, const st + if (!contextWindow.empty()) + execute = StringUtils::Format("ActivateWindow(%s,%s,return)", contextWindow.c_str(), StringUtils::Paramify(item.GetPath()).c_str()); + } +- //! @todo STRING_CLEANUP ++ /* TODO:STRING_CLEANUP */ + else if (item.IsScript() && item.GetPath().size() > 9) // plugin:// + execute = StringUtils::Format("RunScript(%s)", StringUtils::Paramify(item.GetPath().substr(9)).c_str()); + else if (item.IsAndroidApp() && item.GetPath().size() > 26) // androidapp://sources/apps/ +diff --git a/xbmc/filesystem/FileFactory.cpp b/xbmc/filesystem/FileFactory.cpp +index 6ba98d2..dc1044e 100644 +--- a/xbmc/filesystem/FileFactory.cpp ++++ b/xbmc/filesystem/FileFactory.cpp +@@ -32,6 +32,7 @@ + #include "CurlFile.h" + #include "DAVFile.h" + #include "ShoutcastFile.h" ++#include "FileReaderFile.h" + #ifdef HAS_FILESYSTEM_SMB + #ifdef TARGET_WINDOWS + #include "win32/Win32SMBFile.h" +@@ -59,6 +60,9 @@ + #ifdef HAS_FILESYSTEM_NFS + #include "NFSFile.h" + #endif ++#ifdef HAS_FILESYSTEM_AFP ++#include "AFPFile.h" ++#endif + #if defined(TARGET_ANDROID) + #include "AndroidAppFile.h" + #endif +@@ -124,6 +128,7 @@ IFile* CFileFactory::CreateLoader(const CURL& url) + #elif defined(TARGET_WINDOWS) + else if (url.IsProtocol("file") || url.GetProtocol().empty()) return new CWin32File(); + #endif // TARGET_WINDOWS ++ else if (url.IsProtocol("filereader")) return new CFileReaderFile(); + #if defined(HAS_FILESYSTEM_CDDA) && defined(HAS_DVD_DRIVE) + else if (url.IsProtocol("cdda")) return new CFileCDDA(); + #endif +@@ -140,7 +145,7 @@ IFile* CFileFactory::CreateLoader(const CURL& url) + #endif + else if (url.IsProtocol("resource")) return new CResourceFile(); + +- bool networkAvailable = g_application.getNetwork().IsAvailable(); ++ bool networkAvailable = g_application.getNetwork().IsConnected(); + if (networkAvailable) + { + if (url.IsProtocol("ftp") +@@ -163,6 +168,9 @@ IFile* CFileFactory::CreateLoader(const CURL& url) + #ifdef HAS_FILESYSTEM_NFS + else if (url.IsProtocol("nfs")) return new CNFSFile(); + #endif ++#ifdef HAS_FILESYSTEM_AFP ++ else if (url.IsProtocol("afp")) return new CAFPFile(); ++#endif + #ifdef HAS_UPNP + else if (url.IsProtocol("upnp")) return new CUPnPFile(); + #endif +diff --git a/xbmc/filesystem/FileReaderFile.cpp b/xbmc/filesystem/FileReaderFile.cpp +new file mode 100644 +index 0000000..4e6c08c +--- /dev/null ++++ b/xbmc/filesystem/FileReaderFile.cpp +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (c) 2002 Frodo ++ * Portions Copyright (c) by the authors of ffmpeg and xvid ++ * Copyright (C) 2002-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "FileReaderFile.h" ++#include "URL.h" ++ ++using namespace XFILE; ++ ++////////////////////////////////////////////////////////////////////// ++// Construction/Destruction ++////////////////////////////////////////////////////////////////////// ++ ++//********************************************************************************************* ++CFileReaderFile::CFileReaderFile() ++{ ++} ++ ++//********************************************************************************************* ++CFileReaderFile::~CFileReaderFile() ++{ ++ Close(); ++} ++ ++//********************************************************************************************* ++bool CFileReaderFile::Open(const CURL& url) ++{ ++ // URL is of the form filereader:// ++ std::string strURL = url.Get(); ++ strURL = strURL.substr(13); ++ return m_reader.Open(strURL,READ_CACHED); ++} ++ ++bool CFileReaderFile::Exists(const CURL& url) ++{ ++ return CFile::Exists(url.Get().substr(13)); ++} ++ ++int CFileReaderFile::Stat(const CURL& url, struct __stat64* buffer) ++{ ++ return CFile::Stat(url.Get().substr(13), buffer); ++} ++ ++ ++//********************************************************************************************* ++bool CFileReaderFile::OpenForWrite(const CURL& url, bool bOverWrite) ++{ ++ return false; ++} ++ ++//********************************************************************************************* ++ssize_t CFileReaderFile::Read(void *lpBuf, size_t uiBufSize) ++{ ++ return m_reader.Read(lpBuf,uiBufSize); ++} ++ ++//********************************************************************************************* ++ssize_t CFileReaderFile::Write(const void *lpBuf, size_t uiBufSize) ++{ ++ return -1; ++} ++ ++//********************************************************************************************* ++void CFileReaderFile::Close() ++{ ++ m_reader.Close(); ++} ++ ++//********************************************************************************************* ++int64_t CFileReaderFile::Seek(int64_t iFilePosition, int iWhence) ++{ ++ return m_reader.Seek(iFilePosition,iWhence); ++} ++ ++//********************************************************************************************* ++int64_t CFileReaderFile::GetLength() ++{ ++ return m_reader.GetLength(); ++} ++ ++//********************************************************************************************* ++int64_t CFileReaderFile::GetPosition() ++{ ++ return m_reader.GetPosition(); ++} ++ ++ +diff --git a/xbmc/filesystem/FileReaderFile.h b/xbmc/filesystem/FileReaderFile.h +new file mode 100644 +index 0000000..2e6e89b +--- /dev/null ++++ b/xbmc/filesystem/FileReaderFile.h +@@ -0,0 +1,51 @@ ++#pragma once ++/* ++ * Copyright (c) 2002 Frodo ++ * Portions Copyright (c) by the authors of ffmpeg and xvid ++ * Copyright (C) 2002-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "File.h" ++#include "IFile.h" ++ ++namespace XFILE ++{ ++class CFileReaderFile : public IFile ++{ ++public: ++ CFileReaderFile(); ++ virtual ~CFileReaderFile(); ++ virtual int64_t GetPosition(); ++ virtual int64_t GetLength(); ++ virtual bool Open(const CURL& url); ++ virtual bool Exists(const CURL& url); ++ virtual int Stat(const CURL& url, struct __stat64* buffer); ++ virtual ssize_t Read(void* lpBuf, size_t uiBufSize); ++ virtual ssize_t Write(const void* lpBuf, size_t uiBufSize); ++ virtual int64_t Seek(int64_t iFilePosition, int iWhence = SEEK_SET); ++ virtual void Close(); ++ ++ virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false); ++ protected: ++ CFile m_reader; ++}; ++ ++} ++ ++ +diff --git a/xbmc/filesystem/Makefile.in b/xbmc/filesystem/Makefile.in +index 14fb7b7..6381452 100644 +--- a/xbmc/filesystem/Makefile.in ++++ b/xbmc/filesystem/Makefile.in +@@ -20,6 +20,7 @@ SRCS += File.cpp + SRCS += FileCache.cpp + SRCS += FileDirectoryFactory.cpp + SRCS += FileFactory.cpp ++SRCS += FileReaderFile.cpp + SRCS += FTPDirectory.cpp + SRCS += FTPParse.cpp + SRCS += HTTPDirectory.cpp +@@ -94,6 +95,11 @@ SRCS += NFSFile.cpp + SRCS += NFSDirectory.cpp + endif + ++ifeq (@USE_LIBAFPCLIENT@,1) ++SRCS += AFPFile.cpp ++SRCS += AFPDirectory.cpp ++endif ++ + ifeq (@HAVE_LIBBLURAY@,1) + SRCS += BlurayDirectory.cpp + SRCS += BlurayFile.cpp +diff --git a/xbmc/filesystem/MultiPathDirectory.h b/xbmc/filesystem/MultiPathDirectory.h +index 68e2586..481c2f8 100644 +--- a/xbmc/filesystem/MultiPathDirectory.h ++++ b/xbmc/filesystem/MultiPathDirectory.h +@@ -21,8 +21,6 @@ + + #include + #include +-#include +- + #include "IDirectory.h" + + namespace XFILE +diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp +index c15fa65..1666a3e 100644 +--- a/xbmc/filesystem/NFSFile.cpp ++++ b/xbmc/filesystem/NFSFile.cpp +@@ -326,8 +326,8 @@ bool CNfsConnection::Connect(const CURL& url, std::string &relativePath) + m_exportPath = exportPath; + m_hostName = url.GetHostName(); + //read chunksize only works after mount +- m_readChunkSize = m_pLibNfs->nfs_get_readmax(m_pNfsContext); +- m_writeChunkSize = m_pLibNfs->nfs_get_writemax(m_pNfsContext); ++ m_readChunkSize = 262144; /*m_pLibNfs->nfs_get_readmax(m_pNfsContext);*/ ++ m_writeChunkSize = 262144; /*m_pLibNfs->nfs_get_writemax(m_pNfsContext);*/ + + if(contextRet == CONTEXT_NEW) + { +@@ -613,7 +613,7 @@ int CNFSFile::Stat(const CURL& url, struct __stat64* buffer) + { + if(buffer) + { +-#if defined(TARGET_WINDOWS)//! @todo get rid of this define after gotham v13 ++#if defined(TARGET_WINDOWS)// TODO get rid of this define after gotham + memcpy(buffer, &tmpBuffer, sizeof(struct __stat64)); + #else + memset(buffer, 0, sizeof(struct __stat64)); +diff --git a/xbmc/filesystem/PipeFile.h b/xbmc/filesystem/PipeFile.h +index ae307eb..62c945d 100644 +--- a/xbmc/filesystem/PipeFile.h ++++ b/xbmc/filesystem/PipeFile.h +@@ -28,8 +28,6 @@ + #define AFX_FILEPIPE_H__DD2B0A9E_4971_4A29_B525_78CEFCDAF4A1__INCLUDED_ + + #pragma once +-#include +-#include + + #include "IFile.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp +index bcadd68..78de661 100644 +--- a/xbmc/filesystem/PluginDirectory.cpp ++++ b/xbmc/filesystem/PluginDirectory.cpp +@@ -245,7 +245,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const s + if (!dir) + return; + +- //! @todo Add all sort methods and fix which labels go on the right or left ++ // TODO: Add all sort methods and fix which labels go on the right or left + switch(sortMethod) + { + case SORT_METHOD_LABEL: +diff --git a/xbmc/filesystem/RSSDirectory.cpp b/xbmc/filesystem/RSSDirectory.cpp +index 3d9477e..df48f4b 100644 +--- a/xbmc/filesystem/RSSDirectory.cpp ++++ b/xbmc/filesystem/RSSDirectory.cpp +@@ -106,7 +106,7 @@ static bool IsPathToThumbnail(const std::string& strPath ) + static time_t ParseDate(const std::string & strDate) + { + struct tm pubDate = {0}; +- //! @todo Handle time zone ++ // TODO: Handle time zone + strptime(strDate.c_str(), "%a, %d %b %Y %H:%M:%S", &pubDate); + // Check the difference between the time of last check and time of the item + return mktime(&pubDate); +@@ -326,7 +326,7 @@ static void ParseItemVoddler(CFileItem* item, SResources& resources, TiXmlElemen + resources.push_back(res); + } + else if(name == "year") +- vtag->SetYear(atoi(text.c_str())); ++ vtag->m_iYear = atoi(text.c_str()); + else if(name == "rating") + vtag->SetRating((float)atof(text.c_str())); + else if(name == "tagline") +diff --git a/xbmc/filesystem/RarManager.cpp b/xbmc/filesystem/RarManager.cpp +index f3a5622..94e2b9c 100644 +--- a/xbmc/filesystem/RarManager.cpp ++++ b/xbmc/filesystem/RarManager.cpp +@@ -49,10 +49,15 @@ + using namespace XFILE; + + CFileInfo::CFileInfo() +- : m_bAutoDel{true} +- , m_iUsed{0} +- , m_iOffset{0} +- , m_iIsSeekable{-1} ++{ ++ m_strCachedPath.clear(); ++ m_bAutoDel = true; ++ m_iUsed = 0; ++ m_iIsSeekable = -1; ++ m_iOffset = 0; ++} ++ ++CFileInfo::~CFileInfo() + { + } + +@@ -205,10 +210,8 @@ bool CRarManager::CacheRarredFile(std::string& strPathInCache, const std::string + StringUtils::Replace(strPath, '/', '\\'); + #endif + //g_charsetConverter.unknownToUTF8(strPath); +- std::string strCachedPath = URIUtils::AddFileToFolder( +- URIUtils::AddFileToFolder( +- CSpecialProtocol::TranslatePath(strDir), "rarfolder%04d"), +- URIUtils::GetFileName(strPathInRar)); ++ std::string strCachedPath = URIUtils::AddFileToFolder(strDir + "rarfolder%04d", ++ URIUtils::GetFileName(strPathInRar)); + strCachedPath = CUtil::GetNextPathname(strCachedPath, 9999); + if (strCachedPath.empty()) + { +diff --git a/xbmc/filesystem/RarManager.h b/xbmc/filesystem/RarManager.h +index c7f557d..ca1eb69 100644 +--- a/xbmc/filesystem/RarManager.h ++++ b/xbmc/filesystem/RarManager.h +@@ -41,7 +41,7 @@ class CFileItemList; + class CFileInfo{ + public: + CFileInfo(); +- ~CFileInfo() = default; ++ ~CFileInfo(); + std::string m_strCachedPath; + std::string m_strPathInRar; + bool m_bAutoDel; +diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp +index d633840..1f7af9b 100644 +--- a/xbmc/filesystem/SMBFile.cpp ++++ b/xbmc/filesystem/SMBFile.cpp +@@ -390,13 +390,13 @@ int CSMBFile::OpenFile(std::string& strAuth) + std::string strPath = g_passwordManager.GetSMBAuthFilename(strAuth); + + fd = smbc_open(strPath.c_str(), O_RDONLY, 0); +- //! @todo Run a loop here that prompts for our username/password as appropriate? +- //! We have the ability to run a file (eg from a button action) without browsing to +- //! the directory first. In the case of a password protected share that we do +- //! not have the authentication information for, the above smbc_open() will have +- //! returned negative, and the file will not be opened. While this is not a particular +- //! likely scenario, we might want to implement prompting for the password in this case. +- //! The code from SMBDirectory can be used for this. ++ // TODO: Run a loop here that prompts for our username/password as appropriate? ++ // We have the ability to run a file (eg from a button action) without browsing to ++ // the directory first. In the case of a password protected share that we do ++ // not have the authentication information for, the above smbc_open() will have ++ // returned negative, and the file will not be opened. While this is not a particular ++ // likely scenario, we might want to implement prompting for the password in this case. ++ // The code from SMBDirectory can be used for this. + if(fd >= 0) + strAuth = strPath; + +diff --git a/xbmc/filesystem/SourcesDirectory.h b/xbmc/filesystem/SourcesDirectory.h +index a5c6780..3d6dc2d 100644 +--- a/xbmc/filesystem/SourcesDirectory.h ++++ b/xbmc/filesystem/SourcesDirectory.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "IDirectory.h" + + class CMediaSource; +diff --git a/xbmc/filesystem/StackDirectory.h b/xbmc/filesystem/StackDirectory.h +index ee3236c..e3697f5 100644 +--- a/xbmc/filesystem/StackDirectory.h ++++ b/xbmc/filesystem/StackDirectory.h +@@ -22,7 +22,6 @@ + #include "IDirectory.h" + #include "utils/RegExp.h" + #include +-#include + + namespace XFILE + { +diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp +index 0c588d5..cd8430c 100644 +--- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp ++++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp +@@ -39,6 +39,7 @@ + #include "URL.h" + #include "FileItem.h" + #include "utils/StringUtils.h" ++#include "video/VideoDatabase.h" + + using namespace XFILE::VIDEODATABASEDIRECTORY; + +diff --git a/xbmc/filesystem/VirtualDirectory.cpp b/xbmc/filesystem/VirtualDirectory.cpp +index 99e8eb3..1e1c369 100644 +--- a/xbmc/filesystem/VirtualDirectory.cpp ++++ b/xbmc/filesystem/VirtualDirectory.cpp +@@ -155,7 +155,7 @@ bool CVirtualDirectory::IsInSource(const std::string &path) const + } + return false; + } +- //! @todo May need to handle other special cases that GetMatchingSource() fails on ++ // TODO: May need to handle other special cases that GetMatchingSource() fails on + return (iShare > -1); + } + +diff --git a/xbmc/filesystem/XbtFile.cpp b/xbmc/filesystem/XbtFile.cpp +index 87b3cad..7839276 100644 +--- a/xbmc/filesystem/XbtFile.cpp ++++ b/xbmc/filesystem/XbtFile.cpp +@@ -22,11 +22,7 @@ + #include + + #ifdef TARGET_WINDOWS +-#ifdef NDEBUG +-#pragma comment(lib,"lzo2.lib") +-#else +-#pragma comment(lib, "lzo2-no_idb.lib") +-#endif ++#pragma comment(lib,"liblzo2.lib") + #endif + + #include +diff --git a/xbmc/filesystem/XbtFile.h b/xbmc/filesystem/XbtFile.h +index 116c6f2..05ab78a 100644 +--- a/xbmc/filesystem/XbtFile.h ++++ b/xbmc/filesystem/XbtFile.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "IFile.h" + #include "URL.h" + #include "guilib/XBTF.h" +diff --git a/xbmc/filesystem/XbtManager.h b/xbmc/filesystem/XbtManager.h +index 8932c06..0e15889 100644 +--- a/xbmc/filesystem/XbtManager.h ++++ b/xbmc/filesystem/XbtManager.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + + #include "guilib/XBTFReader.h" + +diff --git a/xbmc/filesystem/ZeroconfDirectory.cpp b/xbmc/filesystem/ZeroconfDirectory.cpp +index 264f0b7..1f3159a 100644 +--- a/xbmc/filesystem/ZeroconfDirectory.cpp ++++ b/xbmc/filesystem/ZeroconfDirectory.cpp +@@ -52,6 +52,8 @@ namespace + return "WebDAV"; + else if(fcr_service_type == "_nfs._tcp.") + return "NFS"; ++ else if(fcr_service_type == "_afpovertcp._tcp.") ++ return "AFP"; + else if(fcr_service_type == "_sftp-ssh._tcp.") + return "SFTP"; + //fallback, just return the received type +@@ -67,6 +69,8 @@ namespace + fr_protocol = "dav"; + else if(fcr_service_type == "_nfs._tcp.") + fr_protocol = "nfs"; ++ else if(fcr_service_type == "_afpovertcp._tcp.") ++ fr_protocol = "afp"; + else if(fcr_service_type == "_sftp-ssh._tcp.") + fr_protocol = "sftp"; + else +@@ -211,7 +215,7 @@ bool CZeroconfDirectory::GetDirectory(const CURL& url, CFileItemList &items) + service.SetPort(zeroconf_service.GetPort()); + service.SetHostName(zeroconf_service.GetIP()); + //do protocol conversion (_smb._tcp -> smb) +- //! @todo try automatic conversion -> remove leading '_' and '._tcp'? ++ //ToDo: try automatic conversion -> remove leading '_' and '._tcp'? + std::string protocol; + if(!GetXBMCProtocol(zeroconf_service.GetType(), protocol)) + { +diff --git a/xbmc/filesystem/posix/PosixFile.cpp b/xbmc/filesystem/posix/PosixFile.cpp +index a7fbe76..11a3d57 100644 +--- a/xbmc/filesystem/posix/PosixFile.cpp ++++ b/xbmc/filesystem/posix/PosixFile.cpp +@@ -183,8 +183,8 @@ int64_t CPosixFile::Seek(int64_t iFilePosition, int iWhence /* = SEEK_SET*/) + return -1; + + #ifdef TARGET_ANDROID +- //! @todo properly support with detection in configure +- //! Android special case: Android doesn't substitute off64_t for off_t and similar functions ++ // TODO: properly support with detection in configure ++ // Android special case: Android doesn't substitute off64_t for off_t and similar functions + m_filePos = lseek64(m_fd, (off64_t)iFilePosition, iWhence); + #else // !TARGET_ANDROID + const off_t filePosOffT = (off_t) iFilePosition; +diff --git a/xbmc/filesystem/test/TestRarFile.cpp b/xbmc/filesystem/test/TestRarFile.cpp +index 70cf7ae..2ea62cf 100644 +--- a/xbmc/filesystem/test/TestRarFile.cpp ++++ b/xbmc/filesystem/test/TestRarFile.cpp +@@ -22,7 +22,6 @@ + #ifdef HAS_FILESYSTEM_RAR + #include "filesystem/Directory.h" + #include "filesystem/File.h" +-#include "filesystem/RarManager.h" + #include "URL.h" + #include "utils/URIUtils.h" + #include "FileItem.h" +@@ -87,8 +86,6 @@ TEST(TestRarFile, Read) + EXPECT_TRUE(!memcmp("About\n-----\nXBMC is ", buf, sizeof(buf) - 1)); + EXPECT_EQ(0, file.Seek(0, SEEK_SET)); + EXPECT_EQ(-1, file.Seek(-100, SEEK_SET)); +- // Manual clear to avoid shutdown race +- g_RarManager.ClearCache(); + file.Close(); + } + +@@ -104,9 +101,6 @@ TEST(TestRarFile, Exists) + strpathinrar = itemlist[0]->GetPath(); + + EXPECT_TRUE(XFILE::CFile::Exists(strpathinrar)); +- +- // Manual clear to avoid shutdown race +- g_RarManager.ClearCache(); + } + + TEST(TestRarFile, Stat) +@@ -123,9 +117,6 @@ TEST(TestRarFile, Stat) + + EXPECT_EQ(0, XFILE::CFile::Stat(strpathinrar, &buffer)); + EXPECT_TRUE(buffer.st_mode | _S_IFREG); +- +- // Manual clear to avoid shutdown race +- g_RarManager.ClearCache(); + } + + /* Test case to test for graceful handling of corrupted input. +@@ -201,9 +192,6 @@ TEST(TestRarFile, CorruptedFile) + } + file->Close(); + XBMC_DELETETEMPFILE(file); +- +- // Manual clear to avoid shutdown race +- g_RarManager.ClearCache(); + } + + TEST(TestRarFile, StoredRAR) +@@ -352,12 +340,12 @@ TEST(TestRarFile, StoredRAR) + /* /testdir/testemptysubdir */ + strpathinrar = itemlist[2]->GetPath(); + ASSERT_TRUE(StringUtils::EndsWith(strpathinrar, "/testdir/testemptysubdir")); +- //! @todo Should this set the itemlist to an empty list instead? ++ /* TODO: Should this set the itemlist to an empty list instead? */ + EXPECT_FALSE(XFILE::CDirectory::GetDirectory(strpathinrar, itemlistemptydir)); + EXPECT_EQ(0, XFILE::CFile::Stat(strpathinrar, &stat_buffer)); + EXPECT_TRUE((stat_buffer.st_mode & S_IFMT) | S_IFDIR); + +- //! @todo FIXME: This directory appears a second time as a file ++ /* FIXME: This directory appears a second time as a file */ + strpathinrar = itemlist[3]->GetPath(); + ASSERT_TRUE(StringUtils::EndsWith(strpathinrar, "/testdir/testsubdir")); + +@@ -570,7 +558,7 @@ TEST(TestRarFile, NormalRAR) + /* /testdir/testemptysubdir */ + strpathinrar = itemlist[2]->GetPath(); + ASSERT_TRUE(StringUtils::EndsWith(strpathinrar, "/testdir/testemptysubdir")); +- /* @todo Should this set the itemlist to an empty list instead? */ ++ /* TODO: Should this set the itemlist to an empty list instead? */ + EXPECT_FALSE(XFILE::CDirectory::GetDirectory(strpathinrar, itemlistemptydir)); + EXPECT_EQ(0, XFILE::CFile::Stat(strpathinrar, &stat_buffer)); + EXPECT_TRUE((stat_buffer.st_mode & S_IFMT) | S_IFDIR); +@@ -644,8 +632,5 @@ TEST(TestRarFile, NormalRAR) + EXPECT_EQ(0, file.Seek(0, SEEK_SET)); + EXPECT_EQ(-1, file.Seek(-100, SEEK_SET)); + file.Close(); +- +- // Manual clear to avoid shutdown race +- g_RarManager.ClearCache(); + } + #endif /*HAS_FILESYSTEM_RAR*/ +diff --git a/xbmc/filesystem/test/TestZipFile.cpp b/xbmc/filesystem/test/TestZipFile.cpp +index 1497f1a..65004b8 100644 +--- a/xbmc/filesystem/test/TestZipFile.cpp ++++ b/xbmc/filesystem/test/TestZipFile.cpp +@@ -39,8 +39,7 @@ protected: + /* Add default settings for locale. + * Settings here are taken from CGUISettings::Initialize() + */ +- //! @todo implement +- /* ++ /* TODO + CSettingsCategory *loc = CSettings::GetInstance().AddCategory(7, "locale", 14090); + CSettings::GetInstance().AddString(loc, CSettings::SETTING_LOCALE_LANGUAGE,248,"english", + SPIN_CONTROL_TEXT); +diff --git a/xbmc/filesystem/udf25.cpp b/xbmc/filesystem/udf25.cpp +index 76ccb97..7917756 100644 +--- a/xbmc/filesystem/udf25.cpp ++++ b/xbmc/filesystem/udf25.cpp +@@ -315,7 +315,7 @@ static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, + static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) + { + *TagID = GETN2(0); +- //! @todo check CRC 'n stuff ++ /* TODO: check CRC 'n stuff */ + return 0; + } + +@@ -654,7 +654,7 @@ int udf25::UDFGetAVDP( struct avdp_t *avdp) + lbnum = lastsector; + terminate = 1; + } else { +- //! @todo Find last sector of the disc (this is optional). ++ /* TODO: Find last sector of the disc (this is optional). */ + if( lastsector ) + /* Try #2, backup anchor */ + lbnum = lastsector - 256; +@@ -720,7 +720,7 @@ int udf25::UDFFindPartition( int partnum, struct Partition *part ) + } else if( ( TagID == 6 ) && ( !volvalid ) ) { + /* Logical Volume Descriptor */ + if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { +- //! @todo sector size wrong! ++ /* TODO: sector size wrong! */ + } else + volvalid = 1; + } +diff --git a/xbmc/filesystem/win32/Win32Directory.cpp b/xbmc/filesystem/win32/Win32Directory.cpp +index 41abde4..408d402 100644 +--- a/xbmc/filesystem/win32/Win32Directory.cpp ++++ b/xbmc/filesystem/win32/Win32Directory.cpp +@@ -69,7 +69,7 @@ bool CWin32Directory::GetDirectory(const CURL& url, CFileItemList &items) + if (searchMask.empty()) + return false; + +- //! @todo support m_strFileMask, require rewrite of internal caching ++ // TODO: support m_strFileMask, require rewrite of internal caching + searchMask += L'*'; + + HANDLE hSearch; +diff --git a/xbmc/filesystem/win32/Win32File.cpp b/xbmc/filesystem/win32/Win32File.cpp +index 645b1b9..a210eab 100644 +--- a/xbmc/filesystem/win32/Win32File.cpp ++++ b/xbmc/filesystem/win32/Win32File.cpp +@@ -393,7 +393,7 @@ bool CWin32File::Rename(const CURL& urlCurrentName, const CURL& urlNewName) + if (m_smbFile) + m_lastSMBFileErr = ERROR_INVALID_DATA; // used to indicate internal errors, cleared by successful file operation + +- //! @todo check whether it's file or directory ++ // TODO: check whether it's file or directory + std::wstring curNameW(CWIN32Util::ConvertPathToWin32Form(urlCurrentName)); + if (curNameW.empty()) + return false; +diff --git a/xbmc/filesystem/win32/Win32SMBDirectory.cpp b/xbmc/filesystem/win32/Win32SMBDirectory.cpp +index ad594a8..ed8cecd 100644 +--- a/xbmc/filesystem/win32/Win32SMBDirectory.cpp ++++ b/xbmc/filesystem/win32/Win32SMBDirectory.cpp +@@ -111,7 +111,7 @@ bool CWin32SMBDirectory::GetDirectory(const CURL& url, CFileItemList &items) + if (searchMask.empty()) + return false; + +- //! @todo support m_strFileMask, require rewrite of internal caching ++ // TODO: support m_strFileMask, require rewrite of internal caching + if (searchMask.back() == '\\') + searchMask += L'*'; + else +@@ -263,7 +263,7 @@ bool CWin32SMBDirectory::RealExists(const CURL& url, bool tryToConnect) + if (url.GetHostName().empty()) + return true; // 'root' of network is always exist + +- //! @todo use real caseless string comparison everywhere in this function ++ // TODO: use real caseless string comparison everywhere in this function + if (url.GetShareName().empty() || url.GetShareName() == url.GetFileName()) + { + if (!url.GetShareName().empty()) +diff --git a/xbmc/games/controllers/ControllerLayout.cpp b/xbmc/games/controllers/ControllerLayout.cpp +index 34234fd..0384eb0 100644 +--- a/xbmc/games/controllers/ControllerLayout.cpp ++++ b/xbmc/games/controllers/ControllerLayout.cpp +@@ -104,7 +104,7 @@ bool CControllerLayout::Deserialize(const TiXmlElement* pElement, const CControl + { + std::string strCategory = pElement->Value(); + +- //! @todo Something with category ++ // TODO: Something with category + + for (const TiXmlElement* pFeature = pCategory->FirstChildElement(); pFeature != NULL; pFeature = pFeature->NextSiblingElement()) + { +diff --git a/xbmc/games/controllers/guicontrols/GUIGameController.cpp b/xbmc/games/controllers/guicontrols/GUIGameController.cpp +index 84e63de..569a300 100644 +--- a/xbmc/games/controllers/guicontrols/GUIGameController.cpp ++++ b/xbmc/games/controllers/guicontrols/GUIGameController.cpp +@@ -52,7 +52,7 @@ void CGUIGameController::Render(void) + + if (m_currentController) + { +- //! @todo Render pressed buttons ++ // TODO: Render pressed buttons + } + } + +@@ -66,7 +66,7 @@ void CGUIGameController::ActivateController(const ControllerPtr& controller) + + lock.Leave(); + +- //! @todo Sometimes this fails on window init ++ // TODO: Sometimes this fails on window init + SetFileName(m_currentController->ImagePath()); + } + } +diff --git a/xbmc/games/controllers/windows/GUIControllerList.cpp b/xbmc/games/controllers/windows/GUIControllerList.cpp +index 3a088a6..48132fb 100644 +--- a/xbmc/games/controllers/windows/GUIControllerList.cpp ++++ b/xbmc/games/controllers/windows/GUIControllerList.cpp +@@ -20,7 +20,6 @@ + + #include "GUIControllerList.h" + +-#include + #include + #include + +@@ -35,9 +34,7 @@ + #include "guilib/GUIButtonControl.h" + #include "guilib/GUIControlGroupList.h" + #include "guilib/GUIWindow.h" +-#include "guilib/WindowIDs.h" + #include "input/joysticks/DefaultJoystick.h" // for DEFAULT_CONTROLLER_ID +-#include "messaging/ApplicationMessenger.h" + #include "peripherals/Peripherals.h" + + using namespace ADDON; +@@ -79,13 +76,13 @@ void CGUIControllerList::Deinitialize(void) + m_controllerButton = nullptr; + } + +-bool CGUIControllerList::Refresh(void) ++void CGUIControllerList::Refresh(void) + { +- if (!RefreshControllers()) +- return false; +- + CleanupButtons(); + ++ if (!RefreshControllers()) ++ return; ++ + if (m_controllerList) + { + unsigned int buttonId = 0; +@@ -101,8 +98,6 @@ bool CGUIControllerList::Refresh(void) + break; + } + } +- +- return true; + } + + void CGUIControllerList::OnFocus(unsigned int controllerIndex) +@@ -114,7 +109,7 @@ void CGUIControllerList::OnFocus(unsigned int controllerIndex) + const ControllerPtr& controller = m_controllers[controllerIndex]; + m_featureList->Load(controller); + +- //! @todo Activate controller for all game controller controls ++ // TODO: Activate controller for all game controller controls + CGUIGameController* pController = dynamic_cast(m_guiWindow->GetControl(CONTROL_GAME_CONTROLLER)); + if (pController) + pController->ActivateController(controller); +@@ -123,7 +118,10 @@ void CGUIControllerList::OnFocus(unsigned int controllerIndex) + + void CGUIControllerList::OnSelect(unsigned int controllerIndex) + { +- m_featureList->OnSelect(0); ++ if (controllerIndex < m_controllers.size()) ++ { ++ // TODO ++ } + } + + void CGUIControllerList::ResetController(void) +@@ -132,7 +130,7 @@ void CGUIControllerList::ResetController(void) + { + const std::string strControllerId = m_controllers[m_focusedController]->ID(); + +- //! @todo Choose peripheral ++ // TODO: Choose peripheral + // For now, ask the user if they would like to reset all peripherals + // "Reset controller profile" + // "Would you like to reset this controller profile for all devices?" +@@ -145,41 +143,75 @@ void CGUIControllerList::ResetController(void) + + void CGUIControllerList::Notify(const Observable& obs, const ObservableMessage msg) + { +- using namespace KODI::MESSAGING; +- + if (msg == ObservableMessageAddons) +- { +- CGUIMessage msg(GUI_MSG_REFRESH_LIST, m_guiWindow->GetID(), CONTROL_CONTROLLER_LIST); +- CApplicationMessenger::GetInstance().SendGUIMessage(msg); +- } ++ Refresh(); + } + + bool CGUIControllerList::RefreshControllers(void) + { +- // Cache discovered add-ons between function calls +- VECADDONS addonCache; ++ bool bChanged = false; + +- std::set currentIds = GetControllerIDs(); +- std::set newIds = GetNewControllerIDs(addonCache); ++ // Get controller add-ons ++ ADDON::VECADDONS addons; ++ CAddonMgr::GetInstance().GetAddons(addons, ADDON_GAME_CONTROLLER); + +- std::set added; +- std::set removed; ++ // Convert to controllers ++ ControllerVector controllers; ++ std::transform(addons.begin(), addons.end(), std::back_inserter(controllers), ++ [](const AddonPtr& addon) ++ { ++ return std::static_pointer_cast(addon); ++ }); + +- std::set_difference(newIds.begin(), newIds.end(), currentIds.begin(), currentIds.end(), std::inserter(added, added.end())); +- std::set_difference(currentIds.begin(), currentIds.end(), newIds.begin(), newIds.end(), std::inserter(removed, removed.end())); ++ // Look for new controllers ++ ControllerVector newControllers; ++ for (ControllerVector::const_iterator it = controllers.begin(); it != controllers.end(); ++it) ++ { ++ const ControllerPtr& controller = *it; + +- // Register new controllers +- for (const std::string& addonId : added) +- RegisterController(addonId, addonCache); ++ if (std::find_if(m_controllers.begin(), m_controllers.end(), ++ [controller](const ControllerPtr& ctrl) ++ { ++ return ctrl->ID() == controller->ID(); ++ }) == m_controllers.end()) ++ { ++ newControllers.push_back(controller); ++ } ++ } + +- // Erase removed controllers +- for (const std::string& addonId : removed) +- UnregisterController(addonId); ++ // Remove old controllers ++ for (ControllerVector::iterator it = m_controllers.begin(); it != m_controllers.end(); /* ++it */) ++ { ++ ControllerPtr& controller = *it; + ++ if (std::find_if(controllers.begin(), controllers.end(), ++ [controller](const ControllerPtr& ctrl) ++ { ++ return ctrl->ID() == controller->ID(); ++ }) == controllers.end()) ++ { ++ it = m_controllers.erase(it); // Not found, remove it ++ bChanged = true; ++ } ++ else ++ { ++ ++it; ++ } ++ } + ++ // Add new controllers ++ for (ControllerVector::iterator it = newControllers.begin(); it != newControllers.end(); ++it) ++ { ++ ControllerPtr& newController = *it; ++ ++ if (newController->LoadLayout()) ++ { ++ m_controllers.push_back(newController); ++ bChanged = true; ++ } ++ } + + // Sort add-ons, with default controller first +- const bool bChanged = !added.empty() || !removed.empty(); + if (bChanged) + { + std::sort(m_controllers.begin(), m_controllers.end(), +@@ -188,66 +220,13 @@ bool CGUIControllerList::RefreshControllers(void) + if (i->ID() == DEFAULT_CONTROLLER_ID && j->ID() != DEFAULT_CONTROLLER_ID) return true; + if (i->ID() != DEFAULT_CONTROLLER_ID && j->ID() == DEFAULT_CONTROLLER_ID) return false; + +- return i->Name() < j->Name(); ++ return i->ID() < j->ID(); + }); + } + + return bChanged; + } + +-std::set CGUIControllerList::GetControllerIDs() const +-{ +- std::set controllerIds; +- +- std::transform(m_controllers.begin(), m_controllers.end(), std::inserter(controllerIds, controllerIds.end()), +- [](const ControllerPtr& addon) +- { +- return addon->ID(); +- }); +- +- return controllerIds; +-} +- +-std::set CGUIControllerList::GetNewControllerIDs(ADDON::VECADDONS& addonCache) const +-{ +- std::set controllerIds; +- +- CAddonMgr::GetInstance().GetAddons(addonCache, ADDON_GAME_CONTROLLER); +- +- std::transform(addonCache.begin(), addonCache.end(), std::inserter(controllerIds, controllerIds.end()), +- [](const AddonPtr& addon) +- { +- return addon->ID(); +- }); +- +- return controllerIds; +-} +- +-void CGUIControllerList::RegisterController(const std::string& addonId, const ADDON::VECADDONS& addonCache) +-{ +- auto it = std::find_if(addonCache.begin(), addonCache.end(), +- [addonId](const AddonPtr& addon) +- { +- return addon->ID() == addonId; +- }); +- +- if (it != addonCache.end()) +- { +- ControllerPtr newController = std::dynamic_pointer_cast(*it); +- if (newController && newController->LoadLayout()) +- m_controllers.push_back(newController); +- } +-} +- +-void CGUIControllerList::UnregisterController(const std::string& controllerId) +-{ +- m_controllers.erase(std::remove_if(m_controllers.begin(), m_controllers.end(), +- [controllerId](const ControllerPtr& controller) +- { +- return controller->ID() == controllerId; +- }), m_controllers.end()); +-} +- + void CGUIControllerList::CleanupButtons(void) + { + if (m_controllerList) +diff --git a/xbmc/games/controllers/windows/GUIControllerList.h b/xbmc/games/controllers/windows/GUIControllerList.h +index 44197d5..f59fde0 100644 +--- a/xbmc/games/controllers/windows/GUIControllerList.h ++++ b/xbmc/games/controllers/windows/GUIControllerList.h +@@ -20,13 +20,9 @@ + #pragma once + + #include "IConfigurationWindow.h" +-#include "addons/Addon.h" + #include "games/controllers/ControllerTypes.h" + #include "utils/Observer.h" + +-#include +-#include +- + class CGUIButtonControl; + class CGUIControlGroupList; + class CGUIWindow; +@@ -45,7 +41,7 @@ namespace GAME + // implementation of IControllerList + virtual bool Initialize(void) override; + virtual void Deinitialize(void) override; +- virtual bool Refresh(void) override; ++ virtual void Refresh(void) override; + virtual void OnFocus(unsigned int controllerIndex) override; + virtual void OnSelect(unsigned int controllerIndex) override; + virtual void ResetController(void) override; +@@ -56,12 +52,6 @@ namespace GAME + private: + bool RefreshControllers(void); + +- std::set GetControllerIDs() const; +- std::set GetNewControllerIDs(ADDON::VECADDONS& addonCache) const; +- +- void RegisterController(const std::string& controllerId, const ADDON::VECADDONS& addonCache); +- void UnregisterController(const std::string& controllerId); +- + void CleanupButtons(void); + + // GUI stuff +diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.cpp b/xbmc/games/controllers/windows/GUIControllerWindow.cpp +index 65bb09f..598caa8 100644 +--- a/xbmc/games/controllers/windows/GUIControllerWindow.cpp ++++ b/xbmc/games/controllers/windows/GUIControllerWindow.cpp +@@ -62,7 +62,7 @@ bool CGUIControllerWindow::OnMessage(CGUIMessage& message) + { + case GUI_MSG_WINDOW_INIT: + { +- //! @todo Process parameter ++ // TODO: Process parameter + //std::string strParam = message.GetStringParam(); + break; + } +@@ -130,20 +130,6 @@ bool CGUIControllerWindow::OnMessage(CGUIMessage& message) + } + break; + } +- case GUI_MSG_REFRESH_LIST: +- { +- int controlId = message.GetControlId(); +- +- if (controlId == CONTROL_CONTROLLER_LIST) +- { +- if (m_controllerList && m_controllerList->Refresh()) +- { +- CGUIDialog::OnMessage(message); +- return true; +- } +- } +- break; +- } + default: + break; + } +@@ -187,13 +173,12 @@ void CGUIControllerWindow::OnInitWindow(void) + CGUIMessage msgFocus(GUI_MSG_SETFOCUS, GetID(), CONTROL_CONTROLLER_BUTTONS_START); + OnMessage(msgFocus); + +- // Check for button mapping support +- //! @todo remove this ++ // Check for button mapping support (TODO: remove this) + PeripheralBusAddonPtr bus = std::static_pointer_cast(g_peripherals.GetBusByType(PERIPHERAL_BUS_ADDON)); + if (bus && !bus->HasFeature(FEATURE_JOYSTICK)) + { +- //! @todo Move the XML implementation of button map storage from add-on to +- //! Kodi while keeping support for add-on button-mapping ++ // TODO: Move the XML implementation of button map storage from add-on to ++ // Kodi while keeping support for add-on button-mapping + + CLog::Log(LOGERROR, "Joystick support not found"); + +@@ -239,8 +224,8 @@ void CGUIControllerWindow::OnControllerFocused(unsigned int controllerIndex) + + void CGUIControllerWindow::OnControllerSelected(unsigned int controllerIndex) + { +- if (m_controllerList) +- m_controllerList->OnSelect(controllerIndex); ++ // jump to the feature list ++ SET_CONTROL_FOCUS(CONTROL_FEATURE_BUTTONS_START, 0); + } + + void CGUIControllerWindow::OnFeatureFocused(unsigned int featureIndex) +diff --git a/xbmc/games/controllers/windows/IConfigurationWindow.h b/xbmc/games/controllers/windows/IConfigurationWindow.h +index b6ef34c..2d02091 100644 +--- a/xbmc/games/controllers/windows/IConfigurationWindow.h ++++ b/xbmc/games/controllers/windows/IConfigurationWindow.h +@@ -23,7 +23,6 @@ + #include "input/joysticks/JoystickTypes.h" + + #include +-#include + + class CEvent; + +@@ -71,9 +70,8 @@ namespace GAME + + /*! + * \brief Refresh the contents of the list +- * \return True if the list was changed + */ +- virtual bool Refresh(void) = 0; ++ virtual void Refresh(void) = 0; + + /* + * \brief The specified controller has been focused +diff --git a/xbmc/guiinfo/GUIInfoLabels.h b/xbmc/guiinfo/GUIInfoLabels.h +index 27d6bc2..230e390 100644 +--- a/xbmc/guiinfo/GUIInfoLabels.h ++++ b/xbmc/guiinfo/GUIInfoLabels.h +@@ -759,9 +759,6 @@ + #define LISTITEM_ADDON_LAST_USED (LISTITEM_START + 174) + #define LISTITEM_STATUS (LISTITEM_START + 175) + #define LISTITEM_ENDTIME_RESUME (LISTITEM_START + 176) +-#define LISTITEM_ADDON_ORIGIN (LISTITEM_START + 177) +-#define LISTITEM_ADDON_NEWS (LISTITEM_START + 178) +-#define LISTITEM_ADDON_SIZE (LISTITEM_START + 179) + + #define LISTITEM_PROPERTY_START (LISTITEM_START + 200) + #define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1300) +diff --git a/xbmc/guilib/D3DResource.cpp b/xbmc/guilib/D3DResource.cpp +index 88b4721..36aa6a8 100644 +--- a/xbmc/guilib/D3DResource.cpp ++++ b/xbmc/guilib/D3DResource.cpp +@@ -843,7 +843,7 @@ void CD3DVertexShader::Release() + g_Windowing.Unregister(this); + ReleaseShader(); + SAFE_RELEASE(m_VSBuffer); +- SAFE_DELETE_ARRAY(m_vertexLayout); ++ SAFE_DELETE(m_vertexLayout); + } + + void CD3DVertexShader::ReleaseShader() +diff --git a/xbmc/guilib/DirtyRegionSolvers.cpp b/xbmc/guilib/DirtyRegionSolvers.cpp +index 826c597..4c6c758 100644 +--- a/xbmc/guilib/DirtyRegionSolvers.cpp ++++ b/xbmc/guilib/DirtyRegionSolvers.cpp +@@ -66,7 +66,7 @@ void CGreedyDirtyRegionSolver::Solve(const CDirtyRegionList &input, CDirtyRegion + float temporaryCost = m_costPerArea * (temporaryUnion.Area() - output[j].Area()); + if (temporaryCost < possibleUnionCost) + { +- //! @todo if the temporaryCost is 0 then we could skip checking the other regions since there exist no better solution ++ // TODO if the temporaryCost is 0 then we could skip checking the other regions since there exist no better solution + possibleUnionRegion = temporaryUnion; + possibleUnionNbr = j; + possibleUnionCost = temporaryCost; +diff --git a/xbmc/guilib/GUIBaseContainer.h b/xbmc/guilib/GUIBaseContainer.h +index 52960bf..b941689 100644 +--- a/xbmc/guilib/GUIBaseContainer.h ++++ b/xbmc/guilib/GUIBaseContainer.h +@@ -26,7 +26,6 @@ + */ + + #include +-#include + + #include "GUIListItemLayout.h" + #include "IGUIContainer.h" +diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp +index 84c750b..eed9789 100644 +--- a/xbmc/guilib/GUIControl.cpp ++++ b/xbmc/guilib/GUIControl.cpp +@@ -524,8 +524,8 @@ void CGUIControl::SetHeight(float height) + void CGUIControl::SetVisible(bool bVisible, bool setVisState) + { + if (bVisible && setVisState) +- { //! @todo currently we only update m_visible from GUI_MSG_VISIBLE (SET_CONTROL_VISIBLE) +- //! otherwise we just set m_forceHidden ++ { // TODO: currently we only update m_visible from GUI_MSG_VISIBLE (SET_CONTROL_VISIBLE) ++ // otherwise we just set m_forceHidden + GUIVISIBLE visible; + if (m_visibleCondition) + visible = m_visibleCondition->Get() ? VISIBLE : HIDDEN; +diff --git a/xbmc/guilib/GUIControl.h b/xbmc/guilib/GUIControl.h +index 29858fc..0293bd6 100644 +--- a/xbmc/guilib/GUIControl.h ++++ b/xbmc/guilib/GUIControl.h +@@ -27,8 +27,6 @@ + * + */ + +-#include +- + #include "GraphicContext.h" // needed by any rendering operation (all controls) + #include "GUIMessage.h" // needed by practically all controls + #include "VisibleEffect.h" // needed for the CAnimation members +diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp +index 53f8fe1..a3a9c9b 100644 +--- a/xbmc/guilib/GUIControlFactory.cpp ++++ b/xbmc/guilib/GUIControlFactory.cpp +@@ -778,8 +778,8 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl + + if (!pControlNode->Attribute("id", (int*) &id)) + XMLUtils::GetInt(pControlNode, "id", (int&) id); // backward compatibility - not desired +- //! @todo Perhaps we should check here whether id is valid for focusable controls +- //! such as buttons etc. For labels/fadelabels/images it does not matter ++ // TODO: Perhaps we should check here whether id is valid for focusable controls ++ // such as buttons etc. For labels/fadelabels/images it does not matter + + GetAlignment(pControlNode, "align", labelInfo.align); + if (!GetDimensions(pControlNode, "left", "right", "centerleft", "centerright", "width", rect.Width(), posX, width, minWidth)) +diff --git a/xbmc/guilib/GUIControlFactory.h b/xbmc/guilib/GUIControlFactory.h +index ce9177e..3ae86df 100644 +--- a/xbmc/guilib/GUIControlFactory.h ++++ b/xbmc/guilib/GUIControlFactory.h +@@ -28,9 +28,6 @@ + * + */ + +-#include +-#include +- + #include "GUIControl.h" + + class CTextureInfo; // forward +diff --git a/xbmc/guilib/GUIControlGroup.h b/xbmc/guilib/GUIControlGroup.h +index ea1d8fc..0b38a56 100644 +--- a/xbmc/guilib/GUIControlGroup.h ++++ b/xbmc/guilib/GUIControlGroup.h +@@ -25,8 +25,6 @@ + * + */ + +-#include +- + #include "GUIControl.h" + + /*! +diff --git a/xbmc/guilib/GUIControlProfiler.h b/xbmc/guilib/GUIControlProfiler.h +index c432b01..b62ebb3 100644 +--- a/xbmc/guilib/GUIControlProfiler.h ++++ b/xbmc/guilib/GUIControlProfiler.h +@@ -22,8 +22,6 @@ + #define GUILIB_GUICONTROLPROFILER_H__ + #pragma once + +-#include +- + #include "GUIControl.h" + + class CGUIControlProfiler; +diff --git a/xbmc/guilib/GUIEditControl.cpp b/xbmc/guilib/GUIEditControl.cpp +index acda8bc..52b1a4d 100644 +--- a/xbmc/guilib/GUIEditControl.cpp ++++ b/xbmc/guilib/GUIEditControl.cpp +@@ -358,7 +358,7 @@ void CGUIEditControl::OnClick() + textChanged = CGUIDialogNumeric::ShowAndVerifyNewPassword(utf8); + break; + case INPUT_TYPE_PASSWORD_MD5: +- utf8 = ""; //! @todo Ideally we'd send this to the keyboard and tell the keyboard we have this type of input ++ utf8 = ""; // TODO: Ideally we'd send this to the keyboard and tell the keyboard we have this type of input + // fallthrough + case INPUT_TYPE_TEXT: + default: +@@ -397,7 +397,7 @@ void CGUIEditControl::SetInputType(CGUIEditControl::INPUT_TYPE type, CVariant he + m_inputHeading = heading.asString(); + else if (heading.isInteger() && heading.asInteger()) + m_inputHeading = g_localizeStrings.Get(static_cast(heading.asInteger())); +- //! @todo Verify the current input string? ++ // TODO: Verify the current input string? + } + + void CGUIEditControl::RecalcLabelPosition() +diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp +index 01826a5..d981d66 100644 +--- a/xbmc/guilib/GUIFadeLabelControl.cpp ++++ b/xbmc/guilib/GUIFadeLabelControl.cpp +@@ -19,7 +19,6 @@ + */ + + #include "GUIFadeLabelControl.h" +-#include "utils/Random.h" + + CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, bool scrollOut, unsigned int timeToDelayAtEnd, bool resetOnLabelChange, bool randomized) + : CGUIControl(parentID, controlID, posX, posY, width, height), m_label(labelInfo), m_scrollInfo(50, labelInfo.offsetX, labelInfo.scrollSpeed) +@@ -64,7 +63,7 @@ void CGUIFadeLabelControl::SetInfo(const std::vector &infoLabels) + m_lastLabel = -1; + m_infoLabels = infoLabels; + if (m_randomized) +- KODI::UTILS::RandomShuffle(m_infoLabels.begin(), m_infoLabels.end()); ++ std::random_shuffle(m_infoLabels.begin(), m_infoLabels.end()); + } + + void CGUIFadeLabelControl::AddLabel(const std::string &label) +diff --git a/xbmc/guilib/GUIFadeLabelControl.h b/xbmc/guilib/GUIFadeLabelControl.h +index f17c14d..6cae459 100644 +--- a/xbmc/guilib/GUIFadeLabelControl.h ++++ b/xbmc/guilib/GUIFadeLabelControl.h +@@ -28,8 +28,6 @@ + * + */ + +-#include +- + #include "GUIControl.h" + #include "GUILabel.h" + +diff --git a/xbmc/guilib/GUIFontManager.cpp b/xbmc/guilib/GUIFontManager.cpp +index 7e42707..8e044dd 100644 +--- a/xbmc/guilib/GUIFontManager.cpp ++++ b/xbmc/guilib/GUIFontManager.cpp +@@ -411,7 +411,7 @@ void GUIFontManager::LoadFonts(const TiXmlNode* fontNode) + + if (!fontName.empty() && URIUtils::HasExtension(fileName, ".ttf")) + { +- //! @todo Why do we tolower() this shit? ++ // TODO: Why do we tolower() this shit? + std::string strFontFileName = fileName; + StringUtils::ToLower(strFontFileName); + LoadTTF(fontName, strFontFileName, textColor, shadowColor, iSize, iStyle, false, lineSpacing, aspect); +diff --git a/xbmc/guilib/GUIFontManager.h b/xbmc/guilib/GUIFontManager.h +index 5f8745d..5d1a07b 100644 +--- a/xbmc/guilib/GUIFontManager.h ++++ b/xbmc/guilib/GUIFontManager.h +@@ -29,7 +29,6 @@ + */ + + #include +-#include + + #include "GraphicContext.h" + #include "IMsgTargetCallback.h" +diff --git a/xbmc/guilib/GUIFontTTFDX.h b/xbmc/guilib/GUIFontTTFDX.h +index c66ce34..af7f557 100644 +--- a/xbmc/guilib/GUIFontTTFDX.h ++++ b/xbmc/guilib/GUIFontTTFDX.h +@@ -30,7 +30,6 @@ + #include "D3DResource.h" + #include "GUIFontTTF.h" + #include +-#include + + #define ELEMENT_ARRAY_MAX_CHAR_INDEX (2000) + +diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h +index 88c5f40..bcde308 100644 +--- a/xbmc/guilib/GUIFontTTFGL.h ++++ b/xbmc/guilib/GUIFontTTFGL.h +@@ -28,9 +28,6 @@ + #pragma once + + +-#include +-#include +- + #include "GUIFontTTF.h" + #include "system.h" + #include "system_gl.h" +diff --git a/xbmc/guilib/GUIImage.h b/xbmc/guilib/GUIImage.h +index 8eb8097..27f9fd9 100644 +--- a/xbmc/guilib/GUIImage.h ++++ b/xbmc/guilib/GUIImage.h +@@ -28,8 +28,6 @@ + * + */ + +-#include +- + #include "GUIControl.h" + #include "GUITexture.h" + +diff --git a/xbmc/guilib/GUIKeyboardFactory.cpp b/xbmc/guilib/GUIKeyboardFactory.cpp +index 73f9631..4c6ea49 100644 +--- a/xbmc/guilib/GUIKeyboardFactory.cpp ++++ b/xbmc/guilib/GUIKeyboardFactory.cpp +@@ -201,8 +201,7 @@ int CGUIKeyboardFactory::ShowAndVerifyPassword(std::string& strPassword, const s + g_localizeStrings.Get(12343).c_str()); + + std::string strUserInput; +- //! @todo GUI Setting to enable disable this feature y/n? +- if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true, autoCloseMs)) //bool hiddenInput = false/true ? ++ if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true, autoCloseMs)) //bool hiddenInput = false/true ? TODO: GUI Setting to enable disable this feature y/n? + return -1; // user canceled out + + if (!strPassword.empty()) +diff --git a/xbmc/guilib/GUILabel.cpp b/xbmc/guilib/GUILabel.cpp +index db20131..759ac09 100644 +--- a/xbmc/guilib/GUILabel.cpp ++++ b/xbmc/guilib/GUILabel.cpp +@@ -88,7 +88,7 @@ color_t CGUILabel::GetColor() const + + bool CGUILabel::Process(unsigned int currentTime) + { +- //! @todo Add the correct processing ++ // TODO Add the correct processing + + bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues + bool renderSolid = (m_color == COLOR_DISABLED); +diff --git a/xbmc/guilib/GUIMoverControl.cpp b/xbmc/guilib/GUIMoverControl.cpp +index 13c0fd3..bee68cc 100644 +--- a/xbmc/guilib/GUIMoverControl.cpp ++++ b/xbmc/guilib/GUIMoverControl.cpp +@@ -33,9 +33,9 @@ CGUIMoverControl::CGUIMoverControl(int parentID, int controlID, float posX, floa + m_frameCounter = 0; + m_lastMoveTime = 0; + m_fSpeed = 1.0; +- m_fAnalogSpeed = 2.0f; //! @todo implement correct analog speed +- m_fAcceleration = 0.2f; //! @todo implement correct computation of acceleration +- m_fMaxSpeed = 10.0; //! @todo implement correct computation of maxspeed ++ m_fAnalogSpeed = 2.0f; // TODO: implement correct analog speed ++ m_fAcceleration = 0.2f; // TODO: implement correct computation of acceleration ++ m_fMaxSpeed = 10.0; // TODO: implement correct computation of maxspeed + ControlType = GUICONTROL_MOVER; + SetLimits(0, 0, 720, 576); // defaults + SetLocation(0, 0, false); // defaults +diff --git a/xbmc/guilib/GUIMultiImage.cpp b/xbmc/guilib/GUIMultiImage.cpp +index 4d43531..9038bdd 100644 +--- a/xbmc/guilib/GUIMultiImage.cpp ++++ b/xbmc/guilib/GUIMultiImage.cpp +@@ -28,7 +28,6 @@ + #include "input/Key.h" + #include "TextureCache.h" + #include "WindowIDs.h" +-#include "utils/Random.h" + #include "utils/StringUtils.h" + + using namespace XFILE; +@@ -250,7 +249,7 @@ void CGUIMultiImage::OnDirectoryLoaded() + { + // Randomize or sort our images if necessary + if (m_randomized) +- KODI::UTILS::RandomShuffle(m_files.begin(), m_files.end()); ++ random_shuffle(m_files.begin(), m_files.end()); + else + sort(m_files.begin(), m_files.end()); + +diff --git a/xbmc/guilib/GUIMultiImage.h b/xbmc/guilib/GUIMultiImage.h +index 84535c5..e4af967 100644 +--- a/xbmc/guilib/GUIMultiImage.h ++++ b/xbmc/guilib/GUIMultiImage.h +@@ -28,8 +28,6 @@ + * + */ + +-#include +- + #include "GUIImage.h" + #include "utils/Stopwatch.h" + #include "utils/Job.h" +diff --git a/xbmc/guilib/GUIRSSControl.h b/xbmc/guilib/GUIRSSControl.h +index 583ea20..33dc2f7 100644 +--- a/xbmc/guilib/GUIRSSControl.h ++++ b/xbmc/guilib/GUIRSSControl.h +@@ -28,8 +28,6 @@ + * + */ + +-#include +- + #include "GUIControl.h" + #include "GUILabel.h" + #include "utils/IRssObserver.h" +diff --git a/xbmc/guilib/GUIRenderingControl.cpp b/xbmc/guilib/GUIRenderingControl.cpp +index 8aa58e3..143bb8f 100644 +--- a/xbmc/guilib/GUIRenderingControl.cpp ++++ b/xbmc/guilib/GUIRenderingControl.cpp +@@ -81,7 +81,7 @@ void CGUIRenderingControl::UpdateVisibility(const CGUIListItem *item) + + void CGUIRenderingControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) + { +- //! @todo Add processing to the addon so it could mark when actually changing ++ // TODO Add processing to the addon so it could mark when actually changing + CSingleLock lock(m_rendering); + if (m_callback && m_callback->IsDirty()) + MarkDirtyRegion(); +@@ -113,7 +113,7 @@ void CGUIRenderingControl::FreeResources(bool immediately) + + if (!m_callback) return; + +- g_graphicsContext.CaptureStateBlock(); //! @todo locking ++ g_graphicsContext.CaptureStateBlock(); //TODO locking + m_callback->Stop(); + g_graphicsContext.ApplyStateBlock(); + m_callback = NULL; +diff --git a/xbmc/guilib/GUIRenderingControl.h b/xbmc/guilib/GUIRenderingControl.h +index d46adf4..796d318 100644 +--- a/xbmc/guilib/GUIRenderingControl.h ++++ b/xbmc/guilib/GUIRenderingControl.h +@@ -28,7 +28,7 @@ class CGUIRenderingControl : public CGUIControl + public: + CGUIRenderingControl(int parentID, int controlID, float posX, float posY, float width, float height); + CGUIRenderingControl(const CGUIRenderingControl &from); +- virtual CGUIRenderingControl *Clone() const { return new CGUIRenderingControl(*this); }; //! @todo check for naughties ++ virtual CGUIRenderingControl *Clone() const { return new CGUIRenderingControl(*this); }; //TODO check for naughties + + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void Render(); +diff --git a/xbmc/guilib/GUIResizeControl.cpp b/xbmc/guilib/GUIResizeControl.cpp +index d0531a0..89d3039 100644 +--- a/xbmc/guilib/GUIResizeControl.cpp ++++ b/xbmc/guilib/GUIResizeControl.cpp +@@ -33,9 +33,9 @@ CGUIResizeControl::CGUIResizeControl(int parentID, int controlID, float posX, fl + m_frameCounter = 0; + m_lastMoveTime = 0; + m_fSpeed = 1.0; +- m_fAnalogSpeed = 2.0f; //! @todo implement correct analog speed +- m_fAcceleration = 0.2f; //! @todo implement correct computation of acceleration +- m_fMaxSpeed = 10.0; //! @todo implement correct computation of maxspeed ++ m_fAnalogSpeed = 2.0f; // TODO: implement correct analog speed ++ m_fAcceleration = 0.2f; // TODO: implement correct computation of acceleration ++ m_fMaxSpeed = 10.0; // TODO: implement correct computation of maxspeed + ControlType = GUICONTROL_RESIZE; + SetLimits(0, 0, 720, 576); // defaults + m_nDirection = DIRECTION_NONE; +diff --git a/xbmc/guilib/GUISpinControl.h b/xbmc/guilib/GUISpinControl.h +index 83866d7..fee7875 100644 +--- a/xbmc/guilib/GUISpinControl.h ++++ b/xbmc/guilib/GUISpinControl.h +@@ -28,8 +28,6 @@ + * + */ + +-#include +- + #include "GUIControl.h" + #include "GUITexture.h" + #include "GUILabel.h" +diff --git a/xbmc/guilib/GUIStaticItem.h b/xbmc/guilib/GUIStaticItem.h +index a3f268e..20c7182 100644 +--- a/xbmc/guilib/GUIStaticItem.h ++++ b/xbmc/guilib/GUIStaticItem.h +@@ -26,7 +26,6 @@ + */ + + #include +-#include + + #include "GUIAction.h" + #include "GUIInfoTypes.h" +diff --git a/xbmc/guilib/GUITextLayout.cpp b/xbmc/guilib/GUITextLayout.cpp +index 8c17f67..cc6d04f 100644 +--- a/xbmc/guilib/GUITextLayout.cpp ++++ b/xbmc/guilib/GUITextLayout.cpp +@@ -174,10 +174,10 @@ void CGUITextLayout::RenderOutline(float x, float y, color_t color, color_t outl + align &= ~XBFONT_JUSTIFIED; + // text centered horizontally must be computed using the original font, not the bordered + // font, as the bordered font will be wider, and thus will end up uncentered. +- //! @todo We should really have a better way to handle text extent - at the moment we assume +- //! that text is rendered from a posx, posy, width, and height which isn't enough to +- //! accurately position text. We need a vertical and horizontal offset of the baseline +- //! and cursor as well. ++ // TODO: We should really have a better way to handle text extent - at the moment we assume ++ // that text is rendered from a posx, posy, width, and height which isn't enough to ++ // accurately position text. We need a vertical and horizontal offset of the baseline ++ // and cursor as well. + float bx = x; + if (align & XBFONT_CENTER_X) + { +diff --git a/xbmc/guilib/GUITexture.cpp b/xbmc/guilib/GUITexture.cpp +index 34237e4..5a6ffa0 100644 +--- a/xbmc/guilib/GUITexture.cpp ++++ b/xbmc/guilib/GUITexture.cpp +@@ -198,9 +198,9 @@ void CGUITextureBase::Render() + v3 *= m_texCoordsScaleV; + } + +- //! @todo The diffuse coloring applies to all vertices, which will +- //! look weird for stuff with borders, as will the -ve height/width +- //! for flipping ++ // TODO: The diffuse coloring applies to all vertices, which will ++ // look weird for stuff with borders, as will the -ve height/width ++ // for flipping + + // left segment (0,0,u1,v3) + if (m_info.border.x1) +diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp +index dd1e594..a3f6039 100644 +--- a/xbmc/guilib/GUIVideoControl.cpp ++++ b/xbmc/guilib/GUIVideoControl.cpp +@@ -36,7 +36,7 @@ CGUIVideoControl::~CGUIVideoControl(void) + + void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) + { +- //! @todo Proper processing which marks when its actually changed. Just mark always for now. ++ // TODO Proper processing which marks when its actually changed. Just mark always for now. + if (g_application.m_pPlayer->IsRenderingGuiLayer()) + MarkDirtyRegion(); + +@@ -73,8 +73,8 @@ void CGUIVideoControl::Render() + + g_graphicsContext.RemoveTransform(); + } +- //! @todo remove this crap: HAS_VIDEO_PLAYBACK +- //! instantiating a video control having no playback is complete nonsense ++ // TODO: remove this crap: HAS_VIDEO_PLAYBACK ++ // instantiating a video control having no playback is complete nonsense + CGUIControl::Render(); + } + +diff --git a/xbmc/guilib/GUIVisualisationControl.h b/xbmc/guilib/GUIVisualisationControl.h +index c765cd0..1abdcff 100644 +--- a/xbmc/guilib/GUIVisualisationControl.h ++++ b/xbmc/guilib/GUIVisualisationControl.h +@@ -27,7 +27,7 @@ class CGUIVisualisationControl : public CGUIRenderingControl + public: + CGUIVisualisationControl(int parentID, int controlID, float posX, float posY, float width, float height); + CGUIVisualisationControl(const CGUIVisualisationControl &from); +- virtual CGUIVisualisationControl *Clone() const { return new CGUIVisualisationControl(*this); }; //! @todo check for naughties ++ virtual CGUIVisualisationControl *Clone() const { return new CGUIVisualisationControl(*this); }; //TODO check for naughties + virtual void FreeResources(bool immediately = false); + virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual bool OnAction(const CAction &action); +diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp +index 0a952e3..912a429 100644 +--- a/xbmc/guilib/GUIWindowManager.cpp ++++ b/xbmc/guilib/GUIWindowManager.cpp +@@ -301,9 +301,11 @@ bool CGUIWindowManager::DestroyWindows() + Delete(WINDOW_SPLASH); + Delete(WINDOW_MUSIC_PLAYLIST); + Delete(WINDOW_MUSIC_PLAYLIST_EDITOR); ++ Delete(WINDOW_MUSIC_FILES); + Delete(WINDOW_MUSIC_NAV); + Delete(WINDOW_DIALOG_MUSIC_INFO); + Delete(WINDOW_DIALOG_VIDEO_INFO); ++ Delete(WINDOW_VIDEO_FILES); + Delete(WINDOW_VIDEO_PLAYLIST); + Delete(WINDOW_VIDEO_NAV); + Delete(WINDOW_FILES); +@@ -631,8 +633,8 @@ void CGUIWindowManager::PreviousWindow() + // check to see whether our current window has a tag + if (pCurrentWindow->GetPreviousWindow() != WINDOW_INVALID) + { +- //! @todo we may need to test here for the +- //! whether our history should be changed ++ // TODO: we may need to test here for the ++ // whether our history should be changed + + // don't reactivate the previouswindow if it is ourselves. + if (currentWindow != pCurrentWindow->GetPreviousWindow()) +@@ -727,6 +729,20 @@ void CGUIWindowManager::ActivateWindow(int iWindowID, const std::vector& params, bool swappingWindows, bool force /* = false */) + { + // translate virtual windows ++ // virtual music window which returns the last open music window (aka the music start window) ++ if (iWindowID == WINDOW_MUSIC || iWindowID == WINDOW_MUSIC_FILES) ++ { // backward compatibility for pre-something ++ iWindowID = WINDOW_MUSIC_NAV; ++ } ++ // virtual video window which returns the last open video window (aka the video start window) ++ if (iWindowID == WINDOW_VIDEOS || iWindowID == WINDOW_VIDEO_FILES) ++ { // backward compatibility for pre-Eden ++ iWindowID = WINDOW_VIDEO_NAV; ++ } ++ if (iWindowID == WINDOW_SCRIPTS) ++ { // backward compatibility for pre-Dharma ++ iWindowID = WINDOW_PROGRAMS; ++ } + if (iWindowID == WINDOW_START) + { // virtual start window + iWindowID = g_SkinInfo->GetStartWindow(); +@@ -748,14 +764,10 @@ void CGUIWindowManager::ActivateWindow_Internal(int iWindowID, const std::vector + if (!pNewWindow) + { // nothing to see here - move along + CLog::Log(LOGERROR, "Unable to locate window with id %d. Check skin files", iWindowID - WINDOW_HOME); +- if (GetActiveWindowID() == WINDOW_STARTUP_ANIM) +- ActivateWindow(WINDOW_HOME); + return ; + } + else if (!pNewWindow->CanBeActivated()) + { +- if (GetActiveWindowID() == WINDOW_STARTUP_ANIM) +- ActivateWindow(WINDOW_HOME); + return; + } + else if (pNewWindow->IsDialog()) +diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h +index 85c81fc..150765d 100644 +--- a/xbmc/guilib/GUIWindowManager.h ++++ b/xbmc/guilib/GUIWindowManager.h +@@ -30,7 +30,6 @@ + + #include + #include +-#include + + #include "DirtyRegionTracker.h" + #include "guilib/WindowIDs.h" +diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp +index 9caa431..9c43486 100644 +--- a/xbmc/guilib/GraphicContext.cpp ++++ b/xbmc/guilib/GraphicContext.cpp +@@ -975,12 +975,12 @@ void CGraphicContext::SetMediaDir(const std::string &strMediaDir) + m_strMediaDir = strMediaDir; + } + +-void CGraphicContext::Flip(bool rendered, bool videoLayer) ++void CGraphicContext::Flip(bool rendered) + { + if (IsFullScreenVideo()) + g_Windowing.FinishPipeline(); + +- g_Windowing.PresentRender(rendered, videoLayer); ++ g_Windowing.PresentRender(rendered); + + if(m_stereoMode != m_nextStereoMode) + { +diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h +index 08bbfd7..50a0a6d 100644 +--- a/xbmc/guilib/GraphicContext.h ++++ b/xbmc/guilib/GraphicContext.h +@@ -130,7 +130,7 @@ public: + void SetRenderingResolution(const RESOLUTION_INFO &res, bool needsScaling); ///< Sets scaling up for rendering + void SetScalingResolution(const RESOLUTION_INFO &res, bool needsScaling); ///< Sets scaling up for skin loading etc. + float GetScalingPixelRatio() const; +- void Flip(bool rendered, bool videoLayer); ++ void Flip(bool rendered); + void InvertFinalCoords(float &x, float &y) const; + inline float ScaleFinalXCoord(float x, float y) const XBMC_FORCE_INLINE { return m_finalTransform.matrix.TransformXCoord(x, y, 0); } + inline float ScaleFinalYCoord(float x, float y) const XBMC_FORCE_INLINE { return m_finalTransform.matrix.TransformYCoord(x, y, 0); } +diff --git a/xbmc/guilib/LocalizeStrings.cpp b/xbmc/guilib/LocalizeStrings.cpp +index e62ed7b..c49b290 100644 +--- a/xbmc/guilib/LocalizeStrings.cpp ++++ b/xbmc/guilib/LocalizeStrings.cpp +@@ -123,16 +123,16 @@ static bool LoadPO(const std::string &filename, std::map& stri + } + else if (PODoc.GetEntryType() == MSGID_FOUND) + { +- //! @todo implement reading of non-id based string entries from the PO files. +- //! These entries would go into a separate memory map, using hash codes for fast look-up. +- //! With this memory map we can implement using gettext(), ngettext(), pgettext() calls, +- //! so that we don't have to use new IDs for new strings. Even we can start converting +- //! the ID based calls to normal gettext calls. ++ // TODO: implement reading of non-id based string entries from the PO files. ++ // These entries would go into a separate memory map, using hash codes for fast look-up. ++ // With this memory map we can implement using gettext(), ngettext(), pgettext() calls, ++ // so that we don't have to use new IDs for new strings. Even we can start converting ++ // the ID based calls to normal gettext calls. + } + else if (PODoc.GetEntryType() == MSGID_PLURAL_FOUND) + { +- //! @todo implement reading of non-id based pluralized string entries from the PO files. +- //! We can store the pluralforms for each language, in the langinfo.xml files. ++ // TODO: implement reading of non-id based pluralized string entries from the PO files. ++ // We can store the pluralforms for each language, in the langinfo.xml files. + } + } + +@@ -210,7 +210,7 @@ void CLocalizeStrings::ClearSkinStrings() + + bool CLocalizeStrings::LoadSkinStrings(const std::string& path, const std::string& language) + { +- //! @todo shouldn't hold lock while loading file ++ //TODO: shouldn't hold lock while loading file + CExclusiveLock lock(m_stringsMutex); + ClearSkinStrings(); + // load the skin strings in. +diff --git a/xbmc/guilib/Resolution.cpp b/xbmc/guilib/Resolution.cpp +index b307524..64c7eda 100644 +--- a/xbmc/guilib/Resolution.cpp ++++ b/xbmc/guilib/Resolution.cpp +@@ -24,7 +24,13 @@ + #include "utils/MathUtils.h" + #include "settings/AdvancedSettings.h" + #include "settings/DisplaySettings.h" ++#include "settings/Settings.h" + #include ++#include ++ ++#include "Application.h" ++ ++#include "windowing/egl/vc_hdmi.h" + + RESOLUTION_INFO::RESOLUTION_INFO(int width, int height, float aspect, const std::string &mode) : + strMode(mode) +@@ -51,7 +57,7 @@ RESOLUTION_INFO::RESOLUTION_INFO(const RESOLUTION_INFO& res) : + iScreenWidth = res.iScreenWidth; iScreenHeight = res.iScreenHeight; + iSubtitles = res.iSubtitles; dwFlags = res.dwFlags; + fPixelRatio = res.fPixelRatio; fRefreshRate = res.fRefreshRate; +- iBlanking = res.iBlanking; ++ refresh_rate = res.refresh_rate; iBlanking = res.iBlanking; + } + + float RESOLUTION_INFO::DisplayRatio() const +@@ -59,21 +65,21 @@ float RESOLUTION_INFO::DisplayRatio() const + return iWidth * fPixelRatio / iHeight; + } + +-RESOLUTION CResolutionUtils::ChooseBestResolution(float fps, int width, bool is3D) ++RESOLUTION CResolutionUtils::ChooseBestResolution(float fps, int width, int height, bool is3D, bool isI) + { + RESOLUTION res = g_graphicsContext.GetVideoResolution(); + float weight; +- if (!FindResolutionFromOverride(fps, width, is3D, res, weight, false)) //find a refreshrate from overrides ++ if (!FindResolutionFromOverride(fps, width, height, is3D, isI, res, weight, false)) //find a refreshrate from overrides + { +- if (!FindResolutionFromOverride(fps, width, is3D, res, weight, true))//if that fails find it from a fallback +- FindResolutionFromFpsMatch(fps, width, is3D, res, weight);//if that fails use automatic refreshrate selection ++ if (!FindResolutionFromOverride(fps, width, height, is3D, isI, res, weight, true))//if that fails find it from a fallback ++ FindResolutionFromFpsMatch(fps, width, height, is3D, isI, res, weight);//if that fails use automatic refreshrate selection + } + CLog::Log(LOGNOTICE, "Display resolution ADJUST : %s (%d) (weight: %.3f)", + g_graphicsContext.GetResInfo(res).strMode.c_str(), res, weight); + return res; + } + +-bool CResolutionUtils::FindResolutionFromOverride(float fps, int width, bool is3D, RESOLUTION &resolution, float& weight, bool fallback) ++bool CResolutionUtils::FindResolutionFromOverride(float fps, int width, int height, bool is3D, bool isI, RESOLUTION &resolution, float& weight, bool fallback) + { + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(resolution); + +@@ -127,12 +133,12 @@ bool CResolutionUtils::FindResolutionFromOverride(float fps, int width, bool is3 + return false; //no override found + } + +-void CResolutionUtils::FindResolutionFromFpsMatch(float fps, int width, bool is3D, RESOLUTION &resolution, float& weight) ++void CResolutionUtils::FindResolutionFromFpsMatch(float fps, int width, int height, bool is3D, bool isI, RESOLUTION &resolution, float& weight) + { + const float maxWeight = 0.0021f; + RESOLUTION_INFO curr; + +- resolution = FindClosestResolution(fps, width, is3D, 1.0, resolution, weight); ++ resolution = FindClosestResolution(fps, width, height, is3D, isI, 1.0, resolution, weight); + curr = g_graphicsContext.GetResInfo(resolution); + + if (weight >= maxWeight) //not a very good match, try a 2:3 cadence instead +@@ -140,7 +146,7 @@ void CResolutionUtils::FindResolutionFromFpsMatch(float fps, int width, bool is3 + CLog::Log(LOGDEBUG, "Resolution %s (%d) not a very good match for fps %.3f (weight: %.3f), trying 2:3 cadence", + curr.strMode.c_str(), resolution, fps, weight); + +- resolution = FindClosestResolution(fps, width, is3D, 2.5, resolution, weight); ++ resolution = FindClosestResolution(fps, width, height, is3D, isI, 2.5, resolution, weight); + curr = g_graphicsContext.GetResInfo(resolution); + + if (weight >= maxWeight) //2:3 cadence not a good match +@@ -191,8 +197,11 @@ void CResolutionUtils::FindResolutionFromFpsMatch(float fps, int width, bool is3 + } + } + +-RESOLUTION CResolutionUtils::FindClosestResolution(float fps, int width, bool is3D, float multiplier, RESOLUTION current, float& weight) ++RESOLUTION CResolutionUtils::FindClosestResolution(float fps, int width, int height, bool is3D, bool isI, float multiplier, RESOLUTION current, float& weight) + { ++ if (CDisplaySettings::GetInstance().ResolutionInfoSize() < 2) ++ return current; ++ + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current); + RESOLUTION orig_res = CDisplaySettings::GetInstance().GetCurrentResolution(); + +@@ -203,11 +212,80 @@ RESOLUTION CResolutionUtils::FindClosestResolution(float fps, int width, bool is + + float fRefreshRate = fps; + +- float last_diff = fRefreshRate; ++ float last_diff = FLT_MAX; + + int curr_diff = std::abs(width - curr.iScreenWidth); + int loop_diff = 0; + ++ // CHANGERESOLUTION ++ if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTION) && !is3D) ++ { ++ bool i_found = false; ++ ++ // if interlaced mode ++ if (isI && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTIONINTERLACED)) ++ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::GetInstance().ResolutionInfoSize(); i++) ++ { ++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ if (!(info.dwFlags & D3DPRESENTFLAG_INTERLACED) ++ || CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_MINIMUMVERTICAL) > info.iScreenHeight ++ || ((int)CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA) < GETFLAGS_GROUP(info.dwFlags)-1) ++ || info.iScreenHeight != height ++ || IS_3D(info.dwFlags)) ++ continue; ++ ++ current = (RESOLUTION)i; ++ curr = info; ++ i_found = true; ++ } ++ ++ if (!i_found) ++ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::GetInstance().ResolutionInfoSize(); i++) ++ { ++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ if ((fabs(info.fRefreshRate - fRefreshRate) > 0.001 && fabs(info.fRefreshRate - 2*fRefreshRate) > 0.001) ++ || IS_3D(info.dwFlags) ++ || CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_MINIMUMVERTICAL) > info.iScreenHeight ++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED && !isI) ++ || (!CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTIONINTERLACED) && (info.dwFlags & D3DPRESENTFLAG_INTERLACED)) ++ || ((int)CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA) < GETFLAGS_GROUP(info.dwFlags)-1) ++ || width > info.iScreenWidth || height > info.iScreenHeight ++ || pow(info.iScreenWidth*info.iScreenHeight - width*height, 2) > last_diff) ++ continue; ++ ++ current = (RESOLUTION)i; ++ curr = info; ++ i_found = true; ++ last_diff = pow(curr.iScreenWidth*curr.iScreenHeight - width*height, 2); ++ ++ if (info.iScreenWidth == width && info.iScreenHeight == height) ++ break; ++ } ++ ++ last_diff = FLT_MAX; ++ for (size_t i = (int)RES_DESKTOP; !i_found && i < CDisplaySettings::GetInstance().ResolutionInfoSize(); i++) ++ { ++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ ++ if (width > info.iScreenWidth || height > info.iScreenHeight ++ || CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_MINIMUMVERTICAL) > info.iScreenHeight ++ || pow(info.iScreenWidth*info.iScreenHeight - width*height, 2) > last_diff ++ || info.iScreen != curr.iScreen ++ || ((int)CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA) < GETFLAGS_GROUP(info.dwFlags)-1) ++ || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)) ++ { ++ /* CLog::Log(LOGDEBUG, "curr %.2f, trying %.2f, mode nr. %d, %dx%d msk %d, m_msk %d", info.fPixelRatio, curr.fPixelRatio, i, ++ info.iScreenWidth, info.iScreenHeight, info.dwFlags & D3DPRESENTFLAG_MODEMASK, ++ m_iFlags & D3DPRESENTFLAG_MODEMASK); */ ++ continue; ++ } ++ ++ current = (RESOLUTION)i; ++ curr = info; ++ last_diff = pow(curr.iScreenWidth*curr.iScreenHeight - width*height, 2); ++ } ++ } ++ + // Find closest refresh rate + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::GetInstance().ResolutionInfoSize(); i++) + { +@@ -215,9 +293,15 @@ RESOLUTION CResolutionUtils::FindClosestResolution(float fps, int width, bool is + + //discard resolutions that are not the same width and height (and interlaced/3D flags) + //or have a too low refreshrate +- if (info.iScreenWidth != curr.iScreenWidth || +- info.iScreenHeight != curr.iScreenHeight || +- info.iScreen != curr.iScreen || ++ if ((!CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTION) && ++ (info.iScreenWidth != curr.iScreenWidth || ++ info.iScreenHeight != curr.iScreenHeight)) || ++ (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTION) && ++ CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_MINIMUMVERTICAL) > info.iScreenHeight)) ++ continue; ++ ++ if (info.iScreen != curr.iScreen || ++ ((int)CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA) < GETFLAGS_GROUP(info.dwFlags)-1) || + (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK) || + info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) + { +@@ -227,6 +311,7 @@ RESOLUTION CResolutionUtils::FindClosestResolution(float fps, int width, bool is + if ((width < orig.iScreenWidth) || // orig res large enough + (info.iScreenWidth < orig.iScreenWidth) || // new res is smaller + (info.iScreenHeight < orig.iScreenHeight) || // new height would be smaller ++ ((int)CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA) < GETFLAGS_GROUP(info.dwFlags)-1) || + (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK) || // don't switch to interlaced modes + (info.iScreen != curr.iScreen)) // skip not current displays + { +diff --git a/xbmc/guilib/Resolution.h b/xbmc/guilib/Resolution.h +index f571528..9c69aee 100644 +--- a/xbmc/guilib/Resolution.h ++++ b/xbmc/guilib/Resolution.h +@@ -88,6 +88,7 @@ struct RESOLUTION_INFO + uint32_t dwFlags; + float fPixelRatio; + float fRefreshRate; ++ float refresh_rate; + std::string strMode; + std::string strOutput; + std::string strId; +@@ -100,10 +101,10 @@ public: + class CResolutionUtils + { + public: +- static RESOLUTION ChooseBestResolution(float fps, int width, bool is3D); ++ static RESOLUTION ChooseBestResolution(float fps, int width, int height, bool is3D, bool isI); ++ static RESOLUTION FindClosestResolution(float fps, int width, int height, bool is3D, bool isI, float multiplier, RESOLUTION current, float& weight); + protected: +- static bool FindResolutionFromOverride(float fps, int width, bool is3D, RESOLUTION &resolution, float& weight, bool fallback); +- static void FindResolutionFromFpsMatch(float fps, int width, bool is3D, RESOLUTION &resolution, float& weight); +- static RESOLUTION FindClosestResolution(float fps, int width, bool is3D, float multiplier, RESOLUTION current, float& weight); ++ static bool FindResolutionFromOverride(float fps, int width, int height, bool is3D, bool isI, RESOLUTION &resolution, float& weight, bool fallback); ++ static void FindResolutionFromFpsMatch(float fps, int width, int height, bool is3D, bool isI, RESOLUTION &resolution, float& weight); + static float RefreshWeight(float refresh, float fps); + }; +diff --git a/xbmc/guilib/TextureBundle.cpp b/xbmc/guilib/TextureBundle.cpp +index 596fdf3..d224155 100644 +--- a/xbmc/guilib/TextureBundle.cpp ++++ b/xbmc/guilib/TextureBundle.cpp +@@ -18,10 +18,15 @@ + * + */ + ++#include "system.h" + #include "TextureBundle.h" + +-CTextureBundle::CTextureBundle() +- : m_useXBT{false} ++CTextureBundle::CTextureBundle(void) ++{ ++ m_useXBT = false; ++} ++ ++CTextureBundle::~CTextureBundle(void) + { + } + +@@ -31,14 +36,15 @@ bool CTextureBundle::HasFile(const std::string& Filename) + { + return m_tbXBT.HasFile(Filename); + } +- +- if (m_tbXBT.HasFile(Filename)) ++ else if (m_tbXBT.HasFile(Filename)) + { + m_useXBT = true; + return true; + } +- +- return false; ++ else ++ { ++ return false; ++ } + } + + void CTextureBundle::GetTexturesFromPath(const std::string &path, std::vector &textures) +@@ -56,8 +62,10 @@ bool CTextureBundle::LoadTexture(const std::string& Filename, CBaseTexture** ppT + { + return m_tbXBT.LoadTexture(Filename, ppTexture, width, height); + } +- +- return false; ++ else ++ { ++ return false; ++ } + } + + int CTextureBundle::LoadAnim(const std::string& Filename, CBaseTexture*** ppTextures, +@@ -67,8 +75,16 @@ int CTextureBundle::LoadAnim(const std::string& Filename, CBaseTexture*** ppText + { + return m_tbXBT.LoadAnim(Filename, ppTextures, width, height, nLoops, ppDelays); + } ++ else ++ { ++ return 0; ++ } ++} + +- return 0; ++void CTextureBundle::Cleanup() ++{ ++ m_tbXBT.Cleanup(); ++ m_useXBT = false; + } + + void CTextureBundle::SetThemeBundle(bool themeBundle) +diff --git a/xbmc/guilib/TextureBundle.h b/xbmc/guilib/TextureBundle.h +index 67d62b4..1a4ec48 100644 +--- a/xbmc/guilib/TextureBundle.h ++++ b/xbmc/guilib/TextureBundle.h +@@ -27,8 +27,10 @@ + class CTextureBundle + { + public: +- CTextureBundle(); +- ~CTextureBundle() = default; ++ CTextureBundle(void); ++ ~CTextureBundle(void); ++ ++ void Cleanup(); + + void SetThemeBundle(bool themeBundle); + bool HasFile(const std::string& Filename); +diff --git a/xbmc/guilib/TextureBundleXBT.cpp b/xbmc/guilib/TextureBundleXBT.cpp +index 85ebd5b..4c06ed3 100644 +--- a/xbmc/guilib/TextureBundleXBT.cpp ++++ b/xbmc/guilib/TextureBundleXBT.cpp +@@ -18,46 +18,39 @@ + * + */ + +-#include "TextureBundleXBT.h" +- + #include "system.h" ++#include "TextureBundleXBT.h" + #include "Texture.h" + #include "GraphicContext.h" + #include "utils/log.h" ++#include "addons/Skin.h" + #include "settings/Settings.h" + #include "filesystem/SpecialProtocol.h" + #include "filesystem/XbtManager.h" + #include "utils/URIUtils.h" + #include "utils/StringUtils.h" + #include "XBTF.h" +-#include "XBTFReader.h" + #include + + #ifdef TARGET_WINDOWS +-#ifdef NDEBUG +-#pragma comment(lib,"lzo2.lib") +-#else +-#pragma comment(lib, "lzo2-no_idb.lib") +-#endif ++#pragma comment(lib,"liblzo2.lib") + #endif + + CTextureBundleXBT::CTextureBundleXBT(void) +- : m_TimeStamp{0} +- , m_themeBundle{false} + { ++ m_themeBundle = false; ++ m_TimeStamp = 0; + } + + CTextureBundleXBT::~CTextureBundleXBT(void) + { +- if (m_XBTFReader != nullptr && m_XBTFReader->IsOpen()) +- { +- XFILE::CXbtManager::GetInstance().Release(CURL(m_path)); +- CLog::Log(LOGDEBUG, "%s - Closed %sbundle", __FUNCTION__, m_themeBundle ? "theme " : ""); +- } ++ Cleanup(); + } + + bool CTextureBundleXBT::OpenBundle() + { ++ Cleanup(); ++ + // Find the correct texture file (skin or theme) + if (m_themeBundle) + { +@@ -245,6 +238,15 @@ bool CTextureBundleXBT::ConvertFrameToTexture(const std::string& name, CXBTFFram + return true; + } + ++void CTextureBundleXBT::Cleanup() ++{ ++ if (m_XBTFReader != nullptr && m_XBTFReader->IsOpen()) ++ { ++ XFILE::CXbtManager::GetInstance().Release(CURL(m_path)); ++ CLog::Log(LOGDEBUG, "%s - Closed %sbundle", __FUNCTION__, m_themeBundle ? "theme " : ""); ++ } ++} ++ + void CTextureBundleXBT::SetThemeBundle(bool themeBundle) + { + m_themeBundle = themeBundle; +diff --git a/xbmc/guilib/TextureBundleXBT.h b/xbmc/guilib/TextureBundleXBT.h +index 408ec5e..1c5c516 100644 +--- a/xbmc/guilib/TextureBundleXBT.h ++++ b/xbmc/guilib/TextureBundleXBT.h +@@ -21,20 +21,18 @@ + */ + + #include +-#include + #include +-#include ++#include "XBTFReader.h" + + class CBaseTexture; +-class CXBTFReader; +-class CXBTFFrame; + + class CTextureBundleXBT + { + public: +- CTextureBundleXBT(); +- ~CTextureBundleXBT(); ++ CTextureBundleXBT(void); ++ ~CTextureBundleXBT(void); + ++ void Cleanup(); + void SetThemeBundle(bool themeBundle); + bool HasFile(const std::string& Filename); + void GetTexturesFromPath(const std::string &path, std::vector &textures); +@@ -56,7 +54,7 @@ private: + + bool m_themeBundle; + std::string m_path; +- std::shared_ptr m_XBTFReader; ++ CXBTFReaderPtr m_XBTFReader; + }; + + +diff --git a/xbmc/guilib/TextureManager.cpp b/xbmc/guilib/TextureManager.cpp +index c1c5c8f..f47ef52 100644 +--- a/xbmc/guilib/TextureManager.cpp ++++ b/xbmc/guilib/TextureManager.cpp +@@ -540,7 +540,7 @@ void CGUITextureManager::Cleanup() + i = m_vecTextures.erase(i); + } + for (int i = 0; i < 2; i++) +- m_TexBundle[i] = CTextureBundle(); ++ m_TexBundle[i].Cleanup(); + FreeUnusedTextures(); + } + +diff --git a/xbmc/guilib/WindowIDs.h b/xbmc/guilib/WindowIDs.h +index fcfcc5d..74f2a0c 100644 +--- a/xbmc/guilib/WindowIDs.h ++++ b/xbmc/guilib/WindowIDs.h +@@ -27,16 +27,20 @@ + #define WINDOW_PICTURES 10002 + #define WINDOW_FILES 10003 + #define WINDOW_SETTINGS_MENU 10004 ++#define WINDOW_MUSIC 10005 // virtual window to return the music start window. ++#define WINDOW_VIDEOS 10006 + #define WINDOW_SYSTEM_INFORMATION 10007 + #define WINDOW_TEST_PATTERN 10008 + #define WINDOW_SCREEN_CALIBRATION 10011 + + #define WINDOW_SETTINGS_START 10016 + #define WINDOW_SETTINGS_SYSTEM 10016 +-#define WINDOW_SETTINGS_SERVICE 10018 ++#define WINDOW_SETTINGS_SERVICE 10018 // former (Eden) WINDOW_SETTINGS_NETWORK + ++#define WINDOW_SCRIPTS 10020 // virtual window for backward compatibility + #define WINDOW_SETTINGS_MYPVR 10021 + ++#define WINDOW_VIDEO_FILES 10024 + #define WINDOW_VIDEO_NAV 10025 + #define WINDOW_VIDEO_PLAYLIST 10028 + +@@ -102,6 +106,7 @@ + #define WINDOW_DIALOG_KEYBOARD_TOUCH 10156 + + #define WINDOW_MUSIC_PLAYLIST 10500 ++#define WINDOW_MUSIC_FILES 10501 + #define WINDOW_MUSIC_NAV 10502 + #define WINDOW_MUSIC_PLAYLIST_EDITOR 10503 + +diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp +index 7398fbf..1ff5435 100644 +--- a/xbmc/input/ButtonTranslator.cpp ++++ b/xbmc/input/ButtonTranslator.cpp +@@ -297,9 +297,12 @@ static const ActionMapping windows[] = + { "programs" , WINDOW_PROGRAMS }, + { "pictures" , WINDOW_PICTURES }, + { "filemanager" , WINDOW_FILES }, ++ { "files" , WINDOW_FILES }, // backward compat + { "settings" , WINDOW_SETTINGS_MENU }, +- { "music" , WINDOW_MUSIC_NAV }, ++ { "music" , WINDOW_MUSIC }, ++ { "video" , WINDOW_VIDEOS }, + { "videos" , WINDOW_VIDEO_NAV }, ++ { "pvr" , WINDOW_TV_CHANNELS }, // backward compat + { "tvchannels" , WINDOW_TV_CHANNELS }, + { "tvrecordings" , WINDOW_TV_RECORDINGS }, + { "tvguide" , WINDOW_TV_GUIDE }, +@@ -326,12 +329,18 @@ static const ActionMapping windows[] = + { "systeminfo" , WINDOW_SYSTEM_INFORMATION }, + { "testpattern" , WINDOW_TEST_PATTERN }, + { "screencalibration" , WINDOW_SCREEN_CALIBRATION }, ++ { "guicalibration" , WINDOW_SCREEN_CALIBRATION }, // backward compat + { "systemsettings" , WINDOW_SETTINGS_SYSTEM }, + { "servicesettings" , WINDOW_SETTINGS_SERVICE }, ++ { "networksettings" , WINDOW_SETTINGS_SERVICE }, // backward compat + { "pvrsettings" , WINDOW_SETTINGS_MYPVR }, ++ { "tvsettings" , WINDOW_SETTINGS_MYPVR }, // backward compat + { "playersettings" , WINDOW_SETTINGS_PLAYER }, + { "librarysettings" , WINDOW_SETTINGS_LIBRARY }, + { "interfacesettings" , WINDOW_SETTINGS_INTERFACE }, ++ { "scripts" , WINDOW_PROGRAMS }, // backward compat ++ { "videofiles" , WINDOW_VIDEO_FILES }, ++ { "videolibrary" , WINDOW_VIDEO_NAV }, + { "videoplaylist" , WINDOW_VIDEO_PLAYLIST }, + { "loginscreen" , WINDOW_LOGIN_SCREEN }, + { "profiles" , WINDOW_SETTINGS_PROFILES }, +@@ -345,6 +354,7 @@ static const ActionMapping windows[] = + { "favourites" , WINDOW_DIALOG_FAVOURITES }, + { "contextmenu" , WINDOW_DIALOG_CONTEXT_MENU }, + { "notification" , WINDOW_DIALOG_KAI_TOAST }, ++ { "infodialog" , WINDOW_DIALOG_KAI_TOAST }, // backward compat + { "numericinput" , WINDOW_DIALOG_NUMERIC }, + { "gamepadinput" , WINDOW_DIALOG_GAMEPAD }, + { "shutdownmenu" , WINDOW_DIALOG_BUTTON_MENU }, +@@ -352,6 +362,7 @@ static const ActionMapping windows[] = + { "seekbar" , WINDOW_DIALOG_SEEK_BAR }, + { "musicosd" , WINDOW_DIALOG_MUSIC_OSD }, + { "addonsettings" , WINDOW_DIALOG_ADDON_SETTINGS }, ++ { "visualisationsettings" , WINDOW_DIALOG_ADDON_SETTINGS }, // backward compat + { "visualisationpresetlist" , WINDOW_DIALOG_VIS_PRESET_LIST }, + { "osdvideosettings" , WINDOW_DIALOG_VIDEO_OSD_SETTINGS }, + { "osdaudiosettings" , WINDOW_DIALOG_AUDIO_OSD_SETTINGS }, +@@ -375,6 +386,8 @@ static const ActionMapping windows[] = + { "addoninformation" , WINDOW_DIALOG_ADDON_INFO }, + { "subtitlesearch" , WINDOW_DIALOG_SUBTITLES }, + { "musicplaylist" , WINDOW_MUSIC_PLAYLIST }, ++ { "musicfiles" , WINDOW_MUSIC_FILES }, ++ { "musiclibrary" , WINDOW_MUSIC_NAV }, + { "musicplaylisteditor" , WINDOW_MUSIC_PLAYLIST_EDITOR }, + { "teletext" , WINDOW_DIALOG_OSD_TELETEXT }, + { "selectdialog" , WINDOW_DIALOG_SELECT }, +diff --git a/xbmc/input/InputCodingTableBaiduPY.h b/xbmc/input/InputCodingTableBaiduPY.h +index 3f7c3bb..032d398 100644 +--- a/xbmc/input/InputCodingTableBaiduPY.h ++++ b/xbmc/input/InputCodingTableBaiduPY.h +@@ -22,9 +22,6 @@ + + #include + #include +-#include +-#include +- + #include "InputCodingTable.h" + #include "threads/Thread.h" + +diff --git a/xbmc/input/InputCodingTableBasePY.h b/xbmc/input/InputCodingTableBasePY.h +index 10a5463..7d9f6da 100644 +--- a/xbmc/input/InputCodingTableBasePY.h ++++ b/xbmc/input/InputCodingTableBasePY.h +@@ -23,7 +23,6 @@ + #include "InputCodingTable.h" + #include + #include +-#include + + class CInputCodingTableBasePY : public IInputCodingTable + { +diff --git a/xbmc/input/InputCodingTableKorean.h b/xbmc/input/InputCodingTableKorean.h +index 7cff581..d2d3d9b 100644 +--- a/xbmc/input/InputCodingTableKorean.h ++++ b/xbmc/input/InputCodingTableKorean.h +@@ -23,7 +23,6 @@ + #include "InputCodingTable.h" + #include + #include +-#include + + class CInputCodingTableKorean : public IInputCodingTable + { +diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp +index 009a16e..b88599e 100644 +--- a/xbmc/input/InputManager.cpp ++++ b/xbmc/input/InputManager.cpp +@@ -88,7 +88,7 @@ void CInputManager::InitializeInputs() + + void CInputManager::SetEnabledJoystick(bool enabled /* = true */) + { +- //! @todo ++ // TODO + } + + bool CInputManager::ProcessRemote(int windowId) +diff --git a/xbmc/input/KeyboardLayoutManager.h b/xbmc/input/KeyboardLayoutManager.h +index cfe7ad9..351eb93 100644 +--- a/xbmc/input/KeyboardLayoutManager.h ++++ b/xbmc/input/KeyboardLayoutManager.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + + #include "input/KeyboardLayout.h" + +diff --git a/xbmc/input/joysticks/DefaultJoystick.cpp b/xbmc/input/joysticks/DefaultJoystick.cpp +index 7fddefa..ffd45f9 100644 +--- a/xbmc/input/joysticks/DefaultJoystick.cpp ++++ b/xbmc/input/joysticks/DefaultJoystick.cpp +@@ -110,7 +110,7 @@ bool CDefaultJoystick::OnAnalogStickMotion(const FeatureName& feature, float x, + + bool CDefaultJoystick::OnAccelerometerMotion(const FeatureName& feature, float x, float y, float z) + { +- return false; //! @todo implement ++ return false; // TODO + } + + bool CDefaultJoystick::ActivateDirection(const FeatureName& feature, float magnitude, CARDINAL_DIRECTION dir) +@@ -193,7 +193,7 @@ unsigned int CDefaultJoystick::GetKeyID(const FeatureName& feature, CARDINAL_DIR + break; + } + } +- else if (feature == "accelerometer") return 0; //! @todo implement ++ else if (feature == "accelerometer") return 0; // TODO + + return 0; + } +diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp +index 3875138..1da2986 100644 +--- a/xbmc/input/linux/LinuxInputDevices.cpp ++++ b/xbmc/input/linux/LinuxInputDevices.cpp +@@ -30,6 +30,10 @@ + #include "system.h" + #if defined(HAS_LINUX_EVENTS) + ++#if defined(HAS_LIBAMCODEC) ++#include "utils/AMLUtils.h" ++#endif ++ + #include + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +@@ -1241,6 +1245,17 @@ void CLinuxInputDevices::InitAvailable() + } + } + ++void CLinuxInputDevices::Close() ++{ ++ CSingleLock lock(m_devicesListLock); ++ ++ for (size_t i = 0; i < m_devices.size(); i++) ++ { ++ delete m_devices[i]; ++ } ++ m_devices.clear(); ++} ++ + /* + * Check for hot plugged devices. + */ +diff --git a/xbmc/input/linux/LinuxInputDevices.h b/xbmc/input/linux/LinuxInputDevices.h +index 44a05fe..409bc2e 100644 +--- a/xbmc/input/linux/LinuxInputDevices.h ++++ b/xbmc/input/linux/LinuxInputDevices.h +@@ -96,6 +96,7 @@ class CLinuxInputDevices + { + public: + void InitAvailable(); ++ void Close(); + void CheckHotplugged(); + XBMC_Event ReadEvent(); + bool IsRemoteLowBattery(); +diff --git a/xbmc/interfaces/AnnouncementManager.cpp b/xbmc/interfaces/AnnouncementManager.cpp +index 7e693aa..41272ea 100644 +--- a/xbmc/interfaces/AnnouncementManager.cpp ++++ b/xbmc/interfaces/AnnouncementManager.cpp +@@ -165,7 +165,7 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag, const char *sender, + { + id = item->GetVideoInfoTag()->m_iDbId; + +- //! @todo Can be removed once this is properly handled when starting playback of a file ++ // TODO: Can be removed once this is properly handled when starting playback of a file + if (id <= 0 && !item->GetPath().empty() && + (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) + { +@@ -190,7 +190,7 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag, const char *sender, + + if (id <= 0) + { +- //! @todo Can be removed once this is properly handled when starting playback of a file ++ // TODO: Can be removed once this is properly handled when starting playback of a file + item->SetProperty(LOOKUP_PROPERTY, false); + + std::string title = item->GetVideoInfoTag()->m_strTitle; +@@ -201,8 +201,8 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag, const char *sender, + switch (item->GetVideoContentType()) + { + case VIDEODB_CONTENT_MOVIES: +- if (item->GetVideoInfoTag()->HasYear()) +- object["item"]["year"] = item->GetVideoInfoTag()->GetYear(); ++ if (item->GetVideoInfoTag()->m_iYear > 0) ++ object["item"]["year"] = item->GetVideoInfoTag()->m_iYear; + break; + case VIDEODB_CONTENT_EPISODES: + if (item->GetVideoInfoTag()->m_iEpisode >= 0) +@@ -226,7 +226,7 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag, const char *sender, + id = item->GetMusicInfoTag()->GetDatabaseId(); + type = MediaTypeSong; + +- //! @todo Can be removed once this is properly handled when starting playback of a file ++ // TODO: Can be removed once this is properly handled when starting playback of a file + if (id <= 0 && !item->GetPath().empty() && + (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean())) + { +@@ -246,7 +246,7 @@ void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag, const char *sender, + + if (id <= 0) + { +- //! @todo Can be removed once this is properly handled when starting playback of a file ++ // TODO: Can be removed once this is properly handled when starting playback of a file + item->SetProperty(LOOKUP_PROPERTY, false); + + std::string title = item->GetMusicInfoTag()->GetTitle(); +diff --git a/xbmc/interfaces/IActionListener.h b/xbmc/interfaces/IActionListener.h +index a612c59..84225ab 100644 +--- a/xbmc/interfaces/IActionListener.h ++++ b/xbmc/interfaces/IActionListener.h +@@ -20,7 +20,7 @@ + * + */ + +-class CAction; ++#include "input/Key.h" + + class IActionListener + { +diff --git a/xbmc/interfaces/IAnnouncer.h b/xbmc/interfaces/IAnnouncer.h +index e3dfdd1..3284590 100644 +--- a/xbmc/interfaces/IAnnouncer.h ++++ b/xbmc/interfaces/IAnnouncer.h +@@ -33,10 +33,11 @@ namespace ANNOUNCEMENT + Application = 0x040, + Input = 0x080, + PVR = 0x100, +- Other = 0x200 ++ Other = 0x200, ++ Network = 0x400 + }; + +- #define ANNOUNCE_ALL (Player | Playlist | GUI | System | VideoLibrary | AudioLibrary | Application | Input | ANNOUNCEMENT::PVR | Other) ++ #define ANNOUNCE_ALL (Player | Playlist | GUI | System | VideoLibrary | AudioLibrary | Application | Input | ANNOUNCEMENT::PVR | Other | Network) + + /*! + \brief Returns a string representation for the +@@ -68,6 +69,8 @@ namespace ANNOUNCEMENT + return "PVR"; + case Other: + return "Other"; ++ case Network: ++ return "Network"; + default: + return "Unknown"; + } +diff --git a/xbmc/interfaces/builtins/AddonBuiltins.cpp b/xbmc/interfaces/builtins/AddonBuiltins.cpp +index 446fc97..5012324 100644 +--- a/xbmc/interfaces/builtins/AddonBuiltins.cpp ++++ b/xbmc/interfaces/builtins/AddonBuiltins.cpp +@@ -275,8 +275,8 @@ static int AddonSettings(const std::vector& params) + */ + static int StopScript(const std::vector& params) + { +- //! @todo FIXME: This does not work for addons with multiple extension points! +- //! Are there any use for this? TODO: Fix hack in CScreenSaver::Destroy() and deprecate. ++ // FIXME: This does not work for addons with multiple extension points! ++ // Are there any use for this? TODO: Fix hack in CScreenSaver::Destroy() and deprecate. + std::string scriptpath(params[0]); + // Test to see if the param is an addon ID + AddonPtr script; +diff --git a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp +index 86be03f..e9a41ae 100644 +--- a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp ++++ b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp +@@ -21,12 +21,9 @@ + #include "ApplicationBuiltins.h" + + #include "Application.h" +-#ifdef HAS_FILESYSTEM_RAR + #include "filesystem/RarManager.h" +-#endif + #include "filesystem/ZipManager.h" + #include "messaging/ApplicationMessenger.h" +-#include "input/Key.h" + #include "interfaces/AnnouncementManager.h" + #include "network/Network.h" + #include "settings/AdvancedSettings.h" +diff --git a/xbmc/interfaces/builtins/GUIBuiltins.cpp b/xbmc/interfaces/builtins/GUIBuiltins.cpp +index ccee9af..a15dbbb 100644 +--- a/xbmc/interfaces/builtins/GUIBuiltins.cpp ++++ b/xbmc/interfaces/builtins/GUIBuiltins.cpp +@@ -25,7 +25,6 @@ + #include "dialogs/GUIDialogKaiToast.h" + #include "dialogs/GUIDialogNumeric.h" + #include "filesystem/Directory.h" +-#include "input/Key.h" + #include "guilib/GUIWindowManager.h" + #include "guilib/LocalizeStrings.h" + #include "guilib/StereoscopicsManager.h" +diff --git a/xbmc/interfaces/builtins/GUIControlBuiltins.cpp b/xbmc/interfaces/builtins/GUIControlBuiltins.cpp +index e503230..4bc8b64 100644 +--- a/xbmc/interfaces/builtins/GUIControlBuiltins.cpp ++++ b/xbmc/interfaces/builtins/GUIControlBuiltins.cpp +@@ -52,8 +52,8 @@ static int SendClick(const std::vector& params) + g_windowManager.SendMessage(message); + } + else +- { // single param - assume you meant the focused window +- CGUIMessage message(GUI_MSG_CLICKED, atoi(params[0].c_str()), g_windowManager.GetFocusedWindow()); ++ { // single param - assume you meant the active window ++ CGUIMessage message(GUI_MSG_CLICKED, atoi(params[0].c_str()), g_windowManager.GetActiveWindow()); + g_windowManager.SendMessage(message); + } + +diff --git a/xbmc/interfaces/builtins/PlayerBuiltins.cpp b/xbmc/interfaces/builtins/PlayerBuiltins.cpp +index a97f5ce..2de9975 100644 +--- a/xbmc/interfaces/builtins/PlayerBuiltins.cpp ++++ b/xbmc/interfaces/builtins/PlayerBuiltins.cpp +@@ -424,7 +424,7 @@ static int PlayMedia(const std::vector& params) + break; + } + +- std::unique_ptr state(CGUIViewState::GetViewState(containsVideo ? WINDOW_VIDEO_NAV : WINDOW_MUSIC_NAV, items)); ++ std::unique_ptr state(CGUIViewState::GetViewState(containsVideo ? WINDOW_VIDEO_NAV : WINDOW_MUSIC, items)); + if (state.get()) + items.Sort(state->GetSortMethod()); + else +diff --git a/xbmc/interfaces/builtins/SystemBuiltins.cpp b/xbmc/interfaces/builtins/SystemBuiltins.cpp +index a3b568e..e6976be 100644 +--- a/xbmc/interfaces/builtins/SystemBuiltins.cpp ++++ b/xbmc/interfaces/builtins/SystemBuiltins.cpp +@@ -142,6 +142,12 @@ static int Suspend(const std::vector& params) + return 0; + } + ++static int ChangeVT(const std::vector& params) ++{ ++ CApplicationMessenger::GetInstance().PostMsg(TMSG_CHANGEVT, atoi(params[0].c_str())); ++ ++ return 0; ++} + + // Note: For new Texts with comma add a "\" before!!! Is used for table text. + // +@@ -246,6 +252,7 @@ CBuiltins::CommandMap CSystemBuiltins::GetOperations() const + {"shutdown", {"Shutdown the system", 0, Shutdown}}, + {"suspend", {"Suspends the system", 0, Suspend}}, + {"system.exec", {"Execute shell commands", 1, Exec<0>}}, +- {"system.execwait", {"Execute shell commands and freezes Kodi until shell is closed", 1, Exec<1>}} ++ {"system.execwait", {"Execute shell commands and freezes Kodi until shell is closed", 1, Exec<1>}}, ++ {"changevt", {"Change active VT", 1, ChangeVT}} + }; + } +diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.h b/xbmc/interfaces/generic/LanguageInvokerThread.h +index 65a7765..b3bf52e 100644 +--- a/xbmc/interfaces/generic/LanguageInvokerThread.h ++++ b/xbmc/interfaces/generic/LanguageInvokerThread.h +@@ -19,9 +19,6 @@ + * + */ + +-#include +-#include +- + #include "interfaces/generic/ILanguageInvoker.h" + #include "threads/Thread.h" + +diff --git a/xbmc/interfaces/generic/ScriptInvocationManager.h b/xbmc/interfaces/generic/ScriptInvocationManager.h +index aa5a162..a9ebc9c 100644 +--- a/xbmc/interfaces/generic/ScriptInvocationManager.h ++++ b/xbmc/interfaces/generic/ScriptInvocationManager.h +@@ -20,9 +20,8 @@ + */ + + #include +-#include + #include +-#include ++#include + + #include "addons/IAddon.h" + #include "interfaces/generic/ILanguageInvoker.h" +diff --git a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp +index 749c670..3ab538e 100644 +--- a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp ++++ b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp +@@ -24,7 +24,6 @@ + #include "messaging/ApplicationMessenger.h" + #include "FileItem.h" + #include "Util.h" +-#include "input/Key.h" + #include "utils/log.h" + #include "GUIInfoManager.h" + #include "system.h" +diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.h b/xbmc/interfaces/json-rpc/AudioLibrary.h +index 6b4a2dd..33c05de 100644 +--- a/xbmc/interfaces/json-rpc/AudioLibrary.h ++++ b/xbmc/interfaces/json-rpc/AudioLibrary.h +@@ -20,8 +20,6 @@ + */ + + #include +-#include +-#include + + #include "JSONRPC.h" + #include "FileItemHandler.h" +diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp +index ac24843..ed381a8 100644 +--- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp ++++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp +@@ -399,7 +399,7 @@ bool CFileItemHandler::FillFileItemList(const CVariant ¶meterObject, CFileIt + bool added = false; + for (int index = 0; index < list.Size(); index++) + { +- if (list[index]->GetPath() == file || list[index]->GetMusicInfoTag()->GetURL() == file || list[index]->GetVideoInfoTag()->GetPath() == file) ++ if (list[index]->GetPath() == file) + { + added = true; + break; +diff --git a/xbmc/interfaces/json-rpc/InputOperations.cpp b/xbmc/interfaces/json-rpc/InputOperations.cpp +index 1166471..d70c6e6 100644 +--- a/xbmc/interfaces/json-rpc/InputOperations.cpp ++++ b/xbmc/interfaces/json-rpc/InputOperations.cpp +@@ -26,7 +26,6 @@ + #include "guilib/GUIWindowManager.h" + #include "guilib/GUIKeyboardFactory.h" + #include "input/ButtonTranslator.h" +-#include "input/Key.h" + #include "utils/Variant.h" + #include "input/XBMC_keyboard.h" + #include "input/XBMC_vkeys.h" +@@ -35,9 +34,9 @@ + using namespace JSONRPC; + using namespace KODI::MESSAGING; + +-//! @todo the breakage of the screensaver should be refactored +-//! to one central super duper place for getting rid of +-//! 1 million dupes ++//TODO the breakage of the screensaver should be refactored ++//to one central super duper place for getting rid of ++//1 million dupes + bool CInputOperations::handleScreenSaver() + { + g_application.ResetScreenSaver(); +diff --git a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp +index 1690be5..17a222a 100644 +--- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp ++++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp +@@ -123,7 +123,6 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = { + + // Video Library + { "VideoLibrary.GetGenres", CVideoLibrary::GetGenres }, +- { "VideoLibrary.GetTags", CVideoLibrary::GetTags }, + { "VideoLibrary.GetMovies", CVideoLibrary::GetMovies }, + { "VideoLibrary.GetMovieDetails", CVideoLibrary::GetMovieDetails }, + { "VideoLibrary.GetMovieSets", CVideoLibrary::GetMovieSets }, +diff --git a/xbmc/interfaces/json-rpc/JSONUtils.h b/xbmc/interfaces/json-rpc/JSONUtils.h +index 0e1cd1c..a3c9a0b 100644 +--- a/xbmc/interfaces/json-rpc/JSONUtils.h ++++ b/xbmc/interfaces/json-rpc/JSONUtils.h +@@ -21,7 +21,6 @@ + + #include + #include +-#include + + #include "JSONRPCUtils.h" + #include "XBDateTime.h" +diff --git a/xbmc/interfaces/json-rpc/SettingsOperations.h b/xbmc/interfaces/json-rpc/SettingsOperations.h +index c4680ae..c221129 100644 +--- a/xbmc/interfaces/json-rpc/SettingsOperations.h ++++ b/xbmc/interfaces/json-rpc/SettingsOperations.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "JSONRPC.h" + + class CVariant; +diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp +index c9067a7..cf1393e 100644 +--- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp ++++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp +@@ -478,47 +478,6 @@ JSONRPC_STATUS CVideoLibrary::GetGenres(const std::string &method, ITransportLay + return OK; + } + +-JSONRPC_STATUS CVideoLibrary::GetTags(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) +-{ +- std::string media = parameterObject["type"].asString(); +- StringUtils::ToLower(media); +- int idContent = -1; +- +- std::string strPath = "videodb://"; +- /* select which video content to get tags from*/ +- if (media == MediaTypeMovie) +- { +- idContent = VIDEODB_CONTENT_MOVIES; +- strPath += "movies"; +- } +- else if (media == MediaTypeTvShow) +- { +- idContent = VIDEODB_CONTENT_TVSHOWS; +- strPath += "tvshows"; +- } +- else if (media == MediaTypeMusicVideo) +- { +- idContent = VIDEODB_CONTENT_MUSICVIDEOS; +- strPath += "musicvideos"; +- } +- strPath += "/tags/"; +- +- CVideoDatabase videodatabase; +- if (!videodatabase.Open()) +- return InternalError; +- +- CFileItemList items; +- if (!videodatabase.GetTagsNav(strPath, items, idContent)) +- return InternalError; +- +- /* need to set strTitle in each item*/ +- for (int i = 0; i < items.Size(); i++) +- items[i]->GetVideoInfoTag()->m_strTitle = items[i]->GetLabel(); +- +- HandleFileItemList("tagid", false, "tags", items, parameterObject, result); +- return OK; +-} +- + JSONRPC_STATUS CVideoLibrary::SetMovieDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) + { + int id = (int)parameterObject["movieid"].asInteger(); +@@ -528,7 +487,7 @@ JSONRPC_STATUS CVideoLibrary::SetMovieDetails(const std::string &method, ITransp + return InternalError; + + CVideoInfoTag infos; +- if (!videodatabase.GetMovieInfo("", infos, id, RequiresInitialDetails(parameterObject)) || infos.m_iDbId <= 0) ++ if (!videodatabase.GetMovieInfo("", infos, id) || infos.m_iDbId <= 0) + return InvalidParams; + + // get artwork +@@ -605,7 +564,7 @@ JSONRPC_STATUS CVideoLibrary::SetTVShowDetails(const std::string &method, ITrans + return InternalError; + + CVideoInfoTag infos; +- if (!videodatabase.GetTvShowInfo("", infos, id, (CFileItem *)0, RequiresInitialDetails(parameterObject)) || infos.m_iDbId <= 0) ++ if (!videodatabase.GetTvShowInfo("", infos, id) || infos.m_iDbId <= 0) + return InvalidParams; + + // get artwork +@@ -676,7 +635,7 @@ JSONRPC_STATUS CVideoLibrary::SetEpisodeDetails(const std::string &method, ITran + return InternalError; + + CVideoInfoTag infos; +- videodatabase.GetEpisodeInfo("", infos, id, RequiresInitialDetails(parameterObject)); ++ videodatabase.GetEpisodeInfo("", infos, id); + if (infos.m_iDbId <= 0) + { + videodatabase.Close(); +@@ -988,14 +947,6 @@ bool CVideoLibrary::FillFileItemList(const CVariant ¶meterObject, CFileItemL + return success; + } + +-int CVideoLibrary::RequiresInitialDetails(const CVariant ¶meterObject) +-{ +- int details = VideoDbDetailsNone; +- if (ParameterNotNull(parameterObject, "ratings") || ParameterNotNull(parameterObject, "rating") || ParameterNotNull(parameterObject, "votes")) +- return VideoDbDetailsRating; +- return details; +-} +- + int CVideoLibrary::RequiresAdditionalDetails(const MediaType& mediaType, const CVariant ¶meterObject) + { + if (mediaType != MediaTypeMovie && mediaType != MediaTypeTvShow && mediaType != MediaTypeEpisode && mediaType != MediaTypeMusicVideo) +@@ -1097,6 +1048,8 @@ void CVideoLibrary::UpdateVideoTag(const CVariant ¶meterObject, CVideoInfoTa + UpdateVideoTagField(parameterObject, "studio", studio, updatedDetails); + details.SetStudio(studio); + ++ if (ParameterNotNull(parameterObject, "year")) ++ details.m_iYear = (int)parameterObject["year"].asInteger(); + if (ParameterNotNull(parameterObject, "plot")) + details.SetPlot(parameterObject["plot"].asString()); + if (ParameterNotNull(parameterObject, "album")) +@@ -1127,22 +1080,14 @@ void CVideoLibrary::UpdateVideoTag(const CVariant ¶meterObject, CVideoInfoTa + CVariant ratings = parameterObject["ratings"]; + for (CVariant::const_iterator_map rIt = ratings.begin_map(); rIt != ratings.end_map(); rIt++) + { +- if (rIt->second.isObject() && ParameterNotNull(rIt->second, "rating")) ++ if (rIt->second.isArray() && ParameterNotNull(rIt->second, "name") && ParameterNotNull(rIt->second, "rating")) + { +- const auto& rating = rIt->second; +- if (ParameterNotNull(rating, "votes")) +- details.AddRating(rating["rating"].asFloat(), rating["votes"].asFloat(), rIt->first, (ParameterNotNull(rating, "default") && rating["default"].asBoolean())); +- else +- details.SetRating(rating["rating"].asFloat(), rIt->first, (ParameterNotNull(rating, "default") && rating["default"].asBoolean())); +- +- updatedDetails.insert("ratings"); +- } +- else if (rIt->second.isNull()) +- { +- details.RemoveRating(rIt->first); +- updatedDetails.insert("ratings"); ++ details.SetRating(rIt->second["rating"].asFloat(), rIt->second["name"].asString()); ++ if (ParameterNotNull(rIt->second, "votes")) ++ details.SetVotes(StringUtils::ReturnDigits(parameterObject["votes"].asString()), rIt->second["name"].asString()); + } + } ++ updatedDetails.insert("ratings"); + } + if (ParameterNotNull(parameterObject, "userrating")) + details.m_iUserRating = parameterObject["userrating"].asInteger(); +@@ -1151,13 +1096,7 @@ void CVideoLibrary::UpdateVideoTag(const CVariant ¶meterObject, CVideoInfoTa + if (ParameterNotNull(parameterObject, "imdbnumber")) + details.SetIMDBNumber(parameterObject["imdbnumber"].asString()); + if (ParameterNotNull(parameterObject, "premiered")) +- { +- CDateTime premiered; +- SetFromDBDate(parameterObject["premiered"], premiered); +- details.SetPremiered(premiered); +- } +- else if (ParameterNotNull(parameterObject, "year")) +- details.SetYear((int)parameterObject["year"].asInteger()); ++ SetFromDBDate(parameterObject["premiered"], details.m_premiered); + if (ParameterNotNull(parameterObject, "lastplayed")) + SetFromDBDateTime(parameterObject["lastplayed"], details.m_lastPlayed); + if (ParameterNotNull(parameterObject, "firstaired")) +diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.h b/xbmc/interfaces/json-rpc/VideoLibrary.h +index efe9d5c..e466de3 100644 +--- a/xbmc/interfaces/json-rpc/VideoLibrary.h ++++ b/xbmc/interfaces/json-rpc/VideoLibrary.h +@@ -19,9 +19,6 @@ + * + */ + +-#include +-#include +- + #include "utils/DatabaseUtils.h" + #include "JSONRPC.h" + #include "FileItemHandler.h" +@@ -55,7 +52,6 @@ namespace JSONRPC + static JSONRPC_STATUS GetInProgressTVShows(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + + static JSONRPC_STATUS GetGenres(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); +- static JSONRPC_STATUS GetTags(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + + static JSONRPC_STATUS SetMovieDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + static JSONRPC_STATUS SetMovieSetDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); +@@ -84,7 +80,6 @@ namespace JSONRPC + + private: + static int RequiresAdditionalDetails(const MediaType& mediaType, const CVariant ¶meterObject); +- static int RequiresInitialDetails(const CVariant ¶meterObject); + static JSONRPC_STATUS HandleItems(const char *idProperty, const char *resultName, CFileItemList &items, const CVariant ¶meterObject, CVariant &result, bool limit = true); + static JSONRPC_STATUS RemoveVideo(const CVariant ¶meterObject); + static void UpdateVideoTag(const CVariant ¶meterObject, CVideoInfoTag &details, std::map &artwork, std::set &removedArtwork, std::set& updatedDetails); +diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json +index e4897ef..bd0eab3 100644 +--- a/xbmc/interfaces/json-rpc/schema/methods.json ++++ b/xbmc/interfaces/json-rpc/schema/methods.json +@@ -1434,27 +1434,6 @@ + } + } + }, +- "VideoLibrary.GetTags": { +- "type": "method", +- "description": "Retrieve all tags", +- "transport": "Response", +- "permission": "ReadData", +- "params": [ +- { "name": "type", "type": "string", "required": true, "enum": [ "movie", "tvshow", "musicvideo" ] }, +- { "name": "properties", "$ref": "Library.Fields.Tag" }, +- { "name": "limits", "$ref": "List.Limits" }, +- { "name": "sort", "$ref": "List.Sort" } +- ], +- "returns": { +- "type": "object", +- "properties": { +- "limits": { "$ref": "List.LimitsReturned", "required": true }, +- "tags": { "type": "array", "required": true, +- "items": { "$ref": "Library.Details.Tag" } +- } +- } +- } +- }, + "VideoLibrary.SetMovieDetails": { + "type": "method", + "description": "Update the given movie with the given details", +@@ -1467,7 +1446,7 @@ + { "name": "runtime", "$ref": "Optional.Integer", "description": "Runtime in seconds" }, + { "name": "director", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, + { "name": "studio", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, +- { "name": "year", "$ref": "Optional.Integer", "description": "linked with premiered. Overridden by premiered parameter" }, ++ { "name": "year", "$ref": "Optional.Integer" }, + { "name": "plot", "$ref": "Optional.String" }, + { "name": "genre", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, + { "name": "rating", "$ref": "Optional.Number" }, +@@ -1491,9 +1470,8 @@ + { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null }, + { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null }, + { "name": "userrating", "$ref": "Optional.Integer" }, +- { "name": "ratings", "$ref": "Video.Ratings.Set" }, +- { "name": "dateadded", "$ref": "Optional.String" }, +- { "name": "premiered", "$ref": "Optional.String", "description": "linked with year. Overriedes year" } ++ { "name": "ratings", "$ref": "Video.Ratings" }, ++ { "name": "dateadded", "$ref": "Optional.String" } + ], + "returns": "string" + }, +@@ -1535,7 +1513,7 @@ + { "name": "tag", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, + { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null }, + { "name": "userrating", "$ref": "Optional.Integer" }, +- { "name": "ratings", "$ref": "Video.Ratings.Set" }, ++ { "name": "ratings", "$ref": "Video.Ratings" }, + { "name": "dateadded", "$ref": "Optional.String" }, + { "name": "runtime", "$ref": "Optional.Integer", "description": "Runtime in seconds" }, + { "name": "status", "$ref": "Optional.String" } +@@ -1580,7 +1558,7 @@ + { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null }, + { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null }, + { "name": "userrating", "$ref": "Optional.Integer" }, +- { "name": "ratings", "$ref": "Video.Ratings.Set" }, ++ { "name": "ratings", "$ref": "Video.Ratings" }, + { "name": "dateadded", "$ref": "Optional.String" } + ], + "returns": "string" +@@ -1597,7 +1575,7 @@ + { "name": "runtime", "$ref": "Optional.Integer", "description": "Runtime in seconds" }, + { "name": "director", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, + { "name": "studio", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, +- { "name": "year", "$ref": "Optional.Integer", "description": "linked with premiered. Overridden by premiered parameter" }, ++ { "name": "year", "$ref": "Optional.Integer" }, + { "name": "plot", "$ref": "Optional.String" }, + { "name": "album", "$ref": "Optional.String" }, + { "name": "artist", "type": [ "null", { "$ref": "Array.String", "required": true } ] }, +@@ -1611,8 +1589,7 @@ + { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null }, + { "name": "rating", "$ref": "Optional.Number" }, + { "name": "userrating", "$ref": "Optional.Integer" }, +- { "name": "dateadded", "$ref": "Optional.String" }, +- { "name": "premiered", "$ref": "Optional.String", "description": "linked with year. Overriedes year" } ++ { "name": "dateadded", "$ref": "Optional.String" } + ], + "returns": "string" + }, +diff --git a/xbmc/interfaces/json-rpc/schema/types.json b/xbmc/interfaces/json-rpc/schema/types.json +index 6264dea..c7211d9 100644 +--- a/xbmc/interfaces/json-rpc/schema/types.json ++++ b/xbmc/interfaces/json-rpc/schema/types.json +@@ -392,22 +392,6 @@ + }, + "additionalProperties": { "type": [ "null", { "$ref": "Global.String.NotEmpty", "required": true } ] } + }, +- "Video.Rating": { +- "type": "object", +- "properties": { +- "rating": { "type": "number", "required": true }, +- "votes": { "type": "integer" }, +- "default": { "type": "boolean" } +- } +- }, +- "Video.Ratings": { +- "type": "object", +- "additionalProperties": { "$ref": "Video.Rating" } +- }, +- "Video.Ratings.Set": { +- "type": "object", +- "additionalProperties": { "type": [ "null", { "$ref": "Video.Rating", "required": true } ] } +- }, + "Library.Fields.Genre": { + "extends": "Item.Fields.Base", + "items": { "type": "string", "enum": [ "title", "thumbnail" ] } +@@ -420,17 +404,6 @@ + "thumbnail": { "type": "string" } + } + }, +- "Library.Fields.Tag": { +- "extends": "Item.Fields.Base", +- "items": { "type": "string", "enum": [ "title" ] } +- }, +- "Library.Details.Tag": { +- "extends": "Item.Details.Base", +- "properties": { +- "tagid": { "$ref": "Library.Id", "required": true }, +- "title": { "type": "string" } +- } +- }, + "Audio.Fields.Role": { + "extends": "Item.Fields.Base", + "items": { "type": "string", "enum": [ "title" ] } +@@ -624,7 +597,7 @@ + "playcount", "writer", "studio", "mpaa", "cast", "country", + "imdbnumber", "runtime", "set", "showlink", "streamdetails", + "top250", "votes", "fanart", "thumbnail", "file", "sorttitle", +- "resume", "setid", "dateadded", "tag", "art", "userrating", "ratings", "premiered" ] ++ "resume", "setid", "dateadded", "tag", "art", "userrating", "ratings" ] + } + }, + "Video.Fields.MovieSet": { +@@ -673,7 +646,7 @@ + "studio", "year", "plot", "album", "artist", + "genre", "track", "streamdetails", "lastplayed", + "fanart", "thumbnail", "file", "resume", "dateadded", +- "tag", "art", "rating", "userrating", "premiered" ] ++ "tag", "art", "rating", "userrating" ] + } + }, + "Video.Cast": { +@@ -688,6 +661,18 @@ + "additionalProperties": false + } + }, ++ "Video.Ratings": { ++ "type": "array", ++ "items": { "type": "object", ++ "properties": { ++ "name": { "type": "string", "required": true }, ++ "rating": { "type": "number", "required": true }, ++ "votes": { "type": "integer" }, ++ "default": { "type": "boolean" } ++ }, ++ "additionalProperties": false ++ } ++ }, + "Video.Streams": { + "type": "object", + "properties": { +@@ -788,8 +773,7 @@ + "setid": { "$ref": "Library.Id" }, + "tag": { "$ref": "Array.String" }, + "userrating": { "type": "integer" }, +- "ratings": { "type": "Video.Ratings" }, +- "premiered": { "type": "string" } ++ "ratings": { "type": "Video.Ratings" } + } + }, + "Video.Details.MovieSet": { +@@ -880,8 +864,7 @@ + "track": { "type": "integer" }, + "tag": { "$ref": "Array.String" }, + "rating": { "type": "number" }, +- "userrating": { "type": "integer" }, +- "premiered": { "type": "string" } ++ "userrating": { "type": "integer" } + } + }, + "PVR.Property.Name": { +diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt +index ee0a997..30338c7 100644 +--- a/xbmc/interfaces/json-rpc/schema/version.txt ++++ b/xbmc/interfaces/json-rpc/schema/version.txt +@@ -1 +1 @@ +-7.16.0 +\ No newline at end of file ++7.13.2 +diff --git a/xbmc/interfaces/legacy/CallbackHandler.h b/xbmc/interfaces/legacy/CallbackHandler.h +index db5a56f..4199b34 100644 +--- a/xbmc/interfaces/legacy/CallbackHandler.h ++++ b/xbmc/interfaces/legacy/CallbackHandler.h +@@ -47,8 +47,8 @@ namespace XBMCAddon + * messages over to a language controlled thread for eventual + * execution. + * +- * @todo Allow a cross thread synchronous execution. +- * Fix the stupid means of calling the clearPendingCalls by passing ++ * TODO: Allow a cross thread synchronous execution. ++ * TODO: Fix the stupid means of calling the clearPendingCalls by passing + * userData which is specific to the handler/language type. + */ + class RetardedAsynchCallbackHandler : public CallbackHandler +diff --git a/xbmc/interfaces/legacy/Control.h b/xbmc/interfaces/legacy/Control.h +index ac7b848..7da4249 100644 +--- a/xbmc/interfaces/legacy/Control.h ++++ b/xbmc/interfaces/legacy/Control.h +@@ -20,8 +20,6 @@ + + #pragma once + +-#include +- + #include "guilib/GUIControl.h" + #include "guilib/GUIFont.h" + #include "input/Key.h" +diff --git a/xbmc/interfaces/legacy/InfoTagMusic.cpp b/xbmc/interfaces/legacy/InfoTagMusic.cpp +index 8ee24c1..6b6e416 100644 +--- a/xbmc/interfaces/legacy/InfoTagMusic.cpp ++++ b/xbmc/interfaces/legacy/InfoTagMusic.cpp +@@ -77,16 +77,6 @@ namespace XBMCAddon + return infoTag->GetDuration(); + } + +- int InfoTagMusic::getRating() +- { +- return infoTag->GetRating(); +- } +- +- int InfoTagMusic::getUserRating() +- { +- return infoTag->GetUserrating(); +- } +- + int InfoTagMusic::getTrack() + { + return infoTag->GetTrackNumber(); +diff --git a/xbmc/interfaces/legacy/InfoTagMusic.h b/xbmc/interfaces/legacy/InfoTagMusic.h +index bbfd7c8..ae4dc38 100644 +--- a/xbmc/interfaces/legacy/InfoTagMusic.h ++++ b/xbmc/interfaces/legacy/InfoTagMusic.h +@@ -197,42 +197,6 @@ namespace XBMCAddon + #ifdef DOXYGEN_SHOULD_USE_THIS + /// + /// \ingroup python_InfoTagMusic +- /// @brief \python_func{ getRating() } +- ///----------------------------------------------------------------------- +- /// Returns the scraped rating as integer. +- /// +- /// @return [integer] Rating +- /// +- /// +- ///----------------------------------------------------------------------- +- /// +- /// +- getRating(); +-#else +- int getRating(); +-#endif +- +-#ifdef DOXYGEN_SHOULD_USE_THIS +- /// +- /// \ingroup python_InfoTagMusic +- /// @brief \python_func{ getUserRating() } +- ///----------------------------------------------------------------------- +- /// Returns the user rating as integer (-1 if not existing) +- /// +- /// @return [integer] User rating +- /// +- /// +- ///----------------------------------------------------------------------- +- /// +- /// +- getUserRating(); +-#else +- int getUserRating(); +-#endif +- +-#ifdef DOXYGEN_SHOULD_USE_THIS +- /// +- /// \ingroup python_InfoTagMusic + /// @brief \python_func{ getTrack() } + ///----------------------------------------------------------------------- + /// Returns the track number (if present) from music info tag as integer. +diff --git a/xbmc/interfaces/legacy/InfoTagVideo.cpp b/xbmc/interfaces/legacy/InfoTagVideo.cpp +index 2f635be..f5568f1 100644 +--- a/xbmc/interfaces/legacy/InfoTagVideo.cpp ++++ b/xbmc/interfaces/legacy/InfoTagVideo.cpp +@@ -134,7 +134,7 @@ namespace XBMCAddon + + int InfoTagVideo::getYear() + { +- return infoTag->GetYear(); ++ return infoTag->m_iYear; + } + + double InfoTagVideo::getRating() +@@ -142,11 +142,6 @@ namespace XBMCAddon + return infoTag->GetRating().rating; + } + +- int InfoTagVideo::getUserRating() +- { +- return infoTag->m_iUserRating; +- } +- + int InfoTagVideo::getPlayCount() + { + return infoTag->m_playCount; +@@ -164,7 +159,7 @@ namespace XBMCAddon + + String InfoTagVideo::getPremiered() + { +- return infoTag->GetPremiered().GetAsLocalizedDate(); ++ return infoTag->m_premiered.GetAsLocalizedDate(); + } + + String InfoTagVideo::getFirstAired() +diff --git a/xbmc/interfaces/legacy/InfoTagVideo.h b/xbmc/interfaces/legacy/InfoTagVideo.h +index fc90001..99df329 100644 +--- a/xbmc/interfaces/legacy/InfoTagVideo.h ++++ b/xbmc/interfaces/legacy/InfoTagVideo.h +@@ -441,24 +441,6 @@ namespace XBMCAddon + #ifdef DOXYGEN_SHOULD_USE_THIS + /// + /// \ingroup python_InfoTagVideo +- /// @brief \python_func{ getUserRating() } +- ///----------------------------------------------------------------------- +- /// Get the user rating if present as integer. +- /// +- /// @return [integer] The user rating of the video +- /// +- /// +- ///----------------------------------------------------------------------- +- /// +- /// +- getUserRating(); +-#else +- int getUserRating(); +-#endif +- +-#ifdef DOXYGEN_SHOULD_USE_THIS +- /// +- /// \ingroup python_InfoTagVideo + /// @brief \python_func{ getPlayCount() } + ///----------------------------------------------------------------------- + /// To get the number of plays of the video. +diff --git a/xbmc/interfaces/legacy/ListItem.cpp b/xbmc/interfaces/legacy/ListItem.cpp +index 244ec80..db195dd 100644 +--- a/xbmc/interfaces/legacy/ListItem.cpp ++++ b/xbmc/interfaces/legacy/ListItem.cpp +@@ -294,7 +294,7 @@ namespace XBMCAddon + if (key == "dbid") + item->GetVideoInfoTag()->m_iDbId = strtol(value.c_str(), NULL, 10); + else if (key == "year") +- item->GetVideoInfoTag()->SetYear(strtol(value.c_str(), NULL, 10)); ++ item->GetVideoInfoTag()->m_iYear = strtol(value.c_str(), NULL, 10); + else if (key == "episode") + item->GetVideoInfoTag()->m_iEpisode = strtol(value.c_str(), NULL, 10); + else if (key == "season") +@@ -388,11 +388,7 @@ namespace XBMCAddon + else if (key == "tvshowtitle") + item->GetVideoInfoTag()->m_strShowTitle = value; + else if (key == "premiered") +- { +- CDateTime premiered; +- premiered.SetFromDateString(value); +- item->GetVideoInfoTag()->SetPremiered(premiered); +- } ++ item->GetVideoInfoTag()->m_premiered.SetFromDateString(value); + else if (key == "status") + item->GetVideoInfoTag()->m_strStatus = value; + else if (key == "set") +@@ -446,7 +442,7 @@ namespace XBMCAddon + const InfoLabelValue& alt = it->second; + const String value(alt.which() == first ? alt.former() : emptyString); + +- //! @todo add the rest of the infolabels ++ // TODO: add the rest of the infolabels + if (key == "tracknumber") + item->GetMusicInfoTag()->SetTrackNumber(strtol(value.c_str(), NULL, 10)); + else if (key == "discnumber") +diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp +index af6472f..d7e65ab 100644 +--- a/xbmc/interfaces/legacy/ModuleXbmc.cpp ++++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp +@@ -18,7 +18,7 @@ + * + */ + +-//! @todo Need a uniform way of returning an error status ++// TODO: Need a uniform way of returning an error status + + #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) + #include "config.h" +@@ -43,7 +43,6 @@ + #include "utils/Crc32.h" + #include "FileItem.h" + #include "LangInfo.h" +-#include "PlayListPlayer.h" + #include "settings/AdvancedSettings.h" + #include "settings/Settings.h" + #include "guilib/TextureManager.h" +@@ -454,7 +453,7 @@ namespace XBMCAddon + return result; + } + +- //! @todo Add a mediaType enum ++ // TODO: Add a mediaType enum + String getSupportedMedia(const char* mediaType) + { + XBMC_TRACE; +@@ -466,7 +465,7 @@ namespace XBMCAddon + else if (strcmpi(mediaType, "picture") == 0) + result = g_advancedSettings.m_pictureExtensions; + +- //! @todo implement ++ // TODO: + // else + // return an error + +diff --git a/xbmc/interfaces/legacy/ModuleXbmcplugin.h b/xbmc/interfaces/legacy/ModuleXbmcplugin.h +index 184ada9..39d56d1 100644 +--- a/xbmc/interfaces/legacy/ModuleXbmcplugin.h ++++ b/xbmc/interfaces/legacy/ModuleXbmcplugin.h +@@ -18,8 +18,6 @@ + * + */ + +-#include +- + #include "Tuple.h" + #include "AddonString.h" + #include "ListItem.h" +diff --git a/xbmc/interfaces/legacy/PlayList.cpp b/xbmc/interfaces/legacy/PlayList.cpp +index 5d97a2d..a04edda 100644 +--- a/xbmc/interfaces/legacy/PlayList.cpp ++++ b/xbmc/interfaces/legacy/PlayList.cpp +@@ -30,8 +30,8 @@ namespace XBMCAddon + { + namespace xbmc + { +- //! @todo need a means to check for a valid construction +- //! either by throwing an exception or by an "isValid" check ++ // TODO: need a means to check for a valid construction ++ // either by throwing an exception or by an "isValid" check + PlayList::PlayList(int playList) : + refs(1), iPlayList(playList), pPlayList(NULL) + { +diff --git a/xbmc/interfaces/legacy/Player.h b/xbmc/interfaces/legacy/Player.h +index 29ee6fc..717fabc 100644 +--- a/xbmc/interfaces/legacy/Player.h ++++ b/xbmc/interfaces/legacy/Player.h +@@ -20,8 +20,6 @@ + + #pragma once + +-#include +- + #include "ListItem.h" + #include "PlayList.h" + #include "InfoTagVideo.h" +diff --git a/xbmc/interfaces/legacy/Window.cpp b/xbmc/interfaces/legacy/Window.cpp +index 420bae7..d3404c6 100644 +--- a/xbmc/interfaces/legacy/Window.cpp ++++ b/xbmc/interfaces/legacy/Window.cpp +@@ -168,13 +168,13 @@ namespace XBMCAddon + } + else + { +- //! @bug +- //! This is an existing window, so no resources are free'd. Note that +- //! THIS WILL FAIL for any controls newly created by python - they will +- //! remain after the script ends. Ideally this would be remedied by +- //! a flag in Control that specifies that it was python created - any python +- //! created controls could then be removed + free'd from the window. +- //! how this works with controlgroups though could be a bit tricky. ++ // BUG: ++ // This is an existing window, so no resources are free'd. Note that ++ // THIS WILL FAIL for any controls newly created by python - they will ++ // remain after the script ends. Ideally this would be remedied by ++ // a flag in Control that specifies that it was python created - any python ++ // created controls could then be removed + free'd from the window. ++ // how this works with controlgroups though could be a bit tricky. + } + + // and free our list of controls +@@ -276,7 +276,7 @@ namespace XBMCAddon + + Control* pControl = NULL; + +- //! @todo Yuck! Should probably be done with a Factory pattern ++ // TODO: Yuck! Should probably be done with a Factory pattern + switch(pGUIControl->GetControlType()) + { + case CGUIControl::GUICONTROL_BUTTON: +@@ -305,7 +305,6 @@ namespace XBMCAddon + pControl = new ControlTextBox(); + break; + case CGUIControl::GUICONTROL_IMAGE: +- case CGUIControl::GUICONTROL_BORDEREDIMAGE: + pControl = new ControlImage(); + break; + case CGUIControl::GUICONTROL_PROGRESS: +@@ -679,9 +678,9 @@ namespace XBMCAddon + + while (bModal && !g_application.m_bStop) + { +-//! @todo garbear added this code to the pythin window.cpp class and +-//! commented in XBPyThread.cpp. I'm not sure how to handle this +-//! in this native implementation. ++// TODO: garbear added this code to the pythin window.cpp class and ++// commented in XBPyThread.cpp. I'm not sure how to handle this ++// in this native implementation. + // // Check if XBPyThread::stop() raised a SystemExit exception + // if (PyThreadState_Get()->async_exc == PyExc_SystemExit) + // { +diff --git a/xbmc/interfaces/legacy/Window.h b/xbmc/interfaces/legacy/Window.h +index 746692c..af26b17 100644 +--- a/xbmc/interfaces/legacy/Window.h ++++ b/xbmc/interfaces/legacy/Window.h +@@ -20,7 +20,6 @@ + + #pragma once + #include +-#include + + #include "AddonCallback.h" + #include "Control.h" +diff --git a/xbmc/interfaces/legacy/WindowDialogMixin.cpp b/xbmc/interfaces/legacy/WindowDialogMixin.cpp +index 9bc70c4..3da6d88 100644 +--- a/xbmc/interfaces/legacy/WindowDialogMixin.cpp ++++ b/xbmc/interfaces/legacy/WindowDialogMixin.cpp +@@ -62,7 +62,7 @@ namespace XBMCAddon + CGUIMessage msg(GUI_MSG_WINDOW_INIT,0,0); + w->OnMessage(msg); + w->window->setActive(true); +- //! @todo Figure out how to clean up the CAction ++ // TODO: Figure out how to clean up the CAction + return true; + } + break; +diff --git a/xbmc/interfaces/legacy/WindowXML.cpp b/xbmc/interfaces/legacy/WindowXML.cpp +index 4650c6d..67afe20 100644 +--- a/xbmc/interfaces/legacy/WindowXML.cpp ++++ b/xbmc/interfaces/legacy/WindowXML.cpp +@@ -53,7 +53,7 @@ namespace XBMCAddon + #define checkedv(methcall) { if (window.isNotNull()) xwin-> methcall ; } + + +- //! @todo This should be done with template specialization ++ // TODO: This should be done with template specialization + class WindowXMLInterceptor : public InterceptorDialog + { + WindowXML* xwin; +@@ -62,30 +62,30 @@ namespace XBMCAddon + InterceptorDialog("CGUIMediaWindow",_window,windowid,xmlfile), xwin(_window) + { } + +- virtual void AllocResources(bool forceLoad = false) override ++ virtual void AllocResources(bool forceLoad = false) + { XBMC_TRACE; if(up()) CGUIMediaWindow::AllocResources(forceLoad); else checkedv(AllocResources(forceLoad)); } +- virtual void FreeResources(bool forceUnLoad = false) override ++ virtual void FreeResources(bool forceUnLoad = false) + { XBMC_TRACE; if(up()) CGUIMediaWindow::FreeResources(forceUnLoad); else checkedv(FreeResources(forceUnLoad)); } + virtual bool OnClick(int iItem, const std::string &player = "") override { XBMC_TRACE; return up() ? CGUIMediaWindow::OnClick(iItem, player) : checkedb(OnClick(iItem)); } + +- virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) override ++ virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) + { XBMC_TRACE; if(up()) CGUIMediaWindow::Process(currentTime,dirtyregions); else checkedv(Process(currentTime,dirtyregions)); } + + // this is a hack to SKIP the CGUIMediaWindow +- virtual bool OnAction(const CAction &action) override ++ virtual bool OnAction(const CAction &action) + { XBMC_TRACE; return up() ? CGUIWindow::OnAction(action) : checkedb(OnAction(action)); } + + protected: + // CGUIWindow +- virtual bool LoadXML(const std::string &strPath, const std::string &strPathLower) override ++ virtual bool LoadXML(const std::string &strPath, const std::string &strPathLower) + { XBMC_TRACE; return up() ? CGUIMediaWindow::LoadXML(strPath,strPathLower) : xwin->LoadXML(strPath,strPathLower); } + + // CGUIMediaWindow +- virtual void GetContextButtons(int itemNumber, CContextButtons &buttons) override ++ virtual void GetContextButtons(int itemNumber, CContextButtons &buttons) + { XBMC_TRACE; if (up()) CGUIMediaWindow::GetContextButtons(itemNumber,buttons); else xwin->GetContextButtons(itemNumber,buttons); } +- virtual bool Update(const std::string &strPath) override ++ virtual bool Update(const std::string &strPath) + { XBMC_TRACE; return up() ? CGUIMediaWindow::Update(strPath) : xwin->Update(strPath); } +- virtual void SetupShares() override { XBMC_TRACE; if(up()) CGUIMediaWindow::SetupShares(); else checkedv(SetupShares()); } ++ virtual void SetupShares() { XBMC_TRACE; if(up()) CGUIMediaWindow::SetupShares(); else checkedv(SetupShares()); } + + friend class WindowXML; + friend class WindowXMLDialog; +@@ -185,25 +185,12 @@ namespace XBMCAddon + A(m_vecItems)->AddFront(fileItem,position); + } + A(m_viewControl).SetItems(*(A(m_vecItems))); ++ A(UpdateButtons()); + } + //---------------------------------------------------- + } + } + +- void WindowXML::addItems(const std::vector > & items) +- { +- XBMC_TRACE; +- LOCKGUI; +- for (auto item : items) +- { +- AddonClass::Ref ritem = item.which() == XBMCAddon::first ? ListItem::fromString(item.former()) : AddonClass::Ref(item.later()); +- CFileItemPtr& fileItem = ritem->item; +- A(m_vecItems)->Add(fileItem); +- } +- A(m_viewControl).SetItems(*(A(m_vecItems))); +- } +- +- + void WindowXML::removeItem(int position) + { + XBMC_TRACE; +@@ -211,6 +198,7 @@ namespace XBMCAddon + LOCKGUI; + A(m_vecItems)->Remove(position); + A(m_viewControl).SetItems(*(A(m_vecItems))); ++ A(UpdateButtons()); + } + + int WindowXML::getCurrentListPosition() +@@ -265,6 +253,7 @@ namespace XBMCAddon + A(ClearFileItems()); + + A(m_viewControl).SetItems(*(A(m_vecItems))); ++ A(UpdateButtons()); + } + + void WindowXML::setContainerProperty(const String& key, const String& value) +@@ -301,9 +290,9 @@ namespace XBMCAddon + CLog::Log(LOGDEBUG,"%sMessage id:%d",_tg.getSpaces(),(int)message.GetMessage()); + #endif + +- //! @todo We shouldn't be dropping down to CGUIWindow in any of this ideally. +- //! We have to make up our minds about what python should be doing and +- //! what this side of things should be doing ++ // TODO: We shouldn't be dropping down to CGUIWindow in any of this ideally. ++ // We have to make up our minds about what python should be doing and ++ // what this side of things should be doing + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: +@@ -478,6 +467,7 @@ namespace XBMCAddon + void WindowXML::SetupShares() + { + XBMC_TRACE; ++ A(UpdateButtons()); + } + + bool WindowXML::Update(const String &strPath) +diff --git a/xbmc/interfaces/legacy/WindowXML.h b/xbmc/interfaces/legacy/WindowXML.h +index d2fa2c7..c2cfb9a 100644 +--- a/xbmc/interfaces/legacy/WindowXML.h ++++ b/xbmc/interfaces/legacy/WindowXML.h +@@ -21,7 +21,6 @@ + #pragma once + + #include +-#include + + #include "Window.h" + #include "windows/GUIMediaWindow.h" +@@ -146,31 +145,6 @@ namespace XBMCAddon + #ifdef DOXYGEN_SHOULD_USE_THIS + /// + /// \ingroup python_xbmcgui_window_xml +- /// @brief \python_func{ addItems(items) } +- ///----------------------------------------------------------------------- +- /// Add a list of items to to the window list. +- /// +- /// +- /// @param items List - list of strings, unicode objects or ListItems to add. +- /// +- /// +- /// ---------------------------------------------------------------------- +- /// +- /// **Example:** +- /// ~~~~~~~~~~~~~{.py} +- /// .. +- /// self.addItems(['Reboot Kodi', 'Restart Kodi']) +- /// .. +- /// ~~~~~~~~~~~~~ +- /// +- addItems(...); +-#else +- SWIGHIDDENVIRTUAL void addItems(const std::vector > & items); +-#endif +- +-#ifdef DOXYGEN_SHOULD_USE_THIS +- /// +- /// \ingroup python_xbmcgui_window_xml + /// @brief \python_func{ removeItem(position) } + ///----------------------------------------------------------------------- + /// Removes a specified item based on position, from the Window List. +diff --git a/xbmc/interfaces/legacy/wsgi/WsgiResponse.h b/xbmc/interfaces/legacy/wsgi/WsgiResponse.h +index a741631..a679faa 100644 +--- a/xbmc/interfaces/legacy/wsgi/WsgiResponse.h ++++ b/xbmc/interfaces/legacy/wsgi/WsgiResponse.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "interfaces/legacy/AddonClass.h" + #include "interfaces/legacy/Tuple.h" + #include "interfaces/legacy/wsgi/WsgiResponseBody.h" +diff --git a/xbmc/interfaces/python/CallbackHandler.cpp b/xbmc/interfaces/python/CallbackHandler.cpp +index 1636740..6bcaff6 100644 +--- a/xbmc/interfaces/python/CallbackHandler.cpp ++++ b/xbmc/interfaces/python/CallbackHandler.cpp +@@ -59,7 +59,7 @@ namespace XBMCAddon + * For this method we expect the PyThreadState to be passed as the user + * data for the check. + * +- * @todo This is a stupid way to get this information back to the handler. ++ * TODO: This is a stupid way to get this information back to the handler. + * there should be a more language neutral means. + */ + bool PythonCallbackHandler::shouldRemoveCallback(AddonClass* obj, void* threadState) +diff --git a/xbmc/interfaces/python/PythonInvoker.h b/xbmc/interfaces/python/PythonInvoker.h +index 11fb396..6dab1df 100644 +--- a/xbmc/interfaces/python/PythonInvoker.h ++++ b/xbmc/interfaces/python/PythonInvoker.h +@@ -21,7 +21,6 @@ + + #include + #include +-#include + + #include "interfaces/generic/ILanguageInvoker.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/interfaces/python/swig.cpp b/xbmc/interfaces/python/swig.cpp +index 947c442..fea0a23 100644 +--- a/xbmc/interfaces/python/swig.cpp ++++ b/xbmc/interfaces/python/swig.cpp +@@ -55,9 +55,9 @@ namespace PythonBindings + return; + } + +- //! @todo UTF-8: Does python use UTF-16? +- //! Do we need to convert from the string charset to UTF-8 +- //! for non-unicode data? ++ // TODO: UTF-8: Does python use UTF-16? ++ // Do we need to convert from the string charset to UTF-8 ++ // for non-unicode data? + if (PyUnicode_Check(pObject)) + { + // Python unicode objects are UCS2 or UCS4 depending on compilation +diff --git a/xbmc/linux/LinuxTimezone.cpp b/xbmc/linux/LinuxTimezone.cpp +index b562c49..b780e62 100644 +--- a/xbmc/linux/LinuxTimezone.cpp ++++ b/xbmc/linux/LinuxTimezone.cpp +@@ -119,7 +119,7 @@ CLinuxTimezone::CLinuxTimezone() : m_IsDST(0) + s = line; + StringUtils::Trim(s); + +- //! @todo STRING_CLEANUP ++ /* TODO:STRING_CLEANUP */ + if (s.length() == 0) + continue; + +diff --git a/xbmc/linux/OMXCore.h b/xbmc/linux/OMXCore.h +index 5536cb9..a89b77b 100644 +--- a/xbmc/linux/OMXCore.h ++++ b/xbmc/linux/OMXCore.h +@@ -23,9 +23,8 @@ + + #include + #include +-#include + +-//! @todo should this be in configure ++// TODO: should this be in configure + #ifndef OMX_SKIP64BIT + #define OMX_SKIP64BIT + #endif +diff --git a/xbmc/linux/PosixMountProvider.h b/xbmc/linux/PosixMountProvider.h +index df4cabe..d34247f 100644 +--- a/xbmc/linux/PosixMountProvider.h ++++ b/xbmc/linux/PosixMountProvider.h +@@ -18,9 +18,6 @@ + * . + * + */ +-#include +-#include +- + #include "storage/IStorageProvider.h" + + class CPosixMountProvider : public IStorageProvider +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index d101638..494865d 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -213,8 +213,10 @@ uint32_t CRBP::WaitVsync(uint32_t target) + target = m_vsync_count+1; + while (!delay.IsTimePast()) + { ++ CSingleLock lock(m_critSection); + if ((signed)(m_vsync_count - target) >= 0) + break; ++ lock.Leave(); + if (!m_vsync_cond.wait(vlock, delay.MillisLeft())) + break; + } +@@ -262,6 +264,20 @@ void CRBP::Deinitialize() + vcsm_exit(); + } + ++void CRBP::SuspendVideoOutput() ++{ ++ CLog::Log(LOGDEBUG, "Raspberry PI suspending video output\n"); ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 0"); ++} ++ ++void CRBP::ResumeVideoOutput() ++{ ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 1"); ++ CLog::Log(LOGDEBUG, "Raspberry PI resuming video output\n"); ++} ++ + static int mbox_property(int file_desc, void *buf) + { + int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index a35a509..78e4487 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -82,6 +82,9 @@ public: + void VSyncCallback(); + int GetMBox() { return m_mb; } + ++ void SuspendVideoOutput(); ++ void ResumeVideoOutput(); ++ + private: + DllBcmHost *m_DllBcmHost; + bool m_initialized; +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index 75378ff..1d3d937 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -23,6 +23,20 @@ + #include "threads/Event.h" + #include "threads/Thread.h" + #include "guilib/DispResource.h" ++#include "utils/log.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define likely(x) __builtin_expect(!!(x),1) ++#define unlikely(x) __builtin_expect(!!(x),0) ++ ++class CIMX; ++extern CIMX g_IMX; + + class CIMX : public CThread, IDispResource + { +@@ -52,4 +66,123 @@ private: + uint32_t m_lastSyncFlag; + }; + +-extern CIMX g_IMX; ++// A blocking FIFO buffer ++template ++class lkFIFO ++{ ++public: ++ lkFIFO() { m_size = queue.max_size(); queue.clear(); m_abort = false; } ++ ++public: ++ T pop() ++ { ++ std::unique_lock m_lock(lkqueue); ++ m_abort = false; ++ while (!queue.size() && !m_abort) ++ read.wait(m_lock); ++ ++ T val; ++ if (!queue.empty()) ++ { ++ val = queue.front(); ++ queue.pop_front(); ++ } ++ ++ m_lock.unlock(); ++ write.notify_one(); ++ return val; ++ } ++ ++ bool push(const T& item) ++ { ++ std::unique_lock m_lock(lkqueue); ++ m_abort = false; ++ while (queue.size() >= m_size && !m_abort) ++ write.wait(m_lock); ++ ++ if (m_abort) ++ return false; ++ ++ queue.push_back(item); ++ m_lock.unlock(); ++ read.notify_one(); ++ return true; ++ } ++ ++ void signal() ++ { ++ m_abort = true; ++ read.notify_one(); ++ write.notify_one(); ++ } ++ ++ void setquotasize(size_t newsize) ++ { ++ m_size = newsize; ++ write.notify_one(); ++ } ++ ++ size_t getquotasize() ++ { ++ return m_size; ++ } ++ ++ void for_each(void (*fn)(T &t), bool clear = true) ++ { ++ std::unique_lock m_lock(lkqueue); ++ std::for_each(queue.begin(), queue.end(), fn); ++ ++ if (clear) ++ queue.clear(); ++ ++ write.notify_one(); ++ } ++ ++ size_t size() ++ { ++ return queue.size(); ++ } ++ ++ void clear() ++ { ++ std::unique_lock m_lock(lkqueue); ++ queue.clear(); ++ write.notify_one(); ++ } ++ ++ bool full() { return m_size == queue.size(); } ++ ++private: ++ std::deque queue; ++ std::mutex lkqueue; ++ std::condition_variable write; ++ std::condition_variable read; ++ ++ size_t m_size; ++ volatile bool m_abort; ++}; ++ ++// Generell description of a buffer used by ++// the IMX context, e.g. for blitting ++class CIMXBuffer { ++public: ++ CIMXBuffer() : m_iRefs(0) {} ++ ++ // Shared pointer interface ++ virtual void Lock() = 0; ++ virtual long Release() = 0; ++ ++ int GetFormat() { return iFormat; } ++ ++public: ++ uint32_t iWidth; ++ uint32_t iHeight; ++ int pPhysAddr; ++ uint8_t *pVirtAddr; ++ int iFormat; ++ double m_fps; ++ ++protected: ++ std::atomic m_iRefs; ++}; ++ +diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp +index 75abf5b..f5457bc 100644 +--- a/xbmc/listproviders/DirectoryProvider.cpp ++++ b/xbmc/listproviders/DirectoryProvider.cpp +@@ -211,7 +211,7 @@ bool CDirectoryProvider::Update(bool forceRefresh) + + for (std::vector::iterator i = m_items.begin(); i != m_items.end(); ++i) + changed |= (*i)->UpdateVisibility(m_parentID); +- return changed; //! @todo Also returned changed if properties are changed (if so, need to update scroll to letter). ++ return changed; // TODO: Also returned changed if properties are changed (if so, need to update scroll to letter). + } + + void CDirectoryProvider::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) +diff --git a/xbmc/listproviders/DirectoryProvider.h b/xbmc/listproviders/DirectoryProvider.h +index a15fdd2..d8dad25 100644 +--- a/xbmc/listproviders/DirectoryProvider.h ++++ b/xbmc/listproviders/DirectoryProvider.h +@@ -21,8 +21,6 @@ + #pragma once + + #include +-#include +- + #include "IListProvider.h" + #include "guilib/GUIStaticItem.h" + #include "utils/Job.h" +@@ -56,17 +54,17 @@ public: + CDirectoryProvider(const TiXmlElement *element, int parentID); + virtual ~CDirectoryProvider(); + +- virtual bool Update(bool forceRefresh) override; +- virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) override; +- virtual void Fetch(std::vector &items) const override; +- virtual void Reset(bool immediately = false) override; +- virtual bool OnClick(const CGUIListItemPtr &item) override; ++ virtual bool Update(bool forceRefresh); ++ virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); ++ virtual void Fetch(std::vector &items) const; ++ virtual void Reset(bool immediately = false); ++ virtual bool OnClick(const CGUIListItemPtr &item); + bool OnInfo(const CGUIListItemPtr &item) override; + bool OnContextMenu(const CGUIListItemPtr &item) override; +- virtual bool IsUpdating() const override; ++ virtual bool IsUpdating() const; + + // callback from directory job +- virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job) override; ++ virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job); + private: + UpdateState m_updateState; + bool m_isAnnounced; +diff --git a/xbmc/listproviders/StaticProvider.cpp b/xbmc/listproviders/StaticProvider.cpp +index a0bcd3d..43ef9a3 100644 +--- a/xbmc/listproviders/StaticProvider.cpp ++++ b/xbmc/listproviders/StaticProvider.cpp +@@ -75,7 +75,7 @@ bool CStaticListProvider::Update(bool forceRefresh) + } + for (std::vector::iterator i = m_items.begin(); i != m_items.end(); ++i) + changed |= (*i)->UpdateVisibility(m_parentID); +- return changed; //! @todo Also returned changed if properties are changed (if so, need to update scroll to letter). ++ return changed; // TODO: Also returned changed if properties are changed (if so, need to update scroll to letter). + } + + void CStaticListProvider::Fetch(std::vector &items) const +diff --git a/xbmc/listproviders/StaticProvider.h b/xbmc/listproviders/StaticProvider.h +index 9a36691..5a869e8 100644 +--- a/xbmc/listproviders/StaticProvider.h ++++ b/xbmc/listproviders/StaticProvider.h +@@ -20,8 +20,6 @@ + + #pragma once + +-#include +- + #include "IListProvider.h" + #include "guilib/GUIStaticItem.h" + +@@ -32,14 +30,14 @@ public: + CStaticListProvider(const std::vector &items); // for python + virtual ~CStaticListProvider(); + +- virtual bool Update(bool forceRefresh) override; +- virtual void Fetch(std::vector &items) const override; +- virtual bool OnClick(const CGUIListItemPtr &item) override; ++ virtual bool Update(bool forceRefresh); ++ virtual void Fetch(std::vector &items) const; ++ virtual bool OnClick(const CGUIListItemPtr &item); + bool OnInfo(const CGUIListItemPtr &item) override { return false; } + bool OnContextMenu(const CGUIListItemPtr &item) override { return false; } +- virtual void SetDefaultItem(int item, bool always) override; +- virtual int GetDefaultItem() const override; +- virtual bool AlwaysFocusDefaultItem() const override; ++ virtual void SetDefaultItem(int item, bool always); ++ virtual int GetDefaultItem() const; ++ virtual bool AlwaysFocusDefaultItem() const; + private: + int m_defaultItem; + bool m_defaultAlways; +diff --git a/xbmc/messaging/ApplicationMessenger.h b/xbmc/messaging/ApplicationMessenger.h +index b54b1c8..67cda36 100644 +--- a/xbmc/messaging/ApplicationMessenger.h ++++ b/xbmc/messaging/ApplicationMessenger.h +@@ -90,6 +90,9 @@ + #define TMSG_LOADPROFILE TMSG_MASK_APPLICATION + 27 + #define TMSG_VIDEORESIZE TMSG_MASK_APPLICATION + 28 + #define TMSG_SETAUDIODSPSTATE TMSG_MASK_APPLICATION + 29 ++#define TMSG_CHANGEVT TMSG_MASK_APPLICATION + 30 ++#define TMSG_DISPLAY_RECONFIGURE TMSG_MASK_APPLICATION + 31 ++ + + #define TMSG_GUI_INFOLABEL TMSG_MASK_GUIINFOMANAGER + 0 + #define TMSG_GUI_INFOBOOL TMSG_MASK_GUIINFOMANAGER + 1 +diff --git a/xbmc/music/Album.cpp b/xbmc/music/Album.cpp +index a091766..413b53d 100644 +--- a/xbmc/music/Album.cpp ++++ b/xbmc/music/Album.cpp +@@ -391,9 +391,9 @@ bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) + float max_rating = 10; + XMLUtils::GetFloat(album, "userrating", rating); + if (userrating->QueryFloatAttribute("max", &max_rating) == TIXML_SUCCESS && max_rating >= 1) +- rating *= (10.f / max_rating); // Normalise the Rating to between 0 and 10 +- if (rating > 10.f) +- rating = 10.f; ++ rating *= (5.f / max_rating); // Normalise the Rating to between 0 and 10 ++ if (rating > 5.f) ++ rating = 5.f; + iUserrating = MathUtils::round_int(rating); + } + XMLUtils::GetInt(album, "votes", iVotes); +diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp +index bf6fd4c..4d8adae 100644 +--- a/xbmc/music/GUIViewStateMusic.cpp ++++ b/xbmc/music/GUIViewStateMusic.cpp +@@ -61,6 +61,7 @@ std::string CGUIViewStateWindowMusic::GetExtensions() + + VECSOURCES& CGUIViewStateWindowMusic::GetSources() + { ++ AddAddonsSource("audio", g_localizeStrings.Get(1038), "DefaultAddonMusic.png"); + return CGUIViewState::GetSources(); + } + +@@ -416,12 +417,12 @@ CGUIViewStateMusicPlaylist::CGUIViewStateMusicPlaylist(const CFileItemList& item + SetViewAsControl(viewState->m_viewMode); + SetSortOrder(viewState->m_sortDescription.sortOrder); + +- LoadViewState(items.GetPath(), WINDOW_MUSIC_NAV); ++ LoadViewState(items.GetPath(), WINDOW_MUSIC_FILES); + } + + void CGUIViewStateMusicPlaylist::SaveViewState() + { +- SaveViewToDb(m_items.GetPath(), WINDOW_MUSIC_NAV); ++ SaveViewToDb(m_items.GetPath(), WINDOW_MUSIC_FILES); + } + + CGUIViewStateWindowMusicNav::CGUIViewStateWindowMusicNav(const CFileItemList& items) : CGUIViewStateWindowMusic(items) +@@ -535,6 +536,54 @@ VECSOURCES& CGUIViewStateWindowMusicNav::GetSources() + return CGUIViewStateWindowMusic::GetSources(); + } + ++CGUIViewStateWindowMusicSongs::CGUIViewStateWindowMusicSongs(const CFileItemList& items) : CGUIViewStateWindowMusic(items) ++{ ++ if (items.IsVirtualDirectoryRoot()) ++ { ++ AddSortMethod(SortByLabel, 551, LABEL_MASKS()); // Preformated ++ AddSortMethod(SortByDriveType, 564, LABEL_MASKS()); // Preformated ++ SetSortMethod(SortByLabel); ++ ++ SetViewAsControl(DEFAULT_VIEW_LIST); ++ ++ SetSortOrder(SortOrderAscending); ++ } ++ else if (items.GetPath() == "special://musicplaylists/") ++ { // playlists list sorts by label only, ignoring folders ++ AddSortMethod(SortByLabel, SortAttributeIgnoreFolders, 551, LABEL_MASKS("%F", "%D", "%L", "")); // Filename, Duration | Foldername, empty ++ SetSortMethod(SortByLabel); ++ } ++ else ++ { ++ std::string strTrack=CSettings::GetInstance().GetString(CSettings::SETTING_MUSICFILES_TRACKFORMAT); ++ AddSortMethod(SortByLabel, 551, LABEL_MASKS(strTrack, "%D", "%L", ""), // Userdefined, Duration | FolderName, empty ++ CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING) ? SortAttributeIgnoreArticle : SortAttributeNone); ++ AddSortMethod(SortBySize, 553, LABEL_MASKS(strTrack, "%I", "%L", "%I")); // Userdefined, Size | FolderName, Size ++ AddSortMethod(SortByBitrate, 623, LABEL_MASKS(strTrack, "%X", "%L", "%X")); // Userdefined, Bitrate | FolderName, Bitrate ++ AddSortMethod(SortByDate, 552, LABEL_MASKS(strTrack, "%J", "%L", "%J")); // Userdefined, Date | FolderName, Date ++ AddSortMethod(SortByFile, 561, LABEL_MASKS(strTrack, "%F", "%L", "")); // Userdefined, FileName | FolderName, empty ++ AddSortMethod(SortByListeners, 20455,LABEL_MASKS(strTrack, "%W", "%L", "%W")); ++ ++ const CViewState *viewState = CViewStateSettings::GetInstance().Get("musicfiles"); ++ SetSortMethod(viewState->m_sortDescription); ++ SetViewAsControl(viewState->m_viewMode); ++ SetSortOrder(viewState->m_sortDescription.sortOrder); ++ } ++ LoadViewState(items.GetPath(), WINDOW_MUSIC_FILES); ++} ++ ++void CGUIViewStateWindowMusicSongs::SaveViewState() ++{ ++ SaveViewToDb(m_items.GetPath(), WINDOW_MUSIC_FILES, CViewStateSettings::GetInstance().Get("musicfiles")); ++} ++ ++VECSOURCES& CGUIViewStateWindowMusicSongs::GetSources() ++{ ++ VECSOURCES *musicSources = CMediaSourceSettings::GetInstance().GetSources("music"); ++ AddOrReplace(*musicSources, CGUIViewStateWindowMusic::GetSources()); ++ return *musicSources; ++} ++ + CGUIViewStateWindowMusicPlaylist::CGUIViewStateWindowMusicPlaylist(const CFileItemList& items) : CGUIViewStateWindowMusic(items) + { + std::string strTrack=CSettings::GetInstance().GetString(CSettings::SETTING_MUSICFILES_NOWPLAYINGTRACKFORMAT); +diff --git a/xbmc/music/GUIViewStateMusic.h b/xbmc/music/GUIViewStateMusic.h +index 95a123f..e4f7931 100644 +--- a/xbmc/music/GUIViewStateMusic.h ++++ b/xbmc/music/GUIViewStateMusic.h +@@ -83,6 +83,16 @@ private: + void AddOnlineShares(); + }; + ++class CGUIViewStateWindowMusicSongs : public CGUIViewStateWindowMusic ++{ ++public: ++ CGUIViewStateWindowMusicSongs(const CFileItemList& items); ++ ++protected: ++ virtual void SaveViewState(); ++ virtual VECSOURCES& GetSources(); ++}; ++ + class CGUIViewStateWindowMusicPlaylist : public CGUIViewStateWindowMusic + { + public: +diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp +index 3ae0510..4673b75 100644 +--- a/xbmc/music/MusicDatabase.cpp ++++ b/xbmc/music/MusicDatabase.cpp +@@ -3225,7 +3225,7 @@ bool CMusicDatabase::LookupCDDBInfo(bool bRequery/*=false*/) + return false; + + // check network connectivity +- if (!g_application.getNetwork().IsAvailable()) ++ if (!g_application.getNetwork().IsConnected()) + return false; + + // Get information for the inserted disc +@@ -4086,6 +4086,8 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter & + try + { + total = -1; ++ // Get data from album and album_artist tables to fully populate albums ++ std::string strSQL = "SELECT %s FROM albumview JOIN albumartistview on albumartistview.idalbum = albumview.idalbum "; + + Filter extFilter = filter; + CMusicDbUrl musicUrl; +@@ -4111,9 +4113,9 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter & + return true; + + // Apply the limiting directly here if there's no special sorting but limiting +- bool limited = extFilter.limit.empty() && sortDescription.sortBy == SortByNone && +- (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0); +- if (limited) ++ if (extFilter.limit.empty() && ++ sortDescription.sortBy == SortByNone && ++ (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + { + strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); + albums.reserve(sortDescription.limitEnd - sortDescription.limitStart); +@@ -4121,19 +4123,8 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter & + else + albums.reserve(total); + +- std::string strSQL; +- +- // Get data from album, album_artist and artist tables to fully populate albums with album artists +- // All albums have at least one artist so inner join sufficient +- if (limited) +- //Apply where clause and limits to albumview, then join as mutiple records in result set per album +- strSQL = "SELECT av.*, albumartistview.* " +- "FROM (SELECT albumview.* FROM albumview " + strSQLExtra + ") AS av " +- "JOIN albumartistview ON albumartistview.idalbum = av.idalbum "; +- else +- strSQL = "SELECT albumview.*, albumartistview.* " +- "FROM albumview JOIN albumartistview ON albumartistview.idalbum = albumview.idalbum " + strSQLExtra; +- ++ strSQL = PrepareSQL(strSQL, !filter.fields.empty() && filter.fields.compare("*") != 0 ? filter.fields.c_str() : "albumview.*, albumartistview.* ") + strSQLExtra; ++ + CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); + // run query + unsigned int time = XbmcThreads::SystemClockMillis(); +@@ -4149,16 +4140,10 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter & + return true; + } + ++ //Sort the results set - need to add sort by iOrder to maintain artist name order?? + DatabaseResults results; +- results.reserve(iRowsFound); +- // Do not apply any limit when sorting as have join with albumartistview so limit would +- // apply incorrectly (although when SortByNone limit already applied in SQL). +- // Apply limits later to album list rather than dataset +- // But Artist order may be disturbed by sort??? +- sorting = sortDescription; +- sorting.limitStart = 0; +- sorting.limitEnd = -1; +- if (!SortUtils::SortFromDataset(sorting, MediaTypeAlbum, m_pDS, results)) ++ results.reserve(iRowsFound); ++ if (!SortUtils::SortFromDataset(sortDescription, MediaTypeAlbum, m_pDS, results)) + return false; + + // Get albums from returned rows. Join means there is a row for every album artist +@@ -4174,26 +4159,13 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter & + if (albumId != record->at(album_idAlbum).get_asInt()) + { // New album + albumId = record->at(album_idAlbum).get_asInt(); +- albums.emplace_back(GetAlbumFromDataset(record)); ++ albums.push_back(GetAlbumFromDataset(record)); + } + // Get artists +- albums.back().artistCredits.emplace_back(GetArtistCreditFromDataset(record, albumArtistOffset)); ++ albums.back().artistCredits.push_back(GetArtistCreditFromDataset(record, albumArtistOffset)); + } + + m_pDS->close(); // cleanup recordset data +- +- // Apply any limits to sorted albums +- if (sortDescription.sortBy != SortByNone && (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) +- { +- int limitEnd = sortDescription.limitEnd; +- if (sortDescription.limitStart > 0 && (size_t)sortDescription.limitStart < albums.size()) +- { +- albums.erase(albums.begin(), albums.begin() + sortDescription.limitStart); +- limitEnd = sortDescription.limitEnd - sortDescription.limitStart; +- } +- if (limitEnd > 0 && (size_t)limitEnd < albums.size()) +- albums.erase(albums.begin() + limitEnd, albums.end()); +- } + return true; + } + catch (...) +@@ -4274,16 +4246,10 @@ bool CMusicDatabase::GetSongsFullByWhere(const std::string &baseDir, const Filte + + DatabaseResults results; + results.reserve(iRowsFound); +- // Avoid sorting with limits when have join with songartistview +- // Limit when SortByNone already applied in SQL, +- // apply sort later to fileitems list rather than dataset +- sorting = sortDescription; +- if (artistData && sortDescription.sortBy != SortByNone) +- sorting.sortBy = SortByNone; +- if (!SortUtils::SortFromDataset(sorting, MediaTypeSong, m_pDS, results)) ++ if (!SortUtils::SortFromDataset(sortDescription, MediaTypeSong, m_pDS, results)) + return false; + +- // Get songs from returned rows. If join songartistview then there is a row for every artist ++ // Get songs from returned rows. If join songartistview then there is a row for every album artist + items.Reserve(total); + int songArtistOffset = song_enumCount; + int songId = -1; +@@ -4338,10 +4304,6 @@ bool CMusicDatabase::GetSongsFullByWhere(const std::string &baseDir, const Filte + // cleanup + m_pDS->close(); + +- // When have join with songartistview apply sort (and limit) to items rather than dataset +- if (artistData && sortDescription.sortBy != SortByNone) +- items.Sort(sortDescription); +- + if (cueSheetData) + { // Load some info from embedded cuesheet if present (now only ReplayGain) + CueInfoLoader cueLoader; +@@ -5053,7 +5015,7 @@ bool CMusicDatabase::GetAlbumPath(int idAlbum, std::string& path) + bool CMusicDatabase::SaveAlbumThumb(int idAlbum, const std::string& strThumb) + { + SetArtForItem(idAlbum, MediaTypeAlbum, "thumb", strThumb); +- //! @todo We should prompt the user to update the art for songs ++ // TODO: We should prompt the user to update the art for songs + std::string sql = PrepareSQL("UPDATE art" + " SET url='-'" + " WHERE media_type='song'" +@@ -5371,7 +5333,7 @@ bool CMusicDatabase::RemoveSongsFromPath(const std::string &path1, MAPSONGS& son + // from the song link tables (as otherwise if a song is added back + // to the table with the same idSong, these tables can't be cleaned up properly later) + +- //! @todo SQLite probably doesn't allow this, but can we rely on that?? ++ // TODO: SQLite probably doesn't allow this, but can we rely on that?? + + // We don't need to remove orphaned albums at this point as in AddAlbum() we check + // first whether the album has already been read during this scan, and if it hasn't +@@ -5422,7 +5384,7 @@ bool CMusicDatabase::RemoveSongsFromPath(const std::string &path1, MAPSONGS& son + } + m_pDS->close(); + +- //! @todo move this below the m_pDS->exec block, once UPnP doesn't rely on this anymore ++ //TODO: move this below the m_pDS->exec block, once UPnP doesn't rely on this anymore + for (MAPSONGS::iterator songit = songs.begin(); songit != songs.end(); ++songit) + AnnounceRemove(MediaTypeSong, songit->second.idSong); + +diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h +index 0a23add..12c0d96 100644 +--- a/xbmc/music/MusicDatabase.h ++++ b/xbmc/music/MusicDatabase.h +@@ -23,7 +23,6 @@ + */ + #pragma once + #include +-#include + + #include "addons/Scraper.h" + #include "Album.h" +diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +index 25026b0..3fca559 100644 +--- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp ++++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +@@ -171,7 +171,16 @@ void CGUIDialogMusicInfo::SetAlbum(const CAlbum& album, const std::string &path) + m_album = album; + SetSongs(m_album.infoSongs); + *m_albumItem = CFileItem(path, true); +- m_albumItem->GetMusicInfoTag()->SetAlbum(m_album); ++ m_albumItem->GetMusicInfoTag()->SetAlbum(m_album.strAlbum); ++ m_albumItem->GetMusicInfoTag()->SetAlbumArtist(m_album.GetAlbumArtist()); ++ m_albumItem->GetMusicInfoTag()->SetArtist(m_album.GetAlbumArtist()); ++ m_albumItem->GetMusicInfoTag()->SetYear(m_album.iYear); ++ m_albumItem->GetMusicInfoTag()->SetLoaded(true); ++ m_albumItem->GetMusicInfoTag()->SetRating(m_album.fRating); ++ m_albumItem->GetMusicInfoTag()->SetVotes(m_album.iVotes); ++ m_albumItem->GetMusicInfoTag()->SetUserrating(m_album.iUserrating); ++ m_albumItem->GetMusicInfoTag()->SetGenre(m_album.genre); ++ m_albumItem->GetMusicInfoTag()->SetDatabaseId(m_album.idAlbum, MediaTypeAlbum); + CMusicDatabase::SetPropertiesFromAlbum(*m_albumItem,m_album); + + CMusicThumbLoader loader; +@@ -342,8 +351,8 @@ void CGUIDialogMusicInfo::SetUserrating(int userrating) const + // 3. Local thumb + // 4. No thumb (if no Local thumb is available) + +-//! @todo Currently no support for "embedded thumb" as there is no easy way to grab it +-//! without sending a file that has this as it's album to this class ++// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it ++// without sending a file that has this as it's album to this class + void CGUIDialogMusicInfo::OnGetThumb() + { + CFileItemList items; +@@ -373,7 +382,7 @@ void CGUIDialogMusicInfo::OnGetThumb() + item->SetIconImage("DefaultPicture.png"); + item->SetLabel(g_localizeStrings.Get(20015)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + // CTextureCache::GetInstance().ClearCachedImage(thumb); + items.Add(item); + } +@@ -475,7 +484,7 @@ void CGUIDialogMusicInfo::OnGetFanart() + item->SetIconImage("DefaultPicture.png"); + item->SetLabel(g_localizeStrings.Get(20441)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + // CTextureCache::GetInstance().ClearCachedImage(thumb); + items.Add(item); + } +@@ -493,7 +502,7 @@ void CGUIDialogMusicInfo::OnGetFanart() + itemLocal->SetArt("thumb", strLocal); + itemLocal->SetLabel(g_localizeStrings.Get(20438)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + CTextureCache::GetInstance().ClearCachedImage(strLocal); + items.Add(itemLocal); + } +diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.cpp b/xbmc/music/dialogs/GUIDialogSongInfo.cpp +index 8be349c..a7c97fa 100644 +--- a/xbmc/music/dialogs/GUIDialogSongInfo.cpp ++++ b/xbmc/music/dialogs/GUIDialogSongInfo.cpp +@@ -235,7 +235,7 @@ CFileItemPtr CGUIDialogSongInfo::GetCurrentListItem(int offset) + + bool CGUIDialogSongInfo::DownloadThumbnail(const std::string &thumbFile) + { +- //! @todo Obtain the source... ++ // TODO: Obtain the source... + std::string source; + CCurlFile http; + http.Download(source, thumbFile); +@@ -249,8 +249,8 @@ bool CGUIDialogSongInfo::DownloadThumbnail(const std::string &thumbFile) + // 3. Local thumb + // 4. No thumb (if no Local thumb is available) + +-//! @todo Currently no support for "embedded thumb" as there is no easy way to grab it +-//! without sending a file that has this as it's album to this class ++// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it ++// without sending a file that has this as it's album to this class + void CGUIDialogSongInfo::OnGetThumb() + { + CFileItemList items; +diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp +index 1ebc77e..22dc78d 100644 +--- a/xbmc/music/infoscanner/MusicInfoScanner.cpp ++++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp +@@ -740,7 +740,7 @@ void CMusicInfoScanner::FileItemsToAlbums(CFileItemList& items, VECALBUMS& album + { + if ((*k)->GetAlbumArtist().empty()) + (*k)->SetAlbumArtist(common); +- //! @todo in future we may wish to union up the genres, for now we assume they're the same ++ // TODO: in future we may wish to union up the genres, for now we assume they're the same + album.genre = (*k)->genre; + // in addition, we may want to use year as discriminating for albums + album.iYear = (*k)->iYear; +diff --git a/xbmc/music/infoscanner/MusicInfoScanner.h b/xbmc/music/infoscanner/MusicInfoScanner.h +index 5584b91..ac1ae92 100644 +--- a/xbmc/music/infoscanner/MusicInfoScanner.h ++++ b/xbmc/music/infoscanner/MusicInfoScanner.h +@@ -167,7 +167,7 @@ public: + */ + std::map GetArtistArtwork(const CArtist& artist); + protected: +- virtual void Process() override; ++ virtual void Process(); + + /*! \brief Scan in the ID3/Ogg/FLAC tags for a bunch of FileItems + Given a list of FileItems, scan in the tags for those FileItems +@@ -191,7 +191,7 @@ protected: + + bool DoScan(const std::string& strDirectory) override; + +- virtual void Run() override; ++ virtual void Run(); + int CountFiles(const CFileItemList& items, bool recursive); + int CountFilesRecursively(const std::string& strPath); + +diff --git a/xbmc/music/infoscanner/MusicInfoScraper.cpp b/xbmc/music/infoscanner/MusicInfoScraper.cpp +index 3489ba6..b9fc76a 100644 +--- a/xbmc/music/infoscanner/MusicInfoScraper.cpp ++++ b/xbmc/music/infoscanner/MusicInfoScraper.cpp +@@ -193,8 +193,8 @@ void CMusicInfoScraper::Process() + bool CMusicInfoScraper::CheckValidOrFallback(const std::string &fallbackScraper) + { + return true; +-//! @todo Handle fallback mechanism +-/* ++/* ++ * TODO handle fallback mechanism + if (m_scraper->Path() != fallbackScraper && + parser.Load("special://xbmc/system/scrapers/music/" + fallbackScraper)) + { +diff --git a/xbmc/music/infoscanner/MusicInfoScraper.h b/xbmc/music/infoscanner/MusicInfoScraper.h +index b5f3188..fa9a977 100644 +--- a/xbmc/music/infoscanner/MusicInfoScraper.h ++++ b/xbmc/music/infoscanner/MusicInfoScraper.h +@@ -20,8 +20,6 @@ + * + */ + +-#include +- + #include "MusicAlbumInfo.h" + #include "MusicArtistInfo.h" + #include "addons/Scraper.h" +diff --git a/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp b/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp +index 19872f8..aa15153 100644 +--- a/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp ++++ b/xbmc/music/tags/MusicInfoTagLoaderFactory.cpp +@@ -80,7 +80,6 @@ IMusicInfoTagLoader* CMusicInfoTagLoaderFactory::CreateLoader(const CFileItem& i + strExtension == "m4a" || strExtension == "mp4" || + strExtension == "mpc" || strExtension == "mpp" || strExtension == "mp+" || + strExtension == "ogg" || strExtension == "oga" || strExtension == "oggstream" || +- strExtension == "opus" || + strExtension == "aif" || strExtension == "aiff" || + strExtension == "wav" || + strExtension == "mod" || +@@ -103,7 +102,7 @@ IMusicInfoTagLoader* CMusicInfoTagLoaderFactory::CreateLoader(const CFileItem& i + return (IMusicInfoTagLoader*)pTagLoader; + } + else if (strExtension == "mka" || strExtension == "dsf" || +- strExtension == "dff") ++ strExtension == "dff" || strExtension == "opus") + return new CMusicInfoTagLoaderFFmpeg(); + + return NULL; +diff --git a/xbmc/music/tags/MusicInfoTagLoaderShn.cpp b/xbmc/music/tags/MusicInfoTagLoaderShn.cpp +index ee37747..b2d25fd 100644 +--- a/xbmc/music/tags/MusicInfoTagLoaderShn.cpp ++++ b/xbmc/music/tags/MusicInfoTagLoaderShn.cpp +@@ -36,7 +36,7 @@ bool CMusicInfoTagLoaderSHN::Load(const std::string& strFileName, CMusicInfoTag& + { + + tag.SetURL(strFileName); +- tag.SetDuration((long)0); //! @todo Use libavformat to calculate duration. ++ tag.SetDuration((long)0); //TODO: Use libavformat to calculate duration. + tag.SetLoaded(false); + + return true; +diff --git a/xbmc/music/tags/TagLoaderTagLib.cpp b/xbmc/music/tags/TagLoaderTagLib.cpp +index 45d6408..004849a 100644 +--- a/xbmc/music/tags/TagLoaderTagLib.cpp ++++ b/xbmc/music/tags/TagLoaderTagLib.cpp +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -420,7 +419,7 @@ bool CTagLoaderTagLib::ParseTag(ID3v2::Tag *id3v2, MUSIC_INFO::EmbeddedArt *art, + + // @xbmc.org ratings trump others (of course) + if (popFrame->email() == "ratings@xbmc.org") +- tag.SetUserrating(popFrame->rating() / 51); //! @todo wtf? Why 51 find some explanation, somewhere... ++ tag.SetUserrating(popFrame->rating() / 51); //TODO wtf? Why 51 find some explanation, somewhere... + else if (tag.GetUserrating() == 0) + { + if (popFrame->email() != "Windows Media Player 9 Series" && +@@ -651,7 +650,6 @@ bool CTagLoaderTagLib::ParseTag(Ogg::XiphComment *xiph, EmbeddedArt *art, CMusic + if (iUserrating > 0 && iUserrating <= 100) + tag.SetUserrating((iUserrating / 10)); + } +-#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11 + else if (it->first == "METADATA_BLOCK_PICTURE") + { + const char* b64 = it->second.front().toCString(); +@@ -678,12 +676,10 @@ bool CTagLoaderTagLib::ParseTag(Ogg::XiphComment *xiph, EmbeddedArt *art, CMusic + { + pictures[2].setMimeType(it->second.front()); + } +-#endif + else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) + CLog::Log(LOGDEBUG, "unrecognized XipComment name: %s", it->first.toCString(true)); + } + +-#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11 + // Process the extracted picture frames; 0 = CoverArt, 1 = Other, 2 = COVERART/COVERARTMIME + for (int i = 0; i < 3; ++i) + if (pictures[i].data().size()) +@@ -698,29 +694,6 @@ bool CTagLoaderTagLib::ParseTag(Ogg::XiphComment *xiph, EmbeddedArt *art, CMusic + + break; + } +-#else +- auto pictureList = xiph->pictureList(); +- FLAC::Picture *cover[2] = {}; +- +- for (auto i: pictureList) +- { +- FLAC::Picture *picture = i; +- if (picture->type() == FLAC::Picture::FrontCover) +- cover[0] = picture; +- else // anything else is taken as second priority +- cover[1] = picture; +- } +- for (unsigned int i = 0; i < 2; i++) +- { +- if (cover[i]) +- { +- tag.SetCoverArtInfo(cover[i]->data().size(), cover[i]->mimeType().to8Bit(true)); +- if (art) +- art->set(reinterpret_cast(cover[i]->data().data()), cover[i]->data().size(), cover[i]->mimeType().to8Bit(true)); +- break; // one is enough +- } +- } +-#endif + + if (xiph->comment() != String::null) + tag.SetComment(xiph->comment().toCString(true)); +@@ -1023,7 +996,6 @@ bool CTagLoaderTagLib::Load(const std::string& strFileName, CMusicInfoTag& tag, + TagLib::MPEG::File* mpegFile = nullptr; + TagLib::Ogg::Vorbis::File* oggVorbisFile = nullptr; + TagLib::Ogg::FLAC::File* oggFlacFile = nullptr; +- TagLib::Ogg::Opus::File* oggOpusFile = nullptr; + TagLib::TrueAudio::File* ttaFile = nullptr; + TagLib::WavPack::File* wvFile = nullptr; + TagLib::RIFF::WAV::File * wavFile = nullptr; +@@ -1063,8 +1035,6 @@ bool CTagLoaderTagLib::Load(const std::string& strFileName, CMusicInfoTag& tag, + file = new XM::File(stream); + else if (strExtension == "ogg") + file = oggVorbisFile = new Ogg::Vorbis::File(stream); +- else if (strExtension == "opus") +- file = oggOpusFile = new Ogg::Opus::File(stream); + else if (strExtension == "oga") // Leave this madness until last - oga container can have Vorbis or FLAC + { + file = oggFlacFile = new Ogg::FLAC::File(stream); +@@ -1118,8 +1088,6 @@ bool CTagLoaderTagLib::Load(const std::string& strFileName, CMusicInfoTag& tag, + xiph = dynamic_cast(oggFlacFile->tag()); + else if (oggVorbisFile) + xiph = dynamic_cast(oggVorbisFile->tag()); +- else if (oggOpusFile) +- xiph = dynamic_cast(oggOpusFile->tag()); + else if (ttaFile) + id3v2 = ttaFile->ID3v2Tag(false); + else if (aiffFile) +diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp +index 2e0c897..2a1fdc6 100644 +--- a/xbmc/music/windows/GUIWindowMusicBase.cpp ++++ b/xbmc/music/windows/GUIWindowMusicBase.cpp +@@ -62,9 +62,8 @@ + #include "URL.h" + #include "music/infoscanner/MusicInfoScanner.h" + #include "guiinfo/GUIInfoLabels.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "cores/IPlayer.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "CueDocument.h" + #include "Autorun.h" + +@@ -81,6 +80,7 @@ using namespace MUSIC_INFO; + #define CONTROL_BTNVIEWASICONS 2 + #define CONTROL_BTNSORTBY 3 + #define CONTROL_BTNSORTASC 4 ++#define CONTROL_BTNTYPE 5 + #define CONTROL_BTNPLAYLISTS 7 + #define CONTROL_BTNSCAN 9 + #define CONTROL_BTNREC 10 +@@ -122,6 +122,7 @@ bool CGUIWindowMusicBase::OnBack(int actionID) + ... the base class reacts on the following controls:\n + Buttons:\n + - #CONTROL_BTNVIEWASICONS - switch between list, thumb and with large items ++ - #CONTROL_BTNTYPE - switch between music windows + - #CONTROL_BTNSEARCH - Search for items\n + Other Controls: + - The container controls\n +@@ -151,6 +152,14 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) + if (!CGUIMediaWindow::OnMessage(message)) + return false; + ++ // save current window, unless the current window is the music playlist window ++ if (GetID() != WINDOW_MUSIC_PLAYLIST && ++ CSettings::GetInstance().GetInt(CSettings::SETTING_MYMUSIC_STARTWINDOW) != GetID()) ++ { ++ CSettings::GetInstance().SetInt(CSettings::SETTING_MYMUSIC_STARTWINDOW, GetID()); ++ CSettings::GetInstance().Save(); ++ } ++ + return true; + } + break; +@@ -178,7 +187,26 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); +- if (iControl == CONTROL_BTNRIP) ++ if (iControl == CONTROL_BTNTYPE) ++ { ++ CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_BTNTYPE); ++ g_windowManager.SendMessage(msg); ++ ++ int nWindow = WINDOW_MUSIC_FILES + msg.GetParam1(); ++ ++ if (nWindow == GetID()) ++ return true; ++ ++ CSettings::GetInstance().SetInt(CSettings::SETTING_MYMUSIC_STARTWINDOW, nWindow); ++ CSettings::GetInstance().Save(); ++ g_windowManager.ChangeActiveWindow(nWindow); ++ ++ CGUIMessage msg2(GUI_MSG_SETFOCUS, CSettings::GetInstance().GetInt(CSettings::SETTING_MYMUSIC_STARTWINDOW), CONTROL_BTNTYPE); ++ g_windowManager.SendMessage(msg2); ++ ++ return true; ++ } ++ else if (iControl == CONTROL_BTNRIP) + { + OnRipCD(); + } +@@ -224,6 +252,13 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) + if (m_vecItems->IsPath("special://musicplaylists/")) + OnDeleteItem(iItem); + ++ // or be at the files window and have file deletion enabled ++ else if (GetID() == WINDOW_MUSIC_FILES && ++ CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_ALLOWFILEDELETION)) ++ { ++ OnDeleteItem(iItem); ++ } ++ + else + return false; + } +@@ -457,7 +492,7 @@ bool CGUIWindowMusicBase::ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo / + { + if (!CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) + { +- //! @todo should display a dialog saying no permissions ++ // TODO: should display a dialog saying no permissions + if (m_dlgProgress) + m_dlgProgress->Close(); + return false; +@@ -551,7 +586,7 @@ void CGUIWindowMusicBase::RetrieveMusicInfo() + + OnRetrieveMusicInfo(*m_vecItems); + +- //! @todo Scan for multitrack items here... ++ // \todo Scan for multitrack items here... + std::vector itemsForRemove; + CFileItemList itemsForAdd; + for (int i = 0; i < m_vecItems->Size(); ++i) +@@ -732,6 +767,26 @@ void CGUIWindowMusicBase::AddItemToPlayList(const CFileItemPtr &pItem, CFileItem + + void CGUIWindowMusicBase::UpdateButtons() + { ++ // Update window selection control ++ ++ // Remove labels from the window selection ++ CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_BTNTYPE); ++ g_windowManager.SendMessage(msg); ++ ++ // Add labels to the window selection ++ CGUIMessage msg2(GUI_MSG_LABEL_ADD, GetID(), CONTROL_BTNTYPE); ++ msg2.SetLabel(g_localizeStrings.Get(744)); // Files ++ g_windowManager.SendMessage(msg2); ++ ++ msg2.SetLabel(g_localizeStrings.Get(14022)); // Library ++ g_windowManager.SendMessage(msg2); ++ ++ msg2.SetLabel(g_localizeStrings.Get(20389)); // Music Videos ++ g_windowManager.SendMessage(msg2); ++ ++ // Select the current window as default item ++ CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, CSettings::GetInstance().GetInt(CSettings::SETTING_MYMUSIC_STARTWINDOW) - WINDOW_MUSIC_FILES); ++ + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTNRIP, g_mediaManager.IsAudio()); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTNSCAN, +@@ -1038,7 +1093,7 @@ void CGUIWindowMusicBase::PlayItem(int iItem) + else + { + // just a single item, play it +- //! @todo Add music-specific code for single playback of an item here (See OnClick in MediaWindow, and OnPlayMedia below) ++ // TODO: Add music-specific code for single playback of an item here (See OnClick in MediaWindow, and OnPlayMedia below) + OnClick(iItem); + } + } +@@ -1093,7 +1148,7 @@ bool CGUIWindowMusicBase::OnPlayMedia(int iItem, const std::string &player) + // following etc. + if ( (CSettings::GetInstance().GetBool(CSettings::SETTING_MUSICPLAYER_QUEUEBYDEFAULT) && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST_EDITOR) ) + { +- //! @todo Should the playlist be cleared if nothing is already playing? ++ // TODO: Should the playlist be cleared if nothing is already playing? + OnQueueItem(iItem); + return true; + } +@@ -1163,8 +1218,8 @@ void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const std::string &pa + + // update the file listing - we have to update the whole lot, as it's likely that + // more than just our thumbnaias changed +- //! @todo Ideally this would only be done when needed - at the moment we appear to be +- //! doing this for every lookup, possibly twice (see ShowAlbumInfo) ++ // TODO: Ideally this would only be done when needed - at the moment we appear to be ++ // doing this for every lookup, possibly twice (see ShowAlbumInfo) + Refresh(true); + + // Do we have to autoswitch to the thumb control? +@@ -1346,8 +1401,8 @@ void CGUIWindowMusicBase::OnScan(int iItem) + else if (m_vecItems->Get(iItem)->m_bIsFolder) + strPath = m_vecItems->Get(iItem)->GetPath(); + else +- { //! @todo MUSICDB - should we allow scanning a single item into the database? +- //! This will require changes to the info scanner, which assumes we're running on a folder ++ { // TODO: MUSICDB - should we allow scanning a single item into the database? ++ // This will require changes to the info scanner, which assumes we're running on a folder + strPath = m_vecItems->GetPath(); + } + DoScan(strPath); +diff --git a/xbmc/music/windows/GUIWindowMusicBase.h b/xbmc/music/windows/GUIWindowMusicBase.h +index 6d26e8d..11c22da 100644 +--- a/xbmc/music/windows/GUIWindowMusicBase.h ++++ b/xbmc/music/windows/GUIWindowMusicBase.h +@@ -23,8 +23,6 @@ + * + */ + +-#include +- + #include "windows/GUIMediaWindow.h" + #include "music/MusicDatabase.h" + #include "music/infoscanner/MusicInfoScraper.h" +diff --git a/xbmc/music/windows/GUIWindowMusicNav.h b/xbmc/music/windows/GUIWindowMusicNav.h +index 5954d28..e648db0 100644 +--- a/xbmc/music/windows/GUIWindowMusicNav.h ++++ b/xbmc/music/windows/GUIWindowMusicNav.h +@@ -32,22 +32,22 @@ public: + CGUIWindowMusicNav(void); + virtual ~CGUIWindowMusicNav(void); + +- virtual bool OnMessage(CGUIMessage& message) override; +- virtual bool OnAction(const CAction& action) override; +- virtual void FrameMove() override; ++ virtual bool OnMessage(CGUIMessage& message); ++ virtual bool OnAction(const CAction& action); ++ virtual void FrameMove(); + + protected: +- virtual void OnItemLoaded(CFileItem* pItem) override {}; ++ virtual void OnItemLoaded(CFileItem* pItem) {}; + // override base class methods +- virtual bool Update(const std::string &strDirectory, bool updateFilterPath = true) override; +- virtual bool GetDirectory(const std::string &strDirectory, CFileItemList &items) override; +- virtual void UpdateButtons() override; +- virtual void PlayItem(int iItem) override; +- virtual void OnWindowLoaded() override; +- virtual void GetContextButtons(int itemNumber, CContextButtons &buttons) override; +- virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override; ++ virtual bool Update(const std::string &strDirectory, bool updateFilterPath = true); ++ virtual bool GetDirectory(const std::string &strDirectory, CFileItemList &items); ++ virtual void UpdateButtons(); ++ virtual void PlayItem(int iItem); ++ virtual void OnWindowLoaded(); ++ virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); ++ virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + virtual bool OnClick(int iItem, const std::string &player = "") override; +- virtual std::string GetStartFolder(const std::string &url) override; ++ virtual std::string GetStartFolder(const std::string &url); + + bool GetSongsFromPlayList(const std::string& strPlayList, CFileItemList &items); + std::string GetQuickpathName(const std::string& strPath) const; +diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp +index c846e66..fa7e871 100644 +--- a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp ++++ b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp +@@ -26,7 +26,6 @@ + #include "Application.h" + #include "PlayListPlayer.h" + #include "PartyModeManager.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "utils/LabelFormatter.h" + #include "music/tags/MusicInfoTag.h" + #include "guilib/GUIWindowManager.h" +diff --git a/xbmc/music/windows/GUIWindowVisualisation.cpp b/xbmc/music/windows/GUIWindowVisualisation.cpp +index a4a371f..fd47ec2 100644 +--- a/xbmc/music/windows/GUIWindowVisualisation.cpp ++++ b/xbmc/music/windows/GUIWindowVisualisation.cpp +@@ -112,8 +112,8 @@ bool CGUIWindowVisualisation::OnAction(const CAction &action) + g_infoManager.SetShowInfo(true); + } + break; +- //! @todo These should be mapped to it's own function - at the moment it's overriding +- //! the global action of fastforward/rewind and OSD. ++ // TODO: These should be mapped to it's own function - at the moment it's overriding ++ // the global action of fastforward/rewind and OSD. + /* case KEY_BUTTON_Y: + g_application.m_CdgParser.Pause(); + return true; +diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp +index 7dede5d..ca809ad 100644 +--- a/xbmc/network/AirPlayServer.cpp ++++ b/xbmc/network/AirPlayServer.cpp +@@ -37,7 +37,6 @@ + #include "FileItem.h" + #include "Application.h" + #include "messaging/ApplicationMessenger.h" +-#include "PlayListPlayer.h" + #include "utils/md5.h" + #include "utils/Variant.h" + #include "settings/Settings.h" +diff --git a/xbmc/network/AirPlayServer.h b/xbmc/network/AirPlayServer.h +index 46f80d6..971d464 100644 +--- a/xbmc/network/AirPlayServer.h ++++ b/xbmc/network/AirPlayServer.h +@@ -26,7 +26,6 @@ + #ifdef HAS_AIRPLAY + + #include +-#include + #include + #include "threads/Thread.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp +index 72a06dc..e1a6c7d 100644 +--- a/xbmc/network/AirTunesServer.cpp ++++ b/xbmc/network/AirTunesServer.cpp +@@ -37,7 +37,6 @@ + #include "filesystem/PipeFile.h" + #include "GUIInfoManager.h" + #include "guilib/GUIWindowManager.h" +-#include "input/Key.h" + #include "interfaces/AnnouncementManager.h" + #include "messaging/ApplicationMessenger.h" + #include "music/tags/MusicInfoTag.h" +diff --git a/xbmc/network/DNSNameCache.cpp b/xbmc/network/DNSNameCache.cpp +index f12c782..e1a8ec4 100644 +--- a/xbmc/network/DNSNameCache.cpp ++++ b/xbmc/network/DNSNameCache.cpp +@@ -22,6 +22,8 @@ + #include "threads/SingleLock.h" + #include "utils/log.h" + #include "utils/StringUtils.h" ++#include "network/Network.h" ++#include "Application.h" + + #include + #include +@@ -32,25 +34,37 @@ CDNSNameCache g_DNSCache; + CCriticalSection CDNSNameCache::m_critical; + + CDNSNameCache::CDNSNameCache(void) +-{} ++{ ++} + + CDNSNameCache::~CDNSNameCache(void) +-{} ++{ ++} ++ ++void CDNSNameCache::Flush() ++{ ++ CSingleLock lock(m_critical); ++ CLog::Log(LOGINFO, "%s - DNS cache flushed (%u records)", __FUNCTION__, g_DNSCache.m_vecDNSNames.size()); ++ g_DNSCache.m_vecDNSNames.clear(); ++} + + bool CDNSNameCache::Lookup(const std::string& strHostName, std::string& strIpAddress) + { + if (strHostName.empty() && strIpAddress.empty()) + return false; + +- // first see if this is already an ip address +- unsigned long address = inet_addr(strHostName.c_str()); + strIpAddress.clear(); +- +- if (address != INADDR_NONE) ++ // first see if this is already an ip address + { +- strIpAddress = StringUtils::Format("%lu.%lu.%lu.%lu", (address & 0xFF), (address & 0xFF00) >> 8, (address & 0xFF0000) >> 16, (address & 0xFF000000) >> 24 ); +- return true; ++ struct sockaddr_in sa; ++ ++ if (CNetwork::ConvIPv6(strHostName)) ++ strIpAddress = CNetwork::CanonizeIPv6(strHostName); ++ else if (CNetwork::ConvIPv4(strHostName, &sa)) ++ strIpAddress = inet_ntoa(sa.sin_addr); + } ++ if (!strIpAddress.empty()) ++ return true; + + // check if there's a custom entry or if it's already cached + if(g_DNSCache.GetCached(strHostName, strIpAddress)) +@@ -84,20 +98,56 @@ bool CDNSNameCache::Lookup(const std::string& strHostName, std::string& strIpAdd + #endif + + // perform dns lookup +- struct hostent *host = gethostbyname(strHostName.c_str()); +- if (host && host->h_addr_list[0]) ++ struct addrinfo hints; ++ struct addrinfo *result = NULL; ++ ++ memset(&hints, 0, sizeof(struct addrinfo)); ++ int err; ++ ++ // prefer DNS record type (A vs AAAA) be the same as active interface(address). ++ // otherwise (by default) system prefers A(IPv4) records. this can make ++ // troubles on dual stack configured hosts or even make network access completely ++ // unusable in case of pure IPv6 configuration because returning IPv4 record as first. ++ ++ // (NOTE/TODO: we might consider for future iterating via all returned results, ++ // while checking accessibiity and use record which we can access. For now we just grab ++ // first record from returned list). ++ do + { +- strIpAddress = StringUtils::Format("%d.%d.%d.%d", +- (unsigned char)host->h_addr_list[0][0], +- (unsigned char)host->h_addr_list[0][1], +- (unsigned char)host->h_addr_list[0][2], +- (unsigned char)host->h_addr_list[0][3]); ++ if (result) ++ freeaddrinfo(result); ++ hints.ai_family = hints.ai_family == 0 ? g_application.getNetwork().GetFirstConnectedFamily() : AF_UNSPEC; ++ err = getaddrinfo(strHostName.c_str(), NULL, &hints, &result); ++ } while ((err || !result) && hints.ai_family != AF_UNSPEC); ++ ++ std::string str_err; ++ if (err) ++ str_err = gai_strerror(err); ++ ++ bool bReturn; ++ if (result) ++ { ++ strIpAddress = CNetwork::GetIpStr(result->ai_addr); ++ freeaddrinfo(result); ++ CLog::Log(LOGDEBUG, "%s - %s", __FUNCTION__, strIpAddress.c_str()); + g_DNSCache.Add(strHostName, strIpAddress); +- return true; ++ bReturn = true; ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "Unable to lookup host: '%s' (err detail: %s)", strHostName.c_str(), str_err.c_str()); ++ bReturn = false; + } + +- CLog::Log(LOGERROR, "Unable to lookup host: '%s'", strHostName.c_str()); +- return false; ++ return bReturn; ++} ++ ++std::string CDNSNameCache::Lookup(const std::string& strHostName) ++{ ++ std::string ip; ++ ++ Lookup(strHostName, ip); ++ return ip; + } + + bool CDNSNameCache::GetCached(const std::string& strHostName, std::string& strIpAddress) +diff --git a/xbmc/network/DNSNameCache.h b/xbmc/network/DNSNameCache.h +index 97bb20b..126a980 100644 +--- a/xbmc/network/DNSNameCache.h ++++ b/xbmc/network/DNSNameCache.h +@@ -27,6 +27,8 @@ class CCriticalSection; + + class CDNSNameCache + { ++friend class CNetwork; ++ + public: + class CDNSName + { +@@ -37,9 +39,13 @@ public: + CDNSNameCache(void); + virtual ~CDNSNameCache(void); + static bool Lookup(const std::string& strHostName, std::string& strIpAddress); ++ static std::string Lookup(const std::string& strHostName); + static void Add(const std::string& strHostName, const std::string& strIpAddress); + + protected: ++ static void Flush(); ++ ++private: + static bool GetCached(const std::string& strHostName, std::string& strIpAddress); + static CCriticalSection m_critical; + std::vector m_vecDNSNames; +diff --git a/xbmc/network/EventClient.cpp b/xbmc/network/EventClient.cpp +index 9715f2c..80ab25a 100644 +--- a/xbmc/network/EventClient.cpp ++++ b/xbmc/network/EventClient.cpp +@@ -135,7 +135,7 @@ bool CEventClient::AddPacket(CEventPacket *packet) + ResetTimeout(); + if ( packet->Size() > 1 ) + { +- //! @todo limit payload size ++ // TODO: limit payload size + if (m_seqPackets[ packet->Sequence() ]) + { + if(!m_bSequenceError) +@@ -276,8 +276,8 @@ bool CEventClient::ProcessPacket(CEventPacket *packet) + + bool CEventClient::OnPacketHELO(CEventPacket *packet) + { +- //! @todo check it last HELO packet was received less than 5 minutes back +- //! if so, do not show notification of connection. ++ // TODO: check it last HELO packet was received less than 5 minutes back ++ // if so, do not show notification of connection. + if (Greeted()) + return false; + +diff --git a/xbmc/network/EventPacket.h b/xbmc/network/EventPacket.h +index d436612..694cfcf 100644 +--- a/xbmc/network/EventPacket.h ++++ b/xbmc/network/EventPacket.h +@@ -163,7 +163,6 @@ namespace EVENTPACKET + + PT_BROADCAST = 0x06, + /************************************************************************/ +- /* @todo implement */ + /* Payload format: TODO */ + /************************************************************************/ + +diff --git a/xbmc/network/GUIDialogNetworkSetup.cpp b/xbmc/network/GUIDialogNetworkSetup.cpp +index 51b8425..58003ed 100644 +--- a/xbmc/network/GUIDialogNetworkSetup.cpp ++++ b/xbmc/network/GUIDialogNetworkSetup.cpp +@@ -208,6 +208,9 @@ void CGUIDialogNetworkSetup::InitializeSettings() + #ifdef HAS_FILESYSTEM_SFTP + labels.push_back(std::make_pair(20260, NET_PROTOCOL_SFTP)); + #endif ++#ifdef HAS_FILESYSTEM_AFP ++ labels.push_back(std::make_pair(20261, NET_PROTOCOL_AFP)); ++#endif + + AddSpinner(group, SETTING_PROTOCOL, 1008, 0, m_protocol, labels); + AddEdit(group, SETTING_SERVER_ADDRESS, 1010, 0, m_server, true); +@@ -379,7 +382,8 @@ void CGUIDialogNetworkSetup::UpdateButtons() + m_protocol == NET_PROTOCOL_DAV || + m_protocol == NET_PROTOCOL_DAVS || + m_protocol == NET_PROTOCOL_RSS || +- m_protocol == NET_PROTOCOL_SFTP)); ++ m_protocol == NET_PROTOCOL_SFTP || ++ m_protocol == NET_PROTOCOL_AFP)); + } + } + +@@ -406,6 +410,8 @@ std::string CGUIDialogNetworkSetup::ConstructPath() const + url.SetProtocol("nfs"); + else if (m_protocol == NET_PROTOCOL_SFTP) + url.SetProtocol("sftp"); ++ else if (m_protocol == NET_PROTOCOL_AFP) ++ url.SetProtocol("afp"); + + if (!m_username.empty()) + { +@@ -455,6 +461,8 @@ void CGUIDialogNetworkSetup::SetPath(const std::string &path) + m_protocol = NET_PROTOCOL_NFS; + else if (url.IsProtocol("sftp") || url.IsProtocol("ssh")) + m_protocol = NET_PROTOCOL_SFTP; ++ else if (url.IsProtocol("afp")) ++ m_protocol = NET_PROTOCOL_AFP; + else + m_protocol = NET_PROTOCOL_SMB; // default to smb + m_username = url.GetUserName(); +diff --git a/xbmc/network/GUIDialogNetworkSetup.h b/xbmc/network/GUIDialogNetworkSetup.h +index e42ff34..42b9ba6 100644 +--- a/xbmc/network/GUIDialogNetworkSetup.h ++++ b/xbmc/network/GUIDialogNetworkSetup.h +@@ -35,37 +35,38 @@ public: + NET_PROTOCOL_UPNP, + NET_PROTOCOL_RSS, + NET_PROTOCOL_SFTP, +- NET_PROTOCOL_NFS}; ++ NET_PROTOCOL_NFS, ++ NET_PROTOCOL_AFP}; + CGUIDialogNetworkSetup(void); + virtual ~CGUIDialogNetworkSetup(void); +- virtual bool OnMessage(CGUIMessage& message) override; +- virtual bool OnBack(int actionID) override; +- virtual void OnInitWindow() override; +- virtual void OnDeinitWindow(int nextWindowID) override; ++ virtual bool OnMessage(CGUIMessage& message); ++ virtual bool OnBack(int actionID); ++ virtual void OnInitWindow(); ++ virtual void OnDeinitWindow(int nextWindowID); + + static bool ShowAndGetNetworkAddress(std::string &path); + + std::string ConstructPath() const; + void SetPath(const std::string &path); +- bool IsConfirmed() const override { return m_confirmed; }; ++ bool IsConfirmed() const { return m_confirmed; }; + + protected: + // implementations of ISettingCallback +- virtual void OnSettingChanged(const CSetting *setting) override; +- virtual void OnSettingAction(const CSetting *setting) override; ++ virtual void OnSettingChanged(const CSetting *setting); ++ virtual void OnSettingAction(const CSetting *setting); + + // specialization of CGUIDialogSettingsBase + bool AllowResettingSettings() const override { return false; } +- virtual void Save() override { } +- virtual void SetupView() override; ++ virtual void Save() { } ++ virtual void SetupView(); + + // specialization of CGUIDialogSettingsManualBase +- virtual void InitializeSettings() override; ++ virtual void InitializeSettings(); + + void OnProtocolChange(); + void OnServerBrowse(); + void OnOK(); +- void OnCancel() override; ++ void OnCancel(); + void UpdateButtons(); + + NET_PROTOCOL m_protocol; +diff --git a/xbmc/network/Makefile.in b/xbmc/network/Makefile.in +index c80651c..4baa1ce 100644 +--- a/xbmc/network/Makefile.in ++++ b/xbmc/network/Makefile.in +@@ -27,3 +27,4 @@ LIB = network.a + + include @abs_top_srcdir@/Makefile.include + -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) ++CXXFLAGS += --std=c++11 -DHAVE_CHAR32_T -DHAVE_CHAR16_T +diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp +index 5247036..065afc8 100644 +--- a/xbmc/network/Network.cpp ++++ b/xbmc/network/Network.cpp +@@ -18,11 +18,16 @@ + * + */ + ++#include ++#include ++ + #include + #include + #include + ++#include "settings/Settings.h" + #include "Network.h" ++#include "DNSNameCache.h" + #include "messaging/ApplicationMessenger.h" + #include "network/NetworkServices.h" + #include "utils/log.h" +@@ -32,8 +37,32 @@ + #include "utils/CharsetConverter.h" + #endif + #include "utils/StringUtils.h" ++#include "xbmc/interfaces/AnnouncementManager.h" + + using namespace KODI::MESSAGING; ++using namespace ANNOUNCEMENT; ++ ++/* ++ * in all the geniality of new AF/AF6 compatible system functions & structs, ++ * most of *UNIX socket interface calls vitally depends on (struct)addr size to be specified. ++ * ++ * TODO for v18: as was initially discussed in PR#7030 let's define common 'ADT' to represent ++ * network entity (physical as well as logical ones (connectors/listeners/servers(services), ++ * but also interfaces, hosts). ++ * ++ * ((someone nicely started back in 2008 - xbmc/network/Socket.{cpp,h})) ++ */ ++socklen_t sa_len(struct sockaddr *addr) ++{ ++ switch(((struct sockaddr_storage*)addr)->ss_family) ++ { ++ case AF_INET: ++ return sizeof(struct sockaddr_in); ++ case AF_INET6: ++ return sizeof(struct sockaddr_in6); ++ } ++ return 0; ++} + + /* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */ + bool in_ether (const char *bufp, unsigned char *addr) +@@ -132,14 +161,61 @@ int NetworkAccessPoint::FreqToChannel(float frequency) + } + + +-CNetwork::CNetwork() ++CNetwork::CNetwork() : ++ m_bStop(false) + { +- CApplicationMessenger::GetInstance().PostMsg(TMSG_NETWORKMESSAGE, SERVICES_UP, 0); ++ m_signalNetworkChange.Reset(); + } + + CNetwork::~CNetwork() + { ++ m_bStop = true; ++ m_updThread->StopThread(false); ++ m_signalNetworkChange.Set(); + CApplicationMessenger::GetInstance().PostMsg(TMSG_NETWORKMESSAGE, SERVICES_DOWN, 0); ++ m_updThread->StopThread(true); ++} ++ ++std::string CNetwork::GetIpStr(const struct sockaddr *sa) ++{ ++ std::string result; ++ if (!sa) ++ return result; ++ ++ char s[INET6_ADDRSTRLEN] = {0}; ++ switch(sa->sa_family) ++ { ++ case AF_INET: ++ inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, INET6_ADDRSTRLEN); ++ break; ++ case AF_INET6: ++ inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, INET6_ADDRSTRLEN); ++ break; ++ default: ++ return result; ++ } ++ ++ result = s; ++ return result; ++} ++ ++std::string CNetwork::GetIpStr(unsigned long address) ++{ ++ struct in_addr in = { htonl(address) }; ++ std::string addr = inet_ntoa(in); ++ ++ return addr; ++} ++ ++bool CNetworkInterface::GetHostMacAddress(const std::string &host, std::string &mac) ++{ ++ struct sockaddr_in in; ++ ++ if (!CNetwork::ConvIPv4(host, &in)) ++ return false; ++ ++ unsigned long ip = in.sin_addr.s_addr; ++ return GetHostMacAddress(ip, mac); + } + + int CNetwork::ParseHex(char *str, unsigned char *addr) +@@ -161,6 +237,58 @@ int CNetwork::ParseHex(char *str, unsigned char *addr) + return len; + } + ++bool CNetwork::ConvIPv4(const std::string &address, struct sockaddr_in *sa, unsigned short port) ++{ ++ if (address.empty()) ++ return false; ++ ++ struct in_addr sin_addr; ++ int ret = inet_pton(AF_INET, address.c_str(), &sin_addr); ++ ++ if (ret > 0 && sa) ++ { ++ sa->sin_family = AF_INET; ++ sa->sin_port = htons(port); ++ memcpy(&(sa->sin_addr), &sin_addr, sizeof(struct in_addr)); ++ } ++ ++ return (ret > 0); ++} ++ ++bool CNetwork::ConvIPv6(const std::string &address, struct sockaddr_in6 *sa, unsigned short port) ++{ ++ if (address.empty()) ++ return false; ++ ++ struct in6_addr sin6_addr; ++ int ret = inet_pton(AF_INET6, address.c_str(), &sin6_addr); ++ ++ if (ret > 0 && sa) ++ { ++ sa->sin6_family = AF_INET6; ++ sa->sin6_port = htons((u_int16_t)port); ++ memcpy(&(sa->sin6_addr), &sin6_addr, sizeof(struct in6_addr)); ++ } ++ ++ return (ret > 0); ++} ++ ++struct sockaddr_storage *CNetwork::ConvIP(const std::string &address, unsigned short port) ++{ ++ struct sockaddr_storage *sa = NULL; ++ ++ if (!address.empty()) ++ if (sa = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_storage))) ++ if (ConvIPv4(address, (struct sockaddr_in *) sa, port) ++ || ConvIPv6(address, (struct sockaddr_in6 *) sa, port)) ++ return sa; ++ ++ if (sa) ++ free(sa); ++ ++ return NULL; ++} ++ + bool CNetwork::GetHostName(std::string& hostname) + { + char hostName[128]; +@@ -192,15 +320,12 @@ bool CNetwork::IsLocalHost(const std::string& hostname) + && StringUtils::EqualsNoCase(hostname, myhostname)) + return true; + +- std::vector& ifaces = GetInterfaceList(); +- std::vector::const_iterator iter = ifaces.begin(); +- while (iter != ifaces.end()) ++ myhostname = CanonizeIPv6(hostname); ++ if (ConvIPv4(myhostname) || ConvIPv6(myhostname)) + { +- CNetworkInterface* iface = *iter; +- if (iface && iface->GetCurrentIPAddress() == hostname) +- return true; +- +- ++iter; ++ for (auto &&iface: GetInterfaceList()) ++ if (iface && iface->GetCurrentIPAddress() == myhostname) ++ return true; + } + + return false; +@@ -208,45 +333,87 @@ bool CNetwork::IsLocalHost(const std::string& hostname) + + CNetworkInterface* CNetwork::GetFirstConnectedInterface() + { +- std::vector& ifaces = GetInterfaceList(); +- std::vector::const_iterator iter = ifaces.begin(); +- while (iter != ifaces.end()) +- { +- CNetworkInterface* iface = *iter; +- if (iface && iface->IsConnected()) +- return iface; +- ++iter; +- } ++ for (auto &&iface: GetInterfaceList()) ++ if (iface && iface->IsConnected()) ++ return iface; + + return NULL; + } + +-bool CNetwork::HasInterfaceForIP(unsigned long address) ++bool CNetwork::AddrMatch(const std::string &addr, const std::string &match_ip, const std::string &match_mask) + { +- unsigned long subnet; +- unsigned long local; +- std::vector& ifaces = GetInterfaceList(); +- std::vector::const_iterator iter = ifaces.begin(); +- while (iter != ifaces.end()) +- { +- CNetworkInterface* iface = *iter; +- if (iface && iface->IsConnected()) ++ if (ConvIPv4(addr) && ConvIPv4(match_ip) && ConvIPv4(match_mask)) ++ { ++ unsigned long address = ntohl(inet_addr(addr.c_str())); ++ unsigned long subnet = ntohl(inet_addr(match_mask.c_str())); ++ unsigned long local = ntohl(inet_addr(match_ip.c_str())); ++ return ((address & subnet) == (local & subnet)); ++ } ++ else if (!g_application.getNetwork().SupportsIPv6()) ++ { ++ return false; ++ } ++ else ++ { ++ struct sockaddr_in6 address; ++ struct sockaddr_in6 local; ++ struct sockaddr_in6 subnet; ++ if (!ConvIPv6(addr, &address) || !ConvIPv6(match_ip, &local) ++ || !ConvIPv6(match_mask, &subnet)) ++ return false; ++ ++ // mask matching of IPv6 follows same rule as for IPv4, only ++ // difference is the storage object of IPv6 address what ++ // is 16 segments of 8bit information (16bytes => 128bits) ++ // lets assume we match fd::2 against fd::1/16. this means ++ // for illustration: ++ // 00fd:0000:0000:0000:0000:0000:0000:0002 ++ // to ++ // 00fd:0000:0000:0000:0000:0000:0000:0001 with mask ++ // ffff:0000:0000:0000:0000:0000:0000:0000 ++ // as with IPv4, addr1 & mask == addr2 & mask - for each segment ++ ++ // despite the comment explaining uint_8[16] structure ++ // (what at the time of writing this text was valid for OSX/Linux/BSD) ++ // rather let's use type independent construction. this is because (OSX????) ++ // .h files commented the internal s6_addr structure type inside ++ // sockaddr_in6 as not being mandatory specified by RFC - devil never sleeps. ++ unsigned int m; ++ for (m = 0; m < sizeof(address.sin6_addr.s6_addr); m++) ++ if ((address.sin6_addr.s6_addr[m] & subnet.sin6_addr.s6_addr[m]) != ++ ( local.sin6_addr.s6_addr[m] & subnet.sin6_addr.s6_addr[m])) + { +- subnet = ntohl(inet_addr(iface->GetCurrentNetmask().c_str())); +- local = ntohl(inet_addr(iface->GetCurrentIPAddress().c_str())); +- if( (address & subnet) == (local & subnet) ) +- return true; ++ m = -1; + } +- ++iter; +- } + +- return false; ++ // in case of matching addresses, we loop through each segment, ++ // leaving m with final value of 16. ++ // if we don't match, m is set to .max() and for() is ended. ++ // RESULT: any value of m smaller than .max() indicates success. ++ if (m < (unsigned int)~0) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool CNetwork::HasInterfaceForIP(const std::string &address) ++{ ++ if (address.empty()) ++ return false; ++ ++ for (auto &&iface: GetInterfaceList()) ++ if (iface && iface->IsConnected() && ++ AddrMatch(address, iface->GetCurrentIPAddress(), iface->GetCurrentNetmask())) ++ return true; ++ ++ return false; + } + +-bool CNetwork::IsAvailable(void) ++bool CNetwork::HasInterfaceForIP(unsigned long address) + { +- std::vector& ifaces = GetInterfaceList(); +- return (ifaces.size() != 0); ++ std::string addr = GetIpStr(address); ++ return HasInterfaceForIP(addr); + } + + bool CNetwork::IsConnected() +@@ -256,15 +423,9 @@ bool CNetwork::IsConnected() + + CNetworkInterface* CNetwork::GetInterfaceByName(const std::string& name) + { +- std::vector& ifaces = GetInterfaceList(); +- std::vector::const_iterator iter = ifaces.begin(); +- while (iter != ifaces.end()) +- { +- CNetworkInterface* iface = *iter; +- if (iface && iface->GetName() == name) +- return iface; +- ++iter; +- } ++ for (auto &&iface: GetInterfaceList()) ++ if (iface && iface->GetName() == name) ++ return iface; + + return NULL; + } +@@ -274,7 +435,14 @@ void CNetwork::NetworkMessage(EMESSAGE message, int param) + switch( message ) + { + case SERVICES_UP: ++ if (GetInterfaceList().empty()) ++ { ++ CLog::Log(LOGDEBUG, "%s - There is no configured network interface. Not starting network services",__FUNCTION__); ++ break; ++ } ++ + CLog::Log(LOGDEBUG, "%s - Starting network services",__FUNCTION__); ++ CDNSNameCache::Flush(); + CNetworkServices::GetInstance().Start(); + break; + +@@ -284,6 +452,17 @@ void CNetwork::NetworkMessage(EMESSAGE message, int param) + CLog::Log(LOGDEBUG, "%s - Waiting for network services to stop",__FUNCTION__); + CNetworkServices::GetInstance().Stop(true); // wait for network services to stop + break; ++ ++ case NETWORK_CHANGED: ++ m_signalNetworkChange.Set(); ++ ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::Network, "network", "OnInterfacesChange"); ++ if (CSettings::GetInstance().GetBool(CSettings::SETTING_NETWORK_RESTARTSERVICES)) ++ { ++ CLog::Log(LOGDEBUG, "%s - Network setup changed. Will restart network services",__FUNCTION__); ++ NetworkMessage(SERVICES_DOWN, 0); ++ NetworkMessage(SERVICES_UP, 0); ++ } ++ break; + } + } + +@@ -294,6 +473,9 @@ bool CNetwork::WakeOnLan(const char* mac) + unsigned char buf [128]; + unsigned char *ptr; + ++ if (GetFirstConnectedFamily() == AF_INET6) ++ return false; ++ + // Fetch the hardware address + if (!in_ether(mac, ethaddr)) + { +@@ -345,7 +527,7 @@ bool CNetwork::WakeOnLan(const char* mac) + } + + // ping helper +-static const char* ConnectHostPort(SOCKET soc, const struct sockaddr_in& addr, struct timeval& timeOut, bool tryRead) ++static const char* ConnectHostPort(SOCKET soc, struct sockaddr *addr, struct timeval& timeOut, bool tryRead) + { + // set non-blocking + #ifdef TARGET_WINDOWS +@@ -358,7 +540,7 @@ static const char* ConnectHostPort(SOCKET soc, const struct sockaddr_in& addr, s + if (result != 0) + return "set non-blocking option failed"; + +- result = connect(soc, (struct sockaddr *)&addr, sizeof(addr)); // non-blocking connect, will fail .. ++ result = connect(soc, addr, sa_len(addr)); // non-blocking connect, will fail .. + + if (result < 0) + { +@@ -422,17 +604,17 @@ static const char* ConnectHostPort(SOCKET soc, const struct sockaddr_in& addr, s + return 0; // success + } + +-bool CNetwork::PingHost(unsigned long ipaddr, unsigned short port, unsigned int timeOutMs, bool readability_check) ++bool CNetwork::PingHost(const std::string &ipaddr, unsigned short port, unsigned int timeOutMs, bool readability_check) + { + if (port == 0) // use icmp ping +- return PingHost (ipaddr, timeOutMs); ++ return PingHostImpl (ipaddr, timeOutMs); + +- struct sockaddr_in addr; +- addr.sin_family = AF_INET; +- addr.sin_port = htons(port); +- addr.sin_addr.s_addr = ipaddr; ++ struct sockaddr_storage *addr = ConvIP(ipaddr, port); + +- SOCKET soc = socket(AF_INET, SOCK_STREAM, 0); ++ if (!addr) ++ return false; ++ ++ SOCKET soc = socket(addr->ss_family, SOCK_STREAM, 0); + + const char* err_msg = "invalid socket"; + +@@ -442,7 +624,7 @@ bool CNetwork::PingHost(unsigned long ipaddr, unsigned short port, unsigned int + tmout.tv_sec = timeOutMs / 1000; + tmout.tv_usec = (timeOutMs % 1000) * 1000; + +- err_msg = ConnectHostPort (soc, addr, tmout, readability_check); ++ err_msg = ConnectHostPort (soc, (struct sockaddr *)addr, tmout, readability_check); + + (void) closesocket (soc); + } +@@ -455,12 +637,72 @@ bool CNetwork::PingHost(unsigned long ipaddr, unsigned short port, unsigned int + std::string sock_err = strerror(errno); + #endif + +- CLog::Log(LOGERROR, "%s(%s:%d) - %s (%s)", __FUNCTION__, inet_ntoa(addr.sin_addr), port, err_msg, sock_err.c_str()); ++ CLog::Log(LOGERROR, "%s(%s:%d) - %s (%s)", __FUNCTION__, ipaddr.c_str(), port, err_msg, sock_err.c_str()); + } + ++ free(addr); + return err_msg == 0; + } + ++std::string CNetwork::CanonizeIPv6(const std::string &address) ++{ ++ std::string result = address; ++ ++ struct sockaddr_in6 addr; ++ if (!ConvIPv6(address, &addr)) ++ return result; ++ ++ result = GetIpStr((const sockaddr*)&addr); ++ return result; ++} ++ ++uint8_t CNetwork::PrefixLength(const struct sockaddr *netmask) ++{ ++ uint8_t prefixLength = 0; ++ switch (netmask->sa_family) ++ { ++ case AF_INET: ++ prefixLength = std::bitsetsin_addr.s_addr)>(((struct sockaddr_in *) netmask)->sin_addr.s_addr).count(); ++ break; ++ case AF_INET6: ++ for (unsigned int i = 0; i < sizeof(((struct sockaddr_in6 *) netmask)->sin6_addr.s6_addr); ++i) ++ prefixLength += std::bitsetsin6_addr.s6_addr)>(((struct sockaddr_in6 *) netmask)->sin6_addr.s6_addr[i]).count(); ++ break; ++ } ++ return prefixLength; ++} ++ ++bool CNetwork::CompareAddresses(const struct sockaddr * sa, const struct sockaddr * sb) ++{ ++ if (sa->sa_family != sb->sa_family) ++ return false; ++ else if (sa->sa_family == AF_INET) ++ return ((struct sockaddr_in *)(sa))->sin_addr.s_addr == ((struct sockaddr_in *)(sb))->sin_addr.s_addr; ++ else if (sa->sa_family == AF_INET6) ++ return (memcmp((char *) &(((struct sockaddr_in6 *)(sa))->sin6_addr), (char *) &(((struct sockaddr_in6 *)(sb))->sin6_addr), sizeof(((struct sockaddr_in6 *)(sa))->sin6_addr))) == 0; ++ return false; ++} ++ ++CNetwork::CNetworkUpdater::CNetworkUpdater(void (*watcher)(void *caller)) ++ : CThread("NetConfUpdater") ++ , m_watcher(watcher) ++{ ++ CAnnouncementManager::GetInstance().AddAnnouncer(this); ++} ++ ++CNetwork::CNetworkUpdater::~CNetworkUpdater() ++{ ++ CAnnouncementManager::GetInstance().RemoveAnnouncer(this); ++} ++ ++void CNetwork::CNetworkUpdater::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) ++{ ++ if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) ++ StopThread(false); ++ else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) ++ Create(false); ++} ++ + //creates, binds and listens a tcp socket on the desired port. Set bindLocal to + //true to bind to localhost only. The socket will listen over ipv6 if possible + //and fall back to ipv4 if ipv6 is not available on the platform. +@@ -507,7 +749,8 @@ int CreateTCPServerSocket(const int port, const bool bindLocal, const int backlo + { + closesocket(sock); + sock = -1; +- CLog::Log(LOGDEBUG, "%s Server: Failed to bind ipv6 serversocket, trying ipv4", callerName); ++ CLog::Log(LOGDEBUG, "%s Server: Failed to bind ipv6 serversocket on port %d, trying ipv4 (error was %s (%d))", ++ callerName, port, strerror(errno), errno); + } + } + +@@ -529,7 +772,8 @@ int CreateTCPServerSocket(const int port, const bool bindLocal, const int backlo + if (bind( sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) + { + closesocket(sock); +- CLog::Log(LOGERROR, "%s Server: Failed to bind ipv4 serversocket", callerName); ++ CLog::Log(LOGERROR, "%s Server: Failed to bind ipv4 serversocket on port %d, trying ipv4 (error was %s (%d))", ++ callerName, port, strerror(errno), errno); + return INVALID_SOCKET; + } + } +@@ -548,4 +792,3 @@ int CreateTCPServerSocket(const int port, const bool bindLocal, const int backlo + + return sock; + } +- +diff --git a/xbmc/network/Network.h b/xbmc/network/Network.h +index 0df104f..496b047 100644 +--- a/xbmc/network/Network.h ++++ b/xbmc/network/Network.h +@@ -21,10 +21,17 @@ + + #include + #include ++#include + + #include "system.h" ++#include "threads/Event.h" ++#include "threads/CriticalSection.h" ++#include "threads/Thread.h" ++#include "Application.h" ++#include "interfaces/AnnouncementManager.h" + + #include "settings/lib/ISettingCallback.h" ++#include + + enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 }; + enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 }; +@@ -84,6 +91,7 @@ public: + virtual void GetMacAddressRaw(char rawMac[6]) = 0; + + virtual bool GetHostMacAddress(unsigned long host, std::string& mac) = 0; ++ bool GetHostMacAddress(const std::string &host, std::string& mac); + + virtual std::string GetCurrentIPAddress() = 0; + virtual std::string GetCurrentNetmask() = 0; +@@ -95,45 +103,128 @@ public: + + virtual void GetSettings(NetworkAssignment& assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode) = 0; + virtual void SetSettings(NetworkAssignment& assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode) = 0; ++ ++ // tells if interface itself is configured with IPv6 or IPv4 address ++ virtual bool isIPv6() { return false; } ++ virtual bool isIPv4() { return true; } + }; + + class CNetwork + { + public: ++ class CNetworkUpdater : public CThread, public ANNOUNCEMENT::IAnnouncer ++ { ++ public: ++ CNetworkUpdater(void (*watcher)(void *caller)); ++ virtual ~CNetworkUpdater(void); ++ ++ volatile bool *Stopping() { return &m_bStop; } ++ void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); ++ ++ protected: ++ void Process() { m_watcher(this); } ++ ++ private: ++ void (*m_watcher)(void *caller); ++ }; ++ ++public: + enum EMESSAGE + { + SERVICES_UP, +- SERVICES_DOWN ++ SERVICES_DOWN, ++ NETWORK_CHANGED + }; + + CNetwork(); + virtual ~CNetwork(); + +- // Return our hostname ++ /*! ++ \brief Returns local hostname ++ */ + virtual bool GetHostName(std::string& hostname); + +- // Return the list of interfaces +- virtual std::vector& GetInterfaceList(void) = 0; ++ /*! ++ \brief Return the list of interfaces ++ */ ++ virtual std::forward_list& GetInterfaceList(void) = 0; ++ ++ /*! ++ \brief Returns interface with specific name ++ - in the current implementation, interface as the basic configutation item ++ represents specific IP configuration ++ - this means InterfaceName is not unique key. IP address is ++ ++ \return With respect above comment, it returns first valid configuration on interface ++ holding searched interface name. ++ */ + CNetworkInterface* GetInterfaceByName(const std::string& name); + +- // Return the first interface which is active ++ /*! ++ \brief Return the first interface which is active ++ - list of available interfaces is always sorted: by AF_FAMILY, dependence of their type ++ on other types and alphabetically at last. AF_PACKET comes first, then AF_INET, AF_INET6. ++ physical interfaces (eg network cards) come first. Bridges later before virtual ++ itnerfaces, then tunnels... ++ - This assures that ppp0 won't be picked up (presented as ++ GetFirstConnectedInterface()) at the expense of eth0 for instance / thus providing ++ non-sense info to services expecting interface with MAC address. ++ */ + virtual CNetworkInterface* GetFirstConnectedInterface(void); + +- // Return true if there is a interface for the same network as address +- bool HasInterfaceForIP(unsigned long address); ++ /*! ++ \brief Address family of GetFirstConnectedInterface() interface ++ \sa GetFirstConnectedInterface() ++ \return with respect to comment in GetFirstConnectedInterface() ++ - in case of returned AF_INET6 - host is configured with IPv6 stack only (we don't need ++ iterate over interfaces list further, or trying socket() results to confirm this) ++ - AF_INET - host is configured with IPv4 stack. IPv6 availability unknown, we would need ++ to loop over the list. ++ */ ++ int GetFirstConnectedFamily() { return (GetFirstConnectedInterface() && GetFirstConnectedInterface()->isIPv6() ? AF_INET6 : AF_INET); } ++ ++ /*! ++ \brief Return true if there is a interface for the same network as address ++ */ ++ bool HasInterfaceForIP(const std::string &address); + +- // Return true if there's at least one defined network interface +- bool IsAvailable(void); ++ /*! ++ \brief Compat wrapper to ++ \sa HasInterfaceForIP(const std::string &address) ++ */ ++ bool HasInterfaceForIP(unsigned long address); + + // Return true if there's at least one interface which is connected + bool IsConnected(void); + +- // Return true if the magic packet was send ++ /*! ++ \return Return true if the magic packet was send ++ ++ TODO: current implementation uses ARP for MAC resolution. ++ as IPv6 has no ARP, it will provide expected result ++ only if target host is accessible via IPv4. ++ (anyhow it's use is safe regardless actual. ++ configuration, returns false for IPv6 only stack) ++ */ + bool WakeOnLan(const char *mac); + +- // Return true if host replies to ping +- bool PingHost(unsigned long host, unsigned short port, unsigned int timeout_ms = 2000, bool readability_check = false); +- virtual bool PingHost(unsigned long host, unsigned int timeout_ms = 2000) = 0; ++ /*! ++ \brief Ping remote host ++ \param IP host address, port (optional) ++ \return Return true if host replies to ping, false otherwise ++ Function is IPv6/v4 compatible ++ - If port is not specified, system cmd ping/ping6 is called ++ - If port is specified, host is contacted via sock connect() ++ */ ++ bool PingHost(const std::string &ipaddr, unsigned short port, unsigned int timeout_ms = 2000, bool readability_check = false); ++ ++ /*! ++ \brief Ping remote host (compatibility wrapper, see PingHost(std::string&...)) ++ */ ++ bool PingHost(unsigned long ipaddr, unsigned short port, unsigned int timeout_ms = 2000, bool readability_check = false) ++ { return PingHost(GetIpStr(ipaddr), port, timeout_ms, readability_check); } ++ ++ virtual bool PingHostImpl(const std::string &target, unsigned int timeout_ms = 2000) = 0; + + // Get/set the nameserver(s) + virtual std::vector GetNameServers(void) = 0; +@@ -145,12 +236,164 @@ public: + void StartServices(); + void StopServices(bool bWait); + ++ /*! ++ \brief Tests if parameter specifies valid IPv6 address (as specified by RFCs) ++ \param ipaddress to convert/test ++ \param *sockaddr non mandatory destination for conversion ++ \param port non mandatory port specification to connect to ++ \return Function is dual purpose. With just one parameter (IP), ++ it return true if that IP represents IPv6 address. ++ If case of second / third supplied argument, it directly ++ converts parameters into binary struct pointed by 2nd param. ++ (structure needs to be pre-allocated) ++ ++ \sa ConvIP ++ For direct conversion into (sockaddr*) see ConvIP() variants. ++ (it is universal wrapper to ConvIPv6/v4()) ++ */ ++ static bool ConvIPv6(const std::string &address, struct sockaddr_in6 *sa = NULL, unsigned short port = 0); ++ ++ /*! ++ \brief Tests if parameter specifies valid IPv4 address (as specified by RFCs) ++ \param ipaddress stored as std::string ++ \param sockaddr* non mandatory ++ \param port non mandatory ++ \return Function is dual purpose. With just one parameter (IP), ++ it return true if that IP represents IPv4 address. ++ If case of second / third supplied argument, it directly ++ converts parameters into binary struct pointed by 2nd param. ++ (structure needs to be pre-allocated) ++ ++ \sa ConvIP ++ For direct conversion into (sockaddr*) see ConvIP() variants. ++ (it is universal wrapper to ConvIPv6/v4()) ++ */ ++ static bool ConvIPv4(const std::string &address, struct sockaddr_in *sa = NULL, unsigned short port = 0); ++ ++ /*! ++ \brief Converts host IP address into binary sockaddr ++ (wrapper to ConvIP(std::string&, ushort)) ++ */ ++ static struct sockaddr_storage *ConvIP(unsigned long address, unsigned short port = 0) { return ConvIP(GetIpStr(address), port); } ++ ++ /*! ++ \brief Converts host IP address into binary sockaddr ++ \param IP address as std::string, port specification (optional) ++ \return Function converts host IP to structure directly used ++ in network API functions. It allocates sockaddr_storage ++ (via malloc) and returns pointer to it (on error NULL ++ is returned). af_family, s_addr, port are filled in. ++ Struct sockaddr_storage can be cast to needed structure ++ (sockaddr_in, sockaddr_in6, sockaddr, ...) ++ You have to relese memory with free(p) after use. ++ */ ++ static struct sockaddr_storage *ConvIP(const std::string &address, unsigned short port = 0); ++ + static int ParseHex(char *str, unsigned char *addr); + +- // Return true if given name or ip address corresponds to localhost ++ /*! ++ \brief IPv6/IPv4 compatible conversion of host IP address ++ \param struct sockaddr ++ \return Function converts binary structure sockaddr to std::string. ++ It can read sockaddr_in and sockaddr_in6, cast as (sockaddr*). ++ IPv4 address is returned in the format x.x.x.x (where x is 0-255), ++ IPv6 address is returned in it's canonised form. ++ On error (or no IPv6/v4 valid input) empty string is returned. ++ */ ++ static std::string GetIpStr(const struct sockaddr *sa); ++ ++ /*! ++ \brief Converts IPv4 address stored in unsigned long to std::string ++ Function converts from host byte order to network ++ byte order first ++ \param IPaddress unsigned long ++ \return Result is returned as std::string ++ */ ++ static std::string GetIpStr(unsigned long address); ++ ++ /*! ++ \brief Canonisation of IPv6 address ++ \param Any valid IPv6 address representation (std::string) ++ \return In respect to RFC 2373, provided string in any legal ++ representations will be canonised to it's shortest ++ possible form e.g. ++ 12AB:0000:0000:CD30:0000:0000:0000:0000 -> 12AB:0:0:CD30:: ++ */ ++ static std::string CanonizeIPv6(const std::string &address); ++ ++ /*! ++ \brief computes the prefix length for a (IPv4/IPv6) netmask ++ \param struct sockaddr ++ \return The prefix length of the netmask ++ For IPv4 it can be between 0 and 32 ++ For IPv6 it can be between 0 and 128 ++ */ ++ static uint8_t PrefixLength(const struct sockaddr *netmask); ++ ++ /*! ++ \brief compares two ip addresses (IPv4/IPv6) ++ \param ip address 1 ++ \param ip address 2 ++ \return if the two addresses are the same ++ */ ++ static bool CompareAddresses(const struct sockaddr *sa, const struct sockaddr *sb); ++ ++ /*! ++ \brief fully IPv4/IPv6 compatible ++ - IPv6 part is limited to addr/mask match only (IPv4 way) ++ ++ \param ipaddr1 to match ++ \param ipaddr2 to match agains ++ \param mask2 to match agains ++ ++ \return TRUE if: ipaddr1 & mask2 == ipaddr2 & mask2 , FALSE otherwise ++ ++ TODO: beside addr/match matching IPv6 introduced NetworkDiscoveryProtocol(NDP) ++ currently not implemented. ++ */ ++ static bool AddrMatch(const std::string &addr, const std::string &match_ip, const std::string &match_mask); ++ ++ /*! ++ \brief Per platform implementation. ++ - CNetwork class has both IPv6/IPv4 support, but doesn't require each derived ++ class to support IPv6 as well ++ - By default we assume IPv6 support not existend (or IPv6 stack unconfigured) ++ - CNetwork class functions check IPv6 support automatically based on this call ++ and avoid IPv6 depending code automatically. ++ This makes the calls safe for the caller without prior checks or deep knowledge ++ of CNetwork internals ++ ++ - for calls dealing with IPv6 stack - and no IPv6 available - calls return safely ++ returning string.empty() / FALSE / -1 or NULL ++ ++ \return Static functions providing only type<>type conversions or formal valididy checking ++ are independent on actual IPv6 stack availability ++ */ ++ virtual bool SupportsIPv6(void) { return false; } ++ ++ /*! ++ \brief Return true if given name or ip address corresponds to localhost ++ */ + bool IsLocalHost(const std::string& hostname); ++ ++ /*! ++ \brief Registers function as platform. network settings change watcher. Changes on net ifaces ++ should be reported by sending message TMSG_NETWORKMESSAGE (CNetwork::NETWORK_CHANGED). ++ */ ++ void RegisterWatcher(void (*watcher)(void *caller)) { m_updThread = new CNetworkUpdater(watcher); m_updThread->Create(false); } ++ CNetworkUpdater *m_updThread; ++ ++ virtual bool ForceRereadInterfaces() = 0; ++ ++protected: ++ CCriticalSection m_lockInterfaces; ++ ++private: ++ CEvent m_signalNetworkChange; ++ bool m_bStop; + }; + ++ + #ifdef HAS_LINUX_NETWORK + #include "linux/NetworkLinux.h" + #else +diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp +index f56cb50..46a677b 100644 +--- a/xbmc/network/NetworkServices.cpp ++++ b/xbmc/network/NetworkServices.cpp +@@ -441,7 +441,7 @@ void CNetworkServices::OnSettingChanged(const CSetting *setting) + settingId == CSettings::SETTING_SMB_WORKGROUP) + { + // okey we really don't need to restart, only deinit samba, but that could be damn hard if something is playing +- //! @todo - General way of handling setting changes that require restart ++ // TODO - General way of handling setting changes that require restart + if (HELPERS::ShowYesNoDialogText(CVariant{14038}, CVariant{14039}) == DialogResponse::YES) + { + CSettings::GetInstance().Save(); +@@ -512,9 +512,6 @@ void CNetworkServices::Stop(bool bWait) + bool CNetworkServices::StartWebserver() + { + #ifdef HAS_WEB_SERVER +- if (!g_application.getNetwork().IsAvailable()) +- return false; +- + if (!CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_WEBSERVER)) + return false; + +@@ -587,7 +584,7 @@ bool CNetworkServices::StartAirPlayServer() + return true; + + #ifdef HAS_AIRPLAY +- if (!g_application.getNetwork().IsAvailable() || !CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_AIRPLAY)) ++ if (!g_application.getNetwork().IsConnected() || !CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_AIRPLAY)) + return false; + + if (IsAirPlayServerRunning()) +@@ -649,7 +646,7 @@ bool CNetworkServices::StopAirPlayServer(bool bWait) + bool CNetworkServices::StartAirTunesServer() + { + #ifdef HAS_AIRTUNES +- if (!g_application.getNetwork().IsAvailable() || !CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_AIRPLAY)) ++ if (!g_application.getNetwork().IsConnected() || !CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_AIRPLAY)) + return false; + + if (IsAirTunesServerRunning()) +diff --git a/xbmc/network/Socket.h b/xbmc/network/Socket.h +index 20088c9..2d51ccc 100644 +--- a/xbmc/network/Socket.h ++++ b/xbmc/network/Socket.h +@@ -166,7 +166,7 @@ namespace SOCKETS + int Read(CAddress& addr, const int buffersize, void *buffer); + bool Broadcast(const CAddress& addr, const int datasize, const void* data) + { +- //! @todo implement ++ // TODO + return false; + } + SOCKET Socket() { return m_iSock; } +diff --git a/xbmc/network/TCPServer.cpp b/xbmc/network/TCPServer.cpp +index 7089911..1009de5 100644 +--- a/xbmc/network/TCPServer.cpp ++++ b/xbmc/network/TCPServer.cpp +@@ -67,20 +67,7 @@ bool CTCPServer::StartServer(int port, bool nonlocal) + ServerInstance = new CTCPServer(port, nonlocal); + if (ServerInstance->Initialize()) + { +- size_t thread_stacksize = 0; +-#if defined(TARGET_DARWIN_TVOS) +- void *stack_addr; +- pthread_attr_t attr; +- pthread_attr_init(&attr); +- pthread_attr_getstack(&attr, &stack_addr, &thread_stacksize); +- pthread_attr_destroy(&attr); +- // double the stack size under tvos, not sure why yet +- // but it stoped crashing using Kodi json -> play video. +- // non-tvos will pass a value of zero which means 'system default' +- thread_stacksize *= 2; +- CLog::Log(LOGDEBUG, "CTCPServer: increasing thread stack to %zu", thread_stacksize); +-#endif +- ServerInstance->Create(false, thread_stacksize); ++ ServerInstance->Create(); + return true; + } + else +@@ -480,8 +467,11 @@ void CTCPServer::Deinitialize() + + m_connections.clear(); + +- for (unsigned int i = 0; i < m_servers.size(); i++) +- closesocket(m_servers[i]); ++ for (unsigned int i = m_servers.size(); i > 0; i--) ++ { ++ shutdown(m_servers[i-1], SHUT_RDWR); ++ closesocket(m_servers[i-1]); ++ } + + m_servers.clear(); + +diff --git a/xbmc/network/UdpClient.h b/xbmc/network/UdpClient.h +index ef018c4..576849b 100644 +--- a/xbmc/network/UdpClient.h ++++ b/xbmc/network/UdpClient.h +@@ -24,7 +24,6 @@ + */ + + #include +-#include + #include "threads/Thread.h" + #include "threads/CriticalSection.h" + #include +diff --git a/xbmc/network/WakeOnAccess.cpp b/xbmc/network/WakeOnAccess.cpp +index 2112798..27a1d12 100644 +--- a/xbmc/network/WakeOnAccess.cpp ++++ b/xbmc/network/WakeOnAccess.cpp +@@ -62,13 +62,6 @@ static int GetTotalSeconds(const CDateTimeSpan& ts) + return ts.GetSeconds() + minutes * 60; + } + +-static unsigned long HostToIP(const std::string& host) +-{ +- std::string ip; +- CDNSNameCache::Lookup(host, ip); +- return inet_addr(ip.c_str()); +-} +- + CWakeOnAccess::WakeUpEntry::WakeUpEntry (bool isAwake) + : timeout (0, 0, 0, DEFAULT_TIMEOUT_SEC) + , wait_online1_sec(DEFAULT_WAIT_FOR_ONLINE_SEC_1) +@@ -101,20 +94,14 @@ private: + + bool CMACDiscoveryJob::DoWork() + { +- unsigned long ipAddress = HostToIP(m_host); ++ std::string ipAddress = CDNSNameCache::Lookup(m_host); + +- if (ipAddress == INADDR_NONE) +- { +- CLog::Log(LOGERROR, "%s - can't determine ip of '%s'", __FUNCTION__, m_host.c_str()); ++ if (ipAddress.empty()) + return false; +- } + +- std::vector& ifaces = g_application.getNetwork().GetInterfaceList(); +- for (std::vector::const_iterator it = ifaces.begin(); it != ifaces.end(); ++it) +- { +- if ((*it)->GetHostMacAddress(ipAddress, m_macAddres)) ++ for (auto &&iface : g_application.getNetwork().GetInterfaceList()) ++ if (iface->GetHostMacAddress(ipAddress, m_macAddres)) + return true; +- } + + return false; + } +@@ -237,8 +224,7 @@ public: + } + virtual bool SuccessWaiting () const + { +- unsigned long address = ntohl(HostToIP(m_host)); +- bool online = g_application.getNetwork().HasInterfaceForIP(address); ++ bool online = g_application.getNetwork().HasInterfaceForIP(CDNSNameCache::Lookup(m_host)); + + if (!online) // setup endtime so we dont return true until network is consistently connected + m_end.Set (m_settle_time_ms); +@@ -279,9 +265,7 @@ public: + + static bool Ping (const CWakeOnAccess::WakeUpEntry& server) + { +- ULONG dst_ip = HostToIP(server.host); +- +- return g_application.getNetwork().PingHost(dst_ip, server.ping_port, 2000, server.ping_mode & 1); ++ return g_application.getNetwork().PingHost(CDNSNameCache::Lookup(server.host), server.ping_port, 2000, server.ping_mode & 1); + } + + private: +@@ -374,7 +358,7 @@ bool CWakeOnAccess::WakeUpHost(const WakeUpEntry& server) + + if (dlg.ShowAndWait (waitObj, m_netinit_sec, LOCALIZED(13028)) != ProgressDialogHelper::Success) + { +- if (g_application.getNetwork().IsConnected() && HostToIP(server.host) == INADDR_NONE) ++ if (g_application.getNetwork().IsConnected() && CDNSNameCache::Lookup(server.host).empty()) + { + // network connected (at least one interface) but dns-lookup failed (host by name, not ip-address), so dont abort yet + CLog::Log(LOGWARNING, "WakeOnAccess timeout/cancel while waiting for network (proceeding anyway)"); +@@ -388,9 +372,7 @@ bool CWakeOnAccess::WakeUpHost(const WakeUpEntry& server) + } + + { +- ULONG dst_ip = HostToIP(server.host); +- +- if (g_application.getNetwork().PingHost(dst_ip, server.ping_port, 500)) // quick ping with short timeout to not block too long ++ if (g_application.getNetwork().PingHost(CDNSNameCache::Lookup(server.host), server.ping_port, 500)) // quick ping with short timeout to not block too long + { + CLog::Log(LOGNOTICE,"WakeOnAccess success exit, server already running"); + return true; +diff --git a/xbmc/network/WakeOnAccess.h b/xbmc/network/WakeOnAccess.h +index 27ab581..47f86b4 100644 +--- a/xbmc/network/WakeOnAccess.h ++++ b/xbmc/network/WakeOnAccess.h +@@ -24,7 +24,6 @@ + #include "settings/lib/ISettingCallback.h" + #include "settings/lib/ISettingsHandler.h" + #include +-#include + + class CWakeOnAccess : private IJobCallback, public ISettingCallback, public ISettingsHandler + { +diff --git a/xbmc/network/WebServer.cpp b/xbmc/network/WebServer.cpp +index 779ca70..31dbeb6 100644 +--- a/xbmc/network/WebServer.cpp ++++ b/xbmc/network/WebServer.cpp +@@ -102,23 +102,9 @@ CWebServer::CWebServer() + #endif + } + +-static MHD_Response* create_response(size_t size, void* data, int free, int copy) +-{ +-#if (MHD_VERSION >= 0x00094001) +- MHD_ResponseMemoryMode mode = MHD_RESPMEM_PERSISTENT; +- if (copy) +- mode = MHD_RESPMEM_MUST_COPY; +- else if (free) +- mode = MHD_RESPMEM_MUST_FREE; +- return MHD_create_response_from_buffer(size, data, mode); +-#else +- return MHD_create_response_from_data(size, data, free, copy); +-#endif +-} +- + int CWebServer::AskForAuthentication(struct MHD_Connection *connection) const + { +- struct MHD_Response *response = create_response(0, nullptr, MHD_NO, MHD_NO); ++ struct MHD_Response *response = MHD_create_response_from_data(0, nullptr, MHD_NO, MHD_NO); + if (!response) + { + CLog::Log(LOGERROR, "CWebServer[%hu]: unable to create HTTP Unauthorized response", m_port); +@@ -298,7 +284,7 @@ int CWebServer::HandlePartialRequest(struct MHD_Connection *connection, Connecti + ifModifiedSinceDate.SetFromRFC1123DateTime(ifModifiedSince) && + lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate) + { +- struct MHD_Response *response = create_response(0, nullptr, MHD_NO, MHD_NO); ++ struct MHD_Response *response = MHD_create_response_from_data(0, nullptr, MHD_NO, MHD_NO); + if (response == nullptr) + { + CLog::Log(LOGERROR, "CWebServer[%hu]: failed to create a HTTP 304 response", m_port); +@@ -742,7 +728,7 @@ int CWebServer::CreateRangedMemoryDownloadResponse(const std::shared_ptr(data), free ? MHD_YES : MHD_NO, copy ? MHD_YES : MHD_NO); ++ response = MHD_create_response_from_data(size, const_cast(data), free ? MHD_YES : MHD_NO, copy ? MHD_YES : MHD_NO); + if (response == nullptr) + { + CLog::Log(LOGERROR, "CWebServer[%hu]: failed to create a HTTP download response", m_port); +@@ -988,11 +974,7 @@ int CWebServer::ContentReaderCallback(void *cls, size_t pos, char *buf, int max) + return -1; + + if (g_advancedSettings.CanLogComponent(LOGWEBSERVER)) +-#if (MHD_VERSION >= 0x00090200) +- CLog::Log(LOGDEBUG, "CWebServer [OUT] write maximum %zu bytes from %" PRIu64 " (%" PRIu64 ")", max, context->writePosition, pos); +-#else + CLog::Log(LOGDEBUG, "CWebServer [OUT] write maximum %d bytes from %" PRIu64 " (%" PRIu64 ")", max, context->writePosition, pos); +-#endif + + // check if we need to add the end-boundary + if (context->rangeCountTotal > 1 && context->ranges.IsEmpty()) +diff --git a/xbmc/network/Zeroconf.h b/xbmc/network/Zeroconf.h +index 0afbb70..f4aca4b 100644 +--- a/xbmc/network/Zeroconf.h ++++ b/xbmc/network/Zeroconf.h +@@ -35,8 +35,8 @@ class CCriticalSection; + /// free to add it. The main purpose currently is to provide an easy + /// way to publish services in the different StartXXX/StopXXX methods + /// in CApplication +-//! @todo Make me safe for use in static initialization. CritSec is a static member :/ +-//! use e.g. loki's singleton implementation to make do it properly ++/// TODO: Make me safe for use in static initialization. CritSec is a static member :/ ++/// use e.g. loki's singleton implementation to make do it properly + class CZeroconf + { + public: +diff --git a/xbmc/network/ZeroconfBrowser.cpp b/xbmc/network/ZeroconfBrowser.cpp +index 4b55bda..d96a135 100644 +--- a/xbmc/network/ZeroconfBrowser.cpp ++++ b/xbmc/network/ZeroconfBrowser.cpp +@@ -61,6 +61,9 @@ CZeroconfBrowser::CZeroconfBrowser():mp_crit_sec(new CCriticalSection),m_started + #ifdef HAS_FILESYSTEM_NFS + AddServiceType("_nfs._tcp."); + #endif// HAS_FILESYSTEM_NFS ++#ifdef HAS_FILESYSTEM_AFP ++ AddServiceType("_afpovertcp._tcp."); ++#endif + AddServiceType("_sftp-ssh._tcp."); + } + +diff --git a/xbmc/network/cddb.cpp b/xbmc/network/cddb.cpp +index 3878bfc..7ab238d 100644 +--- a/xbmc/network/cddb.cpp ++++ b/xbmc/network/cddb.cpp +@@ -515,7 +515,7 @@ void Xcddb::parseData(const char *buffer) + std::string strKeyword = *it; + std::string strValue = keywords[strKeyword]; + +- //! @todo STRING_CLEANUP ++ /* TODO:STRING_CLEANUP */ + if (strKeyword == "DTITLE") + { + // DTITLE may contain artist and disc title, separated with " / ", +diff --git a/xbmc/network/httprequesthandler/HTTPImageTransformationHandler.cpp b/xbmc/network/httprequesthandler/HTTPImageTransformationHandler.cpp +index 88d9999..51040da 100644 +--- a/xbmc/network/httprequesthandler/HTTPImageTransformationHandler.cpp ++++ b/xbmc/network/httprequesthandler/HTTPImageTransformationHandler.cpp +@@ -75,7 +75,7 @@ CHTTPImageTransformationHandler::CHTTPImageTransformationHandler(const HTTPReque + StringUtils::ToLower(ext); + m_response.contentType = CMime::GetMimeType(ext); + +- //! @todo determine the maximum age ++ // TODO: determine the maximum age + + // determine the last modified date + struct __stat64 statBuffer; +diff --git a/xbmc/network/httprequesthandler/IHTTPRequestHandler.cpp b/xbmc/network/httprequesthandler/IHTTPRequestHandler.cpp +index f8119a5..9b611ad 100644 +--- a/xbmc/network/httprequesthandler/IHTTPRequestHandler.cpp ++++ b/xbmc/network/httprequesthandler/IHTTPRequestHandler.cpp +@@ -54,9 +54,6 @@ std::string GetHTTPMethod(HTTPMethod method) + + case POST: + return HTTPMethodPost; +- +- case UNKNOWN: +- break; + } + + return ""; +diff --git a/xbmc/network/linux/Makefile b/xbmc/network/linux/Makefile +index 207ecda..557c587 100644 +--- a/xbmc/network/linux/Makefile ++++ b/xbmc/network/linux/Makefile +@@ -6,3 +6,4 @@ LIB=network_linux.a + + include ../../../Makefile.include + -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) ++CXXFLAGS += --std=c++11 -DHAVE_CHAR32_T -DHAVE_CHAR16_T +diff --git a/xbmc/network/linux/NetworkLinux.cpp b/xbmc/network/linux/NetworkLinux.cpp +index 66d996d..1a6e684 100644 +--- a/xbmc/network/linux/NetworkLinux.cpp ++++ b/xbmc/network/linux/NetworkLinux.cpp +@@ -19,15 +19,29 @@ + */ + + #include ++#include + ++#include "xbmc/messaging/ApplicationMessenger.h" ++#include + #include ++#include + #include + #include + #include ++#ifdef TARGET_ANDROID ++ #include "network/linux/android-ifaddrs/ifaddrs.h" ++#endif + #if defined(TARGET_LINUX) + #include + #include + #include ++ #include ++ #include ++#ifndef _IFADDRS_H_ ++ #include ++#endif ++#else ++ #include "network/osx/priv_netlink.h" + #endif + #ifdef TARGET_ANDROID + #include "platform/android/bionic_supplement/bionic_supplement.h" +@@ -67,7 +81,13 @@ + #include "utils/log.h" + #include "utils/StringUtils.h" + +-CNetworkInterfaceLinux::CNetworkInterfaceLinux(CNetworkLinux* network, std::string interfaceName, char interfaceMacAddrRaw[6]): ++using namespace KODI::MESSAGING; ++ ++CNetworkInterfaceLinux::CNetworkInterfaceLinux(CNetworkLinux* network, unsigned int ifa_flags, ++ struct sockaddr *address, struct sockaddr *netmask, ++ std::string interfaceName, char interfaceMacAddrRaw[6]) : ++ m_interfaceFlags(ifa_flags), ++ m_removed(false), + m_interfaceName(interfaceName), + m_interfaceMacAdr(StringUtils::Format("%02X:%02X:%02X:%02X:%02X:%02X", + (uint8_t)interfaceMacAddrRaw[0], +@@ -78,11 +98,17 @@ CNetworkInterfaceLinux::CNetworkInterfaceLinux(CNetworkLinux* network, std::stri + (uint8_t)interfaceMacAddrRaw[5])) + { + m_network = network; ++ m_address = (struct sockaddr *) malloc(sizeof(struct sockaddr_storage)); ++ m_netmask = (struct sockaddr *) malloc(sizeof(struct sockaddr_storage)); ++ memcpy(m_address, address, sizeof(struct sockaddr_storage)); ++ memcpy(m_netmask, netmask, sizeof(struct sockaddr_storage)); + memcpy(m_interfaceMacAddrRaw, interfaceMacAddrRaw, sizeof(m_interfaceMacAddrRaw)); + } + + CNetworkInterfaceLinux::~CNetworkInterfaceLinux(void) + { ++ free(m_address); ++ free(m_netmask); + } + + std::string& CNetworkInterfaceLinux::GetName(void) +@@ -106,31 +132,21 @@ bool CNetworkInterfaceLinux::IsWireless() + + bool CNetworkInterfaceLinux::IsEnabled() + { +- struct ifreq ifr; +- strcpy(ifr.ifr_name, m_interfaceName.c_str()); +- if (ioctl(m_network->GetSocket(), SIOCGIFFLAGS, &ifr) < 0) +- return false; +- +- return ((ifr.ifr_flags & IFF_UP) == IFF_UP); ++ return true; + } + + bool CNetworkInterfaceLinux::IsConnected() + { +- struct ifreq ifr; +- int zero = 0; +- memset(&ifr,0,sizeof(struct ifreq)); +- strcpy(ifr.ifr_name, m_interfaceName.c_str()); +- if (ioctl(m_network->GetSocket(), SIOCGIFFLAGS, &ifr) < 0) +- return false; +- + // ignore loopback +- int iRunning = ( (ifr.ifr_flags & IFF_RUNNING) && (!(ifr.ifr_flags & IFF_LOOPBACK))); ++ if (IsRemoved() || m_interfaceFlags & IFF_LOOPBACK) ++ return false; + +- if (ioctl(m_network->GetSocket(), SIOCGIFADDR, &ifr) < 0) +- return false; ++ // Don't add IFF_LOWER_UP - looks it is driver dependent on Linux ++ // and missing on running interfaces on OSX (Maverick tested) ++ unsigned int needFlags = IFF_RUNNING; //IFF_LOWER_UP ++ bool iRunning = (m_interfaceFlags & needFlags) == needFlags; + +- // return only interfaces which has ip address +- return iRunning && (0 != memcmp(ifr.ifr_addr.sa_data+sizeof(short), &zero, sizeof(int))); ++ return iRunning; + } + + std::string CNetworkInterfaceLinux::GetMacAddress() +@@ -145,31 +161,17 @@ void CNetworkInterfaceLinux::GetMacAddressRaw(char rawMac[6]) + + std::string CNetworkInterfaceLinux::GetCurrentIPAddress(void) + { +- std::string result; +- +- struct ifreq ifr; +- strcpy(ifr.ifr_name, m_interfaceName.c_str()); +- ifr.ifr_addr.sa_family = AF_INET; +- if (ioctl(m_network->GetSocket(), SIOCGIFADDR, &ifr) >= 0) +- { +- result = inet_ntoa((*((struct sockaddr_in *)&ifr.ifr_addr)).sin_addr); +- } +- +- return result; ++ return CNetwork::GetIpStr(m_address); + } + + std::string CNetworkInterfaceLinux::GetCurrentNetmask(void) + { + std::string result; + +- struct ifreq ifr; +- strcpy(ifr.ifr_name, m_interfaceName.c_str()); +- ifr.ifr_addr.sa_family = AF_INET; +- if (ioctl(m_network->GetSocket(), SIOCGIFNETMASK, &ifr) >= 0) +- { +- result = inet_ntoa((*((struct sockaddr_in*)&ifr.ifr_addr)).sin_addr); +- } +- ++ if (isIPv4()) ++ result = CNetwork::GetIpStr(m_netmask); ++ else ++ result = StringUtils::Format("%u", CNetwork::PrefixLength(m_netmask)); + return result; + } + +@@ -258,7 +260,7 @@ std::string CNetworkInterfaceLinux::GetCurrentDefaultGateway(void) + } + free(buf); + #else +- FILE* fp = fopen("/proc/net/route", "r"); ++ FILE* fp = isIPv4() ? fopen("/proc/net/route", "r") : fopen("/proc/net/ipv6_route", "r"); + if (!fp) + { + // TBD: Error +@@ -269,35 +271,45 @@ std::string CNetworkInterfaceLinux::GetCurrentDefaultGateway(void) + char iface[16]; + char dst[128]; + char gateway[128]; ++ unsigned int metric; ++ unsigned int metric_prev = -1; + size_t linel = 0; + int n; + int linenum = 0; + while (getdelim(&line, &linel, '\n', fp) > 0) + { + // skip first two lines +- if (linenum++ < 1) ++ if (isIPv4() && linenum++ < 1) + continue; + + // search where the word begins +- n = sscanf(line, "%15s %127s %127s", +- iface, dst, gateway); ++ if (isIPv4()) ++ n = sscanf(line, "%15s %127s %127s", ++ iface, dst, gateway); ++ else ++ n = sscanf(line, "%*32s %*2s %32s %*2s %32s %8x %*8s %*8s %*8s %8s", ++ dst, gateway, &metric, iface); + + if (n < 3) + continue; + + if (strcmp(iface, m_interfaceName.c_str()) == 0 && +- strcmp(dst, "00000000") == 0 && +- strcmp(gateway, "00000000") != 0) ++ (strcmp(dst, "00000000") == 0 || strcmp(dst, "00000000000000000000000000000000") == 0) && ++ strcmp(gateway, "00000000") != 0 && strcmp(gateway, "00000000000000000000000000000000") != 0) + { +- unsigned char gatewayAddr[4]; +- int len = CNetwork::ParseHex(gateway, gatewayAddr); +- if (len == 4) ++ if (isIPv4()) + { +- struct in_addr in; +- in.s_addr = (gatewayAddr[0] << 24) | (gatewayAddr[1] << 16) | +- (gatewayAddr[2] << 8) | (gatewayAddr[3]); +- result = inet_ntoa(in); +- break; ++ struct in_addr in; ++ sscanf(gateway, "%8x", &in.s_addr); ++ result = inet_ntoa(in); ++ } ++ else if (metric < metric_prev) ++ { ++ metric_prev = metric; ++ std::string tstr = gateway; ++ for(int i = 7; i > 0; i--) ++ tstr.insert(tstr.begin() + i*4, ':'); ++ result = CNetwork::CanonizeIPv6(tstr); + } + } + } +@@ -312,6 +324,8 @@ CNetworkLinux::CNetworkLinux(void) + { + m_sock = socket(AF_INET, SOCK_DGRAM, 0); + queryInterfaceList(); ++ RegisterWatcher(WatcherProcess); ++ CApplicationMessenger::GetInstance().PostMsg(TMSG_NETWORKMESSAGE, CNetwork::SERVICES_UP, 0); + } + + CNetworkLinux::~CNetworkLinux(void) +@@ -319,25 +333,32 @@ CNetworkLinux::~CNetworkLinux(void) + if (m_sock != -1) + close(CNetworkLinux::m_sock); + +- std::vector::iterator it = m_interfaces.begin(); +- while(it != m_interfaces.end()) +- { +- CNetworkInterface* nInt = *it; +- delete nInt; +- it = m_interfaces.erase(it); +- } ++ CSingleLock lock(m_lockInterfaces); ++ InterfacesClear(); ++ DeleteRemoved(); + } + +-std::vector& CNetworkLinux::GetInterfaceList(void) ++void CNetworkLinux::DeleteRemoved(void) + { +- return m_interfaces; ++ m_interfaces.remove_if(IsRemoved); + } + +-//! @bug +-//! Overwrite the GetFirstConnectedInterface and requery +-//! the interface list if no connected device is found +-//! this fixes a bug when no network is available after first start of xbmc +-//! and the interface comes up during runtime ++void CNetworkLinux::InterfacesClear(void) ++{ ++ for (auto &&iface: m_interfaces) ++ ((CNetworkInterfaceLinux*)iface)->SetRemoved(); ++} ++ ++std::forward_list& CNetworkLinux::GetInterfaceList(void) ++{ ++ CSingleLock lock(m_lockInterfaces); ++ return m_interfaces; ++} ++ ++// Overwrite the GetFirstConnectedInterface and requery ++// the interface list if no connected device is found ++// this fixes a bug when no network is available after first start of xbmc ++// and the interface comes up during runtime + CNetworkInterface* CNetworkLinux::GetFirstConnectedInterface(void) + { + CNetworkInterface *pNetIf=CNetwork::GetFirstConnectedInterface(); +@@ -354,147 +375,128 @@ CNetworkInterface* CNetworkLinux::GetFirstConnectedInterface(void) + return pNetIf; + } + +- +-void CNetworkLinux::GetMacAddress(const std::string& interfaceName, char rawMac[6]) ++void CNetworkLinux::GetMacAddress(struct ifaddrs *tif, char *mac) + { +- memset(rawMac, 0, 6); +-#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) +- ++#if !defined(TARGET_LINUX) + #if !defined(IFT_ETHER) + #define IFT_ETHER 0x6/* Ethernet CSMACD */ + #endif +- const struct sockaddr_dl* dlAddr = NULL; +- const uint8_t * base = NULL; +- // Query the list of interfaces. +- struct ifaddrs *list; +- struct ifaddrs *interface; +- +- if( getifaddrs(&list) < 0 ) +- { +- return; +- } +- +- for(interface = list; interface != NULL; interface = interface->ifa_next) ++ if (((const struct sockaddr_dl*) tif->ifa_addr)->sdl_type == IFT_ETHER) + { +- if(interfaceName == interface->ifa_name) +- { +- if ( (interface->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl *) interface->ifa_addr)->sdl_type == IFT_ETHER) ) +- { +- dlAddr = (const struct sockaddr_dl *) interface->ifa_addr; +- base = (const uint8_t *) &dlAddr->sdl_data[dlAddr->sdl_nlen]; ++ const struct sockaddr_dl *dlAddr = (const struct sockaddr_dl *) tif->ifa_addr; ++ const uint8_t *base = (const uint8_t*) &dlAddr->sdl_data[dlAddr->sdl_nlen]; + +- if( dlAddr->sdl_alen > 5 ) +- { +- memcpy(rawMac, base, 6); +- } +- } +- break; +- } ++ if( dlAddr->sdl_alen > 5 ) ++ memcpy(mac, base, 6); + } +- +- freeifaddrs(list); +- + #else +- +- struct ifreq ifr; +- strcpy(ifr.ifr_name, interfaceName.c_str()); +- if (ioctl(GetSocket(), SIOCGIFHWADDR, &ifr) >= 0) +- { +- memcpy(rawMac, ifr.ifr_hwaddr.sa_data, 6); +- } ++ struct ifreq ifr; ++ strcpy(ifr.ifr_name, tif->ifa_name); ++ if (ioctl(GetSocket(), SIOCGIFHWADDR, &ifr) >= 0) ++ memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); + #endif + } + +-void CNetworkLinux::queryInterfaceList() ++CNetworkInterfaceLinux *CNetworkLinux::Exists(const struct sockaddr *addr, const struct sockaddr *mask, const std::string &name) + { +- char macAddrRaw[6]; +- m_interfaces.clear(); ++ for (auto &&iface: m_interfaces) ++ if (((CNetworkInterfaceLinux*)iface)->Exists(addr, mask, name)) ++ return (CNetworkInterfaceLinux*)iface; + +-#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) ++ return NULL; ++} + +- // Query the list of interfaces. +- struct ifaddrs *list; +- if (getifaddrs(&list) < 0) +- return; ++bool CNetworkLinux::queryInterfaceList() ++{ ++ bool change = false; ++ ++ CSingleLock lock(m_lockInterfaces); ++ ++ // Query the list of interfaces. ++ struct ifaddrs *list; ++ if (getifaddrs(&list) < 0) ++ return false; ++ ++#if !defined(TARGET_LINUX) ++ std::map t_hwaddrs; ++#endif ++ ++ InterfacesClear(); ++ ++ // find last IPv4 record, we will add new interfaces ++ // right after this one (to keep IPv4 in front). ++ auto pos = m_interfaces.before_begin(); ++ for (auto &&iface : m_interfaces) ++ { ++ if (iface && iface->isIPv6()) ++ break; ++ ++pos; ++ } + + struct ifaddrs *cur; + for(cur = list; cur != NULL; cur = cur->ifa_next) + { +- if(cur->ifa_addr->sa_family != AF_INET) ++ std::string name = cur->ifa_name; ++#if !defined(TARGET_LINUX) ++ if(cur->ifa_addr->sa_family == AF_LINK) ++ { ++ struct ifaddrs &t = *cur; ++ t_hwaddrs[name] = t; ++ } ++#endif ++ ++ if(!cur->ifa_addr || ++ (cur->ifa_addr->sa_family != AF_INET && ++ cur->ifa_addr->sa_family != AF_INET6)) ++ continue; ++ ++ if(!(cur->ifa_flags & IFF_UP)) + continue; + +- GetMacAddress(cur->ifa_name, macAddrRaw); + // Add the interface. +- m_interfaces.push_back(new CNetworkInterfaceLinux(this, cur->ifa_name, macAddrRaw)); +- } ++ std::string addr = CNetwork::GetIpStr(cur->ifa_addr); ++ std::string mask = CNetwork::GetIpStr(cur->ifa_netmask); + +- freeifaddrs(list); ++ if(addr.empty() || mask.empty()) ++ continue; + ++ CNetworkInterfaceLinux *iface = Exists(cur->ifa_addr, cur->ifa_netmask, name); ++ if (iface) ++ { ++ iface->SetRemoved(false); ++ iface->m_interfaceFlags = cur->ifa_flags; ++ continue; ++ } ++ ++ char macAddrRaw[6] = {0}; ++#if !defined(TARGET_LINUX) ++ GetMacAddress(&t_hwaddrs[name], macAddrRaw); + #else +- FILE* fp = fopen("/proc/net/dev", "r"); +- if (!fp) +- { +- // TBD: Error +- return; +- } ++ GetMacAddress(cur, macAddrRaw); ++#endif + +- char* line = NULL; +- size_t linel = 0; +- int n; +- char* p; +- int linenum = 0; +- while (getdelim(&line, &linel, '\n', fp) > 0) +- { +- // skip first two lines +- if (linenum++ < 2) +- continue; ++ CNetworkInterfaceLinux *i = new CNetworkInterfaceLinux(this, cur->ifa_flags, cur->ifa_addr, ++ cur->ifa_netmask, name, macAddrRaw); ++ ++ m_interfaces.insert_after(pos, i); ++ if (i->isIPv4()) ++ pos++; ++ change = true; ++ } + +- // search where the word begins +- p = line; +- while (isspace(*p)) +- ++p; ++ freeifaddrs(list); + +- // read word until : +- n = strcspn(p, ": \t"); +- p[n] = 0; ++ change |= std::count_if(m_interfaces.begin(), m_interfaces.end(), IsRemoved); ++ DeleteRemoved(); + +- // save the result +- std::string interfaceName = p; +- GetMacAddress(interfaceName, macAddrRaw); +- m_interfaces.push_back(new CNetworkInterfaceLinux(this, interfaceName, macAddrRaw)); +- } +- free(line); +- fclose(fp); +-#endif ++ return change; + } + + std::vector CNetworkLinux::GetNameServers(void) + { + std::vector result; + +-#if defined(TARGET_DARWIN) +- FILE* pipe = popen("scutil --dns | grep \"nameserver\" | tail -n2", "r"); +- usleep(100000); +- if (pipe) +- { +- std::vector tmpStr; +- char buffer[256] = {'\0'}; +- if (fread(buffer, sizeof(char), sizeof(buffer), pipe) > 0 && !ferror(pipe)) +- { +- tmpStr = StringUtils::Split(buffer, "\n"); +- for (unsigned int i = 0; i < tmpStr.size(); i ++) +- { +- // result looks like this - > ' nameserver[0] : 192.168.1.1' +- // 2 blank spaces + 13 in 'nameserver[0]' + blank + ':' + blank == 18 :) +- if (tmpStr[i].length() >= 18) +- result.push_back(tmpStr[i].substr(18)); +- } +- } +- pclose(pipe); +- } +- if (result.empty()) +- CLog::Log(LOGWARNING, "Unable to determine nameserver"); +-#elif defined(TARGET_ANDROID) ++#if defined(TARGET_ANDROID) + char nameserver[PROP_VALUE_MAX]; + + if (__system_property_get("net.dns1",nameserver)) +@@ -503,19 +505,34 @@ std::vector CNetworkLinux::GetNameServers(void) + result.push_back(nameserver); + if (__system_property_get("net.dns3",nameserver)) + result.push_back(nameserver); +- +- if (!result.size()) +- CLog::Log(LOGWARNING, "Unable to determine nameserver"); + #else +- res_init(); ++ int res = res_init(); + +- for (int i = 0; i < _res.nscount; i ++) ++ for (int i = 0; i < MAXNS && !res; i++) + { +- std::string ns = inet_ntoa(((struct sockaddr_in *)&_res.nsaddr_list[i])->sin_addr); +- result.push_back(ns); ++ std::string strIp = CNetwork::GetIpStr((struct sockaddr *)&_res.nsaddr_list[i]); ++ if (!strIp.empty()) ++ result.push_back(strIp); ++ ++#if !defined(TARGET_DARWIN) ++ strIp = CNetwork::GetIpStr((struct sockaddr *)_res._u._ext.nsaddrs[i]); ++ if (!strIp.empty()) ++ result.push_back(strIp); ++#endif ++ ++ if (_res.nscount ++#if !defined(TARGET_DARWIN) ++ + _res._u._ext.nscount6 ++#endif ++ == result.size()) ++ break; + } ++ + #endif +- return result; ++ if (result.empty()) ++ CLog::Log(LOGWARNING, "Unable to determine nameserver"); ++ ++ return result; + } + + void CNetworkLinux::SetNameServers(const std::vector& nameServers) +@@ -532,24 +549,28 @@ void CNetworkLinux::SetNameServers(const std::vector& nameServers) + } + else + { +- //! @todo implement ++ // TODO: + } + #endif + } + +-bool CNetworkLinux::PingHost(unsigned long remote_ip, unsigned int timeout_ms) ++bool CNetworkLinux::PingHostImpl(const std::string &target, unsigned int timeout_ms) + { +- char cmd_line [64]; ++ bool isIPv6 = CNetwork::ConvIPv6(target); ++ if (isIPv6 && !SupportsIPv6()) ++ return false; + +- struct in_addr host_ip; +- host_ip.s_addr = remote_ip; ++ char cmd_line [64]; ++ std::string ping = isIPv6 ? "ping6" : "ping"; + + #if defined (TARGET_DARWIN_IOS) // no timeout option available +- sprintf(cmd_line, "ping -c 1 %s", inet_ntoa(host_ip)); ++ sprintf(cmd_line, "%s -c 1 %s", ping.c_str(), target.c_str()); + #elif defined (TARGET_DARWIN) || defined (TARGET_FREEBSD) +- sprintf(cmd_line, "ping -c 1 -t %d %s", timeout_ms / 1000 + (timeout_ms % 1000) != 0, inet_ntoa(host_ip)); ++ sprintf(cmd_line, "%s -c 1 -%s %d %s >/dev/null 2>&1", ++ ping.c_str(), isIPv6 ? "i" : "t", timeout_ms / 1000 + (timeout_ms % 1000) != 0, target.c_str()); + #else +- sprintf(cmd_line, "ping -c 1 -w %d %s", timeout_ms / 1000 + (timeout_ms % 1000) != 0, inet_ntoa(host_ip)); ++ sprintf(cmd_line, "%s -c 1 -w %d %s >/dev/null 2>&1", ++ ping.c_str(), timeout_ms / 1000 + (timeout_ms % 1000) != 0, target.c_str()); + #endif + + int status = system (cmd_line); +@@ -567,9 +588,12 @@ bool CNetworkLinux::PingHost(unsigned long remote_ip, unsigned int timeout_ms) + return result == 0; + } + +-#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) + bool CNetworkInterfaceLinux::GetHostMacAddress(unsigned long host_ip, std::string& mac) + { ++ if (m_network->GetFirstConnectedFamily() == AF_INET6 || isIPv6()) ++ return false; ++ ++#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) + bool ret = false; + size_t needed; + char *buf, *next; +@@ -616,10 +640,7 @@ bool CNetworkInterfaceLinux::GetHostMacAddress(unsigned long host_ip, std::strin + } + } + return ret; +-} + #else +-bool CNetworkInterfaceLinux::GetHostMacAddress(unsigned long host_ip, std::string& mac) +-{ + struct arpreq areq; + struct sockaddr_in* sin; + +@@ -653,8 +674,8 @@ bool CNetworkInterfaceLinux::GetHostMacAddress(unsigned long host_ip, std::strin + return true; + + return false; +-} + #endif ++} + + std::vector CNetworkInterfaceLinux::GetAccessPoints(void) + { +@@ -906,7 +927,7 @@ void CNetworkInterfaceLinux::GetSettings(NetworkAssignment& assignment, std::str + FILE* fp = fopen("/etc/network/interfaces", "r"); + if (!fp) + { +- //! @todo implement ++ // TODO + return; + } + +@@ -983,14 +1004,14 @@ void CNetworkInterfaceLinux::SetSettings(NetworkAssignment& assignment, std::str + FILE* fr = fopen("/etc/network/interfaces", "r"); + if (!fr) + { +- //! @todo implement ++ // TODO + return; + } + + FILE* fw = fopen("/tmp/interfaces.temp", "w"); + if (!fw) + { +- //! @todo implement ++ // TODO + fclose(fr); + return; + } +@@ -1060,7 +1081,7 @@ void CNetworkInterfaceLinux::SetSettings(NetworkAssignment& assignment, std::str + // Rename the file + if (rename("/tmp/interfaces.temp", "/etc/network/interfaces") < 0) + { +- //! @todo implement ++ // TODO + return; + } + +@@ -1118,4 +1139,53 @@ void CNetworkInterfaceLinux::WriteSettings(FILE* fw, NetworkAssignment assignmen + fprintf(fw, "auto %s\n\n", GetName().c_str()); + } + ++void WatcherProcess(void *caller) ++{ ++ struct sockaddr_nl addr; ++ int fds = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); ++ struct pollfd m_fds = { fds, POLLIN, 0 }; ++ char msg[4096]; ++ volatile bool *stopping = ((CNetwork::CNetworkUpdater*)caller)->Stopping(); ++ ++ memset (&addr, 0, sizeof(struct sockaddr_nl)); ++ addr.nl_family = AF_NETLINK; ++ addr.nl_pid = getpid (); ++#if defined(TARGET_LINUX) ++ addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; ++ /* RTMGRP_IPV4_IFADDR | RTMGRP_TC | RTMGRP_IPV4_MROUTE | ++ RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_RULE | ++ RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_MROUTE | ++ RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFINFO | ++ RTMGRP_IPV6_PREFIX */ ++#else ++ addr.nl_groups = RTMGRP_LINK; ++#endif ++ ++ if (-1 == bind(fds, (const struct sockaddr *) &addr, sizeof(struct sockaddr))) ++ { ++ close(fds); ++ fds = 0; ++ } ++ else ++ fcntl(fds, F_SETFL, O_NONBLOCK); ++ ++ while(!*stopping) ++ if (poll(&m_fds, 1, 1000) > 0) ++ { ++ while (!*stopping && fds && recv(fds, &msg, sizeof(msg), 0) > 0); ++ if (*stopping) ++ continue; ++ ++ if (!fds) ++ ((CNetwork::CNetworkUpdater*)caller)->Sleep(5000); ++ else ++ ((CNetwork::CNetworkUpdater*)caller)->Sleep(1000); ++ ++ if (stopping || !g_application.getNetwork().ForceRereadInterfaces()) ++ continue; ++ ++ CLog::Log(LOGINFO, "Interfaces change %s", __FUNCTION__); ++ CApplicationMessenger::GetInstance().SendMsg(TMSG_NETWORKMESSAGE, CNetwork::NETWORK_CHANGED, 0); ++ } ++} + +diff --git a/xbmc/network/linux/NetworkLinux.h b/xbmc/network/linux/NetworkLinux.h +index d8b65bc..8d316cd 100644 +--- a/xbmc/network/linux/NetworkLinux.h ++++ b/xbmc/network/linux/NetworkLinux.h +@@ -23,15 +23,20 @@ + + #include + #include ++#include + #include + #include "network/Network.h" + + class CNetworkLinux; ++class CNetworkLinuxUpdateThread; + + class CNetworkInterfaceLinux : public CNetworkInterface + { ++ friend class CNetworkLinux; ++ + public: +- CNetworkInterfaceLinux(CNetworkLinux* network, std::string interfaceName, char interfaceMacAddrRaw[6]); ++ CNetworkInterfaceLinux(CNetworkLinux* network, unsigned int ifa_flags, struct sockaddr *address, ++ struct sockaddr *netmask, std::string interfaceName, char interfaceMacAddrRaw[6]); + ~CNetworkInterfaceLinux(void); + + virtual std::string& GetName(void); +@@ -53,11 +58,27 @@ public: + virtual void GetSettings(NetworkAssignment& assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode); + virtual void SetSettings(NetworkAssignment& assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode); + ++ bool isIPv6() { return m_address->sa_family == AF_INET6; } ++ bool isIPv4() { return m_address->sa_family == AF_INET; } ++ + // Returns the list of access points in the area + virtual std::vector GetAccessPoints(void); +- ++ ++ bool Exists(const struct sockaddr *address, const struct sockaddr *netmask, const std::string &name) ++ { ++ return CNetwork::CompareAddresses(m_address, address) && CNetwork::CompareAddresses(m_netmask, netmask) && name == m_interfaceName; ++ } ++ ++protected: ++ void SetRemoved(bool removed = true) { m_removed = removed; } ++ bool IsRemoved(void) { return m_removed; } ++ + private: + void WriteSettings(FILE* fw, NetworkAssignment assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode); ++ unsigned int m_interfaceFlags; /* Flags from SIOCGIFFLAGS */ ++ struct sockaddr* m_address; ++ struct sockaddr* m_netmask; ++ bool m_removed; + std::string m_interfaceName; + std::string m_interfaceMacAdr; + char m_interfaceMacAddrRaw[6]; +@@ -66,30 +87,42 @@ private: + + class CNetworkLinux : public CNetwork + { ++ friend class CNetworkInterfaceLinux; ++ + public: + CNetworkLinux(void); + virtual ~CNetworkLinux(void); + +- // Return the list of interfaces +- virtual std::vector& GetInterfaceList(void); +- virtual CNetworkInterface* GetFirstConnectedInterface(void); +- +- // Ping remote host +- virtual bool PingHost(unsigned long host, unsigned int timeout_ms = 2000); ++ virtual std::forward_list& GetInterfaceList(void); ++ virtual CNetworkInterface* GetFirstConnectedInterface(void); ++ ++ virtual bool SupportsIPv6() { return true; } ++ ++ virtual bool PingHostImpl(const std::string &target, unsigned int timeout_ms = 2000); + + // Get/set the nameserver(s) ++ // Current code is safe for any stack configuration, but APi ++ // used provides IPv4 nameservers only (those specified in system ++ // via IPv4 address). empty otherwise. ++ // TODO: find a method to get list of all defined nameservers + virtual std::vector GetNameServers(void); + virtual void SetNameServers(const std::vector& nameServers); + +- friend class CNetworkInterfaceLinux; +- ++ bool ForceRereadInterfaces() { return queryInterfaceList(); } + private: ++ CNetworkInterfaceLinux *Exists(const struct sockaddr *addr, const struct sockaddr *mask, const std::string &name); ++ void InterfacesClear(void); ++ void DeleteRemoved(void); ++ + int GetSocket() { return m_sock; } +- void GetMacAddress(const std::string& interfaceName, char macAddrRaw[6]); +- void queryInterfaceList(); +- std::vector m_interfaces; ++ void GetMacAddress(struct ifaddrs *tif, char *mac); ++ bool queryInterfaceList(); ++ std::forward_list m_interfaces; + int m_sock; ++ ++ static bool IsRemoved(const CNetworkInterface *i) { return ((CNetworkInterfaceLinux*)i)->IsRemoved(); } + }; + + #endif + ++void WatcherProcess(void *caller); +diff --git a/xbmc/network/linux/ZeroconfAvahi.cpp b/xbmc/network/linux/ZeroconfAvahi.cpp +index 9be965b..746275a 100644 +--- a/xbmc/network/linux/ZeroconfAvahi.cpp ++++ b/xbmc/network/linux/ZeroconfAvahi.cpp +@@ -74,7 +74,7 @@ CZeroconfAvahi::CZeroconfAvahi(): mp_client(0), mp_poll (0), m_shutdown(false),m + if (! (mp_poll = avahi_threaded_poll_new())) + { + CLog::Log(LOGERROR, "CZeroconfAvahi::CZeroconfAvahi(): Could not create threaded poll object"); +- //! @todo throw exception? ++ //TODO: throw exception? + return; + } + +@@ -102,7 +102,7 @@ CZeroconfAvahi::~CZeroconfAvahi() + //so instead of calling + //avahi_threaded_poll_stop(mp_poll); + //we set m_shutdown=true, post an event and wait for it to stop itself +- struct timeval tv = { 0, 0 }; //! @todo does tv survive the thread? ++ struct timeval tv = { 0, 0 }; //TODO: does tv survive the thread? + AvahiTimeout* lp_timeout; + { + ScopedEventLoopBlock l_block(mp_poll); +@@ -428,7 +428,7 @@ void CZeroconfAvahi::addService(tServiceMap::mapped_type fp_service_info, AvahiC + if ((ret = avahi_entry_group_commit(fp_service_info->mp_group)) < 0) + { + CLog::Log(LOGERROR, "CZeroconfAvahi::addService(): Failed to commit entry group! Error:%s", avahi_strerror(ret)); +- //! @todo what now? reset the group? free it? ++ // TODO what now? reset the group? free it? + } + } + +diff --git a/xbmc/network/linux/ZeroconfBrowserAvahi.cpp b/xbmc/network/linux/ZeroconfBrowserAvahi.cpp +index 7e44e7e..1a0402f 100644 +--- a/xbmc/network/linux/ZeroconfBrowserAvahi.cpp ++++ b/xbmc/network/linux/ZeroconfBrowserAvahi.cpp +@@ -52,7 +52,7 @@ CZeroconfBrowserAvahi::CZeroconfBrowserAvahi() : mp_client ( 0 ), mp_poll ( 0 ) + if ( ! ( mp_poll = avahi_threaded_poll_new() ) ) + { + CLog::Log ( LOGERROR, "CZeroconfAvahi::CZeroconfAvahi(): Could not create threaded poll object" ); +- //! @todo throw exception? can this even happen? ++ //TODO: throw exception? can this even happen? + return; + } + +@@ -241,7 +241,7 @@ void CZeroconfBrowserAvahi::browseCallback ( + { + case AVAHI_BROWSER_FAILURE: + CLog::Log ( LOGERROR, "CZeroconfBrowserAvahi::browseCallback error: %s\n", avahi_strerror ( avahi_client_errno ( avahi_service_browser_get_client ( browser ) ) ) ); +- //! @todo implement ++ //TODO + return; + case AVAHI_BROWSER_NEW: + { +diff --git a/xbmc/network/linux/ZeroconfBrowserAvahi.h b/xbmc/network/linux/ZeroconfBrowserAvahi.h +index a20028e..4e56ad9 100644 +--- a/xbmc/network/linux/ZeroconfBrowserAvahi.h ++++ b/xbmc/network/linux/ZeroconfBrowserAvahi.h +@@ -24,7 +24,6 @@ + + #include + #include +-#include + + #include "network/ZeroconfBrowser.h" + #include "threads/Thread.h" +diff --git a/xbmc/network/linux/android-ifaddrs/Makefile b/xbmc/network/linux/android-ifaddrs/Makefile +new file mode 100644 +index 0000000..39e43ea +--- /dev/null ++++ b/xbmc/network/linux/android-ifaddrs/Makefile +@@ -0,0 +1,6 @@ ++SRCS=ifaddrs.c ++ ++LIB=android-ifaddrs.a ++ ++include ../../../../Makefile.include ++-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) +diff --git a/xbmc/network/linux/android-ifaddrs/README.md b/xbmc/network/linux/android-ifaddrs/README.md +new file mode 100644 +index 0000000..dc05bdf +--- /dev/null ++++ b/xbmc/network/linux/android-ifaddrs/README.md +@@ -0,0 +1,6 @@ ++android-ifaddrs ++=============== ++ ++An implementation of getifaddrs() for Android, since the NDK does not natively support it. ++ ++Works just like you would expect on regular Linux. License information is present in each file (BSD license). +diff --git a/xbmc/network/linux/android-ifaddrs/ifaddrs.c b/xbmc/network/linux/android-ifaddrs/ifaddrs.c +new file mode 100644 +index 0000000..c59d8bc +--- /dev/null ++++ b/xbmc/network/linux/android-ifaddrs/ifaddrs.c +@@ -0,0 +1,663 @@ ++/* ++Copyright (c) 2013, Kenneth MacKay ++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. ++ ++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 AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "ifaddrs.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++typedef struct NetlinkList ++{ ++ struct NetlinkList *m_next; ++ struct nlmsghdr *m_data; ++ unsigned int m_size; ++} NetlinkList; ++ ++static int netlink_socket(void) ++{ ++ int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); ++ if(l_socket < 0) ++ { ++ return -1; ++ } ++ ++ struct sockaddr_nl l_addr; ++ memset(&l_addr, 0, sizeof(l_addr)); ++ l_addr.nl_family = AF_NETLINK; ++ if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) ++ { ++ close(l_socket); ++ return -1; ++ } ++ ++ return l_socket; ++} ++ ++static int netlink_send(int p_socket, int p_request) ++{ ++ struct ++ { ++ struct nlmsghdr m_hdr; ++ struct rtgenmsg m_msg; ++ } l_data; ++ ++ memset(&l_data, 0, sizeof(l_data)); ++ ++ l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); ++ l_data.m_hdr.nlmsg_type = p_request; ++ l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; ++ l_data.m_hdr.nlmsg_pid = 0; ++ l_data.m_hdr.nlmsg_seq = p_socket; ++ l_data.m_msg.rtgen_family = AF_UNSPEC; ++ ++ struct sockaddr_nl l_addr; ++ memset(&l_addr, 0, sizeof(l_addr)); ++ l_addr.nl_family = AF_NETLINK; ++ return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); ++} ++ ++static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) ++{ ++ struct msghdr l_msg; ++ struct iovec l_iov = { p_buffer, p_len }; ++ struct sockaddr_nl l_addr; ++ ++ for(;;) ++ { ++ l_msg.msg_name = (void *)&l_addr; ++ l_msg.msg_namelen = sizeof(l_addr); ++ l_msg.msg_iov = &l_iov; ++ l_msg.msg_iovlen = 1; ++ l_msg.msg_control = NULL; ++ l_msg.msg_controllen = 0; ++ l_msg.msg_flags = 0; ++ int l_result = recvmsg(p_socket, &l_msg, 0); ++ ++ if(l_result < 0) ++ { ++ if(errno == EINTR) ++ { ++ continue; ++ } ++ return -2; ++ } ++ ++ if(l_msg.msg_flags & MSG_TRUNC) ++ { // buffer was too small ++ return -1; ++ } ++ return l_result; ++ } ++} ++ ++static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) ++{ ++ size_t l_size = 4096; ++ void *l_buffer = NULL; ++ ++ for(;;) ++ { ++ free(l_buffer); ++ l_buffer = malloc(l_size); ++ if (l_buffer == NULL) ++ { ++ return NULL; ++ } ++ ++ int l_read = netlink_recv(p_socket, l_buffer, l_size); ++ *p_size = l_read; ++ if(l_read == -2) ++ { ++ free(l_buffer); ++ return NULL; ++ } ++ if(l_read >= 0) ++ { ++ pid_t l_pid = getpid(); ++ struct nlmsghdr *l_hdr; ++ for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) ++ { ++ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) ++ { ++ continue; ++ } ++ ++ if(l_hdr->nlmsg_type == NLMSG_DONE) ++ { ++ *p_done = 1; ++ break; ++ } ++ ++ if(l_hdr->nlmsg_type == NLMSG_ERROR) ++ { ++ free(l_buffer); ++ return NULL; ++ } ++ } ++ return l_buffer; ++ } ++ ++ l_size *= 2; ++ } ++} ++ ++static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) ++{ ++ NetlinkList *l_item = malloc(sizeof(NetlinkList)); ++ if (l_item == NULL) ++ { ++ return NULL; ++ } ++ ++ l_item->m_next = NULL; ++ l_item->m_data = p_data; ++ l_item->m_size = p_size; ++ return l_item; ++} ++ ++static void freeResultList(NetlinkList *p_list) ++{ ++ NetlinkList *l_cur; ++ while(p_list) ++ { ++ l_cur = p_list; ++ p_list = p_list->m_next; ++ free(l_cur->m_data); ++ free(l_cur); ++ } ++} ++ ++static NetlinkList *getResultList(int p_socket, int p_request) ++{ ++ if(netlink_send(p_socket, p_request) < 0) ++ { ++ return NULL; ++ } ++ ++ NetlinkList *l_list = NULL; ++ NetlinkList *l_end = NULL; ++ int l_size; ++ int l_done = 0; ++ while(!l_done) ++ { ++ struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); ++ if(!l_hdr) ++ { // error ++ freeResultList(l_list); ++ return NULL; ++ } ++ ++ NetlinkList *l_item = newListItem(l_hdr, l_size); ++ if (!l_item) ++ { ++ freeResultList(l_list); ++ return NULL; ++ } ++ if(!l_list) ++ { ++ l_list = l_item; ++ } ++ else ++ { ++ l_end->m_next = l_item; ++ } ++ l_end = l_item; ++ } ++ return l_list; ++} ++ ++static size_t maxSize(size_t a, size_t b) ++{ ++ return (a > b ? a : b); ++} ++ ++static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) ++{ ++ switch(p_family) ++ { ++ case AF_INET: ++ return sizeof(struct sockaddr_in); ++ case AF_INET6: ++ return sizeof(struct sockaddr_in6); ++ case AF_PACKET: ++ return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); ++ default: ++ return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); ++ } ++} ++ ++static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) ++{ ++ switch(p_family) ++ { ++ case AF_INET: ++ memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); ++ break; ++ case AF_INET6: ++ memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); ++ break; ++ case AF_PACKET: ++ memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); ++ ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; ++ break; ++ default: ++ memcpy(p_dest->sa_data, p_data, p_size); ++ break; ++ } ++ p_dest->sa_family = p_family; ++} ++ ++static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) ++{ ++ if(!*p_resultList) ++ { ++ *p_resultList = p_entry; ++ } ++ else ++ { ++ struct ifaddrs *l_cur = *p_resultList; ++ while(l_cur->ifa_next) ++ { ++ l_cur = l_cur->ifa_next; ++ } ++ l_cur->ifa_next = p_entry; ++ } ++} ++ ++static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) ++{ ++ struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); ++ ++ size_t l_nameSize = 0; ++ size_t l_addrSize = 0; ++ size_t l_dataSize = 0; ++ ++ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); ++ struct rtattr *l_rta; ++ for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) ++ { ++ void *l_rtaData = RTA_DATA(l_rta); ++ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); ++ switch(l_rta->rta_type) ++ { ++ case IFLA_ADDRESS: ++ case IFLA_BROADCAST: ++ l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); ++ break; ++ case IFLA_IFNAME: ++ l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); ++ break; ++ case IFLA_STATS: ++ l_dataSize += NLMSG_ALIGN(l_rtaSize); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); ++ if (l_entry == NULL) ++ { ++ return -1; ++ } ++ memset(l_entry, 0, sizeof(struct ifaddrs)); ++ l_entry->ifa_name = ""; ++ ++ char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs); ++ char *l_name = l_index + sizeof(int); ++ char *l_addr = l_name + l_nameSize; ++ char *l_data = l_addr + l_addrSize; ++ ++ // save the interface index so we can look it up when handling the addresses. ++ memcpy(l_index, &l_info->ifi_index, sizeof(int)); ++ ++ l_entry->ifa_flags = l_info->ifi_flags; ++ ++ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); ++ for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) ++ { ++ void *l_rtaData = RTA_DATA(l_rta); ++ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); ++ switch(l_rta->rta_type) ++ { ++ case IFLA_ADDRESS: ++ case IFLA_BROADCAST: ++ { ++ size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); ++ makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); ++ ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; ++ ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; ++ if(l_rta->rta_type == IFLA_ADDRESS) ++ { ++ l_entry->ifa_addr = (struct sockaddr *)l_addr; ++ } ++ else ++ { ++ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; ++ } ++ l_addr += NLMSG_ALIGN(l_addrLen); ++ break; ++ } ++ case IFLA_IFNAME: ++ strncpy(l_name, l_rtaData, l_rtaDataSize); ++ l_name[l_rtaDataSize] = '\0'; ++ l_entry->ifa_name = l_name; ++ break; ++ case IFLA_STATS: ++ memcpy(l_data, l_rtaData, l_rtaDataSize); ++ l_entry->ifa_data = l_data; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ addToEnd(p_resultList, l_entry); ++ return 0; ++} ++ ++static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) ++{ ++ int l_num = 0; ++ struct ifaddrs *l_cur = *p_links; ++ while(l_cur && l_num < p_numLinks) ++ { ++ char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); ++ int l_index; ++ memcpy(&l_index, l_indexPtr, sizeof(int)); ++ if(l_index == p_index) ++ { ++ return l_cur; ++ } ++ ++ l_cur = l_cur->ifa_next; ++ ++l_num; ++ } ++ return NULL; ++} ++ ++static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) ++{ ++ struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); ++ struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); ++ ++ if(l_info->ifa_family == AF_PACKET) ++ { ++ return 0; ++ } ++ ++ size_t l_nameSize = 0; ++ size_t l_addrSize = 0; ++ ++ int l_addedNetmask = 0; ++ ++ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); ++ struct rtattr *l_rta; ++ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) ++ { ++ void *l_rtaData = RTA_DATA(l_rta); ++ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); ++ ++ switch(l_rta->rta_type) ++ { ++ case IFA_ADDRESS: ++ case IFA_LOCAL: ++ if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) ++ { // make room for netmask ++ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); ++ l_addedNetmask = 1; ++ } ++ case IFA_BROADCAST: ++ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); ++ break; ++ case IFA_LABEL: ++ l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); ++ if (l_entry == NULL) ++ { ++ return -1; ++ } ++ memset(l_entry, 0, sizeof(struct ifaddrs)); ++ l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); ++ ++ char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); ++ char *l_addr = l_name + l_nameSize; ++ ++ l_entry->ifa_flags = l_info->ifa_flags; ++ if(l_interface) ++ { ++ l_entry->ifa_flags |= l_interface->ifa_flags; ++ } ++ ++ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); ++ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) ++ { ++ void *l_rtaData = RTA_DATA(l_rta); ++ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); ++ switch(l_rta->rta_type) ++ { ++ case IFA_ADDRESS: ++ case IFA_BROADCAST: ++ case IFA_LOCAL: ++ { ++ size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); ++ makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); ++ if(l_info->ifa_family == AF_INET6) ++ { ++ if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) ++ { ++ ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; ++ } ++ } ++ ++ if(l_rta->rta_type == IFA_ADDRESS) ++ { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address ++ if(l_entry->ifa_addr) ++ { ++ l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; ++ } ++ else ++ { ++ l_entry->ifa_addr = (struct sockaddr *)l_addr; ++ } ++ } ++ else if(l_rta->rta_type == IFA_LOCAL) ++ { ++ if(l_entry->ifa_addr) ++ { ++ l_entry->ifa_dstaddr = l_entry->ifa_addr; ++ } ++ l_entry->ifa_addr = (struct sockaddr *)l_addr; ++ } ++ else ++ { ++ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; ++ } ++ l_addr += NLMSG_ALIGN(l_addrLen); ++ break; ++ } ++ case IFA_LABEL: ++ strncpy(l_name, l_rtaData, l_rtaDataSize); ++ l_name[l_rtaDataSize] = '\0'; ++ l_entry->ifa_name = l_name; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) ++ { ++ unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); ++ unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); ++ char l_mask[16] = {0}; ++ unsigned i; ++ for(i=0; i<(l_prefix/8); ++i) ++ { ++ l_mask[i] = 0xff; ++ } ++ if(l_prefix % 8) ++ { ++ l_mask[i] = 0xff << (8 - (l_prefix % 8)); ++ } ++ ++ makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); ++ l_entry->ifa_netmask = (struct sockaddr *)l_addr; ++ } ++ ++ addToEnd(p_resultList, l_entry); ++ return 0; ++} ++ ++static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) ++{ ++ int l_numLinks = 0; ++ pid_t l_pid = getpid(); ++ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) ++ { ++ unsigned int l_nlsize = p_netlinkList->m_size; ++ struct nlmsghdr *l_hdr; ++ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) ++ { ++ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) ++ { ++ continue; ++ } ++ ++ if(l_hdr->nlmsg_type == NLMSG_DONE) ++ { ++ break; ++ } ++ ++ if(l_hdr->nlmsg_type == RTM_NEWLINK) ++ { ++ if(interpretLink(l_hdr, p_resultList) == -1) ++ { ++ return -1; ++ } ++ ++l_numLinks; ++ } ++ } ++ } ++ return l_numLinks; ++} ++ ++static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) ++{ ++ pid_t l_pid = getpid(); ++ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) ++ { ++ unsigned int l_nlsize = p_netlinkList->m_size; ++ struct nlmsghdr *l_hdr; ++ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) ++ { ++ if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) ++ { ++ continue; ++ } ++ ++ if(l_hdr->nlmsg_type == NLMSG_DONE) ++ { ++ break; ++ } ++ ++ if(l_hdr->nlmsg_type == RTM_NEWADDR) ++ { ++ if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) ++ { ++ return -1; ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++int getifaddrs(struct ifaddrs **ifap) ++{ ++ if(!ifap) ++ { ++ return -1; ++ } ++ *ifap = NULL; ++ ++ int l_socket = netlink_socket(); ++ if(l_socket < 0) ++ { ++ return -1; ++ } ++ ++ NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); ++ if(!l_linkResults) ++ { ++ close(l_socket); ++ return -1; ++ } ++ ++ NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); ++ if(!l_addrResults) ++ { ++ close(l_socket); ++ freeResultList(l_linkResults); ++ return -1; ++ } ++ ++ int l_result = 0; ++ int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); ++ if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) ++ { ++ l_result = -1; ++ } ++ ++ freeResultList(l_linkResults); ++ freeResultList(l_addrResults); ++ close(l_socket); ++ return l_result; ++} ++ ++void freeifaddrs(struct ifaddrs *ifa) ++{ ++ struct ifaddrs *l_cur; ++ while(ifa) ++ { ++ l_cur = ifa; ++ ifa = ifa->ifa_next; ++ free(l_cur); ++ } ++} +diff --git a/xbmc/network/linux/android-ifaddrs/ifaddrs.h b/xbmc/network/linux/android-ifaddrs/ifaddrs.h +new file mode 100644 +index 0000000..9cd19fe +--- /dev/null ++++ b/xbmc/network/linux/android-ifaddrs/ifaddrs.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (c) 1995, 1999 ++ * Berkeley Software Design, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. 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. ++ * ++ * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp ++ */ ++ ++#ifndef _IFADDRS_H_ ++#define _IFADDRS_H_ ++ ++struct ifaddrs { ++ struct ifaddrs *ifa_next; ++ char *ifa_name; ++ unsigned int ifa_flags; ++ struct sockaddr *ifa_addr; ++ struct sockaddr *ifa_netmask; ++ struct sockaddr *ifa_dstaddr; ++ void *ifa_data; ++}; ++ ++/* ++ * This may have been defined in . Note that if is ++ * to be included it must be included before this header file. ++ */ ++#ifndef ifa_broadaddr ++#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ ++#endif ++ ++#include ++ ++__BEGIN_DECLS ++extern int getifaddrs(struct ifaddrs **ifap); ++extern void freeifaddrs(struct ifaddrs *ifa); ++__END_DECLS ++ ++#endif +diff --git a/xbmc/network/mdns/ZeroconfBrowserMDNS.h b/xbmc/network/mdns/ZeroconfBrowserMDNS.h +index 83206b4..fb35106 100644 +--- a/xbmc/network/mdns/ZeroconfBrowserMDNS.h ++++ b/xbmc/network/mdns/ZeroconfBrowserMDNS.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + + #include + +diff --git a/xbmc/network/mdns/ZeroconfMDNS.cpp b/xbmc/network/mdns/ZeroconfMDNS.cpp +index 8bfd7df..00d02c5 100644 +--- a/xbmc/network/mdns/ZeroconfMDNS.cpp ++++ b/xbmc/network/mdns/ZeroconfMDNS.cpp +@@ -19,7 +19,6 @@ + */ + + #include "ZeroconfMDNS.h" +-#include + + #include + #include +diff --git a/xbmc/network/mdns/ZeroconfMDNS.h b/xbmc/network/mdns/ZeroconfMDNS.h +index fdad063..e6360ab 100644 +--- a/xbmc/network/mdns/ZeroconfMDNS.h ++++ b/xbmc/network/mdns/ZeroconfMDNS.h +@@ -25,9 +25,7 @@ + #include "threads/Thread.h" + + #include +-#include + #include +-#include + + class CZeroconfMDNS : public CZeroconf,public CThread + { +diff --git a/xbmc/network/osx/ZeroconfBrowserOSX.h b/xbmc/network/osx/ZeroconfBrowserOSX.h +index f787f68..581bede 100644 +--- a/xbmc/network/osx/ZeroconfBrowserOSX.h ++++ b/xbmc/network/osx/ZeroconfBrowserOSX.h +@@ -21,8 +21,6 @@ + + #include + #include +-#include +-#include + + #include "network/ZeroconfBrowser.h" + #include "threads/Thread.h" +@@ -66,7 +64,7 @@ private: + CFRunLoopRef m_runloop; + + //shared variables (with guard) +- //! @todo split the guard for discovered, resolved access? ++ //TODO: split the guard for discovered, resolved access? + CCriticalSection m_data_guard; + // tBrowserMap maps service types the corresponding browser + typedef std::map tBrowserMap; +diff --git a/xbmc/network/osx/priv_netlink.h b/xbmc/network/osx/priv_netlink.h +new file mode 100644 +index 0000000..9630969 +--- /dev/null ++++ b/xbmc/network/osx/priv_netlink.h +@@ -0,0 +1,120 @@ ++/* ++ * wpa_supplicant - Private copy of Linux netlink/rtnetlink definitions. ++ * Copyright (c) 2003-2005, Jouni Malinen ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Alternatively, this software may be distributed under the terms of BSD ++ * license. ++ * ++ * See README and COPYING for more details. ++ */ ++ ++#include ++ ++#ifndef PRIV_NETLINK_H ++#define PRIV_NETLINK_H ++ ++/* ++ * This should be replaced with user space header once one is available with C ++ * library, etc.. ++ */ ++ ++#ifndef IFF_LOWER_UP ++#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ ++#endif ++#ifndef IFF_DORMANT ++#define IFF_DORMANT 0x20000 /* driver signals dormant */ ++#endif ++ ++#ifndef IFLA_IFNAME ++#define IFLA_IFNAME 3 ++#endif ++#ifndef IFLA_WIRELESS ++#define IFLA_WIRELESS 11 ++#endif ++#ifndef IFLA_OPERSTATE ++#define IFLA_OPERSTATE 16 ++#endif ++#ifndef IFLA_LINKMODE ++#define IFLA_LINKMODE 17 ++#define IF_OPER_DORMANT 5 ++#define IF_OPER_UP 6 ++#endif ++ ++#define NLM_F_REQUEST 1 ++ ++#define NETLINK_ROUTE 0 ++#define RTMGRP_LINK 1 ++#define RTM_BASE 0x10 ++#define RTM_NEWLINK (RTM_BASE + 0) ++#define RTM_DELLINK (RTM_BASE + 1) ++#define RTM_SETLINK (RTM_BASE + 3) ++ ++#define NLMSG_ALIGNTO 4 ++#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) ++#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) ++#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr))) ++#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) ++#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0))) ++#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ ++ (struct nlmsghdr *) \ ++ (((char *)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) ++#define NLMSG_OK(nlh,len) ((len) >= (int) sizeof(struct nlmsghdr) && \ ++ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ ++ (int) (nlh)->nlmsg_len <= (len)) ++#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) ++ ++#define RTA_ALIGNTO 4 ++#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1)) ++#define RTA_OK(rta,len) \ ++((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \ ++(rta)->rta_len <= (len)) ++#define RTA_NEXT(rta,attrlen) \ ++((attrlen) -= RTA_ALIGN((rta)->rta_len), \ ++(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len))) ++#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) ++#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0))) ++ ++#define PF_NETLINK PF_ROUTE ++#define AF_NETLINK AF_ROUTE ++ ++typedef int32_t u32; ++typedef int16_t u16; ++ ++struct sockaddr_nl ++{ ++ sa_family_t nl_family; ++ unsigned short nl_pad; ++ u32 nl_pid; ++ u32 nl_groups; ++}; ++ ++struct nlmsghdr ++{ ++ u32 nlmsg_len; ++ u16 nlmsg_type; ++ u16 nlmsg_flags; ++ u32 nlmsg_seq; ++ u32 nlmsg_pid; ++}; ++ ++struct ifinfomsg ++{ ++ unsigned char ifi_family; ++ unsigned char __ifi_pad; ++ unsigned short ifi_type; ++ int ifi_index; ++ unsigned ifi_flags; ++ unsigned ifi_change; ++}; ++ ++struct rtattr ++{ ++ unsigned short rta_len; ++ unsigned short rta_type; ++}; ++ ++#endif /* PRIV_NETLINK_H */ +diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp +index a8d5f00..36f5907 100644 +--- a/xbmc/network/upnp/UPnP.cpp ++++ b/xbmc/network/upnp/UPnP.cpp +@@ -37,7 +37,6 @@ + #include "network/Network.h" + #include "utils/log.h" + #include "URL.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "profiles/ProfilesManager.h" + #include "settings/AdvancedSettings.h" + #include "settings/Settings.h" +@@ -275,11 +274,11 @@ public: + NPT_CHECK_LABEL(FindServer(url.GetHostName().c_str(), device),failed); + NPT_CHECK_LABEL(device->FindServiceById("urn:upnp-org:serviceId:ContentDirectory", cds),failed); + +- NPT_CHECK_LABEL(m_CtrlPoint->CreateAction( ++ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction( + device, + "urn:schemas-upnp-org:service:ContentDirectory:1", + "UpdateObject", +- action), failed); ++ action)); + + NPT_CHECK_LABEL(action->SetArgumentValue("ObjectID", url.GetFileName().c_str()), failed); + NPT_CHECK_LABEL(action->SetArgumentValue("CurrentTagValue", curr_value), failed); +diff --git a/xbmc/network/upnp/UPnPInternal.cpp b/xbmc/network/upnp/UPnPInternal.cpp +index 8732c58..a01f830 100644 +--- a/xbmc/network/upnp/UPnPInternal.cpp ++++ b/xbmc/network/upnp/UPnPInternal.cpp +@@ -33,6 +33,7 @@ + #include "filesystem/StackDirectory.h" + #include "filesystem/MusicDatabaseDirectory.h" + #include "filesystem/VideoDatabaseDirectory.h" ++#include "video/VideoDatabase.h" + #include "video/VideoInfoTag.h" + #include "music/MusicDatabase.h" + #include "music/tags/MusicInfoTag.h" +@@ -176,15 +177,15 @@ GetProtocolInfo(const CFileItem& item, + { + NPT_String proto = protocol; + +- //! @todo fixup the protocol just in case nothing was passed ++ /* fixup the protocol just in case nothing was passed */ + if (proto.IsEmpty()) { + proto = item.GetURL().GetProtocol().c_str(); + } + +- /** +- * map protocol to right prefix and use xbmc-get for +- * unsupported UPnP protocols for other xbmc clients +- * @todo add rtsp ? ++ /* ++ map protocol to right prefix and use xbmc-get for ++ unsupported UPnP protocols for other xbmc clients ++ TODO: add rtsp ? + */ + if (proto == "http") { + proto = "http-get"; +@@ -281,12 +282,12 @@ PopulateObjectFromTag(CVideoInfoTag& tag, + object.m_People.artists.Add(itArtist->c_str()); + object.m_Affiliation.album = tag.m_strAlbum.c_str(); + object.m_Title = tag.m_strTitle.c_str(); +- object.m_Date = tag.GetPremiered().GetAsW3CDate().c_str(); ++ object.m_Date = CDateTime(tag.m_iYear, 1, 1, 0, 0, 0).GetAsW3CDate().c_str(); + object.m_ReferenceID = NPT_String::Format("videodb://musicvideos/titles/%i", tag.m_iDbId); + } else if (tag.m_type == MediaTypeMovie) { + object.m_ObjectClass.type = "object.item.videoItem.movie"; + object.m_Title = tag.m_strTitle.c_str(); +- object.m_Date = tag.GetPremiered().GetAsW3CDate().c_str(); ++ object.m_Date = CDateTime(tag.m_iYear, 1, 1, 0, 0, 0).GetAsW3CDate().c_str(); + object.m_ReferenceID = NPT_String::Format("videodb://movies/titles/%i", tag.m_iDbId); + } else { + object.m_ObjectClass.type = "object.item.videoItem.videoBroadcast"; +@@ -529,7 +530,10 @@ BuildObject(CFileItem& item, + container->m_Recorded.episode_number = tag.m_iEpisode; + container->m_MiscInfo.play_count = tag.m_playCount; + container->m_Title = tag.m_strTitle.c_str(); +- container->m_Date = tag.GetPremiered().GetAsW3CDate().c_str(); ++ if (!tag.m_premiered.IsValid() && tag.m_iYear) ++ container->m_Date = CDateTime(tag.m_iYear, 1, 1, 0, 0, 0).GetAsW3CDateTime().c_str(); ++ else ++ container->m_Date = tag.m_premiered.GetAsW3CDate().c_str(); + + for (unsigned int index = 0; index < tag.m_genre.size(); index++) + container->m_Affiliation.genres.Add(tag.m_genre.at(index).c_str()); +@@ -567,7 +571,7 @@ BuildObject(CFileItem& item, + container->m_ChildrenCount = (NPT_Int32)count; + } else { + /* this should be a standard path */ +- //! @todo - get file count of this directory ++ // TODO - get file count of this directory + } + } + } +@@ -800,7 +804,7 @@ PopulateTagFromObject(CVideoInfoTag& tag, + tag.m_strTitle = object.m_Title; // because could be TV show Title, or Season 1 etc + tag.m_iSeason = object.m_Recorded.episode_number / 100; + tag.m_iEpisode = object.m_Recorded.episode_number % 100; +- tag.SetPremiered(date); ++ tag.m_premiered = date; + } + else if(object.m_ObjectClass.type == "object.item.videoItem.musicVideoClip") { + tag.m_type = MediaTypeMusicVideo; +@@ -812,9 +816,12 @@ PopulateTagFromObject(CVideoInfoTag& tag, + { + tag.m_type = MediaTypeMovie; + tag.m_strTitle = object.m_Title; +- tag.SetPremiered(date); ++ tag.m_premiered = date; + } + ++ if (date.IsValid()) ++ tag.m_iYear = date.GetYear(); ++ + for (unsigned int index = 0; index < object.m_People.publisher.GetItemCount(); index++) + tag.m_studio.push_back(object.m_People.publisher.GetItem(index)->GetChars()); + +diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp +index ab4545e..fbec1b4 100644 +--- a/xbmc/network/upnp/UPnPRenderer.cpp ++++ b/xbmc/network/upnp/UPnPRenderer.cpp +@@ -34,7 +34,6 @@ + #include "pictures/PictureInfoTag.h" + #include "interfaces/AnnouncementManager.h" + #include "settings/Settings.h" +-#include "PlayListPlayer.h" + #include "TextureDatabase.h" + #include "ThumbLoader.h" + #include "URL.h" +@@ -261,7 +260,7 @@ CUPnPRenderer::Announce(AnnouncementFlag flag, const char *sender, const char *m + avt->SetStateVariable("AVTransportURIMetaData", meta); + } + +- avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["player"]["speed"].asInteger())); ++ avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + avt->SetStateVariable("TransportState", "PLAYING"); + + /* this could be a transition to next track, so clear next */ +@@ -269,12 +268,11 @@ CUPnPRenderer::Announce(AnnouncementFlag flag, const char *sender, const char *m + avt->SetStateVariable("NextAVTransportURIMetaData", ""); + } + else if (strcmp(message, "OnPause") == 0) { +- int64_t speed = data["player"]["speed"].asInteger(); +- avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(speed != 0 ? speed : 1)); ++ avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + avt->SetStateVariable("TransportState", "PAUSED_PLAYBACK"); + } + else if (strcmp(message, "OnSpeedChanged") == 0) { +- avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["player"]["speed"].asInteger())); ++ avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + } + } + else if (flag == Application && strcmp(message, "OnVolumeChanged") == 0) { +diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp +index c27ea8f..c89205f 100644 +--- a/xbmc/network/upnp/UPnPServer.cpp ++++ b/xbmc/network/upnp/UPnPServer.cpp +@@ -616,7 +616,7 @@ CUPnPServer::OnBrowseMetadata(PLT_ActionReference& action, + // update ID may be wrong here, it should be the one of the container? + NPT_CHECK(action->SetArgumentValue("UpdateId", "0")); + +- //! @todo We need to keep track of the overall SystemUpdateID of the CDS ++ // TODO: We need to keep track of the overall SystemUpdateID of the CDS + + return NPT_SUCCESS; + } +@@ -1097,7 +1097,7 @@ CUPnPServer::OnUpdateObject(PLT_ActionReference& action, + } + + } else if (updated.IsMusicDb()) { +- //! @todo implement this ++ //TODO implement this + + } else { + err = 701; +diff --git a/xbmc/network/windows/NetworkWin32.cpp b/xbmc/network/windows/NetworkWin32.cpp +index 7ae8cff..c6c3e69 100644 +--- a/xbmc/network/windows/NetworkWin32.cpp ++++ b/xbmc/network/windows/NetworkWin32.cpp +@@ -150,28 +150,25 @@ std::string CNetworkInterfaceWin32::GetCurrentDefaultGateway(void) + CNetworkWin32::CNetworkWin32(void) + { + queryInterfaceList(); ++ CApplicationMessenger::GetInstance().PostMsg(TMSG_NETWORKMESSAGE, CNetwork::SERVICES_UP, 0); + } + + CNetworkWin32::~CNetworkWin32(void) + { +- CleanInterfaceList(); + m_netrefreshTimer.Stop(); ++ CleanInterfaceList(); + } + + void CNetworkWin32::CleanInterfaceList() + { +- std::vector::iterator it = m_interfaces.begin(); +- while(it != m_interfaces.end()) +- { +- CNetworkInterface* nInt = *it; +- delete nInt; +- it = m_interfaces.erase(it); +- } ++ CSingleLock lock (m_lockInterfaces); ++ auto it = m_interfaces.before_begin(); ++ m_interfaces.erase_after(it, m_interfaces.end()); + } + +-std::vector& CNetworkWin32::GetInterfaceList(void) ++std::forward_list& CNetworkWin32::GetInterfaceList(void) + { +- CSingleLock lock (m_critSection); ++ CSingleLock lock (m_lockInterfaces); + if(m_netrefreshTimer.GetElapsedSeconds() >= 5.0f) + queryInterfaceList(); + +@@ -185,6 +182,7 @@ void CNetworkWin32::queryInterfaceList() + + PIP_ADAPTER_INFO adapterInfo; + PIP_ADAPTER_INFO adapter = NULL; ++ auto *pos = m_interfaces.before_begin(); + + ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); + +@@ -205,7 +203,8 @@ void CNetworkWin32::queryInterfaceList() + adapter = adapterInfo; + while (adapter) + { +- m_interfaces.push_back(new CNetworkInterfaceWin32(this, *adapter)); ++ m_interfaces.insert_after(pos, new CNetworkInterfaceWin32(this, *adapter)); ++ ++pos; + adapter = adapter->Next; + } + } +@@ -254,15 +253,19 @@ void CNetworkWin32::SetNameServers(const std::vector& nameServers) + return; + } + +-bool CNetworkWin32::PingHost(unsigned long host, unsigned int timeout_ms /* = 2000 */) ++bool CNetworkWin32::PingHostImpl(const std::string &target, unsigned int timeout_ms /* = 2000 */) + { ++ struct sockaddr_in sa; ++ if (!CNetwork::ConvIPv4(target, &sa)) ++ return false; ++ + char SendData[] = "poke"; + HANDLE hIcmpFile = IcmpCreateFile(); + BYTE ReplyBuffer [sizeof(ICMP_ECHO_REPLY) + sizeof(SendData)]; + + SetLastError(ERROR_SUCCESS); + +- DWORD dwRetVal = IcmpSendEcho(hIcmpFile, host, SendData, sizeof(SendData), ++ DWORD dwRetVal = IcmpSendEcho(hIcmpFile, ntohl(sa.sin_addr), SendData, sizeof(SendData), + NULL, ReplyBuffer, sizeof(ReplyBuffer), timeout_ms); + + DWORD lastErr = GetLastError(); +@@ -371,7 +374,7 @@ std::vector CNetworkInterfaceWin32::GetAccessPoints(void) + bss_entry.dot11Bssid[0], bss_entry.dot11Bssid[1], bss_entry.dot11Bssid[2], + bss_entry.dot11Bssid[3], bss_entry.dot11Bssid[4], bss_entry.dot11Bssid[5]); + int signalLevel = bss_entry.lRssi; +- EncMode encryption = ENC_NONE; //! @todo implement ++ EncMode encryption = ENC_NONE; // TODO + int channel = NetworkAccessPoint::FreqToChannel((float)bss_entry.ulChCenterFrequency * 1000); + result.push_back(NetworkAccessPoint(essId, macAddress, signalLevel, encryption, channel)); + } +@@ -495,7 +498,7 @@ void CNetworkInterfaceWin32::GetSettings(NetworkAssignment& assignment, std::str + else + CLog::Log(LOGERROR, "%s: Can't open wlan handle", __FUNCTION__); + } +- //! @todo get the key (WlanGetProfile, CryptUnprotectData?) ++ // Todo: get the key (WlanGetProfile, CryptUnprotectData?) + #endif + } + +diff --git a/xbmc/network/windows/NetworkWin32.h b/xbmc/network/windows/NetworkWin32.h +index 3d5405a..0443825 100644 +--- a/xbmc/network/windows/NetworkWin32.h ++++ b/xbmc/network/windows/NetworkWin32.h +@@ -22,10 +22,10 @@ + + #include + #include ++#include + #include "network/Network.h" + #include "Iphlpapi.h" + #include "utils/stopwatch.h" +-#include "threads/CriticalSection.h" + + class CNetworkWin32; + +@@ -71,10 +71,10 @@ public: + virtual ~CNetworkWin32(void); + + // Return the list of interfaces +- virtual std::vector& GetInterfaceList(void); ++ virtual std::forward_list& GetInterfaceList(void); + + // Ping remote host +- virtual bool PingHost(unsigned long host, unsigned int timeout_ms = 2000); ++ virtual bool PingHostImpl(const std::string &target, unsigned int timeout_ms = 2000); + + // Get/set the nameserver(s) + virtual std::vector GetNameServers(void); +@@ -82,14 +82,14 @@ public: + + friend class CNetworkInterfaceWin32; + ++ bool ForceRereadInterfaces() { queryInterfaceList(); return true; } + private: + int GetSocket() { return m_sock; } + void queryInterfaceList(); + void CleanInterfaceList(); +- std::vector m_interfaces; ++ std::forward_list m_interfaces; + int m_sock; + CStopWatch m_netrefreshTimer; +- CCriticalSection m_critSection; + }; + + #endif +diff --git a/xbmc/peripherals/EventScanner.h b/xbmc/peripherals/EventScanner.h +index 1951016..a645c00 100644 +--- a/xbmc/peripherals/EventScanner.h ++++ b/xbmc/peripherals/EventScanner.h +@@ -19,8 +19,6 @@ + */ + #pragma once + +-#include +- + #include "EventScanRate.h" + #include "threads/CriticalSection.h" + #include "threads/Event.h" +@@ -60,7 +58,7 @@ namespace PERIPHERALS + EventRateHandle SetRate(float rateHz); + + // implementation of IEventRateCallback +- virtual void Release(CEventRateHandle* handle) override; ++ virtual void Release(CEventRateHandle* handle); + + protected: + // implementation of CThread +diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h +index f93adc2..efcd352 100644 +--- a/xbmc/peripherals/PeripheralTypes.h ++++ b/xbmc/peripherals/PeripheralTypes.h +@@ -40,11 +40,13 @@ namespace PERIPHERALS + PERIPHERAL_BUS_USB, + PERIPHERAL_BUS_PCI, + PERIPHERAL_BUS_RPI, ++ PERIPHERAL_BUS_IMX, + PERIPHERAL_BUS_CEC, + PERIPHERAL_BUS_ADDON, + #ifdef TARGET_ANDROID + PERIPHERAL_BUS_ANDROID, + #endif ++ PERIPHERAL_BUS_PLATFORM, + }; + + enum PeripheralFeature +@@ -59,6 +61,7 @@ namespace PERIPHERALS + FEATURE_TUNER, + FEATURE_IMON, + FEATURE_JOYSTICK, ++ FEATURE_CABLESTATE, + }; + + enum PeripheralType +@@ -73,6 +76,7 @@ namespace PERIPHERALS + PERIPHERAL_TUNER, + PERIPHERAL_IMON, + PERIPHERAL_JOYSTICK, ++ PERIPHERAL_VIDEO, + }; + + class CPeripheralAddon; +@@ -126,6 +130,8 @@ namespace PERIPHERALS + return "imon"; + case PERIPHERAL_JOYSTICK: + return "joystick"; ++ case PERIPHERAL_VIDEO: ++ return "video"; + default: + return "unknown"; + } +@@ -154,6 +160,8 @@ namespace PERIPHERALS + return PERIPHERAL_IMON; + else if (strTypeLowerCase == "joystick") + return PERIPHERAL_JOYSTICK; ++ else if (strTypeLowerCase == "video") ++ return PERIPHERAL_VIDEO; + + return PERIPHERAL_UNKNOWN; + }; +@@ -168,6 +176,8 @@ namespace PERIPHERALS + return "pci"; + case PERIPHERAL_BUS_RPI: + return "rpi"; ++ case PERIPHERAL_BUS_IMX: ++ return "imx"; + case PERIPHERAL_BUS_CEC: + return "cec"; + case PERIPHERAL_BUS_ADDON: +@@ -176,6 +186,8 @@ namespace PERIPHERALS + case PERIPHERAL_BUS_ANDROID: + return "android"; + #endif ++ case PERIPHERAL_BUS_PLATFORM: ++ return "platform"; + default: + return "unknown"; + } +@@ -192,6 +204,8 @@ namespace PERIPHERALS + return PERIPHERAL_BUS_PCI; + else if (strTypeLowerCase == "rpi") + return PERIPHERAL_BUS_RPI; ++ else if (strTypeLowerCase == "imx") ++ return PERIPHERAL_BUS_IMX; + else if (strTypeLowerCase == "cec") + return PERIPHERAL_BUS_CEC; + else if (strTypeLowerCase == "addon") +@@ -200,6 +214,8 @@ namespace PERIPHERALS + else if (strTypeLowerCase == "android") + return PERIPHERAL_BUS_ANDROID; + #endif ++ else if (strTypeLowerCase == "platform") ++ return PERIPHERAL_BUS_PLATFORM; + + return PERIPHERAL_BUS_UNKNOWN; + }; +@@ -220,6 +236,14 @@ namespace PERIPHERALS + + strHexString = StringUtils::Format("%04X", iVal); + }; ++ ++ static void UeventToName(std::string &uevent, std::string &name) ++ { ++ std::vector data = StringUtils::Split(uevent, "\n"); ++ for (size_t i = 0; i < data.size(); i++) ++ if (StringUtils::StartsWith(data[i], "OF_NAME=")) ++ name = data[i].substr(8, data[i].length()); ++ }; + }; + + class PeripheralScanResult +diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp +index 55c8f1d..20a4aae 100644 +--- a/xbmc/peripherals/Peripherals.cpp ++++ b/xbmc/peripherals/Peripherals.cpp +@@ -39,6 +39,7 @@ + #include "devices/PeripheralNIC.h" + #include "devices/PeripheralNyxboard.h" + #include "devices/PeripheralTuner.h" ++#include "devices/PeripheralVideo.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "dialogs/GUIDialogOK.h" + #include "dialogs/GUIDialogPeripheralSettings.h" +@@ -100,26 +101,22 @@ void CPeripherals::Initialise() + /* load mappings from peripherals.xml */ + LoadMappings(); + +- std::vector busses; +- ++ { ++ CSingleLock bussesLock(m_critSectionBusses); + #if defined(HAVE_PERIPHERAL_BUS_USB) +- busses.push_back(std::make_shared(this)); ++ m_busses.push_back(std::make_shared(this)); + #endif + #if defined(HAVE_LIBCEC) +- busses.push_back(std::make_shared(this)); ++ m_busses.push_back(std::make_shared(this)); + #endif +- busses.push_back(std::make_shared(this)); ++ m_busses.push_back(std::make_shared(this)); + #if defined(TARGET_ANDROID) +- busses.push_back(std::make_shared(this)); ++ m_busses.push_back(std::make_shared(this)); + #endif + +- /* initialise all known busses and run an initial scan for devices */ +- for (auto& bus : busses) +- bus->Initialise(); +- +- { +- CSingleLock bussesLock(m_critSectionBusses); +- m_busses = std::move(busses); ++ /* initialise all known busses and run an initial scan for devices */ ++ for (auto& bus : m_busses) ++ bus->Initialise(); + } + + m_eventScanner.Start(); +@@ -329,6 +326,10 @@ CPeripheral *CPeripherals::CreatePeripheral(CPeripheralBus &bus, const Periphera + peripheral = new CPeripheralJoystick(mappedResult, &bus); + break; + ++ case PERIPHERAL_VIDEO: ++ peripheral = new CPeripheralVideo(mappedResult, &bus); ++ break; ++ + default: + break; + } +@@ -556,7 +557,7 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, std::mapSetVisible(bConfigurable); +@@ -731,7 +732,7 @@ void CPeripherals::ProcessEvents(void) + { + std::vector busses; + { +- CSingleLock lock(m_critSectionBusses); ++ CSingleLock lock(m_critSection); + busses = m_busses; + } + +@@ -900,3 +901,10 @@ int CPeripherals::GetMessageMask() + { + return TMSG_MASK_PERIPHERALS; + } ++ ++void CPeripherals::CreatePeripheralBus(PeripheralBusPtr bus) ++{ ++ CSingleLock bussesLock(m_critSectionBusses); ++ m_busses.push_back(bus); ++ bus->Initialise(); ++} +diff --git a/xbmc/peripherals/Peripherals.h b/xbmc/peripherals/Peripherals.h +index ed886df..ea5201e 100644 +--- a/xbmc/peripherals/Peripherals.h ++++ b/xbmc/peripherals/Peripherals.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "EventScanner.h" + #include "bus/PeripheralBus.h" + #include "devices/Peripheral.h" +@@ -193,13 +191,13 @@ namespace PERIPHERALS + * @brief Try to mute the audio via a peripheral. + * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. + */ +- virtual bool Mute() { return ToggleMute(); } //! @todo CEC only supports toggling the mute status at this time ++ virtual bool Mute() { return ToggleMute(); } // TODO CEC only supports toggling the mute status at this time + + /*! + * @brief Try to unmute the audio via a peripheral. + * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. + */ +- virtual bool UnMute() { return ToggleMute(); } //! @todo CEC only supports toggling the mute status at this time ++ virtual bool UnMute() { return ToggleMute(); } // TODO CEC only supports toggling the mute status at this time + + /*! + * @brief Try to get a keypress from a peripheral. +@@ -216,6 +214,8 @@ namespace PERIPHERALS + */ + EventRateHandle SetEventScanRate(float rateHz) { return m_eventScanner.SetRate(rateHz); } + ++ virtual void CreatePeripheralBus(PeripheralBusPtr bus); ++ + bool SupportsCEC() const + { + #if defined(HAVE_LIBCEC) +diff --git a/xbmc/peripherals/addons/AddonButtonMap.cpp b/xbmc/peripherals/addons/AddonButtonMap.cpp +index ae65bd8..af82583 100644 +--- a/xbmc/peripherals/addons/AddonButtonMap.cpp ++++ b/xbmc/peripherals/addons/AddonButtonMap.cpp +@@ -272,7 +272,7 @@ bool CAddonButtonMap::AddAccelerometer(const FeatureName& feature, + accelerometer.SetPositiveZ(CPeripheralAddonTranslator::TranslatePrimitive(positiveZ)); + } + +- //! @todo Unmap complementary semiaxes ++ // TODO: Unmap complementary semiaxes + + m_features[feature] = accelerometer; + } +diff --git a/xbmc/peripherals/bus/Makefile.in b/xbmc/peripherals/bus/Makefile.in +index df5250c..d7b0e93 100644 +--- a/xbmc/peripherals/bus/Makefile.in ++++ b/xbmc/peripherals/bus/Makefile.in +@@ -8,6 +8,7 @@ endif + + ifeq (@USE_LIBUDEV@,1) + SRCS += linux/PeripheralBusUSBLibUdev.cpp ++SRCS += linux/PeripheralBusPLATFORMLibUdev.cpp + endif + + ifeq (@USE_LIBUSB@,1) +diff --git a/xbmc/peripherals/bus/PeripheralBus.cpp b/xbmc/peripherals/bus/PeripheralBus.cpp +index 6f07e27..3cddd2e 100644 +--- a/xbmc/peripherals/bus/PeripheralBus.cpp ++++ b/xbmc/peripherals/bus/PeripheralBus.cpp +@@ -114,6 +114,7 @@ void CPeripheralBus::UnregisterRemovedDevices(const PeripheralScanResults &resul + + void CPeripheralBus::RegisterNewDevices(const PeripheralScanResults &results) + { ++ CSingleLock lock(m_critSection); + for (unsigned int iResultPtr = 0; iResultPtr < results.m_results.size(); iResultPtr++) + { + const PeripheralScanResult& result = results.m_results.at(iResultPtr); +@@ -122,6 +123,15 @@ void CPeripheralBus::RegisterNewDevices(const PeripheralScanResults &results) + } + } + ++CPeripheral *CPeripheralBus::RegisterNewDevice(const PeripheralScanResult &result) ++{ ++ CSingleLock lock(m_critSection); ++ if (!HasPeripheral(result.m_strLocation)) ++ return g_peripherals.CreatePeripheral(*this, result); ++ else ++ return GetPeripheral(result.m_strLocation); ++} ++ + bool CPeripheralBus::ScanForDevices(void) + { + bool bReturn(false); +@@ -209,6 +219,13 @@ size_t CPeripheralBus::GetNumberOfPeripheralsWithId(const int iVendorId, const i + return iReturn; + } + ++size_t CPeripheralBus::GetNumberOfPeripheralsWithFeature(const PeripheralFeature feature) const ++{ ++ std::vector peripherals; ++ GetPeripheralsWithFeature(peripherals, feature); ++ return peripherals.size(); ++} ++ + void CPeripheralBus::Process(void) + { + while (!m_bStop) +diff --git a/xbmc/peripherals/bus/PeripheralBus.h b/xbmc/peripherals/bus/PeripheralBus.h +index 8093ca2..49f25bc 100644 +--- a/xbmc/peripherals/bus/PeripheralBus.h ++++ b/xbmc/peripherals/bus/PeripheralBus.h +@@ -80,6 +80,7 @@ namespace PERIPHERALS + + virtual size_t GetNumberOfPeripherals() const; + virtual size_t GetNumberOfPeripheralsWithId(const int iVendorId, const int iProductId) const; ++ virtual size_t GetNumberOfPeripheralsWithFeature(const PeripheralFeature feature) const; + + /*! + * @brief Get all features that are supported by devices on this bus. +@@ -156,6 +157,8 @@ namespace PERIPHERALS + */ + virtual void ProcessEvents(void) { } + ++ virtual CPeripheral *RegisterNewDevice(const PeripheralScanResult &result); ++ + protected: + virtual void Process(void); + virtual bool ScanForDevices(void); +diff --git a/xbmc/peripherals/bus/android/PeripheralBusAndroid.cpp b/xbmc/peripherals/bus/android/PeripheralBusAndroid.cpp +index d5a84b1..3ba40d8 100644 +--- a/xbmc/peripherals/bus/android/PeripheralBusAndroid.cpp ++++ b/xbmc/peripherals/bus/android/PeripheralBusAndroid.cpp +@@ -339,13 +339,15 @@ bool CPeripheralBusAndroid::GetDeviceId(const std::string& deviceLocation, int& + bool CPeripheralBusAndroid::ConvertToPeripheralScanResult(const CJNIViewInputDevice& inputDevice, PeripheralScanResult& peripheralScanResult) + { + int deviceId = inputDevice.getId(); ++ int sources = inputDevice.getSources(); + std::string deviceName = inputDevice.getName(); + if (inputDevice.isVirtual()) + { + CLog::Log(LOGDEBUG, "CPeripheralBusAndroid: ignoring virtual input device \"%s\" with ID %d", deviceName.c_str(), deviceId); + return false; + } +- if (!inputDevice.supportsSource(CJNIViewInputDevice::SOURCE_JOYSTICK) && !inputDevice.supportsSource(CJNIViewInputDevice::SOURCE_GAMEPAD)) ++ if ((sources & CJNIViewInputDevice::SOURCE_JOYSTICK) != CJNIViewInputDevice::SOURCE_JOYSTICK && ++ (sources & CJNIViewInputDevice::SOURCE_GAMEPAD) != CJNIViewInputDevice::SOURCE_GAMEPAD) + { + CLog::Log(LOGDEBUG, "CPeripheralBusAndroid: ignoring unknown input device \"%s\" with ID %d", deviceName.c_str(), deviceId); + return false; +diff --git a/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.cpp b/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.cpp +new file mode 100644 +index 0000000..44762c7 +--- /dev/null ++++ b/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.cpp +@@ -0,0 +1,142 @@ ++/* ++ ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "PeripheralBusPLATFORMLibUdev.h" ++#include "peripherals/Peripherals.h" ++extern "C" { ++#include ++} ++#include ++#include "utils/log.h" ++ ++using namespace PERIPHERALS; ++ ++CPeripheralBusPLATFORM::CPeripheralBusPLATFORM(CPeripherals *manager, const std::string &threadname, PeripheralBusType type) : ++ CPeripheralBusUSB(manager, threadname, type) ++{ ++ m_bNeedsPolling = false; ++ udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "platform", NULL); ++ udev_monitor_filter_update(m_udevMon); ++ Create(); ++} ++ ++void CPeripheralBusPLATFORM::Clear(void) ++{ ++ StopThread(false); ++} ++ ++bool CPeripheralBusPLATFORM::PerformDeviceScan(PeripheralScanResults &results) ++{ ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices, *dev_list_entry; ++ struct udev_device *dev(NULL); ++ enumerate = udev_enumerate_new(m_udev); ++ udev_enumerate_scan_devices(enumerate); ++ devices = udev_enumerate_get_list_entry(enumerate); ++ ++ bool bContinue(true); ++ std::string strPath, t; ++ udev_list_entry_foreach(dev_list_entry, devices) ++ { ++ strPath = udev_list_entry_get_name(dev_list_entry); ++ dev = udev_device_new_from_syspath(m_udev, strPath.c_str()); ++ if (strPath.empty() || !dev) ++ bContinue = false; ++ ++ if (bContinue) ++ { ++ bContinue = false; ++ if (GetCableState(udev_device_get_syspath(dev))) ++ bContinue = true; ++ } ++ ++ if (bContinue) ++ { ++ PeripheralScanResult result(m_type); ++ result.m_strLocation = udev_device_get_syspath(dev); ++ result.m_iSequence = GetNumberOfPeripheralsWithFeature(FEATURE_CABLESTATE); ++ result.m_type = PERIPHERAL_VIDEO; ++ ++ t = udev_device_get_sysattr_value(dev, "uevent"); ++ PeripheralTypeTranslator::UeventToName(t, result.m_strDeviceName); ++ if (result.m_strDeviceName.empty()) ++ result.m_strDeviceName += "generic_video"; ++ ++ result.m_iVendorId = 0; ++ result.m_iProductId = 0; ++ ++ if (!results.ContainsResult(result)) ++ results.m_results.push_back(result); ++ } ++ ++ bContinue = true; ++ } ++ /* Free the enumerator object */ ++ udev_enumerate_unref(enumerate); ++ ++ return true; ++} ++ ++int CPeripheralBusPLATFORM::GetCableState(const std::string &strLocation) ++{ ++ struct udev_device *dev = udev_device_new_from_syspath(m_udev, strLocation.c_str()); ++ std::string files[] = { "cable_state", "status", "state" }; ++ std::vector cableState(files, files + 3); ++ ++ std::string t; ++ int state = CABLE_UNKNOWN; ++ ++ if (!dev) ++ return state; ++ ++ for (std::vector::iterator f = cableState.begin() ; f != cableState.end(); ++f) ++ { ++ if (udev_device_get_sysattr_value(dev, f->c_str())) ++ t = udev_device_get_sysattr_value(dev, f->c_str()); ++ ++ if (!t.empty() && (t.find("disconnected") != std::string::npos || t.find("plugout") != std::string::npos)) ++ state = CABLE_DISCONNECTED; ++ if (!t.empty() && (t.find("connected") != std::string::npos || t.find("plugin") != std::string::npos)) ++ state = CABLE_CONNECTED; ++ ++ if (state) ++ break; ++ } ++ ++ return state; ++} ++ ++void CPeripheralBusPLATFORM::Process(void) ++{ ++ ScanForDevices(); ++ while (!m_bStop) ++ WaitForUpdate(); ++ ++ m_bIsStarted = false; ++} ++ ++void CPeripheralBusPLATFORM::OnDeviceChanged(const std::string &strLocation) ++{ ++ CSingleLock lock(m_critSection); ++ CPeripheral *peripheral = GetPeripheral(strLocation); ++ if (peripheral) ++ peripheral->OnDeviceChanged(GetCableState(strLocation)); ++} +diff --git a/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h b/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h +new file mode 100644 +index 0000000..32a181a +--- /dev/null ++++ b/xbmc/peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h +@@ -0,0 +1,47 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "peripherals/bus/linux/PeripheralBusUSBLibUdev.h" ++ ++struct udev_device; ++ ++namespace PERIPHERALS ++{ ++ class CPeripherals; ++ ++ class CPeripheralBusPLATFORM : public CPeripheralBusUSB ++ { ++ public: ++ CPeripheralBusPLATFORM(CPeripherals *manager, const std::string &threadname = "PeripBusPLATFORMUdev", PeripheralBusType type = PERIPHERAL_BUS_PLATFORM); ++ virtual ~CPeripheralBusPLATFORM(void) {}; ++ ++ virtual void Clear(void) override; ++ ++ bool PerformDeviceScan(PeripheralScanResults &results); ++ ++ virtual void OnDeviceChanged(const std::string &strLocation) override; ++ void OnDeviceAdded(const std::string &strLocation) {}; ++ int GetCableState(const std::string &strLocation); ++ ++ protected: ++ virtual void Process(void) override; ++ }; ++} +diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp +index acbb54b..636f579 100644 +--- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp ++++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp +@@ -76,8 +76,8 @@ extern "C" { + + using namespace PERIPHERALS; + +-CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : +- CPeripheralBus("PeripBusUSBUdev", manager, PERIPHERAL_BUS_USB) ++CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager, const std::string &threadname, PeripheralBusType type) : ++ CPeripheralBus(threadname, manager, type) + { + /* the Process() method in this class overrides the one in CPeripheralBus, so leave this set to true */ + m_bNeedsPolling = true; +@@ -95,12 +95,13 @@ CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : + m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); + udev_monitor_enable_receiving(m_udevMon); + +- CLog::Log(LOGDEBUG, "%s - initialised udev monitor", __FUNCTION__); ++ CLog::Log(LOGDEBUG, "%s - initialised %s monitor", __FUNCTION__, threadname.c_str()); + } + + CPeripheralBusUSB::~CPeripheralBusUSB(void) + { +- StopThread(true); ++ if(IsRunning()) ++ StopThread(true); + udev_monitor_unref(m_udevMon); + udev_unref(m_udev); + } +@@ -147,8 +148,8 @@ bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) + int iClass = PeripheralTypeTranslator::HexStringToInt(strClass.c_str()); + if (iClass == USB_CLASS_PER_INTERFACE) + { +- //! @todo just assume this is a HID device for now, since the only devices that we're currently +- //! interested in are HID devices ++ //TODO just assume this is a HID device for now, since the only devices that we're currently ++ // interested in are HID devices + iClass = USB_CLASS_HID; + } + +@@ -246,7 +247,10 @@ bool CPeripheralBusUSB::WaitForUpdate() + /* we have to read the message from the queue, even though we're not actually using it */ + struct udev_device *dev = udev_monitor_receive_device(m_udevMon); + if (dev) ++ { ++ OnDeviceChanged(udev_device_get_syspath(dev)); + udev_device_unref(dev); ++ } + else + { + CLog::Log(LOGERROR, "%s - failed to get device from udev_monitor_receive_device()", __FUNCTION__); +diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h +index b7715ce..eed2134 100644 +--- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h ++++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h +@@ -32,7 +32,7 @@ namespace PERIPHERALS + class CPeripheralBusUSB : public CPeripheralBus + { + public: +- CPeripheralBusUSB(CPeripherals *manager); ++ CPeripheralBusUSB(CPeripherals *manager, const std::string &threadname = "PeripBusUSBUdev", PeripheralBusType type = PERIPHERAL_BUS_USB); + virtual ~CPeripheralBusUSB(void); + + virtual void Clear(void); +diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h +index 2f09b5a..36c76ff 100644 +--- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h ++++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h +@@ -29,7 +29,6 @@ + + #include + #include +-#include + + namespace PERIPHERALS + { +diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp +index b04fe00..3dc3d0e 100644 +--- a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp ++++ b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp +@@ -102,6 +102,10 @@ bool CPeripheralBusCEC::PerformDeviceScan(PeripheralScanResults &results) + /** the Pi's adapter cannot be removed, no need to rescan */ + m_bNeedsPolling = false; + break; ++ case ADAPTERTYPE_IMX: ++ result.m_mappedBusType = PERIPHERAL_BUS_IMX; ++ m_bNeedsPolling = false; ++ break; + default: + break; + } +diff --git a/xbmc/peripherals/devices/Makefile.in b/xbmc/peripherals/devices/Makefile.in +index b79d94a..0743986 100644 +--- a/xbmc/peripherals/devices/Makefile.in ++++ b/xbmc/peripherals/devices/Makefile.in +@@ -7,6 +7,7 @@ SRCS += PeripheralJoystick.cpp + SRCS += PeripheralNIC.cpp + SRCS += PeripheralNyxboard.cpp + SRCS += PeripheralTuner.cpp ++SRCS += PeripheralVideo.cpp + + ifeq (@USE_LIBCEC@,1) + SRCS += PeripheralCecAdapter.cpp +diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp +index 95aa63a..a14e10b 100644 +--- a/xbmc/peripherals/devices/Peripheral.cpp ++++ b/xbmc/peripherals/devices/Peripheral.cpp +@@ -255,7 +255,7 @@ void CPeripheral::AddSetting(const std::string &strKey, const CSetting *setting, + } + break; + default: +- //! @todo add more types if needed ++ //TODO add more types if needed + break; + } + +diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h +index 646f588..e79306d 100644 +--- a/xbmc/peripherals/devices/Peripheral.h ++++ b/xbmc/peripherals/devices/Peripheral.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + #include "peripherals/PeripheralTypes.h" + + class TiXmlDocument; +@@ -47,6 +46,13 @@ namespace PERIPHERALS + STATE_STANDBY + } CecStateChange; + ++ typedef enum ++ { ++ CABLE_UNKNOWN = 0, ++ CABLE_DISCONNECTED, ++ CABLE_CONNECTED ++ } ScreenCableState; ++ + class CPeripheral + { + friend class CGUIDialogPeripheralSettings; +@@ -106,6 +112,11 @@ namespace PERIPHERALS + virtual void OnSettingChanged(const std::string &strChangedSetting) {}; + + /*! ++ * @brief Called when this device is changed. ++ */ ++ virtual void OnDeviceChanged(int state) {}; ++ ++ /*! + * @brief Called when this device is removed, before calling the destructor. + */ + virtual void OnDeviceRemoved(void) {} +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +index f784bde..a54a794 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +@@ -35,6 +35,7 @@ + #include "utils/JobManager.h" + #include "utils/log.h" + #include "utils/Variant.h" ++#include "utils/Screen.h" + + #include + +@@ -128,7 +129,7 @@ void CPeripheralCecAdapter::ResetMembers(void) + m_lastKeypress = 0; + m_lastChange = VOLUME_CHANGE_NONE; + m_iExitCode = EXITCODE_QUIT; +- m_bIsMuted = false; //! @todo fetch the correct initial value when system audiostatus is implemented in libCEC ++ m_bIsMuted = false; // TODO fetch the correct initial value when system audiostatus is implemented in libCEC + m_bGoingToStandby = false; + m_bIsRunning = false; + m_bDeviceRemoved = false; +@@ -170,6 +171,9 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + m_configuration.bActivateSource == 1) + { + ActivateSource(); ++ if (!m_configuration.wakeDevices.IsEmpty() && m_configuration.wakeDevices.primary == CECDEVICE_AUDIOSYSTEM && ++ GetAudioSystemConnected()) ++ m_cecAdapter->PowerOnDevices(CECDEVICE_AUDIOSYSTEM); + } + } + else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && m_bIsReady) +@@ -180,6 +184,8 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + // only power off when we're the active source + if (m_cecAdapter->IsLibCECActiveSource()) + StandbyDevices(); ++ if (!(CEC_POWER_STATUS_ON == m_cecAdapter->GetDevicePowerStatus(CECDEVICE_TV) && m_cecAdapter->IsLibCECActiveSource())) ++ g_screen.SetOff(); + } + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) +@@ -334,8 +340,6 @@ bool CPeripheralCecAdapter::OpenConnection(void) + if (!bConnectionFailedDisplayed) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); + bConnectionFailedDisplayed = true; +- +- Sleep(10000); + } + } + +@@ -386,7 +390,7 @@ void CPeripheralCecAdapter::Process(void) + ProcessStandbyDevices(); + + if (!m_bStop) +- Sleep(5); ++ Sleep(20); + } + + m_queryThread->StopThread(true); +@@ -449,6 +453,12 @@ void CPeripheralCecAdapter::SetAudioSystemConnected(bool bSetTo) + m_bHasConnectedAudioSystem = bSetTo; + } + ++bool CPeripheralCecAdapter::GetAudioSystemConnected() ++{ ++ CSingleLock lock(m_critSection); ++ return m_bHasConnectedAudioSystem; ++} ++ + void CPeripheralCecAdapter::ProcessVolumeChange(void) + { + bool bSendRelease(false); +@@ -634,6 +644,12 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command command) + else if (adapter->m_configuration.bShutdownOnStandby == 1) + g_application.ExecuteXBMCAction("Shutdown"); + } ++ if (command.initiator == CECDEVICE_TV) ++ { ++ if (adapter->GetSettingInt("standby_pc_on_tv_standby") == 13007) ++ CecEventPostAction(cbParam, 0, true); ++ g_screen.SetOff(); ++ } + break; + case CEC_OPCODE_SET_MENU_LANGUAGE: + if (adapter->m_configuration.bUseTVMenuLanguage == 1 && command.initiator == CECDEVICE_TV && command.parameters.size == 3) +@@ -1150,16 +1166,13 @@ void CPeripheralCecAdapter::OnSettingChanged(const std::string &strChangedSettin + } + } + +-void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_logical_address address, const uint8_t activated) ++ ++void CPeripheralCecAdapter::CecEventPostAction(void *cbParam, const uint8_t activated, bool wait) + { + CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; + if (!adapter) + return; + +- // wake up the screensaver, so the user doesn't switch to a black screen +- if (activated == 1) +- g_application.WakeUpScreenSaverAndDPMS(); +- + if (adapter->GetSettingInt("pause_or_stop_playback_on_deactivate") != LOCALISED_ID_NONE) + { + bool bShowingSlideshow = (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW); +@@ -1181,18 +1194,35 @@ void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_log + pSlideShow->OnAction(CAction(ACTION_PAUSE)); + else + // pause/resume player +- CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PAUSE); ++ CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PAUSE, wait); + } +- else if (adapter->GetSettingInt("pause_or_stop_playback_on_deactivate") == LOCALISED_ID_STOP) ++ else if (bPlayingAndDeactivated ++ && adapter->GetSettingInt("pause_or_stop_playback_on_deactivate") == LOCALISED_ID_STOP) + { + if (pSlideShow) + pSlideShow->OnAction(CAction(ACTION_STOP)); + else +- CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_STOP); ++ CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_STOP, wait); + } + } + } + ++void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_logical_address address, const uint8_t activated) ++{ ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return; ++ ++ // wake up the screensaver, so the user doesn't switch to a black screen ++ if (activated == 1) ++ g_application.WakeUpScreenSaverAndDPMS(); ++ ++ CecEventPostAction(cbParam, activated, true); ++ ++ if (activated != 1) ++ g_screen.SetOff(); ++} ++ + int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message message) + { + CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; +@@ -1219,8 +1249,7 @@ int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message me + break; + } + +- if (iLevel >= CEC_LOG_NOTICE || (iLevel >= 0 && CLog::IsLogLevelLogged(LOGDEBUG) && g_advancedSettings.CanLogComponent(LOGCEC))) +- CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message); ++ CLog::Log(iLevel | LOGCEC, "%s - %s", __FUNCTION__, message.message); + + return 1; + } +@@ -1294,7 +1323,7 @@ void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configu + + bChanged |= SetSetting("standby_pc_on_tv_standby", + m_configuration.bPowerOffOnStandby == 1 ? 13011 : +- m_configuration.bShutdownOnStandby == 1 ? 13005 : 36028); ++ m_configuration.bShutdownOnStandby == 1 ? 13005 : GetSettingInt("standby_pc_on_tv_standby")); + + if (bChanged) + CLog::Log(LOGDEBUG, "SetConfigurationFromLibCEC - settings updated by libCEC"); +@@ -1317,6 +1346,11 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void) + iDeviceType = (int)CEC_DEVICE_TYPE_RECORDING_DEVICE; + m_configuration.deviceTypes.Add((cec_device_type)iDeviceType); + ++ // add all other remaining device types - in case we have already 3 recorders ++ // XBMC would fail obtaining LA ++ m_configuration.deviceTypes.Add((cec_device_type)CEC_DEVICE_TYPE_PLAYBACK_DEVICE); ++ m_configuration.deviceTypes.Add((cec_device_type)CEC_DEVICE_TYPE_TUNER); ++ + // always try to autodetect the address. + // when the firmware supports this, it will override the physical address, connected device and hdmi port settings + m_configuration.bAutodetectAddress = CEC_DEFAULT_SETTING_AUTODETECT_ADDRESS; +@@ -1383,7 +1417,7 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void) + + #if defined(CEC_DOUBLE_TAP_TIMEOUT_MS_OLD) + // double tap prevention timeout in ms. libCEC uses 50ms units for this in 2.2.0, so divide by 50 +- m_configuration.iDoubleTapTimeout50Ms = GetSettingInt("double_tap_timeout_ms") / 50; ++ m_configuration.iDoubleTapTimeout50Ms = (GetSettingInt("double_tap_timeout_ms") / 50 > 10) ? 4 : GetSettingInt("double_tap_timeout_ms") / 50; + #else + // backwards compatibility. will be removed once the next major release of libCEC is out + m_configuration.iDoubleTapTimeoutMs = GetSettingInt("double_tap_timeout_ms"); +@@ -1423,8 +1457,8 @@ void CPeripheralCecAdapter::ReadLogicalAddresses(int iLocalisedId, cec_logical_a + addresses.Set(CECDEVICE_AUDIOSYSTEM); + break; + case LOCALISED_ID_TV_AVR: +- addresses.Set(CECDEVICE_TV); + addresses.Set(CECDEVICE_AUDIOSYSTEM); ++ addresses.Set(CECDEVICE_TV); + break; + case LOCALISED_ID_NONE: + default: +@@ -1505,9 +1539,12 @@ bool CPeripheralCecAdapterUpdateThread::WaitReady(void) + if (m_configuration.wakeDevices.IsEmpty() && m_configuration.bActivateSource == 0) + return true; + ++ CTimer m_timer(this); ++ m_timer.Start(30000); ++ + // wait for the TV if we're configured to become the active source. + // wait for the first device in the wake list otherwise. +- cec_logical_address waitFor = (m_configuration.bActivateSource == 1) ? ++ cec_logical_address waitFor = (m_configuration.bActivateSource == 1 && m_adapter->m_bActiveSourcePending) ? + CECDEVICE_TV : + m_configuration.wakeDevices.primary; + +@@ -1571,38 +1608,48 @@ std::string CPeripheralCecAdapterUpdateThread::UpdateAudioSystemStatus(void) + + bool CPeripheralCecAdapterUpdateThread::SetInitialConfiguration(void) + { +- // the option to make XBMC the active source is set +- if (m_configuration.bActivateSource == 1) +- m_adapter->m_cecAdapter->SetActiveSource(); ++ std::string strNotification; ++ std::string strAmpName = UpdateAudioSystemStatus(); ++ if (!strAmpName.empty()) ++ strNotification += StringUtils::Format("- %s", strAmpName.c_str()); + + // devices to wake are set +- cec_logical_addresses tvOnly; +- tvOnly.Clear(); tvOnly.Set(CECDEVICE_TV); +- if (!m_configuration.wakeDevices.IsEmpty() && (m_configuration.wakeDevices != tvOnly || m_configuration.bActivateSource == 0)) +- m_adapter->m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); ++ if (!m_configuration.wakeDevices.IsEmpty() && (m_configuration.wakeDevices.primary != CECDEVICE_TV || m_configuration.bActivateSource == 0)) ++ { ++ m_adapter->m_cecAdapter->PowerOnDevices(m_configuration.wakeDevices.primary); ++ if (m_configuration.wakeDevices.primary == CECDEVICE_AUDIOSYSTEM && m_adapter->GetAudioSystemConnected()) ++ WaitReady(); ++ } ++ ++ // the option to make XBMC the active source is set ++ if (m_configuration.bActivateSource == 1) ++ m_adapter->ActivateSource(); + +- // wait until devices are powered up ++ // wait until power up + if (!WaitReady()) + return false; + + UpdateMenuLanguage(); ++ CTimer m_timer(this); ++ m_timer.Start(10000); ++ // wait until we get active source ++ bool bContinue(true); ++ while (!m_adapter->m_cecAdapter->IsLibCECActiveSource() && ++ bContinue) ++ bContinue = !m_event.WaitMSec(1000); ++ ++ { ++ CSingleLock lock(m_critSection); ++ m_adapter->m_bIsReady = true; ++ m_bIsUpdating = false; ++ } + + // request the OSD name of the TV +- std::string strNotification; + cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); +- strNotification = StringUtils::Format("%s: %s", g_localizeStrings.Get(36016).c_str(), tvName.name); +- +- std::string strAmpName = UpdateAudioSystemStatus(); +- if (!strAmpName.empty()) +- strNotification += StringUtils::Format("- %s", strAmpName.c_str()); +- +- m_adapter->m_bIsReady = true; ++ strNotification = StringUtils::Format("%s: %s", /*g_localizeStrings.Get(36016).c_str()*/"Connected", tvName.name); + + // and let the gui know that we're done +- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); +- +- CSingleLock lock(m_critSection); +- m_bIsUpdating = false; ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, /*g_localizeStrings.Get(36000)*/"Pulse-Eight CEC adapter", strNotification); + return true; + } + +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h +index e7f769f..af84e42 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h +@@ -48,9 +48,9 @@ namespace PERIPHERALS + #include "PeripheralHID.h" + #include "interfaces/AnnouncementManager.h" + #include "threads/Thread.h" ++#include "threads/Timer.h" + #include "threads/CriticalSection.h" + #include +-#include + + // undefine macro isset, it collides with function in cectypes.h + #ifdef isset +@@ -143,8 +143,11 @@ namespace PERIPHERALS + void GetNextKey(void); + + void SetAudioSystemConnected(bool bSetTo); ++ bool GetAudioSystemConnected(); + void SetMenuLanguage(const char *strLanguage); + ++ static void CecEventPostAction(void *cbParam, const uint8_t activated, bool wait); ++ + // callbacks from libCEC + static int CecLogMessage(void *cbParam, const CEC::cec_log_message message); + static int CecCommand(void *cbParam, const CEC::cec_command command); +@@ -184,7 +187,7 @@ namespace PERIPHERALS + std::string m_strComPort; + }; + +- class CPeripheralCecAdapterUpdateThread : public CThread ++ class CPeripheralCecAdapterUpdateThread : public CThread, ITimerCallback + { + public: + CPeripheralCecAdapterUpdateThread(CPeripheralCecAdapter *adapter, CEC::libcec_configuration *configuration); +@@ -199,6 +202,7 @@ namespace PERIPHERALS + bool WaitReady(void); + bool SetInitialConfiguration(void); + void Process(void); ++ void OnTimeout() { m_event.Set(); }; + + CPeripheralCecAdapter * m_adapter; + CEvent m_event; +diff --git a/xbmc/peripherals/devices/PeripheralJoystick.h b/xbmc/peripherals/devices/PeripheralJoystick.h +index 965285e..67c6ec4 100644 +--- a/xbmc/peripherals/devices/PeripheralJoystick.h ++++ b/xbmc/peripherals/devices/PeripheralJoystick.h +@@ -33,7 +33,7 @@ + + namespace PERIPHERALS + { +- class CPeripheralJoystick : public CPeripheral, //! @todo extend CPeripheralHID ++ class CPeripheralJoystick : public CPeripheral, // TODO: extend CPeripheralHID + public JOYSTICK::IDriverHandler + { + public: +diff --git a/xbmc/peripherals/devices/PeripheralVideo.cpp b/xbmc/peripherals/devices/PeripheralVideo.cpp +new file mode 100644 +index 0000000..b2a433b +--- /dev/null ++++ b/xbmc/peripherals/devices/PeripheralVideo.cpp +@@ -0,0 +1,121 @@ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "PeripheralVideo.h" ++#include "utils/log.h" ++#include "utils/Screen.h" ++#include "guilib/GraphicContext.h" ++#include "dialogs/GUIDialogKaiToast.h" ++#include "guilib/LocalizeStrings.h" ++#include "settings/Settings.h" ++#include "xbmc/utils/SysfsUtils.h" ++#include "messaging/ApplicationMessenger.h" ++#include "Application.h" ++#include ++ ++using namespace PERIPHERALS; ++using namespace KODI::MESSAGING; ++ ++int CPeripheralVideo::m_cableState = 0; ++ ++CPeripheralVideo::CPeripheralVideo(const PeripheralScanResult& scanResult, CPeripheralBus* bus) ++ : CPeripheral(scanResult, bus) ++ , m_timer(this) ++{ ++ m_features.push_back(FEATURE_CABLESTATE); ++} ++ ++CPeripheralVideo::~CPeripheralVideo() ++{ ++} ++ ++void CPeripheralVideo::OnDeviceChanged(int state) ++{ ++ if (g_application.m_bStop) ++ return; ++ ++ if (!GetSettingBool("pass_events")) ++ return; ++ ++ CLog::Log(LOGDEBUG, "%s - state %s over %s, timer %s", __FUNCTION__, stateToStr(state), stateToStr(m_cableState), !m_timer.IsRunning() ? "will be started" : "is already running"); ++ ++ m_cableState = state; ++ ++ if (m_timer.IsRunning()) ++ m_timer.Restart(); ++ else ++ m_timer.Start(3000); ++} ++ ++bool CPeripheralVideo::IsQuantRangeLimited() ++{ ++#ifdef HAS_IMXVPU ++ std::string value; ++ std::string from = "/sys/devices/soc0/soc/20e0000.hdmi_video/rgb_quant_range"; ++ ++ std::ifstream file(from); ++ if (!file.is_open()) ++ { ++ from = "/sys/devices/soc0/soc.1/20e0000.hdmi_video/rgb_quant_range"; ++ } ++ file.close(); ++ ++ SysfsUtils::GetString(from, value); ++ if (value.find("limited") != std::string::npos) ++ return true; ++#endif ++ return false; ++} ++ ++void CPeripheralVideo::OnSettingChanged(const std::string &strChangedSetting) ++{ ++ bool configSet = false; ++ ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, "VIDEO", g_localizeStrings.Get(configSet ? 36023 : 36024)); ++} ++ ++bool CPeripheralVideo::InitialiseFeature(const PeripheralFeature feature) ++{ ++ return CPeripheral::InitialiseFeature(feature); ++} ++ ++void CPeripheralVideo::OnTimeout() ++{ ++ switch (m_cableState) ++ { ++ case CABLE_CONNECTED: ++ CSettings::GetInstance().SetBool("videoscreen.limitedrange", IsQuantRangeLimited()); ++ ++ if (CSettings::GetInstance().GetBool("videoscreen.updateresolutions")) ++ { ++ CApplicationMessenger::GetInstance().PostMsg(TMSG_DISPLAY_RECONFIGURE); ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, "VIDEO", g_localizeStrings.Get(13288)); ++ } ++ ++ g_screen.SetOn(); ++ ++ break; ++ case CABLE_DISCONNECTED: ++ g_screen.SetOff(); ++ ++ default: ++ ; ++ } ++} +diff --git a/xbmc/peripherals/devices/PeripheralVideo.h b/xbmc/peripherals/devices/PeripheralVideo.h +new file mode 100644 +index 0000000..bbbfcfd +--- /dev/null ++++ b/xbmc/peripherals/devices/PeripheralVideo.h +@@ -0,0 +1,62 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "Peripheral.h" ++#include "peripherals/Peripherals.h" ++#include "threads/Timer.h" ++ ++namespace PERIPHERALS ++{ ++ class CPeripheralVideo : public CPeripheral, protected ITimerCallback ++ { ++ public: ++ CPeripheralVideo(const PeripheralScanResult& scanResult, CPeripheralBus* bus); ++ virtual ~CPeripheralVideo(void); ++ ++ virtual void OnDeviceChanged(int state); ++ virtual void OnTimeout(); ++ ++ void OnSettingChanged(const std::string &strChangedSetting); ++ bool InitialiseFeature(const PeripheralFeature feature); ++ ++ static bool IsQuantRangeLimited(); ++ ++ static const char *stateToStr(const int state) ++ { ++ switch (state) ++ { ++ case CABLE_CONNECTED: ++ return "connected"; ++ case CABLE_DISCONNECTED: ++ return "disconnected"; ++ default: ++ return "unknown"; ++ } ++ } ++ ++ public: ++ static int m_cableState; ++ protected: ++ CTimer m_timer; ++ ++ }; ++} ++ +diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp +index 53aa157..96dfa37 100644 +--- a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp ++++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp +@@ -221,7 +221,7 @@ void CGUIDialogPeripheralSettings::InitializeSettings() + } + + default: +- //! @todo add more types if needed ++ // TODO: add more types if needed + CLog::Log(LOGDEBUG, "%s - unknown type", __FUNCTION__); + break; + } +diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp +index 2197079..f87eb70 100644 +--- a/xbmc/pictures/GUIWindowPictures.cpp ++++ b/xbmc/pictures/GUIWindowPictures.cpp +@@ -35,7 +35,6 @@ + #include "input/Key.h" + #include "dialogs/GUIDialogOK.h" + #include "view/GUIViewState.h" +-#include "PlayListPlayer.h" + #include "playlists/PlayList.h" + #include "settings/MediaSourceSettings.h" + #include "settings/Settings.h" +diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp +index e62255d..0f8face 100644 +--- a/xbmc/pictures/GUIWindowSlideShow.cpp ++++ b/xbmc/pictures/GUIWindowSlideShow.cpp +@@ -45,7 +45,6 @@ + #include "interfaces/AnnouncementManager.h" + #include "pictures/GUIViewStatePictures.h" + #include "pictures/PictureThumbLoader.h" +-#include "PlayListPlayer.h" + #ifdef TARGET_POSIX + #include "linux/XTimeUtils.h" + #endif +diff --git a/xbmc/pictures/SlideShowPicture.cpp b/xbmc/pictures/SlideShowPicture.cpp +index 7d77391..5ea4cfe 100644 +--- a/xbmc/pictures/SlideShowPicture.cpp ++++ b/xbmc/pictures/SlideShowPicture.cpp +@@ -460,7 +460,7 @@ void CSlideShowPic::Process(unsigned int currentTime, CDirtyRegionList &dirtyreg + float fScreenRatio = fScreenWidth / fScreenHeight * fPixelRatio; + // work out if we should be compensating the zoom to minimize blackbars + // we should compute this based on the % of black bars on screen perhaps?? +- //! @todo change m_displayEffect != EFFECT_NO_TIMEOUT to whether we're running the slideshow ++ // TODO: change m_displayEffect != EFFECT_NO_TIMEOUT to whether we're running the slideshow + if (m_displayEffect != EFFECT_NO_TIMEOUT && fScreenRatio < fSourceAR * fComp && fSourceAR < fScreenRatio * fComp) + bFillScreen = true; + if ((!bFillScreen && fScreenWidth*fPixelRatio > fScreenHeight*fSourceAR) || (bFillScreen && fScreenWidth*fPixelRatio < fScreenHeight*fSourceAR)) +diff --git a/xbmc/platform/darwin/ios-common/AnnounceReceiver.mm b/xbmc/platform/darwin/ios-common/AnnounceReceiver.mm +index 8ff14cc..5a278e8 100644 +--- a/xbmc/platform/darwin/ios-common/AnnounceReceiver.mm ++++ b/xbmc/platform/darwin/ios-common/AnnounceReceiver.mm +@@ -31,7 +31,6 @@ + #import "music/MusicDatabase.h" + #import "TextureCache.h" + #import "filesystem/SpecialProtocol.h" +-#include "PlayListPlayer.h" + #import "playlists/PlayList.h" + + #import "threads/Atomics.h" +diff --git a/xbmc/platform/darwin/ios/Info.plist.in b/xbmc/platform/darwin/ios/Info.plist.in +index 6c4443c..68dc31d 100644 +--- a/xbmc/platform/darwin/ios/Info.plist.in ++++ b/xbmc/platform/darwin/ios/Info.plist.in +@@ -51,6 +51,11 @@ + + iPhoneOS + ++ UISupportedInterfaceOrientations ++ ++ UIInterfaceOrientationLandscapeLeft ++ UIInterfaceOrientationLandscapeRight ++ + BuildMachineOSBuild + 15E65 + DTPlatformBuild +@@ -147,23 +152,5 @@ + iphoneos + DTCompiler + com.apple.compilers.llvm.clang.1_0 +- UIRequiresFullScreen +- +- UIRequiresPersistentWiFi +- YES +- UIStatusBarHidden +- +- UISupportedInterfaceOrientations +- +- UIInterfaceOrientationLandscapeLeft +- UIInterfaceOrientationLandscapeRight +- +- UISupportedInterfaceOrientations~ipad +- +- UIInterfaceOrientationLandscapeLeft +- UIInterfaceOrientationLandscapeRight +- +- UIViewControllerBasedStatusBarAppearance +- + + +diff --git a/xbmc/platform/darwin/ios/XBMCController.mm b/xbmc/platform/darwin/ios/XBMCController.mm +index b961052..59af2ac 100644 +--- a/xbmc/platform/darwin/ios/XBMCController.mm ++++ b/xbmc/platform/darwin/ios/XBMCController.mm +@@ -360,7 +360,7 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event + { +- if( m_glView && [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + UITouch *touch = (UITouch *)[[touches allObjects] objectAtIndex:0]; + CGPoint point = [touch locationInView:m_glView]; +@@ -372,7 +372,7 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + -(void)handlePinch:(UIPinchGestureRecognizer*)sender + { +- if( m_glView && [m_glView isXBMCAlive] && sender.numberOfTouches )//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + CGPoint point = [sender locationOfTouch:0 inView:m_glView]; + point.x *= screenScale; +@@ -398,7 +398,7 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + -(void)handleRotate:(UIRotationGestureRecognizer*)sender + { +- if( m_glView && [m_glView isXBMCAlive] && sender.numberOfTouches )//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + CGPoint point = [sender locationOfTouch:0 inView:m_glView]; + point.x *= screenScale; +@@ -423,11 +423,11 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + - (IBAction)handlePan:(UIPanGestureRecognizer *)sender + { +- if( m_glView && [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + CGPoint velocity = [sender velocityInView:m_glView]; + +- if( [sender state] == UIGestureRecognizerStateBegan && sender.numberOfTouches ) ++ if( [sender state] == UIGestureRecognizerStateBegan ) + { + CGPoint point = [sender locationOfTouch:0 inView:m_glView]; + point.x *= screenScale; +@@ -436,7 +436,7 @@ XBMCController *g_xbmcController; + lastGesturePoint = point; + } + +- if( [sender state] == UIGestureRecognizerStateChanged && sender.numberOfTouches ) ++ if( [sender state] == UIGestureRecognizerStateChanged ) + { + CGPoint point = [sender locationOfTouch:0 inView:m_glView]; + point.x *= screenScale; +@@ -484,7 +484,7 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + - (IBAction)handleSwipe:(UISwipeGestureRecognizer *)sender + { +- if( m_glView && [m_glView isXBMCAlive] && sender.numberOfTouches )//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + + +@@ -534,7 +534,7 @@ XBMCController *g_xbmcController; + //-------------------------------------------------------------- + - (IBAction)handleSingleFingerSingleLongTap:(UIGestureRecognizer *)sender + { +- if( m_glView && [m_glView isXBMCAlive] && sender.numberOfTouches)//NO GESTURES BEFORE WE ARE UP AND RUNNING ++ if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING + { + CGPoint point = [sender locationOfTouch:0 inView:m_glView]; + point.x *= screenScale; +@@ -567,8 +567,6 @@ XBMCController *g_xbmcController; + if ( !self ) + return ( nil ); + +- m_glView = NULL; +- + m_isPlayingBeforeInactive = NO; + m_bgTask = UIBackgroundTaskInvalid; + m_playbackState = IOS_PLAYBACK_STOPPED; +diff --git a/xbmc/platform/xbmc.cpp b/xbmc/platform/xbmc.cpp +index 0c7a4d1..19de6b8 100644 +--- a/xbmc/platform/xbmc.cpp ++++ b/xbmc/platform/xbmc.cpp +@@ -20,6 +20,9 @@ + + #include "Application.h" + #include "settings/AdvancedSettings.h" ++#include "stdlib.h" ++#include ++#include "utils/log.h" + + #ifdef TARGET_RASPBERRY_PI + #include "linux/RBP.h" +@@ -41,6 +44,14 @@ + extern "C" int XBMC_Run(bool renderGUI) + { + int status = -1; ++ bool showXBMCSplash = true; ++ std::string filename = "/usr/bin/splash"; ++ struct stat buf; ++ if (stat(filename.c_str(), &buf) != -1) ++ { ++ system("/usr/bin/splash --force -i -m 'starting kodi...'"); ++ showXBMCSplash = false; ++ } + + if (!g_advancedSettings.Initialized()) + { +@@ -78,7 +89,7 @@ extern "C" int XBMC_Run(bool renderGUI) + g_RBP.LogFirmwareVerison(); + #endif + +- if (renderGUI && !g_application.CreateGUI()) ++ if (renderGUI && !g_application.CreateGUI(showXBMCSplash)) + { + CMessagePrinter::DisplayError("ERROR: Unable to create GUI. Exiting"); + return status; +@@ -101,6 +112,9 @@ extern "C" int XBMC_Run(bool renderGUI) + } + #endif + ++ CLog::Log(LOGNOTICE, "XBian: notifying Upstart that i'm well"); ++ system("sudo /sbin/start -n -q xbmc-loaded"); ++ + try + { + status = g_application.Run(); +diff --git a/xbmc/playlists/PlayList.cpp b/xbmc/playlists/PlayList.cpp +index 6129f8d..0d2fb66 100644 +--- a/xbmc/playlists/PlayList.cpp ++++ b/xbmc/playlists/PlayList.cpp +@@ -25,7 +25,6 @@ + #include "music/tags/MusicInfoTag.h" + #include "filesystem/File.h" + #include "utils/log.h" +-#include "utils/Random.h" + #include "utils/URIUtils.h" + #include "utils/Variant.h" + #include "utils/StringUtils.h" +@@ -281,7 +280,7 @@ void CPlayList::Shuffle(int iPosition) + CLog::Log(LOGDEBUG,"%s shuffling at pos:%i", __FUNCTION__, iPosition); + + ivecItems it = m_vecItems.begin() + iPosition; +- KODI::UTILS::RandomShuffle(it, m_vecItems.end()); ++ std::random_shuffle(it, m_vecItems.end()); + + // the list is now shuffled! + m_bShuffled = true; +diff --git a/xbmc/playlists/PlayList.h b/xbmc/playlists/PlayList.h +index 1126992..20fb964 100644 +--- a/xbmc/playlists/PlayList.h ++++ b/xbmc/playlists/PlayList.h +@@ -22,7 +22,6 @@ + #include "FileItem.h" + #include + #include +-#include + + namespace PLAYLIST + { +diff --git a/xbmc/playlists/PlayListPLS.h b/xbmc/playlists/PlayListPLS.h +index eb9cb21..49769c4 100644 +--- a/xbmc/playlists/PlayListPLS.h ++++ b/xbmc/playlists/PlayListPLS.h +@@ -18,10 +18,6 @@ + * . + * + */ +- +-#include +-#include +- + #include "PlayList.h" + + namespace PLAYLIST +diff --git a/xbmc/playlists/SmartPlayList.cpp b/xbmc/playlists/SmartPlayList.cpp +index 26dc5d1..500d234 100644 +--- a/xbmc/playlists/SmartPlayList.cpp ++++ b/xbmc/playlists/SmartPlayList.cpp +@@ -26,7 +26,6 @@ + + #include "SmartPlayList.h" + #include "Util.h" +-#include "dbwrappers/Database.h" + #include "filesystem/File.h" + #include "filesystem/SmartPlaylistDirectory.h" + #include "guilib/LocalizeStrings.h" +@@ -34,12 +33,12 @@ + #include "utils/JSONVariantParser.h" + #include "utils/JSONVariantWriter.h" + #include "utils/log.h" +-#include "utils/StreamDetails.h" + #include "utils/StringUtils.h" + #include "utils/StringValidation.h" + #include "utils/URIUtils.h" + #include "utils/Variant.h" + #include "utils/XMLUtils.h" ++#include "video/VideoDatabase.h" + + using namespace XFILE; + +@@ -346,7 +345,6 @@ std::vector CSmartPlaylistRule::GetFields(const std::string &type) + fields.push_back(FieldDisbanded); + fields.push_back(FieldDied); + fields.push_back(FieldRole); +- fields.push_back(FieldPath); + } + else if (type == "tvshows") + { +@@ -736,7 +734,7 @@ CDatabaseQueryRule::SEARCH_OPERATOR CSmartPlaylistRule::GetOperator(const std::s + SEARCH_OPERATOR op = CDatabaseQueryRule::GetOperator(strType); + if ((strType == "tvshows" || strType == "episodes") && m_field == FieldYear) + { // special case for premiered which is a date rather than a year +- //! @todo SMARTPLAYLISTS do we really need this, or should we just make this field the premiered date and request a date? ++ // TODO: SMARTPLAYLISTS do we really need this, or should we just make this field the premiered date and request a date? + if (op == OPERATOR_EQUALS) + op = OPERATOR_CONTAINS; + else if (op == OPERATOR_DOES_NOT_EQUAL) +@@ -808,15 +806,10 @@ std::string CSmartPlaylistRule::FormatWhereClause(const std::string &negate, con + query += " OR "; + query += "EXISTS (SELECT DISTINCT album_artist.idArtist FROM album_artist, album_genre, genre WHERE album_artist.idArtist = " + GetField(FieldId, strType) + " AND album_artist.idAlbum = album_genre.idAlbum AND album_genre.idGenre = genre.idGenre AND genre.strGenre" + parameter + "))"; + } +- else if (m_field == FieldRole) ++ if (m_field == FieldRole) + { + query = negate + " (EXISTS (SELECT DISTINCT song_artist.idArtist FROM song_artist, role WHERE song_artist.idArtist = " + GetField(FieldId, strType) + " AND song_artist.idRole = role.idRole AND role.strRole" + parameter + "))"; + } +- else if (m_field == FieldPath) +- { +- query = negate + " (EXISTS (SELECT DISTINCT song_artist.idArtist FROM song_artist JOIN song ON song.idSong = song_artist.idSong JOIN path ON song.idpath = path.idpath "; +- query += "WHERE song_artist.idArtist = " + GetField(FieldId, strType) + " AND path.strPath" + parameter + "))"; +- } + } + else if (strType == "movies") + { +diff --git a/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp b/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp +index 4e5bcc6..0212306 100644 +--- a/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp ++++ b/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp +@@ -50,11 +50,15 @@ CLogindUPowerSyscall::CLogindUPowerSyscall() + if (!m_hasUPower) + CLog::Log(LOGINFO, "LogindUPowerSyscall - UPower not found, battery information will not be available"); + +- m_canPowerdown = LogindCheckCapability("CanPowerOff"); +- m_canReboot = LogindCheckCapability("CanReboot"); ++ m_canPowerdown = true; ++ m_canReboot = true; ++#if defined(HAS_IMXVPU) || defined(TARGET_RASPBERRY_PI) ++ m_canHibernate = false; ++ m_canSuspend = false; ++#else + m_canHibernate = LogindCheckCapability("CanHibernate"); + m_canSuspend = LogindCheckCapability("CanSuspend"); +- ++#endif + InhibitDelayLock(); + + m_batteryLevel = 0; +diff --git a/xbmc/powermanagement/linux/UPowerSyscall.cpp b/xbmc/powermanagement/linux/UPowerSyscall.cpp +index e3b4725..20175e7 100644 +--- a/xbmc/powermanagement/linux/UPowerSyscall.cpp ++++ b/xbmc/powermanagement/linux/UPowerSyscall.cpp +@@ -62,9 +62,12 @@ CUPowerSyscall::CUPowerSyscall() + + m_lowBattery = false; + ++ m_CanPowerdown = true; ++ m_CanReboot = true; ++ + dbus_error_init (&m_error); +- //! @todo do not use dbus_connection_pop_message() that requires the use of a +- //! private connection ++ // TODO: do not use dbus_connection_pop_message() that requires the use of a ++ // private connection + m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_error); + + if (m_connection) +@@ -83,9 +86,6 @@ CUPowerSyscall::CUPowerSyscall() + m_connection = NULL; + } + +- m_CanPowerdown = false; +- m_CanReboot = false; +- + UpdateCapabilities(); + + EnumeratePowerSources(); +@@ -262,8 +262,13 @@ bool CUPowerSyscall::PumpPowerEvents(IPowerEventsCallback *callback) + + void CUPowerSyscall::UpdateCapabilities() + { ++#if defined(HAS_IMXVPU) || defined(TARGET_RASPBERRY_PI) ++ m_CanSuspend = false; ++ m_CanHibernate = false; ++#else + m_CanSuspend = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanSuspend").asBoolean(false); + m_CanHibernate = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanHibernate").asBoolean(false); ++#endif + } + + #endif +diff --git a/xbmc/powermanagement/osx/CocoaPowerSyscall.cpp b/xbmc/powermanagement/osx/CocoaPowerSyscall.cpp +index db03d1e..a22449b 100644 +--- a/xbmc/powermanagement/osx/CocoaPowerSyscall.cpp ++++ b/xbmc/powermanagement/osx/CocoaPowerSyscall.cpp +@@ -341,12 +341,12 @@ void CCocoaPowerSyscall::OSPowerCallBack(void *refcon, io_service_t service, nat + IOAllowPowerChange(ctx->m_root_port, (long)msg_arg); + //CLog::Log(LOGDEBUG, "%s - kIOMessageSystemWillSleep", __FUNCTION__); + // let XBMC know system will sleep +- //! @todo implement ++ // TODO: + break; + case kIOMessageSystemHasPoweredOn: + // System has awakened from sleep. + // let XBMC know system has woke +- //! @todo implement ++ // TODO: + ctx->m_OnResume = true; + //CLog::Log(LOGDEBUG, "%s - kIOMessageSystemHasPoweredOn", __FUNCTION__); + break; +diff --git a/xbmc/profiles/ProfilesManager.cpp b/xbmc/profiles/ProfilesManager.cpp +index 54f6b8c..86db51a 100644 +--- a/xbmc/profiles/ProfilesManager.cpp ++++ b/xbmc/profiles/ProfilesManager.cpp +@@ -53,10 +53,10 @@ + #include "utils/Variant.h" + #include "utils/XMLUtils.h" + +-//! @todo +-//! eventually the profile should dictate where special://masterprofile/ is +-//! but for now it makes sense to leave all the profile settings in a user +-//! writeable location like special://masterprofile/ ++// TODO ++// eventually the profile should dictate where special://masterprofile/ is ++// but for now it makes sense to leave all the profile settings in a user ++// writeable location like special://masterprofile/ + #define PROFILES_FILE "special://masterprofile/profiles.xml" + + #define XML_PROFILES "profiles" +diff --git a/xbmc/programs/GUIWindowPrograms.h b/xbmc/programs/GUIWindowPrograms.h +index 1398e19..759774e 100644 +--- a/xbmc/programs/GUIWindowPrograms.h ++++ b/xbmc/programs/GUIWindowPrograms.h +@@ -30,16 +30,16 @@ class CGUIWindowPrograms : + public: + CGUIWindowPrograms(void); + virtual ~CGUIWindowPrograms(void); +- virtual bool OnMessage(CGUIMessage& message) override; ++ virtual bool OnMessage(CGUIMessage& message); + virtual void OnItemInfo(int iItem); + protected: +- virtual void OnItemLoaded(CFileItem* pItem) override {}; +- virtual bool Update(const std::string& strDirectory, bool updateFilterPath = true) override; ++ virtual void OnItemLoaded(CFileItem* pItem) {}; ++ virtual bool Update(const std::string& strDirectory, bool updateFilterPath = true); + virtual bool OnPlayMedia(int iItem); +- virtual void GetContextButtons(int itemNumber, CContextButtons &buttons) override; +- virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override; ++ virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); ++ virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + bool OnAddMediaSource() override; +- virtual std::string GetStartFolder(const std::string &dir) override; ++ virtual std::string GetStartFolder(const std::string &dir); + + CGUIDialogProgress* m_dlgProgress; + +diff --git a/xbmc/pvr/PVRActionListener.cpp b/xbmc/pvr/PVRActionListener.cpp +index d8e29a1..ff5a312 100644 +--- a/xbmc/pvr/PVRActionListener.cpp ++++ b/xbmc/pvr/PVRActionListener.cpp +@@ -111,7 +111,7 @@ bool CPVRActionListener::OnAction(const CAction &action) + CFileItemPtr fileItem = group->GetLastPlayedChannel(playingChannel->ChannelID()); + if (fileItem && fileItem->HasPVRChannelInfoTag()) + { +- CLog::Log(LOGDEBUG, "%s - switch to channel number %d", __FUNCTION__, fileItem->GetPVRChannelInfoTag()->ChannelNumber()); ++ CLog::Log(LOGPVR, "%s - switch to channel number %d", __FUNCTION__, fileItem->GetPVRChannelInfoTag()->ChannelNumber()); + CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1,static_cast( + new CAction(ACTION_CHANNEL_SWITCH, static_cast(fileItem->GetPVRChannelInfoTag()->ChannelNumber())))); + } +diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp +index 9d350cd..bb04c06 100644 +--- a/xbmc/pvr/PVRDatabase.cpp ++++ b/xbmc/pvr/PVRDatabase.cpp +@@ -47,7 +47,7 @@ void CPVRDatabase::CreateTables() + { + CLog::Log(LOGINFO, "PVR - %s - creating tables", __FUNCTION__); + +- CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channels'", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVR - %s - creating table 'channels'", __FUNCTION__); + m_pDS->exec( + "CREATE TABLE channels (" + "idChannel integer primary key, " +@@ -64,14 +64,14 @@ void CPVRDatabase::CreateTables() + "sEPGScraper varchar(32), " + "iLastWatched integer," + +- //! @todo use mapping table ++ // TODO use mapping table + "iClientId integer, " + + "idEpg integer" + ")" + ); + +- CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channelgroups'", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVR - %s - creating table 'channelgroups'", __FUNCTION__); + m_pDS->exec( + "CREATE TABLE channelgroups (" + "idGroup integer primary key," +@@ -84,7 +84,7 @@ void CPVRDatabase::CreateTables() + ")" + ); + +- CLog::Log(LOGDEBUG, "PVR - %s - creating table 'map_channelgroups_channels'", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVR - %s - creating table 'map_channelgroups_channels'", __FUNCTION__); + m_pDS->exec( + "CREATE TABLE map_channelgroups_channels (" + "idChannel integer, " +@@ -150,17 +150,34 @@ void CPVRDatabase::UpdateTables(int iVersion) + + bool CPVRDatabase::DeleteChannels(void) + { +- CLog::Log(LOGDEBUG, "PVR - %s - deleting all channels from the database", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVR - %s - deleting all channels from the database", __FUNCTION__); + return DeleteValues("channels"); + } + ++bool CPVRDatabase::DeleteClientChannels(const CPVRClient &client) ++{ ++ /* invalid client Id */ ++ if (client.GetID() <= 0) ++ { ++ CLog::Log(LOGERROR, "PVR - %s - invalid client id: %i", __FUNCTION__, client.GetID()); ++ return false; ++ } ++ ++ CLog::Log(LOGPVR, "PVR - %s - deleting all channels from client '%i' from the database", __FUNCTION__, client.GetID()); ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("iClientId = %u", client.GetID())); ++ ++ return DeleteValues("channels", filter); ++} ++ + bool CPVRDatabase::Delete(const CPVRChannel &channel) + { + /* invalid channel */ + if (channel.ChannelID() <= 0) + return false; + +- CLog::Log(LOGDEBUG, "PVR - %s - deleting channel '%s' from the database", __FUNCTION__, channel.ChannelName().c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - deleting channel '%s' from the database", __FUNCTION__, channel.ChannelName().c_str()); + + Filter filter; + filter.AppendWhere(PrepareSQL("idChannel = %u", channel.ChannelID())); +@@ -207,7 +224,7 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results) + channel->UpdateEncryptionName(); + + #if PVRDB_DEBUGGING +- CLog::Log(LOGDEBUG, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str()); + #endif + PVRChannelGroupMember newMember = { channel, (unsigned int)m_pDS->fv("iChannelNumber").get_asInt() }; + results.m_sortedMembers.push_back(newMember); +@@ -278,6 +295,21 @@ bool CPVRDatabase::GetCurrentGroupMembers(const CPVRChannelGroup &group, std::ve + return bReturn; + } + ++bool CPVRDatabase::DeleteChannelsFromGroup(const CPVRChannelGroup &group) ++{ ++ /* invalid group id */ ++ if (group.GroupID() <= 0) ++ { ++ CLog::Log(LOGERROR, "PVR - %s - invalid group id: %d", __FUNCTION__, group.GroupID()); ++ return false; ++ } ++ ++ Filter filter; ++ filter.AppendWhere(PrepareSQL("idGroup = %u", group.GroupID())); ++ ++ return DeleteValues("map_channelgroups_channels", filter); ++} ++ + bool CPVRDatabase::DeleteChannelsFromGroup(const CPVRChannelGroup &group, const std::vector &channelsToDelete) + { + bool bDelete(true); +@@ -371,7 +403,7 @@ bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group) + + bool CPVRDatabase::DeleteChannelGroups(void) + { +- CLog::Log(LOGDEBUG, "PVR - %s - deleting all channel groups from the database", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVR - %s - deleting all channel groups from the database", __FUNCTION__); + + return DeleteValues("channelgroups") && + DeleteValues("map_channelgroups_channels"); +@@ -412,7 +444,7 @@ bool CPVRDatabase::Get(CPVRChannelGroups &results) + data.SetPosition(m_pDS->fv("iPosition").get_asInt()); + results.Update(data); + +- CLog::Log(LOGDEBUG, "PVR - %s - group '%s' loaded from the database", __FUNCTION__, data.GroupName().c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - group '%s' loaded from the database", __FUNCTION__, data.GroupName().c_str()); + m_pDS->next(); + } + m_pDS->close(); +@@ -454,7 +486,7 @@ int CPVRDatabase::Get(CPVRChannelGroup &group) + if (channel) + { + #if PVRDB_DEBUGGING +- CLog::Log(LOGDEBUG, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str()); ++ CLog::Log(LOGPVR, "PVR - %s - channel '%s' loaded from the database", __FUNCTION__, channel->m_strChannelName.c_str()); + #endif + PVRChannelGroupMember newMember = { channel, (unsigned int)iChannelNumber }; + group.m_sortedMembers.push_back(newMember); +diff --git a/xbmc/pvr/PVRDatabase.h b/xbmc/pvr/PVRDatabase.h +index e64d82b..4aa8c0b 100644 +--- a/xbmc/pvr/PVRDatabase.h ++++ b/xbmc/pvr/PVRDatabase.h +@@ -19,8 +19,6 @@ + * + */ + +-#include +- + #include "dbwrappers/Database.h" + #include "utils/log.h" + +@@ -76,6 +74,13 @@ namespace PVR + bool DeleteChannels(void); + + /*! ++ * @brief Remove all channels from a client from the database. ++ * @param client The client to delete the channels for. ++ * @return True if the channels were deleted, false otherwise. ++ */ ++ bool DeleteClientChannels(const CPVRClient &client); ++ ++ /*! + * @brief Add or update a channel entry in the database + * @param channel The channel to persist. + * @return True when persisted or queued, false otherwise. +@@ -168,6 +173,7 @@ namespace PVR + void CreateTables(); + void CreateAnalytics(); + ++ bool DeleteChannelsFromGroup(const CPVRChannelGroup &group); + bool DeleteChannelsFromGroup(const CPVRChannelGroup &group, const std::vector &channelsToDelete); + + bool GetCurrentGroupMembers(const CPVRChannelGroup &group, std::vector &members); +diff --git a/xbmc/pvr/PVRGUIInfo.h b/xbmc/pvr/PVRGUIInfo.h +index a5529fc..6245dc8 100644 +--- a/xbmc/pvr/PVRGUIInfo.h ++++ b/xbmc/pvr/PVRGUIInfo.h +@@ -27,8 +27,6 @@ + #include "utils/Observer.h" + + #include +-#include +-#include + + namespace EPG + { +diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp +index 295e639..2e12a1c 100644 +--- a/xbmc/pvr/PVRManager.cpp ++++ b/xbmc/pvr/PVRManager.cpp +@@ -29,7 +29,6 @@ + #include "dialogs/GUIDialogNumeric.h" + #include "dialogs/GUIDialogOK.h" + #include "dialogs/GUIDialogProgress.h" +-#include "dialogs/GUIDialogSelect.h" + #include "epg/EpgContainer.h" + #include "GUIInfoManager.h" + #include "guilib/GUIWindowManager.h" +@@ -39,7 +38,6 @@ + #include "messaging/helpers/DialogHelper.h" + #include "music/tags/MusicInfoTag.h" + #include "network/Network.h" +-#include "PlayListPlayer.h" + #include "pvr/addons/PVRClients.h" + #include "pvr/channels/PVRChannel.h" + #include "pvr/channels/PVRChannelGroupInternal.h" +@@ -66,6 +64,7 @@ + #include "utils/Variant.h" + #include "video/VideoDatabase.h" + #include "ServiceBroker.h" ++#include "settings/AdvancedSettings.h" + + using namespace MUSIC_INFO; + using namespace PVR; +@@ -111,7 +110,7 @@ CPVRManager::~CPVRManager(void) + CAnnouncementManager::GetInstance().RemoveAnnouncer(this); + Stop(); + m_addons.reset(); +- CLog::Log(LOGDEBUG,"PVRManager - destroyed"); ++ CLog::Log(LOGPVR,"PVRManager - destroyed"); + } + + void CPVRManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) +@@ -235,6 +234,16 @@ void CPVRManager::OnSettingAction(const CSetting *setting) + } + } + ++bool CPVRManager::IsPVRWindowActive(void) const ++{ ++ return (IsPVRWindow(g_windowManager.GetActiveWindow() & WINDOW_ID_MASK)) ? true : false; ++} ++ ++bool CPVRManager::IsPVRWindow(int windowId) ++{ ++ return (windowId >= WINDOW_PVR_ID_START && windowId <= WINDOW_PVR_ID_END) ? true : false; ++} ++ + void CPVRManager::Cleanup(void) + { + CSingleLock lock(m_critSection); +@@ -401,7 +410,7 @@ void CPVRManager::Process(void) + g_EpgContainer.Start(true); + + /* main loop */ +- CLog::Log(LOGDEBUG, "PVRManager - %s - entering main loop", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVRManager - %s - entering main loop", __FUNCTION__); + + bool bRestart(false); + while (IsStarted() && m_addons->HasCreatedClients() && !bRestart) +@@ -492,7 +501,7 @@ bool CPVRManager::Load(bool bShowProgress) + if (!IsInitialising() || !m_addons->HasCreatedClients()) + return false; + +- CLog::Log(LOGDEBUG, "PVRManager - %s - active clients found. continue to start", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVRManager - %s - active clients found. continue to start", __FUNCTION__); + + /* reset observer for pvr windows */ + for (std::size_t i = 0; i != ARRAY_SIZE(m_pvrWindowIds); i++) +@@ -613,7 +622,7 @@ bool CPVRManager::ContinueLastChannel(void) + return true; + } + +- CLog::Log(LOGDEBUG, "PVRManager - %s - no last played channel to continue playback found", __FUNCTION__); ++ CLog::Log(LOGPVR, "PVRManager - %s - no last played channel to continue playback found", __FUNCTION__); + + return false; + } +@@ -736,7 +745,7 @@ int CPVRManager::GetCurrentEpg(CFileItemList &results) const + if (channel) + iReturn = channel->GetEPG(results); + else +- CLog::Log(LOGDEBUG,"PVRManager - %s - no current channel set", __FUNCTION__); ++ CLog::Log(LOGPVR,"PVRManager - %s - no current channel set", __FUNCTION__); + + return iReturn; + } +@@ -750,245 +759,45 @@ void CPVRManager::ResetPlayingTag(void) + + bool CPVRManager::ToggleRecordingOnChannel(unsigned int iChannelId) + { +- const CPVRChannelPtr channel(m_channelGroups->GetChannelById(iChannelId)); +- if (!channel) +- return false; +- +- return SetRecordingOnChannel(channel, !channel->IsRecording()); +-} +- +-void CPVRManager::StartRecordingOnPlayingChannel(bool bOnOff) +-{ +- // can be called from VideoPlayer thread. SetRecordingOnChannel can open a dialog. Thus, execute async. +- CJobManager::GetInstance().AddJob(new CPVRSetRecordingOnChannelJob(m_addons->GetPlayingChannel(), bOnOff), NULL); +-} +- +-namespace +-{ +-enum PVRRECORD_INSTANTRECORDACTION +-{ +- NONE = -1, +- RECORD_CURRENT_SHOW = 0, +- RECORD_INSTANTRECORDTIME = 1, +- ASK = 2, +- RECORD_30_MINUTES = 3, +- RECORD_60_MINUTES = 4, +- RECORD_120_MINUTES = 5, +- RECORD_NEXT_SHOW = 6 +-}; +- +-class InstantRecordingActionSelector +-{ +-public: +- InstantRecordingActionSelector(); +- virtual ~InstantRecordingActionSelector() {} +- +- void AddAction(PVRRECORD_INSTANTRECORDACTION eAction, const std::string &title); +- void PreSelectAction(PVRRECORD_INSTANTRECORDACTION eAction); +- PVRRECORD_INSTANTRECORDACTION Select(); +- +-private: +- CGUIDialogSelect *m_pDlgSelect; // not owner! +- std::map m_actions; +-}; ++ bool bReturn = false; + +-InstantRecordingActionSelector::InstantRecordingActionSelector() +-: m_pDlgSelect(dynamic_cast(g_windowManager.GetWindow(WINDOW_DIALOG_SELECT))) +-{ +- if (m_pDlgSelect) +- { +- m_pDlgSelect->SetMultiSelection(false); +- m_pDlgSelect->SetHeading(CVariant{19086}); // Instant recording action +- } +- else +- { +- CLog::Log(LOGERROR, "InstantRecordingActionSelector - %s - unable to obtain WINDOW_DIALOG_SELECT instance", __FUNCTION__); +- } +-} ++ CPVRChannelPtr channel(m_channelGroups->GetChannelById(iChannelId)); ++ if (!channel) ++ return bReturn; + +-void InstantRecordingActionSelector::AddAction(PVRRECORD_INSTANTRECORDACTION eAction, const std::string &title) +-{ +- if (m_actions.find(eAction) == m_actions.end()) ++ if (m_addons->HasTimerSupport(channel->ClientID())) + { +- switch (eAction) ++ /* timers are supported on this channel */ ++ if (!channel->IsRecording()) + { +- case RECORD_INSTANTRECORDTIME: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19090).c_str(), +- CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME))); // Record next minutes +- break; +- case RECORD_30_MINUTES: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19090).c_str(), 30)); // Record next 30 minutes +- break; +- case RECORD_60_MINUTES: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19090).c_str(), 60)); // Record next 60 minutes +- break; +- case RECORD_120_MINUTES: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19090).c_str(), 120)); // Record next 120 minutes +- break; +- case RECORD_CURRENT_SHOW: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19091).c_str(), title.c_str())); // Record current show () +- break; +- case RECORD_NEXT_SHOW: +- m_pDlgSelect->Add(StringUtils::Format(g_localizeStrings.Get(19092).c_str(), title.c_str())); // Record next show (<title>) +- break; +- case NONE: +- case ASK: +- default: +- return; ++ bReturn = m_timers->InstantTimer(channel); ++ if (!bReturn) ++ CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19164}); + } +- +- m_actions.insert(std::make_pair(eAction, m_actions.size())); +- } +-} +- +-void InstantRecordingActionSelector::PreSelectAction(PVRRECORD_INSTANTRECORDACTION eAction) +-{ +- const auto &it = m_actions.find(eAction); +- if (it != m_actions.end()) +- m_pDlgSelect->SetSelected(it->second); +-} +- +-PVRRECORD_INSTANTRECORDACTION InstantRecordingActionSelector::Select() +-{ +- PVRRECORD_INSTANTRECORDACTION eAction = NONE; +- +- m_pDlgSelect->Open(); +- +- if (m_pDlgSelect->IsConfirmed()) +- { +- int iSelection = m_pDlgSelect->GetSelectedItem(); +- for (const auto &action : m_actions) ++ else + { +- if (action.second == iSelection) +- { +- eAction = action.first; +- break; +- } ++ /* delete active timers */ ++ bReturn = m_timers->DeleteTimersOnChannel(channel, true, true); + } + } + +- return eAction; ++ return bReturn; + } + +-} // unnamed namespace +- +-bool CPVRManager::SetRecordingOnChannel(const CPVRChannelPtr &channel, bool bOnOff) ++bool CPVRManager::StartRecordingOnPlayingChannel(bool bOnOff) + { + bool bReturn = false; + ++ CPVRChannelPtr channel(m_addons->GetPlayingChannel()); + if (!channel) + return bReturn; + +- if (!g_PVRManager.CheckParentalLock(channel)) +- return bReturn; +- + if (m_addons->HasTimerSupport(channel->ClientID())) + { + /* timers are supported on this channel */ + if (bOnOff && !channel->IsRecording()) + { +- CEpgInfoTagPtr epgTag; +- int iDuration = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME); +- +- int iAction = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDACTION); +- switch (iAction) +- { +- case RECORD_CURRENT_SHOW: +- epgTag = channel->GetEPGNow(); +- break; +- +- case RECORD_INSTANTRECORDTIME: +- epgTag.reset(); +- break; +- +- case ASK: +- { +- PVRRECORD_INSTANTRECORDACTION ePreselect = RECORD_INSTANTRECORDTIME; +- InstantRecordingActionSelector selector; +- CEpgInfoTagPtr epgTagNext; +- +- // fixed length recordings +- selector.AddAction(RECORD_30_MINUTES, ""); +- selector.AddAction(RECORD_60_MINUTES, ""); +- selector.AddAction(RECORD_120_MINUTES, ""); +- +- const int iDurationDefault = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME); +- if (iDurationDefault != 30 && iDurationDefault != 60 && iDurationDefault != 120) +- selector.AddAction(RECORD_INSTANTRECORDTIME, ""); +- +- // epg-based recordings +- epgTag = channel->GetEPGNow(); +- if (epgTag) +- { +- // "now" +- selector.AddAction(RECORD_CURRENT_SHOW, epgTag->Title()); +- ePreselect = RECORD_CURRENT_SHOW; +- +- // "next" +- epgTagNext = channel->GetEPGNext(); +- if (epgTagNext) +- { +- selector.AddAction(RECORD_NEXT_SHOW, epgTagNext->Title()); +- +- // be smart. if current show is almost over, preselect next show. +- if (epgTag->ProgressPercentage() > 90.0f) +- ePreselect = RECORD_NEXT_SHOW; +- } +- } +- +- selector.PreSelectAction(ePreselect); +- +- PVRRECORD_INSTANTRECORDACTION eSelected = selector.Select(); +- switch (eSelected) +- { +- case NONE: +- return false; // dialog canceled +- +- case RECORD_30_MINUTES: +- iDuration = 30; +- epgTag.reset(); +- break; +- +- case RECORD_60_MINUTES: +- iDuration = 60; +- epgTag.reset(); +- break; +- +- case RECORD_120_MINUTES: +- iDuration = 120; +- epgTag.reset(); +- break; +- +- case RECORD_INSTANTRECORDTIME: +- iDuration = iDurationDefault; +- epgTag.reset(); +- break; +- +- case RECORD_CURRENT_SHOW: +- break; +- +- case RECORD_NEXT_SHOW: +- epgTag = epgTagNext; +- break; +- +- default: +- CLog::Log(LOGERROR, "PVRManager - %s - unknown instant record action selection (%d), defaulting to fixed length recording.", __FUNCTION__, eSelected); +- epgTag.reset(); +- break; +- } +- break; +- } +- +- default: +- CLog::Log(LOGERROR, "PVRManager - %s - unknown instant record action setting value (%d), defaulting to fixed length recording.", __FUNCTION__, iAction); +- break; +- } +- +- const CPVRTimerInfoTagPtr newTimer(epgTag ? CPVRTimerInfoTag::CreateFromEpg(epgTag, false) : CPVRTimerInfoTag::CreateInstantTimerTag(channel, iDuration)); +- +- if (newTimer) +- bReturn = newTimer->AddToClient(); +- ++ bReturn = m_timers->InstantTimer(channel); + if (!bReturn) + CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19164}); + } +@@ -1123,7 +932,7 @@ bool CPVRManager::OpenLiveStream(const CFileItem &fileItem) + if (!fileItem.HasPVRChannelInfoTag()) + return bReturn; + +- CLog::Log(LOGDEBUG,"PVRManager - %s - opening live stream on channel '%s'", ++ CLog::Log(LOGPVR,"PVRManager - %s - opening live stream on channel '%s'", + __FUNCTION__, fileItem.GetPVRChannelInfoTag()->ChannelName().c_str()); + + // check if we're allowed to play this file +@@ -1401,7 +1210,7 @@ bool CPVRManager::PerformChannelSwitch(const CPVRChannelPtr &channel, bool bPrev + CSingleLock lock(m_critSection); + if (m_bIsSwitchingChannels) + { +- CLog::Log(LOGDEBUG, "PVRManager - %s - can't switch to channel '%s'. waiting for the previous switch to complete", ++ CLog::Log(LOGPVR, "PVRManager - %s - can't switch to channel '%s'. waiting for the previous switch to complete", + __FUNCTION__, channel->ChannelName().c_str()); + return false; + } +@@ -1417,7 +1226,7 @@ bool CPVRManager::PerformChannelSwitch(const CPVRChannelPtr &channel, bool bPrev + m_bIsSwitchingChannels = true; + } + +- CLog::Log(LOGDEBUG, "PVRManager - %s - switching to channel '%s'", __FUNCTION__, channel->ChannelName().c_str()); ++ CLog::Log(LOGPVR, "PVRManager - %s - switching to channel '%s'", __FUNCTION__, channel->ChannelName().c_str()); + + // will be deleted by CPVRChannelSwitchJob::DoWork() + CFileItem* previousFile = m_currentFile; +@@ -1496,11 +1305,29 @@ int CPVRManager::TranslateIntInfo(DWORD dwInfo) const + return IsStarted() && m_guiInfo ? m_guiInfo->TranslateIntInfo(dwInfo) : 0; + } + ++bool CPVRManager::HasTimers(void) const ++{ ++ return IsStarted() && m_timers ? m_timers->HasActiveTimers() : false; ++} ++ + bool CPVRManager::IsRecording(void) const + { + return IsStarted() && m_timers ? m_timers->IsRecording() : false; + } + ++bool CPVRManager::IsIdle(void) const ++{ ++ bool bReturn(true); ++ if (IsStarted()) ++ { ++ if (IsRecording() || IsPlaying()) // pvr recording or playing? ++ bReturn = false; ++ else ++ bReturn = !IsNextEventWithinBackendIdleTime(); ++ } ++ return bReturn; ++} ++ + bool CPVRManager::CanSystemPowerdown(bool bAskUser /*= true*/) const + { + bool bReturn(true); +@@ -1827,12 +1654,6 @@ bool CPVRClientConnectionJob::DoWork(void) + return true; + } + +-bool CPVRSetRecordingOnChannelJob::DoWork(void) +-{ +- g_PVRManager.SetRecordingOnChannel(m_channel, m_bOnOff); +- return true; +-} +- + bool CPVRManager::CreateChannelEpgs(void) + { + if (EpgsCreated()) +diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h +index 5d7b809..8c46733 100644 +--- a/xbmc/pvr/PVRManager.h ++++ b/xbmc/pvr/PVRManager.h +@@ -32,7 +32,6 @@ + + #include <map> + #include <memory> +-#include <vector> + + class CGUIDialogProgressBarHandle; + class CStopWatch; +@@ -173,6 +172,16 @@ private: + void Cleanup(void); + + /*! ++ * @return True when a PVR window is active, false otherwise. ++ */ ++ bool IsPVRWindowActive(void) const; ++ ++ /*! ++ * @return True when the given window id is an PVR window, false otherwise. ++ */ ++ static bool IsPVRWindow(int windowId); ++ ++ /*! + * @brief Get the TV database. + * @return The TV database. + */ +@@ -241,6 +250,7 @@ private: + return GetState() == ManagerStateStarted; + } + ++ + /*! + * @brief Check whether the PVRManager is stopping + * @return True while the PVRManager is stopping. +@@ -332,16 +342,15 @@ private: + /*! + * @brief Start or stop recording on the channel that is currently being played. + * @param bOnOff True to start recording, false to stop. ++ * @return True if the recording was started or stopped successfully, false otherwise. + */ +- void StartRecordingOnPlayingChannel(bool bOnOff); ++ bool StartRecordingOnPlayingChannel(bool bOnOff); + + /*! +- * @brief Start or stop recording on a given channel. +- * @param channel the channel to start/stop recording. +- * @param bOnOff True to start recording, false to stop. +- * @return True if the recording was started or stopped successfully, false otherwise. ++ * @brief Check whether there are active timers. ++ * @return True if there are active timers, false otherwise. + */ +- bool SetRecordingOnChannel(const CPVRChannelPtr &channel, bool bOnOff); ++ bool HasTimers(void) const; + + /*! + * @brief Check whether there are active recordings. +@@ -350,6 +359,12 @@ private: + bool IsRecording(void) const; + + /*! ++ * @brief Check whether the pvr backend is idle. ++ * @return True if there are no active timers/recordings/wake-ups within the configured time span. ++ */ ++ bool IsIdle(void) const; ++ ++ /*! + * @brief Check whether the system Kodi is running on can be powered down + * (shutdown/reboot/suspend/hibernate) without stopping any active + * recordings and/or without preventing the start of recordings +@@ -543,6 +558,12 @@ private: + void OnWake(); + + /*! ++ * @brief Wait until the pvr manager is loaded ++ * @return True when loaded, false otherwise ++ */ ++ bool WaitUntilInitialised(void); ++ ++ /*! + * @brief Create EPG tags for all channels in internal channel groups + * @return True if EPG tags where created successfully, false otherwise + */ +@@ -755,18 +776,4 @@ private: + PVR_CONNECTION_STATE m_state; + std::string m_message; + }; +- +- class CPVRSetRecordingOnChannelJob : public CJob +- { +- public: +- CPVRSetRecordingOnChannelJob(const CPVRChannelPtr &channel, bool bOnOff) : +- m_channel(channel), m_bOnOff(bOnOff) {} +- virtual ~CPVRSetRecordingOnChannelJob() {} +- virtual const char *GetType() const { return "pvr-set-recording-on-channel"; } +- +- bool DoWork(); +- private: +- CPVRChannelPtr m_channel; +- bool m_bOnOff; +- }; + } +diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp +index 63aa3a2..66b062f 100644 +--- a/xbmc/pvr/addons/PVRClients.cpp ++++ b/xbmc/pvr/addons/PVRClients.cpp +@@ -68,6 +68,16 @@ CPVRClients::~CPVRClients(void) + Unload(); + } + ++bool CPVRClients::IsInUse(const std::string& strAddonId) const ++{ ++ CSingleLock lock(m_critSection); ++ ++ for (const auto &client : m_clientMap) ++ if (!CAddonMgr::GetInstance().IsAddonDisabled(client.second->ID()) && client.second->ID() == strAddonId) ++ return true; ++ return false; ++} ++ + void CPVRClients::Start(void) + { + CAddonMgr::GetInstance().RegisterAddonMgrCallback(ADDON_PVRDLL, this); +@@ -378,7 +388,7 @@ bool CPVRClients::SwitchChannel(const CPVRChannelPtr &channel) + CSingleLock lock(m_critSection); + if (m_bIsSwitchingChannels) + { +- CLog::Log(LOGDEBUG, "PVRClients - %s - can't switch to channel '%s'. waiting for the previous switch to complete", __FUNCTION__, channel->ChannelName().c_str()); ++ CLog::Log(LOGPVR, "PVRClients - %s - can't switch to channel '%s'. waiting for the previous switch to complete", __FUNCTION__, channel->ChannelName().c_str()); + return false; + } + m_bIsSwitchingChannels = true; +@@ -878,6 +888,23 @@ bool CPVRClients::HasMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat) + client->HaveMenuHooks(cat)); + } + ++bool CPVRClients::GetMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, PVR_MENUHOOKS *hooks) ++{ ++ bool bReturn(false); ++ ++ if (iClientID < 0) ++ iClientID = GetPlayingClientID(); ++ ++ PVR_CLIENT client; ++ if (GetCreatedClient(iClientID, client) && client->HaveMenuHooks(cat)) ++ { ++ *hooks = *(client->GetMenuHooks()); ++ bReturn = true; ++ } ++ ++ return bReturn; ++} ++ + void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CFileItem *item) + { + // get client id +@@ -1375,6 +1402,14 @@ int64_t CPVRClients::SeekStream(int64_t iFilePosition, int iWhence/* = SEEK_SET* + return -EINVAL; + } + ++int64_t CPVRClients::GetStreamPosition(void) ++{ ++ PVR_CLIENT client; ++ if (GetPlayingClient(client)) ++ return client->GetStreamPosition(); ++ return -EINVAL; ++} ++ + void CPVRClients::PauseStream(bool bPaused) + { + PVR_CLIENT client; +@@ -1420,6 +1455,12 @@ bool CPVRClients::IsPlayingRecording(void) const + return m_bIsPlayingRecording; + } + ++bool CPVRClients::IsReadingLiveStream(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bIsPlayingLiveTV; ++} ++ + bool CPVRClients::IsEncrypted(void) const + { + PVR_CLIENT client; +diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h +index d5ee5bc..8e9e07f 100644 +--- a/xbmc/pvr/addons/PVRClients.h ++++ b/xbmc/pvr/addons/PVRClients.h +@@ -70,6 +70,13 @@ namespace PVR + virtual ~CPVRClients(void); + + /*! ++ * @brief Checks whether an add-on is loaded by the pvr manager ++ * @param strAddonId The add-on id to check ++ * @return True when in use, false otherwise ++ */ ++ bool IsInUse(const std::string& strAddonId) const; ++ ++ /*! + * @brief Start the backend. + */ + void Start(void); +@@ -223,6 +230,12 @@ namespace PVR + int64_t SeekStream(int64_t iFilePosition, int iWhence = SEEK_SET); + + /*! ++ * @brief Get the currently playing position in a stream. ++ * @return The current position. ++ */ ++ int64_t GetStreamPosition(void); ++ ++ /*! + * @brief Close a PVR stream. + */ + void CloseStream(void); +@@ -249,6 +262,11 @@ namespace PVR + std::string GetCurrentInputFormat(void) const; + + /*! ++ * @return True if a live stream is playing, false otherwise. ++ */ ++ bool IsReadingLiveStream(void) const; ++ ++ /*! + * @return True if a TV channel is playing, false otherwise. + */ + bool IsPlayingTV(void) const; +@@ -677,6 +695,14 @@ namespace PVR + void UpdateAddons(void); + + /*! ++ * @brief Get the menu hooks for a client. ++ * @param iClientID The client to get the hooks for. ++ * @param hooks The container to add the hooks to. ++ * @return True if the hooks were added successfully (if any), false otherwise. ++ */ ++ bool GetMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, PVR_MENUHOOKS *hooks); ++ ++ /*! + * @brief Get the instance of the client. + * @param iClientId The id of the client to get. + * @param addon The client. +diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp +index 136b02e..6994260 100644 +--- a/xbmc/pvr/channels/PVRChannel.cpp ++++ b/xbmc/pvr/channels/PVRChannel.cpp +@@ -545,7 +545,7 @@ int CPVRChannel::GetEPG(CFileItemList &results) const + CEpgPtr epg = GetEPG(); + if (!epg) + { +- CLog::Log(LOGDEBUG, "PVR - %s - cannot get EPG for channel '%s'", ++ CLog::Log(LOGPVR, "PVR - %s - cannot get EPG for channel '%s'", + __FUNCTION__, m_strChannelName.c_str()); + return -1; + } +@@ -675,6 +675,11 @@ bool CPVRChannel::IsSubChannel(void) const + return SubChannelNumber() > 0; + } + ++bool CPVRChannel::IsClientSubChannel(void) const ++{ ++ return ClientSubChannelNumber() > 0; ++} ++ + std::string CPVRChannel::FormattedChannelNumber(void) const + { + return !IsSubChannel() ? +diff --git a/xbmc/pvr/channels/PVRChannel.h b/xbmc/pvr/channels/PVRChannel.h +index 54e5a7f..adc3f18 100644 +--- a/xbmc/pvr/channels/PVRChannel.h ++++ b/xbmc/pvr/channels/PVRChannel.h +@@ -149,6 +149,11 @@ namespace PVR + */ + std::string FormattedChannelNumber(void) const; + ++ /** ++ * @return True when this channel is marked as sub channel by the add-on, false if it's marked as main channel ++ */ ++ bool IsClientSubChannel(void) const; ++ + /*! + * @brief Set to true to hide this channel. Set to false to unhide it. + * +@@ -359,6 +364,7 @@ namespace PVR + */ + bool IsEncrypted(void) const; + ++ + /*! + * @brief Return the encryption system ID for this channel. 0 for FTA. + * +diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp +index c1201fb..73fabd2 100644 +--- a/xbmc/pvr/channels/PVRChannelGroup.cpp ++++ b/xbmc/pvr/channels/PVRChannelGroup.cpp +@@ -18,7 +18,10 @@ + * + */ + +-//! @todo use Observable here, so we can use event driven operations later ++/** ++ * TODO: ++ * - use Observable here, so we can use event driven operations later ++ */ + + #include "PVRChannelGroup.h" + #include "PVRChannelGroupsContainer.h" +@@ -136,6 +139,11 @@ bool CPVRChannelGroup::operator!=(const CPVRChannelGroup &right) const + + PVRChannelGroupMember CPVRChannelGroup::EmptyMember = { CPVRChannelPtr(), 0, 0 }; + ++std::pair<int, int> CPVRChannelGroup::PathIdToStorageId(uint64_t storageId) ++{ ++ return std::make_pair(storageId >> 32, storageId & 0xFFFFFFFF); ++} ++ + void CPVRChannelGroup::OnInit(void) + { + CSettings::GetInstance().RegisterCallback(this, { +@@ -153,7 +161,7 @@ bool CPVRChannelGroup::Load(void) + m_bUsingBackendChannelNumbers = CSettings::GetInstance().GetBool(CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERS); + + int iChannelCount = m_iGroupId > 0 ? LoadFromDb() : 0; +- CLog::Log(LOGDEBUG, "PVRChannelGroup - %s - %d channels loaded from the database for group '%s'", ++ CLog::Log(LOGPVR, "PVRChannelGroup - %s - %d channels loaded from the database for group '%s'", + __FUNCTION__, iChannelCount, m_strGroupName.c_str()); + + if (!Update()) +@@ -164,7 +172,7 @@ bool CPVRChannelGroup::Load(void) + + if (Size() - iChannelCount > 0) + { +- CLog::Log(LOGDEBUG, "PVRChannelGroup - %s - %d channels added from clients to group '%s'", ++ CLog::Log(LOGPVR, "PVRChannelGroup - %s - %d channels added from clients to group '%s'", + __FUNCTION__, static_cast<int>(Size() - iChannelCount), m_strGroupName.c_str()); + } + +@@ -333,7 +341,7 @@ void CPVRChannelGroup::SearchAndSetChannelIcons(bool bUpdateDb /* = false */) + if (bUpdateDb) + channel->Persist(); + +- //! @todo start channel icon scraper here if nothing was found ++ /* TODO: start channel icon scraper here if nothing was found */ + } + + if (dlgProgressHandle) +@@ -730,6 +738,51 @@ bool CPVRChannelGroup::UpdateGroupEntries(const CPVRChannelGroup &channels) + return bReturn; + } + ++void CPVRChannelGroup::RemoveInvalidChannels(void) ++{ ++ CPVRChannelPtr channel; ++ CSingleLock lock(m_critSection); ++ for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end();) ++ { ++ bool bDelete = false; ++ channel = (*it).channel; ++ ++ if (channel->ClientChannelNumber() <= 0) ++ { ++ CLog::Log(LOGERROR, "PVRChannelGroup - %s - removing invalid channel '%s' from client '%i': no valid client channel number", ++ __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); ++ bDelete = true; ++ } ++ ++ if (!bDelete && channel->UniqueID() <= 0) ++ { ++ CLog::Log(LOGERROR, "PVRChannelGroup - %s - removing invalid channel '%s' from client '%i': no valid unique ID", ++ __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID()); ++ bDelete = true; ++ } ++ ++ /* remove this channel from all non-system groups if this is the internal group */ ++ if (bDelete) ++ { ++ if (IsInternalGroup()) ++ { ++ g_PVRChannelGroups->Get(m_bRadio)->RemoveFromAllGroups(channel); ++ channel->Delete(); ++ } ++ else ++ { ++ m_members.erase(channel->StorageId()); ++ it = m_sortedMembers.erase(it); ++ } ++ m_bChanged = true; ++ } ++ else ++ { ++ ++it; ++ } ++ } ++} ++ + bool CPVRChannelGroup::RemoveFromGroup(const CPVRChannelPtr &channel) + { + bool bReturn(false); +@@ -739,7 +792,7 @@ bool CPVRChannelGroup::RemoveFromGroup(const CPVRChannelPtr &channel) + { + if (*channel == *((*it).channel)) + { +- //! @todo notify observers ++ // TODO notify observers + m_members.erase((*it).channel->StorageId()); + it = m_sortedMembers.erase(it); + bReturn = true; +@@ -784,7 +837,7 @@ bool CPVRChannelGroup::AddToGroup(const CPVRChannelPtr &channel, int iChannelNum + + SortAndRenumber(); + +- //! @todo notify observers ++ // TODO notify observers + bReturn = true; + } + } +@@ -846,7 +899,7 @@ bool CPVRChannelGroup::Persist(void) + + if (CPVRDatabase *database = GetPVRDatabase()) + { +- CLog::Log(LOGDEBUG, "CPVRChannelGroup - %s - persisting channel group '%s' with %d channels", ++ CLog::Log(LOGPVR, "CPVRChannelGroup - %s - persisting channel group '%s' with %d channels", + __FUNCTION__, GroupName().c_str(), (int) m_members.size()); + m_bChanged = false; + lock.Leave(); +@@ -957,7 +1010,7 @@ void CPVRChannelGroup::OnSettingChanged(const CSetting *setting) + if (setting == NULL) + return; + +- //! @todo while pvr manager is starting up do accept setting changes. ++ /* TODO: while pvr manager is starting up do accept setting changes. */ + if(!g_PVRManager.IsStarted()) + { + CLog::Log(LOGWARNING, "CPVRChannelGroup setting change ignored while PVRManager is starting\n"); +@@ -980,7 +1033,7 @@ void CPVRChannelGroup::OnSettingChanged(const CSetting *setting) + /* check whether this channel group has to be renumbered */ + if (bChannelOrderChanged || bChannelNumbersChanged) + { +- CLog::Log(LOGDEBUG, "CPVRChannelGroup - %s - renumbering group '%s' to use the backend channel order and/or numbers", ++ CLog::Log(LOGPVR, "CPVRChannelGroup - %s - renumbering group '%s' to use the backend channel order and/or numbers", + __FUNCTION__, m_strGroupName.c_str()); + SortAndRenumber(); + Persist(); +@@ -993,6 +1046,28 @@ bool CPVRPersistGroupJob::DoWork(void) + return m_group->Persist(); + } + ++int CPVRChannelGroup::GetEPGSearch(CFileItemList &results, const EpgSearchFilter &filter) ++{ ++ int iInitialSize = results.Size(); ++ ++ /* get filtered results from all tables */ ++ g_EpgContainer.GetEPGSearch(results, filter); ++ ++ /* remove duplicate entries */ ++ if (filter.m_bPreventRepeats) ++ EpgSearchFilter::RemoveDuplicates(results); ++ ++ /* filter recordings */ ++ if (filter.m_bIgnorePresentRecordings) ++ EpgSearchFilter::FilterRecordings(results); ++ ++ /* filter timers */ ++ if (filter.m_bIgnorePresentTimers) ++ EpgSearchFilter::FilterTimers(results); ++ ++ return results.Size() - iInitialSize; ++} ++ + int CPVRChannelGroup::GetEPGNowOrNext(CFileItemList &results, bool bGetNext) const + { + int iInitialSize = results.Size(); +@@ -1182,7 +1257,7 @@ bool CPVRChannelGroup::UpdateChannel(const CFileItem &item, bool bHidden, bool b + if (iEPGSource == 0) + member.channel->SetEPGScraper("client"); + +- //! @todo add other scrapers ++ // TODO add other scrapers + member.channel->SetEPGEnabled(bEPGEnabled); + + /* set new values in the channel tag */ +@@ -1211,12 +1286,36 @@ bool CPVRChannelGroup::HasChannels() const + return !m_members.empty(); + } + ++bool CPVRChannelGroup::ToggleChannelLocked(const CFileItem &item) ++{ ++ if (!item.HasPVRChannelInfoTag()) ++ return false; ++ ++ CSingleLock lock(m_critSection); ++ ++ /* get the real channel from the group */ ++ const PVRChannelGroupMember& member(GetByUniqueID(item.GetPVRChannelInfoTag()->StorageId())); ++ if (member.channel) ++ { ++ member.channel->SetLocked(!member.channel->IsLocked()); ++ return true; ++ } ++ ++ return false; ++} ++ + void CPVRChannelGroup::SetSelectedGroup(bool bSetTo) + { + CSingleLock lock(m_critSection); + m_bSelectedGroup = bSetTo; + } + ++bool CPVRChannelGroup::IsSelectedGroup(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bSelectedGroup; ++} ++ + bool CPVRChannelGroup::CreateChannelEpgs(bool bForce /* = false */) + { + /* used only by internal channel groups */ +diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h +index dd2ede5..30594bc 100644 +--- a/xbmc/pvr/channels/PVRChannelGroup.h ++++ b/xbmc/pvr/channels/PVRChannelGroup.h +@@ -25,7 +25,6 @@ + + #include <memory> + #include <utility> +-#include <vector> + + class CDateTime; + class CFileItem; +@@ -110,6 +109,13 @@ namespace PVR + static PVRChannelGroupMember EmptyMember; + + /*! ++ * Translate an id used in the path to a client id + unique channel id pair ++ * @param pathId Id in the path to translate ++ * @return The requested pair ++ */ ++ static std::pair<int, int> PathIdToStorageId(uint64_t pathId); ++ ++ /*! + * @return The amount of group members + */ + size_t Size(void) const; +@@ -379,6 +385,14 @@ namespace PVR + void OnJobComplete(unsigned int jobID, bool success, CJob* job) override {} + + /*! ++ * @brief Get all EPG tables and apply a filter. ++ * @param results The fileitem list to store the results in. ++ * @param filter The filter to apply. ++ * @return The amount of entries that were added. ++ */ ++ int GetEPGSearch(CFileItemList &results, const EPG::EpgSearchFilter &filter); ++ ++ /*! + * @brief Get all EPG tables. + * @param results The fileitem list to store the results in. + * @param bIncludeChannelsWithoutEPG, for channels without EPG data, put an empty EPG tag associated with the channel into results +@@ -414,6 +428,8 @@ namespace PVR + + bool UpdateChannel(const CFileItem &channel, bool bHidden, bool bEPGEnabled, bool bParentalLocked, int iEPGSource, int iChannelNumber, const std::string &strChannelName, const std::string &strIconPath, const std::string &strStreamURL, bool bUserSetIcon = false); + ++ bool ToggleChannelLocked(const CFileItem &channel); ++ + /*! + * @brief Get a channel given the channel number on the client. + * @param iUniqueChannelId The unique channel id on the client. +@@ -424,6 +440,7 @@ namespace PVR + const PVRChannelGroupMember& GetByUniqueID(const std::pair<int, int>& id) const; + + void SetSelectedGroup(bool bSetTo); ++ bool IsSelectedGroup(void) const; + + void SetHidden(bool bHidden); + bool IsHidden(void) const; +@@ -467,6 +484,11 @@ namespace PVR + virtual bool CreateChannelEpgs(bool bForce = false); + + /*! ++ * @brief Remove invalid channels from this container. ++ */ ++ void RemoveInvalidChannels(void); ++ ++ /*! + * @brief Load the channels from the database. + * @return True when loaded successfully, false otherwise. + */ +diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp +index 06e23a2..ceeac57 100644 +--- a/xbmc/pvr/channels/PVRChannelGroups.cpp ++++ b/xbmc/pvr/channels/PVRChannelGroups.cpp +@@ -231,6 +231,42 @@ bool CPVRChannelGroups::Update(bool bChannelsOnly /* = false */) + return PersistAll() && bReturn; + } + ++bool CPVRChannelGroups::UpdateGroupsEntries(const CPVRChannelGroups &groups) ++{ ++ CSingleLock lock(m_critSection); ++ ++ // go through groups list and check for deleted groups ++ for (int iGroupPtr = m_groups.size() - 1; iGroupPtr > 0; iGroupPtr--) ++ { ++ CPVRChannelGroup existingGroup(*m_groups.at(iGroupPtr)); ++ CPVRChannelGroupPtr group = groups.GetByName(existingGroup.GroupName()); ++ // user defined group wasn't found ++ if (existingGroup.GroupType() == PVR_GROUP_TYPE_DEFAULT && !group) ++ { ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - user defined group %s with id '%u' does not exist on the client anymore; deleting it", __FUNCTION__, existingGroup.GroupName().c_str(), existingGroup.GroupID()); ++ DeleteGroup(*m_groups.at(iGroupPtr)); ++ } ++ } ++ ++ // go through the groups list and check for new groups ++ for (std::vector<CPVRChannelGroupPtr>::const_iterator it = groups.m_groups.begin(); it != groups.m_groups.end(); ++it) ++ { ++ // check if this group is present in this container ++ CPVRChannelGroupPtr existingGroup = GetByName((*it)->GroupName()); ++ ++ // add it if not ++ if (!existingGroup) ++ { ++ CPVRChannelGroupPtr newGroup(CPVRChannelGroupPtr(new CPVRChannelGroup())); ++ newGroup->SetRadio(m_bRadio); ++ newGroup->SetGroupName((*it)->GroupName()); ++ m_groups.push_back(newGroup); ++ } ++ } ++ ++ return true; ++} ++ + bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) + { + bool bSyncWithBackends = CSettings::GetInstance().GetBool(CSettings::SETTING_PVRMANAGER_SYNCCHANNELGROUPS); +@@ -242,10 +278,10 @@ bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) + if (bSyncWithBackends) + { + GetGroupsFromClients(); +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - %" PRIuS" new user defined %s channel groups fetched from clients", __FUNCTION__, (m_groups.size() - iSize), m_bRadio ? "radio" : "TV"); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - %" PRIuS" new user defined %s channel groups fetched from clients", __FUNCTION__, (m_groups.size() - iSize), m_bRadio ? "radio" : "TV"); + } + else +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - 'synchannelgroups' is disabled; skipping groups from clients", __FUNCTION__); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - 'synchannelgroups' is disabled; skipping groups from clients", __FUNCTION__); + + std::vector<CPVRChannelGroupPtr> emptyGroups; + +@@ -257,7 +293,7 @@ bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) + { + if (!(*it)->Load()) + { +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - failed to load channel group '%s'", __FUNCTION__, (*it)->GroupName().c_str()); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - failed to load channel group '%s'", __FUNCTION__, (*it)->GroupName().c_str()); + return false; + } + +@@ -269,7 +305,7 @@ bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) + + for (std::vector<CPVRChannelGroupPtr>::iterator it = emptyGroups.begin(); it != emptyGroups.end(); ++it) + { +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - deleting empty group '%s'", __FUNCTION__, (*it)->GroupName().c_str()); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - deleting empty group '%s'", __FUNCTION__, (*it)->GroupName().c_str()); + DeleteGroup(*(*it)); + } + +@@ -288,7 +324,7 @@ bool CPVRChannelGroups::Load(void) + // remove previous contents + Clear(); + +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - loading all %s channel groups", __FUNCTION__, m_bRadio ? "radio" : "TV"); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - loading all %s channel groups", __FUNCTION__, m_bRadio ? "radio" : "TV"); + + // create the internal channel group + CPVRChannelGroupPtr internalGroup = CPVRChannelGroupPtr(new CPVRChannelGroupInternal(m_bRadio)); +@@ -296,7 +332,7 @@ bool CPVRChannelGroups::Load(void) + + // load groups from the database + database->Get(*this); +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - %" PRIuS" %s groups fetched from the database", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - %" PRIuS" %s groups fetched from the database", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); + + // load channels of internal group + if (!internalGroup->Load()) +@@ -316,7 +352,7 @@ bool CPVRChannelGroups::Load(void) + CPVRChannelGroupPtr lastPlayedGroup = GetLastPlayedGroup(); + SetSelectedGroup(lastPlayedGroup ? lastPlayedGroup : internalGroup); + +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - %" PRIuS" %s channel groups loaded", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - %" PRIuS" %s channel groups loaded", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); + + // need at least 1 group + return m_groups.size() > 0; +@@ -325,7 +361,7 @@ bool CPVRChannelGroups::Load(void) + bool CPVRChannelGroups::PersistAll(void) + { + bool bReturn(true); +- CLog::Log(LOGDEBUG, "CPVRChannelGroups - %s - persisting all changes in channel groups", __FUNCTION__); ++ CLog::Log(LOGPVR, "CPVRChannelGroups - %s - persisting all changes in channel groups", __FUNCTION__); + + CSingleLock lock(m_critSection); + for (std::vector<CPVRChannelGroupPtr>::iterator it = m_groups.begin(); it != m_groups.end(); ++it) +diff --git a/xbmc/pvr/channels/PVRChannelGroups.h b/xbmc/pvr/channels/PVRChannelGroups.h +index ca9567c..de20b7a 100644 +--- a/xbmc/pvr/channels/PVRChannelGroups.h ++++ b/xbmc/pvr/channels/PVRChannelGroups.h +@@ -214,6 +214,7 @@ namespace PVR + bool Update(bool bChannelsOnly = false); + + private: ++ bool UpdateGroupsEntries(const CPVRChannelGroups &groups); + bool LoadUserDefinedChannelGroups(void); + bool GetGroupsFromClients(void); + void SortGroups(void); +diff --git a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp +index 6b87392..36b17a8 100644 +--- a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp ++++ b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp +@@ -54,7 +54,7 @@ bool CPVRChannelGroupsContainer::Update(bool bChannelsOnly /* = false */) + m_bUpdateChannelsOnly = bChannelsOnly; + lock.Leave(); + +- CLog::Log(LOGDEBUG, "CPVRChannelGroupsContainer - %s - updating %s", __FUNCTION__, bChannelsOnly ? "channels" : "channel groups"); ++ CLog::Log(LOGPVR, "CPVRChannelGroupsContainer - %s - updating %s", __FUNCTION__, bChannelsOnly ? "channels" : "channel groups"); + bool bReturn = m_groupsRadio->Update(bChannelsOnly) && + m_groupsTV->Update(bChannelsOnly); + +@@ -203,6 +203,11 @@ bool CPVRChannelGroupsContainer::GetDirectory(const std::string& strPath, CFileI + return false; + } + ++int CPVRChannelGroupsContainer::GetNumChannelsFromAll() const ++{ ++ return GetGroupAllTV()->Size() + GetGroupAllRadio()->Size(); ++} ++ + CPVRChannelGroupPtr CPVRChannelGroupsContainer::GetSelectedGroup(bool bRadio) const + { + return Get(bRadio)->GetSelectedGroup(); +diff --git a/xbmc/pvr/channels/PVRChannelGroupsContainer.h b/xbmc/pvr/channels/PVRChannelGroupsContainer.h +index e155ad4..1c497c2 100644 +--- a/xbmc/pvr/channels/PVRChannelGroupsContainer.h ++++ b/xbmc/pvr/channels/PVRChannelGroupsContainer.h +@@ -141,6 +141,12 @@ namespace PVR + bool GetDirectory(const std::string& strPath, CFileItemList &results) const; + + /*! ++ * @brief The total amount of unique channels in all containers. ++ * @return The total amount of unique channels in all containers. ++ */ ++ int GetNumChannelsFromAll(void) const; ++ ++ /*! + * @brief Get the group that is currently selected in the UI. + * @param bRadio True to get the selected radio group, false to get the selected TV group. + * @return The selected group. +diff --git a/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp b/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp +index d810ff4..c5abf89 100644 +--- a/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp ++++ b/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp +@@ -221,6 +221,11 @@ void CPVRRadioRDSInfoTag::SetSpeechActive(bool active) + m_RDS_SpeechActive = active; + } + ++bool CPVRRadioRDSInfoTag::IsSpeechActive() ++{ ++ return m_RDS_SpeechActive; ++} ++ + void CPVRRadioRDSInfoTag::SetLanguage(const std::string& strLanguage) + { + m_strLanguage = Trim(strLanguage); +@@ -347,6 +352,16 @@ void CPVRRadioRDSInfoTag::SetInfoNews(const std::string& strNews) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoNews() ++{ ++ m_strInfoNews.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoNewsDeque() const ++{ ++ return m_strInfoNews; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoNews() const + { + std::string retStr = ""; +@@ -381,6 +396,16 @@ void CPVRRadioRDSInfoTag::SetInfoNewsLocal(const std::string& strNews) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoNewsLocal() ++{ ++ m_strInfoNewsLocal.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoNewsLocalDeque() const ++{ ++ return m_strInfoNewsLocal; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoNewsLocal() const + { + std::string retStr = ""; +@@ -415,6 +440,16 @@ void CPVRRadioRDSInfoTag::SetInfoSport(const std::string& strSport) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoSport() ++{ ++ m_strInfoSport.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoSportDeque() const ++{ ++ return m_strInfoSport; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoSport() const + { + std::string retStr = ""; +@@ -449,6 +484,16 @@ void CPVRRadioRDSInfoTag::SetInfoStock(const std::string& strStock) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoStock() ++{ ++ m_strInfoStock.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoStockDeque() const ++{ ++ return m_strInfoStock; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoStock() const + { + std::string retStr = ""; +@@ -482,6 +527,16 @@ void CPVRRadioRDSInfoTag::SetInfoWeather(const std::string& strWeather) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoWeather() ++{ ++ m_strInfoWeather.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoWeatherDeque() const ++{ ++ return m_strInfoWeather; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoWeather() const + { + std::string retStr = ""; +@@ -515,6 +570,16 @@ void CPVRRadioRDSInfoTag::SetInfoLottery(const std::string& strLottery) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoLottery() ++{ ++ m_strInfoLottery.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoLotteryDeque() const ++{ ++ return m_strInfoLottery; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoLottery() const + { + std::string retStr = ""; +@@ -548,6 +613,16 @@ void CPVRRadioRDSInfoTag::SetEditorialStaff(const std::string& strEditorialStaff + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearEditorialStaff() ++{ ++ m_strEditorialStaff.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetEditorialStaffDeque() const ++{ ++ return m_strEditorialStaff; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetEditorialStaff() const + { + std::string retStr = ""; +@@ -581,6 +656,16 @@ void CPVRRadioRDSInfoTag::SetInfoHoroscope(const std::string& strHoroscope) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoHoroscope() ++{ ++ m_strInfoHoroscope.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoHoroscopeDeque() const ++{ ++ return m_strInfoHoroscope; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoHoroscope() const + { + std::string retStr = ""; +@@ -614,6 +699,16 @@ void CPVRRadioRDSInfoTag::SetInfoCinema(const std::string& strCinema) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoCinema() ++{ ++ m_strInfoCinema.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoCinemaDeque() const ++{ ++ return m_strInfoCinema; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoCinema() const + { + std::string retStr = ""; +@@ -647,6 +742,16 @@ void CPVRRadioRDSInfoTag::SetInfoOther(const std::string& strOther) + g_windowManager.SendThreadMessage(msg); + } + ++void CPVRRadioRDSInfoTag::ClearInfoOther() ++{ ++ m_strInfoOther.clear(); ++} ++ ++const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoOtherDeque() const ++{ ++ return m_strInfoOther; ++} ++ + const std::string CPVRRadioRDSInfoTag::GetInfoOther() const + { + std::string retStr = ""; +diff --git a/xbmc/pvr/channels/PVRRadioRDSInfoTag.h b/xbmc/pvr/channels/PVRRadioRDSInfoTag.h +index 17bffda..be45546 100644 +--- a/xbmc/pvr/channels/PVRRadioRDSInfoTag.h ++++ b/xbmc/pvr/channels/PVRRadioRDSInfoTag.h +@@ -76,6 +76,7 @@ public: + + /**! Basic RDS related information */ + void SetSpeechActive(bool active); ++ bool IsSpeechActive(); + void SetLanguage(const std::string& strLanguage); + const std::string& GetLanguage() const; + void SetCountry(const std::string& strCountry); +@@ -125,34 +126,54 @@ public: + const std::string& GetSMSStudio() const; + + void SetInfoNews(const std::string& strNews); ++ void ClearInfoNews(); + const std::string GetInfoNews() const; ++ const std::deque<std::string>& GetInfoNewsDeque() const; + + void SetInfoNewsLocal(const std::string& strNews); ++ void ClearInfoNewsLocal(); + const std::string GetInfoNewsLocal() const; ++ const std::deque<std::string>& GetInfoNewsLocalDeque() const; + + void SetInfoSport(const std::string& strSport); ++ void ClearInfoSport(); + const std::string GetInfoSport() const; ++ const std::deque<std::string>& GetInfoSportDeque() const; + + void SetInfoStock(const std::string& strSport); ++ void ClearInfoStock(); + const std::string GetInfoStock() const; ++ const std::deque<std::string>& GetInfoStockDeque() const; + + void SetInfoWeather(const std::string& strWeather); ++ void ClearInfoWeather(); + const std::string GetInfoWeather() const; ++ const std::deque<std::string>& GetInfoWeatherDeque() const; + + void SetInfoHoroscope(const std::string& strHoroscope); ++ void ClearInfoHoroscope(); + const std::string GetInfoHoroscope() const; ++ const std::deque<std::string>& GetInfoHoroscopeDeque() const; + + void SetInfoCinema(const std::string& strCinema); ++ void ClearInfoCinema(); + const std::string GetInfoCinema() const; ++ const std::deque<std::string>& GetInfoCinemaDeque() const; + + void SetInfoLottery(const std::string& strLottery); ++ void ClearInfoLottery(); + const std::string GetInfoLottery() const; ++ const std::deque<std::string>& GetInfoLotteryDeque() const; + + void SetInfoOther(const std::string& strOther); ++ void ClearInfoOther(); + const std::string GetInfoOther() const; ++ const std::deque<std::string>& GetInfoOtherDeque() const; + + void SetEditorialStaff(const std::string& strEditorialStaff); ++ void ClearEditorialStaff(); + const std::string GetEditorialStaff() const; ++ const std::deque<std::string>& GetEditorialStaffDeque() const; + + void SetRadioStyle(const std::string& style) { m_strRadioStyle = style; } + const std::string GetRadioStyle() const { return m_strRadioStyle; } +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +index eb69c41..9b8b470 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +@@ -409,7 +409,7 @@ bool CGUIDialogPVRChannelManager::OnClickButtonUseEPG(CGUIMessage &message) + + bool CGUIDialogPVRChannelManager::OnClickEPGSourceSpin(CGUIMessage &message) + { +- //! @todo Add EPG scraper support ++ // TODO: Add EPG scraper support + return true; + // CGUISpinControlEx *pSpin = (CGUISpinControlEx *)GetControl(SPIN_EPGSOURCE_SELECTION); + // if (pSpin) +@@ -694,7 +694,7 @@ void CGUIDialogPVRChannelManager::Update() + { + std::vector< std::pair<std::string, int> > labels; + labels.push_back(std::make_pair(g_localizeStrings.Get(19210), 0)); +- //! @todo Add Labels for EPG scrapers here ++ /// TODO: Add Labels for EPG scrapers here + SET_CONTROL_LABELS(SPIN_EPGSOURCE_SELECTION, 0, &labels); + } + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.h b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.h +index c84246f..9b9584b 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.h ++++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.h +@@ -19,8 +19,6 @@ + * + */ + +-#include <vector> +- + #include "dialogs/GUIDialogContextMenu.h" + #include "guilib/GUIDialog.h" + #include "view/GUIViewControl.h" +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp +index 30f7a73..533dfa8 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp +@@ -74,7 +74,7 @@ bool CGUIDialogPVRGroupManager::PersistChanges(void) + + bool CGUIDialogPVRGroupManager::CancelChanges(void) + { +- //! @todo ++ // TODO + return false; + } + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.h b/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.h +index 2cfbfe4..e44ee8a 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.h ++++ b/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.h +@@ -37,15 +37,15 @@ namespace PVR + public: + CGUIDialogPVRGuideInfo(void); + virtual ~CGUIDialogPVRGuideInfo(void); +- virtual bool OnMessage(CGUIMessage& message) override; ++ virtual bool OnMessage(CGUIMessage& message); + virtual bool OnInfo(int actionID) override; +- virtual bool HasListItems() const override { return true; }; +- virtual CFileItemPtr GetCurrentListItem(int offset = 0) override; ++ virtual bool HasListItems() const { return true; }; ++ virtual CFileItemPtr GetCurrentListItem(int offset = 0); + + void SetProgInfo(const EPG::CEpgInfoTagPtr &tag); + + protected: +- virtual void OnInitWindow() override; ++ virtual void OnInitWindow(); + + bool ActionStartTimer(const EPG::CEpgInfoTagPtr &tag); + bool ActionCancelTimer(const CFileItemPtr &timer); +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp +index ade193f..c83d8c1 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp +@@ -415,6 +415,11 @@ void CGUIDialogPVRRadioRDSInfo::OnDeinitWindow(int nextWindowID) + CGUIDialog::OnDeinitWindow(nextWindowID); + } + ++void CGUIDialogPVRRadioRDSInfo::SetRadioRDS(const CFileItem *item) ++{ ++ *m_rdsItem = *item; ++} ++ + CFileItemPtr CGUIDialogPVRRadioRDSInfo::GetCurrentListItem(int offset) + { + return m_rdsItem; +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h +index 68a8e84..e451f55 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h ++++ b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h +@@ -32,6 +32,8 @@ namespace PVR + virtual bool HasListItems() const { return true; }; + virtual CFileItemPtr GetCurrentListItem(int offset = 0); + ++ void SetRadioRDS(const CFileItem *item); ++ + protected: + virtual void OnInitWindow(); + virtual void OnDeinitWindow(int nextWindowID); +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRecordingInfo.h b/xbmc/pvr/dialogs/GUIDialogPVRRecordingInfo.h +index 076cdaf..d6a8022 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRRecordingInfo.h ++++ b/xbmc/pvr/dialogs/GUIDialogPVRRecordingInfo.h +@@ -28,10 +28,10 @@ namespace PVR + public: + CGUIDialogPVRRecordingInfo(void); + virtual ~CGUIDialogPVRRecordingInfo(void) {} +- virtual bool OnMessage(CGUIMessage& message) override; ++ virtual bool OnMessage(CGUIMessage& message); + virtual bool OnInfo(int actionID) override; +- virtual bool HasListItems() const override { return true; }; +- virtual CFileItemPtr GetCurrentListItem(int offset = 0) override; ++ virtual bool HasListItems() const { return true; }; ++ virtual CFileItemPtr GetCurrentListItem(int offset = 0); + + void SetRecording(const CFileItem *item); + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp +index 2e2bd3b..08132fc 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp +@@ -601,7 +601,7 @@ void CGUIDialogPVRTimerSettings::Save() + { + if (m_endLocalTime < m_startLocalTime) // And the end clock is earlier than the start clock + { +- CLog::Log(LOGDEBUG, "CGUIDialogPVRTimerSettings::Save - End before start, adding a day."); ++ CLog::Log(LOGPVR, "CGUIDialogPVRTimerSettings::Save - End before start, adding a day."); + m_endLocalTime += CDateTimeSpan(1, 0, 0, 0); + if (m_endLocalTime < m_startLocalTime) + { +@@ -611,7 +611,7 @@ void CGUIDialogPVRTimerSettings::Save() + } + else if (m_endLocalTime > (m_startLocalTime + CDateTimeSpan(1, 0, 0, 0))) // Or the duration is more than a day + { +- CLog::Log(LOGDEBUG, "CGUIDialogPVRTimerSettings::Save - End > 1 day after start, removing a day."); ++ CLog::Log(LOGPVR, "CGUIDialogPVRTimerSettings::Save - End > 1 day after start, removing a day."); + m_endLocalTime -= CDateTimeSpan(1, 0, 0, 0); + if (m_endLocalTime > (m_startLocalTime + CDateTimeSpan(1, 0, 0, 0))) + { +diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp +index 3de7eca..ad096ee 100644 +--- a/xbmc/pvr/recordings/PVRRecording.cpp ++++ b/xbmc/pvr/recordings/PVRRecording.cpp +@@ -36,6 +36,17 @@ + using namespace PVR; + using namespace EPG; + ++CPVRRecordingUid::CPVRRecordingUid() : ++ m_iClientId(PVR_INVALID_CLIENT_ID) ++{ ++} ++ ++CPVRRecordingUid::CPVRRecordingUid(const CPVRRecordingUid &recordingId) : ++ m_iClientId(recordingId.m_iClientId), ++ m_strRecordingId(recordingId.m_strRecordingId) ++{ ++} ++ + CPVRRecordingUid::CPVRRecordingUid(int iClientId, const std::string& strRecordingId) : + m_iClientId(iClientId), + m_strRecordingId(strRecordingId) +@@ -81,7 +92,7 @@ CPVRRecording::CPVRRecording(const PVR_RECORDING &recording, unsigned int iClien + m_strShowTitle = recording.strEpisodeName; + m_iSeason = recording.iSeriesNumber; + m_iEpisode = recording.iEpisodeNumber; +- SetYear(recording.iYear); ++ m_iYear = recording.iYear; + m_iClientId = iClientId; + m_recordingTime = recording.recordingTime + g_advancedSettings.m_iPVRTimeCorrection; + m_duration = CDateTimeSpan(0, 0, recording.iDuration / 60, recording.iDuration % 60); +@@ -152,7 +163,7 @@ bool CPVRRecording::operator ==(const CPVRRecording& right) const + m_strShowTitle == right.m_strShowTitle && + m_iSeason == right.m_iSeason && + m_iEpisode == right.m_iEpisode && +- GetPremiered() == right.GetPremiered() && ++ m_iYear == right.m_iYear && + m_strIconPath == right.m_strIconPath && + m_strThumbnailPath == right.m_strThumbnailPath && + m_strFanartPath == right.m_strFanartPath && +@@ -377,7 +388,7 @@ void CPVRRecording::Update(const CPVRRecording &tag) + m_strShowTitle = tag.m_strShowTitle; + m_iSeason = tag.m_iSeason; + m_iEpisode = tag.m_iEpisode; +- SetPremiered(tag.GetPremiered()); ++ m_iYear = tag.m_iYear; + m_recordingTime = tag.m_recordingTime; + m_duration = tag.m_duration; + m_iPriority = tag.m_iPriority; +@@ -409,7 +420,7 @@ void CPVRRecording::Update(const CPVRRecording &tag) + std::string strShow = StringUtils::Format("%s - ", g_localizeStrings.Get(20364).c_str()); + if (StringUtils::StartsWithNoCase(m_strPlotOutline, strShow)) + { +- CLog::Log(LOGDEBUG,"CPVRRecording::Update - PVR addon provides episode name in strPlotOutline which is deprecated"); ++ CLog::Log(LOGPVR,"CPVRRecording::Update - PVR addon provides episode name in strPlotOutline which is deprecated"); + std::string strEpisode = m_strPlotOutline; + std::string strTitle = m_strDirectory; + +@@ -437,7 +448,7 @@ void CPVRRecording::UpdatePath(void) + else + { + m_strFileNameAndPath = CPVRRecordingsPath( +- m_bIsDeleted, m_bRadio, m_strDirectory, m_strTitle, m_iSeason, m_iEpisode, GetYear(), m_strShowTitle, m_strChannelName, m_recordingTime, m_strRecordingId); ++ m_bIsDeleted, m_bRadio, m_strDirectory, m_strTitle, m_iSeason, m_iEpisode, m_iYear, m_strShowTitle, m_strChannelName, m_recordingTime, m_strRecordingId); + } + } + +@@ -470,3 +481,17 @@ CPVRChannelPtr CPVRRecording::Channel(void) const + + return CPVRChannelPtr(); + } ++ ++bool CPVRRecording::IsBeingRecorded(void) const ++{ ++ if (m_iEpgEventId != EPG_TAG_INVALID_UID) ++ { ++ const CPVRChannelPtr channel(Channel()); ++ if (channel) ++ { ++ const EPG::CEpgInfoTagPtr epgTag(EPG::CEpgContainer::GetInstance().GetTagById(channel, m_iEpgEventId)); ++ return epgTag ? epgTag->HasRecording() : false; ++ } ++ } ++ return false; ++} +diff --git a/xbmc/pvr/recordings/PVRRecording.h b/xbmc/pvr/recordings/PVRRecording.h +index 9d261b6..c12c7d3 100644 +--- a/xbmc/pvr/recordings/PVRRecording.h ++++ b/xbmc/pvr/recordings/PVRRecording.h +@@ -35,10 +35,6 @@ + * + */ + +-#include <string> +-#include <memory> +-#include <vector> +- + #include "XBDateTime.h" + #include "addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h" + #include "video/VideoInfoTag.h" +@@ -63,6 +59,8 @@ namespace PVR + int m_iClientId; /*!< ID of the backend */ + std::string m_strRecordingId; /*!< unique ID of the recording on the client */ + ++ CPVRRecordingUid(); ++ CPVRRecordingUid(const CPVRRecordingUid& recordingId); + CPVRRecordingUid(int iClientId, const std::string &strRecordingId); + + bool operator >(const CPVRRecordingUid& right) const; +@@ -183,6 +181,8 @@ namespace PVR + + const CDateTime &RecordingTimeAsUTC(void) const { return m_recordingTime; } + const CDateTime &RecordingTimeAsLocalTime(void) const; ++ void SetRecordingTimeFromUTC(CDateTime &recordingTime) { m_recordingTime = recordingTime; } ++ void SetRecordingTimeFromLocalTime(CDateTime &recordingTime) { m_recordingTime = recordingTime.GetAsUTCDateTime(); } + + /*! + * @brief Retrieve the recording title from the URL path +@@ -214,12 +214,23 @@ namespace PVR + unsigned int BroadcastUid(void) const { return m_iEpgEventId; } + + /*! ++ * @return channel id associated with this recording or PVR_CHANNEL_INVALID_UID ++ */ ++ int ChannelUid(void) const { return m_iChannelUid; } ++ ++ /*! + * @return Get the channel on which this recording is/was running + * @note Only works if the recording has a channel uid provided by the add-on + */ + CPVRChannelPtr Channel(void) const; + + /*! ++ * @return True while the recording is running ++ * @note Only works if the recording has a channel uid and an EPG id provided by the add-on ++ */ ++ bool IsBeingRecorded(void) const; ++ ++ /*! + * @brief Retrieve the recording Episode Name + * @note Returns an empty string if no Episode Name was provided by the PVR client + */ +diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp +index 84d19d7..163dc29 100644 +--- a/xbmc/pvr/recordings/PVRRecordings.cpp ++++ b/xbmc/pvr/recordings/PVRRecordings.cpp +@@ -147,6 +147,11 @@ int CPVRRecordings::Load(void) + return m_recordings.size(); + } + ++void CPVRRecordings::Unload() ++{ ++ Clear(); ++} ++ + void CPVRRecordings::Update(void) + { + CSingleLock lock(m_critSection); +@@ -155,7 +160,7 @@ void CPVRRecordings::Update(void) + m_bIsUpdating = true; + lock.Leave(); + +- CLog::Log(LOGDEBUG, "CPVRRecordings - %s - updating recordings", __FUNCTION__); ++ CLog::Log(LOGPVR, "CPVRRecordings - %s - updating recordings", __FUNCTION__); + UpdateFromClients(); + + lock.Enter(); +@@ -260,7 +265,7 @@ bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count) + { + bResult = true; + +- CLog::Log(LOGDEBUG, "CPVRRecordings - %s - item path %s", __FUNCTION__, item->GetPath().c_str()); ++ CLog::Log(LOGPVR, "CPVRRecordings - %s - item path %s", __FUNCTION__, item->GetPath().c_str()); + CFileItemList items; + if (item->m_bIsFolder) + { +@@ -269,15 +274,15 @@ bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count) + else + items.Add(item); + +- CLog::Log(LOGDEBUG, "CPVRRecordings - %s - will set watched for %d items", __FUNCTION__, items.Size()); ++ CLog::Log(LOGPVR, "CPVRRecordings - %s - will set watched for %d items", __FUNCTION__, items.Size()); + for (int i=0;i<items.Size();++i) + { +- CLog::Log(LOGDEBUG, "CPVRRecordings - %s - setting watched for item %d", __FUNCTION__, i); ++ CLog::Log(LOGPVR, "CPVRRecordings - %s - setting watched for item %d", __FUNCTION__, i); + + CFileItemPtr pItem=items[i]; + if (pItem->m_bIsFolder) + { +- CLog::Log(LOGDEBUG, "CPVRRecordings - %s - path %s is a folder, will call recursively", __FUNCTION__, pItem->GetPath().c_str()); ++ CLog::Log(LOGPVR, "CPVRRecordings - %s - path %s is a folder, will call recursively", __FUNCTION__, pItem->GetPath().c_str()); + if (pItem->GetLabel() != "..") + { + SetRecordingsPlayCount(pItem, count); +diff --git a/xbmc/pvr/recordings/PVRRecordings.h b/xbmc/pvr/recordings/PVRRecordings.h +index 675dde8..d32d918 100644 +--- a/xbmc/pvr/recordings/PVRRecordings.h ++++ b/xbmc/pvr/recordings/PVRRecordings.h +@@ -65,6 +65,7 @@ namespace PVR + virtual ~CPVRRecordings(void); + + int Load(); ++ void Unload(); + void Clear(); + void UpdateFromClient(const CPVRRecordingPtr &tag); + void UpdateEpgTags(void); +@@ -97,5 +98,6 @@ namespace PVR + CFileItemPtr GetById(unsigned int iId) const; + + void SetGroupItems(bool value) { m_bGroupItems = value; }; ++ bool IsGroupItems() const { return m_bGroupItems; }; + }; + } +diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.cpp b/xbmc/pvr/timers/PVRTimerInfoTag.cpp +index 2ff44d4..8024967 100644 +--- a/xbmc/pvr/timers/PVRTimerInfoTag.cpp ++++ b/xbmc/pvr/timers/PVRTimerInfoTag.cpp +@@ -46,28 +46,29 @@ using KODI::MESSAGING::HELPERS::DialogResponse; + CPVRTimerInfoTag::CPVRTimerInfoTag(bool bRadio /* = false */) : + m_strTitle(g_localizeStrings.Get(19056)), // New Timer + m_bFullTextEpgSearch(false), +- m_state(PVR_TIMER_STATE_SCHEDULED), +- m_iClientId(g_PVRClients->GetFirstConnectedClientID()), +- m_iClientIndex(PVR_TIMER_NO_CLIENT_INDEX), +- m_iParentClientIndex(PVR_TIMER_NO_PARENT), +- m_iClientChannelUid(PVR_CHANNEL_INVALID_UID), +- m_bStartAnyTime(false), +- m_bEndAnyTime(false), +- m_iPriority(CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_DEFAULTPRIORITY)), +- m_iLifetime(CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_DEFAULTLIFETIME)), +- m_iMaxRecordings(0), +- m_iPreventDupEpisodes(CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_PREVENTDUPLICATEEPISODES)), +- m_iRecordingGroup(0), +- m_iChannelNumber(0), +- m_bIsRadio(bRadio), +- m_iTimerId(0), +- m_iMarginStart(CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_MARGINSTART)), +- m_iMarginEnd(CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_MARGINEND)), +- m_StartTime(CDateTime::GetUTCDateTime()), +- m_StopTime(m_StartTime), + m_iEpgUid(EPG_TAG_INVALID_UID) + { ++ m_iClientId = g_PVRClients->GetFirstConnectedClientID(); ++ m_iClientIndex = PVR_TIMER_NO_CLIENT_INDEX; ++ m_iParentClientIndex = PVR_TIMER_NO_PARENT; ++ m_iClientChannelUid = PVR_CHANNEL_INVALID_UID; ++ m_iPriority = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_DEFAULTPRIORITY); ++ m_iLifetime = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_DEFAULTLIFETIME); ++ m_iMaxRecordings = 0; ++ m_iPreventDupEpisodes = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_PREVENTDUPLICATEEPISODES); ++ m_iRecordingGroup = 0; ++ m_iChannelNumber = 0; ++ m_bIsRadio = bRadio; ++ m_iMarginStart = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_MARGINSTART); ++ m_iMarginEnd = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_MARGINEND); ++ m_StartTime = CDateTime::GetUTCDateTime(); ++ m_StopTime = m_StartTime; ++ m_bStartAnyTime = false; ++ m_bEndAnyTime = false; ++ m_state = PVR_TIMER_STATE_SCHEDULED; + m_FirstDay.SetValid(false); ++ m_iTimerId = 0; ++ ResetChildState(); + + if (g_PVRClients->SupportsTimers(m_iClientId)) + { +@@ -88,10 +89,6 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(bool bRadio /* = false */) : + } + + m_iWeekdays = (m_timerType && m_timerType->IsRepeating()) ? PVR_WEEKDAY_ALLDAYS : PVR_WEEKDAY_NONE; +- +- ResetChildState(); +- UpdateSummary(); +- UpdateEpgInfoTag(); + } + + CPVRTimerInfoTag::CPVRTimerInfoTag(const PVR_TIMER &timer, const CPVRChannelPtr &channel, unsigned int iClientId) : +@@ -99,34 +96,37 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(const PVR_TIMER &timer, const CPVRChannelPtr + m_strEpgSearchString(timer.strEpgSearchString), + m_bFullTextEpgSearch(timer.bFullTextEpgSearch), + m_strDirectory(timer.strDirectory), +- m_state(timer.state), +- m_iClientId(iClientId), +- m_iClientIndex(timer.iClientIndex), +- m_iParentClientIndex(timer.iParentClientIndex), +- m_iClientChannelUid(channel ? channel->UniqueID() : (timer.iClientChannelUid > 0) ? timer.iClientChannelUid : PVR_CHANNEL_INVALID_UID), +- m_bStartAnyTime(timer.bStartAnyTime), +- m_bEndAnyTime(timer.bEndAnyTime), +- m_iPriority(timer.iPriority), +- m_iLifetime(timer.iLifetime), +- m_iMaxRecordings(timer.iMaxRecordings), +- m_iWeekdays(timer.iWeekdays), +- m_iPreventDupEpisodes(timer.iPreventDuplicateEpisodes), +- m_iRecordingGroup(timer.iRecordingGroup), +- m_strFileNameAndPath(StringUtils::Format("pvr://client%i/timers/%i", m_iClientId, m_iClientIndex)), +- m_iChannelNumber(channel ? g_PVRChannelGroups->GetGroupAll(channel->IsRadio())->GetChannelNumber(channel) : 0), +- m_bIsRadio(channel && channel->IsRadio()), +- m_iTimerId(0), +- m_channel(channel), +- m_iMarginStart(timer.iMarginStart), +- m_iMarginEnd(timer.iMarginEnd), +- m_StartTime(timer.startTime + g_advancedSettings.m_iPVRTimeCorrection), +- m_StopTime(timer.endTime + g_advancedSettings.m_iPVRTimeCorrection), +- m_FirstDay(timer.firstDay + g_advancedSettings.m_iPVRTimeCorrection), + m_iEpgUid(timer.iEpgUid) + { ++ m_iClientId = iClientId; ++ m_iClientIndex = timer.iClientIndex; ++ + if (m_iClientIndex == PVR_TIMER_NO_CLIENT_INDEX) + CLog::Log(LOGERROR, "%s: invalid client index supplied by client %d (must be > 0)!", __FUNCTION__, m_iClientId); + ++ m_iParentClientIndex = timer.iParentClientIndex; ++ m_iClientChannelUid = channel ? channel->UniqueID() : (timer.iClientChannelUid > 0) ? timer.iClientChannelUid : PVR_CHANNEL_INVALID_UID; ++ m_iChannelNumber = channel ? g_PVRChannelGroups->GetGroupAll(channel->IsRadio())->GetChannelNumber(channel) : 0; ++ m_StartTime = timer.startTime + g_advancedSettings.m_iPVRTimeCorrection; ++ m_StopTime = timer.endTime + g_advancedSettings.m_iPVRTimeCorrection; ++ m_bStartAnyTime = timer.bStartAnyTime; ++ m_bEndAnyTime = timer.bEndAnyTime; ++ m_iPreventDupEpisodes = timer.iPreventDuplicateEpisodes; ++ m_iRecordingGroup = timer.iRecordingGroup; ++ m_FirstDay = timer.firstDay + g_advancedSettings.m_iPVRTimeCorrection; ++ m_iWeekdays = timer.iWeekdays; ++ m_iPriority = timer.iPriority; ++ m_iLifetime = timer.iLifetime; ++ m_iMaxRecordings = timer.iMaxRecordings; ++ m_iMarginStart = timer.iMarginStart; ++ m_iMarginEnd = timer.iMarginEnd; ++ m_channel = channel; ++ m_bIsRadio = channel && channel->IsRadio(); ++ m_state = timer.state; ++ m_strFileNameAndPath = StringUtils::Format("pvr://client%i/timers/%i", m_iClientId, m_iClientIndex); ++ m_iTimerId = 0; ++ ResetChildState(); ++ + if (g_PVRClients->SupportsTimers(m_iClientId)) + { + // begin compat section +@@ -170,7 +170,6 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(const PVR_TIMER &timer, const CPVRChannelPtr + CLog::Log(LOGERROR, "%s: no epg tag given for epg based timer type (%d)!", __FUNCTION__, m_timerType->GetTypeId()); + } + +- ResetChildState(); + UpdateSummary(); + UpdateEpgInfoTag(); + } +@@ -220,6 +219,7 @@ bool CPVRTimerInfoTag::operator ==(const CPVRTimerInfoTag& right) const + + CPVRTimerInfoTag::~CPVRTimerInfoTag(void) + { ++ ClearEpgTag(); + } + + /** +@@ -331,6 +331,22 @@ void CPVRTimerInfoTag::Serialize(CVariant &value) const + value["epguid"] = m_iEpgUid; + } + ++int CPVRTimerInfoTag::Compare(const CPVRTimerInfoTag &timer) const ++{ ++ CSingleLock lock(m_critSection); ++ int iTimerDelta = 0; ++ if (StartAsUTC() != timer.StartAsUTC()) ++ { ++ CDateTimeSpan timerDelta = StartAsUTC() - timer.StartAsUTC(); ++ iTimerDelta = (timerDelta.GetSeconds() + timerDelta.GetMinutes() * 60 + timerDelta.GetHours() * 3600 + timerDelta.GetDays() * 86400); ++ } ++ ++ /* if the start times are equal, compare the priority of the timers */ ++ return iTimerDelta == 0 ? ++ timer.m_iPriority - m_iPriority : ++ iTimerDelta; ++} ++ + void CPVRTimerInfoTag::UpdateEpgInfoTag(void) + { + CSingleLock lock(m_critSection); +@@ -721,9 +737,19 @@ std::string CPVRTimerInfoTag::ChannelIcon() const + return strReturn; + } + +-static const time_t INSTANT_TIMER_START = 0; // PVR addon API: special start time value to denote an instant timer ++bool CPVRTimerInfoTag::SetDuration(int iDuration) ++{ ++ CSingleLock lock(m_critSection); ++ if (m_StartTime.IsValid()) ++ { ++ m_StopTime = m_StartTime + CDateTimeSpan(0, iDuration / 60, iDuration % 60, 0); ++ return true; ++ } ++ ++ return false; ++} + +-CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateInstantTimerTag(const CPVRChannelPtr &channel, int iDuration /* = DEFAULT_PVRRECORD_INSTANTRECORDTIME */) ++CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateInstantTimerTag(const CPVRChannelPtr &channel) + { + if (!channel) + { +@@ -761,24 +787,17 @@ CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateInstantTimerTag(const CPVRChannelPtr + newTimer->SetTimerType(timerType); + } + +- /* no matter the timer was created from an epg tag, overwrite timer start and end times. */ +- CDateTime now(CDateTime::GetUTCDateTime()); +- newTimer->SetStartFromUTC(now); +- +- if (iDuration == DEFAULT_PVRRECORD_INSTANTRECORDTIME) +- iDuration = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME); ++ // no matter the timer was created from an epg tag, set special instant timer start and end times. ++ CDateTime startTime(0); ++ newTimer->SetStartFromUTC(startTime); ++ newTimer->m_iMarginStart = 0; /* set the start margin to 0 for instant timers */ + +- CDateTime endTime = now + CDateTimeSpan(0, 0, iDuration ? iDuration : 120, 0); ++ int iDuration = CSettings::GetInstance().GetInt(CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME); ++ CDateTime endTime = CDateTime::GetUTCDateTime() + CDateTimeSpan(0, 0, iDuration ? iDuration : 120, 0); + newTimer->SetEndFromUTC(endTime); + +- /* update summary string according to instant recording start/end time */ ++ /* update summary string according to changed start/end time */ + newTimer->UpdateSummary(); +- newTimer->m_strSummary = StringUtils::Format(g_localizeStrings.Get(19093).c_str(), newTimer->Summary().c_str()); +- +- CDateTime startTime(INSTANT_TIMER_START); +- newTimer->SetStartFromUTC(startTime); +- newTimer->m_iMarginStart = 0; +- newTimer->m_iMarginEnd = 0; + + /* set epg tag at timer & timer at epg tag */ + newTimer->UpdateEpgInfoTag(); +@@ -978,9 +997,10 @@ CEpgInfoTagPtr CPVRTimerInfoTag::GetEpgInfoTag(bool bCreate /* = true */) const + { + // if no epg uid present, try to find a tag according to timer's start/end time + m_epgTag = epg->GetTagBetween(StartAsUTC() - CDateTimeSpan(0, 0, 2, 0), EndAsUTC() + CDateTimeSpan(0, 0, 2, 0)); +- if (m_epgTag) +- m_iEpgUid = m_epgTag->UniqueBroadcastID(); + } ++ ++ if (m_epgTag) ++ m_epgTag->SetTimer(g_PVRTimers->GetById(m_iTimerId)); + } + } + } +@@ -988,22 +1008,17 @@ CEpgInfoTagPtr CPVRTimerInfoTag::GetEpgInfoTag(bool bCreate /* = true */) const + return m_epgTag; + } + +-void CPVRTimerInfoTag::SetEpgTag(const CEpgInfoTagPtr &tag) ++void CPVRTimerInfoTag::ClearEpgTag(void) + { +- CEpgInfoTagPtr previousTag; ++ CEpgInfoTagPtr deletedTag; + { + CSingleLock lock(m_critSection); +- previousTag = m_epgTag; +- m_epgTag = tag; ++ deletedTag = m_epgTag; ++ m_epgTag.reset(); + } + +- if (previousTag) +- previousTag->ClearTimer(); +-} +- +-void CPVRTimerInfoTag::ClearEpgTag(void) +-{ +- SetEpgTag(CEpgInfoTagPtr()); ++ if (deletedTag) ++ deletedTag->ClearTimer(); + } + + CPVRChannelPtr CPVRTimerInfoTag::ChannelTag(void) const +@@ -1011,11 +1026,10 @@ CPVRChannelPtr CPVRTimerInfoTag::ChannelTag(void) const + return m_channel; + } + +-CPVRChannelPtr CPVRTimerInfoTag::UpdateChannel(void) ++void CPVRTimerInfoTag::UpdateChannel(void) + { + CSingleLock lock(m_critSection); + m_channel = g_PVRChannelGroups->Get(m_bIsRadio)->GetGroupAll()->GetByUniqueID(m_iClientChannelUid, m_iClientId); +- return m_channel; + } + + const std::string& CPVRTimerInfoTag::Title(void) const +diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.h b/xbmc/pvr/timers/PVRTimerInfoTag.h +index 988f670..9c714b1 100644 +--- a/xbmc/pvr/timers/PVRTimerInfoTag.h ++++ b/xbmc/pvr/timers/PVRTimerInfoTag.h +@@ -86,6 +86,8 @@ namespace PVR + + virtual void Serialize(CVariant &value) const; + ++ int Compare(const CPVRTimerInfoTag &timer) const; ++ + void UpdateSummary(void); + + void DisplayError(PVR_ERROR err) const; +@@ -93,15 +95,14 @@ namespace PVR + std::string GetStatus() const; + std::string GetTypeAsString() const; + +- static const int DEFAULT_PVRRECORD_INSTANTRECORDTIME = -1; ++ bool SetDuration(int iDuration); + + /*! + * @brief create a tag for an instant timer for a given channel +- * @param channel is the channel the instant timer is to be created for +- * @param iDuration is the duration for the instant timer, DEFAULT_PVRRECORD_INSTANTRECORDTIME denotes system default (setting value) ++ * @parame the channel the instant timer is be created for + * @return the timer or null if timer could not be created + */ +- static CPVRTimerInfoTagPtr CreateInstantTimerTag(const CPVRChannelPtr &channel, int iDuration = DEFAULT_PVRRECORD_INSTANTRECORDTIME); ++ static CPVRTimerInfoTagPtr CreateInstantTimerTag(const CPVRChannelPtr &channel); + + /*! + * @brief create a timer or timer rule for the given epg info tag. +@@ -140,6 +141,8 @@ namespace PVR + */ + void ResetChildState(); + ++ void UpdateEpgEvent(bool bClear = false); ++ + bool IsActive(void) const + { + return m_state == PVR_TIMER_STATE_SCHEDULED +@@ -207,9 +210,14 @@ namespace PVR + + CDateTime FirstDayAsUTC(void) const; + CDateTime FirstDayAsLocalTime(void) const; ++ void SetFirstDayFromUTC(CDateTime &firstDay) { m_FirstDay = firstDay; } + void SetFirstDayFromLocalTime(CDateTime &firstDay) { m_FirstDay = firstDay.GetAsUTCDateTime(); } + + unsigned int MarginStart(void) const { return m_iMarginStart; } ++ void SetMarginStart(unsigned int iMinutes) { m_iMarginStart = iMinutes; } ++ ++ unsigned int MarginEnd(void) const { return m_iMarginEnd; } ++ void SetMarginEnd(unsigned int iMinutes) { m_iMarginEnd = iMinutes; } + + /*! + * @brief Get the text for the notification. +@@ -232,22 +240,9 @@ namespace PVR + bool RenameOnClient(const std::string &strNewName); + bool UpdateOnClient(); + +- /*! +- * @brief Associate the given epg tag with this timer; before, clear old timer at associated epg tag, if any. +- * @param tag The epg tag to assign. +- */ +- void SetEpgTag(const EPG::CEpgInfoTagPtr &tag); +- +- /*! +- * @brief Clear the epg tag associated with this timer; before, clear this timer at associated epg tag, if any. +- */ + void ClearEpgTag(void); + +- /*! +- * @brief Update the channel associated with this timer. +- * @return the channel for the timer. Can be empty for epg based repeating timers (e.g. "match any channel" rules) +- */ +- CPVRChannelPtr UpdateChannel(void); ++ void UpdateChannel(void); + + /*! + * @brief Return string representation for any possible combination of weekdays. +@@ -296,6 +291,7 @@ namespace PVR + void UpdateEpgInfoTag(void); + + CCriticalSection m_critSection; ++ unsigned int m_iEpgUid; /*!< id of epg event associated with this timer, EPG_TAG_INVALID_UID if none. */ + CDateTime m_StartTime; /*!< start time */ + CDateTime m_StopTime; /*!< stop time */ + CDateTime m_FirstDay; /*!< if it is a manual repeating timer the first date it starts */ +@@ -306,7 +302,6 @@ namespace PVR + bool m_bHasChildRecording; /*!< @brief Has at least one child timer with status PVR_TIMER_STATE_RECORDING */ + bool m_bHasChildErrors; /*!< @brief Has at least one child timer with status PVR_TIMER_STATE_ERROR */ + +- mutable unsigned int m_iEpgUid; /*!< id of epg event associated with this timer, EPG_TAG_INVALID_UID if none. */ + mutable EPG::CEpgInfoTagPtr m_epgTag; /*!< epg info tag matching m_iEpgUid. */ + }; + } +diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp +index 8f48b52..3a38cb6 100644 +--- a/xbmc/pvr/timers/PVRTimers.cpp ++++ b/xbmc/pvr/timers/PVRTimers.cpp +@@ -84,7 +84,7 @@ bool CPVRTimers::Update(void) + m_bIsUpdating = true; + } + +- CLog::Log(LOGDEBUG, "CPVRTimers - %s - updating timers", __FUNCTION__); ++ CLog::Log(LOGPVR, "CPVRTimers - %s - updating timers", __FUNCTION__); + CPVRTimers newTimerList; + std::vector<int> failedClients; + g_PVRClients->GetTimers(&newTimerList, failedClients); +@@ -103,42 +103,6 @@ bool CPVRTimers::IsRecording(void) const + return false; + } + +-bool CPVRTimers::SetEpgTagTimer(const CPVRTimerInfoTagPtr &timer) +-{ +- if (timer->IsRepeating() || timer->m_bStartAnyTime || timer->m_bEndAnyTime) +- return false; +- +- std::vector<CEpgInfoTagPtr> tags(g_EpgContainer.GetEpgTagsForTimer(timer)); +- +- if (tags.empty()) +- return false; +- +- // assign first matching epg tag to the timer. +- timer->SetEpgTag(tags.front()); +- +- // assign timer to every matching epg tag. +- for (const auto &tag : tags) +- tag->SetTimer(timer); +- +- return true; +-} +- +-bool CPVRTimers::ClearEpgTagTimer(const CPVRTimerInfoTagPtr &timer) +-{ +- if (timer->IsRepeating() || timer->m_bStartAnyTime || timer->m_bEndAnyTime) +- return false; +- +- std::vector<CEpgInfoTagPtr> tags(g_EpgContainer.GetEpgTagsForTimer(timer)); +- +- if (tags.empty()) +- return false; +- +- for (const auto &tag : tags) +- tag->ClearTimer(); +- +- return true; +-} +- + bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> &failedClients) + { + bool bChanged(false); +@@ -158,11 +122,8 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + { + /* if it's present, update the current tag */ + bool bStateChanged(existingTimer->m_state != (*timerIt)->m_state); +- ClearEpgTagTimer(existingTimer); + if (existingTimer->UpdateEntry(*timerIt)) + { +- SetEpgTagTimer(existingTimer); +- + bChanged = true; + existingTimer->ResetChildState(); + +@@ -173,7 +134,7 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + timerNotifications.push_back(std::make_pair((*timerIt)->m_iClientId, strMessage)); + } + +- CLog::Log(LOGDEBUG,"PVRTimers - %s - updated timer %d on client %d", ++ CLog::Log(LOGPVR,"PVRTimers - %s - updated timer %d on client %d", + __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); + } + } +@@ -196,8 +157,6 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + } + + newTimer->m_iTimerId = ++m_iLastId; +- SetEpgTagTimer(newTimer); +- + addEntry->push_back(newTimer); + bChanged = true; + bAddedOrDeleted = true; +@@ -209,7 +168,7 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + timerNotifications.push_back(std::make_pair(newTimer->m_iClientId, strMessage)); + } + +- CLog::Log(LOGDEBUG,"PVRTimers - %s - added timer %d on client %d", ++ CLog::Log(LOGPVR,"PVRTimers - %s - added timer %d on client %d", + __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); + } + } +@@ -243,14 +202,14 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + continue; + } + +- CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", ++ CLog::Log(LOGPVR,"PVRTimers - %s - deleted timer %d on client %d", + __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); + + if (g_PVRManager.IsStarted()) + timerNotifications.push_back(std::make_pair(timer->m_iClientId, timer->GetDeletedNotificationText())); + +- ClearEpgTagTimer(timer); +- ++ /** clear the EPG tag explicitly here, because it no longer happens automatically with shared pointers */ ++ timer->ClearEpgTag(); + it2 = it->second->erase(it2); + + bChanged = true; +@@ -260,10 +219,10 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + (!timer->m_bStartAnyTime && timer->StartAsUTC() != it->first)) + { + /* timer start has changed */ +- CLog::Log(LOGDEBUG,"PVRTimers - %s - changed start time timer %d on client %d", ++ CLog::Log(LOGPVR,"PVRTimers - %s - changed start time timer %d on client %d", + __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); + +- ClearEpgTagTimer(timer); ++ timer->ClearEpgTag(); + + /* remember timer */ + timersToMove.push_back(timer); +@@ -300,8 +259,6 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> + addEntry = itr->second; + } + +- SetEpgTagTimer(*timerIt); +- + addEntry->push_back(*timerIt); + } + +@@ -577,7 +534,7 @@ bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDele + + if (bDeleteActiveItem && bDeleteRepeatingItem && bChannelsMatch) + { +- CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); ++ CLog::Log(LOGPVR,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); + bReturn = (*timerIt)->DeleteFromClient(true) || bReturn; + SetChanged(); + } +@@ -590,6 +547,25 @@ bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDele + return bReturn; + } + ++bool CPVRTimers::InstantTimer(const CPVRChannelPtr &channel) ++{ ++ assert(channel.get()); ++ ++ if (!g_PVRManager.CheckParentalLock(channel)) ++ return false; ++ ++ CPVRTimerInfoTagPtr newTimer(CPVRTimerInfoTag::CreateInstantTimerTag(channel)); ++ ++ bool bReturn(false); ++ if (newTimer) ++ bReturn = newTimer->AddToClient(); ++ ++ if (!bReturn) ++ CLog::Log(LOGERROR, "PVRTimers - %s - unable to add an instant timer on the client", __FUNCTION__); ++ ++ return bReturn; ++} ++ + /********** static methods **********/ + + bool CPVRTimers::AddTimer(const CPVRTimerInfoTagPtr &item) +diff --git a/xbmc/pvr/timers/PVRTimers.h b/xbmc/pvr/timers/PVRTimers.h +index 93874a4..a6129bd 100644 +--- a/xbmc/pvr/timers/PVRTimers.h ++++ b/xbmc/pvr/timers/PVRTimers.h +@@ -21,7 +21,6 @@ + + #include <map> + #include <memory> +-#include <vector> + + #include "addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h" + #include "PVRTimerInfoTag.h" +@@ -137,6 +136,13 @@ namespace PVR + bool DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDeleteRepeating = true, bool bCurrentlyActiveOnly = false); + + /*! ++ * @brief Create a new instant timer on a channel. ++ * @param channel The channel to create the timer on. ++ * @return True if the timer was created, false otherwise. ++ */ ++ bool InstantTimer(const CPVRChannelPtr &channel); ++ ++ /*! + * @return Next event time (timer or daily wake up) + */ + CDateTime GetNextEventTime(void) const; +@@ -210,8 +216,6 @@ namespace PVR + CPVRTimerInfoTagPtr GetByClient(int iClientId, unsigned int iClientTimerId) const; + bool GetRootDirectory(const CPVRTimersPath &path, CFileItemList &items) const; + bool GetSubDirectory(const CPVRTimersPath &path, CFileItemList &items) const; +- bool SetEpgTagTimer(const CPVRTimerInfoTagPtr &timer); +- bool ClearEpgTagTimer(const CPVRTimerInfoTagPtr &timer); + + CCriticalSection m_critSection; + bool m_bIsUpdating; +diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.cpp b/xbmc/pvr/windows/GUIWindowPVRBase.cpp +index 310aba0..9b4c435 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRBase.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRBase.cpp +@@ -22,7 +22,7 @@ + #include "GUIWindowPVRRecordings.h" + + #include "Application.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "dialogs/GUIDialogNumeric.h" + #include "dialogs/GUIDialogOK.h" +@@ -94,20 +94,6 @@ void CGUIWindowPVRBase::ResetObservers(void) + RegisterObservers(); + } + +-void CGUIWindowPVRBase::RegisterObservers(void) +-{ +- CSingleLock lock(m_critSection); +- if (m_group) +- m_group->RegisterObserver(this); +-}; +- +-void CGUIWindowPVRBase::UnregisterObservers(void) +-{ +- CSingleLock lock(m_critSection); +- if (m_group) +- m_group->UnregisterObserver(this); +-}; +- + void CGUIWindowPVRBase::Notify(const Observable &obs, const ObservableMessage msg) + { + CGUIMessage m(GUI_MSG_REFRESH_LIST, GetID(), 0, msg); +@@ -388,7 +374,7 @@ CPVRChannelGroupPtr CGUIWindowPVRBase::GetGroup(void) + return m_group; + } + +-void CGUIWindowPVRBase::SetGroup(const CPVRChannelGroupPtr &group) ++void CGUIWindowPVRBase::SetGroup(CPVRChannelGroupPtr group) + { + CSingleLock lock(m_critSection); + if (!group) +@@ -587,12 +573,8 @@ bool CGUIWindowPVRBase::EditTimer(CFileItem *item) + return false; + } + +- // clone the timer. +- const CPVRTimerInfoTagPtr newTimer(new CPVRTimerInfoTag); +- newTimer->UpdateEntry(timer); +- +- if (ShowTimerSettings(newTimer) && !timer->GetTimerType()->IsReadOnly()) +- return g_PVRTimers->UpdateTimer(newTimer); ++ if (ShowTimerSettings(timer) && !timer->GetTimerType()->IsReadOnly()) ++ return g_PVRTimers->UpdateTimer(timer); + + return false; + } +diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.h b/xbmc/pvr/windows/GUIWindowPVRBase.h +index ebf1347..414367a 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRBase.h ++++ b/xbmc/pvr/windows/GUIWindowPVRBase.h +@@ -97,7 +97,7 @@ namespace PVR + + virtual std::string GetDirectoryPath(void) = 0; + virtual CPVRChannelGroupPtr GetGroup(void); +- virtual void SetGroup(const CPVRChannelGroupPtr &group); ++ virtual void SetGroup(CPVRChannelGroupPtr group); + + virtual bool ActionShowTimerRule(CFileItem *item); + virtual bool ActionToggleTimer(CFileItem *item); +@@ -119,8 +119,8 @@ namespace PVR + bool OnContextButtonEditTimerRule(CFileItem *item, CONTEXT_BUTTON button); + bool OnContextButtonDeleteTimerRule(CFileItem *item, CONTEXT_BUTTON button); + +- virtual void RegisterObservers(void); +- virtual void UnregisterObservers(void); ++ virtual void RegisterObservers(void) {}; ++ virtual void UnregisterObservers(void) {}; + + static CCriticalSection m_selectedItemPathsLock; + static std::string m_selectedItemPaths[2]; +diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +index 8580529..0903370 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +@@ -21,7 +21,7 @@ + + #include "ContextMenuManager.h" + #include "GUIInfoManager.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "epg/EpgContainer.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "dialogs/GUIDialogOK.h" +@@ -56,20 +56,17 @@ void CGUIWindowPVRChannels::RegisterObservers(void) + { + CSingleLock lock(m_critSection); + g_EpgContainer.RegisterObserver(this); +- if (g_PVRTimers) +- g_PVRTimers->RegisterObserver(this); ++ g_PVRTimers->RegisterObserver(this); + g_infoManager.RegisterObserver(this); +- CGUIWindowPVRBase::RegisterObservers(); + } + + void CGUIWindowPVRChannels::UnregisterObservers(void) + { + CSingleLock lock(m_critSection); +- CGUIWindowPVRBase::UnregisterObservers(); +- g_infoManager.UnregisterObserver(this); ++ g_EpgContainer.UnregisterObserver(this); + if (g_PVRTimers) + g_PVRTimers->UnregisterObserver(this); +- g_EpgContainer.UnregisterObserver(this); ++ g_infoManager.UnregisterObserver(this); + } + + void CGUIWindowPVRChannels::GetContextButtons(int itemNumber, CContextButtons &buttons) +diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp +index 194d1b5..f38231d 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp +@@ -37,6 +37,8 @@ + + #include "GUIWindowPVRGuide.h" + ++#define MAX_UPDATE_FREQUENCY 3000 // limit to maximum one update/refresh in x milliseconds ++ + using namespace PVR; + using namespace EPG; + +@@ -53,17 +55,13 @@ CGUIWindowPVRGuide::~CGUIWindowPVRGuide(void) + StopRefreshTimelineItemsThread(); + } + +-CGUIEPGGridContainer* CGUIWindowPVRGuide::GetGridControl() +-{ +- return dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl())); +-} +- + void CGUIWindowPVRGuide::OnInitWindow() + { + if (m_guiState.get()) + m_viewControl.SetCurrentView(m_guiState->GetViewAsControl(), false); + +- CGUIEPGGridContainer *epgGridContainer = GetGridControl(); ++ CGUIEPGGridContainer *epgGridContainer = ++ dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl())); + if (epgGridContainer) + { + epgGridContainer->SetChannel(GetSelectedItemPath(m_bRadio)); +@@ -97,19 +95,11 @@ void CGUIWindowPVRGuide::StopRefreshTimelineItemsThread() + + void CGUIWindowPVRGuide::RegisterObservers(void) + { +- CSingleLock lock(m_critSection); + g_EpgContainer.RegisterObserver(this); +- if (g_PVRTimers) +- g_PVRTimers->RegisterObserver(this); +- CGUIWindowPVRBase::RegisterObservers(); + } + + void CGUIWindowPVRGuide::UnregisterObservers(void) + { +- CSingleLock lock(m_critSection); +- CGUIWindowPVRBase::UnregisterObservers(); +- if (g_PVRTimers) +- g_PVRTimers->UnregisterObserver(this); + g_EpgContainer.UnregisterObserver(this); + } + +@@ -118,7 +108,6 @@ void CGUIWindowPVRGuide::Notify(const Observable &obs, const ObservableMessage m + if (m_viewControl.GetCurrentControl() == GUIDE_VIEW_TIMELINE && + (msg == ObservableMessageEpg || + msg == ObservableMessageEpgContainer || +- msg == ObservableMessageChannelGroupReset || + msg == ObservableMessageChannelGroup)) + { + CSingleLock lock(m_critSection); +@@ -130,15 +119,6 @@ void CGUIWindowPVRGuide::Notify(const Observable &obs, const ObservableMessage m + } + } + +-void CGUIWindowPVRGuide::SetInvalid() +-{ +- CGUIEPGGridContainer *epgGridContainer = GetGridControl(); +- if (epgGridContainer) +- epgGridContainer->SetInvalid(); +- +- CGUIWindowPVRBase::SetInvalid(); +-} +- + void CGUIWindowPVRGuide::GetContextButtons(int itemNumber, CContextButtons &buttons) + { + if (itemNumber < 0 || itemNumber >= m_vecItems->Size()) +@@ -370,7 +350,8 @@ bool CGUIWindowPVRGuide::OnMessage(CGUIMessage& message) + case ACTION_PLAY: + { + // EPG "gap" selected => switch to associated channel. +- CGUIEPGGridContainer *epgGridContainer = GetGridControl(); ++ CGUIEPGGridContainer *epgGridContainer = ++ dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl())); + if (epgGridContainer) + { + CFileItemPtr item(epgGridContainer->GetSelectedChannelItem()); +@@ -405,7 +386,6 @@ bool CGUIWindowPVRGuide::OnMessage(CGUIMessage& message) + case GUI_MSG_REFRESH_LIST: + switch(message.GetParam1()) + { +- case ObservableMessageChannelGroupReset: + case ObservableMessageChannelGroup: + case ObservableMessageEpg: + case ObservableMessageEpgContainer: +@@ -413,12 +393,6 @@ bool CGUIWindowPVRGuide::OnMessage(CGUIMessage& message) + Refresh(true); + break; + } +- case ObservableMessageTimersReset: +- case ObservableMessageTimers: +- { +- SetInvalid(); +- break; +- } + case ObservableMessageEpgActiveItem: + { + if (m_viewControl.GetCurrentControl() != GUIDE_VIEW_TIMELINE) +@@ -503,7 +477,7 @@ bool CGUIWindowPVRGuide::RefreshTimelineItems() + { + m_bRefreshTimelineItems = false; + +- CGUIEPGGridContainer* epgGridContainer = GetGridControl(); ++ CGUIEPGGridContainer* epgGridContainer = dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl())); + if (epgGridContainer) + { + const CPVRChannelGroupPtr group(GetGroup()); +@@ -549,7 +523,7 @@ void CGUIWindowPVRGuide::GetViewTimelineItems(CFileItemList &items) + // group change detected reset grid coordinates and refresh grid items + if (!m_bRefreshTimelineItems && *m_cachedChannelGroup != *GetGroup()) + { +- CGUIEPGGridContainer* epgGridContainer = GetGridControl(); ++ CGUIEPGGridContainer* epgGridContainer = dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl())); + if (!epgGridContainer) + return; + +diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.h b/xbmc/pvr/windows/GUIWindowPVRGuide.h +index 224cf05..0120f86 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRGuide.h ++++ b/xbmc/pvr/windows/GUIWindowPVRGuide.h +@@ -26,11 +26,6 @@ + + class CSetting; + +-namespace EPG +-{ +- class CGUIEPGGridContainer; +-} +- + namespace PVR + { + class CPVRRefreshTimelineItemsThread; +@@ -49,7 +44,6 @@ namespace PVR + virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override; + virtual void UpdateButtons(void) override; + virtual void Notify(const Observable &obs, const ObservableMessage msg) override; +- virtual void SetInvalid() override; + + bool RefreshTimelineItems(); + +@@ -61,8 +55,6 @@ namespace PVR + virtual void UnregisterObservers(void) override; + + private: +- EPG::CGUIEPGGridContainer* GetGridControl(); +- + bool SelectPlayingFile(void); + + bool OnContextButtonBegin(CFileItem *item, CONTEXT_BUTTON button); +diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp +index 5ff21c7..5406929 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp +@@ -20,7 +20,7 @@ + + #include "ContextMenuManager.h" + #include "GUIInfoManager.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "dialogs/GUIDialogYesNo.h" + #include "guilib/LocalizeStrings.h" + #include "guilib/GUIKeyboardFactory.h" +@@ -52,23 +52,19 @@ CGUIWindowPVRRecordings::CGUIWindowPVRRecordings(bool bRadio) : + void CGUIWindowPVRRecordings::RegisterObservers(void) + { + CSingleLock lock(m_critSection); +- if (g_PVRRecordings) +- g_PVRRecordings->RegisterObserver(this); +- if (g_PVRTimers) +- g_PVRTimers->RegisterObserver(this); ++ g_PVRRecordings->RegisterObserver(this); ++ g_PVRTimers->RegisterObserver(this); + g_infoManager.RegisterObserver(this); +- CGUIWindowPVRBase::RegisterObservers(); + } + + void CGUIWindowPVRRecordings::UnregisterObservers(void) + { + CSingleLock lock(m_critSection); +- CGUIWindowPVRBase::UnregisterObservers(); +- g_infoManager.UnregisterObserver(this); +- if (g_PVRTimers) +- g_PVRTimers->UnregisterObserver(this); + if (g_PVRRecordings) + g_PVRRecordings->UnregisterObserver(this); ++ if (g_PVRTimers) ++ g_PVRTimers->UnregisterObserver(this); ++ g_infoManager.UnregisterObserver(this); + } + + void CGUIWindowPVRRecordings::OnWindowLoaded() +diff --git a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp +index 636ed9f..482fb94 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp +@@ -181,7 +181,7 @@ void CGUIWindowPVRSearch::OnPrepareFileItems(CFileItemList &items) + dlgProgress->Progress(); + } + +- //! @todo should we limit the find similar search to the selected group? ++ // TODO should we limit the find similar search to the selected group? + g_EpgContainer.GetEPGSearch(items, m_searchfilter); + + if (dlgProgress) +diff --git a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp +index acf7c0b..7a8071a 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp +@@ -48,19 +48,16 @@ CGUIWindowPVRTimersBase::CGUIWindowPVRTimersBase(bool bRadio, int id, const std: + void CGUIWindowPVRTimersBase::RegisterObservers(void) + { + CSingleLock lock(m_critSection); +- if (g_PVRTimers) +- g_PVRTimers->RegisterObserver(this); ++ g_PVRTimers->RegisterObserver(this); + g_infoManager.RegisterObserver(this); +- CGUIWindowPVRBase::RegisterObservers(); + } + + void CGUIWindowPVRTimersBase::UnregisterObservers(void) + { + CSingleLock lock(m_critSection); +- CGUIWindowPVRBase::UnregisterObservers(); +- g_infoManager.UnregisterObserver(this); + if (g_PVRTimers) + g_PVRTimers->UnregisterObserver(this); ++ g_infoManager.UnregisterObserver(this); + } + + void CGUIWindowPVRTimersBase::GetContextButtons(int itemNumber, CContextButtons &buttons) +diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h +index cba4e58..c4352e7 100644 +--- a/xbmc/rendering/RenderSystem.h ++++ b/xbmc/rendering/RenderSystem.h +@@ -102,7 +102,7 @@ public: + + virtual bool BeginRender() = 0; + virtual bool EndRender() = 0; +- virtual void PresentRender(bool rendered, bool videoLayer) = 0; ++ virtual void PresentRender(bool rendered) = 0; + virtual bool ClearBuffers(color_t color) = 0; + virtual bool IsExtSupported(const char* extension) = 0; + +diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp +index 1666c87..e22c364 100644 +--- a/xbmc/rendering/dx/RenderSystemDX.cpp ++++ b/xbmc/rendering/dx/RenderSystemDX.cpp +@@ -32,15 +32,16 @@ + #include "settings/AdvancedSettings.h" + #include "threads/SingleLock.h" + #include "utils/MathUtils.h" ++#include "utils/TimeUtils.h" + #include "utils/log.h" ++#include "win32/WIN32Util.h" + #include "win32/dxerr.h" + + #pragma comment(lib, "d3d11.lib") + #pragma comment(lib, "dxgi.lib") + #pragma comment(lib, "dxguid.lib") + +-#define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? \ +- static_cast<float>(rational.Numerator) / static_cast<float>(rational.Denominator) : 0.0f) ++#define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? (float)rational.Numerator / (float)rational.Denominator : 0.0) + + using namespace DirectX::PackedVector; + +@@ -48,12 +49,52 @@ CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase() + { + m_enumRenderingSystem = RENDERING_SYSTEM_DIRECTX; + ++ m_hFocusWnd = nullptr; ++ m_hDeviceWnd = nullptr; ++ m_nBackBufferWidth = 0; ++ m_nBackBufferHeight = 0; ++ m_bFullScreenDevice = false; + m_bVSync = true; ++ m_nDeviceStatus = S_OK; ++ m_inScene = false; ++ m_needNewDevice = false; ++ m_resizeInProgress = false; ++ m_screenHeight = 0; ++ m_systemFreq = CurrentHostFrequency(); ++ m_defaultD3DUsage = D3D11_USAGE_DEFAULT; ++ m_featureLevel = D3D_FEATURE_LEVEL_11_1; ++ m_driverType = D3D_DRIVER_TYPE_HARDWARE; ++ m_adapter = nullptr; ++ m_pOutput = nullptr; ++ m_dxgiFactory = nullptr; ++ m_pD3DDev = nullptr; ++ m_pImdContext = nullptr; ++ m_pContext = nullptr; ++ ++ m_pSwapChain = nullptr; ++ m_pSwapChain1 = nullptr; ++ m_pRenderTargetView = nullptr; ++ m_depthStencilState = nullptr; ++ m_depthStencilView = nullptr; ++ m_BlendEnableState = nullptr; ++ m_BlendDisableState = nullptr; ++ m_BlendEnabled = false; ++ m_RSScissorDisable = nullptr; ++ m_RSScissorEnable = nullptr; ++ m_ScissorsEnabled = false; + ++ m_pTextureRight = nullptr; ++ m_pRenderTargetViewRight = nullptr; ++ m_pShaderResourceViewRight = nullptr; ++ m_pGUIShader = nullptr; ++ m_bResizeRequred = false; ++ m_bHWStereoEnabled = false; + ZeroMemory(&m_cachedMode, sizeof(m_cachedMode)); + ZeroMemory(&m_viewPort, sizeof(m_viewPort)); + ZeroMemory(&m_scissor, sizeof(CRect)); + ZeroMemory(&m_adapterDesc, sizeof(DXGI_ADAPTER_DESC)); ++ m_bDefaultStereoEnabled = false; ++ m_bStereoEnabled = false; + } + + CRenderSystemDX::~CRenderSystemDX() +@@ -174,7 +215,7 @@ void CRenderSystemDX::OnMove() + m_pOutput->GetDesc(&outputDesc); + HMONITOR newMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL); + +- if (newMonitor != nullptr && outputDesc.Monitor != newMonitor) ++ if (newMonitor != NULL && outputDesc.Monitor != newMonitor) + { + SetMonitor(newMonitor); + if (m_needNewDevice) +@@ -246,12 +287,12 @@ void CRenderSystemDX::GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached /*= fa + + inline void DXWait(ID3D11Device* pDevice, ID3D11DeviceContext* pContext) + { +- ID3D11Query* wait = nullptr; ++ ID3D11Query* wait = NULL; + CD3D11_QUERY_DESC qd(D3D11_QUERY_EVENT); + if (SUCCEEDED(pDevice->CreateQuery(&qd, &wait))) + { + pContext->End(wait); +- while (S_FALSE == pContext->GetData(wait, nullptr, 0, 0)) ++ while (S_FALSE == pContext->GetData(wait, NULL, 0, 0)) + Sleep(1); + } + SAFE_RELEASE(wait); +@@ -264,7 +305,7 @@ void CRenderSystemDX::SetFullScreenInternal() + + HRESULT hr = S_OK; + BOOL bFullScreen; +- m_pSwapChain->GetFullscreenState(&bFullScreen, nullptr); ++ m_pSwapChain->GetFullscreenState(&bFullScreen, NULL); + + // full-screen to windowed translation. Only change FS state and return + if (!!bFullScreen && m_useWindowedDX) +@@ -272,7 +313,7 @@ void CRenderSystemDX::SetFullScreenInternal() + CLog::Log(LOGDEBUG, "%s - Switching swap chain to windowed mode.", __FUNCTION__); + + OnDisplayLost(); +- hr = m_pSwapChain->SetFullscreenState(false, nullptr); ++ hr = m_pSwapChain->SetFullscreenState(false, NULL); + if (SUCCEEDED(hr)) + m_bResizeRequred = true; + else +@@ -281,7 +322,7 @@ void CRenderSystemDX::SetFullScreenInternal() + // true full-screen + else if (m_bFullScreenDevice && !m_useWindowedDX) + { +- IDXGIOutput* pOutput = nullptr; ++ IDXGIOutput* pOutput = NULL; + m_pSwapChain->GetContainingOutput(&pOutput); + + DXGI_OUTPUT_DESC trgDesc, currDesc; +@@ -390,7 +431,7 @@ void CRenderSystemDX::DeleteDevice() + (*i)->OnDestroyDevice(); + + if (m_pSwapChain) +- m_pSwapChain->SetFullscreenState(false, nullptr); ++ m_pSwapChain->SetFullscreenState(false, NULL); + + SAFE_DELETE(m_pGUIShader); + SAFE_RELEASE(m_pTextureRight); +@@ -584,7 +625,7 @@ bool CRenderSystemDX::CreateDevice() + + // use multi-thread protection on the device context to prevent deadlock issues that can sometimes happen + // when decoder call ID3D11VideoContext::GetDecoderBuffer or ID3D11VideoContext::ReleaseDecoderBuffer. +- ID3D10Multithread *pMultiThreading = nullptr; ++ ID3D10Multithread *pMultiThreading = NULL; + if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&pMultiThreading)))) + { + pMultiThreading->SetMultithreadProtected(true); +@@ -724,7 +765,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + { + DXGI_SWAP_CHAIN_DESC1 scDesc; + m_pSwapChain1->GetDesc1(&scDesc); +- bNeedRecreate = (scDesc.Stereo == TRUE) != bHWStereoEnabled; ++ bNeedRecreate = scDesc.Stereo != bHWStereoEnabled; + } + + if (!bNeedRecreate && !bNeedResize) +@@ -741,13 +782,13 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + ID3D11RenderTargetView* pRTView; ID3D11DepthStencilView* pDSView; + m_pContext->OMGetRenderTargets(1, &pRTView, &pDSView); + +- bRestoreRTView = (nullptr != pRTView || nullptr != pDSView); ++ bRestoreRTView = NULL != pRTView || NULL != pDSView; + + SAFE_RELEASE(pRTView); + SAFE_RELEASE(pDSView); + } + +- m_pContext->OMSetRenderTargets(0, nullptr, nullptr); ++ m_pContext->OMSetRenderTargets(0, NULL, NULL); + FinishCommandList(false); + + SAFE_RELEASE(m_pRenderTargetView); +@@ -765,9 +806,9 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + } + + BOOL fullScreen; +- m_pSwapChain1->GetFullscreenState(&fullScreen, nullptr); ++ m_pSwapChain1->GetFullscreenState(&fullScreen, NULL); + if (fullScreen) +- m_pSwapChain1->SetFullscreenState(false, nullptr); ++ m_pSwapChain1->SetFullscreenState(false, NULL); + + // disable/enable stereo 3D on system level + if (g_advancedSettings.m_useDisplayControlHWStereo) +@@ -791,7 +832,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + CLog::Log(LOGDEBUG, "%s - Creating swapchain in %s mode.", __FUNCTION__, bHWStereoEnabled ? "Stereoscopic 3D" : "Mono"); + + // Create swap chain +- IDXGIFactory2* dxgiFactory2 = nullptr; ++ IDXGIFactory2* dxgiFactory2 = NULL; + hr = m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2)); + if (SUCCEEDED(hr) && dxgiFactory2) + { +@@ -814,7 +855,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + scFSDesc.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + scFSDesc.Windowed = m_useWindowedDX; + +- hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, nullptr, &m_pSwapChain1); ++ hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, NULL, &m_pSwapChain1); + + // some drivers (AMD) are denied to switch in stereoscopic 3D mode, if so then fallback to mono mode + if (FAILED(hr) && bHWStereoEnabled) +@@ -825,7 +866,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + + scDesc1.Stereo = false; + bHWStereoEnabled = false; +- hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, nullptr, &m_pSwapChain1); ++ hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, NULL, &m_pSwapChain1); + + // fallback to split_horisontal mode. + g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_SPLIT_HORIZONTAL); +@@ -933,11 +974,11 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + else if (IsFormatSupport(DXGI_FORMAT_D24_UNORM_S8_UINT, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) zFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + else if (IsFormatSupport(DXGI_FORMAT_D16_UNORM, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) zFormat = DXGI_FORMAT_D16_UNORM; + +- ID3D11Texture2D* depthStencilBuffer = nullptr; ++ ID3D11Texture2D* depthStencilBuffer = NULL; + // Initialize the description of the depth buffer. + CD3D11_TEXTURE2D_DESC depthBufferDesc(zFormat, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL); + // Create the texture for the depth buffer using the filled out description. +- hr = m_pD3DDev->CreateTexture2D(&depthBufferDesc, nullptr, &depthStencilBuffer); ++ hr = m_pD3DDev->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, "%s - Failed to create depth stencil buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str()); +@@ -957,9 +998,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() + + if (m_viewPort.Height == 0 || m_viewPort.Width == 0) + { +- CRect rect(0.0f, 0.0f, +- static_cast<float>(m_nBackBufferWidth), +- static_cast<float>(m_nBackBufferHeight)); ++ CRect rect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight); + SetViewPort(rect); + } + +@@ -1005,7 +1044,7 @@ void CRenderSystemDX::CheckInterlasedStereoView(void) + HRESULT hr; + CD3D11_TEXTURE2D_DESC texDesc(DXGI_FORMAT_B8G8R8A8_UNORM, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); +- hr = m_pD3DDev->CreateTexture2D(&texDesc, nullptr, &m_pTextureRight); ++ hr = m_pD3DDev->CreateTexture2D(&texDesc, NULL, &m_pTextureRight); + if (SUCCEEDED(hr)) + { + CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2D); +@@ -1148,7 +1187,7 @@ void CRenderSystemDX::PresentRenderImpl(bool rendered) + ? SHADER_METHOD_RENDER_STEREO_INTERLACED_RIGHT + : SHADER_METHOD_RENDER_STEREO_CHECKERBOARD_RIGHT; + SetAlphaBlendEnable(true); +- CD3DTexture::DrawQuad(destRect, 0, 1, &m_pShaderResourceViewRight, nullptr, method); ++ CD3DTexture::DrawQuad(destRect, 0, 1, &m_pShaderResourceViewRight, NULL, method); + CD3DHelper::PSClearShaderResources(m_pContext); + } + +@@ -1280,9 +1319,7 @@ bool CRenderSystemDX::ClearBuffers(color_t color) + if (pRTView == nullptr) + return true; + +- CRect clRect(0.0f, 0.0f, +- static_cast<float>(m_nBackBufferWidth), +- static_cast<float>(m_nBackBufferHeight)); ++ CRect clRect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight); + + // Unlike Direct3D 9, D3D11 ClearRenderTargetView always clears full extent of the resource view. + // Viewport and scissor settings are not applied. So clear RT by drawing full sized rect with clear color +@@ -1487,7 +1524,7 @@ bool CRenderSystemDX::ScissorsCanEffectClipping() + if (!m_bRenderCreated) + return false; + +- return m_pGUIShader != nullptr && m_pGUIShader->HardwareClipIsPossible(); ++ return m_pGUIShader != NULL && m_pGUIShader->HardwareClipIsPossible(); + } + + CRect CRenderSystemDX::ClipRectToScissorRect(const CRect &rect) +@@ -1527,9 +1564,7 @@ void CRenderSystemDX::ResetScissors() + if (!m_bRenderCreated) + return; + +- m_scissor.SetRect(0.0f, 0.0f, +- static_cast<float>(m_nBackBufferWidth), +- static_cast<float>(m_nBackBufferHeight)); ++ m_scissor.SetRect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight); + + m_pContext->RSSetState(m_RSScissorDisable); + m_ScissorsEnabled = false; +@@ -1623,7 +1658,7 @@ bool CRenderSystemDX::GetStereoEnabled() const + + IDXGIFactory2* dxgiFactory2 = nullptr; + if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2)))) +- result = dxgiFactory2->IsWindowedStereoEnabled() == TRUE; ++ result = dxgiFactory2->IsWindowedStereoEnabled(); + SAFE_RELEASE(dxgiFactory2); + + return result; +@@ -1634,17 +1669,17 @@ bool CRenderSystemDX::GetDisplayStereoEnabled() const + bool result = false; + + IDXGIDisplayControl * pDXGIDisplayControl = nullptr; +- if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIDisplayControl), reinterpret_cast<void **>(&pDXGIDisplayControl)))) +- result = pDXGIDisplayControl->IsStereoEnabled() == TRUE; ++ if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIDisplayControl), (void **)&pDXGIDisplayControl))) ++ result = pDXGIDisplayControl->IsStereoEnabled(); + SAFE_RELEASE(pDXGIDisplayControl); + + return result; + } + +-void CRenderSystemDX::SetDisplayStereoEnabled(bool enable) const ++void CRenderSystemDX::SetDisplayStereoEnabled(bool enable) + { + IDXGIDisplayControl * pDXGIDisplayControl = nullptr; +- if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIDisplayControl), reinterpret_cast<void **>(&pDXGIDisplayControl)))) ++ if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIDisplayControl), (void **)&pDXGIDisplayControl))) + pDXGIDisplayControl->SetStereoEnabled(enable); + SAFE_RELEASE(pDXGIDisplayControl); + } +@@ -1678,7 +1713,7 @@ bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode) const + } + } + +-void CRenderSystemDX::FlushGPU() const ++void CRenderSystemDX::FlushGPU() + { + if (!m_bRenderCreated) + return; +@@ -1711,16 +1746,16 @@ void CRenderSystemDX::SetAlphaBlendEnable(bool enable) + return; + + float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f }; +- m_pContext->OMSetBlendState(enable ? m_BlendEnableState : m_BlendDisableState, nullptr, 0xFFFFFFFF); ++ m_pContext->OMSetBlendState(enable ? m_BlendEnableState : m_BlendDisableState, 0, 0xFFFFFFFF); + m_BlendEnabled = enable; + } + +-void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/) const ++void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/) + { + if (m_pImdContext == m_pContext) + return; + +- ID3D11CommandList* pCommandList = nullptr; ++ ID3D11CommandList* pCommandList = NULL; + if (FAILED(m_pContext->FinishCommandList(true, &pCommandList))) + { + CLog::Log(LOGERROR, "%s - Failed to finish command queue.", __FUNCTION__); +@@ -1733,7 +1768,7 @@ void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/) const + SAFE_RELEASE(pCommandList); + } + +-void CRenderSystemDX::SetMaximumFrameLatency(uint8_t latency) const ++void CRenderSystemDX::SetMaximumFrameLatency(uint8_t latency) + { + if (!m_pD3DDev) + return; +diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h +index a07dfc8..6ff32bc 100644 +--- a/xbmc/rendering/dx/RenderSystemDX.h ++++ b/xbmc/rendering/dx/RenderSystemDX.h +@@ -46,47 +46,47 @@ public: + virtual ~CRenderSystemDX(); + + // CRenderBase +- bool InitRenderSystem() override; +- bool DestroyRenderSystem() override; +- bool ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate) override; +- bool BeginRender() override; +- bool EndRender() override; +- bool ClearBuffers(color_t color) override; +- bool IsExtSupported(const char* extension) override; ++ virtual bool InitRenderSystem(); ++ virtual bool DestroyRenderSystem(); ++ virtual bool ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate); ++ virtual bool BeginRender(); ++ virtual bool EndRender(); ++ virtual bool ClearBuffers(color_t color); ++ virtual bool IsExtSupported(const char* extension); + virtual bool IsFormatSupport(DXGI_FORMAT format, unsigned int usage); + virtual void SetVSync(bool vsync); +- void SetViewPort(CRect& viewPort) override; +- void GetViewPort(CRect& viewPort) override; +- void RestoreViewPort() override; +- CRect ClipRectToScissorRect(const CRect &rect) override; +- bool ScissorsCanEffectClipping() override; +- void SetScissors(const CRect &rect) override; +- void ResetScissors() override; +- void CaptureStateBlock() override; +- void ApplyStateBlock() override; +- void SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor = 0.f) override; +- void ApplyHardwareTransform(const TransformMatrix &matrix) override; +- void RestoreHardwareTransform() override; +- void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view) override; +- bool SupportsStereo(RENDER_STEREO_MODE mode) const override; +- bool TestRender() override; +- void Project(float &x, float &y, float &z) override; ++ virtual void SetViewPort(CRect& viewPort); ++ virtual void GetViewPort(CRect& viewPort); ++ virtual void RestoreViewPort(); ++ virtual CRect ClipRectToScissorRect(const CRect &rect); ++ virtual bool ScissorsCanEffectClipping(); ++ virtual void SetScissors(const CRect &rect); ++ virtual void ResetScissors(); ++ virtual void CaptureStateBlock(); ++ virtual void ApplyStateBlock(); ++ virtual void SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor = 0.f); ++ virtual void ApplyHardwareTransform(const TransformMatrix &matrix); ++ virtual void RestoreHardwareTransform(); ++ virtual void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view); ++ virtual bool SupportsStereo(RENDER_STEREO_MODE mode) const; ++ virtual bool TestRender(); ++ virtual void Project(float &x, float &y, float &z); + virtual CRect GetBackBufferRect() { return CRect(0.f, 0.f, static_cast<float>(m_nBackBufferWidth), static_cast<float>(m_nBackBufferHeight)); } + +- IDXGIOutput* GetCurrentOutput() const { return m_pOutput; } ++ IDXGIOutput* GetCurrentOutput(void) { return m_pOutput; } + void GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached = false); +- void FinishCommandList(bool bExecute = true) const; +- void FlushGPU() const; +- +- ID3D11Device* Get3D11Device() const { return m_pD3DDev; } +- ID3D11DeviceContext* Get3D11Context() const { return m_pContext; } +- ID3D11DeviceContext* GetImmediateContext() const { return m_pImdContext; } +- CGUIShaderDX* GetGUIShader() const { return m_pGUIShader; } +- unsigned GetFeatureLevel() const { return m_featureLevel; } +- D3D11_USAGE DefaultD3DUsage() const { return m_defaultD3DUsage; } +- DXGI_ADAPTER_DESC GetAIdentifier() const { return m_adapterDesc; } +- bool Interlaced() const { return m_interlaced; } +- int GetBackbufferCount() const { return 2; } ++ void FinishCommandList(bool bExecute = true); ++ void FlushGPU(); ++ ++ ID3D11Device* Get3D11Device() { return m_pD3DDev; } ++ ID3D11DeviceContext* Get3D11Context() { return m_pContext; } ++ ID3D11DeviceContext* GetImmediateContext(){ return m_pImdContext; } ++ CGUIShaderDX* GetGUIShader() { return m_pGUIShader; } ++ unsigned GetFeatureLevel() { return m_featureLevel; } ++ D3D11_USAGE DefaultD3DUsage() { return m_defaultD3DUsage; } ++ DXGI_ADAPTER_DESC GetAIdentifier() { return m_adapterDesc; } ++ bool Interlaced() { return m_interlaced; } ++ int GetBackbufferCount() const { return 2; } + void SetAlphaBlendEnable(bool enable); + + static std::string GetErrorDescription(HRESULT hr); +@@ -110,11 +110,11 @@ protected: + void SetFullScreenInternal(); + void GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode, bool useCached = false); + void CheckInterlasedStereoView(void); +- void SetMaximumFrameLatency(uint8_t latency = -1) const; ++ void SetMaximumFrameLatency(uint8_t latency = -1); + + bool GetStereoEnabled() const; + bool GetDisplayStereoEnabled() const; +- void SetDisplayStereoEnabled(bool enable) const; ++ void SetDisplayStereoEnabled(bool enable); + void UpdateDisplayStereoStatus(bool isfirst = false); + + virtual void Register(ID3DResource *resource); +@@ -125,59 +125,60 @@ protected: + virtual void OnDisplayBack() {}; + + // our adapter could change as we go +- bool m_needNewDevice{false}; ++ bool m_needNewDevice; + bool m_needNewViews; +- bool m_resizeInProgress{false}; +- unsigned int m_screenHeight{0}; +- HWND m_hFocusWnd{nullptr}; +- HWND m_hDeviceWnd{nullptr}; +- unsigned int m_nBackBufferWidth{0}; +- unsigned int m_nBackBufferHeight{0}; +- bool m_bFullScreenDevice{false}; ++ bool m_resizeInProgress; ++ unsigned int m_screenHeight; ++ HWND m_hFocusWnd; ++ HWND m_hDeviceWnd; ++ unsigned int m_nBackBufferWidth; ++ unsigned int m_nBackBufferHeight; ++ bool m_bFullScreenDevice; + float m_refreshRate; + bool m_interlaced; +- HRESULT m_nDeviceStatus{S_OK}; +- D3D11_USAGE m_defaultD3DUsage{D3D11_USAGE_DEFAULT}; ++ HRESULT m_nDeviceStatus; ++ int64_t m_systemFreq; ++ D3D11_USAGE m_defaultD3DUsage; + bool m_useWindowedDX; + CCriticalSection m_resourceSection; + std::vector<ID3DResource*> m_resources; +- bool m_inScene{false}; ///< True if we're in a BeginScene()/EndScene() block +- D3D_DRIVER_TYPE m_driverType{D3D_DRIVER_TYPE_HARDWARE}; +- D3D_FEATURE_LEVEL m_featureLevel{D3D_FEATURE_LEVEL_11_1}; +- IDXGIFactory1* m_dxgiFactory{nullptr}; +- ID3D11Device* m_pD3DDev{nullptr}; +- IDXGIAdapter1* m_adapter{nullptr}; +- IDXGIOutput* m_pOutput{nullptr}; +- ID3D11DeviceContext* m_pContext{nullptr}; +- ID3D11DeviceContext* m_pImdContext{nullptr}; +- IDXGISwapChain* m_pSwapChain{nullptr}; +- IDXGISwapChain1* m_pSwapChain1{nullptr}; +- ID3D11RenderTargetView* m_pRenderTargetView{nullptr}; +- ID3D11DepthStencilState* m_depthStencilState{nullptr}; +- ID3D11DepthStencilView* m_depthStencilView{nullptr}; ++ bool m_inScene; ///< True if we're in a BeginScene()/EndScene() block ++ D3D_DRIVER_TYPE m_driverType; ++ D3D_FEATURE_LEVEL m_featureLevel; ++ IDXGIFactory1* m_dxgiFactory; ++ ID3D11Device* m_pD3DDev; ++ IDXGIAdapter1* m_adapter; ++ IDXGIOutput* m_pOutput; ++ ID3D11DeviceContext* m_pContext; ++ ID3D11DeviceContext* m_pImdContext; ++ IDXGISwapChain* m_pSwapChain; ++ IDXGISwapChain1* m_pSwapChain1; ++ ID3D11RenderTargetView* m_pRenderTargetView; ++ ID3D11DepthStencilState* m_depthStencilState; ++ ID3D11DepthStencilView* m_depthStencilView; + D3D11_VIEWPORT m_viewPort; + CRect m_scissor; +- CGUIShaderDX* m_pGUIShader{nullptr}; +- ID3D11BlendState* m_BlendEnableState{nullptr}; +- ID3D11BlendState* m_BlendDisableState{nullptr}; +- bool m_BlendEnabled{false}; +- ID3D11RasterizerState* m_RSScissorDisable{nullptr}; +- ID3D11RasterizerState* m_RSScissorEnable{nullptr}; +- bool m_ScissorsEnabled{false}; ++ CGUIShaderDX* m_pGUIShader; ++ ID3D11BlendState* m_BlendEnableState; ++ ID3D11BlendState* m_BlendDisableState; ++ bool m_BlendEnabled; ++ ID3D11RasterizerState* m_RSScissorDisable; ++ ID3D11RasterizerState* m_RSScissorEnable; ++ bool m_ScissorsEnabled; + DXGI_ADAPTER_DESC m_adapterDesc; + // stereo interlaced/checkerboard intermediate target +- ID3D11Texture2D* m_pTextureRight{nullptr}; +- ID3D11RenderTargetView* m_pRenderTargetViewRight{nullptr}; +- ID3D11ShaderResourceView* m_pShaderResourceViewRight{nullptr}; +- bool m_bResizeRequred{false}; +- bool m_bHWStereoEnabled{false}; ++ ID3D11Texture2D* m_pTextureRight; ++ ID3D11RenderTargetView* m_pRenderTargetViewRight; ++ ID3D11ShaderResourceView* m_pShaderResourceViewRight; ++ bool m_bResizeRequred; ++ bool m_bHWStereoEnabled; + // improve get current mode + DXGI_MODE_DESC m_cachedMode; + #ifdef _DEBUG +- ID3D11Debug* m_d3dDebug{nullptr}; ++ ID3D11Debug* m_d3dDebug = NULL; + #endif +- bool m_bDefaultStereoEnabled{false}; +- bool m_bStereoEnabled{false}; ++ bool m_bDefaultStereoEnabled; ++ bool m_bStereoEnabled; + }; + + #endif +diff --git a/xbmc/rendering/gl/RenderSystemGL.cpp b/xbmc/rendering/gl/RenderSystemGL.cpp +index fd6ed8d..87ff900 100644 +--- a/xbmc/rendering/gl/RenderSystemGL.cpp ++++ b/xbmc/rendering/gl/RenderSystemGL.cpp +@@ -186,7 +186,7 @@ bool CRenderSystemGL::ResetRenderSystem(int width, int height, bool fullScreen, + glEnable(GL_SCISSOR_TEST); + + glMatrixProject.Clear(); +- glMatrixProject->LoadIdentity(); ++ glMatrixModview->LoadIdentity(); + glMatrixProject->Ortho(0.0f, width-1, height-1, 0.0f, -1.0f, 1.0f); + glMatrixProject.Load(); + +@@ -290,7 +290,7 @@ bool CRenderSystemGL::IsExtSupported(const char* extension) + return m_RenderExtensions.find(name) != std::string::npos; + } + +-void CRenderSystemGL::PresentRender(bool rendered, bool videoLayer) ++void CRenderSystemGL::PresentRender(bool rendered) + { + SetVSync(true); + +diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h +index 5c6ff78..d6fe28b 100644 +--- a/xbmc/rendering/gl/RenderSystemGL.h ++++ b/xbmc/rendering/gl/RenderSystemGL.h +@@ -39,7 +39,7 @@ public: + + bool BeginRender() override; + bool EndRender() override; +- void PresentRender(bool rendered, bool videoLayer) override; ++ void PresentRender(bool rendered) override; + bool ClearBuffers(color_t color) override; + bool IsExtSupported(const char* extension) override; + +diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp +index 8cd5ea3..aa3becc 100644 +--- a/xbmc/rendering/gles/RenderSystemGLES.cpp ++++ b/xbmc/rendering/gles/RenderSystemGLES.cpp +@@ -151,7 +151,7 @@ bool CRenderSystemGLES::ResetRenderSystem(int width, int height, bool fullScreen + glEnable(GL_SCISSOR_TEST); + + glMatrixProject.Clear(); +- glMatrixProject->LoadIdentity(); ++ glMatrixModview->LoadIdentity(); + glMatrixProject->Ortho(0.0f, width-1, height-1, 0.0f, -1.0f, 1.0f); + glMatrixProject.Load(); + +@@ -274,7 +274,7 @@ static int64_t abs64(int64_t a) + return a; + } + +-void CRenderSystemGLES::PresentRender(bool rendered, bool videoLayer) ++void CRenderSystemGLES::PresentRender(bool rendered) + { + SetVSync(true); + +@@ -283,8 +283,7 @@ void CRenderSystemGLES::PresentRender(bool rendered, bool videoLayer) + + PresentRenderImpl(rendered); + +- // if video is rendered to a separate layer, we should not block this thread +- if (!rendered && !videoLayer) ++ if (!rendered) + Sleep(40); + } + +@@ -328,7 +327,7 @@ void CRenderSystemGLES::CaptureStateBlock() + + glDisable(GL_SCISSOR_TEST); // fixes FBO corruption on Macs + glActiveTexture(GL_TEXTURE0); +-//! @todo - NOTE: Only for Screensavers & Visualisations ++//TODO - NOTE: Only for Screensavers & Visualisations + // glColor3f(1.0, 1.0, 1.0); + } + +diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h +index f103cf5..989a43f 100644 +--- a/xbmc/rendering/gles/RenderSystemGLES.h ++++ b/xbmc/rendering/gles/RenderSystemGLES.h +@@ -56,7 +56,7 @@ public: + + bool BeginRender() override; + bool EndRender() override; +- void PresentRender(bool rendered, bool videoLayer) override; ++ void PresentRender(bool rendered) override; + bool ClearBuffers(color_t color) override; + bool IsExtSupported(const char* extension) override; + +diff --git a/xbmc/screensavers/gles/Makefile.in b/xbmc/screensavers/gles/Makefile.in +new file mode 100644 +index 0000000..b83237d +--- /dev/null ++++ b/xbmc/screensavers/gles/Makefile.in +@@ -0,0 +1,6 @@ ++SRCS=triangle2.cpp ++ ++LIB=gleshelpers.a ++ ++include @abs_top_srcdir@/Makefile.include ++-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) +diff --git a/xbmc/screensavers/gles/ball/Makefile.in b/xbmc/screensavers/gles/ball/Makefile.in +new file mode 100644 +index 0000000..d788075 +--- /dev/null ++++ b/xbmc/screensavers/gles/ball/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libball.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.ball/Ball.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=ball ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/ball/wrapper.cc b/xbmc/screensavers/gles/ball/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/ball/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/noise/Makefile.in b/xbmc/screensavers/gles/noise/Makefile.in +new file mode 100644 +index 0000000..ef3287c +--- /dev/null ++++ b/xbmc/screensavers/gles/noise/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libnoise.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.noise/Noise.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=noise ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/noise/wrapper.cc b/xbmc/screensavers/gles/noise/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/noise/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/plasma/Makefile.in b/xbmc/screensavers/gles/plasma/Makefile.in +new file mode 100644 +index 0000000..a69c159 +--- /dev/null ++++ b/xbmc/screensavers/gles/plasma/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libplasma.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.plasma/Plasma.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=plasma ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/plasma/wrapper.cc b/xbmc/screensavers/gles/plasma/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/plasma/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/plasma2/Makefile.in b/xbmc/screensavers/gles/plasma2/Makefile.in +new file mode 100644 +index 0000000..264e576 +--- /dev/null ++++ b/xbmc/screensavers/gles/plasma2/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libplasma2.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.plasma2/Plasma2.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=plasma2 ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/plasma2/wrapper.cc b/xbmc/screensavers/gles/plasma2/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/plasma2/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/solarwinds/Makefile.in b/xbmc/screensavers/gles/solarwinds/Makefile.in +new file mode 100644 +index 0000000..8d4e845 +--- /dev/null ++++ b/xbmc/screensavers/gles/solarwinds/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libsolarwinds.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.solarwinds/Solarwinds.xbs ++endif ++OBJS = wrapper.o solarwinds.o ++DEFINES += -DSCREENSAVER=solarwinds ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/solarwinds/solarwinds.c b/xbmc/screensavers/gles/solarwinds/solarwinds.c +new file mode 100644 +index 0000000..a1125cf +--- /dev/null ++++ b/xbmc/screensavers/gles/solarwinds/solarwinds.c +@@ -0,0 +1,530 @@ ++/* ++Copyright (c) 2012, Broadcom Europe Ltd ++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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. ++*/ ++ ++// OpenGL|ES 2 demo using shader to compute particle/render sets ++// Thanks to Peter de Rivas for original Python code ++ ++#include <stdio.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <math.h> ++#include <assert.h> ++#include <unistd.h> ++#include <stddef.h> ++ ++#include "solarwinds.h" ++ ++#define PARTICLE_WIDTH 16 ++#define PARTICLE_HEIGHT 16 ++ ++#define min(a,b) ((a)<(b)?(a):(b)) ++#define max(a,b) ((a)<(b)?(b):(a)) ++ ++#define check() assert(glGetError() == 0) ++ ++static void showlog(GLint shader) ++{ ++ // Prints the compile log for a shader ++ char log[1024]; ++ glGetShaderInfoLog(shader,sizeof log,NULL,log); ++ printf("%d:shader:\n%s\n", shader, log); ++} ++ ++static void showprogramlog(GLint shader) ++{ ++ // Prints the information log for a program object ++ char log[1024]; ++ glGetProgramInfoLog(shader,sizeof log,NULL,log); ++ printf("%d:program:\n%s\n", shader, log); ++} ++ ++static void *create_particle_tex(int width, int height) ++{ ++ int i, j; ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ unsigned char *p = q; ++ for (j=0; j<height; j++) { ++ for (i=0; i<width; i++) { ++ float x = ((float)i + 0.5f) / (float)width - 0.5f; ++ float y = ((float)j + 0.5f) / (float)height - 0.5f; ++ float d = 1.0f-2.0f*sqrtf(x*x + y*y); ++ unsigned v = 255.0f * max(min(d, 1.0f), 0.0f); ++ *p++ = 255; ++ *p++ = 255; ++ *p++ = 255; ++ *p++ = v; ++ } ++ } ++ return q; ++} ++ ++void solarwinds_init_shaders(CUBE_STATE_T *state) ++{ ++ const GLchar *particle_vshader_source = ++ //"// Attributes" ++ "attribute vec4 aPos;" ++ "attribute vec4 aShade;" ++ "" ++ //"// Uniforms" ++ "uniform mat4 uProjectionMatrix;" ++ "varying vec4 vShade;" ++ "" ++ "void main(void)" ++ "{" ++ " gl_Position = uProjectionMatrix * vec4(aPos.x/60.0, aPos.y/60.0, (16.0-aPos.z)/60.0, 1.0);" ++ " gl_PointSize = 16.0/gl_Position.w;" ++ " vShade = aShade;" ++ "}"; ++ ++ //particle ++ const GLchar *particle_fshader_source = ++ //" Input from Vertex Shader" ++ "varying vec4 vShade;" ++ "" ++ //" Uniforms" ++ "uniform sampler2D uTexture;" ++ "" ++ "void main(void)" ++ "{" ++ " vec4 texture = texture2D(uTexture, gl_PointCoord);" ++ " vec4 color = clamp(vShade, vec4(0.0), vec4(1.0));" ++ " gl_FragColor = texture * color;" ++ "}"; ++ ++ state->mvshader = glCreateShader(GL_VERTEX_SHADER); ++ glShaderSource(state->mvshader, 1, &particle_vshader_source, 0); ++ glCompileShader(state->mvshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->mvshader); ++ ++ state->mshader = glCreateShader(GL_FRAGMENT_SHADER); ++ glShaderSource(state->mshader, 1, &particle_fshader_source, 0); ++ glCompileShader(state->mshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->mshader); ++ ++ // particle ++ state->program_particle = glCreateProgram(); ++ glAttachShader(state->program_particle, state->mvshader); ++ glAttachShader(state->program_particle, state->mshader); ++ glLinkProgram(state->program_particle); ++ glDetachShader(state->program_particle, state->mvshader); ++ glDetachShader(state->program_particle, state->mshader); ++ glDeleteShader(state->mvshader); ++ glDeleteShader(state->mshader); ++ check(); ++ ++ if (state->verbose) ++ showprogramlog(state->program_particle); ++ ++ state->aPos = glGetAttribLocation(state->program_particle, "aPos"); ++ state->uProjectionMatrix = glGetUniformLocation(state->program_particle, "uProjectionMatrix"); ++ state->aShade = glGetAttribLocation(state->program_particle, "aShade"); ++ state->uTexture = glGetUniformLocation(state->program_particle, "uTexture"); ++ check(); ++ ++ glGenBuffers(1, &state->particleBuffer); ++ ++ check(); ++ ++ // Prepare a texture image ++ glGenTextures(1, &state->tex_particle); ++ check(); ++ glBindTexture(GL_TEXTURE_2D, state->tex_particle); ++ check(); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ state->tex_particle_data = create_particle_tex(PARTICLE_WIDTH, PARTICLE_HEIGHT); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PARTICLE_WIDTH, PARTICLE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, state->tex_particle_data); ++ check(); ++ ++ // Upload vertex data to a buffer ++ glBindBuffer(GL_ARRAY_BUFFER, state->particleBuffer); ++ ++ // Create Vertex Buffer Object (VBO) ++ glBufferData( // Fill bound buffer with particles ++ GL_ARRAY_BUFFER, // Buffer target ++ sizeof(state->particles), // Buffer data size ++ state->particles, // Buffer data pointer ++ GL_DYNAMIC_DRAW); // Usage - Data never changes; used for drawing ++ check(); ++} ++ ++void solarwinds_deinit_shaders(CUBE_STATE_T *state) ++{ ++ glDeleteProgram(state->program_particle); ++ check(); ++ ++ glDeleteBuffers(1, &state->particleBuffer); ++ check(); ++ ++ glDeleteTextures(1, &state->tex_particle); ++ check(); ++ ++ free(state->tex_particle_data); ++} ++ ++static void draw_particle_to_texture(CUBE_STATE_T *state) ++{ ++ glClearColor ( 0.0, 0.0, 0.0, 1.0 ); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ glBindTexture(GL_TEXTURE_2D, state->tex_particle); ++ glEnable(GL_BLEND); ++ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ++ ++ glBindBuffer(GL_ARRAY_BUFFER, state->particleBuffer); ++ ++ int remaining = state->numParticles - state->whichParticle; ++ // Create Vertex Buffer Object (VBO) ++ glBufferSubData( // Fill bound buffer with particles ++ GL_ARRAY_BUFFER, // Buffer target ++ 0, ++ remaining * sizeof(state->particles[0]), // Buffer data size ++ state->particles + state->whichParticle // Buffer data pointer ++ ); // Usage - Data never changes; used for drawing ++ check(); ++ // Create Vertex Buffer Object (VBO) ++ glBufferSubData( // Fill bound buffer with particles ++ GL_ARRAY_BUFFER, // Buffer target ++ remaining * sizeof(state->particles[0]), ++ state->whichParticle * sizeof(state->particles[0]), // Buffer data size ++ state->particles // Buffer data pointer ++ ); // Usage - Data never changes; used for drawing ++ check(); ++ ++ glUseProgram ( state->program_particle ); ++ check(); ++ // uniforms ++ const GLfloat projectionMatrix[] = { ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 0.0f, 1.0f ++ }; ++ glUniformMatrix4fv(state->uProjectionMatrix, 1, 0, projectionMatrix); ++ glUniform1i(state->uTexture, 0); // first currently bound texture "GL_TEXTURE0" ++ check(); ++ ++ // Attributes ++ glEnableVertexAttribArray(state->aPos); ++ glVertexAttribPointer(state->aPos, // Set pointer ++ 4, // One component per particle ++ GL_FLOAT, // Data is floating point type ++ GL_FALSE, // No fixed point scaling ++ sizeof(struct Particle), // No gaps in data ++ (void*)(offsetof(struct Particle, pos))); // Start from "theta" offset within bound buffer ++ ++ glEnableVertexAttribArray(state->aShade); ++ glVertexAttribPointer(state->aShade, // Set pointer ++ 4, // Three components per particle ++ GL_FLOAT, // Data is floating point type ++ GL_FALSE, // No fixed point scaling ++ sizeof(struct Particle), // No gaps in data ++ (void*)(offsetof(struct Particle, shade))); // Start from "shade" offset within bound buffer ++ ++ // Draw particles ++ glDrawArrays(GL_POINTS, 0, state->numParticles); ++ ++ glDisable(GL_BLEND); ++ glBindTexture(GL_TEXTURE_2D, 0); ++ ++ glDisableVertexAttribArray(state->aPos); ++ glDisableVertexAttribArray(state->aShade); ++ ++ glBindBuffer(GL_ARRAY_BUFFER, 0); ++ check(); ++} ++ ++//============================================================================== ++ ++static float randrange(float min, float max) ++{ ++ return min + rand() * ((max-min) / RAND_MAX); ++} ++ ++void solarwinds_init(CUBE_STATE_T *state) ++{ ++ int i; ++ state->numWinds = 1; ++ state->numEmitters = min(30, NUMEMITTERS); ++ state->numParticles = min(2000, NUM_PARTICLES); ++ state->size = 50.0f; ++ state->windSpeed = 20.0f; ++ state->emitterSpeed = 15.0f; ++ state->particleSpeed = 10.0f; ++ state->blur = 40.0f; ++ state->eVel = state->emitterSpeed * 0.01f; ++ ++ for (i = 0; i < NUMCONSTS; ++i) { ++ state->_ct[i] = randrange(0.0f, M_PI * 2.0f); ++ state->_cv[i] = randrange(0.0f, 0.00005f * state->windSpeed * state->windSpeed) + ++ 0.00001f * state->windSpeed * state->windSpeed; ++ } ++ for (i=0; i<NUMEMITTERS; i++) ++ { ++ state->emitter[i].x = randrange(0.0f, 60.0f) - 30.0f; ++ state->emitter[i].y = randrange(0.0f, 60.0f) - 30.0f, ++ state->emitter[i].z = randrange(0.0f, 30.0f) - 15.0f; ++ } ++} ++ ++void solarwinds_update(CUBE_STATE_T *state) ++{ ++ int i; ++ // update constants ++ for (i = 0; i < NUMCONSTS; ++i) { ++ state->_ct[i] += state->_cv[i]; ++ if (state->_ct[i] > M_PI * 2.0f) ++ state->_ct[i] -= M_PI * 2.0f; ++ state->_c[i] = cosf(state->_ct[i]); ++ } ++ ++ // calculate emissions ++ for (i = 0; i < state->numEmitters; ++i) { ++ // emitter moves toward viewer ++ state->emitter[i].z += state->eVel; ++ if (state->emitter[i].z > 15.0f) { // reset emitter ++ state->emitter[i].x = randrange(0.0f, 60.0f) - 30.0f; ++ state->emitter[i].y = randrange(0.0f, 60.0f) - 30.0f, ++ state->emitter[i].z = -15.0f; ++ } ++ Particle *p = state->particles + state->whichParticle; ++ p->pos[0] = state->emitter[i].x; ++ p->pos[1] = state->emitter[i].y; ++ p->pos[2] = state->emitter[i].z; ++ p->pos[3] = 1.0; ++ p->shade[3] = 1.0f; ++ ++ ++state->whichParticle; ++ if (state->whichParticle >= state->numParticles) ++ state->whichParticle = 0; ++ } ++ ++ // calculate particle positions and colors ++ // first modify constants that affect colors ++ state->_c[6] *= 9.0f / state->particleSpeed; ++ state->_c[7] *= 9.0f / state->particleSpeed; ++ state->_c[8] *= 9.0f / state->particleSpeed; ++ // then update each particle ++ float pVel = state->particleSpeed * 0.01f; ++ for (i = 0; i < state->numParticles; ++i) { ++ Particle *p = state->particles + i; ++ // store old positions ++ float x = p->pos[0]; ++ float y = p->pos[1]; ++ float z = p->pos[2]; ++ // make new positions ++ p->pos[0] = x + (state->_c[0] * y + state->_c[1] * z) * pVel; ++ p->pos[1] = y + (state->_c[2] * z + state->_c[3] * x) * pVel; ++ p->pos[2] = z + (state->_c[4] * x + state->_c[5] * y) * pVel; ++ // calculate colors ++ p->shade[0] = abs((p->pos[0] - x) * state->_c[6]); ++ p->shade[1] = abs((p->pos[1] - y) * state->_c[7]); ++ p->shade[2] = abs((p->pos[2] - z) * state->_c[8]); ++ } ++} ++ ++void solarwinds_render(CUBE_STATE_T *state) ++{ ++ draw_particle_to_texture(state); ++} ++ ++#ifdef STANDALONE ++ ++typedef struct ++{ ++ uint32_t screen_width; ++ uint32_t screen_height; ++// OpenGL|ES objects ++ EGLDisplay display; ++ EGLSurface surface; ++ EGLContext context; ++} EGL_STATE_T; ++ ++uint64_t GetTimeStamp() { ++ struct timeval tv; ++ gettimeofday(&tv,NULL); ++ return tv.tv_sec*(uint64_t)1000000+tv.tv_usec; ++} ++ ++/*********************************************************** ++ * Name: init_ogl ++ * ++ * Arguments: ++ * CUBE_STATE_T *state - holds OGLES model info ++ * ++ * Description: Sets the display, OpenGL|ES context and screen stuff ++ * ++ * Returns: void ++ * ++ ***********************************************************/ ++static void init_ogl(EGL_STATE_T *state) ++{ ++ int32_t success = 0; ++ EGLBoolean result; ++ EGLint num_config; ++ ++ static EGL_DISPMANX_WINDOW_T nativewindow; ++ ++ DISPMANX_ELEMENT_HANDLE_T dispman_element; ++ DISPMANX_DISPLAY_HANDLE_T dispman_display; ++ DISPMANX_UPDATE_HANDLE_T dispman_update; ++ VC_RECT_T dst_rect; ++ VC_RECT_T src_rect; ++ ++ static const EGLint attribute_list[] = ++ { ++ EGL_RED_SIZE, 8, ++ EGL_GREEN_SIZE, 8, ++ EGL_BLUE_SIZE, 8, ++ EGL_ALPHA_SIZE, 8, ++ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, ++ EGL_NONE ++ }; ++ ++ static const EGLint context_attributes[] = ++ { ++ EGL_CONTEXT_CLIENT_VERSION, 2, ++ EGL_NONE ++ }; ++ EGLConfig config; ++ ++ // get an EGL display connection ++ state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); ++ assert(state->display!=EGL_NO_DISPLAY); ++ check(); ++ ++ // initialize the EGL display connection ++ result = eglInitialize(state->display, NULL, NULL); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // get an appropriate EGL frame buffer configuration ++ result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // get an appropriate EGL frame buffer configuration ++ result = eglBindAPI(EGL_OPENGL_ES_API); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // create an EGL rendering context ++ state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes); ++ assert(state->context!=EGL_NO_CONTEXT); ++ check(); ++ ++ // create an EGL window surface ++ success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height); ++ assert( success >= 0 ); ++ ++ dst_rect.x = 0; ++ dst_rect.y = 0; ++ dst_rect.width = state->screen_width; ++ dst_rect.height = state->screen_height; ++ ++ src_rect.x = 0; ++ src_rect.y = 0; ++ src_rect.width = state->screen_width << 16; ++ src_rect.height = state->screen_height << 16; ++ ++ dispman_display = vc_dispmanx_display_open( 0 /* LCD */); ++ dispman_update = vc_dispmanx_update_start( 0 ); ++ ++ dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, ++ 0/*layer*/, &dst_rect, 0/*src*/, ++ &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); ++ ++ nativewindow.element = dispman_element; ++ nativewindow.width = state->screen_width; ++ nativewindow.height = state->screen_height; ++ vc_dispmanx_update_submit_sync( dispman_update ); ++ ++ check(); ++ ++ state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL ); ++ assert(state->surface != EGL_NO_SURFACE); ++ check(); ++ ++ // connect the context to the surface ++ result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); ++ assert(EGL_FALSE != result); ++ check(); ++} ++ ++int main () ++{ ++ int terminate = 0; ++ CUBE_STATE_T _state, *state=&_state; ++ EGL_STATE_T _eglstate, *eglstate=&_eglstate; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ memset( eglstate, 0, sizeof( *eglstate ) ); ++ state->verbose = 1; ++ bcm_host_init(); ++ // Start OGLES ++ init_ogl(eglstate); ++again: ++ solarwinds_init(state); ++ solarwinds_init_shaders(state); ++ ++ int frames = 0; ++ uint64_t ts = GetTimeStamp(); ++ while (!terminate) ++ { ++ solarwinds_update(state); ++ solarwinds_render(state); ++ //glFlush(); ++ //glFinish(); ++ check(); ++ ++ eglSwapBuffers(eglstate->display, eglstate->surface); ++ check(); ++ ++ frames++; ++ uint64_t ts2 = GetTimeStamp(); ++ if (ts2 - ts > 1e6) ++ { ++ printf("%d fps\n", frames); ++ ts += 1e6; ++ frames = 0; ++ } ++ } ++ solarwinds_deinit_shaders(state); ++ goto again; ++ return 0; ++} ++#endif ++ +diff --git a/xbmc/screensavers/gles/solarwinds/solarwinds.h b/xbmc/screensavers/gles/solarwinds/solarwinds.h +new file mode 100644 +index 0000000..1e9a761 +--- /dev/null ++++ b/xbmc/screensavers/gles/solarwinds/solarwinds.h +@@ -0,0 +1,60 @@ ++#pragma once ++ ++#include "GLES2/gl2.h" ++#include "EGL/egl.h" ++#include "EGL/eglext.h" ++ ++#define NUM_PARTICLES 2000 ++#define NUMCONSTS 9 ++#define NUMEMITTERS 30 ++ ++typedef struct Particle ++{ ++ GLfloat pos[4]; ++ GLfloat shade[4]; ++} Particle; ++ ++typedef struct Emitter ++{ ++ GLfloat x, y, z; ++} Emitter; ++ ++typedef struct ++{ ++ GLuint verbose; ++ GLuint mvshader; ++ GLuint mshader; ++ GLuint program_particle; ++ GLuint tex_particle; ++ GLuint particleBuffer; ++// particle attribs ++ GLuint aPos, aShade, uProjectionMatrix, uTexture; ++ ++ Emitter emitter[NUMEMITTERS]; ++ Particle particles[NUM_PARTICLES]; ++ void *tex_particle_data; ++ ++ float _c[NUMCONSTS]; ++ float _ct[NUMCONSTS]; ++ float _cv[NUMCONSTS]; ++ ++ unsigned int numWinds; ++ unsigned int numEmitters; ++ unsigned int numParticles; ++ unsigned int whichParticle; ++ float size; ++ float windSpeed; ++ float emitterSpeed; ++ float particleSpeed; ++ float blur; ++ float eVel; ++} CUBE_STATE_T; ++ ++ ++void solarwinds_init_shaders(CUBE_STATE_T *state); ++void solarwinds_init(CUBE_STATE_T *state); ++void solarwinds_update(CUBE_STATE_T *state); ++void solarwinds_render(CUBE_STATE_T *state); ++void solarwinds_deinit_shaders(CUBE_STATE_T *state); ++ ++ +diff --git a/xbmc/screensavers/gles/solarwinds/wrapper.cc b/xbmc/screensavers/gles/solarwinds/wrapper.cc +new file mode 100644 +index 0000000..edad7c7 +--- /dev/null ++++ b/xbmc/screensavers/gles/solarwinds/wrapper.cc +@@ -0,0 +1,96 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "solarwinds.h" ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ //state->width = scrprops->width; ++ //state->height = scrprops->height; ++ solarwinds_init(state); ++ solarwinds_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ solarwinds_update(state); ++ solarwinds_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ solarwinds_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/spiral/Makefile.in b/xbmc/screensavers/gles/spiral/Makefile.in +new file mode 100644 +index 0000000..5f57c7d +--- /dev/null ++++ b/xbmc/screensavers/gles/spiral/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libspiral.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.spiral/Spiral.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=spiral ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/spiral/wrapper.cc b/xbmc/screensavers/gles/spiral/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/spiral/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/stellar/Makefile.in b/xbmc/screensavers/gles/stellar/Makefile.in +new file mode 100644 +index 0000000..ef8f5b1 +--- /dev/null ++++ b/xbmc/screensavers/gles/stellar/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libstellar.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.stellar/Stellar.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=stellar ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/stellar/wrapper.cc b/xbmc/screensavers/gles/stellar/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/stellar/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/screensavers/gles/triangle2.c b/xbmc/screensavers/gles/triangle2.c +new file mode 100644 +index 0000000..6fe1155 +--- /dev/null ++++ b/xbmc/screensavers/gles/triangle2.c +@@ -0,0 +1,988 @@ ++/* ++Copyright (c) 2012, Broadcom Europe Ltd ++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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. ++*/ ++ ++// OpenGL|ES 2 demo using shader to compute plasma/render sets ++// Thanks to Peter de Rivas for original Python code ++ ++#include <stdio.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <string.h> ++#include <math.h> ++#include <assert.h> ++#include <unistd.h> ++#include <sys/time.h> ++ ++#include "triangle2.h" ++ ++#define min(a,b) ((a)<(b)?(a):(b)) ++#define max(a,b) ((a)<(b)?(b):(a)) ++#define TO_STRING(...) #__VA_ARGS__ ++ ++#define check() assert(glGetError() == 0) ++ ++static void showlog(GLint shader) ++{ ++ // Prints the compile log for a shader ++ char log[1024]; ++ glGetShaderInfoLog(shader, sizeof log, NULL, log); ++ printf("%d:shader:\n%s\n", shader, log); ++} ++ ++static void showprogramlog(GLint shader) ++{ ++ // Prints the information log for a program object ++ char log[1024]; ++ glGetProgramInfoLog(shader, sizeof log, NULL, log); ++ printf("%d:program:\n%s\n", shader, log); ++} ++ ++static void *create_particle_tex(int width, int height) ++{ ++ int i, j; ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ unsigned char *p = q; ++ for (j=0; j<height; j++) { ++ for (i=0; i<width; i++) { ++ float x = ((float)i + 0.5f) / (float)width - 0.5f; ++ float y = ((float)j + 0.5f) / (float)height - 0.5f; ++ float d = 1.0f-2.0f*sqrtf(x*x + y*y); ++ unsigned v = 255.0f * max(min(d, 1.0f), 0.0f); ++ *p++ = 255; ++ *p++ = 255; ++ *p++ = 255; ++ *p++ = v; ++ } ++ } ++ return q; ++} ++ ++static void *create_checkerboard_tex(int width, int height) ++{ ++ int i, j; ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ unsigned char *p = q; ++ for (j=0; j<height; j++) { ++ for (i=0; i<width; i++) { ++ int b = (i+j) & 1; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ } ++ } ++ return q; ++} ++ ++static void *create_border_tex(int width, int height) ++{ ++ int i, j; ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ unsigned char *p = q; ++ for (j=0; j<height; j++) { ++ for (i=0; i<width; i++) { ++ int b = i == 16 || i == 20 || i == width-1-16 || j == 16 || j == height-1-16; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ *p++ = b ? 255:0; ++ } ++ } ++ return q; ++} ++ ++static void *create_noise_tex(int width, int height) ++{ ++ int i, j; ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ unsigned char *p = q; ++ for (j=0; j<height; j++) { ++ for (i=0; i<width; i++) { ++ *p++ = (rand() >> 16) & 0xff; ++ *p++ = (rand() >> 16) & 0xff; ++ *p++ = (rand() >> 16) & 0xff; ++ *p++ = 255; ++ } ++ } ++ return q; ++} ++ ++static void *create_framebuffer_tex(int width, int height) ++{ ++#ifdef STANDALONE ++ return create_border_tex(width, height); ++#else ++ unsigned char *q = malloc(width * height * 4); ++ if (!q) ++ return NULL; ++ ++ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, q); ++ check(); ++ return q; ++#endif ++} ++ ++void screensaver_init_shaders(CUBE_STATE_T *state) ++{ ++ static const GLfloat vertex_data[] = { ++ -1.0,1.0,1.0,1.0, ++ 1.0,1.0,1.0,1.0, ++ 1.0,-1.0,1.0,1.0, ++ -1.0,-1.0,1.0,1.0, ++ }; ++ // effect ++ state->effect_vshader = glCreateShader(GL_VERTEX_SHADER); ++ glShaderSource(state->effect_vshader, 1, &state->effect_vshader_source, 0); ++ glCompileShader(state->effect_vshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->effect_vshader); ++ ++ state->effect_fshader = glCreateShader(GL_FRAGMENT_SHADER); ++ glShaderSource(state->effect_fshader, 1, &state->effect_fshader_source, 0); ++ glCompileShader(state->effect_fshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->effect_fshader); ++ ++ state->effect_program = glCreateProgram(); ++ glAttachShader(state->effect_program, state->effect_vshader); ++ glAttachShader(state->effect_program, state->effect_fshader); ++ glLinkProgram(state->effect_program); ++ glDetachShader(state->effect_program, state->effect_vshader); ++ glDetachShader(state->effect_program, state->effect_fshader); ++ glDeleteShader(state->effect_vshader); ++ glDeleteShader(state->effect_fshader); ++ check(); ++ ++ if (state->verbose) ++ showprogramlog(state->effect_program); ++ ++ state->attr_vertex = glGetAttribLocation(state->effect_program, "vertex"); ++ state->uResolution = glGetUniformLocation(state->effect_program, "iResolution"); ++ state->uMouse = glGetUniformLocation(state->effect_program, "iMouse"); ++ state->uTime = glGetUniformLocation(state->effect_program, "iGlobalTime"); ++ state->uChannel0 = glGetUniformLocation(state->effect_program, "iChannel0"); ++ state->uScale = glGetUniformLocation(state->effect_program, "uScale"); ++ check(); ++ ++ // render ++ state->render_vshader = glCreateShader(GL_VERTEX_SHADER); ++ check(); ++ glShaderSource(state->render_vshader, 1, &state->render_vshader_source, 0); ++ check(); ++ glCompileShader(state->render_vshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->render_vshader); ++ ++ state->render_fshader = glCreateShader(GL_FRAGMENT_SHADER); ++ glShaderSource(state->render_fshader, 1, &state->render_fshader_source, 0); ++ glCompileShader(state->render_fshader); ++ check(); ++ ++ if (state->verbose) ++ showlog(state->render_fshader); ++ ++ state->render_program = glCreateProgram(); ++ glAttachShader(state->render_program, state->render_vshader); ++ glAttachShader(state->render_program, state->render_fshader); ++ glLinkProgram(state->render_program); ++ glDetachShader(state->render_program, state->render_vshader); ++ glDetachShader(state->render_program, state->render_fshader); ++ glDeleteShader(state->render_vshader); ++ glDeleteShader(state->render_fshader); ++ check(); ++ ++ if (state->verbose) ++ showprogramlog(state->render_program); ++ ++ state->uTexture = glGetUniformLocation(state->render_program, "uTexture"); ++ check(); ++ ++ if (state->fbwidth && state->fbheight) ++ { ++ // Prepare a texture to render to ++ glGenTextures(1, &state->framebuffer_texture); ++ check(); ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(GL_TEXTURE_2D, state->framebuffer_texture); ++ check(); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, state->fbwidth, state->fbheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); ++ check(); ++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ check(); ++ // Prepare a framebuffer for rendering ++ glGenFramebuffers(1, &state->effect_fb); ++ check(); ++ glBindFramebuffer(GL_FRAMEBUFFER, state->effect_fb); ++ check(); ++ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, state->framebuffer_texture, 0); ++ check(); ++ glBindFramebuffer(GL_FRAMEBUFFER, 0); ++ check(); ++ } ++ // Prepare a texture image ++ if (state->effect_texture_data) ++ { ++ glGenTextures(1, &state->effect_texture); ++ check(); ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(GL_TEXTURE_2D, state->effect_texture); ++ check(); ++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, state->texwidth, state->texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, state->effect_texture_data); ++ check(); ++ } ++ // Upload vertex data to a buffer ++ glGenBuffers(1, &state->vertex_buffer); ++ glBindBuffer(GL_ARRAY_BUFFER, state->vertex_buffer); ++ glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); ++ check(); ++} ++ ++void screensaver_deinit_shaders(CUBE_STATE_T *state) ++{ ++ glDeleteProgram(state->render_program); ++ glDeleteProgram(state->effect_program); ++ check(); ++ ++ glDeleteBuffers(1, &state->vertex_buffer); ++ if (state->framebuffer_texture) ++ { ++ glDeleteTextures(1, &state->framebuffer_texture); ++ check(); ++ } ++ if (state->effect_fb) ++ { ++ glDeleteFramebuffers(1, &state->effect_fb); ++ check(); ++ } ++ if (state->effect_texture) ++ { ++ glDeleteTextures(1, &state->effect_texture); ++ check(); ++ } ++ if (state->effect_texture_data) ++ free(state->effect_texture_data); ++} ++ ++static void draw_effect_to_texture(CUBE_STATE_T *state) ++{ ++ // Draw the effect to a texture ++ if (state->effect_fb) ++ glBindFramebuffer(GL_FRAMEBUFFER, state->effect_fb); ++ else ++ glBindFramebuffer(GL_FRAMEBUFFER, 0); ++ check(); ++ ++ glBindBuffer(GL_ARRAY_BUFFER, state->vertex_buffer); ++ check(); ++ glUseProgram( state->effect_program ); ++ check(); ++ if (state->effect_texture) ++ { ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(GL_TEXTURE_2D, state->effect_texture); ++ check(); ++ //glEnable(GL_BLEND); ++ //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ++ } ++ glUniform3f(state->uResolution, state->width, state->height, 1.0f); ++ glUniform2f(state->uMouse, state->mousex, state->mousey); ++ glUniform1f(state->uTime, state->time); ++ glUniform1i(state->uChannel0, 0); // first currently bound texture "GL_TEXTURE0" ++ if (state->effect_fb) ++ glUniform2f(state->uScale, (GLfloat)state->width/state->fbwidth, (GLfloat)state->height/state->fbheight); ++ else ++ glUniform2f(state->uScale, 1.0, 1.0); ++ check(); ++ ++ glVertexAttribPointer(state->attr_vertex, 4, GL_FLOAT, 0, 16, 0); ++ glEnableVertexAttribArray(state->attr_vertex); ++ ++ glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); ++ check(); ++ ++ glDisableVertexAttribArray(state->attr_vertex); ++ glBindTexture(GL_TEXTURE_2D, 0); ++ glBindBuffer(GL_ARRAY_BUFFER, 0); ++ check(); ++} ++ ++static void draw_triangles(CUBE_STATE_T *state) ++{ ++ // already on framebuffer ++ if (!state->framebuffer_texture) ++ return; ++ // Now render to the main frame buffer ++ glBindFramebuffer(GL_FRAMEBUFFER, 0); ++ check(); ++ ++ glBindBuffer(GL_ARRAY_BUFFER, state->vertex_buffer); ++ check(); ++ glUseProgram ( state->render_program ); ++ check(); ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(GL_TEXTURE_2D, state->framebuffer_texture); ++ check(); ++ glUniform1i(state->uTexture, 0); // first currently bound texture "GL_TEXTURE0" ++ check(); ++ ++ glVertexAttribPointer(state->attr_vertex, 4, GL_FLOAT, 0, 16, 0); ++ glEnableVertexAttribArray(state->attr_vertex); ++ check(); ++ ++ glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); ++ check(); ++ ++ glDisableVertexAttribArray(state->attr_vertex); ++ glBindTexture(GL_TEXTURE_2D, 0); ++ glBindBuffer(GL_ARRAY_BUFFER, 0); ++ check(); ++} ++ ++//============================================================================== ++ ++static float randrange(float min, float max) ++{ ++ return min + rand() * ((max-min) / RAND_MAX); ++} ++ ++void screensaver_init(CUBE_STATE_T *state) ++{ ++ int i; ++ for (i = 0; i < NUMCONSTS; ++i) { ++ state->_ct[i] = randrange(0.0f, M_PI * 2.0f); ++ state->_cv[i] = randrange(0.0f, 0.00005f) + ++ 0.00001f; ++ } ++} ++ ++uint64_t GetTimeStamp() { ++ struct timeval tv; ++ gettimeofday(&tv,NULL); ++ return tv.tv_sec*(uint64_t)1000000+tv.tv_usec; ++} ++ ++void screensaver_update(CUBE_STATE_T *state) ++{ ++ int i; ++ // update constants ++ for (i = 0; i < NUMCONSTS; ++i) { ++ state->_ct[i] += state->_cv[i]; ++ if (state->_ct[i] > M_PI * 2.0f) ++ state->_ct[i] -= M_PI * 2.0f; ++ state->_c[i] = cosf(state->_ct[i]); ++ } ++ uint64_t t = GetTimeStamp(); ++ if (state->last_time) ++ state->time += (t-state->last_time) * 1e-6; ++ state->last_time = t; ++ //if (state->time > 12.0f + M_PI) ++ // state->time -= 12.0f * M_PI; ++} ++ ++void screensaver_render(CUBE_STATE_T *state) ++{ ++ draw_effect_to_texture(state); ++ draw_triangles(state); ++} ++ ++void setup_screensaver_default(CUBE_STATE_T *state) ++{ ++ state->effect_vshader_source = TO_STRING( ++ attribute vec4 vertex; ++ varying vec2 vTextureCoord; ++ uniform vec2 uScale; ++ void main(void) ++ { ++ gl_Position = vertex; ++ vTextureCoord = vertex.xy*0.5+0.5; ++ vTextureCoord.x = vTextureCoord.x * uScale.x; ++ vTextureCoord.y = vTextureCoord.y * uScale.y; ++ } ++ ); ++ state->effect_fshader_source = TO_STRING( ++ varying vec2 vTextureCoord; ++ uniform float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ); ++ state->render_vshader_source = TO_STRING( ++ attribute vec4 vertex; ++ varying vec2 vTextureCoord; ++ void main(void) ++ { ++ gl_Position = vertex; ++ vTextureCoord = vertex.xy*0.5+0.5; ++ } ++ ); ++ state->render_fshader_source = TO_STRING( ++ varying vec2 vTextureCoord; ++ uniform sampler2D uTexture; ++ void main(void) ++ { ++ gl_FragColor = texture2D(uTexture, vTextureCoord); ++ //gl_FragColor = vec4(vTextureCoord.x, vTextureCoord.y, 0.0, 1.0); ++ } ++ ); ++} ++ ++void setup_screensaver_plasma(CUBE_STATE_T *state) ++{ ++ state->fbwidth = 960; state->fbheight = 540; ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float u_time=iGlobalTime*0.2; ++ vec2 u_k = vec2(32.0, 32.0); ++ precision mediump float; ++ const float PI=3.1415926535897932384626433832795; ++ void main() ++ { ++ float v = 0.0; ++ vec2 c = vTextureCoord * u_k - u_k/2.0; ++ v += sin((c.x+u_time)); ++ v += sin((c.y+u_time)/2.0); ++ v += sin((c.x+c.y+u_time)/2.0); ++ c += u_k/2.0 * vec2(sin(u_time/3.0), cos(u_time/2.0)); ++ v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+u_time); ++ v = v/2.0; ++ vec3 col = vec3(1.0, sin(PI*v), cos(PI*v)); ++ gl_FragColor = vec4(col*0.5 + 0.5, 1.0); ++ } ++ ); ++} ++ ++ ++void setup_screensaver_plasma2(CUBE_STATE_T *state) ++{ ++ state->fbwidth = 640; state->fbheight = 360; ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float u_time=iGlobalTime*0.2; ++ vec2 u_k = vec2(32.0, 32.0); ++ precision mediump float; ++ const float PI=3.1415926535897932384626433832795; ++ ++ void mainImage( out vec4 fragColor, in vec2 fragCoord ) ++ { ++ vec2 p = -1.0 + 2.0 * fragCoord.xy / iResolution.xy; ++ ++ // main code, *original shader by: 'Plasma' by Viktor Korsun (2011) ++ float x = p.x; ++ float y = p.y; ++ float mov0 = x+y+cos(sin(iGlobalTime)*2.0)*100.+sin(x/100.)*1000.; ++ float mov1 = y / 0.9 + iGlobalTime; ++ float mov2 = x / 0.2; ++ float c1 = abs(sin(mov1+iGlobalTime)/2.+mov2/2.-mov1-mov2+iGlobalTime); ++ float c2 = abs(sin(c1+sin(mov0/1000.+iGlobalTime)+sin(y/40.+iGlobalTime)+sin((x+y)/100.)*3.)); ++ float c3 = abs(sin(c2+cos(mov1+mov2+c2)+cos(mov2)+sin(x/1000.))); ++ fragColor = vec4(c1,c2,c3,1.0); ++ ++ } ++ ++ void main () { ++ vec4 fragColor; ++ vec2 fragCoord = vTextureCoord * vec2(iResolution.x, iResolution.y); ++ mainImage(fragColor, fragCoord); ++ gl_FragColor = fragColor; ++ gl_FragColor.a = 1.0; ++ } ++ ); ++} ++ ++ ++void setup_screensaver_border(CUBE_STATE_T *state) ++{ ++ state->texwidth = state->texheight = 256; ++ state->fbwidth = state->fbheight = 256; ++ state->effect_texture_data = create_border_tex(state->texwidth, state->texheight); ++ state->effect_fshader_source = TO_STRING( ++ varying vec2 vTextureCoord; ++ uniform float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ void main(void) ++ { ++ vec2 v = vTextureCoord; ++ vec4 texture = texture2D(iChannel0, v); ++ gl_FragColor = texture; ++ } ++ ); ++} ++ ++ ++void setup_screensaver_spiral(CUBE_STATE_T *state) ++{ ++ state->fbwidth = 800; state->fbheight = 450; ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float u_time=iGlobalTime*0.2; ++ vec2 u_k = vec2(32.0, 32.0); ++ precision mediump float; ++ const float PI=3.1415926535897932384626433832795; ++ const float TAU=6.283185307179586; ++ ++ void mainImage( out vec4 fragColor, in vec2 fragCoord ) ++ { ++ vec2 p = 2.0*(0.5 * iResolution.xy - fragCoord.xy) / iResolution.xx; ++ float angle = atan(p.y, p.x); ++ float turn = (angle + PI) / TAU; ++ float radius = sqrt(p.x*p.x + p.y*p.y); ++ ++ float rotation = 0.04 * TAU * iGlobalTime; ++ float turn_1 = turn + rotation; ++ ++ float n_sub = 2.0; ++ ++ float turn_sub = mod(float(n_sub) * turn_1, float(n_sub)); ++ ++ float k_sine = 0.1 * sin(3.0 * iGlobalTime); ++ float sine = k_sine * sin(50.0 * (pow(radius, 0.1) - 0.4 * iGlobalTime)); ++ float turn_sine = turn_sub + sine; ++ ++ int n_colors = 5; ++ int i_turn = int(mod(float(n_colors) * turn_sine, float(n_colors))); ++ ++ int i_radius = int(1.5/pow(radius*0.5, 0.6) + 5.0 * iGlobalTime); ++ ++ int i_color = int(mod(float(i_turn + i_radius), float(n_colors))); ++ ++ vec3 color; ++ if(i_color == 0) { ++ color = vec3(1.0, 1.0, 1.0); ++ } else if(i_color == 1) { ++ color = vec3(0.0, 0.0, 0.0); ++ } else if(i_color == 2) { ++ color = vec3(1.0, 0.0, 0.0); ++ } else if(i_color == 3) { ++ color = vec3(1.0, 0.5, 0.0); ++ } else if(i_color == 4) { ++ color = vec3(1.0, 1.0, 0.0); ++ } ++ ++ color *= pow(radius, 0.5)*1.0; ++ ++ fragColor = vec4(color, 1.0); ++ } ++ ++ void main () { ++ vec4 fragColor; ++ vec2 fragCoord = vTextureCoord * vec2(iResolution.x, iResolution.y); ++ mainImage(fragColor, fragCoord); ++ gl_FragColor = fragColor; ++ gl_FragColor.a = 1.0; ++ } ++ ); ++} ++ ++void setup_screensaver_ball(CUBE_STATE_T *state) ++{ ++ state->texwidth = state->width; ++ state->texheight = state->height; ++ state->fbwidth = 960; ++ state->fbheight = 540; ++ state->effect_texture_data = create_framebuffer_tex(state->texwidth, state->texheight); ++ ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float u_time=iGlobalTime*0.2; ++ vec2 u_k = vec2(32.0, 32.0); ++ precision mediump float; ++ const float PI=3.1415926535897932384626433832795; ++ ++ // by maq/floppy ++ const float R=0.2; // to play ++ void mainImage( out vec4 fragColor, in vec2 fragCoord ) ++ { ++ vec3 col; ++ vec2 uv = -0.5+fragCoord.xy / iResolution.xy; ++ uv.y*=0.66; // hack to get ar nice on 16:10 ++ vec2 p = uv; ++ float d=sqrt(dot(p,p)); ++ float fac,fac2; ++ if(d<R) ++ { ++ uv.x=p.x/(R+sqrt(R-d)); ++ uv.y=p.y/(R+sqrt(R-d)); ++ fac = 0.005; ++ fac2 = 5.0; ++ } ++ else ++ { ++ uv.x=p.x/(d*d); ++ uv.y=p.y/(d*d); ++ fac = 0.02; ++ fac2 = 25.0; ++ } ++ ++ uv.x=uv.x-iMouse.x*fac+fac*500.0*sin(0.2*iGlobalTime); ++ uv.y=uv.y-iMouse.y*fac+fac*500.0*sin(0.4*iGlobalTime); ++ col = texture2D(iChannel0, uv/fac2).xyz; ++ col = col*exp(-3.0*(d-R)); // some lighting ++ col = col*(1.1-exp(-8.0*(abs(d-R)))); // and shading ++ ++ ++ fragColor = vec4(col,1.0); ++ } ++ void main () { ++ vec4 fragColor; ++ vec2 fragCoord = vTextureCoord * vec2(iResolution.x, iResolution.y); ++ mainImage(fragColor, fragCoord); ++ gl_FragColor = fragColor; ++ gl_FragColor.a = 1.0; ++ } ++ ); ++} ++ ++ ++void setup_screensaver_stellar(CUBE_STATE_T *state) ++{ ++ state->texwidth = 256; state->texheight = 256; ++ state->effect_texture_data = create_noise_tex(state->texwidth, state->texheight); ++ state->fbwidth = 640; state->fbheight = 360; ++ ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ const float tau = 6.28318530717958647692; ++ vec4 Noise( in ivec2 x ) ++ { ++ return texture2D( iChannel0, (vec2(x)+0.5)/256.0, -100.0 ); ++ } ++ void main() ++ { ++ vec3 ray = vec3(vTextureCoord - vec2(0.5), 1.0); ++ float offset = iGlobalTime*.5; ++ float speed2 = (cos(offset)+1.0)*2.0; ++ float speed = speed2+.1; ++ float ispeed = 1.0/speed; ++ offset += sin(offset)*.96; ++ offset *= 2.0; ++ vec3 col = vec3(0); ++ vec3 stp = ray/max(abs(ray.x),abs(ray.y)); ++ vec3 pos = 2.0*stp+.5; ++ for ( int i=0; i < 10; i++ ) ++ { ++ float z = Noise(ivec2(pos.xy)).x; ++ z = fract(z-offset); ++ float d = 50.0*z-pos.z; ++ float w = max(0.0, 1.0-8.0*length(fract(pos.xy)-.5)); ++ vec3 c = max(vec3(0), vec3(1.0-abs(d+speed2*.5)*ispeed,1.0-abs(d)*ispeed,1.0-abs(d-speed2*.5)*ispeed)); ++ col += 1.5*(1.0-z)*c*w*w; ++ pos += stp; ++ } ++ gl_FragColor = vec4(col,1.0); ++ } ++ ); ++} ++ ++void setup_screensaver_noise(CUBE_STATE_T *state) ++{ ++ state->fbwidth = 960; state->fbheight = 540; ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float time=iGlobalTime*0.1; ++ float pi = 3.14159265; ++ ++ float rand(vec2 co) ++ { ++ return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); ++ } ++ ++ void main() ++ { ++ float r = rand(vec2(1.0*iGlobalTime+vTextureCoord.x, 3.0*iGlobalTime+vTextureCoord.y)); ++ float g = rand(vec2(2.0*iGlobalTime+vTextureCoord.x, 2.0*iGlobalTime+vTextureCoord.y)); ++ float b = rand(vec2(3.0*iGlobalTime+vTextureCoord.x, 1.0*iGlobalTime+vTextureCoord.y)); ++ gl_FragColor = vec4(r, g, b, 1.0); ++ } ++ ); ++} ++ ++void setup_screensaver_warp(CUBE_STATE_T *state) ++{ ++ state->texwidth = state->width; ++ state->texheight = state->height; ++ state->fbwidth = 800; ++ state->fbheight = 450; ++ state->effect_texture_data = create_framebuffer_tex(state->texwidth, state->texheight); ++ ++ state->effect_fshader_source = TO_STRING( ++ precision lowp float; ++ varying vec2 vTextureCoord; ++ uniform highp float iGlobalTime; ++ uniform vec3 iResolution; ++ uniform vec2 iMouse; ++ uniform sampler2D iChannel0; ++ ++ float time=iGlobalTime*0.1; ++ const float pi = 3.14159265; ++ const float sin_4000 = 0.6427876097; ++ const float cos_4000 = 0.7660444431; ++ const float sin_6000 = -0.8660254038; ++ const float cos_6000 = -0.5; ++ ++ void main() ++ { ++ float s = sin(time); ++ float c = cos(time); ++ float s2 = 2.0*s*c; ++ float c2 = 1.0-2.0*s*s; ++ float s3 = s2*c + c2*s; ++ float c3 = c2*c - s2*s; ++ float ss = s2*cos_4000 + c2*sin_4000; ++ float cc = c3*cos_6000 - s3*sin_6000; ++ vec2 offset2 = vec2(6.0*sin(time*1.1), 3.0*cos(time*1.1)); ++ vec2 oldPos = vTextureCoord.xy - vec2(0.5, 0.5); ++ vec2 newPos = vec2(oldPos.x * c2 - oldPos.y * s2, ++ oldPos.y * c2 + oldPos.x * s2); ++ newPos = newPos*(1.0+0.2*s3) - offset2; ++ vec2 temp = newPos; ++ float beta = sin(temp.y*2.0 + time*8.0); ++ newPos.x = temp.x + 0.4*beta; ++ newPos.y = temp.y - 0.4*beta; ++ gl_FragColor = texture2D(iChannel0, newPos); ++ } ++ ); ++} ++ ++#ifdef STANDALONE ++ ++typedef struct ++{ ++ uint32_t screen_width; ++ uint32_t screen_height; ++// OpenGL|ES objects ++ EGLDisplay display; ++ EGLSurface surface; ++ EGLContext context; ++} EGL_STATE_T; ++ ++/*********************************************************** ++ * Name: init_ogl ++ * ++ * Arguments: ++ * CUBE_STATE_T *state - holds OGLES model info ++ * ++ * Description: Sets the display, OpenGL|ES context and screen stuff ++ * ++ * Returns: void ++ * ++ ***********************************************************/ ++static void init_ogl(EGL_STATE_T *state) ++{ ++ int32_t success = 0; ++ EGLBoolean result; ++ EGLint num_config; ++ ++ static EGL_DISPMANX_WINDOW_T nativewindow; ++ ++ DISPMANX_ELEMENT_HANDLE_T dispman_element; ++ DISPMANX_DISPLAY_HANDLE_T dispman_display; ++ DISPMANX_UPDATE_HANDLE_T dispman_update; ++ VC_RECT_T dst_rect; ++ VC_RECT_T src_rect; ++ ++ static const EGLint attribute_list[] = ++ { ++ EGL_RED_SIZE, 8, ++ EGL_GREEN_SIZE, 8, ++ EGL_BLUE_SIZE, 8, ++ EGL_ALPHA_SIZE, 8, ++ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, ++ EGL_NONE ++ }; ++ ++ static const EGLint context_attributes[] = ++ { ++ EGL_CONTEXT_CLIENT_VERSION, 2, ++ EGL_NONE ++ }; ++ EGLConfig config; ++ ++ // get an EGL display connection ++ state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); ++ assert(state->display!=EGL_NO_DISPLAY); ++ check(); ++ ++ // initialize the EGL display connection ++ result = eglInitialize(state->display, NULL, NULL); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // get an appropriate EGL frame buffer configuration ++ result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // get an appropriate EGL frame buffer configuration ++ result = eglBindAPI(EGL_OPENGL_ES_API); ++ assert(EGL_FALSE != result); ++ check(); ++ ++ // create an EGL rendering context ++ state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes); ++ assert(state->context!=EGL_NO_CONTEXT); ++ check(); ++ ++ // create an EGL window surface ++ success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height); ++ assert( success >= 0 ); ++ ++ dst_rect.x = 0; ++ dst_rect.y = 0; ++ dst_rect.width = state->screen_width; ++ dst_rect.height = state->screen_height; ++ ++ src_rect.x = 0; ++ src_rect.y = 0; ++ src_rect.width = state->screen_width << 16; ++ src_rect.height = state->screen_height << 16; ++ ++ dispman_display = vc_dispmanx_display_open( 0 /* LCD */); ++ dispman_update = vc_dispmanx_update_start( 0 ); ++ ++ dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, ++ 0/*layer*/, &dst_rect, 0/*src*/, ++ &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); ++ ++ nativewindow.element = dispman_element; ++ nativewindow.width = state->screen_width; ++ nativewindow.height = state->screen_height; ++ vc_dispmanx_update_submit_sync( dispman_update ); ++ ++ check(); ++ ++ state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL ); ++ assert(state->surface != EGL_NO_SURFACE); ++ check(); ++ ++ // connect the context to the surface ++ result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); ++ assert(EGL_FALSE != result); ++ check(); ++} ++ ++int main () ++{ ++ int terminate = 0; ++ CUBE_STATE_T _state, *state=&_state; ++ EGL_STATE_T _eglstate, *eglstate=&_eglstate; ++ ++ // Clear application state ++ memset( eglstate, 0, sizeof( *eglstate ) ); ++ bcm_host_init(); ++ // Start OGLES ++ init_ogl(eglstate); ++again: ++ memset( state, 0, sizeof( *state ) ); ++ state->verbose = 1; ++ state->width = eglstate->screen_width; ++ state->height = eglstate->screen_height; ++ setup_screensaver_default(state); ++ setup_screensaver_warp(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ int frames = 0; ++ uint64_t ts = GetTimeStamp(); ++ while (!terminate) ++ { ++ screensaver_update(state); ++ screensaver_render(state); ++ eglSwapBuffers(eglstate->display, eglstate->surface); ++ check(); ++ ++ frames++; ++ uint64_t ts2 = GetTimeStamp(); ++ if (ts2 - ts > 1e6) ++ { ++ printf("%d fps (%.3f)\n", frames, state->time); ++ ts += 1e6; ++ frames = 0; ++ //break; ++ } ++ } ++ screensaver_deinit_shaders(state); ++ goto again; ++ return 0; ++} ++#endif ++ +diff --git a/xbmc/screensavers/gles/triangle2.h b/xbmc/screensavers/gles/triangle2.h +new file mode 100644 +index 0000000..6088203 +--- /dev/null ++++ b/xbmc/screensavers/gles/triangle2.h +@@ -0,0 +1,64 @@ ++#pragma once ++ ++#include "GLES2/gl2.h" ++#include "EGL/egl.h" ++#include "EGL/eglext.h" ++ ++#define NUMCONSTS 9 ++ ++typedef struct ++{ ++ GLuint verbose; ++ GLuint effect_vshader; ++ GLuint effect_fshader; ++ GLuint render_vshader; ++ GLuint render_fshader; ++ GLuint effect_program; ++ GLuint render_program; ++ GLuint effect_fb; ++ GLuint framebuffer_texture; ++ GLuint vertex_buffer; ++ GLuint effect_texture; ++ void *effect_texture_data; ++// effect attribs ++ GLuint uTime, uScale, uResolution, uMouse; ++ GLuint uChannel0; ++// render attribs ++ GLuint attr_vertex, uTexture; ++ uint64_t last_time; ++ float _c[NUMCONSTS]; ++ float _ct[NUMCONSTS]; ++ float _cv[NUMCONSTS]; ++ ++// config settings ++ int width, height; ++ int texwidth, texheight; ++ int fbwidth, fbheight; ++ int mousex, mousey; ++ float time; ++ const GLchar *effect_vshader_source; ++ const GLchar *effect_fshader_source; ++ const GLchar *render_vshader_source; ++ const GLchar *render_fshader_source; ++ ++} CUBE_STATE_T; ++ ++ ++void screensaver_init_shaders(CUBE_STATE_T *state); ++void screensaver_init(CUBE_STATE_T *state); ++void screensaver_update(CUBE_STATE_T *state); ++void screensaver_render(CUBE_STATE_T *state); ++void screensaver_deinit_shaders(CUBE_STATE_T *state); ++ ++void setup_screensaver_default(CUBE_STATE_T *state); ++void setup_screensaver_warp(CUBE_STATE_T *state); ++void setup_screensaver_plasma(CUBE_STATE_T *state); ++void setup_screensaver_plasma2(CUBE_STATE_T *state); ++void setup_screensaver_noise(CUBE_STATE_T *state); ++void setup_screensaver_border(CUBE_STATE_T *state); ++void setup_screensaver_stellar(CUBE_STATE_T *state); ++void setup_screensaver_spiral(CUBE_STATE_T *state); ++void setup_screensaver_ball(CUBE_STATE_T *state); ++ ++ ++ +diff --git a/xbmc/screensavers/gles/warp/Makefile.in b/xbmc/screensavers/gles/warp/Makefile.in +new file mode 100644 +index 0000000..4406b4a +--- /dev/null ++++ b/xbmc/screensavers/gles/warp/Makefile.in +@@ -0,0 +1,36 @@ ++ARCH=@ARCH@ ++CXXFLAGS=-fPIC ++ifeq (@USE_ANDROID@,1) ++SLIB = @abs_top_srcdir@/system/libwarp.so ++else ++SLIB = @abs_top_srcdir@/addons/screensaver.gles.warp/Warp.xbs ++endif ++OBJS = wrapper.o ++DEFINES += -DSCREENSAVER=warp ++ ++ifeq (@USE_OPENGLES@,1) ++ DEFINES += -DHAS_GLES=2 ++ INCLUDES+= -I@abs_top_srcdir@/xbmc/screensavers/gles ++ OBJS += @abs_top_srcdir@/xbmc/screensavers/gles/gleshelpers.a ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGLES ++ else ++ LDFLAGS += -lGLESv2 ++ endif ++else ++ DEFINES += -DHAS_GL ++ ifeq ($(findstring osx,$(ARCH)), osx) ++ LDFLAGS += -framework OpenGL ++ else ++ LDFLAGS += -lGL ++ endif ++endif ++ ++$(SLIB): $(OBJS) ++ifeq ($(findstring osx,$(ARCH)), osx) ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -bundle -o $(SLIB) $(OBJS) ++else ++ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(SLIB) $(OBJS) ++endif ++ ++include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/screensavers/gles/warp/wrapper.cc b/xbmc/screensavers/gles/warp/wrapper.cc +new file mode 100644 +index 0000000..fd58b73 +--- /dev/null ++++ b/xbmc/screensavers/gles/warp/wrapper.cc +@@ -0,0 +1,102 @@ ++#include <stdio.h> ++#include <assert.h> ++#include "Application.h" ++#include "../../addons/include/xbmc_scr_dll.h" ++ ++extern "C" { ++ ++#include "triangle2.h" ++ ++#define PASTER(x,y) x ## _ ## y ++#define EVALUATOR(x,y) PASTER(x,y) ++#define NAME(fun) EVALUATOR(fun, SCREENSAVER) ++ ++static CUBE_STATE_T _state, *state=&_state; ++ ++ADDON_STATUS ADDON_Create(void* hdl, void* props) ++{ ++ if (!props) ++ return ADDON_STATUS_UNKNOWN; ++ ++ // Clear application state ++ memset( state, 0, sizeof( *state ) ); ++ // Start OGLES ++ assert( g_application.IsCurrentThread() ); ++ glGetError(); ++ ++ SCR_PROPS* scrprops = (SCR_PROPS*)props; ++ state->width = scrprops->width; ++ state->height = scrprops->height; ++ setup_screensaver_default(state); ++ NAME(setup_screensaver)(state); ++ screensaver_init(state); ++ screensaver_init_shaders(state); ++ ++ return ADDON_STATUS_OK; ++} ++ ++void Start() ++{ ++} ++ ++void Render() ++{ ++ screensaver_update(state); ++ screensaver_render(state); ++} ++ ++void ADDON_Stop() ++{ ++ screensaver_deinit_shaders(state); ++} ++ ++void ADDON_Destroy() ++{ ++} ++ ++ADDON_STATUS ADDON_GetStatus() ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++bool ADDON_HasSettings() ++{ ++puts(__func__); ++ return false; ++} ++ ++unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) ++{ ++puts(__func__); ++ return 0; ++} ++ ++ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) ++{ ++puts(__func__); ++ return ADDON_STATUS_OK; ++} ++ ++void ADDON_FreeSettings() ++{ ++puts(__func__); ++} ++ ++void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) ++{ ++puts(__func__); ++} ++ ++void GetInfo(SCR_INFO *info) ++{ ++puts(__func__); ++} ++ ++void Remove() ++{ ++puts(__func__); ++} ++ ++} ++ +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 8e39d8c..da9db10 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -26,7 +26,6 @@ + #include <vector> + + #include "addons/AudioDecoder.h" +-#include "addons/BinaryAddonCache.h" + #include "addons/IAddon.h" + #include "Application.h" + #include "ServiceBroker.h" +@@ -121,7 +120,8 @@ void CAdvancedSettings::Initialize() + m_limiterHold = 0.025f; + m_limiterRelease = 0.1f; + +- m_seekSteps = { 10, 30, 60, 180, 300, 600, 1800 }; ++ int t[] = { 10, 30, 60, 180, 300, 600, 1800 }; ++ m_seekSteps.assign(t, t + sizeof(t)/sizeof(t[0])); + + m_omxDecodeStartWithValidFrame = true; + +@@ -151,6 +151,7 @@ void CAdvancedSettings::Initialize() + m_videoNonLinStretchRatio = 0.5f; + m_videoEnableHighQualityHwScalers = false; + m_videoAutoScaleMaxFps = 30.0f; ++ m_videoDisableBackgroundDeinterlace = false; + m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect + m_videoVDPAUtelecine = false; + m_videoVDPAUdeintSkipChromaHD = false; +@@ -384,7 +385,7 @@ void CAdvancedSettings::Initialize() + m_databaseMusic.Reset(); + m_databaseVideo.Reset(); + +- m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.rss|.webp|.jp2|.apng"; ++ m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss|.webp|.jp2|.apng"; + m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.gdm|.imf|.m15|.sfx|.uni|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.dsp|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.wtv|.mka|.tak|.opus|.dff|.dsf"; + m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.mpd|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.mk3d|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv"; + m_subtitlesExtensions = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.text|.ssa|.aqt|.jss|.ass|.idx|.ifo|.rar|.zip"; +@@ -556,6 +557,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) + XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f); + XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers); + XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f); ++ XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); + XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); + XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); + XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); +@@ -905,8 +907,8 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) + m_vecTokens.clear(); + CLangInfo::LoadTokens(pRootElement->FirstChild("sorttokens"),m_vecTokens); + +- //! @todo Should cache path be given in terms of our predefined paths?? +- //! Are we even going to have predefined paths?? ++ // TODO: Should cache path be given in terms of our predefined paths?? ++ // Are we even going to have predefined paths?? + std::string tmp; + if (XMLUtils::GetPath(pRootElement, "cachepath", tmp)) + m_cachePath = tmp; +@@ -1342,6 +1344,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + list.push_back(std::make_pair(g_localizeStrings.Get(672), LOGFFMPEG)); + list.push_back(std::make_pair(g_localizeStrings.Get(676), LOGAUDIO)); + list.push_back(std::make_pair(g_localizeStrings.Get(680), LOGVIDEO)); ++ list.push_back(std::make_pair(g_localizeStrings.Get(10525), LOGPVR)); ++#ifdef HAS_LIBRTMP ++ list.push_back(std::make_pair(g_localizeStrings.Get(673), LOGRTMP)); ++#endif + #ifdef HAS_DBUS + list.push_back(std::make_pair(g_localizeStrings.Get(674), LOGDBUS)); + #endif +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index 76fb7ef..3cac9eb 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -185,6 +185,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + std::vector<RefreshOverride> m_videoAdjustRefreshOverrides; + std::vector<RefreshVideoLatency> m_videoRefreshLatency; + float m_videoDefaultLatency; ++ bool m_videoDisableBackgroundDeinterlace; + int m_videoCaptureUseOcclusionQuery; + bool m_DXVACheckCompatibility; + bool m_DXVACheckCompatibilityPresent; +diff --git a/xbmc/settings/AudioDSPSettings.cpp b/xbmc/settings/AudioDSPSettings.cpp +index c2356d7..179bde2 100644 +--- a/xbmc/settings/AudioDSPSettings.cpp ++++ b/xbmc/settings/AudioDSPSettings.cpp +@@ -22,7 +22,7 @@ + ////////////////////////////////////////////////////////////////////// + + #include "AudioDSPSettings.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h" + + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index 363757d..6ce42fa 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -501,7 +501,7 @@ void CDisplaySettings::UpdateCalibrations() + { + if (StringUtils::EqualsNoCase(itCal->strMode, m_resolutions[res].strMode)) + { +- //! @todo erase calibrations with default values ++ // TODO: erase calibrations with default values + *itCal = m_resolutions[res]; + found = true; + break; +@@ -591,16 +591,10 @@ std::string CDisplaySettings::GetStringFromResolution(RESOLUTION resolution, flo + if (resolution >= RES_DESKTOP && resolution < (RESOLUTION)CDisplaySettings::GetInstance().ResolutionInfoSize()) + { + const RESOLUTION_INFO &info = CDisplaySettings::GetInstance().GetResolutionInfo(resolution); +- // also handle RES_DESKTOP resolutions with non-default refresh rates +- if (resolution != RES_DESKTOP || (refreshrate > 0.0f && refreshrate != info.fRefreshRate)) +- { +- return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen, +- info.iScreenWidth, info.iScreenHeight, +- refreshrate > 0.0f ? refreshrate : info.fRefreshRate, ModeFlagsToString(info.dwFlags, true).c_str()); +- } ++ return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen, ++ info.iScreenWidth, info.iScreenHeight, ++ refreshrate > 0.0f ? refreshrate : info.fRefreshRate, ModeFlagsToString(info.dwFlags, true).c_str()); + } +- +- return "DESKTOP"; + } + + RESOLUTION CDisplaySettings::GetResolutionForScreen() +@@ -673,7 +667,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, + std::vector<RESOLUTION_WHR> resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate); + for (std::vector<RESOLUTION_WHR>::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution) + { +- list.push_back(std::make_pair( ++ if (resolution->ResInfo_Index == RES_DESKTOP) ++ continue; ++ list.push_back(make_pair( + StringUtils::Format("%dx%d%s", resolution->width, resolution->height, + ModeFlagsToString(resolution->flags, false).c_str()), + resolution->ResInfo_Index)); +diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp +index 859a3b8..4b17ef6 100644 +--- a/xbmc/settings/MediaSettings.cpp ++++ b/xbmc/settings/MediaSettings.cpp +@@ -42,7 +42,7 @@ + #include "utils/XMLUtils.h" + #include "utils/Variant.h" + #include "video/VideoDatabase.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + + using namespace KODI::MESSAGING; + +diff --git a/xbmc/settings/MediaSourceSettings.cpp b/xbmc/settings/MediaSourceSettings.cpp +index eabe0df..d4f725e 100644 +--- a/xbmc/settings/MediaSourceSettings.cpp ++++ b/xbmc/settings/MediaSourceSettings.cpp +@@ -118,7 +118,7 @@ bool CMediaSourceSettings::Save() + + bool CMediaSourceSettings::Save(const std::string &file) const + { +- //! @todo Should we be specifying utf8 here?? ++ // TODO: Should we be specifying utf8 here?? + CXBMCTinyXML doc; + TiXmlElement xmlRootElement(XML_SOURCES); + TiXmlNode *pRoot = doc.InsertEndChild(xmlRootElement); +diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp +index 1d9e02b..5ed7391 100644 +--- a/xbmc/settings/Settings.cpp ++++ b/xbmc/settings/Settings.cpp +@@ -182,6 +182,10 @@ const std::string CSettings::SETTING_VIDEOPLAYER_USEMMAL = "videoplayer.usemmal" + const std::string CSettings::SETTING_VIDEOPLAYER_USESTAGEFRIGHT = "videoplayer.usestagefright"; + const std::string CSettings::SETTING_VIDEOPLAYER_LIMITGUIUPDATE = "videoplayer.limitguiupdate"; + const std::string CSettings::SETTING_VIDEOPLAYER_SUPPORTMVC = "videoplayer.supportmvc"; ++const std::string CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTION = "videoplayer.adjustresolution"; ++const std::string CSettings::SETTING_VIDEOPLAYER_ADJUSTRESOLUTIONINTERLACED = "videoplayer.adjustresolutioninterlaced"; ++const std::string CSettings::SETTING_VIDEOPLAYER_MINIMUMVERTICAL = "videoplayer.minimumvertical"; ++const std::string CSettings::SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA = "videoplayer.adjustallownoncea"; + const std::string CSettings::SETTING_MYVIDEOS_SELECTACTION = "myvideos.selectaction"; + const std::string CSettings::SETTING_MYVIDEOS_EXTRACTFLAGS = "myvideos.extractflags"; + const std::string CSettings::SETTING_MYVIDEOS_EXTRACTCHAPTERTHUMBS = "myvideos.extractchapterthumbs"; +@@ -216,6 +220,7 @@ const std::string CSettings::SETTING_ACCESSIBILITY_SUBHEARING = "accessibility.s + const std::string CSettings::SETTING_SCRAPERS_MOVIESDEFAULT = "scrapers.moviesdefault"; + const std::string CSettings::SETTING_SCRAPERS_TVSHOWSDEFAULT = "scrapers.tvshowsdefault"; + const std::string CSettings::SETTING_SCRAPERS_MUSICVIDEOSDEFAULT = "scrapers.musicvideosdefault"; ++const std::string CSettings::SETTING_PVRMANAGER_ENABLED = "pvrmanager.enabled"; + const std::string CSettings::SETTING_PVRMANAGER_HIDECONNECTIONLOSTWARNING = "pvrmanager.hideconnectionlostwarning"; + const std::string CSettings::SETTING_PVRMANAGER_SYNCCHANNELGROUPS = "pvrmanager.syncchannelgroups"; + const std::string CSettings::SETTING_PVRMANAGER_BACKENDCHANNELORDER = "pvrmanager.backendchannelorder"; +@@ -242,7 +247,6 @@ const std::string CSettings::SETTING_PVRPLAYBACK_SCANTIME = "pvrplayback.scantim + const std::string CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH = "pvrplayback.confirmchannelswitch"; + const std::string CSettings::SETTING_PVRPLAYBACK_CHANNELENTRYTIMEOUT = "pvrplayback.channelentrytimeout"; + const std::string CSettings::SETTING_PVRPLAYBACK_FPS = "pvrplayback.fps"; +-const std::string CSettings::SETTING_PVRRECORD_INSTANTRECORDACTION = "pvrrecord.instantrecordaction"; + const std::string CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME = "pvrrecord.instantrecordtime"; + const std::string CSettings::SETTING_PVRRECORD_DEFAULTPRIORITY = "pvrrecord.defaultpriority"; + const std::string CSettings::SETTING_PVRRECORD_DEFAULTLIFETIME = "pvrrecord.defaultlifetime"; +@@ -295,6 +299,7 @@ const std::string CSettings::SETTING_AUDIOCDS_TRACKPATHFORMAT = "audiocds.trackp + const std::string CSettings::SETTING_AUDIOCDS_ENCODER = "audiocds.encoder"; + const std::string CSettings::SETTING_AUDIOCDS_SETTINGS = "audiocds.settings"; + const std::string CSettings::SETTING_AUDIOCDS_EJECTONRIP = "audiocds.ejectonrip"; ++const std::string CSettings::SETTING_MYMUSIC_STARTWINDOW = "mymusic.startwindow"; + const std::string CSettings::SETTING_MYMUSIC_SONGTHUMBINVIS = "mymusic.songthumbinvis"; + const std::string CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW = "mymusic.defaultlibview"; + const std::string CSettings::SETTING_PICTURES_GENERATETHUMBS = "pictures.generatethumbs"; +@@ -345,6 +350,7 @@ const std::string CSettings::SETTING_VIDEOSCREEN_GUICALIBRATION = "videoscreen.g + const std::string CSettings::SETTING_VIDEOSCREEN_TESTPATTERN = "videoscreen.testpattern"; + const std::string CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE = "videoscreen.limitedrange"; + const std::string CSettings::SETTING_VIDEOSCREEN_FRAMEPACKING = "videoscreen.framepacking"; ++const std::string CSettings::SETTING_VIDEOSCREEN_BLANKCURRENT = "videoscreen.blankcurrent"; + const std::string CSettings::SETTING_AUDIOOUTPUT_AUDIODEVICE = "audiooutput.audiodevice"; + const std::string CSettings::SETTING_AUDIOOUTPUT_CHANNELS = "audiooutput.channels"; + const std::string CSettings::SETTING_AUDIOOUTPUT_CONFIG = "audiooutput.config"; +@@ -380,6 +386,7 @@ const std::string CSettings::SETTING_NETWORK_HTTPPROXYPORT = "network.httpproxyp + const std::string CSettings::SETTING_NETWORK_HTTPPROXYUSERNAME = "network.httpproxyusername"; + const std::string CSettings::SETTING_NETWORK_HTTPPROXYPASSWORD = "network.httpproxypassword"; + const std::string CSettings::SETTING_NETWORK_BANDWIDTH = "network.bandwidth"; ++const std::string CSettings::SETTING_NETWORK_RESTARTSERVICES = "network.restartservices"; + const std::string CSettings::SETTING_POWERMANAGEMENT_DISPLAYSOFF = "powermanagement.displaysoff"; + const std::string CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNTIME = "powermanagement.shutdowntime"; + const std::string CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNSTATE = "powermanagement.shutdownstate"; +@@ -1030,6 +1037,7 @@ void CSettings::InitializeISettingCallbacks() + settingSet.insert(CSettings::SETTING_VIDEOSCREEN_MONITOR); + settingSet.insert(CSettings::SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE); + m_settingsManager->RegisterCallback(&CDisplaySettings::GetInstance(), settingSet); ++ m_settingsManager->RegisterCallback(&g_application, settingSet); + + settingSet.clear(); + settingSet.insert(CSettings::SETTING_VIDEOPLAYER_SEEKDELAY); +diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h +index f6d1d42..ac97d25 100644 +--- a/xbmc/settings/Settings.h ++++ b/xbmc/settings/Settings.h +@@ -139,6 +139,10 @@ public: + static const std::string SETTING_VIDEOPLAYER_USESTAGEFRIGHT; + static const std::string SETTING_VIDEOPLAYER_LIMITGUIUPDATE; + static const std::string SETTING_VIDEOPLAYER_SUPPORTMVC; ++ static const std::string SETTING_VIDEOPLAYER_ADJUSTRESOLUTION; ++ static const std::string SETTING_VIDEOPLAYER_ADJUSTRESOLUTIONINTERLACED; ++ static const std::string SETTING_VIDEOPLAYER_MINIMUMVERTICAL; ++ static const std::string SETTING_VIDEOPLAYER_ADJUSTALLOWNONCEA; + static const std::string SETTING_MYVIDEOS_SELECTACTION; + static const std::string SETTING_MYVIDEOS_EXTRACTFLAGS; + static const std::string SETTING_MYVIDEOS_EXTRACTCHAPTERTHUMBS; +@@ -173,6 +177,7 @@ public: + static const std::string SETTING_SCRAPERS_MOVIESDEFAULT; + static const std::string SETTING_SCRAPERS_TVSHOWSDEFAULT; + static const std::string SETTING_SCRAPERS_MUSICVIDEOSDEFAULT; ++ static const std::string SETTING_PVRMANAGER_ENABLED; + static const std::string SETTING_PVRMANAGER_HIDECONNECTIONLOSTWARNING; + static const std::string SETTING_PVRMANAGER_SYNCCHANNELGROUPS; + static const std::string SETTING_PVRMANAGER_BACKENDCHANNELORDER; +@@ -199,7 +204,6 @@ public: + static const std::string SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH; + static const std::string SETTING_PVRPLAYBACK_CHANNELENTRYTIMEOUT; + static const std::string SETTING_PVRPLAYBACK_FPS; +- static const std::string SETTING_PVRRECORD_INSTANTRECORDACTION; + static const std::string SETTING_PVRRECORD_INSTANTRECORDTIME; + static const std::string SETTING_PVRRECORD_DEFAULTPRIORITY; + static const std::string SETTING_PVRRECORD_DEFAULTLIFETIME; +@@ -252,6 +256,7 @@ public: + static const std::string SETTING_AUDIOCDS_ENCODER; + static const std::string SETTING_AUDIOCDS_SETTINGS; + static const std::string SETTING_AUDIOCDS_EJECTONRIP; ++ static const std::string SETTING_MYMUSIC_STARTWINDOW; + static const std::string SETTING_MYMUSIC_SONGTHUMBINVIS; + static const std::string SETTING_MYMUSIC_DEFAULTLIBVIEW; + static const std::string SETTING_PICTURES_GENERATETHUMBS; +@@ -302,6 +307,7 @@ public: + static const std::string SETTING_VIDEOSCREEN_TESTPATTERN; + static const std::string SETTING_VIDEOSCREEN_LIMITEDRANGE; + static const std::string SETTING_VIDEOSCREEN_FRAMEPACKING; ++ static const std::string SETTING_VIDEOSCREEN_BLANKCURRENT; + static const std::string SETTING_AUDIOOUTPUT_AUDIODEVICE; + static const std::string SETTING_AUDIOOUTPUT_CHANNELS; + static const std::string SETTING_AUDIOOUTPUT_CONFIG; +@@ -337,6 +343,7 @@ public: + static const std::string SETTING_NETWORK_HTTPPROXYUSERNAME; + static const std::string SETTING_NETWORK_HTTPPROXYPASSWORD; + static const std::string SETTING_NETWORK_BANDWIDTH; ++ static const std::string SETTING_NETWORK_RESTARTSERVICES; + static const std::string SETTING_POWERMANAGEMENT_DISPLAYSOFF; + static const std::string SETTING_POWERMANAGEMENT_SHUTDOWNTIME; + static const std::string SETTING_POWERMANAGEMENT_SHUTDOWNSTATE; +diff --git a/xbmc/settings/dialogs/GUIDialogAudioDSPManager.cpp b/xbmc/settings/dialogs/GUIDialogAudioDSPManager.cpp +index 37b6211..cc4fd8e 100644 +--- a/xbmc/settings/dialogs/GUIDialogAudioDSPManager.cpp ++++ b/xbmc/settings/dialogs/GUIDialogAudioDSPManager.cpp +@@ -21,7 +21,7 @@ + #include "GUIDialogAudioDSPManager.h" + + #include "FileItem.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "dialogs/GUIDialogTextViewer.h" + #include "dialogs/GUIDialogOK.h" + #include "dialogs/GUIDialogBusy.h" +@@ -1026,17 +1026,14 @@ CFileItem *CGUIDialogAudioDSPManager::helper_CreateModeListItem(CActiveAEDSPMode + // set list item properties + pItem->SetProperty("ActiveMode", isActive); + pItem->SetProperty("Number", number); +- pItem->SetLabel(modeName); ++ pItem->SetProperty("Name", modeName); + pItem->SetProperty("Description", description); + pItem->SetProperty("Help", ModePointer->ModeHelp()); +- if (ModePointer->IconOwnModePath().empty()) +- pItem->SetIconImage("DefaultAddonAudioDSP.png"); +- else +- pItem->SetIconImage(ModePointer->IconOwnModePath()); ++ pItem->SetProperty("Icon", ModePointer->IconOwnModePath()); + pItem->SetProperty("SettingsDialog", dialogId); + pItem->SetProperty("AddonId", AddonID); + pItem->SetProperty("AddonModeNumber", ModePointer->AddonModeNumber()); +- pItem->SetLabel2(addonName); ++ pItem->SetProperty("AddonName", addonName); + pItem->SetProperty("Changed", false); + + return pItem; +diff --git a/xbmc/settings/dialogs/GUIDialogAudioDSPManager.h b/xbmc/settings/dialogs/GUIDialogAudioDSPManager.h +index bf5ed9c..ae0cf78 100644 +--- a/xbmc/settings/dialogs/GUIDialogAudioDSPManager.h ++++ b/xbmc/settings/dialogs/GUIDialogAudioDSPManager.h +@@ -20,7 +20,7 @@ + */ + + #include "addons/kodi-addon-dev-kit/include/kodi/kodi_adsp_types.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h" + #include "dialogs/GUIDialogContextMenu.h" + #include "guilib/GUIDialog.h" + #include "view/GUIViewControl.h" +diff --git a/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.cpp b/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.cpp +index e0b77ef..04eb2ff 100644 +--- a/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.cpp ++++ b/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.cpp +@@ -22,8 +22,8 @@ + #include "Application.h" + #include "addons/Skin.h" + #include "cores/IPlayer.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPDatabase.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPMode.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPDatabase.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPMode.h" + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "dialogs/GUIDialogYesNo.h" +diff --git a/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.h b/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.h +index b90c2c5..c573098 100644 +--- a/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.h ++++ b/xbmc/settings/dialogs/GUIDialogAudioDSPSettings.h +@@ -20,9 +20,8 @@ + */ + + #include <utility> +-#include <vector> + +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSPProcess.h" + #include "settings/dialogs/GUIDialogSettingsManualBase.h" + + namespace ActiveAE +diff --git a/xbmc/settings/dialogs/GUIDialogSettingsManualBase.h b/xbmc/settings/dialogs/GUIDialogSettingsManualBase.h +index 47022ae..3798dcd 100644 +--- a/xbmc/settings/dialogs/GUIDialogSettingsManualBase.h ++++ b/xbmc/settings/dialogs/GUIDialogSettingsManualBase.h +@@ -21,8 +21,6 @@ + */ + + #include <map> +-#include <string> +-#include <vector> + + #include "addons/IAddon.h" + #include "settings/dialogs/GUIDialogSettingsManagerBase.h" +diff --git a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.h b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.h +index 34d5af4..671c09b 100644 +--- a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.h ++++ b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.h +@@ -20,8 +20,6 @@ + * + */ + +-#include <vector> +- + #include "guilib/GUIWindow.h" + + class CGUIWindowSettingsScreenCalibration : public CGUIWindow +diff --git a/xbmc/storage/AutorunMediaJob.cpp b/xbmc/storage/AutorunMediaJob.cpp +index 28fd034..dee6728 100644 +--- a/xbmc/storage/AutorunMediaJob.cpp ++++ b/xbmc/storage/AutorunMediaJob.cpp +@@ -67,9 +67,9 @@ const char *CAutorunMediaJob::GetWindowString(int selection) + switch (selection) + { + case 0: +- return "Videos"; ++ return "VideoFiles"; + case 1: +- return "Music"; ++ return "MusicFiles"; + case 2: + return "Pictures"; + case 3: +diff --git a/xbmc/storage/DetectDVDType.cpp b/xbmc/storage/DetectDVDType.cpp +index 14b0304..99e3b63 100644 +--- a/xbmc/storage/DetectDVDType.cpp ++++ b/xbmc/storage/DetectDVDType.cpp +@@ -132,7 +132,7 @@ VOID CDetectDVDMedia::UpdateDvdrom() + switch (GetTrayState()) + { + case DRIVE_NONE: +- //! @todo reduce / stop polling for drive updates ++ // TODO: reduce / stop polling for drive updates + break; + + case DRIVE_OPEN: +diff --git a/xbmc/storage/IStorageProvider.h b/xbmc/storage/IStorageProvider.h +index c02c7c2..0325b0b 100644 +--- a/xbmc/storage/IStorageProvider.h ++++ b/xbmc/storage/IStorageProvider.h +@@ -18,10 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <string> +-#include <vector> +- + #include "system.h" + #include "MediaSource.h" + #ifdef HAS_DVD_DRIVE +diff --git a/xbmc/storage/MediaManager.cpp b/xbmc/storage/MediaManager.cpp +index b0dbc84..931cfac 100644 +--- a/xbmc/storage/MediaManager.cpp ++++ b/xbmc/storage/MediaManager.cpp +@@ -30,7 +30,7 @@ + #include "guilib/GUIWindowManager.h" + #ifdef HAS_DVD_DRIVE + #ifndef TARGET_WINDOWS +-//! @todo switch all ports to use auto sources ++// TODO: switch all ports to use auto sources + #include <map> + #include <utility> + #include "DetectDVDType.h" +@@ -314,7 +314,7 @@ void CMediaManager::RemoveAutoSource(const CMediaSource &share) + + ///////////////////////////////////////////////////////////// + // AutoSource status functions: +-//! @todo translate cdda://<device>/ ++// - TODO: translate cdda://<device>/ + + std::string CMediaManager::TranslateDevicePath(const std::string& devicePath, bool bReturnAsDevice) + { +@@ -357,7 +357,7 @@ bool CMediaManager::IsDiscInDrive(const std::string& devicePath) + return false; + #else + if(URIUtils::IsDVD(devicePath) || devicePath.empty()) +- return MEDIA_DETECT::CDetectDVDMedia::IsDiscInDrive(); //! @todo switch all ports to use auto sources ++ return MEDIA_DETECT::CDetectDVDMedia::IsDiscInDrive(); // TODO: switch all ports to use auto sources + else + return true; // Assume other paths to be mounted already + #endif +@@ -379,7 +379,7 @@ bool CMediaManager::IsAudio(const std::string& devicePath) + + return false; + #else +- //! @todo switch all ports to use auto sources ++ // TODO: switch all ports to use auto sources + MEDIA_DETECT::CCdInfo* pInfo = MEDIA_DETECT::CDetectDVDMedia::GetCdInfo(); + if (pInfo != NULL && pInfo->IsAudio(1)) + return true; +@@ -679,6 +679,9 @@ std::vector<std::string> CMediaManager::GetDiskUsage() + void CMediaManager::OnStorageAdded(const std::string &label, const std::string &path) + { + #ifdef HAS_DVD_DRIVE ++ if (path == "/run/btrfs-snap" || path == "/tmp/btrfs-snap") ++ return; ++ + if (CSettings::GetInstance().GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) != AUTOCD_NONE || CSettings::GetInstance().GetBool(CSettings::SETTING_DVDS_AUTORUN)) + if (CSettings::GetInstance().GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) == AUTOCD_RIP) + CJobManager::GetInstance().AddJob(new CAutorunMediaJob(label, path), this, CJob::PRIORITY_LOW); +diff --git a/xbmc/storage/MediaManager.h b/xbmc/storage/MediaManager.h +index 3ea422f..a2c71a5 100644 +--- a/xbmc/storage/MediaManager.h ++++ b/xbmc/storage/MediaManager.h +@@ -19,10 +19,8 @@ + * + */ + +-#include <map> +-#include <vector> +- + #include "MediaSource.h" // for VECSOURCES ++#include <map> + #include "utils/Job.h" + #include "IStorageProvider.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/storage/android/AndroidStorageProvider.cpp b/xbmc/storage/android/AndroidStorageProvider.cpp +index 2bb8731..51ddbba 100644 +--- a/xbmc/storage/android/AndroidStorageProvider.cpp ++++ b/xbmc/storage/android/AndroidStorageProvider.cpp +@@ -71,7 +71,7 @@ std::string CAndroidStorageProvider::unescape(const std::string& str) + i += 1; + if (str[i] == 'u') // unicode + { +- //! @todo implement ++ // TODO + } + else if (str[i] >= '0' && str[i] <= '7') // octal + { +diff --git a/xbmc/storage/android/AndroidStorageProvider.h b/xbmc/storage/android/AndroidStorageProvider.h +index 33628d9..d405c20 100644 +--- a/xbmc/storage/android/AndroidStorageProvider.h ++++ b/xbmc/storage/android/AndroidStorageProvider.h +@@ -20,9 +20,6 @@ + */ + + #include <set> +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + + class CAndroidStorageProvider : public IStorageProvider +diff --git a/xbmc/storage/cdioSupport.cpp b/xbmc/storage/cdioSupport.cpp +index 2c278eb..6f31fe7 100644 +--- a/xbmc/storage/cdioSupport.cpp ++++ b/xbmc/storage/cdioSupport.cpp +@@ -502,7 +502,7 @@ bool CCdIoSupport::IsIt(int num) + signature_t *sigp = &sigs[num]; + int len = strlen(sigp->sig_str); + +- //! @todo check that num < largest sig. ++ /* TODO: check that num < largest sig. */ + return 0 == memcmp(&buffer[sigp->buf_num][sigp->offset], sigp->sig_str, len); + } + +diff --git a/xbmc/storage/linux/DeviceKitDisksProvider.cpp b/xbmc/storage/linux/DeviceKitDisksProvider.cpp +index e5123e2..5fc844e 100644 +--- a/xbmc/storage/linux/DeviceKitDisksProvider.cpp ++++ b/xbmc/storage/linux/DeviceKitDisksProvider.cpp +@@ -195,8 +195,8 @@ std::string CDeviceKitDiskDevice::toString() + CDeviceKitDisksProvider::CDeviceKitDisksProvider() + { + dbus_error_init (&m_error); +- //! @todo do not use dbus_connection_pop_message() that requires the use of a +- //! private connection ++ // TODO: do not use dbus_connection_pop_message() that requires the use of a ++ // private connection + m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_error); + dbus_connection_set_exit_on_disconnect(m_connection, false); + +diff --git a/xbmc/storage/linux/DeviceKitDisksProvider.h b/xbmc/storage/linux/DeviceKitDisksProvider.h +index 4888eda..2902fe5 100644 +--- a/xbmc/storage/linux/DeviceKitDisksProvider.h ++++ b/xbmc/storage/linux/DeviceKitDisksProvider.h +@@ -18,10 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + #ifdef HAS_DBUS + #include "DBusUtil.h" +diff --git a/xbmc/storage/linux/LinuxStorageProvider.h b/xbmc/storage/linux/LinuxStorageProvider.h +index b4794ab..6cda860 100644 +--- a/xbmc/storage/linux/LinuxStorageProvider.h ++++ b/xbmc/storage/linux/LinuxStorageProvider.h +@@ -18,9 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <vector> +- + #include "storage/IStorageProvider.h" + #include "DeviceKitDisksProvider.h" + #include "UDevProvider.h" +diff --git a/xbmc/storage/linux/UDevProvider.h b/xbmc/storage/linux/UDevProvider.h +index 5c890cf..35ae37e 100644 +--- a/xbmc/storage/linux/UDevProvider.h ++++ b/xbmc/storage/linux/UDevProvider.h +@@ -19,9 +19,6 @@ + * + */ + +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + + #ifdef HAVE_LIBUDEV +diff --git a/xbmc/storage/linux/UDisksProvider.cpp b/xbmc/storage/linux/UDisksProvider.cpp +index 7bdc520..498d0ef 100644 +--- a/xbmc/storage/linux/UDisksProvider.cpp ++++ b/xbmc/storage/linux/UDisksProvider.cpp +@@ -174,8 +174,8 @@ std::string CUDiskDevice::toString() + CUDisksProvider::CUDisksProvider() + { + dbus_error_init (&m_error); +- //! @todo do not use dbus_connection_pop_message() that requires the use of a +- //! private connection ++ // TODO: do not use dbus_connection_pop_message() that requires the use of a ++ // private connection + m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_error); + + if (m_connection) +diff --git a/xbmc/storage/linux/UDisksProvider.h b/xbmc/storage/linux/UDisksProvider.h +index cbc8243..572103f 100644 +--- a/xbmc/storage/linux/UDisksProvider.h ++++ b/xbmc/storage/linux/UDisksProvider.h +@@ -18,10 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + #ifdef HAS_DBUS + #include "DBusUtil.h" +diff --git a/xbmc/storage/osx/DarwinStorageProvider.h b/xbmc/storage/osx/DarwinStorageProvider.h +index 4d50d26..e337432 100644 +--- a/xbmc/storage/osx/DarwinStorageProvider.h ++++ b/xbmc/storage/osx/DarwinStorageProvider.h +@@ -18,10 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + + class CDarwinStorageProvider : public IStorageProvider +diff --git a/xbmc/storage/windows/Win32StorageProvider.h b/xbmc/storage/windows/Win32StorageProvider.h +index cce1a39..2b123e9 100644 +--- a/xbmc/storage/windows/Win32StorageProvider.h ++++ b/xbmc/storage/windows/Win32StorageProvider.h +@@ -18,10 +18,6 @@ + * <http://www.gnu.org/licenses/>. + * + */ +- +-#include <string> +-#include <vector> +- + #include "storage/IStorageProvider.h" + #include "utils/Job.h" + +diff --git a/xbmc/system.h b/xbmc/system.h +index d426ade..1831e86 100644 +--- a/xbmc/system.h ++++ b/xbmc/system.h +@@ -59,6 +59,10 @@ + #define HAS_FILESYSTEM_NFS + #endif + ++#ifdef HAVE_LIBAFPCLIENT ++ #define HAS_FILESYSTEM_AFP ++#endif ++ + #ifdef HAVE_LIBPLIST + #define HAS_AIRPLAY + #endif +@@ -105,6 +109,7 @@ + #define HAS_WEB_SERVER + #define HAS_WEB_INTERFACE + #define HAVE_LIBSSH ++#define HAS_LIBRTMP + #define HAS_FILESYSTEM_SMB + #define HAS_ZEROCONF + #define HAS_MDNS +diff --git a/xbmc/test/TestBasicEnvironment.cpp b/xbmc/test/TestBasicEnvironment.cpp +index 58ccf4d..0a59603 100644 +--- a/xbmc/test/TestBasicEnvironment.cpp ++++ b/xbmc/test/TestBasicEnvironment.cpp +@@ -20,7 +20,7 @@ + + #include "TestBasicEnvironment.h" + #include "TestUtils.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "filesystem/Directory.h" + #include "filesystem/File.h" + #include "filesystem/SpecialProtocol.h" +@@ -30,9 +30,6 @@ + #include "Util.h" + #include "Application.h" + #include "interfaces/AnnouncementManager.h" +-#include "addons/BinaryAddonCache.h" +-#include "interfaces/python/XBPython.h" +-#include "pvr/PVRManager.h" + + #if defined(TARGET_WINDOWS) + #include "win32/WIN32Util.h" +@@ -70,8 +67,7 @@ void TestBasicEnvironment::SetUp() + std::string frameworksPath = CUtil::GetFrameworksPath(); + CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath); + #endif +- /** +- * @todo Something should be done about all the asserts in GUISettings so ++ /* TODO: Something should be done about all the asserts in GUISettings so + * that the initialization of these components won't be needed. + */ + g_powerManager.Initialize(); +@@ -109,7 +105,7 @@ void TestBasicEnvironment::SetUp() + * CLibcdio). This is done so that the initialization of the VFS does not + * affect the performance results of the test cases. + */ +- /** @todo Make the initialization of the VFS here optional so it can be ++ /* TODO: Make the initialization of the VFS here optional so it can be + * testable in a test case. + */ + f = XBMC_CREATETEMPFILE(""); +diff --git a/xbmc/test/TestURL.cpp b/xbmc/test/TestURL.cpp +index cd2fda4..bf5c8c9 100644 +--- a/xbmc/test/TestURL.cpp ++++ b/xbmc/test/TestURL.cpp +@@ -68,11 +68,11 @@ const TestURLGetWithoutUserDetailsData values[] = { + { std::string("smb://god@[fd00::1]:8080/example"), std::string("smb://USERNAME@[fd00::1]:8080/example"), true }, + { std::string("smb://god:universe@fd00::1/example"), std::string("smb://USERNAME:PASSWORD@fd00::1/example"), true }, + { std::string("http://god:universe@[fd00::1]:8448/example|auth=digest"), std::string("http://USERNAME:PASSWORD@[fd00::1]:8448/example|auth=digest"), true }, +- { std::string("smb://00ff:1:0000:abde::/example"), std::string("smb://00ff:1:0000:abde::/example"), true }, +- { std::string("smb://god:universe@[00ff:1:0000:abde::]:8080/example"), std::string("smb://[00ff:1:0000:abde::]:8080/example"), false }, +- { std::string("smb://god@[00ff:1:0000:abde::]:8080/example"), std::string("smb://USERNAME@[00ff:1:0000:abde::]:8080/example"), true }, +- { std::string("smb://god:universe@00ff:1:0000:abde::/example"), std::string("smb://USERNAME:PASSWORD@00ff:1:0000:abde::/example"), true }, +- { std::string("http://god:universe@[00ff:1:0000:abde::]:8448/example|auth=digest"), std::string("http://USERNAME:PASSWORD@[00ff:1:0000:abde::]:8448/example|auth=digest"), true } ++ { std::string("smb://00ff:1:0000:abde::/example"), std::string("smb://ff:1:0:abde::/example"), true }, ++ { std::string("smb://god:universe@[00ff:1:0000:abde::]:8080/example"), std::string("smb://[ff:1:0:abde::]:8080/example"), false }, ++ { std::string("smb://god@[00ff:1:0000:abde::]:8080/example"), std::string("smb://USERNAME@[ff:1:0:abde::]:8080/example"), true }, ++ { std::string("smb://god:universe@00ff:1:0000:abde::/example"), std::string("smb://USERNAME:PASSWORD@ff:1:0:abde::/example"), true }, ++ { std::string("http://god:universe@[00ff:1:0000:abde::]:8448/example|auth=digest"), std::string("http://USERNAME:PASSWORD@[ff:1:0:abde::]:8448/example|auth=digest"), true } + }; + + INSTANTIATE_TEST_CASE_P(URL, TestURLGetWithoutUserDetails, ValuesIn(values)); +diff --git a/xbmc/threads/Atomics.h b/xbmc/threads/Atomics.h +index d28d62d..a43681c 100644 +--- a/xbmc/threads/Atomics.h ++++ b/xbmc/threads/Atomics.h +@@ -20,7 +20,7 @@ + * + */ + +-//! @todo Inline these methods ++// TODO: Inline these methods + long cas(volatile long *pAddr, long expectedVal, long swapVal); + #if !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) + long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal); +diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.cpp b/xbmc/threads/platform/pthreads/ThreadImpl.cpp +index 99c3dbe..7c315cf 100644 +--- a/xbmc/threads/platform/pthreads/ThreadImpl.cpp ++++ b/xbmc/threads/platform/pthreads/ThreadImpl.cpp +@@ -144,6 +144,9 @@ int CThread::GetNormalPriority(void) + + bool CThread::SetPriority(const int iPriority) + { ++#if 1 ++ bool bReturn = true; ++#else + bool bReturn = false; + + // wait until thread is running, it needs to get its lwp id +@@ -195,6 +198,7 @@ bool CThread::SetPriority(const int iPriority) + if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); + } + #endif ++#endif + + return bReturn; + } +diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp +index 4ae45f3..5915e61 100644 +--- a/xbmc/utils/AMLUtils.cpp ++++ b/xbmc/utils/AMLUtils.cpp +@@ -118,21 +118,6 @@ bool aml_permissions() + CLog::Log(LOGERROR, "AML: no rw on /sys/class/tsync/pts_pcrscr"); + permissions_ok = 0; + } +- if (!SysfsUtils::HasRW("/dev/video10")) +- { +- CLog::Log(LOGERROR, "AML: no rw on /dev/video10"); +- permissions_ok = 0; +- } +- if (!SysfsUtils::HasRW("/sys/module/amvideo/parameters/omx_pts")) +- { +- CLog::Log(LOGERROR, "AML: no rw on /sys/module/amvideo/parameters/omx_pts"); +- permissions_ok = 0; +- } +- if (!SysfsUtils::HasRW("/sys/module/amlvideodri/parameters/freerun_mode")) +- { +- CLog::Log(LOGERROR, "AML: no rw on /sys/module/amlvideodri/parameters/freerun_mode"); +- permissions_ok = 0; +- } + if (!SysfsUtils::HasRW("/sys/class/audiodsp/digital_raw")) + { + CLog::Log(LOGERROR, "AML: no rw on /sys/class/audiodsp/digital_raw"); +diff --git a/xbmc/utils/AliasShortcutUtils.cpp b/xbmc/utils/AliasShortcutUtils.cpp +index ce5f93b..ef96f70 100644 +--- a/xbmc/utils/AliasShortcutUtils.cpp ++++ b/xbmc/utils/AliasShortcutUtils.cpp +@@ -34,7 +34,7 @@ bool IsAliasShortcut(const std::string& path, bool isdirectory) + #if defined(TARGET_DARWIN_OSX) + // Note: regular files that have an .alias extension can be + // reported as an alias when clearly, they are not. Trap them out. +- if (!URIUtils::HasExtension(path, ".alias"))//! @todo - check if this is still needed with the new API ++ if (!URIUtils::HasExtension(path, ".alias"))// TODO - check if this is still needed with the new API + { + rtn = CDarwinUtils::IsAliasShortcut(path, isdirectory); + } +diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp +index d0a4c20..7bff587 100644 +--- a/xbmc/utils/BitstreamConverter.cpp ++++ b/xbmc/utils/BitstreamConverter.cpp +@@ -421,12 +421,11 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + // valid hvcC data (bitstream) always starts with the value 1 (version) + if(m_to_annexb) + { +- /** @todo from Amlogic +- * It seems the extradata is encoded as hvcC format. +- * Temporarily, we support configurationVersion==0 until 14496-15 3rd +- * is finalized. When finalized, configurationVersion will be 1 and we +- * can recognize hvcC by checking if extradata[0]==1 or not. +- */ ++ // TODO: from Amlogic ++ /* It seems the extradata is encoded as hvcC format. ++ * Temporarily, we support configurationVersion==0 until 14496-15 3rd ++ * is finalized. When finalized, configurationVersion will be 1 and we ++ * can recognize hvcC by checking if extradata[0]==1 or not. */ + + if (in_extradata[0] || in_extradata[1] || in_extradata[2] > 1) + { +@@ -449,7 +448,7 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 1) ) + { + CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init"); +- //! @todo convert annexb to bitstream format ++ // TODO: convert annexb to bitstream format + return false; + } + else +@@ -1405,7 +1404,7 @@ void CBitstreamConverter::parseh264_sps(const uint8_t *sps, const uint32_t sps_s + sps_info.seq_scaling_matrix_present_flag = nal_bs_read (&bs, 1); + if (sps_info.seq_scaling_matrix_present_flag) + { +- //! @todo unfinished ++ /* TODO: unfinished */ + } + } + sps_info.log2_max_frame_num_minus4 = nal_bs_read_ue(&bs); +@@ -1419,7 +1418,7 @@ void CBitstreamConverter::parseh264_sps(const uint8_t *sps, const uint32_t sps_s + sps_info.log2_max_pic_order_cnt_lsb_minus4 = nal_bs_read_ue(&bs); + } + else if (sps_info.pic_order_cnt_type == 1) +- { //! @todo unfinished ++ { // TODO: unfinished + /* + delta_pic_order_always_zero_flag = gst_nal_bs_read (bs, 1); + offset_for_non_ref_pic = gst_nal_bs_read_se (bs); +diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h +index 9045ef9..cf5d5ef 100644 +--- a/xbmc/utils/BitstreamConverter.h ++++ b/xbmc/utils/BitstreamConverter.h +@@ -43,8 +43,8 @@ typedef struct { + } bits_reader_t; + + //////////////////////////////////////////////////////////////////////////////////////////// +-//! @todo refactor this so as not to need these ffmpeg routines. +-//! These are not exposed in ffmpeg's API so we dupe them here. ++// TODO: refactor this so as not to need these ffmpeg routines. ++// These are not exposed in ffmpeg's API so we dupe them here. + // AVC helper functions for muxers, + // * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com> + // This is part of FFmpeg +diff --git a/xbmc/utils/CPUInfo.cpp b/xbmc/utils/CPUInfo.cpp +index 4dff0e9..2a656ae 100644 +--- a/xbmc/utils/CPUInfo.cpp ++++ b/xbmc/utils/CPUInfo.cpp +@@ -377,7 +377,7 @@ CCPUInfo::CCPUInfo(void) + StringUtils::Trim(m_cores[nCurrId].m_strModel); + } + } +- else if (strncmp(buffer, "flags", 5) == 0) ++ else if (strncmp(buffer, "flags", 5) == 0 || strncmp(buffer, "Features", 8) == 0) + { + char* needle = strchr(buffer, ':'); + if (needle) +@@ -408,6 +408,10 @@ CCPUInfo::CCPUInfo(void) + m_cpuFeatures |= CPU_FEATURE_3DNOW; + else if (0 == strcmp(tok, "3dnowext")) + m_cpuFeatures |= CPU_FEATURE_3DNOWEXT; ++ else if (0 == strcmp(tok, "neon")) ++ m_cpuFeatures |= CPU_FEATURE_NEON; ++ else if (0 == strcmp(tok, "thumb")) ++ m_cpuFeatures |= CPU_FEATURE_THUMB; + tok = strtok_r(NULL, " ", &save); + } + } +@@ -461,10 +465,6 @@ CCPUInfo::CCPUInfo(void) + // Set MMX2 when SSE is present as SSE is a superset of MMX2 and Intel doesn't set the MMX2 cap + if (m_cpuFeatures & CPU_FEATURE_SSE) + m_cpuFeatures |= CPU_FEATURE_MMX2; +- +- if (HasNeon()) +- m_cpuFeatures |= CPU_FEATURE_NEON; +- + } + + CCPUInfo::~CCPUInfo() +@@ -948,27 +948,7 @@ bool CCPUInfo::HasNeon() + has_neon = 1; + + #elif defined(TARGET_LINUX) && defined(__ARM_NEON__) +- if (has_neon == -1) +- { +- has_neon = 0; +- // why are we not looking at the Features in +- // /proc/cpuinfo for neon ? +- int fd = open("/proc/self/auxv", O_RDONLY); +- if (fd >= 0) +- { +- Elf32_auxv_t auxv; +- while (read(fd, &auxv, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) +- { +- if (auxv.a_type == AT_HWCAP) +- { +- has_neon = (auxv.a_un.a_val & HWCAP_NEON) ? 1 : 0; +- break; +- } +- } +- close(fd); +- } +- } +- ++ has_neon = ((g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) == CPU_FEATURE_NEON) ? 1 : 0; + #endif + + return has_neon == 1; +diff --git a/xbmc/utils/CPUInfo.h b/xbmc/utils/CPUInfo.h +index 1c5e5ba..5f3e2f9 100644 +--- a/xbmc/utils/CPUInfo.h ++++ b/xbmc/utils/CPUInfo.h +@@ -47,6 +47,7 @@ class CTemperature; + #define CPU_FEATURE_3DNOWEXT 1 << 9 + #define CPU_FEATURE_ALTIVEC 1 << 10 + #define CPU_FEATURE_NEON 1 << 11 ++#define CPU_FEATURE_THUMB 1 << 12 + + struct CoreInfo + { +diff --git a/xbmc/utils/CryptThreading.cpp b/xbmc/utils/CryptThreading.cpp +index 6088929..1d2deca 100644 +--- a/xbmc/utils/CryptThreading.cpp ++++ b/xbmc/utils/CryptThreading.cpp +@@ -29,10 +29,8 @@ + #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) + #include "config.h" + #else +-#ifndef HAVE_OPENSSL + #define HAVE_OPENSSL + #endif +-#endif + + #ifdef HAVE_OPENSSL + #include <openssl/crypto.h> +diff --git a/xbmc/utils/DatabaseUtils.cpp b/xbmc/utils/DatabaseUtils.cpp +index cecc83a..282dac9 100644 +--- a/xbmc/utils/DatabaseUtils.cpp ++++ b/xbmc/utils/DatabaseUtils.cpp +@@ -125,7 +125,7 @@ std::string DatabaseUtils::GetField(Field field, const MediaType &mediaType, Dat + else if (field == FieldTime) result = StringUtils::Format("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_RUNTIME); + else if (field == FieldDirector) result = StringUtils::Format("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_DIRECTOR); + else if (field == FieldStudio) result = StringUtils::Format("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_STUDIOS); +- else if (field == FieldYear) return "musicvideo_view.premiered"; ++ else if (field == FieldYear) result = StringUtils::Format("musicvideo_view.c%02d",VIDEODB_ID_MUSICVIDEO_YEAR); + else if (field == FieldPlot) result = StringUtils::Format("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_PLOT); + else if (field == FieldAlbum) result = StringUtils::Format("musicvideo_view.c%02d",VIDEODB_ID_MUSICVIDEO_ALBUM); + else if (field == FieldArtist) result = StringUtils::Format("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_ARTIST); +@@ -159,7 +159,7 @@ std::string DatabaseUtils::GetField(Field field, const MediaType &mediaType, Dat + else if (field == FieldVotes) return "movie_view.votes"; + else if (field == FieldRating) return "movie_view.rating"; + else if (field == FieldWriter) result = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_CREDITS); +- else if (field == FieldYear) return "movie_view.premiered"; ++ else if (field == FieldYear) result = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_YEAR); + else if (field == FieldSortTitle) result = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_SORTTITLE); + else if (field == FieldTime) result = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_RUNTIME); + else if (field == FieldMPAA) result = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_MPAA); +@@ -540,7 +540,7 @@ int DatabaseUtils::GetField(Field field, const MediaType &mediaType, bool asInde + else if (field == FieldTime) index = VIDEODB_ID_MUSICVIDEO_RUNTIME; + else if (field == FieldDirector) index = VIDEODB_ID_MUSICVIDEO_DIRECTOR; + else if (field == FieldStudio) index = VIDEODB_ID_MUSICVIDEO_STUDIOS; +- else if (field == FieldYear) return VIDEODB_DETAILS_MUSICVIDEO_PREMIERED; ++ else if (field == FieldYear) index = VIDEODB_ID_MUSICVIDEO_YEAR; + else if (field == FieldPlot) index = VIDEODB_ID_MUSICVIDEO_PLOT; + else if (field == FieldAlbum) index = VIDEODB_ID_MUSICVIDEO_ALBUM; + else if (field == FieldArtist) index = VIDEODB_ID_MUSICVIDEO_ARTIST; +@@ -574,7 +574,7 @@ int DatabaseUtils::GetField(Field field, const MediaType &mediaType, bool asInde + else if (field == FieldVotes) return VIDEODB_DETAILS_MOVIE_VOTES; + else if (field == FieldRating) return VIDEODB_DETAILS_MOVIE_RATING; + else if (field == FieldWriter) index = VIDEODB_ID_CREDITS; +- else if (field == FieldYear) return VIDEODB_DETAILS_MOVIE_PREMIERED; ++ else if (field == FieldYear) index = VIDEODB_ID_YEAR; + else if (field == FieldTime) index = VIDEODB_ID_RUNTIME; + else if (field == FieldMPAA) index = VIDEODB_ID_MPAA; + else if (field == FieldTop250) index = VIDEODB_ID_TOP250; +diff --git a/xbmc/utils/GroupUtils.cpp b/xbmc/utils/GroupUtils.cpp +index 62a7aeb..7d9055c 100644 +--- a/xbmc/utils/GroupUtils.cpp ++++ b/xbmc/utils/GroupUtils.cpp +@@ -115,8 +115,8 @@ bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileI + } + + // handle year +- if (movieInfo->GetYear() > setInfo->GetYear()) +- setInfo->SetYear(movieInfo->GetYear()); ++ if (movieInfo->m_iYear > setInfo->m_iYear) ++ setInfo->m_iYear = movieInfo->m_iYear; + + // handle lastplayed + if (movieInfo->m_lastPlayed.IsValid() && movieInfo->m_lastPlayed > setInfo->m_lastPlayed) +diff --git a/xbmc/utils/HTMLUtil.cpp b/xbmc/utils/HTMLUtil.cpp +index 6cd4f3c..54cf3fa 100644 +--- a/xbmc/utils/HTMLUtil.cpp ++++ b/xbmc/utils/HTMLUtil.cpp +@@ -195,7 +195,7 @@ static const HTMLMapping mappings[] = + + void CHTMLUtil::ConvertHTMLToW(const std::wstring& strHTML, std::wstring& strStripped) + { +- //! @todo STRING_CLEANUP ++ /* TODO:STRING_CLEANUP */ + if (strHTML.empty()) + { + strStripped.clear(); +diff --git a/xbmc/utils/IRssObserver.h b/xbmc/utils/IRssObserver.h +index ef2a64d..eb930b6 100644 +--- a/xbmc/utils/IRssObserver.h ++++ b/xbmc/utils/IRssObserver.h +@@ -19,8 +19,6 @@ + * + */ + +-#include <vector> +- + typedef uint32_t character_t; + typedef std::vector<character_t> vecText; + +diff --git a/xbmc/utils/JSONVariantParser.cpp b/xbmc/utils/JSONVariantParser.cpp +index b457280..d146cdd 100644 +--- a/xbmc/utils/JSONVariantParser.cpp ++++ b/xbmc/utils/JSONVariantParser.cpp +@@ -57,11 +57,6 @@ void CJSONVariantParser::push_buffer(const unsigned char *buffer, unsigned int l + yajl_parse(m_handler, buffer, length); + } + +-CVariant CJSONVariantParser::Parse(const std::string& json) +-{ +- return Parse(reinterpret_cast<const unsigned char*>(json.c_str()), json.length()); +-} +- + CVariant CJSONVariantParser::Parse(const unsigned char *json, unsigned int length) + { + CSimpleParseCallback callback; +diff --git a/xbmc/utils/JSONVariantParser.h b/xbmc/utils/JSONVariantParser.h +index 535636c..7682bd5 100644 +--- a/xbmc/utils/JSONVariantParser.h ++++ b/xbmc/utils/JSONVariantParser.h +@@ -19,9 +19,6 @@ + * + */ + +-#include <string> +-#include <vector> +- + #include "utils/Variant.h" + + #include <yajl/yajl_parse.h> +@@ -54,8 +51,6 @@ public: + + static CVariant Parse(const unsigned char *json, unsigned int length); + +- static CVariant Parse(const std::string& json); +- + private: + static int ParseNull(void * ctx); + static int ParseBoolean(void * ctx, int boolean); +diff --git a/xbmc/utils/LabelFormatter.cpp b/xbmc/utils/LabelFormatter.cpp +index b7e628a..cc4fe49 100644 +--- a/xbmc/utils/LabelFormatter.cpp ++++ b/xbmc/utils/LabelFormatter.cpp +@@ -209,8 +209,10 @@ std::string CLabelFormatter::GetMaskContent(const CMaskString &mask, const CFile + { + if (movie->m_firstAired.IsValid()) + value = movie->m_firstAired.GetAsLocalizedDate(); +- else if (movie->HasYear()) +- value = StringUtils::Format("%i", movie->GetYear()); ++ else if (movie->m_premiered.IsValid()) ++ value = movie->m_premiered.GetAsLocalizedDate(); ++ else if (movie->m_iYear > 0) ++ value = StringUtils::Format("%i", movie->m_iYear); + } + break; + case 'F': // filename +diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in +index 47ad392..686d947 100644 +--- a/xbmc/utils/Makefile.in ++++ b/xbmc/utils/Makefile.in +@@ -52,6 +52,7 @@ SRCS += RssReader.cpp + SRCS += SaveFileStateJob.cpp + SRCS += ScraperParser.cpp + SRCS += ScraperUrl.cpp ++SRCS += Screen.cpp + SRCS += Screenshot.cpp + SRCS += SeekHandler.cpp + SRCS += SortUtils.cpp +@@ -74,9 +75,7 @@ SRCS += Weather.cpp + SRCS += XBMCTinyXML.cpp + SRCS += XMLUtils.cpp + SRCS += Utf8Utils.cpp +-ifeq (@HAVE_LIBXSLT@,1) + SRCS += XSLTUtils.cpp +-endif + SRCS += ActorProtocol.cpp + SRCS += SysfsUtils.cpp + +diff --git a/xbmc/utils/Mime.cpp b/xbmc/utils/Mime.cpp +index 1acdb1c..8845b53 100644 +--- a/xbmc/utils/Mime.cpp ++++ b/xbmc/utils/Mime.cpp +@@ -638,7 +638,7 @@ CMime::EFileType CMime::GetFileTypeFromContent(const std::string& fileContent) + + const unsigned char* const b = (const unsigned char*)fileContent.c_str(); + +- //! @todo add detection for text types ++ // TODO: add detection for text types + + // check image types + if (b[0] == 'B' && b[1] == 'M') +@@ -658,7 +658,7 @@ CMime::EFileType CMime::GetFileTypeFromContent(const std::string& fileContent) + if (len >= 7 && b[0] == 'R' && b[1] == 'a' && b[2] == 'r' && b[3] == ' ' && b[4] == 0x1A && b[5] == 0x07 && b[6] == 0x00) + return FileTypeRar; + +- //! @todo add detection for other types if required ++ // TODO: add detection for other types if required + + return FileTypeUnknown; + } +diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp +index 20d9d82..937c969 100644 +--- a/xbmc/utils/RecentlyAddedJob.cpp ++++ b/xbmc/utils/RecentlyAddedJob.cpp +@@ -68,7 +68,7 @@ bool CRecentlyAddedJob::UpdateVideo() + + home->SetProperty("LatestMovie." + value + ".Title" , item->GetLabel()); + home->SetProperty("LatestMovie." + value + ".Rating" , strRating); +- home->SetProperty("LatestMovie." + value + ".Year" , item->GetVideoInfoTag()->GetYear()); ++ home->SetProperty("LatestMovie." + value + ".Year" , item->GetVideoInfoTag()->m_iYear); + home->SetProperty("LatestMovie." + value + ".Plot" , item->GetVideoInfoTag()->m_strPlot); + home->SetProperty("LatestMovie." + value + ".RunningTime" , item->GetVideoInfoTag()->GetDuration() / 60); + home->SetProperty("LatestMovie." + value + ".Path" , item->GetVideoInfoTag()->m_strFileNameAndPath); +@@ -159,7 +159,7 @@ bool CRecentlyAddedJob::UpdateVideo() + std::string value = StringUtils::Format("%i", i + 1); + + home->SetProperty("LatestMusicVideo." + value + ".Title" , item->GetLabel()); +- home->SetProperty("LatestMusicVideo." + value + ".Year" , item->GetVideoInfoTag()->GetYear()); ++ home->SetProperty("LatestMusicVideo." + value + ".Year" , item->GetVideoInfoTag()->m_iYear); + home->SetProperty("LatestMusicVideo." + value + ".Plot" , item->GetVideoInfoTag()->m_strPlot); + home->SetProperty("LatestMusicVideo." + value + ".RunningTime" , item->GetVideoInfoTag()->GetDuration() / 60); + home->SetProperty("LatestMusicVideo." + value + ".Path" , item->GetVideoInfoTag()->m_strFileNameAndPath); +diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp +index e0dbe58..0c12123 100644 +--- a/xbmc/utils/RssManager.cpp ++++ b/xbmc/utils/RssManager.cpp +@@ -145,8 +145,8 @@ bool CRssManager::Load() + + if (pFeed->FirstChild() != NULL) + { +- //! @todo UTF-8: Do these URLs need to be converted to UTF-8? +- //! What about the xml encoding? ++ // TODO: UTF-8: Do these URLs need to be converted to UTF-8? ++ // What about the xml encoding? + std::string strUrl = pFeed->FirstChild()->ValueStr(); + set.url.push_back(strUrl); + set.interval.push_back(iInterval); +diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp +index 9186f56..114a18c 100644 +--- a/xbmc/utils/RssReader.cpp ++++ b/xbmc/utils/RssReader.cpp +@@ -146,7 +146,7 @@ void CRssReader::Process() + + // we wait for the network to come up + if ((url.IsProtocol("http") || url.IsProtocol("https")) && +- !g_application.getNetwork().IsAvailable()) ++ !g_application.getNetwork().IsConnected()) + { + CLog::Log(LOGWARNING, "RSS: No network connection"); + strXML = "<rss><item><title>"+g_localizeStrings.Get(15301)+""; +diff --git a/xbmc/utils/SaveFileStateJob.cpp b/xbmc/utils/SaveFileStateJob.cpp +index 89ad9c8..8363a67 100644 +--- a/xbmc/utils/SaveFileStateJob.cpp ++++ b/xbmc/utils/SaveFileStateJob.cpp +@@ -34,7 +34,7 @@ + #include "guilib/GUIWindowManager.h" + #include "GUIUserMessages.h" + #include "music/MusicDatabase.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "xbmc/music/tags/MusicInfoTag.h" + + bool CSaveFileStateJob::DoWork() +diff --git a/xbmc/utils/ScraperParser.cpp b/xbmc/utils/ScraperParser.cpp +index 23e627f..57476ed 100644 +--- a/xbmc/utils/ScraperParser.cpp ++++ b/xbmc/utils/ScraperParser.cpp +@@ -28,9 +28,7 @@ + #include "utils/StringUtils.h" + #include "log.h" + #include "CharsetConverter.h" +-#ifdef HAVE_LIBXSLT + #include "utils/XSLTUtils.h" +-#endif + #include "utils/XMLUtils.h" + #include + #include +@@ -340,7 +338,6 @@ void CScraperParser::ParseExpression(const std::string& input, std::string& dest + + void CScraperParser::ParseXSLT(const std::string& input, std::string& dest, TiXmlElement* element, bool bAppend) + { +-#ifdef HAVE_LIBXSLT + TiXmlElement* pSheet = element->FirstChildElement(); + if (pSheet) + { +@@ -357,18 +354,13 @@ void CScraperParser::ParseXSLT(const std::string& input, std::string& dest, TiXm + + xsltUtils.XSLTTransform(dest); + } +-#endif + } + + TiXmlElement *FirstChildScraperElement(TiXmlElement *element) + { + for (TiXmlElement *child = element->FirstChildElement(); child; child = child->NextSiblingElement()) + { +-#ifdef HAVE_LIBXSLT +- if (child->ValueStr() == "XSLT") +- return child; +-#endif +- if (child->ValueStr() == "RegExp") ++ if (child->ValueStr() == "RegExp" || child->ValueStr() == "XSLT") + return child; + } + return NULL; +@@ -378,11 +370,7 @@ TiXmlElement *NextSiblingScraperElement(TiXmlElement *element) + { + for (TiXmlElement *next = element->NextSiblingElement(); next; next = next->NextSiblingElement()) + { +-#ifdef HAVE_LIBXSLT +- if (next->ValueStr() == "XSLT") +- return next; +-#endif +- if (next->ValueStr() == "RegExp") ++ if (next->ValueStr() == "RegExp" || next->ValueStr() == "XSLT") + return next; + } + return NULL; +@@ -444,11 +432,9 @@ void CScraperParser::ParseNext(TiXmlElement* element) + { + if (iDest-1 < MAX_SCRAPER_BUFFERS && iDest-1 > -1) + { +-#ifdef HAVE_LIBXSLT + if (pReg->ValueStr() == "XSLT") + ParseXSLT(strInput, m_param[iDest - 1], pReg, bAppend); + else +-#endif + ParseExpression(strInput, m_param[iDest - 1],pReg,bAppend); + } + else +diff --git a/xbmc/utils/Screen.cpp b/xbmc/utils/Screen.cpp +new file mode 100644 +index 0000000..b350fa8 +--- /dev/null ++++ b/xbmc/utils/Screen.cpp +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "Application.h" ++#include "utils/log.h" ++#include "settings/Settings.h" ++//#include "video/VideoReferenceClock.h" ++#include "guilib/GUIWindowManager.h" ++#include "utils/Screen.h" ++#include "windowing/WindowingFactory.h" ++#include "threads/SingleLock.h" ++#ifdef HAS_IMXVPU ++#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h" ++#elif defined(TARGET_RASPBERRY_PI) ++#include "linux/RBP.h" ++#endif ++#include "cores/AudioEngine/AEFactory.h" ++ ++using namespace ANNOUNCEMENT; ++ ++CScreen g_screen; ++ ++CScreen::CScreen() ++ : m_state(false) ++ , m_changedBlank(false) ++{ ++} ++ ++void CScreen::RegisterToAnnouncer() ++{ ++ CAnnouncementManager::GetInstance().AddAnnouncer(this); ++} ++ ++CScreen::~CScreen() ++{ ++} ++ ++void CScreen::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) ++{ ++ if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit")) ++ g_application.SetRenderGUI(true); ++ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated")) ++ g_screen.SetOn(); ++ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && CSettings::GetInstance().GetString("screensaver.mode") == "screensaver.xbmc.builtin.black") ++ { ++ if ((g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->IsPausedPlayback() && ++ !CSettings::GetInstance().GetBool(CSettings::SETTING_SCREENSAVER_USEDIMONPAUSE)) ++ || !g_application.m_pPlayer->IsPlaying()) ++ g_screen.SetOff(); ++ } ++/* ++ else if (flag == Player && !strcmp(sender, "xbmc") && !strcmp(message, "OnPlay")) ++ g_VideoReferenceClock.Start(); ++ else if (flag == Player && !strcmp(sender, "xbmc") && !strcmp(message, "OnPause")) ++ g_VideoReferenceClock.Stop(); ++*/ ++} ++ ++void CScreen::ScreenPowerOff(bool doBlank) ++{ ++ if (!doBlank || !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_BLANKCURRENT)) ++ return; ++ ++ m_changedBlank = true; ++#if defined(TARGET_RASPBERRY_PI) ++ g_RBP.SuspendVideoOutput(); ++#elif HAS_IMXVPU ++ CAEFactory::Suspend(); ++ // calling CIMXContext::Blank() tells CodecIMX ++ // fb1 is not ready ++ g_IMXContext.Blank(); ++ g_Windowing.Hide(); ++#endif ++} ++ ++void CScreen::ScreenPowerOn(bool doBlank) ++{ ++ if (!doBlank || !m_changedBlank) ++ return; ++ ++ m_changedBlank = false; ++#if defined(TARGET_RASPBERRY_PI) ++ g_RBP.ResumeVideoOutput(); ++#elif HAS_IMXVPU ++ g_Windowing.Show(); ++ g_IMXContext.Unblank(); ++ CAEFactory::Resume(); ++#endif ++} ++ ++void CScreen::SetState(bool state, bool doBlank) ++{ ++ if (g_application.m_bStop) ++ { ++ g_application.SetRenderGUI(true); ++ return; ++ } ++ ++ CSingleLock lock(m_critSection); ++ if (state == m_state) ++ return; ++ ++ CLog::Log(LOGDEBUG, "%s - set standby %d, screensaver is %s", __FUNCTION__, (int)state, g_application.IsInScreenSaver() ? "active" : "inactive"); ++ ++ m_state = state; ++ ++ switch (state) ++ { ++ case true: ++ if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPausedPlayback()) ++ return; ++ ++// g_VideoReferenceClock.Stop(); ++ ScreenPowerOff(doBlank); ++ if (!g_application.IsInScreenSaver()) ++ g_application.ActivateScreenSaver(); ++ ++ break; ++ case false: ++ g_application.WakeUpScreenSaverAndDPMS(); ++ ScreenPowerOn(doBlank); ++// if (g_application.m_pPlayer->IsPlayingVideo()) ++// g_VideoReferenceClock.Start(); ++ ++ default: ++ ; ++ } ++ ++ g_application.SetRenderGUI(!m_state); ++} +diff --git a/xbmc/utils/Screen.h b/xbmc/utils/Screen.h +new file mode 100644 +index 0000000..9ef0c48 +--- /dev/null ++++ b/xbmc/utils/Screen.h +@@ -0,0 +1,52 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "interfaces/AnnouncementManager.h" ++#include "threads/CriticalSection.h" ++#include "threads/Timer.h" ++ ++class CScreen : public ANNOUNCEMENT::IAnnouncer ++{ ++public: ++ CScreen(); ++ ~CScreen(); ++ ++ void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); ++ ++ void SetOff(bool doBlank = true) { SetState(true, doBlank); }; ++ void SetOn() { SetState(false); }; ++ void SwitchState() { SetState(!m_state, m_changedBlank); }; ++ ++ bool GetScreenState() { return m_state; } ++ ++ void RegisterToAnnouncer(); ++ ++private: ++ void SetState(bool status, bool doBlank = true); ++ void ScreenPowerOn(bool doBlank); ++ void ScreenPowerOff(bool doBlank); ++ ++ bool m_state; ++ bool m_changedBlank; ++ CCriticalSection m_critSection; ++}; ++ ++extern CScreen g_screen; +diff --git a/xbmc/utils/SortUtils.cpp b/xbmc/utils/SortUtils.cpp +index cff9637..f79c7dd 100644 +--- a/xbmc/utils/SortUtils.cpp ++++ b/xbmc/utils/SortUtils.cpp +@@ -190,7 +190,7 @@ std::string ByProgramCount(SortAttribute attributes, const SortItem &values) + + std::string ByPlaylistOrder(SortAttribute attributes, const SortItem &values) + { +- //! @todo Playlist order is hacked into program count variable (not nice, but ok until 2.0) ++ // TODO: Playlist order is hacked into program count variable (not nice, but ok until 2.0) + return ByProgramCount(attributes, values); + } + +diff --git a/xbmc/utils/SortUtils.h b/xbmc/utils/SortUtils.h +index e49c4fe..e9999ca 100644 +--- a/xbmc/utils/SortUtils.h ++++ b/xbmc/utils/SortUtils.h +@@ -20,9 +20,8 @@ + */ + + #include +-#include + #include +-#include ++#include + + #include "DatabaseUtils.h" + #include "SortFileItem.h" +diff --git a/xbmc/utils/Splash.cpp b/xbmc/utils/Splash.cpp +index 7e1d885..df50665 100644 +--- a/xbmc/utils/Splash.cpp ++++ b/xbmc/utils/Splash.cpp +@@ -72,6 +72,6 @@ void CSplash::Show() + + //show it on screen + g_Windowing.EndRender(); +- g_graphicsContext.Flip(true, false); ++ g_graphicsContext.Flip(true); + g_graphicsContext.Unlock(); + } +diff --git a/xbmc/utils/StringUtils.cpp b/xbmc/utils/StringUtils.cpp +index 197ae07..40b4d1a 100644 +--- a/xbmc/utils/StringUtils.cpp ++++ b/xbmc/utils/StringUtils.cpp +@@ -38,7 +38,7 @@ + #include "utils/fstrcmp.h" + #include "Util.h" + #include +-#include ++ + #include + #include + #include +@@ -1284,29 +1284,3 @@ void StringUtils::Tokenize(const std::string& input, std::vector& t + dataPos = input.find_first_not_of(delimiter, nextDelimPos); + } + } +- +-uint64_t StringUtils::ToUint64(std::string str, uint64_t fallback) noexcept +-{ +- std::istringstream iss(str); +- uint64_t result(fallback); +- iss >> result; +- return result; +-} +- +-std::string StringUtils::FormatFileSize(uint64_t bytes) +-{ +- const std::array units{"B", "kB", "MB", "GB", "TB", "PB"}; +- if (bytes < 1000) +- return Format("%lluB", bytes); +- +- int i = 0; +- double value = static_cast(bytes); +- while (i < units.size() - 1 && value >= 999.5) +- { +- ++i; +- value /= 1024.0; +- } +- int decimals = value < 9.995 ? 2 : (value < 99.95 ? 1 : 0); +- auto frmt = "%.0" + Format("%d", decimals) + "f%s"; +- return Format(frmt.c_str(), value, units[i].c_str()); +-} +diff --git a/xbmc/utils/StringUtils.h b/xbmc/utils/StringUtils.h +index d16e2b6..ad0e088 100644 +--- a/xbmc/utils/StringUtils.h ++++ b/xbmc/utils/StringUtils.h +@@ -244,17 +244,6 @@ public: + static void Tokenize(const std::string& input, std::vector& tokens, const std::string& delimiters); + static std::vector Tokenize(const std::string& input, const char delimiter); + static void Tokenize(const std::string& input, std::vector& tokens, const char delimiter); +- static uint64_t ToUint64(std::string str, uint64_t fallback) noexcept; +- +- /*! +- * Returns bytes in a human readable format using the smallest unit that will fit `bytes` in at +- * most three digits. The number of decimals are adjusted with significance such that 'small' +- * numbers will have more decimals than larger ones. +- * +- * For example: 1024 bytes will be formatted as "1.00kB", 10240 bytes as "10.0kB" and +- * 102400 bytes as "100kB". See TestStringUtils for more examples. +- */ +- static std::string FormatFileSize(uint64_t bytes); + }; + + struct sortstringbyname +diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp +index 06b2068..f569a0c 100644 +--- a/xbmc/utils/URIUtils.cpp ++++ b/xbmc/utils/URIUtils.cpp +@@ -631,9 +631,9 @@ bool URIUtils::IsOnLAN(const std::string& strPath) + + static bool addr_match(uint32_t addr, const char* target, const char* submask) + { +- uint32_t addr2 = ntohl(inet_addr(target)); +- uint32_t mask = ntohl(inet_addr(submask)); +- return (addr & mask) == (addr2 & mask); ++ struct in_addr in = { htonl(addr) }; ++ std::string address = inet_ntoa(in); ++ return CNetwork::AddrMatch(address, target, submask); + } + + bool URIUtils::IsHostOnLAN(const std::string& host, bool offLineCheck) +@@ -646,32 +646,19 @@ bool URIUtils::IsHostOnLAN(const std::string& host, bool offLineCheck) + if(host.find('.') == std::string::npos) + return true; + +- uint32_t address = ntohl(inet_addr(host.c_str())); +- if(address == INADDR_NONE) +- { +- std::string ip; +- if(CDNSNameCache::Lookup(host, ip)) +- address = ntohl(inet_addr(ip.c_str())); +- } ++ std::string address; ++ if (!CDNSNameCache::Lookup(host, address)) ++ return false; + +- if(address != INADDR_NONE) +- { +- if (offLineCheck) // check if in private range, ref https://en.wikipedia.org/wiki/Private_network +- { +- if ( +- addr_match(address, "192.168.0.0", "255.255.0.0") || +- addr_match(address, "10.0.0.0", "255.0.0.0") || +- addr_match(address, "172.16.0.0", "255.240.0.0") +- ) +- return true; +- } +- // check if we are on the local subnet +- if (!g_application.getNetwork().GetFirstConnectedInterface()) +- return false; ++ if (offLineCheck && /* check if in private range, ref https://en.wikipedia.org/wiki/Private_network */ ++ (CNetwork::AddrMatch(address, "192.168.0.0", "255.255.0.0") || ++ CNetwork::AddrMatch(address, "10.0.0.0", "255.0.0.0") || ++ CNetwork::AddrMatch(address, "172.16.0.0", "255.240.0.0")) ++ ) ++ return true; + +- if (g_application.getNetwork().HasInterfaceForIP(address)) +- return true; +- } ++ if (g_application.getNetwork().HasInterfaceForIP(address)) ++ return true; + + return false; + } +@@ -1005,6 +992,22 @@ bool URIUtils::IsNfs(const std::string& strFile) + return IsProtocol(strFile, "nfs"); + } + ++bool URIUtils::IsAfp(const std::string& strFile) ++{ ++ if (IsStack(strFile)) ++ return IsAfp(CStackDirectory::GetFirstStackedFile(strFile)); ++ ++ if (IsSpecial(strFile)) ++ return IsAfp(CSpecialProtocol::TranslatePath(strFile)); ++ ++ CURL url(strFile); ++ if (HasParentInHostname(url)) ++ return IsAfp(url.GetHostName()); ++ ++ return IsProtocol(strFile, "afp"); ++} ++ ++ + bool URIUtils::IsVideoDb(const std::string& strFile) + { + return IsProtocol(strFile, "videodb"); +@@ -1356,3 +1359,18 @@ bool URIUtils::IsUsingFastSwitch(const std::string& strFile) + { + return IsUDP(strFile) || IsTCP(strFile) || IsPVRChannel(strFile); + } ++ ++bool URIUtils::ConvIPv6(const std::string &address, struct sockaddr_in6 *sa) ++{ ++ return CNetwork::ConvIPv6(address, sa); ++} ++ ++bool URIUtils::ConvIPv4(const std::string &address, struct sockaddr_in *sa) ++{ ++ return CNetwork::ConvIPv4(address, sa); ++} ++ ++std::string URIUtils::CanonizeIPv6(const std::string &address) ++{ ++ return CNetwork::CanonizeIPv6(address); ++} +diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h +index f6be769..467eee4 100644 +--- a/xbmc/utils/URIUtils.h ++++ b/xbmc/utils/URIUtils.h +@@ -142,6 +142,7 @@ public: + static bool IsMultiPath(const std::string& strPath); + static bool IsMusicDb(const std::string& strFile); + static bool IsNfs(const std::string& strFile); ++ static bool IsAfp(const std::string& strFile); + static bool IsOnDVD(const std::string& strFile); + static bool IsOnLAN(const std::string& strFile); + static bool IsHostOnLAN(const std::string& hostName, bool offLineCheck = false); +@@ -221,6 +222,10 @@ public: + */ + static bool UpdateUrlEncoding(std::string &strFilename); + ++ static bool ConvIPv6(const std::string &address, struct sockaddr_in6 *sa = NULL); ++ static bool ConvIPv4(const std::string &address, struct sockaddr_in *sa = NULL); ++ static std::string CanonizeIPv6(const std::string &address); ++ + private: + static std::string resolvePath(const std::string &path); + }; +diff --git a/xbmc/utils/Weather.cpp b/xbmc/utils/Weather.cpp +index 36d2165..13f3fd9 100644 +--- a/xbmc/utils/Weather.cpp ++++ b/xbmc/utils/Weather.cpp +@@ -78,7 +78,7 @@ CWeatherJob::CWeatherJob(int location) + bool CWeatherJob::DoWork() + { + // wait for the network +- if (!g_application.getNetwork().IsAvailable()) ++ if (!g_application.getNetwork().IsConnected()) + return false; + + AddonPtr addon; +@@ -426,7 +426,7 @@ void CWeather::OnSettingAction(const CSetting *setting) + { + AddonPtr addon; + if (CAddonMgr::GetInstance().GetAddon(CSettings::GetInstance().GetString(CSettings::SETTING_WEATHER_ADDON), addon, ADDON_SCRIPT_WEATHER) && addon != NULL) +- { //! @todo maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true. ++ { // TODO: maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true. + CGUIDialogAddonSettings::ShowAndGetInput(addon); + Refresh(); + } +diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp +index 3443f12..ba31766 100644 +--- a/xbmc/utils/log.cpp ++++ b/xbmc/utils/log.cpp +@@ -17,6 +17,7 @@ + * . + * + */ ++#undef _DEBUG + + #include "log.h" + #include "system.h" +@@ -24,6 +25,8 @@ + #include "threads/Thread.h" + #include "utils/StringUtils.h" + #include "CompileInfo.h" ++#include "utils/TimeUtils.cpp" ++#include "settings/AdvancedSettings.h" + + static const char* const levelNames[] = + {"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"}; +@@ -166,25 +169,24 @@ int CLog::GetLogLevel() + void CLog::SetExtraLogLevels(int level) + { + CSingleLock waitLock(s_globals.critSec); +- s_globals.m_extraLogLevels = level; ++ s_globals.m_extraLogLevels = level & ~LOGMASK; + } + + bool CLog::IsLogLevelLogged(int loglevel) + { + const int extras = (loglevel & ~LOGMASK); +- if (extras != 0 && (s_globals.m_extraLogLevels & extras) == 0) +- return false; ++ const bool canlog = (extras ? g_advancedSettings.CanLogComponent(extras) : true); + + #if defined(_DEBUG) || defined(PROFILE) + return true; + #else + if (s_globals.m_logLevel >= LOG_LEVEL_DEBUG) +- return true; ++ return canlog; + if (s_globals.m_logLevel <= LOG_LEVEL_NONE) + return false; + + // "m_logLevel" is "LOG_LEVEL_NORMAL" +- return (loglevel & LOGMASK) >= LOGNOTICE; ++ return ((loglevel & LOGMASK) >= LOGNOTICE) && canlog; + #endif + } + +@@ -198,21 +200,33 @@ void CLog::PrintDebugString(const std::string& line) + + bool CLog::WriteLogString(int logLevel, const std::string& logString) + { ++#if defined(TARGET_LINUX) ++ static const char* prefixFormat = "%02.2d:%02.2d:%02.2d %10.6f T:%" PRIu64" %7s: "; ++#else + static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%" PRIu64" %7s: "; +- ++#endif + std::string strData(logString); + /* fixup newline alignment, number of spaces should equal prefix length */ + StringUtils::Replace(strData, "\n", "\n "); + + int hour, minute, second; + s_globals.m_platform.GetCurrentLocalTime(hour, minute, second); +- ++ ++#if defined(TARGET_LINUX) ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ float Now = now.tv_sec + now.tv_nsec * 1e-9; ++#endif ++ + strData = StringUtils::Format(prefixFormat, + hour, + minute, + second, ++#if defined(TARGET_LINUX) ++ Now, ++#endif + (uint64_t)CThread::GetCurrentThreadId(), +- levelNames[logLevel]) + strData; ++ levelNames[logLevel & LOGMASK]) + strData; + + return s_globals.m_platform.WriteStringToLog(strData); + } +diff --git a/xbmc/utils/test/TestCPUInfo.cpp b/xbmc/utils/test/TestCPUInfo.cpp +index f5ec5a9..c17b14f 100644 +--- a/xbmc/utils/test/TestCPUInfo.cpp ++++ b/xbmc/utils/test/TestCPUInfo.cpp +@@ -130,7 +130,7 @@ TEST(TestCPUInfo, GetCPUFeatures) + TEST(TestCPUInfo, getUsedPercentage_output) + { + CCPUInfo c; +- Sleep(1); //! @todo Support option from main that sets this parameter ++ Sleep(1); /* TODO: Support option from main that sets this parameter */ + int r = c.getUsedPercentage(); + std::cout << "Percentage: " << testing::PrintToString(r) << std::endl; + } +diff --git a/xbmc/utils/test/TestCharsetConverter.cpp b/xbmc/utils/test/TestCharsetConverter.cpp +index b9fafd0..97f2344 100644 +--- a/xbmc/utils/test/TestCharsetConverter.cpp ++++ b/xbmc/utils/test/TestCharsetConverter.cpp +@@ -89,8 +89,7 @@ protected: + /* Add default settings for locale. + * Settings here are taken from CGUISettings::Initialize() + */ +- /* +- //! @todo implement ++ /* TODO + CSettingsCategory *loc = CSettings::GetInstance().AddCategory(7, "locale", 14090); + CSettings::GetInstance().AddString(loc, CSettings::SETTING_LOCALE_LANGUAGE,248,"english", + SPIN_CONTROL_TEXT); +@@ -133,7 +132,7 @@ TEST_F(TestCharsetConverter, utf8ToW) + //TEST_F(TestCharsetConverter, utf16LEtoW) + //{ + // refstrw1 = L"test_utf16LEtow"; +-// //! @todo Should be able to use '=' operator instead of assign() ++// /* TODO: Should be able to use '=' operator instead of assign() */ + // std::wstring refstr16_1; + // refstr16_1.assign(refutf16LE1); + // varstrw1.clear(); +@@ -249,7 +248,7 @@ TEST_F(TestCharsetConverter, isValidUtf8_4) + EXPECT_FALSE(CUtf8Utils::isValidUtf8(refutf16LE3)); + } + +-//! @todo Resolve correct input/output for this function ++/* TODO: Resolve correct input/output for this function */ + // TEST_F(TestCharsetConverter, ucs2CharsetToStringCharset) + // { + // void ucs2CharsetToStringCharset(const std::wstring& strSource, +@@ -301,7 +300,7 @@ TEST_F(TestCharsetConverter, utf8logicalToVisualBiDi) + EXPECT_STREQ(refstra2.c_str(), varstra1.c_str()); + } + +-//! @todo Resolve correct input/output for this function ++/* TODO: Resolve correct input/output for this function */ + // TEST_F(TestCharsetConverter, utf32ToStringCharset) + // { + // void utf32ToStringCharset(const unsigned long* strSource, std::string& strDest); +diff --git a/xbmc/utils/test/TestDatabaseUtils.cpp b/xbmc/utils/test/TestDatabaseUtils.cpp +index 1f2ce32..1207829 100644 +--- a/xbmc/utils/test/TestDatabaseUtils.cpp ++++ b/xbmc/utils/test/TestDatabaseUtils.cpp +@@ -360,6 +360,11 @@ TEST(TestDatabaseUtils, GetField_MediaTypeMusicVideo) + DatabaseQueryPartSelect); + EXPECT_STREQ(refstr.c_str(), varstr.c_str()); + ++ refstr = StringUtils::Format("musicvideo_view.c%02d",VIDEODB_ID_MUSICVIDEO_YEAR); ++ varstr = DatabaseUtils::GetField(FieldYear, MediaTypeMusicVideo, ++ DatabaseQueryPartSelect); ++ EXPECT_STREQ(refstr.c_str(), varstr.c_str()); ++ + refstr = StringUtils::Format("musicvideo_view.c%02d",VIDEODB_ID_MUSICVIDEO_PLOT); + varstr = DatabaseUtils::GetField(FieldPlot, MediaTypeMusicVideo, + DatabaseQueryPartSelect); +@@ -482,6 +487,11 @@ TEST(TestDatabaseUtils, GetField_MediaTypeMovie) + DatabaseQueryPartSelect); + EXPECT_STREQ(refstr.c_str(), varstr.c_str()); + ++ refstr = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_YEAR); ++ varstr = DatabaseUtils::GetField(FieldYear, MediaTypeMovie, ++ DatabaseQueryPartSelect); ++ EXPECT_STREQ(refstr.c_str(), varstr.c_str()); ++ + refstr = StringUtils::Format("movie_view.c%02d", VIDEODB_ID_SORTTITLE); + varstr = DatabaseUtils::GetField(FieldSortTitle, MediaTypeMovie, + DatabaseQueryPartSelect); +@@ -812,7 +822,7 @@ TEST(TestDatabaseUtils, GetFieldIndex_None) + EXPECT_EQ(refindex, varindex); + } + +-//! @todo Should enums in CMusicDatabase be made public instead? ++/* TODO: Should enums in CMusicDatabase be made public instead? */ + TEST(TestDatabaseUtils, GetFieldIndex_MediaTypeAlbum) + { + int refindex, varindex; +@@ -985,6 +995,10 @@ TEST(TestDatabaseUtils, GetFieldIndex_MediaTypeMusicVideo) + varindex = DatabaseUtils::GetFieldIndex(FieldStudio, MediaTypeMusicVideo); + EXPECT_EQ(refindex, varindex); + ++ refindex = VIDEODB_ID_MUSICVIDEO_YEAR + 2; ++ varindex = DatabaseUtils::GetFieldIndex(FieldYear, MediaTypeMusicVideo); ++ EXPECT_EQ(refindex, varindex); ++ + refindex = VIDEODB_ID_MUSICVIDEO_PLOT + 2; + varindex = DatabaseUtils::GetFieldIndex(FieldPlot, MediaTypeMusicVideo); + EXPECT_EQ(refindex, varindex); +@@ -1029,10 +1043,6 @@ TEST(TestDatabaseUtils, GetFieldIndex_MediaTypeMusicVideo) + varindex = DatabaseUtils::GetFieldIndex(FieldUserRating, MediaTypeMusicVideo); + EXPECT_EQ(refindex, varindex); + +- refindex = VIDEODB_DETAILS_MUSICVIDEO_PREMIERED; +- varindex = DatabaseUtils::GetFieldIndex(FieldYear, MediaTypeMusicVideo); +- EXPECT_EQ(refindex, varindex); +- + refindex = -1; + varindex = DatabaseUtils::GetFieldIndex(FieldRandom, MediaTypeMusicVideo); + EXPECT_EQ(refindex, varindex); +@@ -1070,6 +1080,10 @@ TEST(TestDatabaseUtils, GetFieldIndex_MediaTypeMovie) + varindex = DatabaseUtils::GetFieldIndex(FieldWriter, MediaTypeMovie); + EXPECT_EQ(refindex, varindex); + ++ refindex = VIDEODB_ID_YEAR + 2; ++ varindex = DatabaseUtils::GetFieldIndex(FieldYear, MediaTypeMovie); ++ EXPECT_EQ(refindex, varindex); ++ + refindex = VIDEODB_ID_RUNTIME + 2; + varindex = DatabaseUtils::GetFieldIndex(FieldTime, MediaTypeMovie); + EXPECT_EQ(refindex, varindex); +@@ -1134,10 +1148,6 @@ TEST(TestDatabaseUtils, GetFieldIndex_MediaTypeMovie) + varindex = DatabaseUtils::GetFieldIndex(FieldRating, MediaTypeMovie); + EXPECT_EQ(refindex, varindex); + +- refindex = VIDEODB_DETAILS_MOVIE_PREMIERED; +- varindex = DatabaseUtils::GetFieldIndex(FieldYear, MediaTypeMovie); +- EXPECT_EQ(refindex, varindex); +- + refindex = -1; + varindex = DatabaseUtils::GetFieldIndex(FieldRandom, MediaTypeMovie); + EXPECT_EQ(refindex, varindex); +@@ -1347,7 +1357,7 @@ TEST(TestDatabaseUtils, GetFieldValue) + EXPECT_TRUE(v_string.isString()); + } + +-//! @todo Need some way to test this function ++/* TODO: Need some way to test this function */ + // TEST(TestDatabaseUtils, GetDatabaseResults) + // { + // static bool GetDatabaseResults(MediaType mediaType, const FieldList &fields, +diff --git a/xbmc/utils/test/TestJobManager.cpp b/xbmc/utils/test/TestJobManager.cpp +index f306322..f6e975e 100644 +--- a/xbmc/utils/test/TestJobManager.cpp ++++ b/xbmc/utils/test/TestJobManager.cpp +@@ -30,8 +30,7 @@ class TestJobManager : public testing::Test + protected: + TestJobManager() + { +- //! @todo implement +- /* ++ /* TODO + CSettingsCategory* net = CSettings::GetInstance().AddCategory(4, "network", 798); + CSettings::GetInstance().AddBool(net, CSettings::SETTING_NETWORK_USEHTTPPROXY, 708, false); + CSettings::GetInstance().AddString(net, CSettings::SETTING_NETWORK_HTTPPROXYSERVER, 706, "", +diff --git a/xbmc/utils/test/TestLabelFormatter.cpp b/xbmc/utils/test/TestLabelFormatter.cpp +index 4dfa004..5c37f8f 100644 +--- a/xbmc/utils/test/TestLabelFormatter.cpp ++++ b/xbmc/utils/test/TestLabelFormatter.cpp +@@ -33,7 +33,6 @@ class TestLabelFormatter : public testing::Test + protected: + TestLabelFormatter() + { +- //! @todo implement + /* TODO + CSettingsCategory* fl = CSettings::GetInstance().AddCategory(7, "filelists", 14081); + CSettings::GetInstance().AddBool(fl, CSettings::SETTING_FILELISTS_SHOWPARENTDIRITEMS, 13306, true); +diff --git a/xbmc/utils/test/TestRegExp.cpp b/xbmc/utils/test/TestRegExp.cpp +index 796cf8d..c161aff 100644 +--- a/xbmc/utils/test/TestRegExp.cpp ++++ b/xbmc/utils/test/TestRegExp.cpp +@@ -18,7 +18,7 @@ + * + */ + +-/** @todo gtest/gtest.h needs to come in before utils/RegExp.h. ++/* TODO: gtest/gtest.h needs to come in before utils/RegExp.h. + * Investigate why. + */ + #include "gtest/gtest.h" +diff --git a/xbmc/utils/test/TestStringUtils.cpp b/xbmc/utils/test/TestStringUtils.cpp +index 16e5e76..ccabbbb 100644 +--- a/xbmc/utils/test/TestStringUtils.cpp ++++ b/xbmc/utils/test/TestStringUtils.cpp +@@ -525,26 +525,3 @@ TEST(TestStringUtils, sortstringbyname) + EXPECT_STREQ("B", strarray[1].c_str()); + EXPECT_STREQ("c", strarray[2].c_str()); + } +- +-TEST(TestStringUtils, FileSizeFormat) +-{ +- EXPECT_STREQ("0B", StringUtils::FormatFileSize(0).c_str()); +- +- EXPECT_STREQ("999B", StringUtils::FormatFileSize(999).c_str()); +- EXPECT_STREQ("0.98kB", StringUtils::FormatFileSize(1000).c_str()); +- +- EXPECT_STREQ("1.00kB", StringUtils::FormatFileSize(1024).c_str()); +- EXPECT_STREQ("9.99kB", StringUtils::FormatFileSize(10229).c_str()); +- +- EXPECT_STREQ("10.1kB", StringUtils::FormatFileSize(10387).c_str()); +- EXPECT_STREQ("99.9kB", StringUtils::FormatFileSize(102297).c_str()); +- +- EXPECT_STREQ("100kB", StringUtils::FormatFileSize(102400).c_str()); +- EXPECT_STREQ("999kB", StringUtils::FormatFileSize(1023431).c_str()); +- +- EXPECT_STREQ("0.98MB", StringUtils::FormatFileSize(1023897).c_str()); +- EXPECT_STREQ("0.98MB", StringUtils::FormatFileSize(1024000).c_str()); +- +- //Last unit should overflow the 3 digit limit +- EXPECT_STREQ("5432PB", StringUtils::FormatFileSize(6115888293969133568).c_str()); +-} +diff --git a/xbmc/utils/test/TestURIUtils.cpp b/xbmc/utils/test/TestURIUtils.cpp +index 13f93a7..cb987ac 100644 +--- a/xbmc/utils/test/TestURIUtils.cpp ++++ b/xbmc/utils/test/TestURIUtils.cpp +@@ -333,6 +333,12 @@ TEST_F(TestURIUtils, IsNfs) + EXPECT_TRUE(URIUtils::IsNfs("stack://nfs://path/to/file")); + } + ++TEST_F(TestURIUtils, IsAfp) ++{ ++ EXPECT_TRUE(URIUtils::IsAfp("afp://path/to/file")); ++ EXPECT_TRUE(URIUtils::IsAfp("stack://afp://path/to/file")); ++} ++ + TEST_F(TestURIUtils, IsOnDVD) + { + EXPECT_TRUE(URIUtils::IsOnDVD("dvd://path/to/file")); +diff --git a/xbmc/video/ContextMenus.cpp b/xbmc/video/ContextMenus.cpp +index 540fa80..de20bd4 100644 +--- a/xbmc/video/ContextMenus.cpp ++++ b/xbmc/video/ContextMenus.cpp +@@ -22,7 +22,6 @@ + #include "Application.h" + #include "Autorun.h" + #include "video/dialogs/GUIDialogVideoInfo.h" +-#include "video/windows/GUIWindowVideoBase.h" + + + namespace CONTEXTMENU +@@ -115,7 +114,7 @@ std::string CPlay::GetLabel(const CFileItem& item) const + bool CPlay::IsVisible(const CFileItem& item) const + { + if (item.m_bIsFolder) +- return false; //! @todo implement ++ return false; //TODO: implement + return item.IsVideo() || item.IsDVD() || item.IsCDDA(); + } + +diff --git a/xbmc/video/ContextMenus.h b/xbmc/video/ContextMenus.h +index 33cbd62..fbfcf07 100644 +--- a/xbmc/video/ContextMenus.h ++++ b/xbmc/video/ContextMenus.h +@@ -21,6 +21,7 @@ + + #include "ContextMenuItem.h" + #include "guilib/GUIWindowManager.h" ++#include "video/windows/GUIWindowVideoNav.h" + #include "VideoLibraryQueue.h" + + namespace CONTEXTMENU +diff --git a/xbmc/video/Episode.h b/xbmc/video/Episode.h +index 22cd76b..de29450 100644 +--- a/xbmc/video/Episode.h ++++ b/xbmc/video/Episode.h +@@ -18,10 +18,6 @@ + * . + * + */ +- +-#include +-#include +- + #include "utils/ScraperUrl.h" + #include "XBDateTime.h" + +diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp +index 85e8e14..8704c43 100644 +--- a/xbmc/video/GUIViewStateVideo.cpp ++++ b/xbmc/video/GUIViewStateVideo.cpp +@@ -56,6 +56,46 @@ VECSOURCES& CGUIViewStateWindowVideo::GetSources() + return CGUIViewState::GetSources(); + } + ++CGUIViewStateWindowVideoFiles::CGUIViewStateWindowVideoFiles(const CFileItemList& items) : CGUIViewStateWindowVideo(items) ++{ ++ if (items.IsVirtualDirectoryRoot()) ++ { ++ AddSortMethod(SortByLabel, 551, LABEL_MASKS()); // Preformated ++ AddSortMethod(SortByDriveType, 564, LABEL_MASKS()); // Preformated ++ SetSortMethod(SortByLabel); ++ ++ SetViewAsControl(DEFAULT_VIEW_LIST); ++ ++ SetSortOrder(SortOrderAscending); ++ } ++ else ++ { ++ AddSortMethod(SortByLabel, 551, LABEL_MASKS("%L", "%I", "%L", ""), // Label, Size | Label, empty ++ CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING) ? SortAttributeIgnoreArticle : SortAttributeNone); ++ AddSortMethod(SortBySize, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // Label, Size | Label, Size ++ AddSortMethod(SortByDate, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); // Label, Date | Label, Date ++ AddSortMethod(SortByFile, 561, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty ++ ++ const CViewState *viewState = CViewStateSettings::GetInstance().Get("videofiles"); ++ SetSortMethod(viewState->m_sortDescription); ++ SetViewAsControl(viewState->m_viewMode); ++ SetSortOrder(viewState->m_sortDescription.sortOrder); ++ } ++ LoadViewState(items.GetPath(), WINDOW_VIDEO_FILES); ++} ++ ++void CGUIViewStateWindowVideoFiles::SaveViewState() ++{ ++ SaveViewToDb(m_items.GetPath(), WINDOW_VIDEO_FILES, CViewStateSettings::GetInstance().Get("videofiles")); ++} ++ ++VECSOURCES& CGUIViewStateWindowVideoFiles::GetSources() ++{ ++ VECSOURCES *videoSources = CMediaSourceSettings::GetInstance().GetSources("video"); ++ AddOrReplace(*videoSources, CGUIViewStateWindowVideo::GetSources()); ++ return *videoSources; ++} ++ + CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& items) : CGUIViewStateWindowVideo(items) + { + SortAttribute sortAttributes = SortAttributeNone; +diff --git a/xbmc/video/GUIViewStateVideo.h b/xbmc/video/GUIViewStateVideo.h +index ec63c71..31d7dba 100644 +--- a/xbmc/video/GUIViewStateVideo.h ++++ b/xbmc/video/GUIViewStateVideo.h +@@ -34,6 +34,16 @@ protected: + virtual std::string GetExtensions(); + }; + ++class CGUIViewStateWindowVideoFiles : public CGUIViewStateWindowVideo ++{ ++public: ++ CGUIViewStateWindowVideoFiles(const CFileItemList& items); ++ ++protected: ++ virtual void SaveViewState(); ++ virtual VECSOURCES& GetSources(); ++}; ++ + class CGUIViewStateWindowVideoNav : public CGUIViewStateWindowVideo + { + public: +diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp +index b02a203..201dd7a 100644 +--- a/xbmc/video/VideoDatabase.cpp ++++ b/xbmc/video/VideoDatabase.cpp +@@ -125,7 +125,7 @@ void CVideoDatabase::CreateTables() + for (int i = 0; i < VIDEODB_MAX_COLUMNS; i++) + columns += StringUtils::Format(",c%02d text", i); + +- columns += ", idSet integer, userrating integer, premiered text)"; ++ columns += ", idSet integer, userrating integer)"; + m_pDS->exec(columns); + + CLog::Log(LOGINFO, "create actor table"); +@@ -179,7 +179,7 @@ void CVideoDatabase::CreateTables() + for (int i = 0; i < VIDEODB_MAX_COLUMNS; i++) + columns += StringUtils::Format(",c%02d text", i); + +- columns += ", userrating integer, premiered text)"; ++ columns += ", userrating integer)"; + m_pDS->exec(columns); + + CLog::Log(LOGINFO, "create streaminfo table"); +@@ -269,8 +269,6 @@ void CVideoDatabase::CreateAnalytics() + m_pDS->exec("CREATE INDEX ix_seasons ON seasons (idShow, season)"); + m_pDS->exec("CREATE INDEX ix_art ON art(media_id, media_type(20), type(20))"); + +- m_pDS->exec("CREATE INDEX ix_rating ON rating(media_id, media_type(20))"); +- + CreateLinkIndex("tag"); + CreateLinkIndex("actor"); + CreateForeignLinkIndex("director", "actor"); +@@ -1848,7 +1846,7 @@ void CVideoDatabase::GetMusicVideosByArtist(const std::string& strArtist, CFileI + if (NULL == m_pDS.get()) return ; + + std::string strSQL; +- if (strArtist.empty()) //! @todo SMARTPLAYLISTS what is this here for??? ++ if (strArtist.empty()) // TODO: SMARTPLAYLISTS what is this here for??? + strSQL=PrepareSQL("select distinct * from musicvideo_view join actor_link on actor_link.media_id=musicvideo_view.idMVideo AND actor_link.media_type='musicvideo' join actor on actor.actor_id=actor_link.actor_id"); + else + strSQL=PrepareSQL("select * from musicvideo_view join actor_link on actor_link.media_id=musicvideo_view.idMVideo AND actor_link.media_type='musicvideo' join actor on actor.actor_id=actor_link.actor_id where actor.name='%s'", strArtist.c_str()); +@@ -2107,8 +2105,6 @@ std::string CVideoDatabase::GetValueString(const CVideoInfoTag &details, int min + case VIDEODB_TYPE_DATETIME: + conditions.emplace_back(PrepareSQL("c%02d='%s'", i, ((CDateTime*)(((char*)&details)+offsets[i].offset))->GetAsDBDateTime().c_str())); + break; +- case VIDEODB_TYPE_UNUSED: // Skip the unused field to avoid populating unused data +- continue; + } + } + return StringUtils::Join(conditions, ","); +@@ -2190,7 +2186,7 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV + AddActorLinksToItem(idMovie, MediaTypeMovie, "writer", details.m_writingCredits); + + // add ratings +- details.m_iIdRating = AddRatings(idMovie, MediaTypeMovie, details.m_ratings, details.GetDefaultRating()); ++ details.m_iIdRating = AddRatings(idMovie, MediaTypeMovie, details.m_ratings, details.m_strDefaultRating); + + // add set... + int idSet = -1; +@@ -2208,9 +2204,9 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV + + SetArtForItem(idMovie, MediaTypeMovie, artwork); + +- if (!details.m_strIMDBNumber.empty() && details.HasYear()) ++ if (!details.m_strIMDBNumber.empty() && details.m_iYear) + { // query DB for any movies matching imdbid and year +- std::string strSQL = PrepareSQL("SELECT files.playCount, files.lastPlayed FROM movie INNER JOIN files ON files.idFile=movie.idFile WHERE movie.c%02d='%s' AND movie.premiered LIKE '%i%%' AND movie.idMovie!=%i AND files.playCount > 0", VIDEODB_ID_IDENT, details.m_strIMDBNumber.c_str(), details.GetYear(), idMovie); ++ std::string strSQL = PrepareSQL("SELECT files.playCount, files.lastPlayed FROM movie INNER JOIN files ON files.idFile=movie.idFile WHERE movie.c%02d='%s' AND movie.c%02d=%i AND movie.idMovie!=%i AND files.playCount > 0", VIDEODB_ID_IDENT, details.m_strIMDBNumber.c_str(), VIDEODB_ID_YEAR, details.m_iYear, idMovie); + m_pDS->query(strSQL); + + if (!m_pDS->eof()) +@@ -2240,10 +2236,6 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV + sql += PrepareSQL(", userrating = %i", details.m_iUserRating); + else + sql += ", userrating = NULL"; +- if (details.HasPremiered()) +- sql += PrepareSQL(", premiered = '%s'", details.GetPremiered().GetAsDBDate().c_str()); +- else +- sql += PrepareSQL(", premiered = '%i'", details.GetYear()); + sql += PrepareSQL(" where idMovie=%i", idMovie); + m_pDS->exec(sql); + CommitTransaction(); +@@ -2285,7 +2277,7 @@ int CVideoDatabase::UpdateDetailsForMovie(int idMovie, CVideoInfoTag& details, c + if (updatedDetails.find("art.altered") != updatedDetails.end()) + SetArtForItem(idMovie, MediaTypeMovie, artwork); + if (updatedDetails.find("ratings") != updatedDetails.end()) +- details.m_iIdRating = UpdateRatings(idMovie, MediaTypeMovie, details.m_ratings, details.GetDefaultRating()); ++ details.m_iIdRating = UpdateRatings(idMovie, MediaTypeMovie, details.m_ratings, details.m_strDefaultRating); + if (updatedDetails.find("dateadded") != updatedDetails.end() && details.m_dateAdded.IsValid()) + { + if (details.m_iFileId <= 0) +@@ -2339,10 +2331,6 @@ int CVideoDatabase::UpdateDetailsForMovie(int idMovie, CVideoInfoTag& details, c + sql += PrepareSQL(", userrating = %i", details.m_iUserRating); + else + sql += ", userrating = NULL"; +- if (details.HasPremiered()) +- sql += PrepareSQL(", premiered = '%s'", details.GetPremiered().GetAsDBDate().c_str()); +- else +- sql += PrepareSQL(", premiered = '%i'", details.GetYear()); + sql += PrepareSQL(" where idMovie=%i", idMovie); + m_pDS->exec(sql); + +@@ -2402,7 +2390,7 @@ int CVideoDatabase::GetMatchingTvShow(const CVideoInfoTag &details) + if (!details.m_strIMDBNumber.empty()) + id = GetDbId(PrepareSQL("SELECT idShow from tvshow WHERE c%02d='%s'", VIDEODB_ID_TV_IDENT, details.m_strIMDBNumber.c_str())); + if (id < 0) +- id = GetDbId(PrepareSQL("SELECT idShow FROM tvshow WHERE c%02d='%s' AND c%02d='%s'", VIDEODB_ID_TV_TITLE, details.m_strTitle.c_str(), VIDEODB_ID_TV_PREMIERED, details.GetPremiered().GetAsDBDate().c_str())); ++ id = GetDbId(PrepareSQL("SELECT idShow FROM tvshow WHERE c%02d='%s' AND c%02d='%s'", VIDEODB_ID_TV_TITLE, details.m_strTitle.c_str(), VIDEODB_ID_TV_PREMIERED, details.m_premiered.GetAsDBDate().c_str())); + return id; + } + +@@ -2461,7 +2449,7 @@ bool CVideoDatabase::UpdateDetailsForTvShow(int idTvShow, CVideoInfoTag &details + AddActorLinksToItem(idTvShow, MediaTypeTvShow, "director", details.m_director); + + // add ratings +- details.m_iIdRating = AddRatings(idTvShow, MediaTypeTvShow, details.m_ratings, details.GetDefaultRating()); ++ details.m_iIdRating = AddRatings(idTvShow, MediaTypeTvShow, details.m_ratings, details.m_strDefaultRating); + + // add "all seasons" - the rest are added in SetDetailsForEpisode + AddSeason(idTvShow, -1); +@@ -2590,7 +2578,7 @@ int CVideoDatabase::SetDetailsForEpisode(const std::string& strFilenameAndPath, + AddActorLinksToItem(idEpisode, MediaTypeEpisode, "writer", details.m_writingCredits); + + // add ratings +- details.m_iIdRating = AddRatings(idEpisode, MediaTypeEpisode, details.m_ratings, details.GetDefaultRating()); ++ details.m_iIdRating = AddRatings(idEpisode, MediaTypeEpisode, details.m_ratings, details.m_strDefaultRating); + + if (details.HasStreamDetails()) + { +@@ -2725,10 +2713,6 @@ int CVideoDatabase::SetDetailsForMusicVideo(const std::string& strFilenameAndPat + sql += PrepareSQL(", userrating = %i", details.m_iUserRating); + else + sql += ", userrating = NULL"; +- if (details.HasPremiered()) +- sql += PrepareSQL(", premiered = '%s'", details.GetPremiered().GetAsDBDate().c_str()); +- else +- sql += PrepareSQL(", premiered = '%i'", details.GetYear()); + sql += PrepareSQL(" where idMVideo=%i", idMVideo); + m_pDS->exec(sql); + CommitTransaction(); +@@ -3178,7 +3162,7 @@ void CVideoDatabase::DeleteMovie(int idMovie, bool bKeepId /* = false */) + m_pDS->exec(strSQL); + } + +- //! @todo move this below CommitTransaction() once UPnP doesn't rely on this anymore ++ // TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore + if (!bKeepId) + AnnounceRemove(MediaTypeMovie, idMovie); + +@@ -3241,7 +3225,7 @@ void CVideoDatabase::DeleteTvShow(int idTvShow, bool bKeepId /* = false */) + } + } + +- //! @todo move this below CommitTransaction() once UPnP doesn't rely on this anymore ++ //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore + if (!bKeepId) + AnnounceRemove(MediaTypeTvShow, idTvShow); + +@@ -3307,7 +3291,7 @@ void CVideoDatabase::DeleteEpisode(int idEpisode, bool bKeepId /* = false */) + if (NULL == m_pDB.get()) return ; + if (NULL == m_pDS.get()) return ; + +- //! @todo move this below CommitTransaction() once UPnP doesn't rely on this anymore ++ //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore + if (!bKeepId) + AnnounceRemove(MediaTypeEpisode, idEpisode); + +@@ -3363,7 +3347,7 @@ void CVideoDatabase::DeleteMusicVideo(int idMVideo, bool bKeepId /* = false */) + m_pDS->exec(strSQL); + } + +- //! @todo move this below CommitTransaction() once UPnP doesn't rely on this anymore ++ //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore + if (!bKeepId) + AnnounceRemove(MediaTypeMusicVideo, idMVideo); + +@@ -3489,8 +3473,6 @@ void CVideoDatabase::GetDetailsFromDB(const dbiplus::sql_record* const record, i + case VIDEODB_TYPE_DATETIME: + ((CDateTime*)(((char*)&details)+offsets[i].offset))->SetFromDBDateTime(record->at(i+idxOffset).get_asString()); + break; +- case VIDEODB_TYPE_UNUSED: // Skip the unused field to avoid populating unused data +- continue; + } + } + } +@@ -3677,14 +3659,9 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons + details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_MOVIE_TOTAL_TIME).get_asInt(); + details.m_resumePoint.type = CBookmark::RESUME; + details.m_iUserRating = record->at(VIDEODB_DETAILS_MOVIE_USER_RATING).get_asInt(); +- details.AddRating(record->at(VIDEODB_DETAILS_MOVIE_RATING).get_asFloat(), +- record->at(VIDEODB_DETAILS_MOVIE_VOTES).get_asInt(), +- record->at(VIDEODB_DETAILS_MOVIE_RATING_TYPE).get_asString(), true); +- std::string premieredString = record->at(VIDEODB_DETAILS_MOVIE_PREMIERED).get_asString(); +- if (premieredString.size() == 4) +- details.SetYear(record->at(VIDEODB_DETAILS_MOVIE_PREMIERED).get_asInt()); +- else +- details.SetPremieredFromDBDate(premieredString); ++ details.AddRating(record->at(VIDEODB_DETAILS_MOVIE_RATING).get_asFloat(), ++ record->at(VIDEODB_DETAILS_MOVIE_VOTES).get_asInt(), ++ record->at(VIDEODB_DETAILS_MOVIE_RATING_TYPE).get_asString()); + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); + + if (getDetails) +@@ -3743,7 +3720,6 @@ CVideoInfoTag CVideoDatabase::GetDetailsForTvShow(const dbiplus::sql_record* con + int idTvShow = record->at(0).get_asInt(); + + GetDetailsFromDB(record, VIDEODB_ID_TV_MIN, VIDEODB_ID_TV_MAX, DbTvShowOffsets, details, 1); +- details.m_bHasPremiered = details.m_premiered.IsValid(); + details.m_iDbId = idTvShow; + details.m_type = MediaTypeTvShow; + details.m_strPath = record->at(VIDEODB_DETAILS_TVSHOW_PATH).get_asString(); +@@ -3755,10 +3731,12 @@ CVideoInfoTag CVideoDatabase::GetDetailsForTvShow(const dbiplus::sql_record* con + details.m_iEpisode = record->at(VIDEODB_DETAILS_TVSHOW_NUM_EPISODES).get_asInt(); + details.m_playCount = record->at(VIDEODB_DETAILS_TVSHOW_NUM_WATCHED).get_asInt(); + details.m_strShowTitle = details.m_strTitle; ++ if (details.m_premiered.IsValid()) ++ details.m_iYear = details.m_premiered.GetYear(); + details.m_iUserRating = record->at(VIDEODB_DETAILS_TVSHOW_USER_RATING).get_asInt(); +- details.AddRating(record->at(VIDEODB_DETAILS_TVSHOW_RATING).get_asFloat(), +- record->at(VIDEODB_DETAILS_TVSHOW_VOTES).get_asInt(), +- record->at(VIDEODB_DETAILS_TVSHOW_RATING_TYPE).get_asString(), true); ++ details.AddRating(record->at(VIDEODB_DETAILS_TVSHOW_RATING).get_asFloat(), ++ record->at(VIDEODB_DETAILS_TVSHOW_VOTES).get_asInt(), ++ record->at(VIDEODB_DETAILS_TVSHOW_RATING_TYPE).get_asString()); + details.m_duration = record->at(VIDEODB_DETAILS_TVSHOW_DURATION).get_asInt(); + + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); +@@ -3784,7 +3762,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForTvShow(const dbiplus::sql_record* con + + if (item != NULL) + { +- item->m_dateTime = details.GetPremiered(); ++ item->m_dateTime = details.m_premiered; + item->SetProperty("totalseasons", details.m_iSeason); + item->SetProperty("totalepisodes", details.m_iEpisode); + item->SetProperty("numepisodes", details.m_iEpisode); // will be changed later to reflect watchmode setting +@@ -3825,7 +3803,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForEpisode(const dbiplus::sql_record* co + details.m_strShowTitle = record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_NAME).get_asString(); + details.m_genre = StringUtils::Split(record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_GENRE).get_asString(), g_advancedSettings.m_videoItemSeparator); + details.m_studio = StringUtils::Split(record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_STUDIO).get_asString(), g_advancedSettings.m_videoItemSeparator); +- details.SetPremieredFromDBDate(record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED).get_asString()); ++ details.m_premiered.SetFromDBDate(record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED).get_asString()); + details.m_iIdShow = record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(); + details.m_iIdSeason = record->at(VIDEODB_DETAILS_EPISODE_SEASON_ID).get_asInt(); + +@@ -3833,9 +3811,10 @@ CVideoInfoTag CVideoDatabase::GetDetailsForEpisode(const dbiplus::sql_record* co + details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_EPISODE_TOTAL_TIME).get_asInt(); + details.m_resumePoint.type = CBookmark::RESUME; + details.m_iUserRating = record->at(VIDEODB_DETAILS_EPISODE_USER_RATING).get_asInt(); +- details.AddRating(record->at(VIDEODB_DETAILS_EPISODE_RATING).get_asFloat(), +- record->at(VIDEODB_DETAILS_EPISODE_VOTES).get_asInt(), +- record->at(VIDEODB_DETAILS_EPISODE_RATING_TYPE).get_asString(), true); ++ details.AddRating(record->at(VIDEODB_DETAILS_EPISODE_RATING).get_asFloat(), ++ record->at(VIDEODB_DETAILS_EPISODE_VOTES).get_asInt(), ++ record->at(VIDEODB_DETAILS_EPISODE_RATING_TYPE).get_asString()); ++ + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); + + if (getDetails) +@@ -3890,11 +3869,6 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMusicVideo(const dbiplus::sql_record* + details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME).get_asInt(); + details.m_resumePoint.type = CBookmark::RESUME; + details.m_iUserRating = record->at(VIDEODB_DETAILS_MUSICVIDEO_USER_RATING).get_asInt(); +- std::string premieredString = record->at(VIDEODB_DETAILS_MUSICVIDEO_PREMIERED).get_asString(); +- if (premieredString.size() == 4) +- details.SetYear(record->at(VIDEODB_DETAILS_MUSICVIDEO_PREMIERED).get_asInt()); +- else +- details.SetPremieredFromDBDate(premieredString); + + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); + +@@ -4959,19 +4933,11 @@ void CVideoDatabase::UpdateTables(int iVersion) + } + m_pDS->close(); + } +- +- if (iVersion < 105) +- { +- m_pDS->exec("ALTER TABLE movie ADD premiered TEXT"); +- m_pDS->exec(PrepareSQL("UPDATE movie SET premiered=c%02d", VIDEODB_ID_YEAR)); +- m_pDS->exec("ALTER TABLE musicvideo ADD premiered TEXT"); +- m_pDS->exec(PrepareSQL("UPDATE musicvideo SET premiered=c%02d", VIDEODB_ID_MUSICVIDEO_YEAR)); +- } + } + + int CVideoDatabase::GetSchemaVersion() const + { +- return 106; ++ return 104; + } + + bool CVideoDatabase::LookupByFolders(const std::string &path, bool shows) +@@ -5014,7 +4980,7 @@ bool CVideoDatabase::GetPlayCounts(const std::string &strPath, CFileItemList &it + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + +- //! @todo also test a single query for the above and below ++ // TODO: also test a single query for the above and below + std::string sql = PrepareSQL( + "SELECT" + " files.strFilename, files.playCount," +@@ -5706,12 +5672,12 @@ bool CVideoDatabase::GetPeopleNav(const std::string& strBaseDir, CFileItemList& + + try + { +- //! @todo This routine (and probably others at this same level) use playcount as a reference to filter on at a later +- //! point. This means that we *MUST* filter these levels as you'll get double ups. Ideally we'd allow playcount +- //! to filter through as we normally do for tvshows to save this happening. +- //! Also, we apply this same filtering logic to the locked or unlocked paths to prevent these from showing. +- //! Whether or not this should happen is a tricky one - it complicates all the high level categories (everything +- //! above titles). ++ // TODO: This routine (and probably others at this same level) use playcount as a reference to filter on at a later ++ // point. This means that we *MUST* filter these levels as you'll get double ups. Ideally we'd allow playcount ++ // to filter through as we normally do for tvshows to save this happening. ++ // Also, we apply this same filtering logic to the locked or unlocked paths to prevent these from showing. ++ // Whether or not this should happen is a tricky one - it complicates all the high level categories (everything ++ // above titles). + + // General routine that the other actor/director/writer routines call + +@@ -5955,7 +5921,7 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + { + if (idContent == VIDEODB_CONTENT_MOVIES) + { +- strSQL = "select movie_view.premiered, path.strPath, files.playCount from movie_view "; ++ strSQL = PrepareSQL("select movie_view.c%02d, path.strPath, files.playCount from movie_view ", VIDEODB_ID_YEAR); + extFilter.AppendJoin("join files on files.idFile = movie_view.idFile join path on files.idPath = path.idPath"); + } + else if (idContent == VIDEODB_CONTENT_TVSHOWS) +@@ -5965,7 +5931,7 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + } + else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) + { +- strSQL = "select musicvideo_view.premiered, path.strPath, files.playCount from musicvideo_view "; ++ strSQL = PrepareSQL("select musicvideo_view.c%02d, path.strPath, files.playCount from musicvideo_view ", VIDEODB_ID_MUSICVIDEO_YEAR); + extFilter.AppendJoin("join files on files.idFile = musicvideo_view.idFile join path on files.idPath = path.idPath"); + } + else +@@ -5976,9 +5942,9 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + std::string group; + if (idContent == VIDEODB_CONTENT_MOVIES) + { +- strSQL = "select movie_view.premiered, count(1), count(files.playCount) from movie_view "; ++ strSQL = PrepareSQL("select movie_view.c%02d, count(1), count(files.playCount) from movie_view ", VIDEODB_ID_YEAR); + extFilter.AppendJoin("join files on files.idFile = movie_view.idFile"); +- extFilter.AppendGroup("movie_view.premiered"); ++ extFilter.AppendGroup(PrepareSQL("movie_view.c%02d", VIDEODB_ID_YEAR)); + } + else if (idContent == VIDEODB_CONTENT_TVSHOWS) + { +@@ -5987,9 +5953,9 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + } + else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) + { +- strSQL = "select musicvideo_view.premiered, count(1), count(files.playCount) from musicvideo_view "; ++ strSQL = PrepareSQL("select musicvideo_view.c%02d, count(1), count(files.playCount) from musicvideo_view ", VIDEODB_ID_MUSICVIDEO_YEAR); + extFilter.AppendJoin("join files on files.idFile = musicvideo_view.idFile"); +- extFilter.AppendGroup("musicvideo_view.premiered"); ++ extFilter.AppendGroup(PrepareSQL("musicvideo_view.c%02d", VIDEODB_ID_MUSICVIDEO_YEAR)); + } + else + return false; +@@ -6010,15 +5976,14 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + while (!m_pDS->eof()) + { + int lYear = 0; +- std::string dateString = m_pDS->fv(0).get_asString(); +- if (dateString.size() == 4) +- lYear = m_pDS->fv(0).get_asInt(); +- else ++ if (idContent == VIDEODB_CONTENT_TVSHOWS) + { + CDateTime time; +- time.SetFromDateString(dateString); ++ time.SetFromDateString(m_pDS->fv(0).get_asString()); + lYear = time.GetYear(); + } ++ else if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) ++ lYear = m_pDS->fv(0).get_asInt(); + it = mapYears.find(lYear); + if (it == mapYears.end()) + { +@@ -6058,15 +6023,18 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i + while (!m_pDS->eof()) + { + int lYear = 0; +- std::string strLabel = m_pDS->fv(0).get_asString(); +- if (strLabel.size() == 4) +- lYear = m_pDS->fv(0).get_asInt(); +- else ++ std::string strLabel; ++ if (idContent == VIDEODB_CONTENT_TVSHOWS) + { + CDateTime time; +- time.SetFromDateString(strLabel); ++ time.SetFromDateString(m_pDS->fv(0).get_asString()); + lYear = time.GetYear(); +- strLabel = StringUtils::Format("%i", lYear); ++ strLabel = StringUtils::Format("%i",lYear); ++ } ++ else if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) ++ { ++ lYear = m_pDS->fv(0).get_asInt(); ++ strLabel = m_pDS->fv(0).get_asString(); + } + if (lYear == 0) + { +@@ -6224,17 +6192,16 @@ bool CVideoDatabase::GetSeasonsByWhere(const std::string& strBaseDir, const Filt + pItem->GetVideoInfoTag()->m_strPath = path; + pItem->GetVideoInfoTag()->m_strShowTitle = m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_TITLE).get_asString(); + pItem->GetVideoInfoTag()->m_strPlot = m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_PLOT).get_asString(); +- pItem->GetVideoInfoTag()->SetPremieredFromDBDate(m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_PREMIERED).get_asString()); ++ pItem->GetVideoInfoTag()->m_premiered.SetFromDBDate(m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_PREMIERED).get_asString()); + pItem->GetVideoInfoTag()->m_firstAired.SetFromDBDate(m_pDS->fv(VIDEODB_ID_SEASON_PREMIERED).get_asString()); + pItem->GetVideoInfoTag()->m_iUserRating = m_pDS->fv(VIDEODB_ID_SEASON_USER_RATING).get_asInt(); +- // season premiered date based on first episode airdate associated to the season +- // tvshow premiered date is used as a fallback ++ ++ // season premiered date based on first episode airdate associated to the season ++ // tvshow premiered date is used as a fallback + if (pItem->GetVideoInfoTag()->m_firstAired.IsValid()) +- pItem->GetVideoInfoTag()->SetPremiered(pItem->GetVideoInfoTag()->m_firstAired); +- else if (pItem->GetVideoInfoTag()->HasPremiered()) +- pItem->GetVideoInfoTag()->SetPremiered(pItem->GetVideoInfoTag()->GetPremiered()); +- else if (pItem->GetVideoInfoTag()->HasYear()) +- pItem->GetVideoInfoTag()->SetYear(pItem->GetVideoInfoTag()->GetYear()); ++ pItem->GetVideoInfoTag()->m_iYear = pItem->GetVideoInfoTag()->m_firstAired.GetYear(); ++ else if (pItem->GetVideoInfoTag()->m_premiered.IsValid()) ++ pItem->GetVideoInfoTag()->m_iYear = pItem->GetVideoInfoTag()->m_premiered.GetYear(); + pItem->GetVideoInfoTag()->m_genre = StringUtils::Split(m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_GENRE).get_asString(), g_advancedSettings.m_videoItemSeparator); + pItem->GetVideoInfoTag()->m_studio = StringUtils::Split(m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_STUDIO).get_asString(), g_advancedSettings.m_videoItemSeparator); + pItem->GetVideoInfoTag()->m_strMPAARating = m_pDS->fv(VIDEODB_ID_SEASON_TVSHOW_MPAA).get_asString(); +@@ -6740,6 +6707,7 @@ bool CVideoDatabase::GetEpisodesByWhere(const std::string& strBaseDir, const Fil + + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, movie.m_playCount > 0); + pItem->m_dateTime = movie.m_firstAired; ++ pItem->GetVideoInfoTag()->m_iYear = pItem->m_dateTime.GetYear(); + items.Add(pItem); + } + } +@@ -8703,8 +8671,8 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t + if (singleFile) + { + std::string strFileName(movie.m_strTitle); +- if (movie.HasYear()) +- strFileName += StringUtils::Format("_%i", movie.GetYear()); ++ if (movie.m_iYear > 0) ++ strFileName += StringUtils::Format("_%i", movie.m_iYear); + item.SetPath(GetSafeFile(moviesDir, strFileName) + ".avi"); + } + for (std::map::const_iterator i = artwork.begin(); i != artwork.end(); ++i) +@@ -8792,8 +8760,8 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t + if (singleFile) + { + std::string strFileName(StringUtils::Join(movie.m_artist, g_advancedSettings.m_videoItemSeparator) + "." + movie.m_strTitle); +- if (movie.HasYear()) +- strFileName += StringUtils::Format("_%i", movie.GetYear()); ++ if (movie.m_iYear > 0) ++ strFileName += StringUtils::Format("_%i", movie.m_iYear); + item.SetPath(GetSafeFile(moviesDir, strFileName) + ".avi"); + } + for (std::map::const_iterator i = artwork.begin(); i != artwork.end(); ++i) +@@ -9170,8 +9138,8 @@ void CVideoDatabase::ImportFromXML(const std::string &path) + CFileItem item(info); + bool useFolders = info.m_basePath.empty() ? LookupByFolders(item.GetPath()) : false; + std::string filename = info.m_strTitle; +- if (info.HasYear()) +- filename += StringUtils::Format("_%i", info.GetYear()); ++ if (info.m_iYear > 0) ++ filename += StringUtils::Format("_%i", info.m_iYear); + CFileItem artItem(item); + artItem.SetPath(GetSafeFile(moviesDir, filename) + ".avi"); + scanner.GetArtwork(&artItem, CONTENT_MOVIES, useFolders, true, actorsDir); +@@ -9185,8 +9153,8 @@ void CVideoDatabase::ImportFromXML(const std::string &path) + CFileItem item(info); + bool useFolders = info.m_basePath.empty() ? LookupByFolders(item.GetPath()) : false; + std::string filename = StringUtils::Join(info.m_artist, g_advancedSettings.m_videoItemSeparator) + "." + info.m_strTitle; +- if (info.HasYear()) +- filename += StringUtils::Format("_%i", info.GetYear()); ++ if (info.m_iYear > 0) ++ filename += StringUtils::Format("_%i", info.m_iYear); + CFileItem artItem(item); + artItem.SetPath(GetSafeFile(musicvideosDir, filename) + ".avi"); + scanner.GetArtwork(&artItem, CONTENT_MUSICVIDEOS, useFolders, true, actorsDir); +@@ -9523,7 +9491,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription + + option = options.find("year"); + if (option != options.end()) +- filter.AppendWhere(PrepareSQL("movie_view.premiered like '%i%%'", (int)option->second.asInteger())); ++ filter.AppendWhere(PrepareSQL("movie_view.c%02d = '%i'", VIDEODB_ID_YEAR, (int)option->second.asInteger())); + + AppendIdLinkFilter("actor", "actor", "movie", "movie", "idMovie", options, filter); + AppendLinkFilter("actor", "actor", "movie", "movie", "idMovie", options, filter); +@@ -9645,7 +9613,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription + + option = options.find("year"); + if (option != options.end()) +- filter.AppendWhere(PrepareSQL("musicvideo_view.premiered like '%i%%'", (int)option->second.asInteger())); ++ filter.AppendWhere(PrepareSQL("musicvideo_view.c%02d = '%i'",VIDEODB_ID_MUSICVIDEO_YEAR, (int)option->second.asInteger())); + + option = options.find("artistid"); + if (option != options.end()) +diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h +index 3747886..b85ed4b 100644 +--- a/xbmc/video/VideoDatabase.h ++++ b/xbmc/video/VideoDatabase.h +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + + #include "addons/Scraper.h" + #include "Bookmark.h" +@@ -87,19 +86,18 @@ enum VideoDbDetails + + #define VIDEODB_DETAILS_MOVIE_SET_ID VIDEODB_MAX_COLUMNS + 2 + #define VIDEODB_DETAILS_MOVIE_USER_RATING VIDEODB_MAX_COLUMNS + 3 +-#define VIDEODB_DETAILS_MOVIE_PREMIERED VIDEODB_MAX_COLUMNS + 4 +-#define VIDEODB_DETAILS_MOVIE_SET_NAME VIDEODB_MAX_COLUMNS + 5 +-#define VIDEODB_DETAILS_MOVIE_SET_OVERVIEW VIDEODB_MAX_COLUMNS + 6 +-#define VIDEODB_DETAILS_MOVIE_FILE VIDEODB_MAX_COLUMNS + 7 +-#define VIDEODB_DETAILS_MOVIE_PATH VIDEODB_MAX_COLUMNS + 8 +-#define VIDEODB_DETAILS_MOVIE_PLAYCOUNT VIDEODB_MAX_COLUMNS + 9 +-#define VIDEODB_DETAILS_MOVIE_LASTPLAYED VIDEODB_MAX_COLUMNS + 10 +-#define VIDEODB_DETAILS_MOVIE_DATEADDED VIDEODB_MAX_COLUMNS + 11 +-#define VIDEODB_DETAILS_MOVIE_RESUME_TIME VIDEODB_MAX_COLUMNS + 12 +-#define VIDEODB_DETAILS_MOVIE_TOTAL_TIME VIDEODB_MAX_COLUMNS + 13 +-#define VIDEODB_DETAILS_MOVIE_RATING VIDEODB_MAX_COLUMNS + 14 +-#define VIDEODB_DETAILS_MOVIE_VOTES VIDEODB_MAX_COLUMNS + 15 +-#define VIDEODB_DETAILS_MOVIE_RATING_TYPE VIDEODB_MAX_COLUMNS + 16 ++#define VIDEODB_DETAILS_MOVIE_SET_NAME VIDEODB_MAX_COLUMNS + 4 ++#define VIDEODB_DETAILS_MOVIE_SET_OVERVIEW VIDEODB_MAX_COLUMNS + 5 ++#define VIDEODB_DETAILS_MOVIE_FILE VIDEODB_MAX_COLUMNS + 6 ++#define VIDEODB_DETAILS_MOVIE_PATH VIDEODB_MAX_COLUMNS + 7 ++#define VIDEODB_DETAILS_MOVIE_PLAYCOUNT VIDEODB_MAX_COLUMNS + 8 ++#define VIDEODB_DETAILS_MOVIE_LASTPLAYED VIDEODB_MAX_COLUMNS + 9 ++#define VIDEODB_DETAILS_MOVIE_DATEADDED VIDEODB_MAX_COLUMNS + 10 ++#define VIDEODB_DETAILS_MOVIE_RESUME_TIME VIDEODB_MAX_COLUMNS + 11 ++#define VIDEODB_DETAILS_MOVIE_TOTAL_TIME VIDEODB_MAX_COLUMNS + 12 ++#define VIDEODB_DETAILS_MOVIE_RATING VIDEODB_MAX_COLUMNS + 13 ++#define VIDEODB_DETAILS_MOVIE_VOTES VIDEODB_MAX_COLUMNS + 14 ++#define VIDEODB_DETAILS_MOVIE_RATING_TYPE VIDEODB_MAX_COLUMNS + 15 + + #define VIDEODB_DETAILS_EPISODE_TVSHOW_ID VIDEODB_MAX_COLUMNS + 2 + #define VIDEODB_DETAILS_EPISODE_USER_RATING VIDEODB_MAX_COLUMNS + 3 +@@ -134,16 +132,14 @@ enum VideoDbDetails + #define VIDEODB_DETAILS_TVSHOW_RATING_TYPE VIDEODB_MAX_COLUMNS + 12 + + #define VIDEODB_DETAILS_MUSICVIDEO_USER_RATING VIDEODB_MAX_COLUMNS + 2 +-#define VIDEODB_DETAILS_MUSICVIDEO_PREMIERED VIDEODB_MAX_COLUMNS + 3 +-#define VIDEODB_DETAILS_MUSICVIDEO_FILE VIDEODB_MAX_COLUMNS + 4 +-#define VIDEODB_DETAILS_MUSICVIDEO_PATH VIDEODB_MAX_COLUMNS + 5 +-#define VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT VIDEODB_MAX_COLUMNS + 6 +-#define VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED VIDEODB_MAX_COLUMNS + 7 +-#define VIDEODB_DETAILS_MUSICVIDEO_DATEADDED VIDEODB_MAX_COLUMNS + 8 +-#define VIDEODB_DETAILS_MUSICVIDEO_RESUME_TIME VIDEODB_MAX_COLUMNS + 9 +-#define VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME VIDEODB_MAX_COLUMNS + 10 +- +-#define VIDEODB_TYPE_UNUSED 0 ++#define VIDEODB_DETAILS_MUSICVIDEO_FILE VIDEODB_MAX_COLUMNS + 3 ++#define VIDEODB_DETAILS_MUSICVIDEO_PATH VIDEODB_MAX_COLUMNS + 4 ++#define VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT VIDEODB_MAX_COLUMNS + 5 ++#define VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED VIDEODB_MAX_COLUMNS + 6 ++#define VIDEODB_DETAILS_MUSICVIDEO_DATEADDED VIDEODB_MAX_COLUMNS + 7 ++#define VIDEODB_DETAILS_MUSICVIDEO_RESUME_TIME VIDEODB_MAX_COLUMNS + 8 ++#define VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME VIDEODB_MAX_COLUMNS + 9 ++ + #define VIDEODB_TYPE_STRING 1 + #define VIDEODB_TYPE_INT 2 + #define VIDEODB_TYPE_FLOAT 3 +@@ -172,7 +168,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s + VIDEODB_ID_VOTES = 4, // unused + VIDEODB_ID_RATING_ID = 5, + VIDEODB_ID_CREDITS = 6, +- VIDEODB_ID_YEAR = 7, // unused ++ VIDEODB_ID_YEAR = 7, + VIDEODB_ID_THUMBURL = 8, + VIDEODB_ID_IDENT = 9, + VIDEODB_ID_SORTTITLE = 10, +@@ -202,10 +198,10 @@ const struct SDbTableOffsets + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlotOutline) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTagLine) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strVotes) }, + { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_writingCredits) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iYear) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_xml) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strIMDBNumber) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle) }, +@@ -251,7 +247,7 @@ const struct SDbTableOffsets DbTvShowOffsets[] = + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTitle) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strStatus) }, +- { VIDEODB_TYPE_UNUSED, 0 }, //unused ++ { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strVotes) }, + { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) }, + { VIDEODB_TYPE_DATE, my_offsetof(CVideoInfoTag,m_premiered) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_xml) }, +@@ -266,7 +262,7 @@ const struct SDbTableOffsets DbTvShowOffsets[] = + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle)}, + }; + +-//! @todo is this comment valid for seasons? There is no offset structure or am I wrong? ++// TODO is this comment valid for seasons? There is no offset structure or am I wrong? + typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets) + { + VIDEODB_ID_SEASON_MIN = -1, +@@ -319,13 +315,13 @@ const struct SDbTableOffsets DbEpisodeOffsets[] = + { + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTitle) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strVotes) }, + { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_writingCredits) }, + { VIDEODB_TYPE_DATE, my_offsetof(CVideoInfoTag,m_firstAired) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_xml) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_spoof) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_COUNT, my_offsetof(CVideoInfoTag,m_playCount) }, // unused + { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_director) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strProductionCode) }, +@@ -350,7 +346,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s + VIDEODB_ID_MUSICVIDEO_RUNTIME = 4, + VIDEODB_ID_MUSICVIDEO_DIRECTOR = 5, + VIDEODB_ID_MUSICVIDEO_STUDIOS = 6, +- VIDEODB_ID_MUSICVIDEO_YEAR = 7, // unused ++ VIDEODB_ID_MUSICVIDEO_YEAR = 7, + VIDEODB_ID_MUSICVIDEO_PLOT = 8, + VIDEODB_ID_MUSICVIDEO_ALBUM = 9, + VIDEODB_ID_MUSICVIDEO_ARTIST = 10, +@@ -366,11 +362,11 @@ const struct SDbTableOffsets DbMusicVideoOffsets[] = + { VIDEODB_TYPE_STRING, my_offsetof(class CVideoInfoTag,m_strTitle) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_xml) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_spoof) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_COUNT, my_offsetof(CVideoInfoTag,m_playCount) }, // unused + { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_director) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_studio) }, +- { VIDEODB_TYPE_UNUSED, 0 }, // unused ++ { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iYear) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) }, + { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strAlbum) }, + { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_artist) }, +diff --git a/xbmc/video/VideoInfoDownloader.h b/xbmc/video/VideoInfoDownloader.h +index ee85c53..5698f3b 100644 +--- a/xbmc/video/VideoInfoDownloader.h ++++ b/xbmc/video/VideoInfoDownloader.h +@@ -26,7 +26,6 @@ + #include "Episode.h" + #include "filesystem/CurlFile.h" + #include +-#include + + // forward declarations + class CXBMCTinyXML; +diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp +index 797013a..8584e0a 100644 +--- a/xbmc/video/VideoInfoScanner.cpp ++++ b/xbmc/video/VideoInfoScanner.cpp +@@ -139,11 +139,7 @@ namespace VIDEO + * occurs. + */ + std::string directory = *m_pathsToScan.begin(); +- if (m_bStop) +- { +- bCancelled = true; +- } +- else if (!CDirectory::Exists(directory)) ++ if (!CDirectory::Exists(directory)) + { + /* + * Note that this will skip clean (if m_bClean is enabled) if the directory really +@@ -617,7 +613,7 @@ namespace VIDEO + return INFO_ERROR; + return INFO_ADDED; + } +- //! @todo This is not strictly correct as we could fail to download information here or error, or be cancelled ++ // TODO: This is not strictly correct as we could fail to download information here or error, or be cancelled + return INFO_NOT_FOUND; + } + +@@ -666,7 +662,7 @@ namespace VIDEO + return INFO_ERROR; + return INFO_ADDED; + } +- //! @todo This is not strictly correct as we could fail to download information here or error, or be cancelled ++ // TODO: This is not strictly correct as we could fail to download information here or error, or be cancelled + return INFO_NOT_FOUND; + } + +@@ -1594,7 +1590,7 @@ namespace VIDEO + CFileItem item; + item.SetPath(file->strPath); + if (!imdb.GetEpisodeDetails(guide->cScraperUrl, *item.GetVideoInfoTag(), pDlgProgress)) +- return INFO_NOT_FOUND; //! @todo should we just skip to the next episode? ++ return INFO_NOT_FOUND; // TODO: should we just skip to the next episode? + + // Only set season/epnum from filename when it is not already set by a scraper + if (item.GetVideoInfoTag()->m_iSeason == -1) +@@ -1841,8 +1837,8 @@ namespace VIDEO + struct __stat64 buffer; + if (XFILE::CFile::Stat(items[i]->GetPath(), &buffer) == 0) + { +- //! @todo some filesystems may return the mtime/ctime inline, in which case this is +- //! unnecessarily expensive. Consider supporting Stat() in our directory cache? ++ // TODO: some filesystems may return the mtime/ctime inline, in which case this is ++ // unnecessarily expensive. Consider supporting Stat() in our directory cache? + stat_time = buffer.st_mtime ? buffer.st_mtime : buffer.st_ctime; + time += stat_time; + } +diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h +index d7ca10b..64facc8 100644 +--- a/xbmc/video/VideoInfoScanner.h ++++ b/xbmc/video/VideoInfoScanner.h +@@ -18,11 +18,6 @@ + * . + * + */ +- +-#include +-#include +-#include +- + #include "InfoScanner.h" + #include "NfoFile.h" + #include "VideoDatabase.h" +@@ -153,7 +148,7 @@ namespace VIDEO + int FindVideo(const std::string &videoName, const ADDON::ScraperPtr &scraper, CScraperUrl &url, CGUIDialogProgress *progress); + + /*! \brief Retrieve detailed information for an item from an online source, optionally supplemented with local data +- @todo sort out some better return codes. ++ TODO: sort out some better return codes. + \param pItem item to retrieve online details for. + \param url URL to use to retrieve online details. + \param scraper Scraper that handles parsing the online data. +@@ -222,7 +217,7 @@ namespace VIDEO + bool CanFastHash(const CFileItemList &items, const std::vector &excludes) const; + + /*! \brief Process a series folder, filling in episode details and adding them to the database. +- @todo Ideally we would return INFO_HAVE_ALREADY if we don't have to update any episodes ++ TODO: Ideally we would return INFO_HAVE_ALREADY if we don't have to update any episodes + and we should return INFO_NOT_FOUND only if no information is found for any of + the episodes. INFO_ADDED then indicates we've added one or more episodes. + \param files the episode files to process. +diff --git a/xbmc/video/VideoInfoTag.cpp b/xbmc/video/VideoInfoTag.cpp +index 79f9362..4b7f20e 100644 +--- a/xbmc/video/VideoInfoTag.cpp ++++ b/xbmc/video/VideoInfoTag.cpp +@@ -58,7 +58,6 @@ void CVideoInfoTag::Reset() + m_strMPAARating.clear(); + m_strFileNameAndPath.clear(); + m_premiered.Reset(); +- m_bHasPremiered = false; + m_strStatus.clear(); + m_strProductionCode.clear(); + m_firstAired.Reset(); +@@ -67,6 +66,7 @@ void CVideoInfoTag::Reset() + m_artist.clear(); + m_strTrailer.clear(); + m_iTop250 = 0; ++ m_iYear = 0; + m_iSeason = -1; + m_iEpisode = -1; + m_strUniqueId.clear(); +@@ -149,6 +149,7 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const std::string &tag, bool savePathI + movie->InsertEndChild(epbookmark); + } + ++ XMLUtils::SetInt(movie, "year", m_iYear); + XMLUtils::SetInt(movie, "top250", m_iTop250); + if (tag == "episodedetails" || tag == "tvshow") + { +@@ -218,10 +219,7 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const std::string &tag, bool savePathI + XMLUtils::SetStringArray(movie, "tag", m_tags); + XMLUtils::SetStringArray(movie, "credits", m_writingCredits); + XMLUtils::SetStringArray(movie, "director", m_director); +- if (HasPremiered()) +- XMLUtils::SetDate(movie, "premiered", m_premiered); +- if (HasYear()) +- XMLUtils::SetInt(movie, "year", GetYear()); ++ XMLUtils::SetDate(movie, "premiered", m_premiered); + XMLUtils::SetString(movie, "status", m_strStatus); + XMLUtils::SetString(movie, "code", m_strProductionCode); + XMLUtils::SetDate(movie, "aired", m_firstAired); +@@ -348,7 +346,6 @@ void CVideoInfoTag::Archive(CArchive& ar) + ar << m_strOriginalTitle; + ar << m_strEpisodeGuide; + ar << m_premiered; +- ar << m_bHasPremiered; + ar << m_strStatus; + ar << m_strProductionCode; + ar << m_firstAired; +@@ -358,6 +355,7 @@ void CVideoInfoTag::Archive(CArchive& ar) + ar << m_playCount; + ar << m_lastPlayed; + ar << m_iTop250; ++ ar << m_iYear; + ar << m_iSeason; + ar << m_iEpisode; + ar << m_strUniqueId; +@@ -440,7 +438,6 @@ void CVideoInfoTag::Archive(CArchive& ar) + ar >> m_strOriginalTitle; + ar >> m_strEpisodeGuide; + ar >> m_premiered; +- ar >> m_bHasPremiered; + ar >> m_strStatus; + ar >> m_strProductionCode; + ar >> m_firstAired; +@@ -450,6 +447,7 @@ void CVideoInfoTag::Archive(CArchive& ar) + ar >> m_playCount; + ar >> m_lastPlayed; + ar >> m_iTop250; ++ ar >> m_iYear; + ar >> m_iSeason; + ar >> m_iEpisode; + ar >> m_strUniqueId; +@@ -551,22 +549,22 @@ void CVideoInfoTag::Serialize(CVariant& value) const + value["playcount"] = m_playCount; + value["lastplayed"] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::Empty; + value["top250"] = m_iTop250; +- value["year"] = m_premiered.GetYear(); ++ value["year"] = m_iYear; + value["season"] = m_iSeason; + value["episode"] = m_iEpisode; + value["uniqueid"]["unknown"] = m_strUniqueId; + value["rating"] = GetRating().rating; +- CVariant ratings = CVariant(CVariant::VariantTypeObject); ++ value["ratings"] = CVariant(CVariant::VariantTypeArray); + for (const auto& i : m_ratings) + { + CVariant rating; ++ rating["name"] = i.first; + rating["rating"] = i.second.rating; + rating["votes"] = i.second.votes; +- rating["default"] = i.first == m_strDefaultRating; +- +- ratings[i.first] = rating; ++ if (i.first == m_strDefaultRating) ++ rating["default"] = true; ++ value["ratings"].push_back(rating); + } +- value["ratings"] = ratings; + value["userrating"] = m_iUserRating; + value["dbid"] = m_iDbId; + value["fileid"] = m_iFileId; +@@ -637,7 +635,7 @@ void CVideoInfoTag::ToSortable(SortItem& sortable, Field field) const + case FieldPlaycount: sortable[FieldPlaycount] = m_playCount; break; + case FieldLastPlayed: sortable[FieldLastPlayed] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::Empty; break; + case FieldTop250: sortable[FieldTop250] = m_iTop250; break; +- case FieldYear: sortable[FieldYear] = m_premiered.GetYear(); break; ++ case FieldYear: sortable[FieldYear] = m_iYear; break; + case FieldSeason: sortable[FieldSeason] = m_iSeason; break; + case FieldEpisodeNumber: sortable[FieldEpisodeNumber] = m_iEpisode; break; + case FieldNumberOfEpisodes: sortable[FieldNumberOfEpisodes] = m_iEpisode; break; +@@ -674,38 +672,10 @@ const CRating CVideoInfoTag::GetRating(std::string type) const + if (type.empty()) + type = m_strDefaultRating; + +- const auto& rating = m_ratings.find(type); +- if (rating == m_ratings.end()) ++ if (m_ratings.find(type) == m_ratings.end()) + return CRating(); + +- return rating->second; +-} +- +-const std::string& CVideoInfoTag::GetDefaultRating() const +-{ +- return m_strDefaultRating; +-} +- +-const bool CVideoInfoTag::HasYear() const +-{ +- return m_premiered.IsValid(); +-} +- +-const int CVideoInfoTag::GetYear() const +-{ +- if (m_premiered.IsValid()) +- return GetPremiered().GetYear(); +- return 0; +-} +- +-const bool CVideoInfoTag::HasPremiered() const +-{ +- return m_bHasPremiered; +-} +- +-const CDateTime& CVideoInfoTag::GetPremiered() const +-{ +- return m_premiered; ++ return m_ratings.find(type)->second; + } + + const std::string CVideoInfoTag::GetCast(bool bIncludeRole /*= false*/) const +@@ -793,6 +763,7 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise) + const TiXmlElement* urElement = movie->FirstChildElement("userrating"); + if (urElement && (urElement->QueryIntAttribute("max", &max_value) == TIXML_SUCCESS) && max_value >= 1) + m_iUserRating = m_iUserRating / max_value * 10; // Normalise the user Movie Rating to between 1 and 10 ++ XMLUtils::GetInt(movie, "year", m_iYear); + XMLUtils::GetInt(movie, "top250", m_iTop250); + XMLUtils::GetInt(movie, "season", m_iSeason); + XMLUtils::GetInt(movie, "episode", m_iEpisode); +@@ -841,16 +812,7 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise) + if (XMLUtils::GetString(movie, "filenameandpath", value)) + SetFileNameAndPath(value); + +- if (XMLUtils::GetDate(movie, "premiered", m_premiered)) +- { +- m_bHasPremiered = true; +- } +- else +- { +- int year; +- if (XMLUtils::GetInt(movie, "year", year)) +- SetYear(year); +- } ++ XMLUtils::GetDate(movie, "premiered", m_premiered); + + if (XMLUtils::GetString(movie, "status", value)) + SetStatus(value); +@@ -1200,46 +1162,25 @@ void CVideoInfoTag::SetPictureURL(CScraperUrl &pictureURL) + m_strPictureURL = pictureURL; + } + +-void CVideoInfoTag::AddRating(float rating, int votes, const std::string& type /* = "" */, bool def /* = false */) ++void CVideoInfoTag::AddRating(float rating, int votes, const std::string& type /* = "" */) + { + AddRating(CRating(rating, votes), type); + } + +-void CVideoInfoTag::AddRating(CRating rating, const std::string& type /* = "" */, bool def /* = false */) ++void CVideoInfoTag::AddRating(CRating rating, const std::string& type /* = "" */) + { + if (type.empty()) + m_ratings[m_strDefaultRating] = rating; + else + m_ratings[type] = rating; +- +- if (def) +- m_strDefaultRating = type; + } + +-void CVideoInfoTag::SetRating(float rating, const std::string& type /* = "" */, bool def /* = false */) ++void CVideoInfoTag::SetRating(float rating, const std::string& type /* = "" */) + { + if (type.empty()) + m_ratings[m_strDefaultRating].rating = rating; + else + m_ratings[type].rating = rating; +- +- if (def) +- m_strDefaultRating = type; +-} +- +-void CVideoInfoTag::RemoveRating(const std::string& type) +-{ +- if (m_ratings.find(type) != m_ratings.end()) +- { +- m_ratings.erase(type); +- if (m_strDefaultRating == type && !m_ratings.empty()) +- m_strDefaultRating = m_ratings.begin()->first; +- } +-} +- +-void CVideoInfoTag::SetRatings(RatingMap ratings) +-{ +- m_ratings = std::move(ratings); + } + + void CVideoInfoTag::SetVotes(int votes, const std::string& type /* = "" */) +@@ -1250,27 +1191,6 @@ void CVideoInfoTag::SetVotes(int votes, const std::string& type /* = "" */) + m_ratings[type].votes = votes; + } + +-void CVideoInfoTag::SetPremiered(CDateTime premiered) +-{ +- m_premiered = premiered; +- m_bHasPremiered = premiered.IsValid(); +-} +- +-void CVideoInfoTag::SetPremieredFromDBDate(std::string premieredString) +-{ +- CDateTime premiered; +- premiered.SetFromDBDate(premieredString); +- SetPremiered(premiered); +-} +- +-void CVideoInfoTag::SetYear(int year) +-{ +- if (m_bHasPremiered) +- m_premiered.SetDate(year, m_premiered.GetMonth(), m_premiered.GetDay()); +- else +- m_premiered = CDateTime(year, 1, 1, 0, 0, 0); +-} +- + void CVideoInfoTag::SetArtist(std::vector artist) + { + m_artist = Trim(std::move(artist)); +diff --git a/xbmc/video/VideoInfoTag.h b/xbmc/video/VideoInfoTag.h +index e4ead34..733d78c 100644 +--- a/xbmc/video/VideoInfoTag.h ++++ b/xbmc/video/VideoInfoTag.h +@@ -50,9 +50,10 @@ struct SActorInfo + class CRating + { + public: +- CRating(): rating(0.0f), votes(0) {} +- CRating(float r): rating(r), votes(0) {} +- CRating(float r, int v): rating(r), votes(v) {} ++ CRating() ++ : CRating(0.0f, 0) ++ { } ++ CRating(float r, int v) { rating = r; votes = v; } + float rating; + int votes; + }; +@@ -84,11 +85,6 @@ public: + virtual void Serialize(CVariant& value) const; + virtual void ToSortable(SortItem& sortable, Field field) const; + const CRating GetRating(std::string type = "") const; +- const std::string& GetDefaultRating() const; +- const bool HasYear() const; +- const int GetYear() const; +- const bool HasPremiered() const; +- const CDateTime& GetPremiered() const; + const std::string GetCast(bool bIncludeRole = false) const; + bool HasStreamDetails() const; + bool IsEmpty() const; +@@ -123,15 +119,10 @@ public: + void SetTitle(std::string title); + void SetSortTitle(std::string sortTitle); + void SetPictureURL(CScraperUrl &pictureURL); +- void AddRating(float rating, int votes, const std::string& type = "", bool def = false); +- void AddRating(CRating rating, const std::string& type = "", bool def = false); +- void SetRating(float rating, const std::string& type = "", bool def = false); +- void RemoveRating(const std::string& type); +- void SetRatings(RatingMap ratings); ++ void AddRating(float rating, int votes, const std::string& type = ""); ++ void AddRating(CRating rating, const std::string& type = ""); ++ void SetRating(float rating, const std::string& type = ""); + void SetVotes(int votes, const std::string& type = ""); +- void SetPremiered(CDateTime premiered); +- void SetPremieredFromDBDate(std::string premieredString); +- void SetYear(int year); + void SetArtist(std::vector artist); + void SetSet(std::string set); + void SetSetOverview(std::string setOverview); +@@ -166,6 +157,7 @@ public: + CScraperUrl m_strPictureURL; + std::string m_strTitle; + std::string m_strSortTitle; ++ std::string m_strVotes; + std::vector m_artist; + std::vector< SActorInfo > m_cast; + typedef std::vector< SActorInfo >::const_iterator iCast; +@@ -181,7 +173,6 @@ public: + std::string m_strOriginalTitle; + std::string m_strEpisodeGuide; + CDateTime m_premiered; +- bool m_bHasPremiered; + std::string m_strStatus; + std::string m_strProductionCode; + CDateTime m_firstAired; +@@ -193,6 +184,7 @@ public: + std::map m_namedSeasons; + int m_playCount; + int m_iTop250; ++ int m_iYear; + int m_iSeason; + int m_iEpisode; + std::string m_strUniqueId; +@@ -203,6 +195,7 @@ public: + int m_iTrack; + RatingMap m_ratings; + int m_iIdRating; ++ std::string m_strDefaultRating; + int m_iUserRating; + CBookmark m_EpBookmark; + int m_iBookmarkId; +@@ -227,7 +220,6 @@ private: + */ + void ParseNative(const TiXmlElement* element, bool prioritise); + +- std::string m_strDefaultRating; + std::string Trim(std::string &&value); + std::vector Trim(std::vector &&items); + }; +diff --git a/xbmc/video/VideoLibraryQueue.cpp b/xbmc/video/VideoLibraryQueue.cpp +index bd6e5e3..aacc1ea 100644 +--- a/xbmc/video/VideoLibraryQueue.cpp ++++ b/xbmc/video/VideoLibraryQueue.cpp +@@ -31,6 +31,7 @@ + #include "video/jobs/VideoLibraryMarkWatchedJob.h" + #include "video/jobs/VideoLibraryRefreshingJob.h" + #include "video/jobs/VideoLibraryScanningJob.h" ++#include "video/VideoDatabase.h" + + CVideoLibraryQueue::CVideoLibraryQueue() + : CJobQueue(false, 1, CJob::PRIORITY_LOW), +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index 4e566e4..4b19657 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -195,7 +195,7 @@ void CVideoReferenceClock::UpdateClock(int NrVBlanks, bool CheckMissed) + m_VblankTime += m_SystemFrequency * static_cast(NrVBlanks) / MathUtils::round_int(m_RefreshRate); //set the vblank time forward + } + +- if (NrVBlanks > 0) //update the clock with the adjusted frequency if we have any vblanks ++ if (NrVBlanks > 0 && CheckMissed) //update the clock with the adjusted frequency if we have any vblanks + { + double increment = UpdateInterval() * NrVBlanks; + double integer = floor(increment); +@@ -265,6 +265,7 @@ void CVideoReferenceClock::SetSpeed(double Speed) + //VideoPlayer can change the speed to fit the rereshrate + if (m_UseVblank) + { ++ Speed = (Speed*100 - trunc(Speed*100)) / 100 + 1.0; + if (Speed != m_ClockSpeed) + { + m_ClockSpeed = Speed; +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index 4714f1f..7628997 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -622,7 +622,7 @@ void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item) + m_videoDatabase->Close(); + + // still empty, try grabbing from filename +- //! @todo in case of too many false positives due to using the full path, extract the filename only using string utils ++ // TODO: in case of too many false positives due to using the full path, extract the filename only using string utils + if (stereoMode.empty()) + stereoMode = CStereoscopicsManager::GetInstance().DetectStereoModeByString( path ); + } +diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h +index 4f425ae..569bbd2 100644 +--- a/xbmc/video/VideoThumbLoader.h ++++ b/xbmc/video/VideoThumbLoader.h +@@ -20,7 +20,6 @@ + */ + + #include +-#include + #include "ThumbLoader.h" + #include "utils/JobManager.h" + #include "FileItem.h" +diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +index eb67552..601067e 100644 +--- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +@@ -85,7 +85,7 @@ void CGUIDialogAudioSubtitleSettings::FrameMove() + const CVideoSettings &videoSettings = CMediaSettings::GetInstance().GetCurrentVideoSettings(); + + // these settings can change on the fly +- //! @todo (needs special handling): m_settingsManager->SetInt(SETTING_AUDIO_STREAM, g_application.m_pPlayer->GetAudioStream()); ++ // TODO (needs special handling): m_settingsManager->SetInt(SETTING_AUDIO_STREAM, g_application.m_pPlayer->GetAudioStream()); + if (!m_dspEnabled) //< The follow settings are on enabled DSP system separated to them and need no update here. + { + m_settingsManager->SetNumber(SETTING_AUDIO_DELAY, videoSettings.m_AudioDelay); +@@ -93,10 +93,10 @@ void CGUIDialogAudioSubtitleSettings::FrameMove() + } + m_settingsManager->SetBool(SETTING_AUDIO_PASSTHROUGH, CSettings::GetInstance().GetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH)); + +- //! @todo m_settingsManager->SetBool(SETTING_SUBTITLE_ENABLE, g_application.m_pPlayer->GetSubtitleVisible()); ++ // TODO: m_settingsManager->SetBool(SETTING_SUBTITLE_ENABLE, g_application.m_pPlayer->GetSubtitleVisible()); + // \-> Unless subtitle visibility can change on the fly, while Dialog is up, this code should be removed. + m_settingsManager->SetNumber(SETTING_SUBTITLE_DELAY, videoSettings.m_SubtitleDelay); +- //! @todo (needs special handling): m_settingsManager->SetInt(SETTING_SUBTITLE_STREAM, g_application.m_pPlayer->GetSubtitle()); ++ // TODO (needs special handling): m_settingsManager->SetInt(SETTING_SUBTITLE_STREAM, g_application.m_pPlayer->GetSubtitle()); + } + + CGUIDialogSettingsManualBase::FrameMove(); +@@ -350,7 +350,7 @@ void CGUIDialogAudioSubtitleSettings::InitializeSettings() + AddAudioStreams(groupAudio, SETTING_AUDIO_STREAM); + + // audio output to all speakers setting +- //! @todo remove this setting ++ // TODO: remove this setting + if (SupportsAudioFeature(IPC_AUD_OUTPUT_STEREO) && !m_dspEnabled) + AddToggle(groupAudio, SETTING_AUDIO_OUTPUT_TO_ALL_SPEAKERS, 252, 0, videoSettings.m_OutputToAllSpeakers); + +diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.h b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.h +index ecca0bc..b27cba7 100644 +--- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.h ++++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.h +@@ -20,9 +20,7 @@ + * + */ + +-#include + #include +-#include + + #include "settings/dialogs/GUIDialogSettingsManualBase.h" + +diff --git a/xbmc/video/dialogs/GUIDialogSubtitles.cpp b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +index 398558e..6822179 100644 +--- a/xbmc/video/dialogs/GUIDialogSubtitles.cpp ++++ b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +@@ -465,9 +465,9 @@ void CGUIDialogSubtitles::OnDownloadComplete(const CFileItemList *items, const s + if (!subPath.empty()) + strDownloadPath = subPath; + +- /** Get item's folder for sub storage, special case for RAR/ZIP items +- * @todo We need some way to avoid special casing this all over the place +- * for rar/zip (perhaps modify GetDirectory?) ++ /* Get item's folder for sub storage, special case for RAR/ZIP items ++ TODO: We need some way to avoid special casing this all over the place ++ for rar/zip (perhaps modify GetDirectory?) + */ + if (URIUtils::IsInRAR(strCurrentFile) || URIUtils::IsInZIP(strCurrentFile)) + strCurrentFilePath = URIUtils::GetDirectory(CURL(strCurrentFile).GetHostName()); +diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp +index 53ffdfb..d4247d5 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp +@@ -22,6 +22,9 @@ + #include "GUIDialogVideoBookmarks.h" + #include "video/VideoDatabase.h" + #include "Application.h" ++#if defined(HAS_LIBAMCODEC) ++#include "utils/ScreenshotAML.h" ++#endif//HAS_LIBAMCODEC + #include "pictures/Picture.h" + #include "dialogs/GUIDialogContextMenu.h" + #include "view/ViewState.h" +diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +index fdf4a50..2f3ea96 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +@@ -496,8 +496,8 @@ void CGUIDialogVideoInfo::DoSearch(std::string& strSearch, CFileItemList& items) + for (int i = 0; i < movies.Size(); ++i) + { + std::string label = movies[i]->GetVideoInfoTag()->m_strTitle; +- if (movies[i]->GetVideoInfoTag()->HasYear()) +- label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->GetYear()); ++ if (movies[i]->GetVideoInfoTag()->m_iYear > 0) ++ label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->m_iYear); + movies[i]->SetLabel(label); + } + CGUIWindowVideoBase::AppendAndClearSearchItems(movies, "[" + g_localizeStrings.Get(20338) + "] ", items); +@@ -506,8 +506,8 @@ void CGUIDialogVideoInfo::DoSearch(std::string& strSearch, CFileItemList& items) + for (int i = 0; i < movies.Size(); ++i) + { + std::string label = movies[i]->GetVideoInfoTag()->m_strShowTitle; +- if (movies[i]->GetVideoInfoTag()->HasYear()) +- label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->GetYear()); ++ if (movies[i]->GetVideoInfoTag()->m_iYear > 0) ++ label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->m_iYear); + movies[i]->SetLabel(label); + } + CGUIWindowVideoBase::AppendAndClearSearchItems(movies, "[" + g_localizeStrings.Get(20364) + "] ", items); +@@ -524,8 +524,8 @@ void CGUIDialogVideoInfo::DoSearch(std::string& strSearch, CFileItemList& items) + for (int i = 0; i < movies.Size(); ++i) + { + std::string label = StringUtils::Join(movies[i]->GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator) + " - " + movies[i]->GetVideoInfoTag()->m_strTitle; +- if (movies[i]->GetVideoInfoTag()->HasYear()) +- label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->GetYear()); ++ if (movies[i]->GetVideoInfoTag()->m_iYear > 0) ++ label += StringUtils::Format(" (%i)", movies[i]->GetVideoInfoTag()->m_iYear); + movies[i]->SetLabel(label); + } + CGUIWindowVideoBase::AppendAndClearSearchItems(movies, "[" + g_localizeStrings.Get(20391) + "] ", items); +@@ -676,7 +676,7 @@ void CGUIDialogVideoInfo::OnGetArt() + if (type.empty()) + return; // cancelled + +- //! @todo this can be removed once these are unified. ++ // TODO: this can be removed once these are unified. + if (type == "fanart") + OnGetFanart(); + else +@@ -712,7 +712,7 @@ void CGUIDialogVideoInfo::OnGetArt() + item->SetIconImage("DefaultPicture.png"); + item->SetLabel(g_localizeStrings.Get(13513)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + // CTextureCache::GetInstance().ClearCachedImage(thumb); + items.Add(item); + } +@@ -808,7 +808,7 @@ void CGUIDialogVideoInfo::OnGetFanart() + item->SetIconImage("DefaultPicture.png"); + item->SetLabel(g_localizeStrings.Get(20441)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + // CTextureCache::GetInstance().ClearCachedImage(thumb); + items.Add(item); + } +@@ -821,7 +821,7 @@ void CGUIDialogVideoInfo::OnGetFanart() + itemLocal->SetArt("thumb", strLocal); + itemLocal->SetLabel(g_localizeStrings.Get(20438)); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + CTextureCache::GetInstance().ClearCachedImage(strLocal); + items.Add(itemLocal); + } +@@ -1755,7 +1755,7 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const CFileItemPtr &item, const + item->SetLabel(g_localizeStrings.Get(13513)); + items.Add(item); + +- //! @todo Do we need to clear the cached image? ++ // TODO: Do we need to clear the cached image? + // CTextureCache::GetInstance().ClearCachedImage(thumbs[i]); + } + +diff --git a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +index c1e99cf..5e3a31b 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +@@ -30,7 +30,7 @@ using namespace PVR; + CGUIDialogVideoOSD::CGUIDialogVideoOSD(void) + : CGUIDialog(WINDOW_DIALOG_VIDEO_OSD, "VideoOSD.xml") + { +- m_loadType = KEEP_IN_MEMORY; ++ m_loadType = LOAD_ON_GUI_INIT; + } + + CGUIDialogVideoOSD::~CGUIDialogVideoOSD(void) +diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +index afbe203..d00165c 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +@@ -170,7 +170,7 @@ void CGUIDialogVideoSettings::OnSettingAction(const CSetting *setting) + return; + g_windowManager.ForceActivateWindow(WINDOW_SCREEN_CALIBRATION); + } +- //! @todo implement ++ // TODO + else if (settingId == SETTING_VIDEO_MAKE_DEFAULT) + Save(); + } +@@ -290,6 +290,10 @@ void CGUIDialogVideoSettings::InitializeSettings() + entries.push_back(std::make_pair(16333, VS_INTERLACEMETHOD_MMAL_BOB_HALF)); + entries.push_back(std::make_pair(16334, VS_INTERLACEMETHOD_IMX_FASTMOTION)); + entries.push_back(std::make_pair(16335, VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE)); ++ entries.push_back(std::make_pair(16336, VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE_INVERTED)); ++ entries.push_back(std::make_pair(16337, VS_INTERLACEMETHOD_IMX_ADVMOTION)); ++ entries.push_back(std::make_pair(16338, VS_INTERLACEMETHOD_IMX_ADVMOTION_DOUBLE)); ++ entries.push_back(std::make_pair(16339, VS_INTERLACEMETHOD_IMX_WEAVE)); + + /* remove unsupported methods */ + for (StaticIntegerSettingOptions::iterator it = entries.begin(); it != entries.end(); ) +diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.h b/xbmc/video/dialogs/GUIDialogVideoSettings.h +index adad488..bb9c31a 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoSettings.h ++++ b/xbmc/video/dialogs/GUIDialogVideoSettings.h +@@ -20,10 +20,6 @@ + * + */ + +-#include +-#include +-#include +- + #include "settings/dialogs/GUIDialogSettingsManualBase.h" + + class CGUIDialogVideoSettings : public CGUIDialogSettingsManualBase +diff --git a/xbmc/video/videosync/CMakeLists.txt b/xbmc/video/videosync/CMakeLists.txt +index 0dcfab5..147373a 100644 +--- a/xbmc/video/videosync/CMakeLists.txt ++++ b/xbmc/video/videosync/CMakeLists.txt +@@ -20,7 +20,7 @@ if(CORE_SYSTEM_NAME STREQUAL rbpi) + list(APPEND HEADERS VideoSyncPi.h) + endif() + +-if(CORE_SYSTEM_NAME STREQUAL osx) ++if(CORE_SYSTEM_NAME STREQUAL darwin) + list(APPEND SOURCES VideoSyncOsx.cpp) + list(APPEND HEADERS VideoSyncOsx.h) + endif() +diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp +index 0c49cd2..5d98a66 100644 +--- a/xbmc/video/windows/GUIWindowFullScreen.cpp ++++ b/xbmc/video/windows/GUIWindowFullScreen.cpp +@@ -488,8 +488,8 @@ void CGUIWindowFullScreen::Process(unsigned int currentTime, CDirtyRegionList &d + + CGUIWindow::Process(currentTime, dirtyregion); + +- //! @todo This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect +- //! which is probably the job of the renderer as it can more easily track resizing etc. ++ // TODO: This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect ++ // which is probably the job of the renderer as it can more easily track resizing etc. + m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()); + } + +diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp +index 0aed13a..d8e81cb 100644 +--- a/xbmc/video/windows/GUIWindowVideoBase.cpp ++++ b/xbmc/video/windows/GUIWindowVideoBase.cpp +@@ -34,7 +34,6 @@ + #include "Application.h" + #include "NfoFile.h" + #include "PlayListPlayer.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "GUIPassword.h" + #include "filesystem/StackDirectory.h" + #include "filesystem/VideoDatabaseDirectory.h" +@@ -181,6 +180,10 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) + if (GetID() == WINDOW_VIDEO_NAV) + OnDeleteItem(iItem); + ++ // or be at the files window and have file deletion enabled ++ else if (GetID() == WINDOW_VIDEO_FILES && CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_ALLOWFILEDELETION)) ++ OnDeleteItem(iItem); ++ + // or be at the video playlists location + else if (m_vecItems->IsPath("special://videoplaylists/")) + OnDeleteItem(iItem); +@@ -258,7 +261,8 @@ void CGUIWindowVideoBase::OnItemInfo(const CFileItem& fileItem, ADDON::ScraperPt + + bool modified = ShowIMDB(CFileItemPtr(new CFileItem(item)), scraper, fromDB); + if (modified && +- (g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV)) // since we can be called from the music library we need this check ++ (g_windowManager.GetActiveWindow() == WINDOW_VIDEO_FILES || ++ g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV)) // since we can be called from the music library we need this check + { + int itemNumber = m_viewControl.GetSelectedItem(); + Refresh(); +@@ -1093,8 +1097,8 @@ bool CGUIWindowVideoBase::OnPlayMedia(int iItem, const std::string &player) + CLog::Log(LOGDEBUG, "%s %s", __FUNCTION__, CURL::GetRedacted(item.GetPath()).c_str()); + + +- //! @todo delete entire block in v18 +- //! @deprecated m_strStreamURL is deprecated in v17 ++ // TODO: delete entire block in v18 ++ // m_strStreamURL is deprecated + if (item.IsPVR()) + { + CPVRRecordingsPath path(item.GetPath()); +diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp +index 1818b43..a4e6c3d 100644 +--- a/xbmc/video/windows/GUIWindowVideoNav.cpp ++++ b/xbmc/video/windows/GUIWindowVideoNav.cpp +@@ -506,8 +506,8 @@ void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items) + + void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items, CVideoDatabase &database, bool allowReplaceLabels) + { +- //! @todo this could possibly be threaded as per the music info loading, +- //! we could also cache the info ++ // TODO: this could possibly be threaded as per the music info loading, ++ // we could also cache the info + if (!items.GetContent().empty() && !items.IsPlugin()) + return; // don't load for listings that have content set and weren't created from plugins + +@@ -965,7 +965,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) + item = m_vecItems->Get(itemNumber); + if (CGUIDialogContextMenu::OnContextButton("video", item, button)) + { +- //! @todo should we search DB for entries from plugins? ++ //TODO should we search DB for entries from plugins? + if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin() + && !item->IsLiveTV() &&!item->IsRSS() && !URIUtils::IsUPnP(item->GetPath())) + { +diff --git a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp +index 2faaf59..0d6d1e2 100644 +--- a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp ++++ b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp +@@ -24,7 +24,6 @@ + #include "Application.h" + #include "PlayListPlayer.h" + #include "PartyModeManager.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "dialogs/GUIDialogSmartPlaylistEditor.h" + #include "guilib/GUIWindowManager.h" + #include "guilib/GUIKeyboardFactory.h" +diff --git a/xbmc/view/GUIViewState.cpp b/xbmc/view/GUIViewState.cpp +index ceb7881..78f2cb4 100644 +--- a/xbmc/view/GUIViewState.cpp ++++ b/xbmc/view/GUIViewState.cpp +@@ -101,7 +101,7 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it + return new CGUIViewStateMusicPlaylist(items); + + if (items.GetPath() == "special://musicplaylists/") +- return new CGUIViewStateWindowMusicNav(items); ++ return new CGUIViewStateWindowMusicSongs(items); + + if (url.IsProtocol("androidapp")) + return new CGUIViewStateWindowPrograms(items); +@@ -112,11 +112,17 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it + if (windowId == WINDOW_MUSIC_NAV) + return new CGUIViewStateWindowMusicNav(items); + ++ if (windowId == WINDOW_MUSIC_FILES) ++ return new CGUIViewStateWindowMusicSongs(items); ++ + if (windowId == WINDOW_MUSIC_PLAYLIST) + return new CGUIViewStateWindowMusicPlaylist(items); + + if (windowId == WINDOW_MUSIC_PLAYLIST_EDITOR) +- return new CGUIViewStateWindowMusicNav(items); ++ return new CGUIViewStateWindowMusicSongs(items); ++ ++ if (windowId == WINDOW_VIDEO_FILES) ++ return new CGUIViewStateWindowVideoFiles(items); + + if (windowId == WINDOW_VIDEO_NAV) + return new CGUIViewStateWindowVideoNav(items); +@@ -556,7 +562,7 @@ CGUIViewStateFromItems::CGUIViewStateFromItems(const CFileItemList &items) : CGU + const GUIViewSortDetails sort = details[i]; + AddSortMethod(sort.m_sortDescription, sort.m_buttonLabel, sort.m_labelMasks); + } +- //! @todo Should default sort/view mode be specified? ++ // TODO: Should default sort/view mode be specified? + m_currentSortMethod = 0; + + SetViewAsControl(DEFAULT_VIEW_LIST); +diff --git a/xbmc/view/GUIViewState.h b/xbmc/view/GUIViewState.h +index 4ae382a..55d2eb2 100644 +--- a/xbmc/view/GUIViewState.h ++++ b/xbmc/view/GUIViewState.h +@@ -20,8 +20,6 @@ + * + */ + +-#include +- + #include "utils/LabelFormatter.h" + #include "utils/SortUtils.h" + #include "MediaSource.h" +diff --git a/xbmc/win32/WIN32Util.cpp b/xbmc/win32/WIN32Util.cpp +index 6b80d78..f7c5220 100644 +--- a/xbmc/win32/WIN32Util.cpp ++++ b/xbmc/win32/WIN32Util.cpp +@@ -328,7 +328,7 @@ bool CWIN32Util::XBMCShellExecute(const std::string &strPath, bool bWaitForScrip + + if(bWaitForScriptExit) + { +- //! @todo Pause music and video playback ++ // Todo: Pause music and video playback + WaitForSingleObject(ShExecInfo.hProcess,INFINITE); + } + +@@ -923,8 +923,7 @@ void CWIN32Util::GetDrivesByType(VECSOURCES &localDrives, Drive_Types eDriveType + } + else + { +- // Lets show it, like Windows explorer do... +- //! @todo Sorting should depend on driver letter ++ // Lets show it, like Windows explorer do... TODO: sorting should depend on driver letter + switch(uDriveType) + { + case DRIVE_CDROM: +diff --git a/xbmc/win32/WIN32Util.h b/xbmc/win32/WIN32Util.h +index 8687b90..7079e81 100644 +--- a/xbmc/win32/WIN32Util.h ++++ b/xbmc/win32/WIN32Util.h +@@ -20,8 +20,6 @@ + * + */ + +-#include +- + #include "URL.h" + #include "Cfgmgr32.h" + #include "MediaSource.h" +diff --git a/xbmc/win32/Win32DelayedDllLoad.cpp b/xbmc/win32/Win32DelayedDllLoad.cpp +index 60ffc22..dc22705 100644 +--- a/xbmc/win32/Win32DelayedDllLoad.cpp ++++ b/xbmc/win32/Win32DelayedDllLoad.cpp +@@ -18,13 +18,6 @@ + * + */ + +-/** +-* @todo this is to disable a change coming in update 3 +-* We should get rid of this and switch the hooks to const +-* once update 3 is rtm and we know our developers have +-* updated +-*/ +-#define DELAYIMP_INSECURE_WRITABLE_HOOKS 1 + #include + #include "Application.h" + #include "utils/StringUtils.h" +@@ -77,11 +70,5 @@ FARPROC WINAPI delayHookFailureFunc (unsigned dliNotify, PDelayLoadInfo pdli) + } + + // assign hook functions +-#if !defined(DELAYIMP_INSECURE_WRITABLE_HOOKS) +-const +-#endif + PfnDliHook __pfnDliNotifyHook2 = delayHookNotifyFunc; +-#if !defined(DELAYIMP_INSECURE_WRITABLE_HOOKS) +-const +-#endif + PfnDliHook __pfnDliFailureHook2 = delayHookFailureFunc; +diff --git a/xbmc/windowing/WinEvents.cpp b/xbmc/windowing/WinEvents.cpp +index 36c5fab..001256d 100644 +--- a/xbmc/windowing/WinEvents.cpp ++++ b/xbmc/windowing/WinEvents.cpp +@@ -54,6 +54,7 @@ + static WinEventsType g_imp; + static CCriticalSection g_lock; + static bool g_init = false; ++static bool g_suspend = false; + + void Init() + { +@@ -65,8 +66,23 @@ void Init() + } + } + ++void CWinEvents::Stop(bool suspend) ++{ ++ CSingleLock lock(g_lock); ++ ++ if (suspend == g_suspend) ++ return; ++ ++ g_suspend = suspend; ++ if (suspend) ++ g_imp.CloseDevices(); ++} ++ + void CWinEvents::MessagePush(XBMC_Event* ev) + { ++ if (g_suspend) ++ return; ++ + if (!g_init) + Init(); + g_imp.MessagePush(ev); +@@ -74,6 +90,9 @@ void CWinEvents::MessagePush(XBMC_Event* ev) + + bool CWinEvents::MessagePump() + { ++ if (g_suspend) ++ return false; ++ + if (!g_init) + Init(); + return g_imp.MessagePump(); +diff --git a/xbmc/windowing/WinEvents.h b/xbmc/windowing/WinEvents.h +index e04631f..0902183 100644 +--- a/xbmc/windowing/WinEvents.h ++++ b/xbmc/windowing/WinEvents.h +@@ -43,6 +43,7 @@ class CWinEvents + static void MessagePush(XBMC_Event* ev); + static bool MessagePump(); + static size_t GetQueueSize(); ++ static void Stop(bool suspend); + }; + + #endif // WINDOW_EVENTS_H +diff --git a/xbmc/windowing/WinEventsLinux.cpp b/xbmc/windowing/WinEventsLinux.cpp +index a958a23..156348d 100644 +--- a/xbmc/windowing/WinEventsLinux.cpp ++++ b/xbmc/windowing/WinEventsLinux.cpp +@@ -42,6 +42,11 @@ void CWinEventsLinux::RefreshDevices() + m_devices.InitAvailable(); + } + ++void CWinEventsLinux::CloseDevices() ++{ ++ m_devices.Close(); ++} ++ + bool CWinEventsLinux::IsRemoteLowBattery() + { + return m_devices.IsRemoteLowBattery(); +diff --git a/xbmc/windowing/WinEventsLinux.h b/xbmc/windowing/WinEventsLinux.h +index 1b1d2f2..edc5ba6 100644 +--- a/xbmc/windowing/WinEventsLinux.h ++++ b/xbmc/windowing/WinEventsLinux.h +@@ -34,6 +34,7 @@ public: + size_t GetQueueSize(); + void MessagePush(XBMC_Event *ev); + void RefreshDevices(); ++ void CloseDevices(); + void Notify(const Observable &obs, const ObservableMessage msg) + { + if (msg == ObservableMessagePeripheralsChanged) +diff --git a/xbmc/windowing/WinSystem.cpp b/xbmc/windowing/WinSystem.cpp +index 50cf0a7..878557f 100644 +--- a/xbmc/windowing/WinSystem.cpp ++++ b/xbmc/windowing/WinSystem.cpp +@@ -180,7 +180,7 @@ std::vector CWinSystemBase::ScreenResolutions(int screen, float + + // Can't assume a sort order + // don't touch RES_DESKTOP which is index 0 +- sort(resolutions.begin()+1, resolutions.end(), resSortPredicate); ++ sort(resolutions.begin()+0, resolutions.end(), resSortPredicate); + + return resolutions; + } +@@ -242,7 +242,7 @@ REFRESHRATE CWinSystemBase::DefaultRefreshRate(int screen, std::vectorGetValue(); + #else +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 6a22b33..4119178 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -20,9 +20,6 @@ + + #pragma once + +-#include +-#include +- + #include "windowing/WinSystem.h" + #include "utils/Stopwatch.h" + #include "threads/CriticalSection.h" +diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.cpp b/xbmc/windowing/X11/WinSystemX11GLContext.cpp +index f1f94ae..b975c5d 100644 +--- a/xbmc/windowing/X11/WinSystemX11GLContext.cpp ++++ b/xbmc/windowing/X11/WinSystemX11GLContext.cpp +@@ -111,7 +111,7 @@ bool CWinSystemX11GLContext::SetWindow(int width, int height, bool fullscreen, c + RefreshGLContext(m_currentOutput.compare(output) != 0); + XSync(m_dpy, FALSE); + g_graphicsContext.Clear(0); +- g_graphicsContext.Flip(true, false); ++ g_graphicsContext.Flip(true); + ResetVSync(); + + m_windowDirty = false; +diff --git a/xbmc/windowing/X11/WinSystemX11GLESContext.cpp b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp +index a9995d6..d671aa2 100644 +--- a/xbmc/windowing/X11/WinSystemX11GLESContext.cpp ++++ b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp +@@ -55,7 +55,7 @@ bool CWinSystemX11GLESContext::SetWindow(int width, int height, bool fullscreen, + RefreshGLContext(m_currentOutput.compare(output) != 0); + XSync(m_dpy, FALSE); + g_graphicsContext.Clear(0); +- g_graphicsContext.Flip(true, false); ++ g_graphicsContext.Flip(true); + ResetVSync(); + + m_windowDirty = false; +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index cd8bd12..e0595f3 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -104,7 +104,7 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff) + TiXmlElement *pRootElement = xmlDoc.RootElement(); + if (atoi(pRootElement->Attribute("id")) != screennum) + { +- //! @todo ERROR ++ // TODO ERROR + return false; + } + +@@ -407,7 +407,7 @@ void CXRandR::LoadCustomModeLinesToAllOutputs(void) + TiXmlElement *pRootElement = xmlDoc.RootElement(); + if (strcasecmp(pRootElement->Value(), "modelines") != 0) + { +- //! @todo ERROR ++ // TODO ERROR + return; + } + +diff --git a/xbmc/windowing/android/CMakeLists.txt b/xbmc/windowing/android/CMakeLists.txt +index b7782d0..8e58d66 100644 +--- a/xbmc/windowing/android/CMakeLists.txt ++++ b/xbmc/windowing/android/CMakeLists.txt +@@ -3,4 +3,3 @@ set(SOURCES WinEventsAndroid.cpp) + set(HEADERS WinEventsAndroid.h) + + core_add_library(windowing_android) +-add_dependencies(windowing_android libcpluff) +diff --git a/xbmc/windowing/egl/EGLEdid.cpp b/xbmc/windowing/egl/EGLEdid.cpp +new file mode 100644 +index 0000000..1e24c1d +--- /dev/null ++++ b/xbmc/windowing/egl/EGLEdid.cpp +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++#include "EGLEdid.h" ++#include "utils/log.h" ++#include "threads/SingleLock.h" ++#include "settings/DisplaySettings.h" ++ ++CEGLEdid g_EGLEdid; ++ ++CEGLEdid::CEGLEdid() ++ : m_fSar(0.0f) ++ , m_edidEmpty(true) ++{ ++ memset(&m_edid, 0, EDID_MAXSIZE); ++} ++ ++CEGLEdid::~CEGLEdid() ++{ ++} ++ ++float CEGLEdid::ValidateSAR(struct dt_dim *dtm, bool mb) ++{ ++ int Height = dtm->Height | (mb ? (dtm->msbits & 0x0f) << 8 : 0); ++ if (Height < 1) ++ return .0f; ++ ++ int Width = dtm->Width | (mb ? (dtm->msbits & 0xf0) << 4 : 0); ++ float t_sar = (float) Width / Height; ++ ++ if (t_sar < 0.33 || t_sar > 3.00) ++ t_sar = .0f; ++ else ++ CLog::Log(LOGINFO, "%s: Screen SAR: %.3f (from detailed: %s, %dx%d)",__FUNCTION__, t_sar, mb ? "yes" : "no", Width, Height); ++ ++ return t_sar; ++} ++ ++void CEGLEdid::CalcSAR() ++{ ++ CSingleLock lk(m_lock); ++ ++ m_fSar = .0f; ++ m_edidEmpty = true; ++ ReadEdidData(); ++ ++ // enumerate through (max four) detailed timing info blocks ++ // specs and lookup WxH [mm / in]. W and H are in 3 bytes, ++ // where 1st = W, 2nd = H, 3rd byte is 4bit/4bit. ++ // ++ // if DTM block starts with 0 - it is not DTM, skip ++ for (int i = EDID_DTM_START; i < 126 && m_fSar == 0 && *(m_edid +i); i += 18) ++ m_fSar = ValidateSAR((struct dt_dim *)(m_edid +i +EDID_DTM_OFFSET_DIMENSION), true); ++ ++ // fallback - info related to 'Basic display parameters.' is at offset 0x14-0x18. ++ // where W is 2nd byte, H 3rd. ++ if (m_fSar == 0) ++ m_fSar = ValidateSAR((struct dt_dim *)(m_edid +EDID_STRUCT_DISPLAY +1)); ++ ++ // if m_sar != 0, final SAR is usefull ++ // if it is 0, EDID info was missing or calculated ++ // SAR value wasn't sane ++ if (m_fSar == 0) ++ { ++ RESOLUTION_INFO res = CDisplaySettings::GetInstance().GetCurrentResolutionInfo(); ++ ++ CLog::Log(LOGWARNING, "%s: Screen SAR - not usable info",__FUNCTION__); ++ ++ if (res.iScreenWidth != 0) ++ m_fSar = res.iScreenHeight / res.iScreenWidth; ++ else ++ m_fSar = .0f; ++ } ++ ++ m_edidEmpty = false; ++} +diff --git a/xbmc/windowing/egl/EGLEdid.h b/xbmc/windowing/egl/EGLEdid.h +new file mode 100644 +index 0000000..e4b3287 +--- /dev/null ++++ b/xbmc/windowing/egl/EGLEdid.h +@@ -0,0 +1,71 @@ ++#pragma once ++ ++/* ++ * Copyright (C) 2011-2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "threads/CriticalSection.h" ++#include "threads/SingleLock.h" ++#include ++#include "guilib/GraphicContext.h" ++ ++#define EDID_STRUCT_DISPLAY 0x14 ++#define EDID_DTM_START 0x36 ++#define EDID_DTM_OFFSET_DIMENSION 0x0c ++#define EDID_EXTENSION_BLOCK_START 0x7e ++ ++#define EDID_STRUCT_DISPLAY 0x14 ++#define EDID_MAXSIZE 512 ++#define EDID_HEADERSIZE 8 ++ ++static const char EDID_HEADER[8] = { 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0 }; ++ ++class CEGLEdid ++{ ++ struct dt_dim { ++ uint8_t Width; ++ uint8_t Height; ++ uint8_t msbits; ++ }; ++ ++public: ++ CEGLEdid(); ++ virtual ~CEGLEdid(); ++ ++ bool ReadEdidData(); ++ const uint8_t *GetRawEdid() { Lock(); if (m_edidEmpty) CalcSAR(); return m_edidEmpty ? NULL : &m_edid[0]; } ++ ++ float GetSAR() const { CSingleLock lk(m_lock); return m_fSar; } ++ void CalcSAR(); ++ ++ void Lock() { m_lock.lock(); } ++ void Unlock() { m_lock.unlock(); } ++ ++ uint8_t m_edid[EDID_MAXSIZE]; ++ ++protected: ++ float ValidateSAR(struct dt_dim *dtm, bool mb = false); ++ ++ float m_fSar; ++ bool m_edidEmpty; ++ ++ CCriticalSection m_lock; ++}; ++ ++extern CEGLEdid g_EGLEdid; +diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlAndroid.h b/xbmc/windowing/egl/EGLNativeTypeAmlAndroid.h +index 188217c..6887537 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeAmlAndroid.h ++++ b/xbmc/windowing/egl/EGLNativeTypeAmlAndroid.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "EGLNativeTypeAndroid.h" + class CEGLNativeTypeAmlAndroid : public CEGLNativeTypeAndroid + { +diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +index 88cd385..3d6598a 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +@@ -55,7 +55,8 @@ bool CEGLNativeTypeAmlogic::CheckCompatibility() + std::string modalias = "/sys/class/graphics/" + m_framebuffer_name + "/device/modalias"; + + SysfsUtils::GetString(modalias, name); +- if (name.find("meson") != std::string::npos) ++ StringUtils::Trim(name); ++ if (name == "platform:mesonfb") + return true; + return false; + } +diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h +index cfb33ca..6867c38 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h ++++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "EGLNativeType.h" + class CEGLNativeTypeAmlogic : public CEGLNativeType + { +diff --git a/xbmc/windowing/egl/EGLNativeTypeAndroid.h b/xbmc/windowing/egl/EGLNativeTypeAndroid.h +index b88eb57..f26215d 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeAndroid.h ++++ b/xbmc/windowing/egl/EGLNativeTypeAndroid.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "EGLNativeType.h" + class CEGLNativeTypeAndroid : public CEGLNativeType + { +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index c7567a9..0bab5ad 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -23,6 +23,7 @@ + #include "system.h" + #include + ++#include "Application.h" + #include "EGLNativeTypeIMX.h" + #include + #include +@@ -39,13 +40,27 @@ + #include "windowing/WindowingFactory.h" + #include "cores/AudioEngine/AEFactory.h" + #include ++#include ++#include "peripherals/Peripherals.h" ++#include "peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h" ++ ++#include "EGLEdid.h" ++ ++using namespace PERIPHERALS; + + CEGLNativeTypeIMX::CEGLNativeTypeIMX() +- : m_sar(0.0f) +- , m_show(true) ++#ifdef HAS_IMXVPU ++ : m_show(true) + , m_display(NULL) + , m_window(NULL) ++ , m_ntsc(0) ++ , m_ignorenext(false) ++#endif + { ++#ifdef HAS_IMXVPU ++ m_show = true; ++ m_readonly = true; ++#endif + } + + CEGLNativeTypeIMX::~CEGLNativeTypeIMX() +@@ -54,12 +69,17 @@ CEGLNativeTypeIMX::~CEGLNativeTypeIMX() + + bool CEGLNativeTypeIMX::CheckCompatibility() + { ++#ifdef HAS_IMXVPU + std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); + return file.is_open(); ++#else ++ return false; ++#endif + } + + void CEGLNativeTypeIMX::Initialize() + { ++#ifdef HAS_IMXVPU + int fd; + + // Check if we can change the framebuffer resolution +@@ -102,7 +122,7 @@ void CEGLNativeTypeIMX::Initialize() + CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); + return; + } +-#ifdef HAS_IMXVPU ++ + struct mxcfb_color_key colorKey; + struct mxcfb_gbl_alpha gbl_alpha; + struct mxcfb_loc_alpha lalpha; +@@ -123,21 +143,20 @@ void CEGLNativeTypeIMX::Initialize() + colorKey.color_key = (16 << 16)|(8 << 8)|16; + if (ioctl(fd, MXCFB_SET_CLR_KEY, &colorKey) < 0) + CLog::Log(LOGERROR, "%s - Failed to setup color keying\n", __FUNCTION__); +-#endif +- // Unblank the fb +- if (ioctl(fd, FBIOBLANK, 0) < 0) +- { +- CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); +- } + +- close(fd); ++ // Check if we can change the framebuffer resolution ++ if (!m_readonly) ++ GetNativeResolution(&m_init); + +- m_sar = GetMonitorSAR(); ++ close(fd); ++#endif + return; + } + + void CEGLNativeTypeIMX::Destroy() + { ++#ifdef HAS_IMXVPU ++ CLog::Log(LOGDEBUG, "%s\n", __FUNCTION__); + struct fb_fix_screeninfo fixed_info; + void *fb_buffer; + int fd; +@@ -161,20 +180,29 @@ void CEGLNativeTypeIMX::Destroy() + memset(fb_buffer, 0x0, fixed_info.smem_len); + munmap(fb_buffer, fixed_info.smem_len); + } +- + close(fd); + ++ if (!m_readonly) ++ SysfsUtils::SetString("/sys/class/graphics/fb0/mode", m_init.strId + "\n"); ++ SysfsUtils::SetInt("/sys/class/graphics/fb1/blank", 1); ++ ++ system("/usr/bin/splash --force -i -m 'stopping kodi...'"); ++#endif + return; + } + + bool CEGLNativeTypeIMX::CreateNativeDisplay() + { ++ CLog::Log(LOGDEBUG,": %s", __FUNCTION__); ++#ifdef HAS_IMXVPU ++ if (m_display) ++ return true; ++ + // Force double-buffering + CEnvironment::setenv("FB_MULTI_BUFFER", "2", 0); +- +-#ifdef HAS_IMXVPU + // EGL will be rendered on fb0 +- m_display = fbGetDisplayByIndex(0); ++ if (!(m_display = fbGetDisplayByIndex(0))) ++ return false; + m_nativeDisplay = &m_display; + return true; + #else +@@ -184,8 +212,14 @@ bool CEGLNativeTypeIMX::CreateNativeDisplay() + + bool CEGLNativeTypeIMX::CreateNativeWindow() + { ++ CLog::Log(LOGDEBUG,": %s", __FUNCTION__); + #ifdef HAS_IMXVPU +- m_window = fbCreateWindow(m_display, 0, 0, 0, 0); ++ if (m_window) ++ return true; ++ ++ if (!(m_window = fbCreateWindow(m_display, 0, 0, 0, 0))) ++ return false; ++ + m_nativeWindow = &m_window; + return true; + #else +@@ -195,30 +229,39 @@ bool CEGLNativeTypeIMX::CreateNativeWindow() + + bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const + { +- if (!nativeDisplay) +- return false; ++#ifdef HAS_IMXVPU + if (!m_nativeDisplay) + return false; ++ + *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; + return true; ++#else ++ return false; ++#endif + } + + bool CEGLNativeTypeIMX::GetNativeWindow(XBNativeWindowType **nativeWindow) const + { +- if (!nativeWindow) +- return false; +- if (!m_nativeWindow || !m_window) ++#ifdef HAS_IMXVPU ++ if (!m_nativeWindow) + return false; ++ + *nativeWindow = (XBNativeWindowType*)m_nativeWindow; + return true; ++#else ++ return false; ++#endif + } + + bool CEGLNativeTypeIMX::DestroyNativeDisplay() + { ++ CLog::Log(LOGDEBUG,": %s", __FUNCTION__); + #ifdef HAS_IMXVPU + if (m_display) + fbDestroyDisplay(m_display); +- m_display = NULL; ++ ++ m_display = NULL; ++ m_nativeDisplay = NULL; + return true; + #else + return false; +@@ -227,47 +270,100 @@ bool CEGLNativeTypeIMX::DestroyNativeDisplay() + + bool CEGLNativeTypeIMX::DestroyNativeWindow() + { ++ CLog::Log(LOGDEBUG,": %s", __FUNCTION__); + #ifdef HAS_IMXVPU + if (m_window) + fbDestroyWindow(m_window); +- m_window = NULL; ++ ++ m_window = NULL; ++ m_nativeWindow = NULL; + return true; + #else + return false; + #endif + } + ++#ifdef HAS_IMXVPU ++bool ntsc_mode() ++{ ++ std::ifstream file("/sys/class/graphics/fb0/ntsc_mode"); ++ return file.is_open(); ++} ++ ++bool get_ntsc() ++{ ++ std::string mode; ++ SysfsUtils::GetString("/sys/class/graphics/fb0/ntsc_mode", mode); ++ return mode.find("active") != std::string::npos; ++} ++#endif ++ + bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const + { ++#ifdef HAS_IMXVPU + std::string mode; + SysfsUtils::GetString("/sys/class/graphics/fb0/mode", mode); +- return ModeToResolution(mode, res); ++ CLog::Log(LOGDEBUG,": %s, %s", __FUNCTION__, mode.c_str()); ++ ++ bool ret = ModeToResolution(mode, res); ++ if (ntsc_mode() && get_ntsc()) ++ res->fRefreshRate = (float)res->refresh_rate * (1000.0f/1001.0f); ++ else if (!ntsc_mode()) ++ return ret; ++ ++ SetStrMode(res); ++ return ret; ++#else ++ return false; ++#endif + } + + bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) + { ++#ifdef HAS_IMXVPU + if (m_readonly) + return false; + + std::string mode; ++ int new_ntsc; ++ ++ if (ntsc_mode()) ++ new_ntsc = fabs(res.refresh_rate - res.fRefreshRate) < FLT_EPSILON ? 0 : 1; ++ else ++ new_ntsc = 0; ++ + SysfsUtils::GetString("/sys/class/graphics/fb0/mode", mode); +- if (res.strId == mode) +- return false; ++ ++ if (res.strId == mode && m_ntsc == new_ntsc) ++ { ++ CLog::Log(LOGDEBUG,": %s - not changing res (%s vs %s)%s", __FUNCTION__, res.strId.c_str(), mode.c_str(), new_ntsc ? " mode NTSC" : ""); ++ return true; ++ } + + DestroyNativeWindow(); + DestroyNativeDisplay(); + ++ if (ntsc_mode()) ++ { ++ SysfsUtils::SetInt("/sys/class/graphics/fb0/ntsc_mode", new_ntsc); ++ m_ntsc = new_ntsc; ++ } ++ + ShowWindow(false); ++ CLog::Log(LOGDEBUG,": %s - changing resolution to %s%s", __FUNCTION__, res.strId.c_str(), new_ntsc ? " mode NTSC" : ""); + SysfsUtils::SetString("/sys/class/graphics/fb0/mode", res.strId + "\n"); + + CreateNativeDisplay(); + CreateNativeWindow(); + + CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); +- + return true; ++#else ++ return false; ++#endif + } + ++#ifdef HAS_IMXVPU + bool CEGLNativeTypeIMX::FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector &resolutions) + { + for (int i = 0; i < (int)resolutions.size(); i++) +@@ -282,9 +378,13 @@ bool CEGLNativeTypeIMX::FindMatchingResolution(const RESOLUTION_INFO &res, const + } + return false; + } ++#endif + + bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutions) + { ++#ifdef HAS_IMXVPU ++ g_EGLEdid.CalcSAR(); ++ + if (m_readonly) + return false; + +@@ -302,26 +402,53 @@ bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutio + RESOLUTION_INFO res; + for (size_t i = 0; i < probe_str.size(); i++) + { +- if(!StringUtils::StartsWith(probe_str[i], "S:") && !StringUtils::StartsWith(probe_str[i], "U:") && +- !StringUtils::StartsWith(probe_str[i], "V:") && !StringUtils::StartsWith(probe_str[i], "D:")) ++ if(!StringUtils::StartsWithNoCase(probe_str[i], "S:") && !StringUtils::StartsWithNoCase(probe_str[i], "U:") && ++ !StringUtils::StartsWithNoCase(probe_str[i], "V:") && !StringUtils::StartsWithNoCase(probe_str[i], "D:") && ++ !StringUtils::StartsWithNoCase(probe_str[i], "H:") && !StringUtils::StartsWithNoCase(probe_str[i], "T:")) + continue; + + if(ModeToResolution(probe_str[i], &res)) + if(!FindMatchingResolution(res, resolutions)) ++ { + resolutions.push_back(res); ++ if (!ntsc_mode()) ++ continue; ++ ++ if (res.refresh_rate == 24 || res.refresh_rate == 30 || res.refresh_rate == 60) ++ { ++ RESOLUTION_INFO res2 = res; ++ res2.fRefreshRate = (float)res.refresh_rate * (1000.0f/1001.0f); ++ SetStrMode(&res2); ++ resolutions.push_back(res2); ++ } ++ } + } + return resolutions.size() > 0; ++#else ++ return false; ++#endif + } + + bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const + { ++#ifdef HAS_IMXVPU + return GetNativeResolution(res); ++#else ++ return false; ++#endif + } + + bool CEGLNativeTypeIMX::ShowWindow(bool show) + { +- if (m_show == show) ++#ifdef HAS_IMXVPU ++ ++ if (m_ignorenext || (m_show == show)) ++ { ++ if (!show) ++ m_ignorenext ^= 1; ++ + return true; ++ } + + CLog::Log(LOGDEBUG, ": %s %s", __FUNCTION__, show?"show":"hide"); + SysfsUtils::SetInt("/sys/class/graphics/fb0/blank", show ? 0 : 1 ); +@@ -329,9 +456,13 @@ bool CEGLNativeTypeIMX::ShowWindow(bool show) + m_show = show; + + return true; ++#else ++ return false; ++#endif + } + +-float CEGLNativeTypeIMX::GetMonitorSAR() ++#ifdef HAS_IMXVPU ++bool CEGLEdid::ReadEdidData() + { + FILE *f_edid; + char *str = NULL; +@@ -346,7 +477,7 @@ float CEGLNativeTypeIMX::GetMonitorSAR() + f_edid = fopen("/sys/devices/soc0/soc.1/20e0000.hdmi_video/edid", "r"); + + if(!f_edid) +- return 0; ++ return false; + + // first check if EDID is in binary format by reading 512bytes, compare 1st 8bytes + // against EDID 1.4 identificator [0x0,0xff,0xff,0xff,0xff,0xff,0xff,0x0] +@@ -390,20 +521,15 @@ float CEGLNativeTypeIMX::GetMonitorSAR() + } + fclose(f_edid); + +- // info related to 'Basic display parameters.' is at offset 0x14-0x18. +- // where W is 2nd byte, H 3rd. +- int cmWidth = (int)*(m_edid +EDID_STRUCT_DISPLAY +1); +- int cmHeight = (int)*(m_edid +EDID_STRUCT_DISPLAY +2); +- if (cmHeight > 0) +- { +- float t_sar = (float) cmWidth / cmHeight; +- if (t_sar >= 0.33 && t_sar <= 3.0) +- return t_sar; +- } ++ return true; ++} + +- // if we end up here, H/W values or final SAR are useless +- // return 0 and use 1.0f as PR for all resolutions +- return 0; ++void CEGLNativeTypeIMX::SetStrMode(RESOLUTION_INFO *res) const ++{ ++ res->strMode = StringUtils::Format("%4sx%4s @ %.3f%s - Full Screen %s (%.3f) %s", StringUtils::Format("%d", res->iScreenWidth).c_str(), ++ StringUtils::Format("%d", res->iScreenHeight).c_str(), res->fRefreshRate, ++ res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : " ", HDMI_RES_GROUP_NAME(GETFLAGS_GROUP(res->dwFlags)), res->fPixelRatio, ++ res->dwFlags & D3DPRESENTFLAG_MODE3DSBS ? "- 3DSBS" : res->dwFlags & D3DPRESENTFLAG_MODE3DTB ? "- 3DTB" : ""); + } + + bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const +@@ -420,6 +546,13 @@ bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) + std::string fromMode = StringUtils::Mid(mode, 2); + StringUtils::Trim(fromMode); + ++ if (StringUtils::StartsWithNoCase(mode, "U:") || StringUtils::StartsWithNoCase(mode, "V:")) ++ res->dwFlags = HDMI_RES_GROUP_DMT; ++ else ++ res->dwFlags = HDMI_RES_GROUP_CEA; ++ ++ res->fPixelRatio = 1.0f; ++ + CRegExp split(true); + split.RegComp("([0-9]+)x([0-9]+)([pi])-([0-9]+)"); + if (split.RegFind(fromMode) < 0) +@@ -434,18 +567,30 @@ bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) + res->iHeight= h; + res->iScreenWidth = w; + res->iScreenHeight= h; +- res->fRefreshRate = r; +- res->dwFlags = p[0] == 'p' ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED; ++ if (!ntsc_mode() && StringUtils::isasciilowercaseletter(mode[0])) ++ res->fRefreshRate = (float)r * 1000 / 1001; ++ else ++ res->fRefreshRate = (float)r; ++ res->refresh_rate = (float)r; ++ ++ res->dwFlags = MAKEFLAGS(res->dwFlags, 0, p[0] != 'p' && p[0] != 'd'); ++ ++ if (StringUtils::StartsWithNoCase(mode, "H:")) { ++ res->dwFlags |= D3DPRESENTFLAG_MODE3DSBS; ++ res->fPixelRatio = 2.0f; ++ } else if (StringUtils::StartsWithNoCase(mode, "T:")) { ++ res->dwFlags |= D3DPRESENTFLAG_MODE3DTB; ++ res->fPixelRatio = 0.5f; ++ } + + res->iScreen = 0; + res->bFullScreen = true; + res->iSubtitles = (int)(0.965 * res->iHeight); + +- res->fPixelRatio = !m_sar ? 1.0f : (float)m_sar / res->iScreenWidth * res->iScreenHeight; +- res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, +- res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); ++ res->fPixelRatio *= (g_EGLEdid.GetSAR() ? (float)g_EGLEdid.GetSAR() / res->iScreenWidth * res->iScreenHeight : (float)1.0f); + res->strId = mode; ++ SetStrMode(res); + + return res->iWidth > 0 && res->iHeight> 0; + } +- ++#endif +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h +index 53cbc2e..f7fcca8 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.h ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h +@@ -19,20 +19,11 @@ + * . + * + */ +- +-#include +-#include +- + #include + + #include + #include "EGLNativeType.h" +- +-#define EDID_STRUCT_DISPLAY 0x14 +-#define EDID_MAXSIZE 512 +-#define EDID_HEADERSIZE 8 +- +-static const char EDID_HEADER[EDID_HEADERSIZE] = { 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0 }; ++#include "windowing/egl/vc_hdmi.h" + + class CEGLNativeTypeIMX : public CEGLNativeType + { +@@ -58,17 +49,22 @@ public: + virtual bool ProbeResolutions(std::vector &resolutions); + virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; + +- virtual bool ShowWindow(bool show); ++ virtual bool ShowWindow(bool show = true); + ++#ifdef HAS_IMXVPU + protected: + bool m_readonly; +- float m_sar; + bool m_show; ++ RESOLUTION_INFO m_init; + bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const; + bool FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector &resolutions); +- float GetMonitorSAR(); + + EGLNativeDisplayType m_display; + EGLNativeWindowType m_window; +- uint8_t m_edid[EDID_MAXSIZE]; ++ ++private: ++ void SetStrMode(RESOLUTION_INFO *res) const; ++ int m_ntsc; ++ bool m_ignorenext; ++#endif + }; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRKAndroid.h b/xbmc/windowing/egl/EGLNativeTypeRKAndroid.h +index 98b89f1..69baaed 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRKAndroid.h ++++ b/xbmc/windowing/egl/EGLNativeTypeRKAndroid.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "EGLNativeTypeAndroid.h" + class CEGLNativeTypeRKAndroid : public CEGLNativeTypeAndroid + { +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index ee29770..4b83bb7 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -32,6 +32,13 @@ + #include "guilib/StereoscopicsManager.h" + #include "rendering/RenderSystem.h" + #include ++#include "peripherals/Peripherals.h" ++#include "peripherals/bus/PeripheralBus.h" ++#include "peripherals/bus/linux/PeripheralBusPLATFORMLibUdev.h" ++ ++#include "EGLEdid.h" ++ ++using namespace PERIPHERALS; + + #ifndef __VIDEOCORE4__ + #define __VIDEOCORE4__ +@@ -69,10 +76,14 @@ static SDTV_ASPECT_T get_sdtv_aspect_from_display_aspect(float display_aspect); + #endif + + CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI() ++#if defined(TARGET_RASPBERRY_PI) ++ : m_video(NULL) ++#endif + { + #if defined(TARGET_RASPBERRY_PI) + m_DllBcmHost = NULL; + m_nativeWindow = NULL; ++ m_event.Reset(); + #endif + } + +@@ -108,12 +119,32 @@ void CEGLNativeTypeRaspberryPI::Initialize() + + m_DllBcmHost = new DllBcmHost; + m_DllBcmHost->Load(); ++ vc_tv_register_callback(CallbackTvServiceCallback, this); ++ ++ TV_DISPLAY_STATE_T tv_state; ++ m_DllBcmHost->vc_tv_get_display_state(&tv_state); ++ ++ PeripheralBusPtr m_bus = std::make_shared(&g_peripherals); ++ g_peripherals.CreatePeripheralBus(m_bus); ++ ++ PeripheralScanResult result(m_bus->Type()); ++ PeripheralScanResults results; ++ result.m_strLocation = "/sys/class/graphics/fb0"; ++ result.m_iSequence = m_bus->GetNumberOfPeripheralsWithFeature(FEATURE_CABLESTATE); ++ result.m_type = PERIPHERAL_VIDEO; ++ result.m_strDeviceName = "generic_video"; ++ result.m_iVendorId = 0; ++ result.m_iProductId = 0; ++ results.m_results.push_back(result); ++ ++ m_video = m_bus->RegisterNewDevice(result); + #endif + } + + void CEGLNativeTypeRaspberryPI::Destroy() + { + #if defined(TARGET_RASPBERRY_PI) ++ vc_tv_unregister_callback_full(CallbackTvServiceCallback, this); + if(m_DllBcmHost && m_DllBcmHost->IsLoaded()) + m_DllBcmHost->Unload(); + delete m_DllBcmHost; +@@ -175,10 +206,69 @@ bool CEGLNativeTypeRaspberryPI::DestroyNativeWindow() + #endif + } + ++#if defined(TARGET_RASPBERRY_PI) ++static float get_display_aspect_ratio(SDTV_ASPECT_T aspect); ++#endif ++ + bool CEGLNativeTypeRaspberryPI::GetNativeResolution(RESOLUTION_INFO *res) const + { + #if defined(TARGET_RASPBERRY_PI) +- *res = m_desktopRes; ++ TV_DISPLAY_STATE_T tv_state; ++ ++ // get current display settings state ++ memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); ++ m_DllBcmHost->vc_tv_get_display_state(&tv_state); ++ ++ if ((tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) != 0) // hdtv ++ { ++ res->iScreen = 0; ++ res->bFullScreen = true; ++ res->iWidth = tv_state.display.hdmi.width; ++ res->iHeight = tv_state.display.hdmi.height; ++ res->iScreenWidth = tv_state.display.hdmi.width; ++ res->iScreenHeight= tv_state.display.hdmi.height; ++ res->dwFlags = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode); ++ res->fPixelRatio = g_EGLEdid.GetSAR() ? (float)g_EGLEdid.GetSAR() / ((float)res->iScreenWidth / (float)res->iScreenHeight) : 1.0f; ++ // Also add 3D flags ++ if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) ++ { ++ res->dwFlags |= D3DPRESENTFLAG_MODE3DSBS; ++ res->fPixelRatio *= 2.0; ++ } ++ else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF) ++ { ++ res->dwFlags |= D3DPRESENTFLAG_MODE3DTB; ++ res->fPixelRatio *= 0.5; ++ } ++ HDMI_PROPERTY_PARAM_T property; ++ property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; ++ vc_tv_hdmi_get_property(&property); ++ res->fRefreshRate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tv_state.display.hdmi.frame_rate * (1000.0f/1001.0f) : tv_state.display.hdmi.frame_rate; ++ } ++ else if ((tv_state.state & ( VC_SDTV_NTSC | VC_SDTV_PAL )) != 0) // sdtv ++ { ++ res->iScreen = 0; ++ res->bFullScreen = true; ++ res->iWidth = tv_state.display.sdtv.width; ++ res->iHeight = tv_state.display.sdtv.height; ++ res->iScreenWidth = tv_state.display.sdtv.width; ++ res->iScreenHeight= tv_state.display.sdtv.height; ++ res->dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, tv_state.display.sdtv.mode, 1); ++ res->fRefreshRate = (float)tv_state.display.sdtv.frame_rate; ++ res->fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)res->iScreenWidth / (float)res->iScreenHeight); ++ } ++ else if ((tv_state.state & VC_LCD_ATTACHED_DEFAULT) != 0) // lcd ++ { ++ res->iScreen = 0; ++ res->bFullScreen = true; ++ res->iWidth = tv_state.display.sdtv.width; ++ res->iHeight = tv_state.display.sdtv.height; ++ res->iScreenWidth = tv_state.display.sdtv.width; ++ res->iScreenHeight= tv_state.display.sdtv.height; ++ res->dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, 0, 0); ++ res->fRefreshRate = (float)tv_state.display.sdtv.frame_rate; ++ res->fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)res->iScreenWidth / (float)res->iScreenHeight); ++ } + + DLOG("CEGLNativeTypeRaspberryPI::GetNativeResolution %s\n", res->strMode.c_str()); + return true; +@@ -208,15 +298,9 @@ int CEGLNativeTypeRaspberryPI::AddUniqueResolution(RESOLUTION_INFO &res, std::ve + { + SetResolutionString(res); + int i = FindMatchingResolution(res, resolutions, desktop); +- if (i>=0) +- { // don't replace a progressive resolution with an interlaced one of same resolution +- if (!(res.dwFlags & D3DPRESENTFLAG_INTERLACED)) +- resolutions[i] = res; +- } +- else +- { +- resolutions.push_back(res); +- } ++ if (i == -1) ++ resolutions.push_back(res); ++ + return i; + } + #endif +@@ -233,8 +317,6 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + { + uint32_t mode3d = HDMI_3D_FORMAT_NONE; +- sem_init(&m_tv_synced, 0, 0); +- m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); + + if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL || stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) + { +@@ -274,7 +356,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + CStereoscopicsManager::GetInstance().ConvertGuiStereoModeToString(stereo_mode), + mode3d==HDMI_3D_FORMAT_FRAME_PACKING ? " FP" : mode3d==HDMI_3D_FORMAT_SBS_HALF ? " SBS" : mode3d==HDMI_3D_FORMAT_TB_HALF ? " TB" : ""); + +- sem_wait(&m_tv_synced); ++ m_event.WaitMSec(10000); + } + else + { +@@ -283,16 +365,11 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + CStereoscopicsManager::GetInstance().ConvertGuiStereoModeToString(stereo_mode), + mode3d==HDMI_3D_FORMAT_FRAME_PACKING ? " FP" : mode3d==HDMI_3D_FORMAT_SBS_HALF ? " SBS" : mode3d==HDMI_3D_FORMAT_TB_HALF ? " TB" : ""); + } +- m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback); +- sem_destroy(&m_tv_synced); + + m_desktopRes = res; + } + else if(!GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + { +- sem_init(&m_tv_synced, 0, 0); +- m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); +- + SDTV_OPTIONS_T options; + options.aspect = get_sdtv_aspect_from_display_aspect((float)res.iScreenWidth / (float)res.iScreenHeight); + +@@ -303,15 +380,13 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + CLog::Log(LOGDEBUG, "EGL set SDTV mode (%d,%d)=%d\n", + GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success); + +- sem_wait(&m_tv_synced); ++ m_event.WaitMSec(10000); + } + else + { + CLog::Log(LOGERROR, "EGL failed to set SDTV mode (%d,%d)=%d\n", + GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success); + } +- m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback); +- sem_destroy(&m_tv_synced); + + m_desktopRes = res; + } +@@ -485,74 +560,11 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + if(!m_DllBcmHost) + return false; + +- /* read initial desktop resolution before probe resolutions. +- * probing will replace the desktop resolution when it finds the same one. +- * we raplace it because probing will generate more detailed +- * resolution flags we don't get with vc_tv_get_state. +- */ ++ g_EGLEdid.CalcSAR(); + +- if(m_initDesktopRes) +- { +- TV_DISPLAY_STATE_T tv_state; +- +- // get current display settings state +- memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); +- m_DllBcmHost->vc_tv_get_display_state(&tv_state); +- +- if ((tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) != 0) // hdtv +- { +- m_desktopRes.iScreen = 0; +- m_desktopRes.bFullScreen = true; +- m_desktopRes.iWidth = tv_state.display.hdmi.width; +- m_desktopRes.iHeight = tv_state.display.hdmi.height; +- m_desktopRes.iScreenWidth = tv_state.display.hdmi.width; +- m_desktopRes.iScreenHeight= tv_state.display.hdmi.height; +- m_desktopRes.dwFlags = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode); +- m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); +- HDMI_PROPERTY_PARAM_T property; +- property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; +- vc_tv_hdmi_get_property(&property); +- m_desktopRes.fRefreshRate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tv_state.display.hdmi.frame_rate * (1000.0f/1001.0f) : tv_state.display.hdmi.frame_rate; +- } +- else if ((tv_state.state & ( VC_SDTV_NTSC | VC_SDTV_PAL )) != 0) // sdtv +- { +- m_desktopRes.iScreen = 0; +- m_desktopRes.bFullScreen = true; +- m_desktopRes.iWidth = tv_state.display.sdtv.width; +- m_desktopRes.iHeight = tv_state.display.sdtv.height; +- m_desktopRes.iScreenWidth = tv_state.display.sdtv.width; +- m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; +- m_desktopRes.dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, tv_state.display.sdtv.mode, 1); +- m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; +- m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); +- } +- else if ((tv_state.state & VC_LCD_ATTACHED_DEFAULT) != 0) // lcd +- { +- m_desktopRes.iScreen = 0; +- m_desktopRes.bFullScreen = true; +- m_desktopRes.iWidth = tv_state.display.sdtv.width; +- m_desktopRes.iHeight = tv_state.display.sdtv.height; +- m_desktopRes.iScreenWidth = tv_state.display.sdtv.width; +- m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; +- m_desktopRes.dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, 0, 0); +- m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; +- m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); +- } +- +- SetResolutionString(m_desktopRes); +- +- m_initDesktopRes = false; +- +- m_desktopRes.iSubtitles = (int)(0.965 * m_desktopRes.iHeight); +- +- CLog::Log(LOGDEBUG, "EGL initial desktop resolution %s (%.2f)\n", m_desktopRes.strMode.c_str(), m_desktopRes.fPixelRatio); +- } +- +- if(GETFLAGS_GROUP(m_desktopRes.dwFlags) && GETFLAGS_MODE(m_desktopRes.dwFlags)) +- { +- GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions); +- GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions); +- } ++ GetNativeResolution(&m_desktopRes); ++ GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions); ++ GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions); + { + AddUniqueResolution(m_desktopRes, resolutions, true); + CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags); +@@ -641,7 +653,7 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v + res.iHeight = tv->height; + res.iScreenWidth = tv->width; + res.iScreenHeight = tv->height; +- res.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res.iScreenWidth / (float)res.iScreenHeight); ++ res.fPixelRatio = g_EGLEdid.GetSAR() ? (float)g_EGLEdid.GetSAR() / ((float)res.iScreenWidth / (float)res.iScreenHeight) : 1.0f; + res.iSubtitles = (int)(0.965 * res.iHeight); + + if (!m_desktopRes.dwFlags && prefer_group == group && prefer_mode == tv->code) +@@ -669,15 +681,19 @@ void CEGLNativeTypeRaspberryPI::TvServiceCallback(uint32_t reason, uint32_t para + switch(reason) + { + case VC_HDMI_UNPLUGGED: ++ if (m_video) ++ m_video->OnDeviceChanged(CABLE_DISCONNECTED); + break; +- case VC_HDMI_STANDBY: ++ case VC_HDMI_ATTACHED: ++ if (m_video) ++ m_video->OnDeviceChanged(CABLE_CONNECTED); + break; + case VC_SDTV_NTSC: + case VC_SDTV_PAL: + case VC_HDMI_HDMI: + case VC_HDMI_DVI: + //Signal we are ready now +- sem_post(&m_tv_synced); ++ m_event.Set(); + break; + default: + break; +@@ -690,5 +706,33 @@ void CEGLNativeTypeRaspberryPI::CallbackTvServiceCallback(void *userdata, uint32 + callback->TvServiceCallback(reason, param1, param2); + } + +-#endif ++bool CEGLEdid::ReadEdidData() ++{ ++ uint8_t buffer[128]; ++ size_t offset = 0; ++ int i, extensions = 0; ++ ++ int siz = vc_tv_hdmi_ddc_read(offset, sizeof(buffer), buffer); ++ offset += sizeof(buffer); ++ ++ /* First block always exist */ ++ if (siz == sizeof(buffer)) ++ { ++ memcpy(&m_edid, &buffer, sizeof(buffer)); ++ extensions = buffer[0x7e]; /* This tells you how many more blocks to read */ + ++ for (i = 0; i < extensions && i < EDID_MAXSIZE - sizeof(buffer); i++, offset += sizeof(buffer)) ++ { ++ siz = vc_tv_hdmi_ddc_read(offset, sizeof(buffer), buffer); ++ ++ if (siz != sizeof(buffer)) ++ break; ++ ++ memcpy((uint8_t *)(&m_edid + offset), &buffer, sizeof(buffer)); ++ } ++ } ++ ++ return true; ++} ++ ++#endif +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +index b524bb4..904645f 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +@@ -20,14 +20,15 @@ + * + */ + +-#include +-#include +- + #include "EGLNativeType.h" + #if defined(TARGET_RASPBERRY_PI) + #include + #include + #endif ++#include "peripherals/Peripherals.h" ++#include "threads/Thread.h" ++ ++using namespace PERIPHERALS; + + class DllBcmHost; + class CEGLNativeTypeRaspberryPI : public CEGLNativeType +@@ -55,17 +56,19 @@ public: + virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; + + virtual bool ShowWindow(bool show); ++ + #if defined(TARGET_RASPBERRY_PI) + private: + DllBcmHost *m_DllBcmHost; + DISPMANX_ELEMENT_HANDLE_T m_dispman_display; + DISPMANX_ELEMENT_HANDLE_T m_dispman_element; + TV_GET_STATE_RESP_T m_tv_state; +- sem_t m_tv_synced; ++ CEvent m_event; + RESOLUTION_INFO m_desktopRes; + int m_width; + int m_height; + int m_initDesktopRes; ++ PERIPHERALS::CPeripheral *m_video; + + void GetSupportedModes(HDMI_RES_GROUP_T group, std::vector &resolutions); + void TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2); +diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp +index 0074027..76d1c4a 100644 +--- a/xbmc/windowing/egl/EGLWrapper.cpp ++++ b/xbmc/windowing/egl/EGLWrapper.cpp +@@ -85,6 +85,7 @@ bool CEGLWrapper::Initialize(const std::string &implementation) + { + CEGLNativeType *nativeGuess = NULL; + ++ system("/usr/bin/splash --force -b"); + // Try to create each backend in sequence and go with the first one + // that we know will work + if ( +diff --git a/xbmc/windowing/egl/EGLWrapper.h b/xbmc/windowing/egl/EGLWrapper.h +index 5a74868..f133d86 100644 +--- a/xbmc/windowing/egl/EGLWrapper.h ++++ b/xbmc/windowing/egl/EGLWrapper.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/Resolution.h" + #include + class CEGLNativeType; +diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in +index 3754233..ffaec1c 100644 +--- a/xbmc/windowing/egl/Makefile.in ++++ b/xbmc/windowing/egl/Makefile.in +@@ -14,6 +14,7 @@ ifeq (@USE_IMXVPU@,1) + SRCS+= EGLNativeTypeIMX.cpp + endif + SRCS+= EGLWrapper.cpp ++SRCS+= EGLEdid.cpp + + LIB = windowing_egl.a + +diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp +index 852f337..302001f 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.cpp ++++ b/xbmc/windowing/egl/WinSystemEGL.cpp +@@ -18,6 +18,7 @@ + * + */ + #include "system.h" ++#include "Application.h" + + #ifdef HAS_EGL + +@@ -29,6 +30,7 @@ + #include "settings/AdvancedSettings.h" + #include "settings/Settings.h" + #include "settings/DisplaySettings.h" ++#include "guilib/Resolution.h" + #include "guilib/DispResource.h" + #include "threads/SingleLock.h" + #ifdef HAS_IMXVPU +@@ -56,7 +58,6 @@ CWinSystemEGL::CWinSystemEGL() : CWinSystemBase() + + m_egl = NULL; + m_iVSyncMode = 0; +- m_delayDispReset = false; + } + + CWinSystemEGL::~CWinSystemEGL() +@@ -284,20 +285,9 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + m_stereo_mode == stereo_mode) + { + CLog::Log(LOGDEBUG, "CWinSystemEGL::CreateNewWindow: No need to create a new window"); ++#if !defined(TARGET_RASPBERRY_PI) + return true; +- } +- +- int delay = CSettings::GetInstance().GetInt("videoscreen.delayrefreshchange"); +- if (delay > 0) +- { +- m_delayDispReset = true; +- m_dispResetTimer.Set(delay * 100); +- } +- +- { +- CSingleLock lock(m_resourceSection); +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnLostDisplay(); ++#endif + } + + m_stereo_mode = stereo_mode; +@@ -314,7 +304,6 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + return false; + } + +- if (!m_delayDispReset) + { + CSingleLock lock(m_resourceSection); + // tell any shared resources +@@ -362,7 +351,7 @@ void CWinSystemEGL::UpdateResolutions() + { + CWinSystemBase::UpdateResolutions(); + +- RESOLUTION_INFO resDesktop, curDisplay; ++ RESOLUTION_INFO curDisplay, resDesktop = CDisplaySettings::GetInstance().GetResolutionInfo(CDisplaySettings::GetInstance().GetCurrentResolution()); + std::vector resolutions; + + if (!m_egl->ProbeResolutions(resolutions) || resolutions.empty()) +@@ -381,14 +370,6 @@ void CWinSystemEGL::UpdateResolutions() + } + } + +- /* ProbeResolutions includes already all resolutions. +- * Only get desktop resolution so we can replace xbmc's desktop res +- */ +- if (m_egl->GetNativeResolution(&curDisplay)) +- resDesktop = curDisplay; +- +- +- RESOLUTION ResDesktop = RES_INVALID; + RESOLUTION res_index = RES_DESKTOP; + + for (size_t i = 0; i < resolutions.size(); i++) +@@ -404,41 +385,43 @@ void CWinSystemEGL::UpdateResolutions() + g_graphicsContext.ResetOverscan(resolutions[i]); + CDisplaySettings::GetInstance().GetResolutionInfo(res_index) = resolutions[i]; + +- CLog::Log(LOGNOTICE, "Found resolution %d x %d for display %d with %d x %d%s @ %f Hz\n", +- resolutions[i].iWidth, +- resolutions[i].iHeight, +- resolutions[i].iScreen, +- resolutions[i].iScreenWidth, +- resolutions[i].iScreenHeight, +- resolutions[i].dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", +- resolutions[i].fRefreshRate); ++ CLog::Log(LOGNOTICE, "Found resolution %s\n", resolutions[i].strMode.c_str()); ++ ++ res_index = (RESOLUTION)((int)res_index + 1); ++ } + ++ /* ProbeResolutions includes already all resolutions. ++ * Only get desktop resolution so we can replace xbmc's desktop res ++ */ ++ if (resDesktop.strMode.empty() || CDisplaySettings::GetInstance().GetCurrentResolution() != CDisplaySettings::GetInstance().GetDisplayResolution()) ++ resDesktop = CDisplaySettings::GetInstance().GetResolutionInfo(CDisplaySettings::GetInstance().GetDisplayResolution()); ++ if (CDisplaySettings::GetInstance().GetCurrentResolution() == RES_DESKTOP) ++ if (m_egl->GetNativeResolution(&curDisplay)) ++ resDesktop = curDisplay; ++ ++ CLog::Log(LOGDEBUG, "Looking for resolution %s", resDesktop.strMode.c_str()); ++ RESOLUTION ResDesktop = RES_INVALID; ++ ++ for (size_t i = 0; i < resolutions.size(); i++) + if(resDesktop.iWidth == resolutions[i].iWidth && + resDesktop.iHeight == resolutions[i].iHeight && + resDesktop.iScreenWidth == resolutions[i].iScreenWidth && + resDesktop.iScreenHeight == resolutions[i].iScreenHeight && + (resDesktop.dwFlags & D3DPRESENTFLAG_MODEMASK) == (resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) && +- fabs(resDesktop.fRefreshRate - resolutions[i].fRefreshRate) < FLT_EPSILON) ++ fabs(resDesktop.fRefreshRate - resolutions[i].fRefreshRate) < FLT_EPSILON && ++ fabs(resDesktop.fPixelRatio - resolutions[i].fPixelRatio) < FLT_EPSILON) + { +- ResDesktop = res_index; ++ ResDesktop = (RESOLUTION)(i + (int)RES_DESKTOP); + } + +- res_index = (RESOLUTION)((int)res_index + 1); +- } +- +- // swap desktop index for desktop res if available +- if (ResDesktop != RES_INVALID) ++ if (ResDesktop == RES_INVALID) + { +- CLog::Log(LOGNOTICE, "Found (%dx%d%s@%f) at %d, setting to RES_DESKTOP at %d", +- resDesktop.iWidth, resDesktop.iHeight, +- resDesktop.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", +- resDesktop.fRefreshRate, +- (int)ResDesktop, (int)RES_DESKTOP); +- +- RESOLUTION_INFO desktop = CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP); +- CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP) = CDisplaySettings::GetInstance().GetResolutionInfo(ResDesktop); +- CDisplaySettings::GetInstance().GetResolutionInfo(ResDesktop) = desktop; ++ ResDesktop = CDisplaySettings::GetInstance().GetDisplayResolution(); ++ CLog::Log(LOGNOTICE, "New screen doesn't provide previous resolution. Will change to %d (%s)", ResDesktop, ++ CDisplaySettings::GetInstance().GetResolutionInfo(ResDesktop).strMode.c_str()); + } ++ ++ CDisplaySettings::GetInstance().SetCurrentResolution(ResDesktop); + } + + bool CWinSystemEGL::IsExtSupported(const char* extension) +@@ -454,14 +437,6 @@ bool CWinSystemEGL::IsExtSupported(const char* extension) + + void CWinSystemEGL::PresentRenderImpl(bool rendered) + { +- if (m_delayDispReset && m_dispResetTimer.IsTimePast()) +- { +- m_delayDispReset = false; +- CSingleLock lock(m_resourceSection); +- // tell any shared resources +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnResetDisplay(); +- } + if (!rendered) + return; + m_egl->SwapBuffers(m_display, m_surface); +diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h +index c24bb35..f2991b2 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.h ++++ b/xbmc/windowing/egl/WinSystemEGL.h +@@ -23,14 +23,10 @@ + * + */ + +-#include +-#include +- + #include "rendering/gles/RenderSystemGLES.h" + #include "utils/GlobalsHandling.h" + #include + #include "windowing/WinSystem.h" +-#include "threads/SystemClock.h" + + class CEGLWrapper; + class IDispResource; +@@ -88,8 +84,6 @@ protected: + std::string m_extensions; + CCriticalSection m_resourceSection; + std::vector m_resources; +- bool m_delayDispReset; +- XbmcThreads::EndTime m_dispResetTimer; + }; + + XBMC_GLOBAL_REF(CWinSystemEGL,g_Windowing); +diff --git a/xbmc/windowing/egl/vc_hdmi.h b/xbmc/windowing/egl/vc_hdmi.h +new file mode 100644 +index 0000000..c8e21ce +--- /dev/null ++++ b/xbmc/windowing/egl/vc_hdmi.h +@@ -0,0 +1,565 @@ ++/* ++Copyright (c) 2012, Broadcom Europe Ltd ++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 copyright holder 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 AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. ++*/ ++ ++/* ++ * HDMI common host header for TV service, defines resolution code which host applications should ++ * use for power up command for HDMI ++ */ ++ ++#ifndef _VC_HDMI_H_ ++#define _VC_HDMI_H_ ++ ++#include "guilib/gui3d.h" ++ ++typedef int VC_HDMI_BOOL_T; ++ ++/** ++ * HDMI resolution groups. There are two main groups: ++ * CEA - the conventional HDMI ones like 720p ++ * DMT - computer monitor resolutions like XGA ++ */ ++typedef enum { ++ HDMI_RES_GROUP_INVALID = 0, /**< Initialised value */ ++ HDMI_RES_GROUP_CEA = 1, /**< CEA - HDMI device */ ++ HDMI_RES_GROUP_DMT = 2, /**< DMT - computer monitors */ ++ HDMI_RES_GROUP_CEA_3D = 3, /* deprecated */ ++ ++} HDMI_RES_GROUP_T; ++ ++ ++/** ++ * CEA 861 defined video code and aspect ratios for various HDMI modes ++ * Not all values are valid for AVI infoframe ++ */ ++typedef enum { ++ HDMI_ASPECT_UNKNOWN = 0, /**< Unknown aspect ratio, or not one of the values below */ ++ HDMI_ASPECT_4_3 = 1, /**< 4:3 */ ++ HDMI_ASPECT_14_9 = 2, /**< 14:9 */ ++ HDMI_ASPECT_16_9 = 3, /**< 16:9 */ ++ HDMI_ASPECT_5_4 = 4, /**< 5:4 */ ++ HDMI_ASPECT_16_10 = 5, /**< 16:10*/ ++ HDMI_ASPECT_15_9 = 6, /**< 15:9 */ ++ HDMI_ASPECT_64_27 = 7, /**< 64:27 */ ++ HDMI_ASPECT_21_9 = HDMI_ASPECT_64_27 /**< 21:9 is jargon, 64:27 is the actual aspect ratio */ ++ /* More aspect ratio values may be added here if defined by CEA in future */ ++} HDMI_ASPECT_T; ++ ++/** ++ * Display options set the bounding box (only used in CEA mode) ++ */ ++typedef struct { ++ uint16_t aspect; /**> 16) & 0xff )) ++#define GETFLAGS_MODE(f) ( ( (f) >>24 ) & 0xff ) ++ ++#define IS_3D(f) ( f & (D3DPRESENTFLAG_MODE3DSBS | D3DPRESENTFLAG_MODE3DTB) ) ++ ++#endif /*HDMI_RES_GROUP_NAME*/ +diff --git a/xbmc/windowing/osx/CMakeLists.txt b/xbmc/windowing/osx/CMakeLists.txt +index db2c51c..b4006d6 100644 +--- a/xbmc/windowing/osx/CMakeLists.txt ++++ b/xbmc/windowing/osx/CMakeLists.txt +@@ -1,4 +1,4 @@ +-if(CORE_SYSTEM_NAME STREQUAL osx) ++if(CORE_SYSTEM_NAME STREQUAL darwin) + set(SOURCES WinEventsOSX.mm + WinSystemOSX.mm + WinSystemOSXGL.mm) +diff --git a/xbmc/windowing/osx/WinSystemIOS.h b/xbmc/windowing/osx/WinSystemIOS.h +index 7ecdf67..eda4b7e 100644 +--- a/xbmc/windowing/osx/WinSystemIOS.h ++++ b/xbmc/windowing/osx/WinSystemIOS.h +@@ -24,9 +24,6 @@ + #define WINDOW_SYSTEM_IOSEGL_H + + #if defined(TARGET_DARWIN_IOS) +-#include +-#include +- + #include "windowing/WinSystem.h" + #include "rendering/gles/RenderSystemGLES.h" + #include "utils/GlobalsHandling.h" +diff --git a/xbmc/windowing/osx/WinSystemOSX.h b/xbmc/windowing/osx/WinSystemOSX.h +index 1360fc8..dbc9245 100644 +--- a/xbmc/windowing/osx/WinSystemOSX.h ++++ b/xbmc/windowing/osx/WinSystemOSX.h +@@ -22,9 +22,6 @@ + + #if defined(TARGET_DARWIN_OSX) + +-#include +-#include +- + #include "windowing/WinSystem.h" + #include "threads/CriticalSection.h" + #include "threads/Timer.h" +diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp +index d62abf1..405cb49 100644 +--- a/xbmc/windowing/windows/WinSystemWin32.cpp ++++ b/xbmc/windowing/windows/WinSystemWin32.cpp +@@ -459,7 +459,7 @@ bool CWinSystemWin32::ResizeInternal(bool forceRefresh) + // white frame plus titlebar around the xbmc splash + SetWindowPos(m_hWnd, windowAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW|SWP_DRAWFRAME); + +- //! @todo Probably only need this if switching screens ++ // TODO: Probably only need this if switching screens + ValidateRect(NULL, NULL); + } + return true; +@@ -702,7 +702,7 @@ bool CWinSystemWin32::UpdateResolutionsInternal() + CLog::Log(LOGNOTICE, "Found screen: %s on %s, adapter %d.", monitorStr.c_str(), adapterStr.c_str(), adapter); + + // get information about the display's current position and display mode +- //! @todo for Windows 7/Server 2008 and up, Microsoft recommends QueryDisplayConfig() instead, the API used by the control panel. ++ // TODO: for Windows 7/Server 2008 and up, Microsoft recommends QueryDisplayConfig() instead, the API used by the control panel. + DEVMODEW dm; + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); +diff --git a/xbmc/windowing/windows/WinSystemWin32.h b/xbmc/windowing/windows/WinSystemWin32.h +index 4de378c..59e78f4 100644 +--- a/xbmc/windowing/windows/WinSystemWin32.h ++++ b/xbmc/windowing/windows/WinSystemWin32.h +@@ -26,7 +26,6 @@ + #include "threads/SystemClock.h" + #include "windowing/WinSystem.h" + #include +-#include + + struct MONITOR_DETAILS + { +diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp +index 61d2491..0a4d18c 100644 +--- a/xbmc/windowing/windows/WinSystemWin32DX.cpp ++++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp +@@ -40,7 +40,7 @@ CWinSystemWin32DX::~CWinSystemWin32DX() + + } + +-void CWinSystemWin32DX::PresentRender(bool rendered, bool videoLayer) ++void CWinSystemWin32DX::PresentRender(bool rendered) + { + if (rendered) + PresentRenderImpl(rendered); +diff --git a/xbmc/windowing/windows/WinSystemWin32DX.h b/xbmc/windowing/windows/WinSystemWin32DX.h +index dc32ad2..ca8716a 100644 +--- a/xbmc/windowing/windows/WinSystemWin32DX.h ++++ b/xbmc/windowing/windows/WinSystemWin32DX.h +@@ -42,7 +42,7 @@ public: + virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays); + virtual bool WindowedMode() { return CRenderSystemDX::m_useWindowedDX; } + virtual void NotifyAppFocusChange(bool bGaining); +- virtual void PresentRender(bool rendererd, bool videoLayer); ++ virtual void PresentRender(bool rendererd); + + std::string GetClipboardText(void); + +diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp +index 075d531..08e53a7 100644 +--- a/xbmc/windows/GUIMediaWindow.cpp ++++ b/xbmc/windows/GUIMediaWindow.cpp +@@ -708,10 +708,10 @@ bool CGUIMediaWindow::GetDirectory(const std::string &strDirectory, CFileItemLis + int iWindow = GetID(); + std::vector regexps; + +- //! @todo Do we want to limit the directories we apply the video ones to? ++ // TODO: Do we want to limit the directories we apply the video ones to? + if (iWindow == WINDOW_VIDEO_NAV) + regexps = g_advancedSettings.m_videoExcludeFromListingRegExps; +- if (iWindow == WINDOW_MUSIC_NAV) ++ if (iWindow == WINDOW_MUSIC_FILES || iWindow == WINDOW_MUSIC_NAV) + regexps = g_advancedSettings.m_audioExcludeFromListingRegExps; + if (iWindow == WINDOW_PICTURES) + regexps = g_advancedSettings.m_pictureExcludeFromListingRegExps; +@@ -736,7 +736,7 @@ bool CGUIMediaWindow::GetDirectory(const std::string &strDirectory, CFileItemLis + + bool CGUIMediaWindow::Update(const std::string &strDirectory, bool updateFilterPath /* = true */) + { +- //! @todo OnInitWindow calls Update() before window path has been set properly. ++ // TODO: OnInitWindow calls Update() before window path has been set properly. + if (strDirectory == "?") + return false; + +@@ -789,6 +789,8 @@ bool CGUIMediaWindow::Update(const std::string &strDirectory, bool updateFilterP + { + if (iWindow == WINDOW_PICTURES) + showLabel = 997; ++ else if (iWindow == WINDOW_MUSIC_FILES) ++ showLabel = 998; + else if (iWindow == WINDOW_FILES) + showLabel = 1026; + } +@@ -1073,7 +1075,7 @@ bool CGUIMediaWindow::HaveDiscOrConnection(const std::string& strPath, int iDriv + } + else if (iDriveType==CMediaSource::SOURCE_TYPE_REMOTE) + { +- //! @todo Handle not connected to a remote share ++ // TODO: Handle not connected to a remote share + if ( !g_application.getNetwork().IsConnected() ) + { + CGUIDialogOK::ShowAndGetInput(CVariant{220}, CVariant{221}); +@@ -1623,7 +1625,7 @@ void CGUIMediaWindow::GetContextButtons(int itemNumber, CContextButtons &buttons + if (!item || item->IsParentFolder()) + return; + +- //! @todo FAVOURITES Conditions on masterlock and localisation ++ // TODO: FAVOURITES Conditions on masterlock and localisation + if (!item->IsParentFolder() && !item->IsPath("add") && !item->IsPath("newplaylist://") && + !URIUtils::IsProtocol(item->GetPath(), "newsmartplaylist") && !URIUtils::IsProtocol(item->GetPath(), "newtag") && + !URIUtils::IsProtocol(item->GetPath(), "musicsearch") && +@@ -1674,7 +1676,7 @@ const CFileItemList& CGUIMediaWindow::CurrentDirectory() const + + bool CGUIMediaWindow::WaitForNetwork() const + { +- if (g_application.getNetwork().IsAvailable()) ++ if (g_application.getNetwork().IsConnected()) + return true; + + CGUIDialogProgress *progress = (CGUIDialogProgress *)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); +@@ -1686,7 +1688,7 @@ bool CGUIMediaWindow::WaitForNetwork() const + progress->SetLine(1, CVariant{url.GetWithoutUserDetails()}); + progress->ShowProgressBar(false); + progress->Open(); +- while (!g_application.getNetwork().IsAvailable()) ++ while (!g_application.getNetwork().IsConnected()) + { + progress->Progress(); + if (progress->IsCanceled()) +@@ -1869,11 +1871,11 @@ bool CGUIMediaWindow::GetFilteredItems(const std::string &filter, CFileItemList + filteredItems.Add(item); + continue; + } +- //! @todo Need to update this to get all labels, ideally out of the displayed info (ie from m_layout and m_focusedLayout) +- //! though that isn't practical. Perhaps a better idea would be to just grab the info that we should filter on based on +- //! where we are in the library tree. +- //! Another idea is tying the filter string to the current level of the tree, so that going deeper disables the filter, +- //! but it's re-enabled on the way back out. ++ // TODO: Need to update this to get all labels, ideally out of the displayed info (ie from m_layout and m_focusedLayout) ++ // though that isn't practical. Perhaps a better idea would be to just grab the info that we should filter on based on ++ // where we are in the library tree. ++ // Another idea is tying the filter string to the current level of the tree, so that going deeper disables the filter, ++ // but it's re-enabled on the way back out. + std::string match; + /* if (item->GetFocusedLayout()) + match = item->GetFocusedLayout()->GetAllText(); +diff --git a/xbmc/windows/GUIMediaWindow.h b/xbmc/windows/GUIMediaWindow.h +index b917f31..b1eb511 100644 +--- a/xbmc/windows/GUIMediaWindow.h ++++ b/xbmc/windows/GUIMediaWindow.h +@@ -38,19 +38,19 @@ public: + virtual ~CGUIMediaWindow(void); + + // specializations of CGUIControl +- virtual bool OnAction(const CAction &action) override; +- virtual bool OnBack(int actionID) override; +- virtual bool OnMessage(CGUIMessage& message) override; ++ virtual bool OnAction(const CAction &action); ++ virtual bool OnBack(int actionID); ++ virtual bool OnMessage(CGUIMessage& message); + + // specializations of CGUIWindow +- virtual void OnWindowLoaded() override; +- virtual void OnWindowUnload() override; +- virtual void OnInitWindow() override; +- virtual bool IsMediaWindow() const override { return true; } +- int GetViewContainerID() const override { return m_viewControl.GetCurrentControl(); } +- int GetViewCount() const override { return m_viewControl.GetViewModeCount(); }; +- virtual bool HasListItems() const override { return true; } +- virtual CFileItemPtr GetCurrentListItem(int offset = 0) override; ++ virtual void OnWindowLoaded(); ++ virtual void OnWindowUnload(); ++ virtual void OnInitWindow(); ++ virtual bool IsMediaWindow() const { return true; } ++ int GetViewContainerID() const { return m_viewControl.GetCurrentControl(); } ++ int GetViewCount() const { return m_viewControl.GetViewModeCount(); }; ++ virtual bool HasListItems() const { return true; } ++ virtual CFileItemPtr GetCurrentListItem(int offset = 0); + + // custom methods + virtual bool CanFilterAdvanced() { return m_canFilterAdvanced; } +@@ -64,10 +64,10 @@ public: + + protected: + // specializations of CGUIControlGroup +- virtual CGUIControl *GetFirstFocusableControl(int id) override; ++ virtual CGUIControl *GetFirstFocusableControl(int id); + + // specializations of CGUIWindow +- virtual void LoadAdditionalTags(TiXmlElement *root) override; ++ virtual void LoadAdditionalTags(TiXmlElement *root); + + // custom methods + virtual void SetupShares(); +diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp +index 57a73b7..602c254 100644 +--- a/xbmc/windows/GUIWindowFileManager.cpp ++++ b/xbmc/windows/GUIWindowFileManager.cpp +@@ -41,9 +41,7 @@ + #include "guilib/GUIKeyboardFactory.h" + #include "dialogs/GUIDialogProgress.h" + #include "filesystem/FavouritesDirectory.h" +-#include "PlayListPlayer.h" + #include "playlists/PlayList.h" +-#include "cores/playercorefactory/PlayerCoreFactory.h" + #include "storage/MediaManager.h" + #include "settings/MediaSourceSettings.h" + #include "settings/Settings.h" +@@ -589,7 +587,7 @@ void CGUIWindowFileManager::OnClick(int iList, int iItem) + // UpdateButtons(); + } + +-//! @todo 2.0: Can this be removed, or should we run without the "special" file directories while ++// TODO 2.0: Can this be removed, or should we run without the "special" file directories while + // in filemanager view. + void CGUIWindowFileManager::OnStart(CFileItem *pItem, const std::string &player) + { +@@ -653,7 +651,7 @@ bool CGUIWindowFileManager::HaveDiscOrConnection( std::string& strPath, int iDri + } + else if ( iDriveType == CMediaSource::SOURCE_TYPE_REMOTE ) + { +- //! @todo Handle not connected to a remote share ++ // TODO: Handle not connected to a remote share + if ( !g_application.getNetwork().IsConnected() ) + { + CGUIDialogOK::ShowAndGetInput(CVariant{220}, CVariant{221}); +@@ -881,8 +879,8 @@ bool CGUIWindowFileManager::GetDirectory(int iList, const std::string &strDirect + + bool CGUIWindowFileManager::CanRename(int iList) + { +- //! @todo Renaming of shares (requires writing to sources.xml) +- //! this might be able to be done via the webserver code stuff... ++ // TODO: Renaming of shares (requires writing to sources.xml) ++ // this might be able to be done via the webserver code stuff... + if (m_Directory[iList]->IsVirtualDirectoryRoot()) return false; + if (m_Directory[iList]->IsReadOnly()) return false; + +@@ -892,8 +890,8 @@ bool CGUIWindowFileManager::CanRename(int iList) + bool CGUIWindowFileManager::CanCopy(int iList) + { + // can't copy if the destination is not writeable, or if the source is a share! +- //! @todo Perhaps if the source is removeable media (DVD/CD etc.) we could +- //! put ripping/backup in here. ++ // TODO: Perhaps if the source is removeable media (DVD/CD etc.) we could ++ // put ripping/backup in here. + if (!CUtil::SupportsReadFileOperations(m_Directory[iList]->GetPath())) return false; + if (m_Directory[iList]->IsVirtualDirectoryRoot()) return false; + if (m_Directory[1 - iList]->IsVirtualDirectoryRoot()) return false; +@@ -960,7 +958,7 @@ void CGUIWindowFileManager::OnPopupMenu(int list, int item, bool bContextDriven + if (m_Directory[list]->IsVirtualDirectoryRoot()) + { + if (item < 0) +- { //! @todo We should add the option here for shares to be added if there aren't any ++ { // TODO: We should add the option here for shares to be added if there aren't any + return ; + } + +diff --git a/xbmc/windows/GUIWindowFileManager.h b/xbmc/windows/GUIWindowFileManager.h +index 1f35d2f..36197ad 100644 +--- a/xbmc/windows/GUIWindowFileManager.h ++++ b/xbmc/windows/GUIWindowFileManager.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/GUIWindow.h" + #include "filesystem/VirtualDirectory.h" + #include "filesystem/DirectoryHistory.h" +diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp +index d6d14ff..ca2edb7 100644 +--- a/xbmc/windows/GUIWindowLoginScreen.cpp ++++ b/xbmc/windows/GUIWindowLoginScreen.cpp +@@ -28,7 +28,7 @@ + #include "GUIPassword.h" + #include "addons/AddonManager.h" + #include "addons/Skin.h" +-#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h" ++#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h" + #include "dialogs/GUIDialogContextMenu.h" + #include "dialogs/GUIDialogOK.h" + #include "guilib/GUIMessage.h" +@@ -42,7 +42,6 @@ + #endif + #include "messaging/ApplicationMessenger.h" + #include "network/Network.h" +-#include "PlayListPlayer.h" + #include "profiles/Profile.h" + #include "profiles/ProfilesManager.h" + #include "profiles/dialogs/GUIDialogProfileSettings.h" +diff --git a/xbmc/windows/GUIWindowSystemInfo.cpp b/xbmc/windows/GUIWindowSystemInfo.cpp +index 0cd539e..59b6da7 100644 +--- a/xbmc/windows/GUIWindowSystemInfo.cpp ++++ b/xbmc/windows/GUIWindowSystemInfo.cpp +@@ -100,7 +100,9 @@ void CGUIWindowSystemInfo::FrameMove() + SetControlLabel(i++, "%s %s", 13283, SYSTEM_OS_VERSION_INFO); + SetControlLabel(i++, "%s: %s", 12390, SYSTEM_UPTIME); + SetControlLabel(i++, "%s: %s", 12394, SYSTEM_TOTALUPTIME); ++#if 0 + SetControlLabel(i++, "%s: %s", 12395, SYSTEM_BATTERY_LEVEL); ++#endif + } + + else if (m_section == CONTROL_BT_STORAGE) +diff --git a/xbmc/windows/GUIWindowSystemInfo.h b/xbmc/windows/GUIWindowSystemInfo.h +index 2fed1f5..751995d 100644 +--- a/xbmc/windows/GUIWindowSystemInfo.h ++++ b/xbmc/windows/GUIWindowSystemInfo.h +@@ -20,9 +20,6 @@ + * + */ + +-#include +-#include +- + #include "guilib/GUIWindow.h" + + class CGUIWindowSystemInfo : public CGUIWindow +-- +2.7.1 + diff --git a/projects/imx6/patches/libcec/libcec-00-imx6-support.patch b/projects/imx6/patches/libcec/libcec-00-imx6-support.patch deleted file mode 100644 index 101e535e79..0000000000 --- a/projects/imx6/patches/libcec/libcec-00-imx6-support.patch +++ /dev/null @@ -1,884 +0,0 @@ -From 3bd000096d6c0d9fb84cb5476b4dcae7e12f17df Mon Sep 17 00:00:00 2001 -From: Peter Vicman -Date: Sun, 24 Apr 2016 14:26:55 +0200 -Subject: [PATCH] imx support (rebased again) - -From a7f3315333c1a79259a763c6542a6cd71855b357 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Thu, 7 May 2015 11:35:04 +0300 -Subject: [PATCH] imx support - -note. I am NOT the author of the patch. just rebased it ---- - include/cectypes.h | 14 +- - src/libcec/CECTypeUtils.h | 2 + - src/libcec/adapter/AdapterFactory.cpp | 29 +- - src/libcec/adapter/IMX/AdapterMessageQueue.h | 134 +++++++++ - .../adapter/IMX/IMXCECAdapterCommunication.cpp | 328 +++++++++++++++++++++ - .../adapter/IMX/IMXCECAdapterCommunication.h | 119 ++++++++ - src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp | 42 +++ - src/libcec/adapter/IMX/IMXCECAdapterDetection.h | 36 +++ - src/libcec/cmake/CheckPlatformSupport.cmake | 10 + - src/libcec/cmake/DisplayPlatformSupport.cmake | 6 + - src/libcec/env.h.in | 3 + - 11 files changed, 720 insertions(+), 3 deletions(-) - create mode 100644 src/libcec/adapter/IMX/AdapterMessageQueue.h - create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp - create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.h - create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp - create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.h - -diff --git a/include/cectypes.h b/include/cectypes.h -index 0fdd48e..e28c8df 100644 ---- a/include/cectypes.h -+++ b/include/cectypes.h -@@ -309,6 +309,17 @@ namespace CEC { - #define CEC_EXYNOS_VIRTUAL_COM "Exynos" - - /*! -+ * the path to use for the i.MX CEC wire -+ */ -+#define CEC_IMX_PATH "/dev/mxc_hdmi_cec" -+ -+/*! -+ * the name of the virtual COM port to use for the i.MX CEC wire -+ */ -+#define CEC_IMX_VIRTUAL_COM "i.MX" -+ -+ -+/*! - * Mimimum client version - */ - #define CEC_MIN_LIB_VERSION 3 -@@ -877,7 +888,8 @@ typedef enum cec_adapter_type - ADAPTERTYPE_P8_DAUGHTERBOARD = 0x2, - ADAPTERTYPE_RPI = 0x100, - ADAPTERTYPE_TDA995x = 0x200, -- ADAPTERTYPE_EXYNOS = 0x300 -+ ADAPTERTYPE_EXYNOS = 0x300, -+ ADAPTERTYPE_IMX = 0x400 - } cec_adapter_type; - - /** force exporting through swig */ -diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h -index 0d0cf17..f6c818a 100644 ---- a/src/libcec/CECTypeUtils.h -+++ b/src/libcec/CECTypeUtils.h -@@ -766,6 +766,8 @@ namespace CEC - return "Raspberry Pi"; - case ADAPTERTYPE_TDA995x: - return "TDA995x"; -+ case ADAPTERTYPE_IMX: -+ return "i.MX"; - default: - return "unknown"; - } -diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp -index da05725..92e378b 100644 ---- a/src/libcec/adapter/AdapterFactory.cpp -+++ b/src/libcec/adapter/AdapterFactory.cpp -@@ -58,6 +58,11 @@ - #include "Exynos/ExynosCECAdapterCommunication.h" - #endif - -+#if defined(HAVE_IMX_API) -+#include "IMX/IMXCECAdapterDetection.h" -+#include "IMX/IMXCECAdapterCommunication.h" -+#endif -+ - using namespace CEC; - - int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */) -@@ -127,7 +132,22 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 - #endif - - --#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) -+ -+#if defined(HAVE_IMX_API) -+ if (iAdaptersFound < iBufSize && CIMXCECAdapterDetection::FindAdapter() && -+ (!strDevicePath || !strcmp(strDevicePath, CEC_IMX_VIRTUAL_COM))) -+ { -+ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_IMX_PATH); -+ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_IMX_VIRTUAL_COM); -+ deviceList[iAdaptersFound].iVendorId = IMX_ADAPTER_VID; -+ deviceList[iAdaptersFound].iProductId = IMX_ADAPTER_PID; -+ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_IMX; -+ iAdaptersFound++; -+ } -+#endif -+ -+ -+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API) - #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" - #endif - -@@ -151,11 +171,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ - return new CRPiCECAdapterCommunication(m_lib->m_cec); - #endif - -+#if defined(HAVE_IMX_API) -+ if (!strcmp(strPort, CEC_IMX_VIRTUAL_COM)) -+ return new CIMXCECAdapterCommunication(m_lib->m_cec); -+#endif -+ - #if defined(HAVE_P8_USB) - return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); - #endif - --#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) -+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) - return NULL; - #endif - } -diff --git a/src/libcec/adapter/IMX/AdapterMessageQueue.h b/src/libcec/adapter/IMX/AdapterMessageQueue.h -new file mode 100644 -index 0000000..7749874 ---- /dev/null -+++ b/src/libcec/adapter/IMX/AdapterMessageQueue.h -@@ -0,0 +1,134 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * This program is dual-licensed; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ * Alternatively, you can license this library under a commercial license, -+ * please contact Pulse-Eight Licensing for more information. -+ * -+ * For more information contact: -+ * Pulse-Eight Licensing -+ * http://www.pulse-eight.com/ -+ * http://www.pulse-eight.net/ -+ */ -+ -+#include "p8-platform/threads/mutex.h" -+ -+namespace CEC -+{ -+ using namespace P8PLATFORM; -+ -+ class CAdapterMessageQueueEntry -+ { -+ public: -+ CAdapterMessageQueueEntry(const cec_command &command) -+ : m_bWaiting(true), m_retval((uint32_t)-1), m_bSucceeded(false) -+ { -+ m_hash = hashValue( -+ uint32_t(command.opcode_set ? command.opcode : CEC_OPCODE_NONE), -+ command.initiator, command.destination); -+ } -+ -+ virtual ~CAdapterMessageQueueEntry(void) {} -+ -+ /*! -+ * @brief Query result from worker thread -+ */ -+ uint32_t Result() const -+ { -+ return m_retval; -+ } -+ -+ /*! -+ * @brief Signal waiting threads -+ */ -+ void Broadcast(void) -+ { -+ CLockObject lock(m_mutex); -+ m_condition.Broadcast(); -+ } -+ -+ /*! -+ * @brief Signal waiting thread(s) when message matches this entry -+ */ -+ bool CheckMatch(uint32_t opcode, cec_logical_address initiator, -+ cec_logical_address destination, uint32_t response) -+ { -+ uint32_t hash = hashValue(opcode, initiator, destination); -+ -+ if (hash == m_hash) -+ { -+ CLockObject lock(m_mutex); -+ -+ m_retval = response; -+ m_bSucceeded = true; -+ m_condition.Signal(); -+ return true; -+ } -+ -+ return false; -+ } -+ -+ /*! -+ * @brief Wait for a response to this command. -+ * @param iTimeout The timeout to use while waiting. -+ * @return True when a response was received before the timeout passed, false otherwise. -+ */ -+ bool Wait(uint32_t iTimeout) -+ { -+ CLockObject lock(m_mutex); -+ -+ bool bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout); -+ m_bWaiting = false; -+ return bReturn; -+ } -+ -+ /*! -+ * @return True while a thread is waiting for a signal or isn't waiting yet, false otherwise. -+ */ -+ bool IsWaiting(void) -+ { -+ CLockObject lock(m_mutex); -+ return m_bWaiting; -+ } -+ -+ /*! -+ * @return Hash value for given cec_command -+ */ -+ static uint32_t hashValue(uint32_t opcode, -+ cec_logical_address initiator, -+ cec_logical_address destination) -+ { -+ return 1 | ((uint32_t)initiator << 8) | -+ ((uint32_t)destination << 16) | ((uint32_t)opcode << 16); -+ } -+ -+ private: -+ bool m_bWaiting; /**< true while a thread is waiting or when it hasn't started waiting yet */ -+ P8PLATFORM::CCondition m_condition; /**< the condition to wait on */ -+ P8PLATFORM::CMutex m_mutex; /**< mutex for changes to this class */ -+ uint32_t m_hash; -+ uint32_t m_retval; -+ bool m_bSucceeded; -+ }; -+ -+}; -diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp -new file mode 100644 -index 0000000..ba88137 ---- /dev/null -+++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp -@@ -0,0 +1,328 @@ -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin -+ * -+ * You can redistribute this file and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ */ -+ -+#include "env.h" -+ -+#if defined(HAVE_IMX_API) -+#include "IMXCECAdapterCommunication.h" -+ -+#include "CECTypeUtils.h" -+#include "LibCEC.h" -+#include "p8-platform/sockets/cdevsocket.h" -+#include "p8-platform/util/StdString.h" -+#include "p8-platform/util/buffer.h" -+ -+/* -+ * Ioctl definitions from kernel header -+ */ -+#define HDMICEC_IOC_MAGIC 'H' -+#define HDMICEC_IOC_SETLOGICALADDRESS _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char) -+#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2) -+#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3) -+#define HDMICEC_IOC_GETPHYADDRESS _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]) -+ -+#define MAX_CEC_MESSAGE_LEN 17 -+ -+#define MESSAGE_TYPE_RECEIVE_SUCCESS 1 -+#define MESSAGE_TYPE_NOACK 2 -+#define MESSAGE_TYPE_DISCONNECTED 3 -+#define MESSAGE_TYPE_CONNECTED 4 -+#define MESSAGE_TYPE_SEND_SUCCESS 5 -+ -+typedef struct hdmi_cec_event{ -+ int event_type; -+ int msg_len; -+ unsigned char msg[MAX_CEC_MESSAGE_LEN]; -+}hdmi_cec_event; -+ -+ -+using namespace std; -+using namespace CEC; -+using namespace P8PLATFORM; -+ -+#include "AdapterMessageQueue.h" -+ -+#define LIB_CEC m_callback->GetLib() -+ -+// these are defined in nxp private header file -+#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/ -+#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/ -+#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/ -+#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/ -+#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/ -+#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/ -+#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/ -+#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/ -+ -+ -+CIMXCECAdapterCommunication::CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback) : -+ IAdapterCommunication(callback)/*, -+ m_bLogicalAddressChanged(false)*/ -+{ -+ CLockObject lock(m_mutex); -+ -+ m_iNextMessage = 0; -+ //m_logicalAddresses.Clear(); -+ m_logicalAddress = CECDEVICE_UNKNOWN; -+ m_bLogicalAddressRegistered = false; -+ m_bInitialised = false; -+ m_dev = new CCDevSocket(CEC_IMX_PATH); -+} -+ -+CIMXCECAdapterCommunication::~CIMXCECAdapterCommunication(void) -+{ -+ Close(); -+ -+ CLockObject lock(m_mutex); -+ delete m_dev; -+ m_dev = 0; -+} -+ -+bool CIMXCECAdapterCommunication::IsOpen(void) -+{ -+ return IsInitialised() && m_dev->IsOpen(); -+} -+ -+bool CIMXCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening) -+{ -+ if (m_dev->Open(iTimeoutMs)) -+ { -+ if (!bStartListening || CreateThread()) { -+ if (m_dev->Ioctl(HDMICEC_IOC_STARTDEVICE, NULL) == 0) { -+ m_bInitialised = true; -+ return true; -+ } -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to start device\n", __func__); -+ } -+ m_dev->Close(); -+ } -+ -+ return false; -+} -+ -+ -+void CIMXCECAdapterCommunication::Close(void) -+{ -+ StopThread(0); -+ -+ CLockObject lock(m_mutex); -+ if (!m_bInitialised) { -+ return; -+ } -+ if (m_dev->Ioctl(HDMICEC_IOC_STOPDEVICE, NULL) != 0) { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to stop device\n", __func__); -+ } -+ m_dev->Close(); -+ m_bInitialised = false; -+} -+ -+ -+std::string CIMXCECAdapterCommunication::GetError(void) const -+{ -+ std::string strError(m_strError); -+ return strError; -+} -+ -+ -+cec_adapter_message_state CIMXCECAdapterCommunication::Write( -+ const cec_command &data, bool &UNUSED(bRetry), uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) -+{ -+ //cec_frame frame; -+ unsigned char message[MAX_CEC_MESSAGE_LEN]; -+ int msg_len = 1; -+ cec_adapter_message_state rc = ADAPTER_MESSAGE_STATE_ERROR; -+ -+ if ((size_t)data.parameters.size + data.opcode_set + 1 > sizeof(message)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: data size too large !", __func__); -+ return ADAPTER_MESSAGE_STATE_ERROR; -+ } -+ -+ message[0] = (data.initiator << 4) | (data.destination & 0x0f); -+ if (data.opcode_set) -+ { -+ message[1] = data.opcode; -+ msg_len++; -+ memcpy(&message[2], data.parameters.data, data.parameters.size); -+ msg_len+=data.parameters.size; -+ } -+ -+ if (m_dev->Write(message, msg_len) == msg_len) -+ { -+ rc = ADAPTER_MESSAGE_STATE_SENT_ACKED; -+ } -+ else -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: sent command error !", __func__); -+ -+ return rc; -+} -+ -+ -+uint16_t CIMXCECAdapterCommunication::GetFirmwareVersion(void) -+{ -+ /* FIXME add ioctl ? */ -+ return 0; -+} -+ -+ -+cec_vendor_id CIMXCECAdapterCommunication::GetVendorId(void) -+{ -+ return CEC_VENDOR_UNKNOWN; -+} -+ -+ -+uint16_t CIMXCECAdapterCommunication::GetPhysicalAddress(void) -+{ -+ uint32_t info; -+ uint16_t phy_addr; -+ -+ if (m_dev->Ioctl(HDMICEC_IOC_GETPHYADDRESS, &info) != 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_GETPHYADDRESS failed !", __func__); -+ return CEC_INVALID_PHYSICAL_ADDRESS; -+ } -+ /* Rebuild 16 bit raw value from fsl 32 bits value */ -+ phy_addr = ((info & 0x0f) << 12) | (info & 0x0f00) | -+ ((info & 0x0f0000) >> 12) | ((info & 0x0f000000) >> 24); -+ -+ return phy_addr; -+} -+ -+ -+cec_logical_addresses CIMXCECAdapterCommunication::GetLogicalAddresses(void) -+{ -+ cec_logical_addresses addresses; -+ addresses.Clear(); -+ -+ CLockObject lock(m_mutex); -+ if ((m_logicalAddress & (CECDEVICE_UNKNOWN | CECDEVICE_UNREGISTERED)) == 0) -+ addresses.Set(m_logicalAddress); -+ -+ return addresses; -+} -+ -+void CIMXCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) -+{ -+ UnregisterLogicalAddress(); -+} -+ -+bool CIMXCECAdapterCommunication::UnregisterLogicalAddress(void) -+{ -+ CLockObject lock(m_mutex); -+ if (!m_bLogicalAddressRegistered) -+ return true; -+ -+ if (m_dev->Ioctl(HDMICEC_IOC_SETLOGICALADDRESS, (void *)CECDEVICE_BROADCAST) != 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_SETLOGICALADDRESS failed !", __func__); -+ return false; -+ } -+ -+ m_logicalAddress = CECDEVICE_UNKNOWN; -+ m_bLogicalAddressRegistered = false; -+ return true; -+} -+ -+bool CIMXCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address) -+{ -+ CLockObject lock(m_mutex); -+ -+ if (m_logicalAddress == address && m_bLogicalAddressRegistered) -+ { -+ return true; -+ } -+ -+ if (m_dev->Ioctl(HDMICEC_IOC_SETLOGICALADDRESS, (void *)address) != 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_SETLOGICALADDRESS failed !", __func__); -+ return false; -+ } -+ -+ m_logicalAddress = address; -+ m_bLogicalAddressRegistered = true; -+ return true; -+} -+ -+bool CIMXCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) -+{ -+ int log_addr = addresses.primary; -+ -+ return RegisterLogicalAddress((cec_logical_address)log_addr); -+} -+ -+void *CIMXCECAdapterCommunication::Process(void) -+{ -+ bool bHandled; -+ hdmi_cec_event event; -+ int ret; -+ -+ uint32_t opcode, status; -+ cec_logical_address initiator, destination; -+ -+ while (!IsStopped()) -+ { -+ ret = m_dev->Read((char *)&event, sizeof(event), 5000); -+ if (ret > 0) -+ { -+ -+ initiator = cec_logical_address(event.msg[0] >> 4); -+ destination = cec_logical_address(event.msg[0] & 0x0f); -+ -+ //LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: Read data : type : %d initiator %d dest %d", __func__, event.event_type, initiator, destination); -+ if (event.event_type == MESSAGE_TYPE_RECEIVE_SUCCESS) -+ /* Message received */ -+ { -+ cec_command cmd; -+ -+ cec_command::Format( -+ cmd, initiator, destination, -+ ( event.msg_len > 1 ) ? cec_opcode(event.msg[1]) : CEC_OPCODE_NONE); -+ -+ for( uint8_t i = 2; i < event.msg_len; i++ ) -+ cmd.parameters.PushBack(event.msg[i]); -+ -+ if (!IsStopped()) -+ m_callback->OnCommandReceived(cmd); -+ } -+ -+ if (event.event_type == MESSAGE_TYPE_CONNECTED) -+ /* HDMI has just been reconnected - Notify phy address*/ -+ { -+ uint16_t iNewAddress = GetPhysicalAddress(); -+ m_callback->HandlePhysicalAddressChanged(iNewAddress); -+ } -+ /* We are not interested in other events */ -+ } /*else { -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: Read returned %d", __func__, ret); -+ }*/ -+ -+ } -+ -+ return 0; -+} -+ -+#endif // HAVE_IMX_API -diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h -new file mode 100644 -index 0000000..cebe5b6 ---- /dev/null -+++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h -@@ -0,0 +1,119 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin -+ * -+ * You can redistribute this file and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ */ -+ -+#if defined(HAVE_IMX_API) -+ -+#include "p8-platform/threads/mutex.h" -+#include "p8-platform/threads/threads.h" -+#include "p8-platform/sockets/socket.h" -+#include "adapter/AdapterCommunication.h" -+#include -+ -+#define IMX_ADAPTER_VID 0x0471 /*FIXME TBD*/ -+#define IMX_ADAPTER_PID 0x1001 -+ -+ -+ -+namespace P8PLATFORM -+{ -+ class CCDevSocket; -+}; -+ -+ -+namespace CEC -+{ -+ class CAdapterMessageQueueEntry; -+ -+ class CIMXCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread -+ { -+ public: -+ /*! -+ * @brief Create a new USB-CEC communication handler. -+ * @param callback The callback to use for incoming CEC commands. -+ */ -+ CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback); -+ virtual ~CIMXCECAdapterCommunication(void); -+ -+ /** @name IAdapterCommunication implementation */ -+ ///{ -+ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true); -+ void Close(void); -+ bool IsOpen(void); -+ std::string GetError(void) const; -+ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply); -+ -+ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) { return true; } -+ bool StartBootloader(void) { return false; } -+ bool SetLogicalAddresses(const cec_logical_addresses &addresses); -+ cec_logical_addresses GetLogicalAddresses(void); -+ bool PingAdapter(void) { return IsInitialised(); } -+ uint16_t GetFirmwareVersion(void); -+ uint32_t GetFirmwareBuildDate(void) { return 0; } -+ bool IsRunningLatestFirmware(void) { return true; } -+ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } -+ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } -+ std::string GetPortName(void) { return std::string("IMX"); } -+ uint16_t GetPhysicalAddress(void); -+ bool SetControlledMode(bool UNUSED(controlled)) { return true; } -+ cec_vendor_id GetVendorId(void); -+ bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } -+ cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_IMX; } -+ uint16_t GetAdapterVendorId(void) const { return IMX_ADAPTER_VID; } -+ uint16_t GetAdapterProductId(void) const { return IMX_ADAPTER_PID; } -+ void HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)); -+ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {} -+ bool RegisterLogicalAddress(const cec_logical_address address); -+ ///} -+ -+ /** @name P8PLATFORM::CThread implementation */ -+ ///{ -+ void *Process(void); -+ ///} -+ -+ private: -+ bool IsInitialised(void) const { return m_bInitialised; }; -+ bool UnregisterLogicalAddress(void); -+ -+ std::string m_strError; /**< current error message */ -+ -+ //cec_logical_addresses m_logicalAddresses; -+ cec_logical_address m_logicalAddress; -+ -+ P8PLATFORM::CMutex m_mutex; -+ P8PLATFORM::CCDevSocket *m_dev; /**< the device connection */ -+ bool m_bLogicalAddressRegistered; -+ bool m_bInitialised; -+ -+ P8PLATFORM::CMutex m_messageMutex; -+ uint32_t m_iNextMessage; -+ std::map m_messages; -+ }; -+ -+}; -+ -+#endif -diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp -new file mode 100644 -index 0000000..6c93c45 ---- /dev/null -+++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp -@@ -0,0 +1,42 @@ -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin -+ * -+ * You can redistribute this file and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ */ -+ -+#include "env.h" -+#include -+ -+#if defined(HAVE_IMX_API) -+#include "IMXCECAdapterDetection.h" -+ -+ -+using namespace CEC; -+ -+bool CIMXCECAdapterDetection::FindAdapter(void) -+{ -+ return access(CEC_IMX_PATH, 0) == 0; -+} -+ -+#endif -diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.h b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h -new file mode 100644 -index 0000000..d54891d ---- /dev/null -+++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h -@@ -0,0 +1,36 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin -+ * -+ * You can redistribute this file and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ */ -+ -+namespace CEC -+{ -+ class CIMXCECAdapterDetection -+ { -+ public: -+ static bool FindAdapter(void); -+ }; -+} -diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake -index b8a16c8..dc5bc25 100644 ---- a/src/libcec/cmake/CheckPlatformSupport.cmake -+++ b/src/libcec/cmake/CheckPlatformSupport.cmake -@@ -7,6 +7,7 @@ - # HAVE_RANDR 1 if xrandr is supported - # HAVE_LIBUDEV 1 if udev is supported - # HAVE_RPI_API 1 if Raspberry Pi is supported -+# HAVE_IMX_API 1 if i.MX is supported - # HAVE_TDA995X_API 1 if TDA995X is supported - # HAVE_EXYNOS_API 1 if Exynos is supported - # HAVE_P8_USB 1 if Pulse-Eight devices are supported -@@ -110,6 +111,15 @@ else() - list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_RPI}) - endif() - -+ # i.MX -+ if (HAVE_IMX_API) -+ set(LIB_INFO "${LIB_INFO}, 'IMX'") -+ set(CEC_SOURCES_ADAPTER_IMX adapter/IMX/IMXCECAdapterDetection.cpp -+ adapter/IMX/IMXCECAdapterCommunication.cpp) -+ source_group("Source Files\\adapter\\IMX" FILES ${CEC_SOURCES_ADAPTER_IMX}) -+ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_IMX}) -+ endif() -+ - # TDA995x - check_include_files("tda998x_ioctl.h;comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h" HAVE_TDA995X_API) - if (HAVE_TDA995X_API) -diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake -index 9dcaacf..4e24def 100644 ---- a/src/libcec/cmake/DisplayPlatformSupport.cmake -+++ b/src/libcec/cmake/DisplayPlatformSupport.cmake -@@ -26,6 +26,12 @@ else() - message(STATUS "Raspberry Pi support: no") - endif() - -+if (HAVE_IMX_API) -+ message(STATUS "i.MX support: yes") -+else() -+ message(STATUS "i.MX support: no") -+endif() -+ - if (HAVE_TDA995X_API) - message(STATUS "TDA995x support: yes") - else() -diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in -index 0496aa0..384f1c7 100644 ---- a/src/libcec/env.h.in -+++ b/src/libcec/env.h.in -@@ -66,6 +66,9 @@ - /* Define to 1 for Raspberry Pi support */ - #cmakedefine HAVE_RPI_API @HAVE_RPI_API@ - -+/* Define to 1 for IMX support */ -+#cmakedefine HAVE_IMX_API @HAVE_IMX_API@ -+ - /* Define to 1 for TDA995x support */ - #cmakedefine HAVE_TDA995X_API @HAVE_TDA995X_API@ - --- -2.7.1 - diff --git a/projects/imx6/patches/libcec/libcec-100-from-xbian.patch b/projects/imx6/patches/libcec/libcec-100-from-xbian.patch new file mode 100644 index 0000000000..fd30a83749 --- /dev/null +++ b/projects/imx6/patches/libcec/libcec-100-from-xbian.patch @@ -0,0 +1,1749 @@ +From c7b9650dd936976ce150cf0b8233bacc1613c983 Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Sun, 10 Jul 2016 13:46:01 +0200 +Subject: [PATCH] patch for libcec from xbian + +libcec base: libcec-6d68d21 +libcec xbian: + https://github.com/xbianonpi/xbian-sources-libcec/tree/masterv3 2d231e5781a808cc7bcfaf65a69387e841c47652 +--- + debian/control | 5 +- + debian/libcec-dev.install | 1 + + debian/libcec3.install | 2 + + include/cec.h | 2 + + include/cectypes.h | 47 ++- + src/cec-client/CMakeLists.txt | 4 +- + src/cecc-client/cecc-client.c | 2 +- + src/libcec/CECClient.cpp | 12 +- + src/libcec/CECClient.h | 1 + + src/libcec/CECProcessor.cpp | 6 + + src/libcec/CECProcessor.h | 1 + + src/libcec/CECTypeUtils.h | 2 + + src/libcec/CMakeLists.txt | 22 +- + src/libcec/LibCEC.cpp | 5 + + src/libcec/LibCEC.h | 1 + + src/libcec/adapter/AdapterFactory.cpp | 27 +- + .../adapter/IMX/IMXCECAdapterCommunication.cpp | 381 +++++++++++++++++++++ + .../adapter/IMX/IMXCECAdapterCommunication.h | 139 ++++++++ + src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp | 42 +++ + src/libcec/adapter/IMX/IMXCECAdapterDetection.h | 36 ++ + src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h | 118 +++++++ + src/libcec/adapter/IMX/mxc_hdmi-cec.h | 47 +++ + src/libcec/cmake/CheckPlatformSupport.cmake | 47 ++- + src/libcec/cmake/DisplayPlatformSupport.cmake | 6 + + src/libcec/cmake/LinkPlatformSupport.cmake | 7 +- + src/libcec/devices/CECBusDevice.cpp | 28 +- + src/libcec/devices/CECBusDevice.h | 2 + + src/libcec/env.h.in | 3 + + src/libcec/implementations/CECCommandHandler.cpp | 16 +- + src/libcec/implementations/CECCommandHandler.h | 6 +- + src/libcec/implementations/GRCommandHandler.cpp | 93 +++++ + src/libcec/implementations/GRCommandHandler.h | 53 +++ + support/git-rev.sh | 2 +- + 33 files changed, 1096 insertions(+), 70 deletions(-) + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.h + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.h + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h + create mode 100644 src/libcec/adapter/IMX/mxc_hdmi-cec.h + create mode 100644 src/libcec/implementations/GRCommandHandler.cpp + create mode 100644 src/libcec/implementations/GRCommandHandler.h + +diff --git a/debian/control b/debian/control +index e9335ef..c9fa004 100644 +--- a/debian/control ++++ b/debian/control +@@ -43,6 +43,7 @@ Description: libCEC communication Library (shared library) + Package: cec-utils + Architecture: any + Section: utils ++Replaces: xbian-package-cec + Depends: libcec3 (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +@@ -63,6 +64,8 @@ Description: Python bindings for libCEC + + Package: libcec + Architecture: any +-Depends: ${shlibs:Depends}, ${misc:Depends}, libcec3 (= ${binary:Version}) ++Depends: ${shlibs:Depends}, ${misc:Depends}, libcec3 (= ${binary:Version}), python-libcec, cec-utils, libcec-dev ++Provides: xbian-package-cec ++Breaks: xbian-package-cec (<<10.0) + Description: Meta package libCEC. + +diff --git a/debian/libcec-dev.install b/debian/libcec-dev.install +index e5bbd96..15a3585 100644 +--- a/debian/libcec-dev.install ++++ b/debian/libcec-dev.install +@@ -1,3 +1,4 @@ + usr/include + usr/lib/pkgconfig + usr/lib/*/*.so ++usr/lib/p8-platform +diff --git a/debian/libcec3.install b/debian/libcec3.install +index ca5ebe3..ac5e50a 100644 +--- a/debian/libcec3.install ++++ b/debian/libcec3.install +@@ -1 +1,3 @@ + usr/lib/*/libcec.so.* ++usr/lib/libp*.a ++ +diff --git a/include/cec.h b/include/cec.h +index c5dc713..ea1454e 100644 +--- a/include/cec.h ++++ b/include/cec.h +@@ -408,6 +408,8 @@ namespace CEC + */ + virtual uint16_t GetAdapterProductId(void) const = 0; + ++ virtual bool TransmitSystemAudioModeRequest(void) = 0; ++ + virtual const char* ToString(const cec_menu_state state) = 0; + virtual const char* ToString(const cec_version version) = 0; + virtual const char* ToString(const cec_power_status status) = 0; +diff --git a/include/cectypes.h b/include/cectypes.h +index 0fdd48e..403c10b 100644 +--- a/include/cectypes.h ++++ b/include/cectypes.h +@@ -299,9 +299,19 @@ namespace CEC { + #define CEC_TDA995x_VIRTUAL_COM "CuBox" + + /*! ++ * the path to use for the i.MX CEC wire ++ */ ++#define CEC_IMX_PATH "/dev/mxc_hdmi_cec" ++ ++/*! ++ * the name of the virtual COM port to use for the i.MX CEC wire ++ */ ++#define CEC_IMX_VIRTUAL_COM "i.MX" ++ ++/*! + * the path to use for the Exynos HDMI CEC device + */ +-#define CEC_EXYNOS_PATH "/dev/CEC" ++#define CEC_EXYNOS_PATH "/dev/CEC" + + /*! + * the name of the virtual COM port to use for the EXYNOS' CEC wire +@@ -877,7 +887,8 @@ typedef enum cec_adapter_type + ADAPTERTYPE_P8_DAUGHTERBOARD = 0x2, + ADAPTERTYPE_RPI = 0x100, + ADAPTERTYPE_TDA995x = 0x200, +- ADAPTERTYPE_EXYNOS = 0x300 ++ ADAPTERTYPE_EXYNOS = 0x300, ++ ADAPTERTYPE_IMX = 0x400 + } cec_adapter_type; + + /** force exporting through swig */ +@@ -1262,7 +1273,7 @@ typedef struct cec_device_type_list + typedef struct cec_logical_addresses + { + cec_logical_address primary; /**< the primary logical address to use */ +- int addresses[16]; /**< the list of addresses */ ++ uint16_t addresses; /**< the list of addresses */ + + #ifdef __cplusplus + /*! +@@ -1271,8 +1282,7 @@ typedef struct cec_logical_addresses + void Clear(void) + { + primary = CECDEVICE_UNREGISTERED; +- for (unsigned int iPtr = 0; iPtr < 16; iPtr++) +- addresses[iPtr] = 0; ++ addresses = 0; + } + + /*! +@@ -1280,7 +1290,7 @@ typedef struct cec_logical_addresses + */ + bool IsEmpty(void) const + { +- return primary == CECDEVICE_UNREGISTERED; ++ return primary == CECDEVICE_UNREGISTERED && addresses == 0; + } + + /*! +@@ -1289,11 +1299,7 @@ typedef struct cec_logical_addresses + */ + uint16_t AckMask(void) const + { +- uint16_t mask = 0; +- for (unsigned int iPtr = 0; iPtr < 16; iPtr++) +- if (addresses[iPtr] == 1) +- mask |= 0x1 << iPtr; +- return mask; ++ return addresses; + } + + /*! +@@ -1305,7 +1311,7 @@ typedef struct cec_logical_addresses + if (primary == CECDEVICE_UNREGISTERED) + primary = address; + +- addresses[(int) address] = 1; ++ addresses |= (1 << (int) address); + } + + /*! +@@ -1317,7 +1323,7 @@ typedef struct cec_logical_addresses + if (primary == address) + primary = CECDEVICE_UNREGISTERED; + +- addresses[(int) address] = 0; ++ addresses &= ~(uint16_t)(1 << (int) address); + } + + /*! +@@ -1325,7 +1331,7 @@ typedef struct cec_logical_addresses + * @param address The address to check. + * @return True when set, false otherwise. + */ +- bool IsSet(cec_logical_address address) const { return addresses[(int) address] == 1; } ++ bool IsSet(cec_logical_address address) const { return (addresses & (1 << (int) address)); } + + /*! + * @brief Check whether an address is set in this list. +@@ -1334,18 +1340,9 @@ typedef struct cec_logical_addresses + */ + bool operator[](uint8_t pos) const { return pos < 16 ? IsSet((cec_logical_address) pos) : false; } + +- bool operator==(const cec_logical_addresses &other) const +- { +- bool bEqual(true); +- for (uint8_t iPtr = 0; iPtr < 16; iPtr++) +- bEqual &= ((addresses[(int)iPtr] == 1) == other[iPtr]); +- return bEqual; +- } ++ bool operator==(const cec_logical_addresses &other) const { return addresses == other.addresses; } + +- bool operator!=(const cec_logical_addresses &other) const +- { +- return !(*this == other); +- } ++ bool operator!=(const cec_logical_addresses &other) const { return !(*this == other); } + #endif + } cec_logical_addresses; + +diff --git a/src/cec-client/CMakeLists.txt b/src/cec-client/CMakeLists.txt +index 2cb42bb..c708fdb 100644 +--- a/src/cec-client/CMakeLists.txt ++++ b/src/cec-client/CMakeLists.txt +@@ -13,9 +13,9 @@ include(CheckLibraryExists) + include(CheckIncludeFiles) + include(CheckCXXCompilerFlag) + +-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11) ++check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11) + if (SUPPORTS_CXX11) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + + find_package(p8-platform REQUIRED) +diff --git a/src/cecc-client/cecc-client.c b/src/cecc-client/cecc-client.c +index b912118..f5eef85 100644 +--- a/src/cecc-client/cecc-client.c ++++ b/src/cecc-client/cecc-client.c +@@ -332,7 +332,7 @@ static int cec_process_command_scan(const char* data) + activeSource = g_iface.get_active_source(g_iface.connection); + for (iPtr = 0; iPtr < 16; iPtr++) + { +- if (addresses.addresses[iPtr]) ++ if (addresses.addresses & (1 << iPtr)) + { + cec_menu_language lang; + uint64_t iVendorId = g_iface.get_device_vendor_id(g_iface.connection, (cec_logical_address)iPtr); +diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp +index 91e97cb..e7cdf87 100644 +--- a/src/libcec/CECClient.cpp ++++ b/src/libcec/CECClient.cpp +@@ -139,10 +139,6 @@ bool CCECClient::OnRegister(void) + // set the physical address + SetPhysicalAddress(m_configuration); + +- // make the primary device the active source if the option is set +- if (m_configuration.bActivateSource == 1) +- GetPrimaryDevice()->ActivateSource(500); +- + return true; + } + +@@ -348,12 +344,13 @@ bool CCECClient::AllocateLogicalAddresses(void) + if (address == CECDEVICE_UNKNOWN) + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - failed to allocate device '%d', type '%s'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr])); +- return false; ++ continue; + } + + // display the registered LA + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - device '%d', type '%s', LA '%X'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr]), address); + m_configuration.logicalAddresses.Set(address); ++ break; + } + + // persist the new configuration +@@ -1559,6 +1556,11 @@ bool CCECClient::IsLibCECActiveSource(void) + return bReturn; + } + ++bool CCECClient::TransmitSystemAudioModeRequest(void) ++{ ++ return m_processor ? m_processor->TransmitSystemAudioModeRequest(m_configuration.logicalAddresses.primary) : false; ++} ++ + void CCECClient::SourceActivated(const cec_logical_address logicalAddress) + { + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress); +diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h +index badd2eb..0d585bf 100644 +--- a/src/libcec/CECClient.h ++++ b/src/libcec/CECClient.h +@@ -289,6 +289,7 @@ namespace CEC + virtual cec_logical_addresses GetLogicalAddresses(void); + virtual void RescanActiveDevices(void); + virtual bool IsLibCECActiveSource(void); ++ virtual bool TransmitSystemAudioModeRequest(void); + + // configuration + virtual bool GetCurrentConfiguration(libcec_configuration &configuration); +diff --git a/src/libcec/CECProcessor.cpp b/src/libcec/CECProcessor.cpp +index 5c11209..25a86ab 100644 +--- a/src/libcec/CECProcessor.cpp ++++ b/src/libcec/CECProcessor.cpp +@@ -709,6 +709,12 @@ bool CCECProcessor::TransmitPendingActiveSourceCommands(void) + return bReturn; + } + ++bool CCECProcessor::TransmitSystemAudioModeRequest(cec_logical_address initiator) ++{ ++ CCECBusDevice *device = m_busDevices->At(initiator); ++ return device && device->TransmitSystemAudioModeRequest(initiator); ++} ++ + CCECTV *CCECProcessor::GetTV(void) const + { + return CCECBusDevice::AsTV(m_busDevices->At(CECDEVICE_TV)); +diff --git a/src/libcec/CECProcessor.h b/src/libcec/CECProcessor.h +index 08917b9..1971dee 100644 +--- a/src/libcec/CECProcessor.h ++++ b/src/libcec/CECProcessor.h +@@ -149,6 +149,7 @@ namespace CEC + bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT); + + bool TransmitPendingActiveSourceCommands(void); ++ bool TransmitSystemAudioModeRequest(cec_logical_address initiator); + + CCECDeviceMap *GetDevices(void) const { return m_busDevices; } + CLibCEC *GetLib(void) const { return m_libcec; } +diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h +index 0d0cf17..f6c818a 100644 +--- a/src/libcec/CECTypeUtils.h ++++ b/src/libcec/CECTypeUtils.h +@@ -766,6 +766,8 @@ namespace CEC + return "Raspberry Pi"; + case ADAPTERTYPE_TDA995x: + return "TDA995x"; ++ case ADAPTERTYPE_IMX: ++ return "i.MX"; + default: + return "unknown"; + } +diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt +index a494533..f097bf4 100644 +--- a/src/libcec/CMakeLists.txt ++++ b/src/libcec/CMakeLists.txt +@@ -13,9 +13,9 @@ include(CheckIncludeFiles) + include(CheckCXXCompilerFlag) + include(../../cmake/UseMultiArch.cmake) + +-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11) ++check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11) + if (SUPPORTS_CXX11) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + + find_package(p8-platform REQUIRED) +@@ -64,7 +64,8 @@ set(CEC_SOURCES_IMPLEMENTATIONS implementations/ANCommandHandler.cpp + implementations/RLCommandHandler.cpp + implementations/PHCommandHandler.cpp + implementations/RHCommandHandler.cpp +- implementations/AQCommandHandler.cpp) ++ implementations/AQCommandHandler.cpp ++ implementations/GRCommandHandler.cpp) + + # /platform/* + set(CEC_SOURCES_PLATFORM platform/adl/adl-edid.cpp +@@ -121,6 +122,7 @@ set(CEC_HEADERS devices/CECRecordingDevice.h + implementations/RHCommandHandler.h + implementations/PHCommandHandler.h + implementations/AQCommandHandler.h ++ implementations/GRCommandHandler.h + CECProcessor.h) + source_group("Header Files" FILES ${CEC_HEADERS}) + +@@ -173,13 +175,17 @@ install(FILES ${PROJECT_SOURCE_DIR}/../../include/cec.h + DESTINATION include/libcec) + + # libCEC target +-add_library(cec SHARED ${CEC_SOURCES}) +-install(TARGETS cec ++add_library(cecobj OBJECT ${CEC_SOURCES}) ++set_property(TARGET ${cecobj} PROPERTY POSITION_INDEPENDENT_CODE 1) ++add_library(cec SHARED $) ++add_library(cecstatic STATIC $) ++set_target_properties(cecstatic PROPERTIES OUTPUT_NAME cec) ++install(TARGETS cec cecstatic + DESTINATION ${LIB_DESTINATION}) +-set_target_properties(cec PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH} ++set_target_properties(cec cecstatic PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH} + SOVERSION ${LIBCEC_VERSION_MAJOR}) +-target_link_libraries(cec ${p8-platform_LIBRARIES}) +-target_link_libraries(cec ${CMAKE_THREAD_LIBS_INIT}) ++target_link_libraries(cec cecstatic ${platform_LIBRARIES}) ++target_link_libraries(cec cecstatic ${CMAKE_THREAD_LIBS_INIT}) + + include(cmake/LinkPlatformSupport.cmake) + include(cmake/DisplayPlatformSupport.cmake) +diff --git a/src/libcec/LibCEC.cpp b/src/libcec/LibCEC.cpp +index 5f6a136..177c409 100644 +--- a/src/libcec/LibCEC.cpp ++++ b/src/libcec/LibCEC.cpp +@@ -621,3 +621,8 @@ void CLibCEC::PrintVersion(uint32_t version, char* buf, size_t bufSize) + std::string strVersion = CCECTypeUtils::VersionToString(version); + snprintf(buf, bufSize, "%s", strVersion.c_str()); + } ++ ++bool CLibCEC::TransmitSystemAudioModeRequest(void) ++{ ++ return m_client ? m_client->TransmitSystemAudioModeRequest() : false; ++} +diff --git a/src/libcec/LibCEC.h b/src/libcec/LibCEC.h +index cc29c82..f769d8c 100644 +--- a/src/libcec/LibCEC.h ++++ b/src/libcec/LibCEC.h +@@ -102,6 +102,7 @@ namespace CEC + bool PersistConfiguration(libcec_configuration *configuration); + void RescanActiveDevices(void); + bool IsLibCECActiveSource(void); ++ bool TransmitSystemAudioModeRequest(void); + + const char* ToString(const cec_menu_state state) { return CCECTypeUtils::ToString(state); } + const char* ToString(const cec_version version) { return CCECTypeUtils::ToString(version); } +diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp +index da05725..3fe49f1 100644 +--- a/src/libcec/adapter/AdapterFactory.cpp ++++ b/src/libcec/adapter/AdapterFactory.cpp +@@ -58,6 +58,11 @@ + #include "Exynos/ExynosCECAdapterCommunication.h" + #endif + ++#if defined(HAVE_IMX_API) ++#include "IMX/IMXCECAdapterDetection.h" ++#include "IMX/IMXCECAdapterCommunication.h" ++#endif ++ + using namespace CEC; + + int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */) +@@ -126,8 +131,21 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + } + #endif + ++#if defined(HAVE_IMX_API) ++ if (iAdaptersFound < iBufSize && CIMXCECAdapterDetection::FindAdapter() && ++ (!strDevicePath || !strcmp(strDevicePath, CEC_IMX_VIRTUAL_COM))) ++ { ++ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_IMX_PATH); ++ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_IMX_VIRTUAL_COM); ++ deviceList[iAdaptersFound].iVendorId = IMX_ADAPTER_VID; ++ deviceList[iAdaptersFound].iProductId = IMX_ADAPTER_PID; ++ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_IMX; ++ iAdaptersFound++; ++ } ++#endif ++ + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API) + #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" + #endif + +@@ -151,11 +169,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CRPiCECAdapterCommunication(m_lib->m_cec); + #endif + ++#if defined(HAVE_IMX_API) ++ if (!strcmp(strPort, CEC_IMX_VIRTUAL_COM)) ++ return new CIMXCECAdapterCommunication(m_lib->m_cec); ++#endif ++ + #if defined(HAVE_P8_USB) + return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); + #endif + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) + return NULL; + #endif + } +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp +new file mode 100644 +index 0000000..212dd75 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp +@@ -0,0 +1,381 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * Copyright (C) 2014 by Matus Kral ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_IMX_API) ++#include "IMXCECAdapterCommunication.h" ++ ++#include "CECTypeUtils.h" ++#include "LibCEC.h" ++#include ++#include ++#include ++ ++using namespace std; ++using namespace CEC; ++using namespace P8PLATFORM; ++ ++#include "IMXCECAdapterMessageQueue.h" ++ ++#define LIB_CEC m_callback->GetLib() ++ ++// these are defined in nxp private header file ++#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/ ++#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/ ++#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/ ++#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/ ++#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/ ++#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/ ++#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/ ++#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/ ++ ++CIMXCECAdapterCommunication::CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback) : ++ IAdapterCommunication(callback), ++ m_PAReporter(NULL) ++{ ++ CLockObject lock(m_mutex); ++ ++ m_iNextMessage = 0; ++ m_logicalAddress = CECDEVICE_UNKNOWN; ++ m_bLogicalAddressRegistered = false; ++ m_bInitialised = false; ++ m_dev = new CCDevSocket(CEC_IMX_PATH); ++ m_physicalAddress = -1; ++} ++ ++CIMXCECAdapterCommunication::~CIMXCECAdapterCommunication(void) ++{ ++ Close(); ++ SAFE_DELETE(m_PAReporter); ++ delete m_dev; ++ m_dev = 0; ++} ++ ++bool CIMXCECAdapterCommunication::IsOpen(void) ++{ ++ return IsInitialised() && m_dev->IsOpen(); ++} ++ ++bool CIMXCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening) ++{ ++ if (m_dev->Open(iTimeoutMs)) ++ { ++ if (!bStartListening || CreateThread()) { ++ if (m_dev->Ioctl(HDMICEC_IOC_STARTDEVICE, NULL) == 0) { ++ m_bInitialised = true; ++ RegisterLogicalAddress(CECDEVICE_BROADCAST); ++ return true; ++ } ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to start device\n", __func__); ++ } ++ m_dev->Close(); ++ } ++ ++ return false; ++} ++ ++ ++void CIMXCECAdapterCommunication::Close(void) ++{ ++ m_bInitialised = false; ++ if (m_dev->Ioctl(HDMICEC_IOC_STOPDEVICE, NULL) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to stop device\n", __func__); ++ } ++ StopThread(false); ++ m_dev->Close(); ++} ++ ++ ++std::string CIMXCECAdapterCommunication::GetError(void) const ++{ ++ std::string strError(m_strError); ++ return strError; ++} ++ ++ ++cec_adapter_message_state CIMXCECAdapterCommunication::Write( ++ const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool UNUSED(bIsReply)) ++{ ++ unsigned char message[MAX_MESSAGE_LEN]; ++ CIMXCECAdapterMessageQueueEntry *entry; ++ int msg_len = 1; ++ cec_adapter_message_state rc = ADAPTER_MESSAGE_STATE_ERROR; ++ ++ bRetry = true; ++ if ((size_t)data.parameters.size + data.opcode_set + 1 > sizeof(message)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: data size too large !", __func__); ++ bRetry = false; ++ return rc; ++ } ++ ++ message[0] = (data.initiator << 4) | (data.destination & 0x0f); ++ if (data.opcode_set) ++ { ++ message[1] = data.opcode; ++ msg_len++; ++ memcpy(&message[2], data.parameters.data, data.parameters.size); ++ msg_len+=data.parameters.size; ++ } ++ ++ entry = new CIMXCECAdapterMessageQueueEntry(message[0], data.opcode); ++ m_messageMutex.Lock(); ++ uint32_t msgKey = ++m_iNextMessage; ++ m_messages.insert(make_pair(msgKey, entry)); ++ m_messageMutex.Unlock(); ++ ++ if (m_dev->Write(message, msg_len) > 0) ++ { ++ if (entry->Wait(data.transmit_timeout ? data.transmit_timeout : iLineTimeout *1000)) ++ { ++ int status = entry->Result(); ++ ++ if (status == MESSAGE_TYPE_NOACK) ++ rc = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; ++ else if (status == MESSAGE_TYPE_SEND_SUCCESS) ++ rc = ADAPTER_MESSAGE_STATE_SENT_ACKED; ++ ++ bRetry = false; ++ } ++ else ++ { ++ rc = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT; ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: command timed out !", __func__); ++#endif ++ } ++ } ++ else ++ { ++ Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: write failed !", __func__); ++#endif ++ } ++ ++ m_messageMutex.Lock(); ++ m_messages.erase(msgKey); ++ m_messageMutex.Unlock(); ++ ++ delete entry; ++ ++ return rc; ++} ++ ++ ++uint16_t CIMXCECAdapterCommunication::GetFirmwareVersion(void) ++{ ++ /* FIXME add ioctl ? */ ++ return 0; ++} ++ ++ ++cec_vendor_id CIMXCECAdapterCommunication::GetVendorId(void) ++{ ++ return CEC_VENDOR_UNKNOWN; ++} ++ ++ ++uint16_t CIMXCECAdapterCommunication::GetPhysicalAddress(void) ++{ ++ uint8_t phy_addr[4]; ++ uint16_t pa_tmp; ++ ++ if (m_dev->Ioctl(HDMICEC_IOC_GETPHYADDRESS, &phy_addr) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_GETPHYADDRESS failed !", __func__); ++ return CEC_INVALID_PHYSICAL_ADDRESS; ++ } ++ ++ if ((pa_tmp = ((phy_addr[0] << 4 | phy_addr[1]) << 8) | (phy_addr[2] << 4 | phy_addr[3]))) ++ m_physicalAddress = pa_tmp; ++ ++ return m_physicalAddress; ++} ++ ++ ++cec_logical_addresses CIMXCECAdapterCommunication::GetLogicalAddresses(void) ++{ ++ cec_logical_addresses addresses; ++ addresses.Clear(); ++ ++ CLockObject lock(m_mutex); ++ if (m_bLogicalAddressRegistered) ++ addresses.Set(m_logicalAddress); ++ ++ return addresses; ++} ++ ++void CIMXCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) ++{ ++ UnregisterLogicalAddress(); ++} ++ ++bool CIMXCECAdapterCommunication::UnregisterLogicalAddress(void) ++{ ++ { ++ CLockObject lock(m_mutex); ++ if (!m_bLogicalAddressRegistered) ++ return true; ++ } ++ ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - releasing previous logical address", __func__); ++#endif ++ return RegisterLogicalAddress(CECDEVICE_BROADCAST); ++} ++ ++bool CIMXCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address) ++{ ++ { ++ CLockObject lock(m_mutex); ++ if ((m_logicalAddress == address && m_bLogicalAddressRegistered) || ++ (m_logicalAddress == address && address == CECDEVICE_BROADCAST)) ++ { ++ return true; ++ } ++ } ++ ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: %x to %x", __func__, m_logicalAddress, address); ++#endif ++ ++ if (m_dev->Ioctl(HDMICEC_IOC_SETLOGICALADDRESS, (void *)address) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_SETLOGICALADDRESS failed !", __func__); ++ return false; ++ } ++ ++ CLockObject lock(m_mutex); ++ ++ m_logicalAddress = address; ++ m_bLogicalAddressRegistered = (address != CECDEVICE_BROADCAST) ? true : false; ++ return true; ++} ++ ++bool CIMXCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) ++{ ++ int log_addr = addresses.primary; ++ ++ return RegisterLogicalAddress((cec_logical_address)log_addr); ++} ++ ++ ++void *CIMXCECAdapterCommunication::Process(void) ++{ ++ bool bHandled; ++ hdmi_cec_event event; ++ int ret; ++ ++ cec_logical_address initiator, destination; ++ ++ while (!IsStopped()) ++ { ++ if (IsInitialised() && (ret = m_dev->Read((char *)&event, sizeof(event), 0)) > 0) ++ { ++ ++ initiator = cec_logical_address(event.msg[0] >> 4); ++ destination = cec_logical_address(event.msg[0] & 0x0f); ++ ++ if (event.event_type == MESSAGE_TYPE_RECEIVE_SUCCESS) ++ { ++ cec_command cmd; ++ ++ cec_command::Format( ++ cmd, initiator, destination, ++ ( event.msg_len > 1 ) ? cec_opcode(event.msg[1]) : CEC_OPCODE_NONE); ++ ++ for( uint8_t i = 2; i < event.msg_len; i++ ) ++ cmd.parameters.PushBack(event.msg[i]); ++ ++ if (!IsStopped()) { ++ m_callback->OnCommandReceived(cmd); ++ } ++ } ++ else if (event.event_type == MESSAGE_TYPE_SEND_SUCCESS ++ || event.event_type == MESSAGE_TYPE_NOACK) ++ { ++ bHandled = false; ++ ++ m_messageMutex.Lock(); ++ for (map::iterator it = m_messages.begin(); ++ !bHandled && it != m_messages.end(); it++) ++ { ++ bHandled = it->second->Received(event.event_type, event.msg[0], (cec_opcode)event.msg[1]); ++ } ++ m_messageMutex.Unlock(); ++ ++ if (!bHandled) ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: response not matched !", __func__); ++ } ++ else if (event.event_type == MESSAGE_TYPE_DISCONNECTED) ++ { ++ /* HDMI Hotplug event - disconnect */ ++ } ++ else if (event.event_type == MESSAGE_TYPE_CONNECTED) ++ { ++ if (m_physicalAddress == 0xffff) ++ continue; ++ /* HDMI Hotplug event - connect */ ++ uint16_t oldAddress = m_physicalAddress; ++ ++ if (oldAddress != GetPhysicalAddress()) { ++ if (m_PAReporter) ++ while (m_PAReporter->IsRunning()) Sleep(5); ++ delete m_PAReporter; ++ ++ m_PAReporter = new CCECPAChangedReporter(m_callback, m_physicalAddress); ++ m_PAReporter->CreateThread(false); ++ } ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: plugin event received", __func__); ++#endif ++ } ++ else ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: unhandled response received %d!", __func__, event.event_type); ++ } ++ } ++ ++ return 0; ++} ++ ++CCECPAChangedReporter::CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA) : ++ m_callback(callback), ++ m_newPA(newPA) ++{ ++} ++ ++void* CCECPAChangedReporter::Process(void) ++{ ++ m_callback->HandlePhysicalAddressChanged(m_newPA); ++ return NULL; ++} ++ ++#endif // HAVE_IMX_API +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h +new file mode 100644 +index 0000000..2da38c1 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h +@@ -0,0 +1,139 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * Copyright (C) 2014 by Matus Kral ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#if defined(HAVE_IMX_API) ++ ++#include "adapter/AdapterCommunication.h" ++#include ++#include ++#include ++#include "adapter/IMX/mxc_hdmi-cec.h" ++#include ++ ++#define IMX_ADAPTER_VID 0x0471 /*FIXME TBD*/ ++#define IMX_ADAPTER_PID 0x1001 ++ ++typedef struct hdmi_cec_event{ ++ uint8_t event_type; ++ uint8_t msg_len; ++ uint8_t msg[MAX_MESSAGE_LEN]; ++}hdmi_cec_event; ++ ++ ++namespace P8PLATFORM ++{ ++ class CCDevSocket; ++}; ++ ++namespace CEC ++{ ++ class CIMXCECAdapterMessageQueueEntry; ++ ++ class CCECPAChangedReporter : public P8PLATFORM::CThread ++ { ++ public: ++ CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA); ++ void* Process(void); ++ ++ private: ++ IAdapterCommunicationCallback *m_callback; ++ uint16_t m_newPA; ++ }; ++ ++ class CIMXCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread ++ { ++ public: ++ /*! ++ * @brief Create a new USB-CEC communication handler. ++ * @param callback The callback to use for incoming CEC commands. ++ */ ++ CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback); ++ virtual ~CIMXCECAdapterCommunication(void); ++ ++ /** @name IAdapterCommunication implementation */ ++ ///{ ++ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true); ++ void Close(void); ++ bool IsOpen(void); ++ std::string GetError(void) const; ++ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply); ++ ++ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) { return true; } ++ bool StartBootloader(void) { return false; } ++ bool SetLogicalAddresses(const cec_logical_addresses &addresses); ++ cec_logical_addresses GetLogicalAddresses(void); ++ bool PingAdapter(void) { return IsInitialised(); } ++ uint16_t GetFirmwareVersion(void); ++ uint32_t GetFirmwareBuildDate(void) { return 0; } ++ bool IsRunningLatestFirmware(void) { return true; } ++ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } ++ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } ++ std::string GetPortName(void) { return std::string("IMX"); } ++ uint16_t GetPhysicalAddress(void); ++ bool SetControlledMode(bool UNUSED(controlled)) { return true; } ++ cec_vendor_id GetVendorId(void); ++ void HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)); ++ bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } ++ cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_IMX; } ++ uint16_t GetAdapterVendorId(void) const { return IMX_ADAPTER_VID; } ++ uint16_t GetAdapterProductId(void) const { return IMX_ADAPTER_PID; } ++ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {} ++ ///} ++ ++ /** @name PLATFORM::CThread implementation */ ++ ///{ ++ void *Process(void); ++ ///} ++ ++ private: ++ bool IsInitialised(void) { return m_bInitialised; }; ++ bool RegisterLogicalAddress(const cec_logical_address address); ++ bool UnregisterLogicalAddress(void); ++ ++ std::string m_strError; /**< current error message */ ++ ++ cec_logical_address m_logicalAddress; ++ uint16_t m_physicalAddress; ++ ++ P8PLATFORM::CMutex m_mutex; ++ P8PLATFORM::CCDevSocket *m_dev; /**< the device connection */ ++ ++ P8PLATFORM::CMutex m_messageMutex; ++ uint32_t m_iNextMessage; ++ std::map m_messages; ++ ++ bool m_bLogicalAddressRegistered; ++ bool m_bInitialised; ++ ++ CCECPAChangedReporter *m_PAReporter; ++ }; ++ ++}; ++ ++#endif +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp +new file mode 100644 +index 0000000..6c93c45 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp +@@ -0,0 +1,42 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#include "env.h" ++#include ++ ++#if defined(HAVE_IMX_API) ++#include "IMXCECAdapterDetection.h" ++ ++ ++using namespace CEC; ++ ++bool CIMXCECAdapterDetection::FindAdapter(void) ++{ ++ return access(CEC_IMX_PATH, 0) == 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.h b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h +new file mode 100644 +index 0000000..d54891d +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h +@@ -0,0 +1,36 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++namespace CEC ++{ ++ class CIMXCECAdapterDetection ++ { ++ public: ++ static bool FindAdapter(void); ++ }; ++} +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h +new file mode 100644 +index 0000000..e54c192 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h +@@ -0,0 +1,118 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include ++ ++namespace CEC ++{ ++ using namespace P8PLATFORM; ++ ++ class CIMXCECAdapterMessageQueueEntry ++ { ++ public: ++ CIMXCECAdapterMessageQueueEntry(uint8_t addrs, cec_opcode opcode) ++ : m_bWaiting(true), m_retval((uint32_t)-1), m_bSucceeded(false) ++ { ++ m_opcode = opcode; ++ m_addrs = addrs; ++ } ++ ++ virtual ~CIMXCECAdapterMessageQueueEntry(void) {} ++ ++ /*! ++ * @brief Query result from worker thread ++ */ ++ uint32_t Result() const ++ { ++ return m_retval; ++ } ++ ++ /*! ++ * @brief Signal waiting threads ++ */ ++ void Broadcast(void) ++ { ++ CLockObject lock(m_mutex); ++ m_condition.Broadcast(); ++ } ++ ++ /*! ++ * @brief Signal waiting thread(s) when message matches this entry ++ */ ++ bool Received(int response, uint8_t addrs, cec_opcode opcode) ++ { ++ CLockObject lock(m_mutex); ++ ++ if (!(m_addrs == addrs && m_opcode == opcode)) ++ return false; ++ ++ m_retval = response; ++ m_bSucceeded = true; ++ m_condition.Signal(); ++ return true; ++ } ++ ++ /*! ++ * @brief Wait for a response to this command. ++ * @param iTimeout The timeout to use while waiting. ++ * @return True when a response was received before the timeout passed, false otherwise. ++ */ ++ bool Wait(uint32_t iTimeout) ++ { ++ CLockObject lock(m_mutex); ++ ++ bool bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout); ++ m_bWaiting = false; ++ return bReturn; ++ } ++ ++ /*! ++ * @return True while a thread is waiting for a signal or isn't waiting yet, false otherwise. ++ */ ++ bool IsWaiting(void) ++ { ++ CLockObject lock(m_mutex); ++ return m_bWaiting; ++ } ++ ++ private: ++ bool m_bWaiting; /**< true while a thread is waiting or when it hasn't started waiting yet */ ++ P8PLATFORM::CCondition m_condition; /**< the condition to wait on */ ++ P8PLATFORM::CMutex m_mutex; /**< mutex for changes to this class */ ++ int m_retval; ++ bool m_bSucceeded; ++ uint8_t m_addrs; ++ cec_opcode m_opcode; ++ }; ++ ++}; +diff --git a/src/libcec/adapter/IMX/mxc_hdmi-cec.h b/src/libcec/adapter/IMX/mxc_hdmi-cec.h +new file mode 100644 +index 0000000..bc5bbce +--- /dev/null ++++ b/src/libcec/adapter/IMX/mxc_hdmi-cec.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef _HDMICEC_H_ ++#define _HDMICEC_H_ ++#include ++ ++/* ++ * Ioctl definitions ++ */ ++ ++/* Use 'k' as magic number */ ++#define HDMICEC_IOC_MAGIC 'H' ++/* ++ * S means "Set" through a ptr, ++ * T means "Tell" directly with the argument value ++ * G means "Get": reply by setting through a pointer ++ * Q means "Query": response is on the return value ++ * X means "eXchange": G and S atomically ++ * H means "sHift": T and Q atomically ++ */ ++#define HDMICEC_IOC_SETLOGICALADDRESS \ ++ _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char) ++#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2) ++#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3) ++#define HDMICEC_IOC_GETPHYADDRESS \ ++ _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]) ++ ++#define MAX_MESSAGE_LEN 16 ++ ++#define MESSAGE_TYPE_RECEIVE_SUCCESS 1 ++#define MESSAGE_TYPE_NOACK 2 ++#define MESSAGE_TYPE_DISCONNECTED 3 ++#define MESSAGE_TYPE_CONNECTED 4 ++#define MESSAGE_TYPE_SEND_SUCCESS 5 ++ ++#endif /* !_HDMICEC_H_ */ ++ +diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake +index b8a16c8..36ed4cf 100644 +--- a/src/libcec/cmake/CheckPlatformSupport.cmake ++++ b/src/libcec/cmake/CheckPlatformSupport.cmake +@@ -83,26 +83,49 @@ else() + endif() + + # xrandr +- check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS) +- check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB) +- if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB) +- set(LIB_INFO "${LIB_INFO}, randr") +- list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp) +- set(HAVE_RANDR 1) ++ if (${HAVE_RANDR_API}) ++ check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS) ++ check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB) ++ if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB) ++ set(LIB_INFO "${LIB_INFO}, randr") ++ list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp) ++ set(HAVE_RANDR 1) ++ else() ++ set(HAVE_RANDR 0) ++ endif() + else() + set(HAVE_RANDR 0) + endif() + +- # raspberry pi +- find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}") +- check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_LIB) +- if (HAVE_RPI_LIB) ++ # iMX6 ++ if (${HAVE_IMX_API}) ++ set(LIB_INFO "${LIB_INFO}, iMX6") ++ set(HAVE_IMX_API 1) ++ set(CEC_SOURCES_ADAPTER_IMX adapter/IMX/IMXCECAdapterDetection.cpp ++ adapter/IMX/IMXCECAdapterCommunication.cpp) ++ source_group("Source Files\\adapter\\iMX6" FILES ${CEC_SOURCES_ADAPTER_IMX}) ++ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_IMX}) ++ set(HAVE_RPI_API 0) ++ else() ++ set(HAVE_IMX_API 0) + set(HAVE_RPI_API 1) ++ endif() ++ ++ # raspberry pi ++ if (HAVE_RPI_API) ++ find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}") ++ check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_API) ++ endif() ++ if (HAVE_RPI_API) + find_library(RPI_VCOS vcos "${RPI_LIB_DIR}") + find_library(RPI_VCHIQ_ARM vchiq_arm "${RPI_LIB_DIR}") + include_directories(${RPI_INCLUDE_DIR} ${RPI_INCLUDE_DIR}/interface/vcos/pthreads ${RPI_INCLUDE_DIR}/interface/vmcs_host/linux) + +- set(LIB_INFO "${LIB_INFO}, RPi") ++ set(LIB_INFO "${LIB_INFO}, 'RPi'") ++ # find includes files on Raspberry Pi ++ include_directories(/opt/vc/include /opt/vc/include/interface/vcos/pthreads /opt/vc/include/interface/vmcs_host/linux) ++ list(APPEND CMAKE_REQUIRED_LIBRARIES "vcos") ++ list(APPEND CMAKE_REQUIRED_LIBRARIES "vchiq_arm") + set(CEC_SOURCES_ADAPTER_RPI adapter/RPi/RPiCECAdapterDetection.cpp + adapter/RPi/RPiCECAdapterCommunication.cpp + adapter/RPi/RPiCECAdapterMessageQueue.cpp) +@@ -132,6 +155,8 @@ else() + else() + set(HAVE_EXYNOS_API 0) + endif() ++ ++ + endif() + + # rt +diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake +index 9dcaacf..770b1a5 100644 +--- a/src/libcec/cmake/DisplayPlatformSupport.cmake ++++ b/src/libcec/cmake/DisplayPlatformSupport.cmake +@@ -38,6 +38,12 @@ else() + message(STATUS "Exynos support: no") + endif() + ++if (HAVE_IMX_API) ++ message(STATUS "i.MX6 support: yes") ++else() ++ message(STATUS "i.MX6 support: no") ++endif() ++ + if (HAVE_DRM_EDID_PARSER) + message(STATUS "DRM support: yes") + else() +diff --git a/src/libcec/cmake/LinkPlatformSupport.cmake b/src/libcec/cmake/LinkPlatformSupport.cmake +index fc27353..b203f6f 100644 +--- a/src/libcec/cmake/LinkPlatformSupport.cmake ++++ b/src/libcec/cmake/LinkPlatformSupport.cmake +@@ -28,7 +28,12 @@ endif() + + # raspberry pi + if (HAVE_RPI_API) +- target_link_libraries(cec ${RPI_VCOS} ${RPI_VCHIQ_ARM} ${RPI_BCM_HOST}) ++ find_library (VCOS vcos) ++ target_link_libraries(cec ${VCOS}) ++ find_library (VCHIQ_ARM vchiq_arm) ++ target_link_libraries(cec ${VCHIP_ARM}) ++ find_library (BCM_HOST bcm_host) ++ target_link_libraries(cec ${BCM_HOST}) + endif() + + # Apple +diff --git a/src/libcec/devices/CECBusDevice.cpp b/src/libcec/devices/CECBusDevice.cpp +index e2d5ea3..0cbdb8d 100644 +--- a/src/libcec/devices/CECBusDevice.cpp ++++ b/src/libcec/devices/CECBusDevice.cpp +@@ -44,6 +44,7 @@ + #include "implementations/RLCommandHandler.h" + #include "implementations/RHCommandHandler.h" + #include "implementations/AQCommandHandler.h" ++#include "implementations/GRCommandHandler.h" + #include "LibCEC.h" + #include "CECTypeUtils.h" + #include +@@ -222,6 +223,9 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) + case CEC_VENDOR_SHARP2: + m_handler = new CAQCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); + break; ++ case CEC_VENDOR_GRUNDIG: ++ m_handler = new CGRCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); ++ break; + default: + m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); + break; +@@ -1025,21 +1029,18 @@ bool CCECBusDevice::ActivateSource(uint64_t iDelay /* = 0 */) + bool bReturn(true); + if (iDelay == 0) + { +- /** send system audio mode request if AVR exists */ +- if (m_iLogicalAddress != CECDEVICE_AUDIOSYSTEM) ++ /** some AVRs fail to be powered up by the TV when it powers up. power up the AVR explicitly */ ++ /*if (m_iLogicalAddress != CECDEVICE_AUDIOSYSTEM) + { + CCECBusDevice* audioSystem(m_processor->GetDevice(CECDEVICE_AUDIOSYSTEM)); +- if (audioSystem && audioSystem->IsPresent()) ++ if (audioSystem && audioSystem->IsPresent() && audioSystem->GetPowerStatus(m_iLogicalAddress) != CEC_POWER_STATUS_ON) + { +- cec_command command; ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "powering up the AVR"); ++ audioSystem->PowerOn(m_iLogicalAddress); + +- LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending system audio mode request for '%s'", ToString(m_iLogicalAddress)); +- cec_command::Format(command, m_iLogicalAddress, CECDEVICE_AUDIOSYSTEM, CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST); +- command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF)); +- command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF)); +- bReturn = m_handler->Transmit(command, false, false); ++ audioSystem->m_waitForResponse->Wait(CEC_OPCODE_DEVICE_VENDOR_ID, 10000); + } +- } ++ }*/ + + LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending active source message for '%s'", ToString(m_iLogicalAddress)); + bReturn = m_handler->ActivateSource(); +@@ -1283,7 +1284,7 @@ bool CCECBusDevice::PowerOn(const cec_logical_address initiator) + + MarkBusy(); + cec_power_status currentStatus; +- if (m_iLogicalAddress == CECDEVICE_TV || ++ if ((m_iLogicalAddress == CECDEVICE_TV && !ImageViewOnSent()) || + ((currentStatus = GetPowerStatus(initiator, false)) != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON && + currentStatus != CEC_POWER_STATUS_ON)) + { +@@ -1488,3 +1489,8 @@ bool CCECBusDevice::WaitForOpcode(cec_opcode opcode) + { + return m_waitForResponse->Wait(opcode); + } ++ ++bool CCECBusDevice::TransmitSystemAudioModeRequest(const cec_logical_address initiator) ++{ ++ return m_handler->TransmitSystemAudioModeRequest(initiator, m_iPhysicalAddress, false); ++} +diff --git a/src/libcec/devices/CECBusDevice.h b/src/libcec/devices/CECBusDevice.h +index d8b7193..23751fb 100644 +--- a/src/libcec/devices/CECBusDevice.h ++++ b/src/libcec/devices/CECBusDevice.h +@@ -194,6 +194,8 @@ namespace CEC + void SignalOpcode(cec_opcode opcode); + bool WaitForOpcode(cec_opcode opcode); + ++ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address initiator); ++ + CCECAudioSystem * AsAudioSystem(void); + static CCECAudioSystem * AsAudioSystem(CCECBusDevice *device); + CCECPlaybackDevice * AsPlaybackDevice(void); +diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in +index 0496aa0..836a4ce 100644 +--- a/src/libcec/env.h.in ++++ b/src/libcec/env.h.in +@@ -66,6 +66,9 @@ + /* Define to 1 for Raspberry Pi support */ + #cmakedefine HAVE_RPI_API @HAVE_RPI_API@ + ++/* Define to 1 for iMX6 support */ ++#cmakedefine HAVE_IMX_API @HAVE_IMX_API@ ++ + /* Define to 1 for TDA995x support */ + #cmakedefine HAVE_TDA995X_API @HAVE_TDA995X_API@ + +diff --git a/src/libcec/implementations/CECCommandHandler.cpp b/src/libcec/implementations/CECCommandHandler.cpp +index 2c2db21..59daaac 100644 +--- a/src/libcec/implementations/CECCommandHandler.cpp ++++ b/src/libcec/implementations/CECCommandHandler.cpp +@@ -62,6 +62,7 @@ CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice, + m_iTransmitRetries(iTransmitRetries), + m_bHandlerInited(false), + m_bOPTSendDeckStatusUpdateOnActiveSource(false), ++ m_bOPTSendMenuStatusUpdateOnActiveSource(true), + m_vendorId(CEC_VENDOR_UNKNOWN), + m_iActiveSourcePending(iActiveSourcePending), + m_iPowerStatusRequested(0) +@@ -1132,6 +1133,19 @@ bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiato + return Transmit(command, false, bIsReply); + } + ++bool CCECCommandHandler::TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply) ++{ ++ cec_command command; ++ cec_command::Format(command, iInitiator, CECDEVICE_AUDIOSYSTEM, CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST); ++ command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF)); ++ command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF)); ++ ++ if (Transmit(command, true, bIsReply)) ++ return true; ++ ++ return false; ++} ++ + bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply) + { + cec_command command; +@@ -1293,7 +1307,7 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f + if (!bActiveSourceFailed && bSourceSwitchAllowed) + { + bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false); +- if (bTvPresent && !bActiveSourceFailed) ++ if (bTvPresent && !bActiveSourceFailed && SendMenuStatusUpdateOnActiveSource()) + m_busDevice->TransmitMenuState(CECDEVICE_TV, false); + + // update the deck status for playback devices +diff --git a/src/libcec/implementations/CECCommandHandler.h b/src/libcec/implementations/CECCommandHandler.h +index 31da3e7..cd3afa3 100644 +--- a/src/libcec/implementations/CECCommandHandler.h ++++ b/src/libcec/implementations/CECCommandHandler.h +@@ -60,7 +60,8 @@ namespace CEC + virtual bool HandleCommand(const cec_command &command); + virtual cec_vendor_id GetVendorId(void) { return m_vendorId; }; + virtual void SetVendorId(cec_vendor_id vendorId) { m_vendorId = vendorId; } +- static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO;} ++ static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO ++ || vendorId == CEC_VENDOR_GRUNDIG; } + + virtual bool InitHandler(void) { return true; } + virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false); +@@ -89,6 +90,7 @@ namespace CEC + virtual bool TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state, bool bIsReply); + virtual bool TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t iVendorId, bool bIsReply); + virtual bool TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state, bool bIsReply); ++ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply); + virtual bool TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply); + virtual bool TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply); + virtual bool TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state, bool bIsReply); +@@ -96,6 +98,7 @@ namespace CEC + virtual bool TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWait = true); + virtual bool TransmitSetStreamPath(uint16_t iStreamPath, bool bIsReply); + virtual bool SendDeckStatusUpdateOnActiveSource(void) const { return m_bOPTSendDeckStatusUpdateOnActiveSource; }; ++ virtual bool SendMenuStatusUpdateOnActiveSource(void) const { return m_bOPTSendMenuStatusUpdateOnActiveSource; }; + + virtual void ScheduleActivateSource(uint64_t iDelay); + +@@ -164,6 +167,7 @@ namespace CEC + int8_t m_iTransmitRetries; + bool m_bHandlerInited; + bool m_bOPTSendDeckStatusUpdateOnActiveSource; ++ bool m_bOPTSendMenuStatusUpdateOnActiveSource; + cec_vendor_id m_vendorId; + int64_t m_iActiveSourcePending; + P8PLATFORM::CMutex m_mutex; +diff --git a/src/libcec/implementations/GRCommandHandler.cpp b/src/libcec/implementations/GRCommandHandler.cpp +new file mode 100644 +index 0000000..55857a3 +--- /dev/null ++++ b/src/libcec/implementations/GRCommandHandler.cpp +@@ -0,0 +1,93 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include "GRCommandHandler.h" ++ ++#include "devices/CECBusDevice.h" ++#include "CECProcessor.h" ++#include "LibCEC.h" ++#include "CECClient.h" ++ ++using namespace CEC; ++ ++#define LIB_CEC m_busDevice->GetProcessor()->GetLib() ++#define ToString(p) LIB_CEC->ToString(p) ++ ++CGRCommandHandler::CGRCommandHandler(CCECBusDevice *busDevice, ++ int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */, ++ int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */, ++ int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */, ++ int64_t iActiveSourcePending /* = 0 */) : ++ CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending) ++{ ++ m_vendorId = CEC_VENDOR_GRUNDIG; ++ m_bOPTSendMenuStatusUpdateOnActiveSource = false; ++ ++ m_busDevice->SetCecVersion(CEC_VERSION_1_3A); ++ ++ /* Grundig devices return "" as language */ ++ cec_menu_language lang; ++ lang.device = m_busDevice->GetLogicalAddress(); ++ snprintf(lang.language, 4, "eng"); ++ m_busDevice->SetMenuLanguage(lang); ++} ++ ++bool CGRCommandHandler::InitHandler(void) ++{ ++ if (m_bHandlerInited) ++ return true; ++ m_bHandlerInited = true; ++ ++ if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV) ++ return true; ++ ++ CCECBusDevice *primary = m_processor->GetPrimaryDevice(); ++ if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED) ++ { ++ /* imitate Toshiba devices */ ++ if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress()) ++ { ++ primary->SetVendorId(CEC_VENDOR_GRUNDIG); ++ primary->ReplaceHandler(false); ++ } ++ ++ if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV) ++ { ++ /* send the vendor id */ ++ primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false); ++ } ++ } ++ ++ return true; ++} +diff --git a/src/libcec/implementations/GRCommandHandler.h b/src/libcec/implementations/GRCommandHandler.h +new file mode 100644 +index 0000000..e01c7fc +--- /dev/null ++++ b/src/libcec/implementations/GRCommandHandler.h +@@ -0,0 +1,53 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include "CECCommandHandler.h" ++#include "p8-platform/threads/threads.h" ++ ++namespace CEC ++{ ++ class CGRCommandHandler : public CCECCommandHandler ++ { ++ public: ++ CGRCommandHandler(CCECBusDevice *busDevice, ++ int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT, ++ int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT, ++ int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES, ++ int64_t iActiveSourcePending = 0); ++ ++ bool InitHandler(void); ++ virtual ~CGRCommandHandler(void) {}; ++ }; ++}; +diff --git a/support/git-rev.sh b/support/git-rev.sh +index db682c1..15b6a23 100755 +--- a/support/git-rev.sh ++++ b/support/git-rev.sh +@@ -2,7 +2,7 @@ + + ## cmake doesn't read the variable when it doesn't end with a newline, and I haven't figured out how to have it add a newline directly... + if git rev-parse --git-dir > /dev/null 2>&1; then +- last_tag=`git describe --tags --abbrev=0` ++ last_tag=`git describe --tags --abbrev=0 --all` + last_hash=`git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h"` + commits_since_tag=`git log ${last_tag}..HEAD --oneline | wc -l` + git_dirty=`git diff HEAD | wc -l` +-- +2.7.1 + diff --git a/projects/imx6/patches/linux/4.4-xbian/linux-000-commits-d08b62d-ade5a7b.patch b/projects/imx6/patches/linux/4.4-xbian/linux-000-commits-d08b62d-ade5a7b.patch deleted file mode 100644 index 2305cc7d56..0000000000 --- a/projects/imx6/patches/linux/4.4-xbian/linux-000-commits-d08b62d-ade5a7b.patch +++ /dev/null @@ -1,16315 +0,0 @@ -From eb69269a27cf75c34e22728a5499ce4ca9e3bc4e Mon Sep 17 00:00:00 2001 -From: Fugang Duan -Date: Fri, 10 Oct 2014 16:25:26 +0800 -Subject: [PATCH 01/13] ENGR00299323-10 net:fec: add enet AVB Ubuntu Gstreamer - demo support - -Support Gstreamer AVB demo support. - -ring1 -> ClassA, ring2 -> ClassB, ring0 -> Best Effort - -For QoS: ring1 > ring2 > ring0 -For bandwidth reverse: - 50% bandwidth -> ClassA - 33% bandwidth -> ClassB - 17% bandwidth -> Best effort queue - -In general, ClassA run audio, ClassB run video. -Since AVB demo use big bandwidth streaming, video cost more than -33Mbps bandwidth, and with Qos limitation: ClassA >= ClassB > Best effort, -so we have to change ring2 bandwidth equal to ring1 bandwidth (50%). -After validate on FPGA, AVB demo can work fine for audio and video. - -Signed-off-by: Fugang Duan -(cherry picked from commit 93d6579a7b3d2dafa721c835df5d5f7d30ed386e) -(cherry picked from commit 2f78438d70c847f0570ece98cd7933041e36f6bd) -Signed-off-by: Matus Kral ---- - drivers/net/ethernet/freescale/fec_main.c | 35 ++++++++++++++++++++++++++++++- - 1 file changed, 34 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c -index 969922a..d9f1ab3 100644 ---- a/drivers/net/ethernet/freescale/fec_main.c -+++ b/drivers/net/ethernet/freescale/fec_main.c -@@ -18,7 +18,7 @@ - * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) - * Copyright (c) 2004-2006 Macq Electronique SA. - * -- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. -+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. - */ - - #include -@@ -70,6 +70,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); - #define DRIVER_NAME "fec" - - #define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0)) -+static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2}; - - /* Pause frame feild and FIFO threshold */ - #define FEC_ENET_FCE (1 << 5) -@@ -3171,10 +3172,42 @@ static int fec_set_features(struct net_device *netdev, - return 0; - } - -+u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb) -+{ -+ struct vlan_ethhdr *vhdr; -+ unsigned short vlan_TCI = 0; -+ -+ if (skb->protocol == ntohs(ETH_P_ALL)) { -+ vhdr = (struct vlan_ethhdr *)(skb->data); -+ vlan_TCI = ntohs(vhdr->h_vlan_TCI); -+ } -+ -+ return vlan_TCI; -+} -+ -+u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, -+ void *accel_priv, select_queue_fallback_t fallback) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ const struct platform_device_id *id_entry = -+ platform_get_device_id(fep->pdev); -+ u16 vlan_tag; -+ -+ if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB)) -+ return skb_tx_hash(ndev, skb); -+ -+ vlan_tag = fec_enet_get_raw_vlan_tci(skb); -+ if (!vlan_tag) -+ return vlan_tag; -+ -+ return fec_enet_vlan_pri_to_queue[vlan_tag >> 13]; -+} -+ - static const struct net_device_ops fec_netdev_ops = { - .ndo_open = fec_enet_open, - .ndo_stop = fec_enet_close, - .ndo_start_xmit = fec_enet_start_xmit, -+ .ndo_select_queue = fec_enet_select_queue, - .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - -From 4455ed29cc7a523a293bbe766a75aab04a7f9372 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Sun, 3 Apr 2016 09:09:27 +0200 -Subject: [PATCH 02/13] apply Real-Time patch -rt13 - ---- - Documentation/kernel-parameters.txt | 9 + - Makefile | 3 + - arch/Kconfig | 1 + - arch/arm/kvm/arm.c | 12 +- - arch/arm/kvm/psci.c | 4 +- - arch/arm/mach-at91/Kconfig | 1 + - arch/arm/mach-at91/at91rm9200.c | 2 - - arch/arm/mach-at91/at91sam9.c | 2 - - arch/arm/mach-at91/generic.h | 13 +- - arch/arm/mach-at91/pm.c | 70 +++++- - arch/arm/mach-at91/sama5.c | 2 +- - arch/arm64/kernel/debug-monitors.c | 21 +- - arch/mips/kvm/mips.c | 8 +- - arch/powerpc/include/asm/kvm_host.h | 4 +- - arch/powerpc/kvm/book3s_hv.c | 22 +- - arch/s390/include/asm/kvm_host.h | 2 +- - arch/s390/kvm/interrupt.c | 4 +- - arch/x86/kernel/kvm.c | 37 +-- - arch/x86/kvm/lapic.c | 6 +- - block/blk-core.c | 4 +- - block/blk-mq.c | 4 +- - drivers/block/zram/zram_drv.c | 30 +-- - drivers/block/zram/zram_drv.h | 41 +++ - drivers/clk/at91/clk-generated.c | 95 ++++--- - drivers/clk/at91/clk-h32mx.c | 40 +-- - drivers/clk/at91/clk-main.c | 324 +++++++++++------------- - drivers/clk/at91/clk-master.c | 94 +++---- - drivers/clk/at91/clk-peripheral.c | 136 +++++----- - drivers/clk/at91/clk-pll.c | 150 +++++------ - drivers/clk/at91/clk-plldiv.c | 44 ++-- - drivers/clk/at91/clk-programmable.c | 96 +++---- - drivers/clk/at91/clk-slow.c | 34 +-- - drivers/clk/at91/clk-smd.c | 56 +++-- - drivers/clk/at91/clk-system.c | 96 +++---- - drivers/clk/at91/clk-usb.c | 123 ++++----- - drivers/clk/at91/clk-utmi.c | 80 ++---- - drivers/clk/at91/pmc.c | 426 +------------------------------- - drivers/clk/at91/pmc.h | 98 +------- - drivers/clocksource/tcb_clksrc.c | 33 ++- - drivers/clocksource/timer-atmel-pit.c | 8 +- - drivers/gpu/drm/i915/i915_irq.c | 2 + - drivers/gpu/drm/i915/intel_sprite.c | 11 +- - drivers/gpu/drm/radeon/radeon_display.c | 2 + - drivers/iommu/amd_iommu.c | 12 +- - drivers/tty/serial/sc16is7xx.c | 2 +- - drivers/usb/gadget/function/f_fs.c | 2 +- - drivers/usb/gadget/udc/atmel_usba_udc.c | 20 +- - drivers/usb/gadget/udc/atmel_usba_udc.h | 2 + - fs/btrfs/volumes.c | 1 - - fs/f2fs/f2fs.h | 4 +- - include/linux/blkdev.h | 2 +- - include/linux/clk/at91_pmc.h | 12 - - include/linux/completion.h | 8 +- - include/linux/ftrace.h | 12 + - include/linux/hrtimer.h | 2 +- - include/linux/kvm_host.h | 5 +- - include/linux/list_bl.h | 12 +- - include/linux/locallock.h | 6 +- - include/linux/sched.h | 2 - - include/linux/spinlock_rt.h | 25 +- - include/linux/suspend.h | 6 + - include/linux/swait.h | 173 +++++++++++++ - include/linux/wait-simple.h | 207 ---------------- - include/trace/events/hist.h | 1 + - include/trace/events/writeback.h | 121 ++++----- - kernel/cpu.c | 4 +- - kernel/events/core.c | 1 + - kernel/futex.c | 18 +- - kernel/irq/irqdesc.c | 21 +- - kernel/irq/manage.c | 2 +- - kernel/locking/lglock.c | 6 +- - kernel/locking/rt.c | 2 - - kernel/locking/rtmutex.c | 244 +++++++++++------- - kernel/power/hibernate.c | 7 + - kernel/power/suspend.c | 5 + - kernel/printk/printk.c | 116 ++++----- - kernel/rcu/rcutorture.c | 7 + - kernel/rcu/tree.c | 24 +- - kernel/rcu/tree.h | 15 +- - kernel/rcu/tree_plugin.h | 26 +- - kernel/sched/Makefile | 2 +- - kernel/sched/completion.c | 10 +- - kernel/sched/core.c | 21 +- - kernel/sched/swait.c | 143 +++++++++++ - kernel/sched/wait-simple.c | 115 --------- - kernel/sched/work-simple.c | 8 +- - kernel/softirq.c | 8 +- - kernel/stop_machine.c | 40 +-- - kernel/time/tick-broadcast-hrtimer.c | 1 + - kernel/trace/trace_irqsoff.c | 8 +- - lib/dump_stack.c | 4 +- - localversion-rt | 2 +- - mm/backing-dev.c | 4 +- - mm/zsmalloc.c | 4 +- - net/core/dev.c | 6 +- - virt/kvm/async_pf.c | 4 +- - virt/kvm/kvm_main.c | 17 +- - 97 files changed, 1679 insertions(+), 2103 deletions(-) - create mode 100644 include/linux/swait.h - delete mode 100644 include/linux/wait-simple.h - create mode 100644 kernel/sched/swait.c - delete mode 100644 kernel/sched/wait-simple.c - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 742f69d..bcaf28e 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1629,6 +1629,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - ip= [IP_PNP] - See Documentation/filesystems/nfs/nfsroot.txt. - -+ irqaffinity= [SMP] Set the default irq affinity mask -+ Format: -+ ,..., -+ or -+ - -+ (must be a positive range in ascending order) -+ or a mixture -+ ,...,- -+ - irqfixup [HW] - When an interrupt is not handled search all handlers - for it. Intended to get systems with badly broken -diff --git a/Makefile b/Makefile -index 87d12b4..d95c4a4 100644 ---- a/Makefile -+++ b/Makefile -@@ -767,6 +767,9 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=strict-prototypes) - # Prohibit date/time macros, which would make the build non-deterministic - KBUILD_CFLAGS += $(call cc-option,-Werror=date-time) - -+# enforce correct pointer usage -+#KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types) -+ - # use the deterministic mode of AR if available - KBUILD_ARFLAGS := $(call ar-option,D) - -diff --git a/arch/Kconfig b/arch/Kconfig -index 81592b3..3b26d76 100644 ---- a/arch/Kconfig -+++ b/arch/Kconfig -@@ -53,6 +53,7 @@ config KPROBES - config JUMP_LABEL - bool "Optimize very unlikely/likely branches" - depends on HAVE_ARCH_JUMP_LABEL -+ depends on (!INTERRUPT_OFF_HIST && !PREEMPT_OFF_HIST && !WAKEUP_LATENCY_HIST && !MISSED_TIMER_OFFSETS_HIST) - help - This option enables a transparent branch optimization that - makes certain almost-always-true or almost-always-false branch -diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c -index 4f5c42a..bb43bc3 100644 ---- a/arch/arm/kvm/arm.c -+++ b/arch/arm/kvm/arm.c -@@ -498,16 +498,16 @@ static void kvm_arm_resume_guest(struct kvm *kvm) - struct kvm_vcpu *vcpu; - - kvm_for_each_vcpu(i, vcpu, kvm) { -- struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); -+ struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); - - vcpu->arch.pause = false; -- swait_wake_interruptible(wq); -+ swake_up(wq); - } - } - - static void vcpu_sleep(struct kvm_vcpu *vcpu) - { -- struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); -+ struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); - - swait_event_interruptible(*wq, ((!vcpu->arch.power_off) && - (!vcpu->arch.pause))); -@@ -568,7 +568,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) - * involves poking the GIC, which must be done in a - * non-preemptible context. - */ -- preempt_disable(); -+ migrate_disable(); - kvm_timer_flush_hwstate(vcpu); - kvm_vgic_flush_hwstate(vcpu); - -@@ -587,7 +587,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) - local_irq_enable(); - kvm_timer_sync_hwstate(vcpu); - kvm_vgic_sync_hwstate(vcpu); -- preempt_enable(); -+ migrate_enable(); - continue; - } - -@@ -641,7 +641,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) - - kvm_vgic_sync_hwstate(vcpu); - -- preempt_enable(); -+ migrate_enable(); - - ret = handle_exit(vcpu, run, ret); - } -diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c -index 08148c4..c2b1315 100644 ---- a/arch/arm/kvm/psci.c -+++ b/arch/arm/kvm/psci.c -@@ -70,7 +70,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) - { - struct kvm *kvm = source_vcpu->kvm; - struct kvm_vcpu *vcpu = NULL; -- struct swait_head *wq; -+ struct swait_queue_head *wq; - unsigned long cpu_id; - unsigned long context_id; - phys_addr_t target_pc; -@@ -119,7 +119,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) - smp_mb(); /* Make sure the above is visible */ - - wq = kvm_arch_vcpu_wq(vcpu); -- swait_wake_interruptible(wq); -+ swake_up(wq); - - return PSCI_RET_SUCCESS; - } -diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig -index 28656c2..3f50130 100644 ---- a/arch/arm/mach-at91/Kconfig -+++ b/arch/arm/mach-at91/Kconfig -@@ -99,6 +99,7 @@ config HAVE_AT91_USB_CLK - config COMMON_CLK_AT91 - bool - select COMMON_CLK -+ select MFD_SYSCON - - config HAVE_AT91_SMD - bool -diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c -index c1a7c6c..63b4fa2 100644 ---- a/arch/arm/mach-at91/at91rm9200.c -+++ b/arch/arm/mach-at91/at91rm9200.c -@@ -12,7 +12,6 @@ - #include - - #include --#include - - #include "generic.h" - #include "soc.h" -@@ -33,7 +32,6 @@ static void __init at91rm9200_dt_device_init(void) - - of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); - -- arm_pm_idle = at91rm9200_idle; - at91rm9200_pm_init(); - } - -diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c -index 7eb64f7..cada2a6 100644 ---- a/arch/arm/mach-at91/at91sam9.c -+++ b/arch/arm/mach-at91/at91sam9.c -@@ -62,8 +62,6 @@ static void __init at91sam9_common_init(void) - soc_dev = soc_device_to_device(soc); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); -- -- arm_pm_idle = at91sam9_idle; - } - - static void __init at91sam9_dt_device_init(void) -diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h -index b0fa7dc..28ca57a 100644 ---- a/arch/arm/mach-at91/generic.h -+++ b/arch/arm/mach-at91/generic.h -@@ -11,27 +11,18 @@ - #ifndef _AT91_GENERIC_H - #define _AT91_GENERIC_H - --#include --#include -- -- /* Map io */ --extern void __init at91_map_io(void); --extern void __init at91_alt_map_io(void); -- --/* idle */ --extern void at91rm9200_idle(void); --extern void at91sam9_idle(void); -- - #ifdef CONFIG_PM - extern void __init at91rm9200_pm_init(void); - extern void __init at91sam9260_pm_init(void); - extern void __init at91sam9g45_pm_init(void); - extern void __init at91sam9x5_pm_init(void); -+extern void __init sama5_pm_init(void); - #else - static inline void __init at91rm9200_pm_init(void) { } - static inline void __init at91sam9260_pm_init(void) { } - static inline void __init at91sam9g45_pm_init(void) { } - static inline void __init at91sam9x5_pm_init(void) { } -+static inline void __init sama5_pm_init(void) { } - #endif - - #endif /* _AT91_GENERIC_H */ -diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c -index 23726fb3..f062701 100644 ---- a/arch/arm/mach-at91/pm.c -+++ b/arch/arm/mach-at91/pm.c -@@ -31,10 +31,13 @@ - #include - #include - #include -+#include - - #include "generic.h" - #include "pm.h" - -+static void __iomem *pmc; -+ - /* - * FIXME: this is needed to communicate between the pinctrl driver and - * the PM implementation in the machine. Possibly part of the PM -@@ -87,7 +90,7 @@ static int at91_pm_verify_clocks(void) - unsigned long scsr; - int i; - -- scsr = at91_pmc_read(AT91_PMC_SCSR); -+ scsr = readl(pmc + AT91_PMC_SCSR); - - /* USB must not be using PLLB */ - if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { -@@ -101,8 +104,7 @@ static int at91_pm_verify_clocks(void) - - if ((scsr & (AT91_PMC_PCK0 << i)) == 0) - continue; -- -- css = at91_pmc_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; -+ css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; - if (css != AT91_PMC_CSS_SLOW) { - pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); - return 0; -@@ -145,8 +147,8 @@ static void at91_pm_suspend(suspend_state_t state) - flush_cache_all(); - outer_disable(); - -- at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], -- at91_ramc_base[1], pm_data); -+ at91_suspend_sram_fn(pmc, at91_ramc_base[0], -+ at91_ramc_base[1], pm_data); - - outer_resume(); - } -@@ -353,6 +355,21 @@ static __init void at91_dt_ramc(void) - at91_pm_set_standby(standby); - } - -+void at91rm9200_idle(void) -+{ -+ /* -+ * Disable the processor clock. The processor will be automatically -+ * re-enabled by an interrupt or by a reset. -+ */ -+ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); -+} -+ -+void at91sam9_idle(void) -+{ -+ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); -+ cpu_do_idle(); -+} -+ - static void __init at91_pm_sram_init(void) - { - struct gen_pool *sram_pool; -@@ -399,13 +416,36 @@ static void __init at91_pm_sram_init(void) - &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); - } - --static void __init at91_pm_init(void) -+static const struct of_device_id atmel_pmc_ids[] __initconst = { -+ { .compatible = "atmel,at91rm9200-pmc" }, -+ { .compatible = "atmel,at91sam9260-pmc" }, -+ { .compatible = "atmel,at91sam9g45-pmc" }, -+ { .compatible = "atmel,at91sam9n12-pmc" }, -+ { .compatible = "atmel,at91sam9x5-pmc" }, -+ { .compatible = "atmel,sama5d3-pmc" }, -+ { .compatible = "atmel,sama5d2-pmc" }, -+ { /* sentinel */ }, -+}; -+ -+static void __init at91_pm_init(void (*pm_idle)(void)) - { -- at91_pm_sram_init(); -+ struct device_node *pmc_np; - - if (at91_cpuidle_device.dev.platform_data) - platform_device_register(&at91_cpuidle_device); - -+ pmc_np = of_find_matching_node(NULL, atmel_pmc_ids); -+ pmc = of_iomap(pmc_np, 0); -+ if (!pmc) { -+ pr_err("AT91: PM not supported, PMC not found\n"); -+ return; -+ } -+ -+ if (pm_idle) -+ arm_pm_idle = pm_idle; -+ -+ at91_pm_sram_init(); -+ - if (at91_suspend_sram_fn) - suspend_set_ops(&at91_pm_ops); - else -@@ -424,7 +464,7 @@ void __init at91rm9200_pm_init(void) - at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; - at91_pm_data.memctrl = AT91_MEMCTRL_MC; - -- at91_pm_init(); -+ at91_pm_init(at91rm9200_idle); - } - - void __init at91sam9260_pm_init(void) -@@ -432,7 +472,7 @@ void __init at91sam9260_pm_init(void) - at91_dt_ramc(); - at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; -- return at91_pm_init(); -+ at91_pm_init(at91sam9_idle); - } - - void __init at91sam9g45_pm_init(void) -@@ -440,7 +480,7 @@ void __init at91sam9g45_pm_init(void) - at91_dt_ramc(); - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; - at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; -- return at91_pm_init(); -+ at91_pm_init(at91sam9_idle); - } - - void __init at91sam9x5_pm_init(void) -@@ -448,5 +488,13 @@ void __init at91sam9x5_pm_init(void) - at91_dt_ramc(); - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; - at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; -- return at91_pm_init(); -+ at91_pm_init(at91sam9_idle); -+} -+ -+void __init sama5_pm_init(void) -+{ -+ at91_dt_ramc(); -+ at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; -+ at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; -+ at91_pm_init(NULL); - } -diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c -index d9cf679..df8fdf1 100644 ---- a/arch/arm/mach-at91/sama5.c -+++ b/arch/arm/mach-at91/sama5.c -@@ -51,7 +51,7 @@ static void __init sama5_dt_device_init(void) - soc_dev = soc_device_to_device(soc); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); -- at91sam9x5_pm_init(); -+ sama5_pm_init(); - } - - static const char *const sama5_dt_board_compat[] __initconst = { -diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c -index 8aee3ae..c1492ba 100644 ---- a/arch/arm64/kernel/debug-monitors.c -+++ b/arch/arm64/kernel/debug-monitors.c -@@ -186,20 +186,21 @@ static void clear_regs_spsr_ss(struct pt_regs *regs) - - /* EL1 Single Step Handler hooks */ - static LIST_HEAD(step_hook); --static DEFINE_RWLOCK(step_hook_lock); -+static DEFINE_SPINLOCK(step_hook_lock); - - void register_step_hook(struct step_hook *hook) - { -- write_lock(&step_hook_lock); -- list_add(&hook->node, &step_hook); -- write_unlock(&step_hook_lock); -+ spin_lock(&step_hook_lock); -+ list_add_rcu(&hook->node, &step_hook); -+ spin_unlock(&step_hook_lock); - } - - void unregister_step_hook(struct step_hook *hook) - { -- write_lock(&step_hook_lock); -- list_del(&hook->node); -- write_unlock(&step_hook_lock); -+ spin_lock(&step_hook_lock); -+ list_del_rcu(&hook->node); -+ spin_unlock(&step_hook_lock); -+ synchronize_rcu(); - } - - /* -@@ -213,15 +214,15 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr) - struct step_hook *hook; - int retval = DBG_HOOK_ERROR; - -- read_lock(&step_hook_lock); -+ rcu_read_lock(); - -- list_for_each_entry(hook, &step_hook, node) { -+ list_for_each_entry_rcu(hook, &step_hook, node) { - retval = hook->fn(regs, esr); - if (retval == DBG_HOOK_HANDLED) - break; - } - -- read_unlock(&step_hook_lock); -+ rcu_read_unlock(); - - return retval; - } -diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c -index 2683d04..8a11329 100644 ---- a/arch/mips/kvm/mips.c -+++ b/arch/mips/kvm/mips.c -@@ -445,8 +445,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, - - dvcpu->arch.wait = 0; - -- if (waitqueue_active(&dvcpu->wq)) -- wake_up_interruptible(&dvcpu->wq); -+ if (swait_active(&dvcpu->wq)) -+ swake_up(&dvcpu->wq); - - return 0; - } -@@ -1174,8 +1174,8 @@ static void kvm_mips_comparecount_func(unsigned long data) - kvm_mips_callbacks->queue_timer_int(vcpu); - - vcpu->arch.wait = 0; -- if (waitqueue_active(&vcpu->wq)) -- wake_up_interruptible(&vcpu->wq); -+ if (swait_active(&vcpu->wq)) -+ swake_up(&vcpu->wq); - } - - /* low level hrtimer wake routine */ -diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h -index b439518..f8673ff 100644 ---- a/arch/powerpc/include/asm/kvm_host.h -+++ b/arch/powerpc/include/asm/kvm_host.h -@@ -286,7 +286,7 @@ struct kvmppc_vcore { - struct list_head runnable_threads; - struct list_head preempt_list; - spinlock_t lock; -- struct swait_head wq; -+ struct swait_queue_head wq; - spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */ - u64 stolen_tb; - u64 preempt_tb; -@@ -626,7 +626,7 @@ struct kvm_vcpu_arch { - u8 prodded; - u32 last_inst; - -- struct swait_head *wqp; -+ struct swait_queue_head *wqp; - struct kvmppc_vcore *vcore; - int ret; - int trap; -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 32be32b..df34a64 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -114,11 +114,11 @@ static bool kvmppc_ipi_thread(int cpu) - static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) - { - int cpu; -- struct swait_head *wqp; -+ struct swait_queue_head *wqp; - - wqp = kvm_arch_vcpu_wq(vcpu); -- if (swaitqueue_active(wqp)) { -- swait_wake_interruptible(wqp); -+ if (swait_active(wqp)) { -+ swake_up(wqp); - ++vcpu->stat.halt_wakeup; - } - -@@ -707,8 +707,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) - tvcpu->arch.prodded = 1; - smp_mb(); - if (vcpu->arch.ceded) { -- if (swaitqueue_active(&vcpu->wq)) { -- swait_wake_interruptible(&vcpu->wq); -+ if (swait_active(&vcpu->wq)) { -+ swake_up(&vcpu->wq); - vcpu->stat.halt_wakeup++; - } - } -@@ -1447,7 +1447,7 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core) - INIT_LIST_HEAD(&vcore->runnable_threads); - spin_lock_init(&vcore->lock); - spin_lock_init(&vcore->stoltb_lock); -- init_swait_head(&vcore->wq); -+ init_swait_queue_head(&vcore->wq); - vcore->preempt_tb = TB_NIL; - vcore->lpcr = kvm->arch.lpcr; - vcore->first_vcpuid = core * threads_per_subcore; -@@ -2519,9 +2519,9 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) - { - struct kvm_vcpu *vcpu; - int do_sleep = 1; -- DEFINE_SWAITER(wait); -+ DECLARE_SWAITQUEUE(wait); - -- swait_prepare(&vc->wq, &wait, TASK_INTERRUPTIBLE); -+ prepare_to_swait(&vc->wq, &wait, TASK_INTERRUPTIBLE); - - /* - * Check one last time for pending exceptions and ceded state after -@@ -2535,7 +2535,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) - } - - if (!do_sleep) { -- swait_finish(&vc->wq, &wait); -+ finish_swait(&vc->wq, &wait); - return; - } - -@@ -2543,7 +2543,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) - trace_kvmppc_vcore_blocked(vc, 0); - spin_unlock(&vc->lock); - schedule(); -- swait_finish(&vc->wq, &wait); -+ finish_swait(&vc->wq, &wait); - spin_lock(&vc->lock); - vc->vcore_state = VCORE_INACTIVE; - trace_kvmppc_vcore_blocked(vc, 1); -@@ -2599,7 +2599,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) - kvmppc_start_thread(vcpu, vc); - trace_kvm_guest_enter(vcpu); - } else if (vc->vcore_state == VCORE_SLEEPING) { -- swait_wake(&vc->wq); -+ swake_up(&vc->wq); - } - - } -diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h -index 2a84c76..bbdc539 100644 ---- a/arch/s390/include/asm/kvm_host.h -+++ b/arch/s390/include/asm/kvm_host.h -@@ -427,7 +427,7 @@ struct kvm_s390_irq_payload { - struct kvm_s390_local_interrupt { - spinlock_t lock; - struct kvm_s390_float_interrupt *float_int; -- struct swait_head *wq; -+ struct swait_queue_head *wq; - atomic_t *cpuflags; - DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS); - struct kvm_s390_irq_payload irq; -diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c -index 8b4516b..cc862c4 100644 ---- a/arch/s390/kvm/interrupt.c -+++ b/arch/s390/kvm/interrupt.c -@@ -868,13 +868,13 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) - - void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) - { -- if (swaitqueue_active(&vcpu->wq)) { -+ if (swait_active(&vcpu->wq)) { - /* - * The vcpu gave up the cpu voluntarily, mark it as a good - * yield-candidate. - */ - vcpu->preempted = true; -- swait_wake_interruptible(&vcpu->wq); -+ swake_up(&vcpu->wq); - vcpu->stat.halt_wakeup++; - } - } -diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c -index 47190bd..8079508 100644 ---- a/arch/x86/kernel/kvm.c -+++ b/arch/x86/kernel/kvm.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -91,14 +92,14 @@ static void kvm_io_delay(void) - - struct kvm_task_sleep_node { - struct hlist_node link; -- wait_queue_head_t wq; -+ struct swait_queue_head wq; - u32 token; - int cpu; - bool halted; - }; - - static struct kvm_task_sleep_head { -- spinlock_t lock; -+ raw_spinlock_t lock; - struct hlist_head list; - } async_pf_sleepers[KVM_TASK_SLEEP_HASHSIZE]; - -@@ -122,17 +123,17 @@ void kvm_async_pf_task_wait(u32 token) - u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS); - struct kvm_task_sleep_head *b = &async_pf_sleepers[key]; - struct kvm_task_sleep_node n, *e; -- DEFINE_WAIT(wait); -+ DECLARE_SWAITQUEUE(wait); - - rcu_irq_enter(); - -- spin_lock(&b->lock); -+ raw_spin_lock(&b->lock); - e = _find_apf_task(b, token); - if (e) { - /* dummy entry exist -> wake up was delivered ahead of PF */ - hlist_del(&e->link); - kfree(e); -- spin_unlock(&b->lock); -+ raw_spin_unlock(&b->lock); - - rcu_irq_exit(); - return; -@@ -141,13 +142,13 @@ void kvm_async_pf_task_wait(u32 token) - n.token = token; - n.cpu = smp_processor_id(); - n.halted = is_idle_task(current) || preempt_count() > 1; -- init_waitqueue_head(&n.wq); -+ init_swait_queue_head(&n.wq); - hlist_add_head(&n.link, &b->list); -- spin_unlock(&b->lock); -+ raw_spin_unlock(&b->lock); - - for (;;) { - if (!n.halted) -- prepare_to_wait(&n.wq, &wait, TASK_UNINTERRUPTIBLE); -+ prepare_to_swait(&n.wq, &wait, TASK_UNINTERRUPTIBLE); - if (hlist_unhashed(&n.link)) - break; - -@@ -166,7 +167,7 @@ void kvm_async_pf_task_wait(u32 token) - } - } - if (!n.halted) -- finish_wait(&n.wq, &wait); -+ finish_swait(&n.wq, &wait); - - rcu_irq_exit(); - return; -@@ -178,8 +179,8 @@ static void apf_task_wake_one(struct kvm_task_sleep_node *n) - hlist_del_init(&n->link); - if (n->halted) - smp_send_reschedule(n->cpu); -- else if (waitqueue_active(&n->wq)) -- wake_up(&n->wq); -+ else if (swait_active(&n->wq)) -+ swake_up(&n->wq); - } - - static void apf_task_wake_all(void) -@@ -189,14 +190,14 @@ static void apf_task_wake_all(void) - for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++) { - struct hlist_node *p, *next; - struct kvm_task_sleep_head *b = &async_pf_sleepers[i]; -- spin_lock(&b->lock); -+ raw_spin_lock(&b->lock); - hlist_for_each_safe(p, next, &b->list) { - struct kvm_task_sleep_node *n = - hlist_entry(p, typeof(*n), link); - if (n->cpu == smp_processor_id()) - apf_task_wake_one(n); - } -- spin_unlock(&b->lock); -+ raw_spin_unlock(&b->lock); - } - } - -@@ -212,7 +213,7 @@ void kvm_async_pf_task_wake(u32 token) - } - - again: -- spin_lock(&b->lock); -+ raw_spin_lock(&b->lock); - n = _find_apf_task(b, token); - if (!n) { - /* -@@ -225,17 +226,17 @@ void kvm_async_pf_task_wake(u32 token) - * Allocation failed! Busy wait while other cpu - * handles async PF. - */ -- spin_unlock(&b->lock); -+ raw_spin_unlock(&b->lock); - cpu_relax(); - goto again; - } - n->token = token; - n->cpu = smp_processor_id(); -- init_waitqueue_head(&n->wq); -+ init_swait_queue_head(&n->wq); - hlist_add_head(&n->link, &b->list); - } else - apf_task_wake_one(n); -- spin_unlock(&b->lock); -+ raw_spin_unlock(&b->lock); - return; - } - EXPORT_SYMBOL_GPL(kvm_async_pf_task_wake); -@@ -486,7 +487,7 @@ void __init kvm_guest_init(void) - paravirt_ops_setup(); - register_reboot_notifier(&kvm_pv_reboot_nb); - for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++) -- spin_lock_init(&async_pf_sleepers[i].lock); -+ raw_spin_lock_init(&async_pf_sleepers[i].lock); - if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF)) - x86_init.irqs.trap_init = kvm_apf_trap_init; - -diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c -index 906a1ec..20d9e9f 100644 ---- a/arch/x86/kvm/lapic.c -+++ b/arch/x86/kvm/lapic.c -@@ -1195,7 +1195,7 @@ static void apic_update_lvtt(struct kvm_lapic *apic) - static void apic_timer_expired(struct kvm_lapic *apic) - { - struct kvm_vcpu *vcpu = apic->vcpu; -- struct swait_head *q = &vcpu->wq; -+ struct swait_queue_head *q = &vcpu->wq; - struct kvm_timer *ktimer = &apic->lapic_timer; - - if (atomic_read(&apic->lapic_timer.pending)) -@@ -1204,8 +1204,8 @@ static void apic_timer_expired(struct kvm_lapic *apic) - atomic_inc(&apic->lapic_timer.pending); - kvm_set_pending_timer(vcpu); - -- if (swaitqueue_active(q)) -- swait_wake_interruptible(q); -+ if (swait_active(q)) -+ swake_up(q); - - if (apic_lvtt_tscdeadline(apic)) - ktimer->expired_tscdeadline = ktimer->tscdeadline; -diff --git a/block/blk-core.c b/block/blk-core.c -index 4c8cefd..2f7afb9 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -680,7 +680,7 @@ static void blk_queue_usage_counter_release(struct percpu_ref *ref) - struct request_queue *q = - container_of(ref, struct request_queue, q_usage_counter); - -- swait_wake_all(&q->mq_freeze_wq); -+ swake_up_all(&q->mq_freeze_wq); - } - - struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) -@@ -742,7 +742,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) - q->bypass_depth = 1; - __set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags); - -- init_swait_head(&q->mq_freeze_wq); -+ init_swait_queue_head(&q->mq_freeze_wq); - - /* - * Init percpu_ref in atomic mode so that it's faster to shutdown. -diff --git a/block/blk-mq.c b/block/blk-mq.c -index 3c70813..7cdf19e 100644 ---- a/block/blk-mq.c -+++ b/block/blk-mq.c -@@ -130,7 +130,7 @@ void blk_mq_unfreeze_queue(struct request_queue *q) - WARN_ON_ONCE(freeze_depth < 0); - if (!freeze_depth) { - percpu_ref_reinit(&q->q_usage_counter); -- swait_wake_all(&q->mq_freeze_wq); -+ swake_up_all(&q->mq_freeze_wq); - } - } - EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); -@@ -149,7 +149,7 @@ void blk_mq_wake_waiters(struct request_queue *q) - * dying, we need to ensure that processes currently waiting on - * the queue are notified as well. - */ -- swait_wake_all(&q->mq_freeze_wq); -+ swake_up_all(&q->mq_freeze_wq); - } - - bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx) -diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c -index 370c2f7..65e0b37 100644 ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -520,6 +520,8 @@ static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) - goto out_error; - } - -+ zram_meta_init_table_locks(meta, disksize); -+ - return meta; - - out_error: -@@ -568,12 +570,12 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) - unsigned long handle; - size_t size; - -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - handle = meta->table[index].handle; - size = zram_get_obj_size(meta, index); - - if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - clear_page(mem); - return 0; - } -@@ -584,7 +586,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) - else - ret = zcomp_decompress(zram->comp, cmem, size, mem); - zs_unmap_object(meta->mem_pool, handle); -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - - /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret)) { -@@ -604,14 +606,14 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, - struct zram_meta *meta = zram->meta; - page = bvec->bv_page; - -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - if (unlikely(!meta->table[index].handle) || - zram_test_flag(meta, index, ZRAM_ZERO)) { -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - handle_zero_page(bvec); - return 0; - } -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - - if (is_partial_io(bvec)) - /* Use a temporary buffer to decompress the page */ -@@ -689,10 +691,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, - if (user_mem) - kunmap_atomic(user_mem); - /* Free memory associated with this sector now. */ -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - zram_free_page(zram, index); - zram_set_flag(meta, index, ZRAM_ZERO); -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - - atomic64_inc(&zram->stats.zero_pages); - ret = 0; -@@ -752,12 +754,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, - * Free memory associated with this sector - * before overwriting unused sectors. - */ -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - zram_free_page(zram, index); - - meta->table[index].handle = handle; - zram_set_obj_size(meta, index, clen); -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - - /* Update stats */ - atomic64_add(clen, &zram->stats.compr_data_size); -@@ -800,9 +802,9 @@ static void zram_bio_discard(struct zram *zram, u32 index, - } - - while (n >= PAGE_SIZE) { -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - zram_free_page(zram, index); -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - atomic64_inc(&zram->stats.notify_free); - index++; - n -= PAGE_SIZE; -@@ -928,9 +930,9 @@ static void zram_slot_free_notify(struct block_device *bdev, - zram = bdev->bd_disk->private_data; - meta = zram->meta; - -- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_lock_table(&meta->table[index]); - zram_free_page(zram, index); -- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); -+ zram_unlock_table(&meta->table[index]); - atomic64_inc(&zram->stats.notify_free); - } - -diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h -index 8e92339..1e4a3c6 100644 ---- a/drivers/block/zram/zram_drv.h -+++ b/drivers/block/zram/zram_drv.h -@@ -72,6 +72,9 @@ enum zram_pageflags { - struct zram_table_entry { - unsigned long handle; - unsigned long value; -+#ifdef CONFIG_PREEMPT_RT_BASE -+ spinlock_t lock; -+#endif - }; - - struct zram_stats { -@@ -119,4 +122,42 @@ struct zram { - */ - bool claim; /* Protected by bdev->bd_mutex */ - }; -+ -+#ifndef CONFIG_PREEMPT_RT_BASE -+static inline void zram_lock_table(struct zram_table_entry *table) -+{ -+ bit_spin_lock(ZRAM_ACCESS, &table->value); -+} -+ -+static inline void zram_unlock_table(struct zram_table_entry *table) -+{ -+ bit_spin_unlock(ZRAM_ACCESS, &table->value); -+} -+ -+static inline void zram_meta_init_locks(struct zram_meta *meta, u64 disksize) { } -+#else /* CONFIG_PREEMPT_RT_BASE */ -+static inline void zram_lock_table(struct zram_table_entry *table) -+{ -+ spin_lock(&table->lock); -+ __set_bit(ZRAM_ACCESS, &table->value); -+} -+ -+static inline void zram_unlock_table(struct zram_table_entry *table) -+{ -+ __clear_bit(ZRAM_ACCESS, &table->value); -+ spin_unlock(&table->lock); -+} -+ -+static inline void zram_meta_init_table_locks(struct zram_meta *meta, u64 disksize) -+{ -+ size_t num_pages = disksize >> PAGE_SHIFT; -+ size_t index; -+ -+ for (index = 0; index < num_pages; index++) { -+ spinlock_t *lock = &meta->table[index].lock; -+ spin_lock_init(lock); -+ } -+} -+#endif /* CONFIG_PREEMPT_RT_BASE */ -+ - #endif -diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c -index abc8094..4ad3298 100644 ---- a/drivers/clk/at91/clk-generated.c -+++ b/drivers/clk/at91/clk-generated.c -@@ -15,8 +15,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -28,8 +28,9 @@ - - struct clk_generated { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - struct clk_range range; -+ spinlock_t *lock; - u32 id; - u32 gckdiv; - u8 parent_id; -@@ -41,49 +42,52 @@ struct clk_generated { - static int clk_generated_enable(struct clk_hw *hw) - { - struct clk_generated *gck = to_clk_generated(hw); -- struct at91_pmc *pmc = gck->pmc; -- u32 tmp; -+ unsigned long flags; - - pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n", - __func__, gck->gckdiv, gck->parent_id); - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR) & -- ~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK); -- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id) -- | AT91_PMC_PCR_CMD -- | AT91_PMC_PCR_GCKDIV(gck->gckdiv) -- | AT91_PMC_PCR_GCKEN); -- pmc_unlock(pmc); -+ spin_lock_irqsave(gck->lock, flags); -+ regmap_write(gck->regmap, AT91_PMC_PCR, -+ (gck->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_update_bits(gck->regmap, AT91_PMC_PCR, -+ AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK | -+ AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, -+ AT91_PMC_PCR_GCKCSS(gck->parent_id) | -+ AT91_PMC_PCR_CMD | -+ AT91_PMC_PCR_GCKDIV(gck->gckdiv) | -+ AT91_PMC_PCR_GCKEN); -+ spin_unlock_irqrestore(gck->lock, flags); - return 0; - } - - static void clk_generated_disable(struct clk_hw *hw) - { - struct clk_generated *gck = to_clk_generated(hw); -- struct at91_pmc *pmc = gck->pmc; -- u32 tmp; -- -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN; -- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD); -- pmc_unlock(pmc); -+ unsigned long flags; -+ -+ spin_lock_irqsave(gck->lock, flags); -+ regmap_write(gck->regmap, AT91_PMC_PCR, -+ (gck->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_update_bits(gck->regmap, AT91_PMC_PCR, -+ AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, -+ AT91_PMC_PCR_CMD); -+ spin_unlock_irqrestore(gck->lock, flags); - } - - static int clk_generated_is_enabled(struct clk_hw *hw) - { - struct clk_generated *gck = to_clk_generated(hw); -- struct at91_pmc *pmc = gck->pmc; -- int ret; -+ unsigned long flags; -+ unsigned int status; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); -- ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN); -- pmc_unlock(pmc); -+ spin_lock_irqsave(gck->lock, flags); -+ regmap_write(gck->regmap, AT91_PMC_PCR, -+ (gck->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_read(gck->regmap, AT91_PMC_PCR, &status); -+ spin_unlock_irqrestore(gck->lock, flags); - -- return ret; -+ return status & AT91_PMC_PCR_GCKEN ? 1 : 0; - } - - static unsigned long -@@ -214,13 +218,14 @@ static const struct clk_ops generated_ops = { - */ - static void clk_generated_startup(struct clk_generated *gck) - { -- struct at91_pmc *pmc = gck->pmc; - u32 tmp; -+ unsigned long flags; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR); -- pmc_unlock(pmc); -+ spin_lock_irqsave(gck->lock, flags); -+ regmap_write(gck->regmap, AT91_PMC_PCR, -+ (gck->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_read(gck->regmap, AT91_PMC_PCR, &tmp); -+ spin_unlock_irqrestore(gck->lock, flags); - - gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK) - >> AT91_PMC_PCR_GCKCSS_OFFSET; -@@ -229,8 +234,8 @@ static void clk_generated_startup(struct clk_generated *gck) - } - - static struct clk * __init --at91_clk_register_generated(struct at91_pmc *pmc, const char *name, -- const char **parent_names, u8 num_parents, -+at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const char -+ *name, const char **parent_names, u8 num_parents, - u8 id, const struct clk_range *range) - { - struct clk_generated *gck; -@@ -249,7 +254,8 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, - - gck->id = id; - gck->hw.init = &init; -- gck->pmc = pmc; -+ gck->regmap = regmap; -+ gck->lock = lock; - gck->range = *range; - - clk = clk_register(NULL, &gck->hw); -@@ -261,8 +267,7 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, - return clk; - } - --void __init of_sama5d2_clk_generated_setup(struct device_node *np, -- struct at91_pmc *pmc) -+void __init of_sama5d2_clk_generated_setup(struct device_node *np) - { - int num; - u32 id; -@@ -272,6 +277,7 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, - const char *parent_names[GENERATED_SOURCE_MAX]; - struct device_node *gcknp; - struct clk_range range = CLK_RANGE(0, 0); -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > GENERATED_SOURCE_MAX) -@@ -283,6 +289,10 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, - if (!num || num > PERIPHERAL_MAX) - return; - -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ - for_each_child_of_node(np, gcknp) { - if (of_property_read_u32(gcknp, "reg", &id)) - continue; -@@ -296,11 +306,14 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, - of_at91_get_clk_range(gcknp, "atmel,clk-output-range", - &range); - -- clk = at91_clk_register_generated(pmc, name, parent_names, -- num_parents, id, &range); -+ clk = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, -+ parent_names, num_parents, -+ id, &range); - if (IS_ERR(clk)) - continue; - - of_clk_add_provider(gcknp, of_clk_src_simple_get, clk); - } - } -+CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated", -+ of_sama5d2_clk_generated_setup); -diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c -index 61566bc..819f584 100644 ---- a/drivers/clk/at91/clk-h32mx.c -+++ b/drivers/clk/at91/clk-h32mx.c -@@ -15,15 +15,9 @@ - #include - #include - #include --#include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -31,7 +25,7 @@ - - struct clk_sama5d4_h32mx { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - #define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw) -@@ -40,8 +34,10 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); -+ unsigned int mckr; - -- if (pmc_read(h32mxclk->pmc, AT91_PMC_MCKR) & AT91_PMC_H32MXDIV) -+ regmap_read(h32mxclk->regmap, AT91_PMC_MCKR, &mckr); -+ if (mckr & AT91_PMC_H32MXDIV) - return parent_rate / 2; - - if (parent_rate > H32MX_MAX_FREQ) -@@ -70,18 +66,16 @@ static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { - struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); -- struct at91_pmc *pmc = h32mxclk->pmc; -- u32 tmp; -+ u32 mckr = 0; - - if (parent_rate != rate && (parent_rate / 2) != rate) - return -EINVAL; - -- pmc_lock(pmc); -- tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_H32MXDIV; - if ((parent_rate / 2) == rate) -- tmp |= AT91_PMC_H32MXDIV; -- pmc_write(pmc, AT91_PMC_MCKR, tmp); -- pmc_unlock(pmc); -+ mckr = AT91_PMC_H32MXDIV; -+ -+ regmap_update_bits(h32mxclk->regmap, AT91_PMC_MCKR, -+ AT91_PMC_H32MXDIV, mckr); - - return 0; - } -@@ -92,14 +86,18 @@ static const struct clk_ops h32mx_ops = { - .set_rate = clk_sama5d4_h32mx_set_rate, - }; - --void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) - { - struct clk_sama5d4_h32mx *h32mxclk; - struct clk_init_data init; - const char *parent_name; -+ struct regmap *regmap; - struct clk *clk; - -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ - h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL); - if (!h32mxclk) - return; -@@ -113,7 +111,7 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, - init.flags = CLK_SET_RATE_GATE; - - h32mxclk->hw.init = &init; -- h32mxclk->pmc = pmc; -+ h32mxclk->regmap = regmap; - - clk = clk_register(NULL, &h32mxclk->hw); - if (!clk) { -@@ -123,3 +121,5 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx", -+ of_sama5d4_clk_h32mx_setup); -diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c -index fd7247d..4bfc94d 100644 ---- a/drivers/clk/at91/clk-main.c -+++ b/drivers/clk/at91/clk-main.c -@@ -13,13 +13,8 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -34,18 +29,14 @@ - - struct clk_main_osc { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - }; - - #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw) - - struct clk_main_rc_osc { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - unsigned long frequency; - unsigned long accuracy; - }; -@@ -54,51 +45,47 @@ struct clk_main_rc_osc { - - struct clk_rm9200_main { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw) - - struct clk_sam9x5_main { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - u8 parent; - }; - - #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw) - --static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id) -+static inline bool clk_main_osc_ready(struct regmap *regmap) - { -- struct clk_main_osc *osc = dev_id; -+ unsigned int status; - -- wake_up(&osc->wait); -- disable_irq_nosync(osc->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & AT91_PMC_MOSCS; - } - - static int clk_main_osc_prepare(struct clk_hw *hw) - { - struct clk_main_osc *osc = to_clk_main_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -+ struct regmap *regmap = osc->regmap; - u32 tmp; - -- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; -+ regmap_read(regmap, AT91_CKGR_MOR, &tmp); -+ tmp &= ~MOR_KEY_MASK; -+ - if (tmp & AT91_PMC_OSCBYPASS) - return 0; - - if (!(tmp & AT91_PMC_MOSCEN)) { - tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY; -- pmc_write(pmc, AT91_CKGR_MOR, tmp); -+ regmap_write(regmap, AT91_CKGR_MOR, tmp); - } - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { -- enable_irq(osc->irq); -- wait_event(osc->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); -- } -+ while (!clk_main_osc_ready(regmap)) -+ cpu_relax(); - - return 0; - } -@@ -106,9 +93,10 @@ static int clk_main_osc_prepare(struct clk_hw *hw) - static void clk_main_osc_unprepare(struct clk_hw *hw) - { - struct clk_main_osc *osc = to_clk_main_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); -+ struct regmap *regmap = osc->regmap; -+ u32 tmp; - -+ regmap_read(regmap, AT91_CKGR_MOR, &tmp); - if (tmp & AT91_PMC_OSCBYPASS) - return; - -@@ -116,20 +104,22 @@ static void clk_main_osc_unprepare(struct clk_hw *hw) - return; - - tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); -- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); -+ regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); - } - - static int clk_main_osc_is_prepared(struct clk_hw *hw) - { - struct clk_main_osc *osc = to_clk_main_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); -+ struct regmap *regmap = osc->regmap; -+ u32 tmp, status; - -+ regmap_read(regmap, AT91_CKGR_MOR, &tmp); - if (tmp & AT91_PMC_OSCBYPASS) - return 1; - -- return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) && -- (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN)); -+ regmap_read(regmap, AT91_PMC_SR, &status); -+ -+ return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN); - } - - static const struct clk_ops main_osc_ops = { -@@ -139,18 +129,16 @@ static const struct clk_ops main_osc_ops = { - }; - - static struct clk * __init --at91_clk_register_main_osc(struct at91_pmc *pmc, -- unsigned int irq, -+at91_clk_register_main_osc(struct regmap *regmap, - const char *name, - const char *parent_name, - bool bypass) - { -- int ret; - struct clk_main_osc *osc; - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !irq || !name || !parent_name) -+ if (!name || !parent_name) - return ERR_PTR(-EINVAL); - - osc = kzalloc(sizeof(*osc), GFP_KERNEL); -@@ -164,85 +152,70 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, - init.flags = CLK_IGNORE_UNUSED; - - osc->hw.init = &init; -- osc->pmc = pmc; -- osc->irq = irq; -- -- init_waitqueue_head(&osc->wait); -- irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); -- ret = request_irq(osc->irq, clk_main_osc_irq_handler, -- IRQF_TRIGGER_HIGH, name, osc); -- if (ret) { -- kfree(osc); -- return ERR_PTR(ret); -- } -+ osc->regmap = regmap; - - if (bypass) -- pmc_write(pmc, AT91_CKGR_MOR, -- (pmc_read(pmc, AT91_CKGR_MOR) & -- ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) | -- AT91_PMC_OSCBYPASS | AT91_PMC_KEY); -+ regmap_update_bits(regmap, -+ AT91_CKGR_MOR, MOR_KEY_MASK | -+ AT91_PMC_MOSCEN, -+ AT91_PMC_OSCBYPASS | AT91_PMC_KEY); - - clk = clk_register(NULL, &osc->hw); -- if (IS_ERR(clk)) { -- free_irq(irq, osc); -+ if (IS_ERR(clk)) - kfree(osc); -- } - - return clk; - } - --void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np) - { - struct clk *clk; -- unsigned int irq; - const char *name = np->name; - const char *parent_name; -+ struct regmap *regmap; - bool bypass; - - of_property_read_string(np, "clock-output-names", &name); - bypass = of_property_read_bool(np, "atmel,osc-bypass"); - parent_name = of_clk_get_parent_name(np, 0); - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) - return; - -- clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass); -+ clk = at91_clk_register_main_osc(regmap, name, parent_name, bypass); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc", -+ of_at91rm9200_clk_main_osc_setup); - --static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id) -+static bool clk_main_rc_osc_ready(struct regmap *regmap) - { -- struct clk_main_rc_osc *osc = dev_id; -+ unsigned int status; - -- wake_up(&osc->wait); -- disable_irq_nosync(osc->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & AT91_PMC_MOSCRCS; - } - - static int clk_main_rc_osc_prepare(struct clk_hw *hw) - { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -- u32 tmp; -+ struct regmap *regmap = osc->regmap; -+ unsigned int mor; - -- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; -+ regmap_read(regmap, AT91_CKGR_MOR, &mor); - -- if (!(tmp & AT91_PMC_MOSCRCEN)) { -- tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY; -- pmc_write(pmc, AT91_CKGR_MOR, tmp); -- } -+ if (!(mor & AT91_PMC_MOSCRCEN)) -+ regmap_update_bits(regmap, AT91_CKGR_MOR, -+ MOR_KEY_MASK | AT91_PMC_MOSCRCEN, -+ AT91_PMC_MOSCRCEN | AT91_PMC_KEY); - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) { -- enable_irq(osc->irq); -- wait_event(osc->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS); -- } -+ while (!clk_main_rc_osc_ready(regmap)) -+ cpu_relax(); - - return 0; - } -@@ -250,23 +223,28 @@ static int clk_main_rc_osc_prepare(struct clk_hw *hw) - static void clk_main_rc_osc_unprepare(struct clk_hw *hw) - { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); -+ struct regmap *regmap = osc->regmap; -+ unsigned int mor; -+ -+ regmap_read(regmap, AT91_CKGR_MOR, &mor); - -- if (!(tmp & AT91_PMC_MOSCRCEN)) -+ if (!(mor & AT91_PMC_MOSCRCEN)) - return; - -- tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN); -- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); -+ regmap_update_bits(regmap, AT91_CKGR_MOR, -+ MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); - } - - static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) - { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); -- struct at91_pmc *pmc = osc->pmc; -+ struct regmap *regmap = osc->regmap; -+ unsigned int mor, status; - -- return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) && -- (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN)); -+ regmap_read(regmap, AT91_CKGR_MOR, &mor); -+ regmap_read(regmap, AT91_PMC_SR, &status); -+ -+ return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS); - } - - static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, -@@ -294,17 +272,15 @@ static const struct clk_ops main_rc_osc_ops = { - }; - - static struct clk * __init --at91_clk_register_main_rc_osc(struct at91_pmc *pmc, -- unsigned int irq, -+at91_clk_register_main_rc_osc(struct regmap *regmap, - const char *name, - u32 frequency, u32 accuracy) - { -- int ret; - struct clk_main_rc_osc *osc; - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !irq || !name || !frequency) -+ if (!name || !frequency) - return ERR_PTR(-EINVAL); - - osc = kzalloc(sizeof(*osc), GFP_KERNEL); -@@ -318,63 +294,53 @@ at91_clk_register_main_rc_osc(struct at91_pmc *pmc, - init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED; - - osc->hw.init = &init; -- osc->pmc = pmc; -- osc->irq = irq; -+ osc->regmap = regmap; - osc->frequency = frequency; - osc->accuracy = accuracy; - -- init_waitqueue_head(&osc->wait); -- irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); -- ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler, -- IRQF_TRIGGER_HIGH, name, osc); -- if (ret) -- return ERR_PTR(ret); -- - clk = clk_register(NULL, &osc->hw); -- if (IS_ERR(clk)) { -- free_irq(irq, osc); -+ if (IS_ERR(clk)) - kfree(osc); -- } - - return clk; - } - --void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np) - { - struct clk *clk; -- unsigned int irq; - u32 frequency = 0; - u32 accuracy = 0; - const char *name = np->name; -+ struct regmap *regmap; - - of_property_read_string(np, "clock-output-names", &name); - of_property_read_u32(np, "clock-frequency", &frequency); - of_property_read_u32(np, "clock-accuracy", &accuracy); - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) - return; - -- clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency, -- accuracy); -+ clk = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc", -+ of_at91sam9x5_clk_main_rc_osc_setup); - - --static int clk_main_probe_frequency(struct at91_pmc *pmc) -+static int clk_main_probe_frequency(struct regmap *regmap) - { - unsigned long prep_time, timeout; -- u32 tmp; -+ unsigned int mcfr; - - timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); - do { - prep_time = jiffies; -- tmp = pmc_read(pmc, AT91_CKGR_MCFR); -- if (tmp & AT91_PMC_MAINRDY) -+ regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); -+ if (mcfr & AT91_PMC_MAINRDY) - return 0; - usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); - } while (time_before(prep_time, timeout)); -@@ -382,34 +348,37 @@ static int clk_main_probe_frequency(struct at91_pmc *pmc) - return -ETIMEDOUT; - } - --static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc, -+static unsigned long clk_main_recalc_rate(struct regmap *regmap, - unsigned long parent_rate) - { -- u32 tmp; -+ unsigned int mcfr; - - if (parent_rate) - return parent_rate; - - pr_warn("Main crystal frequency not set, using approximate value\n"); -- tmp = pmc_read(pmc, AT91_CKGR_MCFR); -- if (!(tmp & AT91_PMC_MAINRDY)) -+ regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); -+ if (!(mcfr & AT91_PMC_MAINRDY)) - return 0; - -- return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; -+ return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; - } - - static int clk_rm9200_main_prepare(struct clk_hw *hw) - { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); - -- return clk_main_probe_frequency(clkmain->pmc); -+ return clk_main_probe_frequency(clkmain->regmap); - } - - static int clk_rm9200_main_is_prepared(struct clk_hw *hw) - { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); -+ unsigned int status; -+ -+ regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status); - -- return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY); -+ return status & AT91_PMC_MAINRDY ? 1 : 0; - } - - static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, -@@ -417,7 +386,7 @@ static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, - { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); - -- return clk_main_recalc_rate(clkmain->pmc, parent_rate); -+ return clk_main_recalc_rate(clkmain->regmap, parent_rate); - } - - static const struct clk_ops rm9200_main_ops = { -@@ -427,7 +396,7 @@ static const struct clk_ops rm9200_main_ops = { - }; - - static struct clk * __init --at91_clk_register_rm9200_main(struct at91_pmc *pmc, -+at91_clk_register_rm9200_main(struct regmap *regmap, - const char *name, - const char *parent_name) - { -@@ -435,7 +404,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !name) -+ if (!name) - return ERR_PTR(-EINVAL); - - if (!parent_name) -@@ -452,7 +421,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, - init.flags = 0; - - clkmain->hw.init = &init; -- clkmain->pmc = pmc; -+ clkmain->regmap = regmap; - - clk = clk_register(NULL, &clkmain->hw); - if (IS_ERR(clk)) -@@ -461,52 +430,54 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, - return clk; - } - --void __init of_at91rm9200_clk_main_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_main_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_name; - const char *name = np->name; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91_clk_register_rm9200_main(pmc, name, parent_name); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ -+ clk = at91_clk_register_rm9200_main(regmap, name, parent_name); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main", -+ of_at91rm9200_clk_main_setup); - --static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id) -+static inline bool clk_sam9x5_main_ready(struct regmap *regmap) - { -- struct clk_sam9x5_main *clkmain = dev_id; -+ unsigned int status; - -- wake_up(&clkmain->wait); -- disable_irq_nosync(clkmain->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & AT91_PMC_MOSCSELS ? 1 : 0; - } - - static int clk_sam9x5_main_prepare(struct clk_hw *hw) - { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); -- struct at91_pmc *pmc = clkmain->pmc; -+ struct regmap *regmap = clkmain->regmap; - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { -- enable_irq(clkmain->irq); -- wait_event(clkmain->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); -- } -+ while (!clk_sam9x5_main_ready(regmap)) -+ cpu_relax(); - -- return clk_main_probe_frequency(pmc); -+ return clk_main_probe_frequency(regmap); - } - - static int clk_sam9x5_main_is_prepared(struct clk_hw *hw) - { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); - -- return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); -+ return clk_sam9x5_main_ready(clkmain->regmap); - } - - static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, -@@ -514,30 +485,28 @@ static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, - { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); - -- return clk_main_recalc_rate(clkmain->pmc, parent_rate); -+ return clk_main_recalc_rate(clkmain->regmap, parent_rate); - } - - static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) - { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); -- struct at91_pmc *pmc = clkmain->pmc; -- u32 tmp; -+ struct regmap *regmap = clkmain->regmap; -+ unsigned int tmp; - - if (index > 1) - return -EINVAL; - -- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; -+ regmap_read(regmap, AT91_CKGR_MOR, &tmp); -+ tmp &= ~MOR_KEY_MASK; - - if (index && !(tmp & AT91_PMC_MOSCSEL)) -- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); -+ regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); - else if (!index && (tmp & AT91_PMC_MOSCSEL)) -- pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); -+ regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { -- enable_irq(clkmain->irq); -- wait_event(clkmain->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); -- } -+ while (!clk_sam9x5_main_ready(regmap)) -+ cpu_relax(); - - return 0; - } -@@ -545,8 +514,11 @@ static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) - static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw) - { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); -+ unsigned int status; -+ -+ regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); - -- return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN); -+ return status & AT91_PMC_MOSCEN ? 1 : 0; - } - - static const struct clk_ops sam9x5_main_ops = { -@@ -558,18 +530,17 @@ static const struct clk_ops sam9x5_main_ops = { - }; - - static struct clk * __init --at91_clk_register_sam9x5_main(struct at91_pmc *pmc, -- unsigned int irq, -+at91_clk_register_sam9x5_main(struct regmap *regmap, - const char *name, - const char **parent_names, - int num_parents) - { -- int ret; - struct clk_sam9x5_main *clkmain; - struct clk *clk = NULL; - struct clk_init_data init; -+ unsigned int status; - -- if (!pmc || !irq || !name) -+ if (!name) - return ERR_PTR(-EINVAL); - - if (!parent_names || !num_parents) -@@ -586,51 +557,42 @@ at91_clk_register_sam9x5_main(struct at91_pmc *pmc, - init.flags = CLK_SET_PARENT_GATE; - - clkmain->hw.init = &init; -- clkmain->pmc = pmc; -- clkmain->irq = irq; -- clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & -- AT91_PMC_MOSCEN); -- init_waitqueue_head(&clkmain->wait); -- irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); -- ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler, -- IRQF_TRIGGER_HIGH, name, clkmain); -- if (ret) -- return ERR_PTR(ret); -+ clkmain->regmap = regmap; -+ regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); -+ clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0; - - clk = clk_register(NULL, &clkmain->hw); -- if (IS_ERR(clk)) { -- free_irq(clkmain->irq, clkmain); -+ if (IS_ERR(clk)) - kfree(clkmain); -- } - - return clk; - } - --void __init of_at91sam9x5_clk_main_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_main_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_names[2]; - int num_parents; -- unsigned int irq; - const char *name = np->name; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > 2) - return; - - of_clk_parent_fill(np, parent_names, num_parents); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; - - of_property_read_string(np, "clock-output-names", &name); - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -- return; -- -- clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names, -+ clk = at91_clk_register_sam9x5_main(regmap, name, parent_names, - num_parents); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main", -+ of_at91sam9x5_clk_main_setup); -diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c -index 620ea32..7d4a186 100644 ---- a/drivers/clk/at91/clk-master.c -+++ b/drivers/clk/at91/clk-master.c -@@ -12,13 +12,8 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -44,32 +39,26 @@ struct clk_master_layout { - - struct clk_master { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - const struct clk_master_layout *layout; - const struct clk_master_characteristics *characteristics; - }; - --static irqreturn_t clk_master_irq_handler(int irq, void *dev_id) -+static inline bool clk_master_ready(struct regmap *regmap) - { -- struct clk_master *master = (struct clk_master *)dev_id; -+ unsigned int status; - -- wake_up(&master->wait); -- disable_irq_nosync(master->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & AT91_PMC_MCKRDY ? 1 : 0; - } -+ - static int clk_master_prepare(struct clk_hw *hw) - { - struct clk_master *master = to_clk_master(hw); -- struct at91_pmc *pmc = master->pmc; - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) { -- enable_irq(master->irq); -- wait_event(master->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); -- } -+ while (!clk_master_ready(master->regmap)) -+ cpu_relax(); - - return 0; - } -@@ -78,7 +67,7 @@ static int clk_master_is_prepared(struct clk_hw *hw) - { - struct clk_master *master = to_clk_master(hw); - -- return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); -+ return clk_master_ready(master->regmap); - } - - static unsigned long clk_master_recalc_rate(struct clk_hw *hw, -@@ -88,18 +77,16 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw, - u8 div; - unsigned long rate = parent_rate; - struct clk_master *master = to_clk_master(hw); -- struct at91_pmc *pmc = master->pmc; - const struct clk_master_layout *layout = master->layout; - const struct clk_master_characteristics *characteristics = - master->characteristics; -- u32 tmp; -+ unsigned int mckr; - -- pmc_lock(pmc); -- tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask; -- pmc_unlock(pmc); -+ regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); -+ mckr &= layout->mask; - -- pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK; -- div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; -+ pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK; -+ div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; - - if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX) - rate /= 3; -@@ -119,9 +106,11 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw, - static u8 clk_master_get_parent(struct clk_hw *hw) - { - struct clk_master *master = to_clk_master(hw); -- struct at91_pmc *pmc = master->pmc; -+ unsigned int mckr; - -- return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS; -+ regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); -+ -+ return mckr & AT91_PMC_CSS; - } - - static const struct clk_ops master_ops = { -@@ -132,18 +121,17 @@ static const struct clk_ops master_ops = { - }; - - static struct clk * __init --at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, -+at91_clk_register_master(struct regmap *regmap, - const char *name, int num_parents, - const char **parent_names, - const struct clk_master_layout *layout, - const struct clk_master_characteristics *characteristics) - { -- int ret; - struct clk_master *master; - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !irq || !name || !num_parents || !parent_names) -+ if (!name || !num_parents || !parent_names) - return ERR_PTR(-EINVAL); - - master = kzalloc(sizeof(*master), GFP_KERNEL); -@@ -159,20 +147,10 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, - master->hw.init = &init; - master->layout = layout; - master->characteristics = characteristics; -- master->pmc = pmc; -- master->irq = irq; -- init_waitqueue_head(&master->wait); -- irq_set_status_flags(master->irq, IRQ_NOAUTOEN); -- ret = request_irq(master->irq, clk_master_irq_handler, -- IRQF_TRIGGER_HIGH, "clk-master", master); -- if (ret) { -- kfree(master); -- return ERR_PTR(ret); -- } -+ master->regmap = regmap; - - clk = clk_register(NULL, &master->hw); - if (IS_ERR(clk)) { -- free_irq(master->irq, master); - kfree(master); - } - -@@ -217,15 +195,15 @@ of_at91_clk_master_get_characteristics(struct device_node *np) - } - - static void __init --of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, -+of_at91_clk_master_setup(struct device_node *np, - const struct clk_master_layout *layout) - { - struct clk *clk; - int num_parents; -- unsigned int irq; - const char *parent_names[MASTER_SOURCE_MAX]; - const char *name = np->name; - struct clk_master_characteristics *characteristics; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX) -@@ -239,11 +217,11 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, - if (!characteristics) - return; - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -- goto out_free_characteristics; -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; - -- clk = at91_clk_register_master(pmc, irq, name, num_parents, -+ clk = at91_clk_register_master(regmap, name, num_parents, - parent_names, layout, - characteristics); - if (IS_ERR(clk)) -@@ -256,14 +234,16 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, - kfree(characteristics); - } - --void __init of_at91rm9200_clk_master_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_master_setup(struct device_node *np) - { -- of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout); -+ of_at91_clk_master_setup(np, &at91rm9200_master_layout); - } -+CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master", -+ of_at91rm9200_clk_master_setup); - --void __init of_at91sam9x5_clk_master_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_master_setup(struct device_node *np) - { -- of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout); -+ of_at91_clk_master_setup(np, &at91sam9x5_master_layout); - } -+CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master", -+ of_at91sam9x5_clk_master_setup); -diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c -index 58f3b56..d69cd2a 100644 ---- a/drivers/clk/at91/clk-peripheral.c -+++ b/drivers/clk/at91/clk-peripheral.c -@@ -12,11 +12,13 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "pmc.h" - -+DEFINE_SPINLOCK(pmc_pcr_lock); -+ - #define PERIPHERAL_MAX 64 - - #define PERIPHERAL_AT91RM9200 0 -@@ -33,7 +35,7 @@ - - struct clk_peripheral { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - u32 id; - }; - -@@ -41,8 +43,9 @@ struct clk_peripheral { - - struct clk_sam9x5_peripheral { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - struct clk_range range; -+ spinlock_t *lock; - u32 id; - u32 div; - bool auto_div; -@@ -54,7 +57,6 @@ struct clk_sam9x5_peripheral { - static int clk_peripheral_enable(struct clk_hw *hw) - { - struct clk_peripheral *periph = to_clk_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; - int offset = AT91_PMC_PCER; - u32 id = periph->id; - -@@ -62,14 +64,14 @@ static int clk_peripheral_enable(struct clk_hw *hw) - return 0; - if (id > PERIPHERAL_ID_MAX) - offset = AT91_PMC_PCER1; -- pmc_write(pmc, offset, PERIPHERAL_MASK(id)); -+ regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id)); -+ - return 0; - } - - static void clk_peripheral_disable(struct clk_hw *hw) - { - struct clk_peripheral *periph = to_clk_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; - int offset = AT91_PMC_PCDR; - u32 id = periph->id; - -@@ -77,21 +79,23 @@ static void clk_peripheral_disable(struct clk_hw *hw) - return; - if (id > PERIPHERAL_ID_MAX) - offset = AT91_PMC_PCDR1; -- pmc_write(pmc, offset, PERIPHERAL_MASK(id)); -+ regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id)); - } - - static int clk_peripheral_is_enabled(struct clk_hw *hw) - { - struct clk_peripheral *periph = to_clk_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; - int offset = AT91_PMC_PCSR; -+ unsigned int status; - u32 id = periph->id; - - if (id < PERIPHERAL_ID_MIN) - return 1; - if (id > PERIPHERAL_ID_MAX) - offset = AT91_PMC_PCSR1; -- return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id)); -+ regmap_read(periph->regmap, offset, &status); -+ -+ return status & PERIPHERAL_MASK(id) ? 1 : 0; - } - - static const struct clk_ops peripheral_ops = { -@@ -101,14 +105,14 @@ static const struct clk_ops peripheral_ops = { - }; - - static struct clk * __init --at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, -+at91_clk_register_peripheral(struct regmap *regmap, const char *name, - const char *parent_name, u32 id) - { - struct clk_peripheral *periph; - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX) -+ if (!name || !parent_name || id > PERIPHERAL_ID_MAX) - return ERR_PTR(-EINVAL); - - periph = kzalloc(sizeof(*periph), GFP_KERNEL); -@@ -123,7 +127,7 @@ at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, - - periph->id = id; - periph->hw.init = &init; -- periph->pmc = pmc; -+ periph->regmap = regmap; - - clk = clk_register(NULL, &periph->hw); - if (IS_ERR(clk)) -@@ -160,53 +164,58 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) - static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) - { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; -- u32 tmp; -+ unsigned long flags; - - if (periph->id < PERIPHERAL_ID_MIN) - return 0; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_DIV_MASK; -- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_DIV(periph->div) -- | AT91_PMC_PCR_CMD -- | AT91_PMC_PCR_EN); -- pmc_unlock(pmc); -+ spin_lock_irqsave(periph->lock, flags); -+ regmap_write(periph->regmap, AT91_PMC_PCR, -+ (periph->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_update_bits(periph->regmap, AT91_PMC_PCR, -+ AT91_PMC_PCR_DIV_MASK | AT91_PMC_PCR_CMD | -+ AT91_PMC_PCR_EN, -+ AT91_PMC_PCR_DIV(periph->div) | -+ AT91_PMC_PCR_CMD | -+ AT91_PMC_PCR_EN); -+ spin_unlock_irqrestore(periph->lock, flags); -+ - return 0; - } - - static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) - { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; -- u32 tmp; -+ unsigned long flags; - - if (periph->id < PERIPHERAL_ID_MIN) - return; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_EN; -- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD); -- pmc_unlock(pmc); -+ spin_lock_irqsave(periph->lock, flags); -+ regmap_write(periph->regmap, AT91_PMC_PCR, -+ (periph->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_update_bits(periph->regmap, AT91_PMC_PCR, -+ AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD, -+ AT91_PMC_PCR_CMD); -+ spin_unlock_irqrestore(periph->lock, flags); - } - - static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) - { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; -- int ret; -+ unsigned long flags; -+ unsigned int status; - - if (periph->id < PERIPHERAL_ID_MIN) - return 1; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); -- ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN); -- pmc_unlock(pmc); -+ spin_lock_irqsave(periph->lock, flags); -+ regmap_write(periph->regmap, AT91_PMC_PCR, -+ (periph->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_read(periph->regmap, AT91_PMC_PCR, &status); -+ spin_unlock_irqrestore(periph->lock, flags); - -- return ret; -+ return status & AT91_PMC_PCR_EN ? 1 : 0; - } - - static unsigned long -@@ -214,19 +223,20 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); -- struct at91_pmc *pmc = periph->pmc; -- u32 tmp; -+ unsigned long flags; -+ unsigned int status; - - if (periph->id < PERIPHERAL_ID_MIN) - return parent_rate; - -- pmc_lock(pmc); -- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); -- tmp = pmc_read(pmc, AT91_PMC_PCR); -- pmc_unlock(pmc); -+ spin_lock_irqsave(periph->lock, flags); -+ regmap_write(periph->regmap, AT91_PMC_PCR, -+ (periph->id & AT91_PMC_PCR_PID_MASK)); -+ regmap_read(periph->regmap, AT91_PMC_PCR, &status); -+ spin_unlock_irqrestore(periph->lock, flags); - -- if (tmp & AT91_PMC_PCR_EN) { -- periph->div = PERIPHERAL_RSHIFT(tmp); -+ if (status & AT91_PMC_PCR_EN) { -+ periph->div = PERIPHERAL_RSHIFT(status); - periph->auto_div = false; - } else { - clk_sam9x5_peripheral_autodiv(periph); -@@ -318,15 +328,15 @@ static const struct clk_ops sam9x5_peripheral_ops = { - }; - - static struct clk * __init --at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, -- const char *parent_name, u32 id, -- const struct clk_range *range) -+at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, -+ const char *name, const char *parent_name, -+ u32 id, const struct clk_range *range) - { - struct clk_sam9x5_peripheral *periph; - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !name || !parent_name) -+ if (!name || !parent_name) - return ERR_PTR(-EINVAL); - - periph = kzalloc(sizeof(*periph), GFP_KERNEL); -@@ -342,7 +352,8 @@ at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, - periph->id = id; - periph->hw.init = &init; - periph->div = 0; -- periph->pmc = pmc; -+ periph->regmap = regmap; -+ periph->lock = lock; - periph->auto_div = true; - periph->range = *range; - -@@ -356,7 +367,7 @@ at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, - } - - static void __init --of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) -+of_at91_clk_periph_setup(struct device_node *np, u8 type) - { - int num; - u32 id; -@@ -364,6 +375,7 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) - const char *parent_name; - const char *name; - struct device_node *periphclknp; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - if (!parent_name) -@@ -373,6 +385,10 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) - if (!num || num > PERIPHERAL_MAX) - return; - -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ - for_each_child_of_node(np, periphclknp) { - if (of_property_read_u32(periphclknp, "reg", &id)) - continue; -@@ -384,7 +400,7 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) - name = periphclknp->name; - - if (type == PERIPHERAL_AT91RM9200) { -- clk = at91_clk_register_peripheral(pmc, name, -+ clk = at91_clk_register_peripheral(regmap, name, - parent_name, id); - } else { - struct clk_range range = CLK_RANGE(0, 0); -@@ -393,7 +409,9 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) - "atmel,clk-output-range", - &range); - -- clk = at91_clk_register_sam9x5_peripheral(pmc, name, -+ clk = at91_clk_register_sam9x5_peripheral(regmap, -+ &pmc_pcr_lock, -+ name, - parent_name, - id, &range); - } -@@ -405,14 +423,16 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) - } - } - --void __init of_at91rm9200_clk_periph_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_periph_setup(struct device_node *np) - { -- of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200); -+ of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200); - } -+CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral", -+ of_at91rm9200_clk_periph_setup); - --void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np) - { -- of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5); -+ of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5); - } -+CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral", -+ of_at91sam9x5_clk_periph_setup); -diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c -index 18b60f4..fb2e0b5 100644 ---- a/drivers/clk/at91/clk-pll.c -+++ b/drivers/clk/at91/clk-pll.c -@@ -12,14 +12,8 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -58,9 +52,7 @@ struct clk_pll_layout { - - struct clk_pll { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - u8 id; - u8 div; - u8 range; -@@ -69,20 +61,19 @@ struct clk_pll { - const struct clk_pll_characteristics *characteristics; - }; - --static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id) -+static inline bool clk_pll_ready(struct regmap *regmap, int id) - { -- struct clk_pll *pll = (struct clk_pll *)dev_id; -+ unsigned int status; - -- wake_up(&pll->wait); -- disable_irq_nosync(pll->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & PLL_STATUS_MASK(id) ? 1 : 0; - } - - static int clk_pll_prepare(struct clk_hw *hw) - { - struct clk_pll *pll = to_clk_pll(hw); -- struct at91_pmc *pmc = pll->pmc; -+ struct regmap *regmap = pll->regmap; - const struct clk_pll_layout *layout = pll->layout; - const struct clk_pll_characteristics *characteristics = - pll->characteristics; -@@ -90,39 +81,34 @@ static int clk_pll_prepare(struct clk_hw *hw) - u32 mask = PLL_STATUS_MASK(id); - int offset = PLL_REG(id); - u8 out = 0; -- u32 pllr, icpr; -+ unsigned int pllr; -+ unsigned int status; - u8 div; - u16 mul; - -- pllr = pmc_read(pmc, offset); -+ regmap_read(regmap, offset, &pllr); - div = PLL_DIV(pllr); - mul = PLL_MUL(pllr, layout); - -- if ((pmc_read(pmc, AT91_PMC_SR) & mask) && -+ regmap_read(regmap, AT91_PMC_SR, &status); -+ if ((status & mask) && - (div == pll->div && mul == pll->mul)) - return 0; - - if (characteristics->out) - out = characteristics->out[pll->range]; -- if (characteristics->icpll) { -- icpr = pmc_read(pmc, AT91_PMC_PLLICPR) & ~PLL_ICPR_MASK(id); -- icpr |= (characteristics->icpll[pll->range] << -- PLL_ICPR_SHIFT(id)); -- pmc_write(pmc, AT91_PMC_PLLICPR, icpr); -- } - -- pllr &= ~layout->pllr_mask; -- pllr |= layout->pllr_mask & -- (pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | -- (out << PLL_OUT_SHIFT) | -- ((pll->mul & layout->mul_mask) << layout->mul_shift)); -- pmc_write(pmc, offset, pllr); -- -- while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { -- enable_irq(pll->irq); -- wait_event(pll->wait, -- pmc_read(pmc, AT91_PMC_SR) & mask); -- } -+ if (characteristics->icpll) -+ regmap_update_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), -+ characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id)); -+ -+ regmap_update_bits(regmap, offset, layout->pllr_mask, -+ pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | -+ (out << PLL_OUT_SHIFT) | -+ ((pll->mul & layout->mul_mask) << layout->mul_shift)); -+ -+ while (!clk_pll_ready(regmap, pll->id)) -+ cpu_relax(); - - return 0; - } -@@ -130,32 +116,35 @@ static int clk_pll_prepare(struct clk_hw *hw) - static int clk_pll_is_prepared(struct clk_hw *hw) - { - struct clk_pll *pll = to_clk_pll(hw); -- struct at91_pmc *pmc = pll->pmc; - -- return !!(pmc_read(pmc, AT91_PMC_SR) & -- PLL_STATUS_MASK(pll->id)); -+ return clk_pll_ready(pll->regmap, pll->id); - } - - static void clk_pll_unprepare(struct clk_hw *hw) - { - struct clk_pll *pll = to_clk_pll(hw); -- struct at91_pmc *pmc = pll->pmc; -- const struct clk_pll_layout *layout = pll->layout; -- int offset = PLL_REG(pll->id); -- u32 tmp = pmc_read(pmc, offset) & ~(layout->pllr_mask); -+ unsigned int mask = pll->layout->pllr_mask; - -- pmc_write(pmc, offset, tmp); -+ regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); - } - - static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct clk_pll *pll = to_clk_pll(hw); -+ unsigned int pllr; -+ u16 mul; -+ u8 div; - -- if (!pll->div || !pll->mul) -+ regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); -+ -+ div = PLL_DIV(pllr); -+ mul = PLL_MUL(pllr, pll->layout); -+ -+ if (!div || !mul) - return 0; - -- return (parent_rate / pll->div) * (pll->mul + 1); -+ return (parent_rate / div) * (mul + 1); - } - - static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, -@@ -308,7 +297,7 @@ static const struct clk_ops pll_ops = { - }; - - static struct clk * __init --at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, -+at91_clk_register_pll(struct regmap *regmap, const char *name, - const char *parent_name, u8 id, - const struct clk_pll_layout *layout, - const struct clk_pll_characteristics *characteristics) -@@ -316,9 +305,8 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, - struct clk_pll *pll; - struct clk *clk = NULL; - struct clk_init_data init; -- int ret; - int offset = PLL_REG(id); -- u32 tmp; -+ unsigned int pllr; - - if (id > PLL_MAX_ID) - return ERR_PTR(-EINVAL); -@@ -337,23 +325,13 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, - pll->hw.init = &init; - pll->layout = layout; - pll->characteristics = characteristics; -- pll->pmc = pmc; -- pll->irq = irq; -- tmp = pmc_read(pmc, offset) & layout->pllr_mask; -- pll->div = PLL_DIV(tmp); -- pll->mul = PLL_MUL(tmp, layout); -- init_waitqueue_head(&pll->wait); -- irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); -- ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, -- id ? "clk-pllb" : "clk-plla", pll); -- if (ret) { -- kfree(pll); -- return ERR_PTR(ret); -- } -+ pll->regmap = regmap; -+ regmap_read(regmap, offset, &pllr); -+ pll->div = PLL_DIV(pllr); -+ pll->mul = PLL_MUL(pllr, layout); - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { -- free_irq(pll->irq, pll); - kfree(pll); - } - -@@ -483,12 +461,12 @@ of_at91_clk_pll_get_characteristics(struct device_node *np) - } - - static void __init --of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, -+of_at91_clk_pll_setup(struct device_node *np, - const struct clk_pll_layout *layout) - { - u32 id; -- unsigned int irq; - struct clk *clk; -+ struct regmap *regmap; - const char *parent_name; - const char *name = np->name; - struct clk_pll_characteristics *characteristics; -@@ -500,15 +478,15 @@ of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, - - of_property_read_string(np, "clock-output-names", &name); - -- characteristics = of_at91_clk_pll_get_characteristics(np); -- if (!characteristics) -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) - return; - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -+ characteristics = of_at91_clk_pll_get_characteristics(np); -+ if (!characteristics) - return; - -- clk = at91_clk_register_pll(pmc, irq, name, parent_name, id, layout, -+ clk = at91_clk_register_pll(regmap, name, parent_name, id, layout, - characteristics); - if (IS_ERR(clk)) - goto out_free_characteristics; -@@ -520,26 +498,30 @@ of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, - kfree(characteristics); - } - --void __init of_at91rm9200_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_pll_setup(struct device_node *np) - { -- of_at91_clk_pll_setup(np, pmc, &at91rm9200_pll_layout); -+ of_at91_clk_pll_setup(np, &at91rm9200_pll_layout); - } -+CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll", -+ of_at91rm9200_clk_pll_setup); - --void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np) - { -- of_at91_clk_pll_setup(np, pmc, &at91sam9g45_pll_layout); -+ of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout); - } -+CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll", -+ of_at91sam9g45_clk_pll_setup); - --void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np) - { -- of_at91_clk_pll_setup(np, pmc, &at91sam9g20_pllb_layout); -+ of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout); - } -+CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb", -+ of_at91sam9g20_clk_pllb_setup); - --void __init of_sama5d3_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_sama5d3_clk_pll_setup(struct device_node *np) - { -- of_at91_clk_pll_setup(np, pmc, &sama5d3_pll_layout); -+ of_at91_clk_pll_setup(np, &sama5d3_pll_layout); - } -+CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll", -+ of_sama5d3_clk_pll_setup); -diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c -index ea22656..2bed264 100644 ---- a/drivers/clk/at91/clk-plldiv.c -+++ b/drivers/clk/at91/clk-plldiv.c -@@ -12,8 +12,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -21,16 +21,18 @@ - - struct clk_plldiv { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct clk_plldiv *plldiv = to_clk_plldiv(hw); -- struct at91_pmc *pmc = plldiv->pmc; -+ unsigned int mckr; - -- if (pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_PLLADIV2) -+ regmap_read(plldiv->regmap, AT91_PMC_MCKR, &mckr); -+ -+ if (mckr & AT91_PMC_PLLADIV2) - return parent_rate / 2; - - return parent_rate; -@@ -57,18 +59,12 @@ static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { - struct clk_plldiv *plldiv = to_clk_plldiv(hw); -- struct at91_pmc *pmc = plldiv->pmc; -- u32 tmp; - -- if (parent_rate != rate && (parent_rate / 2) != rate) -+ if ((parent_rate != rate) && (parent_rate / 2 != rate)) - return -EINVAL; - -- pmc_lock(pmc); -- tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_PLLADIV2; -- if ((parent_rate / 2) == rate) -- tmp |= AT91_PMC_PLLADIV2; -- pmc_write(pmc, AT91_PMC_MCKR, tmp); -- pmc_unlock(pmc); -+ regmap_update_bits(plldiv->regmap, AT91_PMC_MCKR, AT91_PMC_PLLADIV2, -+ parent_rate != rate ? AT91_PMC_PLLADIV2 : 0); - - return 0; - } -@@ -80,7 +76,7 @@ static const struct clk_ops plldiv_ops = { - }; - - static struct clk * __init --at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, -+at91_clk_register_plldiv(struct regmap *regmap, const char *name, - const char *parent_name) - { - struct clk_plldiv *plldiv; -@@ -98,7 +94,7 @@ at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, - init.flags = CLK_SET_RATE_GATE; - - plldiv->hw.init = &init; -- plldiv->pmc = pmc; -+ plldiv->regmap = regmap; - - clk = clk_register(NULL, &plldiv->hw); - -@@ -109,27 +105,27 @@ at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, - } - - static void __init --of_at91_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc) -+of_at91sam9x5_clk_plldiv_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_name; - const char *name = np->name; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91_clk_register_plldiv(pmc, name, parent_name); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; - -+ clk = at91_clk_register_plldiv(regmap, name, parent_name); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - return; - } -- --void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, -- struct at91_pmc *pmc) --{ -- of_at91_clk_plldiv_setup(np, pmc); --} -+CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv", -+ of_at91sam9x5_clk_plldiv_setup); -diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c -index 14b270b..bc0be62 100644 ---- a/drivers/clk/at91/clk-programmable.c -+++ b/drivers/clk/at91/clk-programmable.c -@@ -12,10 +12,8 @@ - #include - #include - #include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -24,6 +22,7 @@ - - #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) - #define PROG_PRES_MASK 0x7 -+#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) - #define PROG_MAX_RM9200_CSS 3 - - struct clk_programmable_layout { -@@ -34,7 +33,7 @@ struct clk_programmable_layout { - - struct clk_programmable { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - u8 id; - const struct clk_programmable_layout *layout; - }; -@@ -44,14 +43,12 @@ struct clk_programmable { - static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { -- u32 pres; - struct clk_programmable *prog = to_clk_programmable(hw); -- struct at91_pmc *pmc = prog->pmc; -- const struct clk_programmable_layout *layout = prog->layout; -+ unsigned int pckr; -+ -+ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); - -- pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) & -- PROG_PRES_MASK; -- return parent_rate >> pres; -+ return parent_rate >> PROG_PRES(prog->layout, pckr); - } - - static int clk_programmable_determine_rate(struct clk_hw *hw, -@@ -101,36 +98,36 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) - { - struct clk_programmable *prog = to_clk_programmable(hw); - const struct clk_programmable_layout *layout = prog->layout; -- struct at91_pmc *pmc = prog->pmc; -- u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask; -+ unsigned int mask = layout->css_mask; -+ unsigned int pckr = 0; - - if (layout->have_slck_mck) -- tmp &= AT91_PMC_CSSMCK_MCK; -+ mask |= AT91_PMC_CSSMCK_MCK; - - if (index > layout->css_mask) { -- if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { -- tmp |= AT91_PMC_CSSMCK_MCK; -- return 0; -- } else { -+ if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck) - return -EINVAL; -- } -+ -+ pckr |= AT91_PMC_CSSMCK_MCK; - } - -- pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index); -+ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr); -+ - return 0; - } - - static u8 clk_programmable_get_parent(struct clk_hw *hw) - { -- u32 tmp; -- u8 ret; - struct clk_programmable *prog = to_clk_programmable(hw); -- struct at91_pmc *pmc = prog->pmc; - const struct clk_programmable_layout *layout = prog->layout; -+ unsigned int pckr; -+ u8 ret; -+ -+ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); -+ -+ ret = pckr & layout->css_mask; - -- tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); -- ret = tmp & layout->css_mask; -- if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret) -+ if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret) - ret = PROG_MAX_RM9200_CSS + 1; - - return ret; -@@ -140,26 +137,27 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { - struct clk_programmable *prog = to_clk_programmable(hw); -- struct at91_pmc *pmc = prog->pmc; - const struct clk_programmable_layout *layout = prog->layout; - unsigned long div = parent_rate / rate; -+ unsigned int pckr; - int shift = 0; -- u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & -- ~(PROG_PRES_MASK << layout->pres_shift); -+ -+ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); - - if (!div) - return -EINVAL; - - shift = fls(div) - 1; - -- if (div != (1<= PROG_PRES_MASK) - return -EINVAL; - -- pmc_write(pmc, AT91_PMC_PCKR(prog->id), -- tmp | (shift << layout->pres_shift)); -+ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), -+ PROG_PRES_MASK << layout->pres_shift, -+ shift << layout->pres_shift); - - return 0; - } -@@ -173,7 +171,7 @@ static const struct clk_ops programmable_ops = { - }; - - static struct clk * __init --at91_clk_register_programmable(struct at91_pmc *pmc, -+at91_clk_register_programmable(struct regmap *regmap, - const char *name, const char **parent_names, - u8 num_parents, u8 id, - const struct clk_programmable_layout *layout) -@@ -198,7 +196,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, - prog->id = id; - prog->layout = layout; - prog->hw.init = &init; -- prog->pmc = pmc; -+ prog->regmap = regmap; - - clk = clk_register(NULL, &prog->hw); - if (IS_ERR(clk)) -@@ -226,7 +224,7 @@ static const struct clk_programmable_layout at91sam9x5_programmable_layout = { - }; - - static void __init --of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, -+of_at91_clk_prog_setup(struct device_node *np, - const struct clk_programmable_layout *layout) - { - int num; -@@ -236,6 +234,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, - const char *parent_names[PROG_SOURCE_MAX]; - const char *name; - struct device_node *progclknp; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX) -@@ -247,6 +246,10 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, - if (!num || num > (PROG_ID_MAX + 1)) - return; - -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ - for_each_child_of_node(np, progclknp) { - if (of_property_read_u32(progclknp, "reg", &id)) - continue; -@@ -254,7 +257,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, - if (of_property_read_string(np, "clock-output-names", &name)) - name = progclknp->name; - -- clk = at91_clk_register_programmable(pmc, name, -+ clk = at91_clk_register_programmable(regmap, name, - parent_names, num_parents, - id, layout); - if (IS_ERR(clk)) -@@ -265,20 +268,23 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, - } - - --void __init of_at91rm9200_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_prog_setup(struct device_node *np) - { -- of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); -+ of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout); - } -+CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable", -+ of_at91rm9200_clk_prog_setup); - --void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np) - { -- of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); -+ of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout); - } -+CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable", -+ of_at91sam9g45_clk_prog_setup); - --void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np) - { -- of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); -+ of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout); - } -+CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable", -+ of_at91sam9x5_clk_prog_setup); -diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c -index d0d5076..221c096 100644 ---- a/drivers/clk/at91/clk-slow.c -+++ b/drivers/clk/at91/clk-slow.c -@@ -13,17 +13,11 @@ - #include - #include - #include --#include - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - #include "sckc.h" -@@ -59,7 +53,7 @@ struct clk_slow_rc_osc { - - struct clk_sam9260_slow { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) -@@ -393,8 +387,11 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, - static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) - { - struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); -+ unsigned int status; - -- return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL); -+ regmap_read(slowck->regmap, AT91_PMC_SR, &status); -+ -+ return status & AT91_PMC_OSCSEL ? 1 : 0; - } - - static const struct clk_ops sam9260_slow_ops = { -@@ -402,7 +399,7 @@ static const struct clk_ops sam9260_slow_ops = { - }; - - static struct clk * __init --at91_clk_register_sam9260_slow(struct at91_pmc *pmc, -+at91_clk_register_sam9260_slow(struct regmap *regmap, - const char *name, - const char **parent_names, - int num_parents) -@@ -411,7 +408,7 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, - struct clk *clk = NULL; - struct clk_init_data init; - -- if (!pmc || !name) -+ if (!name) - return ERR_PTR(-EINVAL); - - if (!parent_names || !num_parents) -@@ -428,7 +425,7 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, - init.flags = 0; - - slowck->hw.init = &init; -- slowck->pmc = pmc; -+ slowck->regmap = regmap; - - clk = clk_register(NULL, &slowck->hw); - if (IS_ERR(clk)) -@@ -439,29 +436,34 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, - return clk; - } - --void __init of_at91sam9260_clk_slow_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9260_clk_slow_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_names[2]; - int num_parents; - const char *name = np->name; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents != 2) - return; - - of_clk_parent_fill(np, parent_names, num_parents); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91_clk_register_sam9260_slow(pmc, name, parent_names, -+ clk = at91_clk_register_sam9260_slow(regmap, name, parent_names, - num_parents); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow", -+ of_at91sam9260_clk_slow_setup); - - /* - * FIXME: All slow clk users are not properly claiming it (get + prepare + -diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c -index a7f8501..e6948a5 100644 ---- a/drivers/clk/at91/clk-smd.c -+++ b/drivers/clk/at91/clk-smd.c -@@ -12,8 +12,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -24,7 +24,7 @@ - - struct at91sam9x5_clk_smd { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - #define to_at91sam9x5_clk_smd(hw) \ -@@ -33,13 +33,13 @@ struct at91sam9x5_clk_smd { - static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { -- u32 tmp; -- u8 smddiv; - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); -- struct at91_pmc *pmc = smd->pmc; -+ unsigned int smdr; -+ u8 smddiv; -+ -+ regmap_read(smd->regmap, AT91_PMC_SMD, &smdr); -+ smddiv = (smdr & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; - -- tmp = pmc_read(pmc, AT91_PMC_SMD); -- smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; - return parent_rate / (smddiv + 1); - } - -@@ -67,40 +67,38 @@ static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, - - static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) - { -- u32 tmp; - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); -- struct at91_pmc *pmc = smd->pmc; - - if (index > 1) - return -EINVAL; -- tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS; -- if (index) -- tmp |= AT91_PMC_SMDS; -- pmc_write(pmc, AT91_PMC_SMD, tmp); -+ -+ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMDS, -+ index ? AT91_PMC_SMDS : 0); -+ - return 0; - } - - static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) - { - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); -- struct at91_pmc *pmc = smd->pmc; -+ unsigned int smdr; - -- return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS; -+ regmap_read(smd->regmap, AT91_PMC_SMD, &smdr); -+ -+ return smdr & AT91_PMC_SMDS; - } - - static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { -- u32 tmp; - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); -- struct at91_pmc *pmc = smd->pmc; - unsigned long div = parent_rate / rate; - - if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1)) - return -EINVAL; -- tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV; -- tmp |= (div - 1) << SMD_DIV_SHIFT; -- pmc_write(pmc, AT91_PMC_SMD, tmp); -+ -+ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMD_DIV, -+ (div - 1) << SMD_DIV_SHIFT); - - return 0; - } -@@ -114,7 +112,7 @@ static const struct clk_ops at91sam9x5_smd_ops = { - }; - - static struct clk * __init --at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, -+at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, - const char **parent_names, u8 num_parents) - { - struct at91sam9x5_clk_smd *smd; -@@ -132,7 +130,7 @@ at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, - init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; - - smd->hw.init = &init; -- smd->pmc = pmc; -+ smd->regmap = regmap; - - clk = clk_register(NULL, &smd->hw); - if (IS_ERR(clk)) -@@ -141,13 +139,13 @@ at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, - return clk; - } - --void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np) - { - struct clk *clk; - int num_parents; - const char *parent_names[SMD_SOURCE_MAX]; - const char *name = np->name; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX) -@@ -157,10 +155,16 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91sam9x5_clk_register_smd(pmc, name, parent_names, -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ -+ clk = at91sam9x5_clk_register_smd(regmap, name, parent_names, - num_parents); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd", -+ of_at91sam9x5_clk_smd_setup); -diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c -index 3f53143..8f35d81 100644 ---- a/drivers/clk/at91/clk-system.c -+++ b/drivers/clk/at91/clk-system.c -@@ -12,13 +12,8 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -29,9 +24,7 @@ - #define to_clk_system(hw) container_of(hw, struct clk_system, hw) - struct clk_system { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - u8 id; - }; - -@@ -39,58 +32,54 @@ static inline int is_pck(int id) - { - return (id >= 8) && (id <= 15); - } --static irqreturn_t clk_system_irq_handler(int irq, void *dev_id) -+ -+static inline bool clk_system_ready(struct regmap *regmap, int id) - { -- struct clk_system *sys = (struct clk_system *)dev_id; -+ unsigned int status; - -- wake_up(&sys->wait); -- disable_irq_nosync(sys->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & (1 << id) ? 1 : 0; - } - - static int clk_system_prepare(struct clk_hw *hw) - { - struct clk_system *sys = to_clk_system(hw); -- struct at91_pmc *pmc = sys->pmc; -- u32 mask = 1 << sys->id; - -- pmc_write(pmc, AT91_PMC_SCER, mask); -+ regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id); - - if (!is_pck(sys->id)) - return 0; - -- while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { -- if (sys->irq) { -- enable_irq(sys->irq); -- wait_event(sys->wait, -- pmc_read(pmc, AT91_PMC_SR) & mask); -- } else -- cpu_relax(); -- } -+ while (!clk_system_ready(sys->regmap, sys->id)) -+ cpu_relax(); -+ - return 0; - } - - static void clk_system_unprepare(struct clk_hw *hw) - { - struct clk_system *sys = to_clk_system(hw); -- struct at91_pmc *pmc = sys->pmc; - -- pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); -+ regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id); - } - - static int clk_system_is_prepared(struct clk_hw *hw) - { - struct clk_system *sys = to_clk_system(hw); -- struct at91_pmc *pmc = sys->pmc; -+ unsigned int status; -+ -+ regmap_read(sys->regmap, AT91_PMC_SCSR, &status); - -- if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id))) -+ if (!(status & (1 << sys->id))) - return 0; - - if (!is_pck(sys->id)) - return 1; - -- return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id)); -+ regmap_read(sys->regmap, AT91_PMC_SR, &status); -+ -+ return status & (1 << sys->id) ? 1 : 0; - } - - static const struct clk_ops system_ops = { -@@ -100,13 +89,12 @@ static const struct clk_ops system_ops = { - }; - - static struct clk * __init --at91_clk_register_system(struct at91_pmc *pmc, const char *name, -- const char *parent_name, u8 id, int irq) -+at91_clk_register_system(struct regmap *regmap, const char *name, -+ const char *parent_name, u8 id) - { - struct clk_system *sys; - struct clk *clk = NULL; - struct clk_init_data init; -- int ret; - - if (!parent_name || id > SYSTEM_MAX_ID) - return ERR_PTR(-EINVAL); -@@ -123,44 +111,33 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, - - sys->id = id; - sys->hw.init = &init; -- sys->pmc = pmc; -- sys->irq = irq; -- if (irq) { -- init_waitqueue_head(&sys->wait); -- irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); -- ret = request_irq(sys->irq, clk_system_irq_handler, -- IRQF_TRIGGER_HIGH, name, sys); -- if (ret) { -- kfree(sys); -- return ERR_PTR(ret); -- } -- } -+ sys->regmap = regmap; - - clk = clk_register(NULL, &sys->hw); -- if (IS_ERR(clk)) { -- if (irq) -- free_irq(sys->irq, sys); -+ if (IS_ERR(clk)) - kfree(sys); -- } - - return clk; - } - --static void __init --of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) - { - int num; -- int irq = 0; - u32 id; - struct clk *clk; - const char *name; - struct device_node *sysclknp; - const char *parent_name; -+ struct regmap *regmap; - - num = of_get_child_count(np); - if (num > (SYSTEM_MAX_ID + 1)) - return; - -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ - for_each_child_of_node(np, sysclknp) { - if (of_property_read_u32(sysclknp, "reg", &id)) - continue; -@@ -168,21 +145,14 @@ of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) - if (of_property_read_string(np, "clock-output-names", &name)) - name = sysclknp->name; - -- if (is_pck(id)) -- irq = irq_of_parse_and_map(sysclknp, 0); -- - parent_name = of_clk_get_parent_name(sysclknp, 0); - -- clk = at91_clk_register_system(pmc, name, parent_name, id, irq); -+ clk = at91_clk_register_system(regmap, name, parent_name, id); - if (IS_ERR(clk)) - continue; - - of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); - } - } -- --void __init of_at91rm9200_clk_sys_setup(struct device_node *np, -- struct at91_pmc *pmc) --{ -- of_at91_clk_sys_setup(np, pmc); --} -+CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system", -+ of_at91rm9200_clk_sys_setup); -diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c -index 8ab8502..650ca45 100644 ---- a/drivers/clk/at91/clk-usb.c -+++ b/drivers/clk/at91/clk-usb.c -@@ -12,8 +12,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -27,7 +27,7 @@ - - struct at91sam9x5_clk_usb { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - }; - - #define to_at91sam9x5_clk_usb(hw) \ -@@ -35,7 +35,7 @@ struct at91sam9x5_clk_usb { - - struct at91rm9200_clk_usb { - struct clk_hw hw; -- struct at91_pmc *pmc; -+ struct regmap *regmap; - u32 divisors[4]; - }; - -@@ -45,13 +45,12 @@ struct at91rm9200_clk_usb { - static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { -- u32 tmp; -- u8 usbdiv; - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; -+ unsigned int usbr; -+ u8 usbdiv; - -- tmp = pmc_read(pmc, AT91_PMC_USB); -- usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; -+ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); -+ usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; - - return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); - } -@@ -109,33 +108,31 @@ static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw, - - static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) - { -- u32 tmp; - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; - - if (index > 1) - return -EINVAL; -- tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS; -- if (index) -- tmp |= AT91_PMC_USBS; -- pmc_write(pmc, AT91_PMC_USB, tmp); -+ -+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, -+ index ? AT91_PMC_USBS : 0); -+ - return 0; - } - - static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) - { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; -+ unsigned int usbr; - -- return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS; -+ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); -+ -+ return usbr & AT91_PMC_USBS; - } - - static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { -- u32 tmp; - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; - unsigned long div; - - if (!rate) -@@ -145,9 +142,8 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, - if (div > SAM9X5_USB_MAX_DIV + 1 || !div) - return -EINVAL; - -- tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; -- tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT; -- pmc_write(pmc, AT91_PMC_USB, tmp); -+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV, -+ (div - 1) << SAM9X5_USB_DIV_SHIFT); - - return 0; - } -@@ -163,28 +159,28 @@ static const struct clk_ops at91sam9x5_usb_ops = { - static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) - { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; - -- pmc_write(pmc, AT91_PMC_USB, -- pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS); -+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, -+ AT91_PMC_USBS); -+ - return 0; - } - - static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) - { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; - -- pmc_write(pmc, AT91_PMC_USB, -- pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS); -+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0); - } - - static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) - { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; -+ unsigned int usbr; - -- return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS); -+ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); -+ -+ return usbr & AT91_PMC_USBS; - } - - static const struct clk_ops at91sam9n12_usb_ops = { -@@ -197,7 +193,7 @@ static const struct clk_ops at91sam9n12_usb_ops = { - }; - - static struct clk * __init --at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, -+at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, - const char **parent_names, u8 num_parents) - { - struct at91sam9x5_clk_usb *usb; -@@ -216,7 +212,7 @@ at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, - CLK_SET_RATE_PARENT; - - usb->hw.init = &init; -- usb->pmc = pmc; -+ usb->regmap = regmap; - - clk = clk_register(NULL, &usb->hw); - if (IS_ERR(clk)) -@@ -226,7 +222,7 @@ at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, - } - - static struct clk * __init --at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, -+at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, - const char *parent_name) - { - struct at91sam9x5_clk_usb *usb; -@@ -244,7 +240,7 @@ at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, - init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; - - usb->hw.init = &init; -- usb->pmc = pmc; -+ usb->regmap = regmap; - - clk = clk_register(NULL, &usb->hw); - if (IS_ERR(clk)) -@@ -257,12 +253,12 @@ static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { - struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; -- u32 tmp; -+ unsigned int pllbr; - u8 usbdiv; - -- tmp = pmc_read(pmc, AT91_CKGR_PLLBR); -- usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; -+ regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr); -+ -+ usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; - if (usb->divisors[usbdiv]) - return parent_rate / usb->divisors[usbdiv]; - -@@ -310,10 +306,8 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, - static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { -- u32 tmp; - int i; - struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); -- struct at91_pmc *pmc = usb->pmc; - unsigned long div; - - if (!rate) -@@ -323,10 +317,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, - - for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { - if (usb->divisors[i] == div) { -- tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & -- ~AT91_PMC_USBDIV; -- tmp |= i << RM9200_USB_DIV_SHIFT; -- pmc_write(pmc, AT91_CKGR_PLLBR, tmp); -+ regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR, -+ AT91_PMC_USBDIV, -+ i << RM9200_USB_DIV_SHIFT); -+ - return 0; - } - } -@@ -341,7 +335,7 @@ static const struct clk_ops at91rm9200_usb_ops = { - }; - - static struct clk * __init --at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, -+at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, - const char *parent_name, const u32 *divisors) - { - struct at91rm9200_clk_usb *usb; -@@ -359,7 +353,7 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, - init.flags = CLK_SET_RATE_PARENT; - - usb->hw.init = &init; -- usb->pmc = pmc; -+ usb->regmap = regmap; - memcpy(usb->divisors, divisors, sizeof(usb->divisors)); - - clk = clk_register(NULL, &usb->hw); -@@ -369,13 +363,13 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, - return clk; - } - --void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np) - { - struct clk *clk; - int num_parents; - const char *parent_names[USB_SOURCE_MAX]; - const char *name = np->name; -+ struct regmap *regmap; - - num_parents = of_clk_get_parent_count(np); - if (num_parents <= 0 || num_parents > USB_SOURCE_MAX) -@@ -385,19 +379,26 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ -+ clk = at91sam9x5_clk_register_usb(regmap, name, parent_names, -+ num_parents); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb", -+ of_at91sam9x5_clk_usb_setup); - --void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_name; - const char *name = np->name; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - if (!parent_name) -@@ -405,20 +406,26 @@ void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91sam9n12_clk_register_usb(pmc, name, parent_name); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ -+ clk = at91sam9n12_clk_register_usb(regmap, name, parent_name); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb", -+ of_at91sam9n12_clk_usb_setup); - --void __init of_at91rm9200_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc) -+static void __init of_at91rm9200_clk_usb_setup(struct device_node *np) - { - struct clk *clk; - const char *parent_name; - const char *name = np->name; - u32 divisors[4] = {0, 0, 0, 0}; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - if (!parent_name) -@@ -430,9 +437,15 @@ void __init of_at91rm9200_clk_usb_setup(struct device_node *np, - - of_property_read_string(np, "clock-output-names", &name); - -- clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors); -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) -+ return; -+ -+ clk = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - } -+CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb", -+ of_at91rm9200_clk_usb_setup); -diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c -index ca561e9..61fcf39 100644 ---- a/drivers/clk/at91/clk-utmi.c -+++ b/drivers/clk/at91/clk-utmi.c -@@ -11,14 +11,9 @@ - #include - #include - #include --#include --#include - #include --#include --#include --#include --#include --#include -+#include -+#include - - #include "pmc.h" - -@@ -26,37 +21,30 @@ - - struct clk_utmi { - struct clk_hw hw; -- struct at91_pmc *pmc; -- unsigned int irq; -- wait_queue_head_t wait; -+ struct regmap *regmap; - }; - - #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) - --static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) -+static inline bool clk_utmi_ready(struct regmap *regmap) - { -- struct clk_utmi *utmi = (struct clk_utmi *)dev_id; -+ unsigned int status; - -- wake_up(&utmi->wait); -- disable_irq_nosync(utmi->irq); -+ regmap_read(regmap, AT91_PMC_SR, &status); - -- return IRQ_HANDLED; -+ return status & AT91_PMC_LOCKU; - } - - static int clk_utmi_prepare(struct clk_hw *hw) - { - struct clk_utmi *utmi = to_clk_utmi(hw); -- struct at91_pmc *pmc = utmi->pmc; -- u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | -- AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; -+ unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | -+ AT91_PMC_BIASEN; - -- pmc_write(pmc, AT91_CKGR_UCKR, tmp); -+ regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr); - -- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) { -- enable_irq(utmi->irq); -- wait_event(utmi->wait, -- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); -- } -+ while (!clk_utmi_ready(utmi->regmap)) -+ cpu_relax(); - - return 0; - } -@@ -64,18 +52,15 @@ static int clk_utmi_prepare(struct clk_hw *hw) - static int clk_utmi_is_prepared(struct clk_hw *hw) - { - struct clk_utmi *utmi = to_clk_utmi(hw); -- struct at91_pmc *pmc = utmi->pmc; - -- return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); -+ return clk_utmi_ready(utmi->regmap); - } - - static void clk_utmi_unprepare(struct clk_hw *hw) - { - struct clk_utmi *utmi = to_clk_utmi(hw); -- struct at91_pmc *pmc = utmi->pmc; -- u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN; - -- pmc_write(pmc, AT91_CKGR_UCKR, tmp); -+ regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0); - } - - static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, -@@ -93,10 +78,9 @@ static const struct clk_ops utmi_ops = { - }; - - static struct clk * __init --at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, -+at91_clk_register_utmi(struct regmap *regmap, - const char *name, const char *parent_name) - { -- int ret; - struct clk_utmi *utmi; - struct clk *clk = NULL; - struct clk_init_data init; -@@ -112,52 +96,36 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, - init.flags = CLK_SET_RATE_GATE; - - utmi->hw.init = &init; -- utmi->pmc = pmc; -- utmi->irq = irq; -- init_waitqueue_head(&utmi->wait); -- irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); -- ret = request_irq(utmi->irq, clk_utmi_irq_handler, -- IRQF_TRIGGER_HIGH, "clk-utmi", utmi); -- if (ret) { -- kfree(utmi); -- return ERR_PTR(ret); -- } -+ utmi->regmap = regmap; - - clk = clk_register(NULL, &utmi->hw); -- if (IS_ERR(clk)) { -- free_irq(utmi->irq, utmi); -+ if (IS_ERR(clk)) - kfree(utmi); -- } - - return clk; - } - --static void __init --of_at91_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc) -+static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) - { -- unsigned int irq; - struct clk *clk; - const char *parent_name; - const char *name = np->name; -+ struct regmap *regmap; - - parent_name = of_clk_get_parent_name(np, 0); - - of_property_read_string(np, "clock-output-names", &name); - -- irq = irq_of_parse_and_map(np, 0); -- if (!irq) -+ regmap = syscon_node_to_regmap(of_get_parent(np)); -+ if (IS_ERR(regmap)) - return; - -- clk = at91_clk_register_utmi(pmc, irq, name, parent_name); -+ clk = at91_clk_register_utmi(regmap, name, parent_name); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - return; - } -- --void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, -- struct at91_pmc *pmc) --{ -- of_at91_clk_utmi_setup(np, pmc); --} -+CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi", -+ of_at91sam9x5_clk_utmi_setup); -diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c -index 8476b57..526df5b 100644 ---- a/drivers/clk/at91/pmc.c -+++ b/drivers/clk/at91/pmc.c -@@ -12,36 +12,13 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #include - - #include "pmc.h" - --void __iomem *at91_pmc_base; --EXPORT_SYMBOL_GPL(at91_pmc_base); -- --void at91rm9200_idle(void) --{ -- /* -- * Disable the processor clock. The processor will be automatically -- * re-enabled by an interrupt or by a reset. -- */ -- at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); --} -- --void at91sam9_idle(void) --{ -- at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); -- cpu_do_idle(); --} -- - int of_at91_get_clk_range(struct device_node *np, const char *propname, - struct clk_range *range) - { -@@ -64,402 +41,3 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, - return 0; - } - EXPORT_SYMBOL_GPL(of_at91_get_clk_range); -- --static void pmc_irq_mask(struct irq_data *d) --{ -- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); -- -- pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq); --} -- --static void pmc_irq_unmask(struct irq_data *d) --{ -- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); -- -- pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq); --} -- --static int pmc_irq_set_type(struct irq_data *d, unsigned type) --{ -- if (type != IRQ_TYPE_LEVEL_HIGH) { -- pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n"); -- return -EINVAL; -- } -- -- return 0; --} -- --static void pmc_irq_suspend(struct irq_data *d) --{ -- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); -- -- pmc->imr = pmc_read(pmc, AT91_PMC_IMR); -- pmc_write(pmc, AT91_PMC_IDR, pmc->imr); --} -- --static void pmc_irq_resume(struct irq_data *d) --{ -- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); -- -- pmc_write(pmc, AT91_PMC_IER, pmc->imr); --} -- --static struct irq_chip pmc_irq = { -- .name = "PMC", -- .irq_disable = pmc_irq_mask, -- .irq_mask = pmc_irq_mask, -- .irq_unmask = pmc_irq_unmask, -- .irq_set_type = pmc_irq_set_type, -- .irq_suspend = pmc_irq_suspend, -- .irq_resume = pmc_irq_resume, --}; -- --static struct lock_class_key pmc_lock_class; -- --static int pmc_irq_map(struct irq_domain *h, unsigned int virq, -- irq_hw_number_t hw) --{ -- struct at91_pmc *pmc = h->host_data; -- -- irq_set_lockdep_class(virq, &pmc_lock_class); -- -- irq_set_chip_and_handler(virq, &pmc_irq, -- handle_level_irq); -- irq_set_chip_data(virq, pmc); -- -- return 0; --} -- --static int pmc_irq_domain_xlate(struct irq_domain *d, -- struct device_node *ctrlr, -- const u32 *intspec, unsigned int intsize, -- irq_hw_number_t *out_hwirq, -- unsigned int *out_type) --{ -- struct at91_pmc *pmc = d->host_data; -- const struct at91_pmc_caps *caps = pmc->caps; -- -- if (WARN_ON(intsize < 1)) -- return -EINVAL; -- -- *out_hwirq = intspec[0]; -- -- if (!(caps->available_irqs & (1 << *out_hwirq))) -- return -EINVAL; -- -- *out_type = IRQ_TYPE_LEVEL_HIGH; -- -- return 0; --} -- --static const struct irq_domain_ops pmc_irq_ops = { -- .map = pmc_irq_map, -- .xlate = pmc_irq_domain_xlate, --}; -- --static irqreturn_t pmc_irq_handler(int irq, void *data) --{ -- struct at91_pmc *pmc = (struct at91_pmc *)data; -- unsigned long sr; -- int n; -- -- sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR); -- if (!sr) -- return IRQ_NONE; -- -- for_each_set_bit(n, &sr, BITS_PER_LONG) -- generic_handle_irq(irq_find_mapping(pmc->irqdomain, n)); -- -- return IRQ_HANDLED; --} -- --static const struct at91_pmc_caps at91rm9200_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | -- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | -- AT91_PMC_PCK3RDY, --}; -- --static const struct at91_pmc_caps at91sam9260_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | -- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY, --}; -- --static const struct at91_pmc_caps at91sam9g45_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | -- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY, --}; -- --static const struct at91_pmc_caps at91sam9n12_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | -- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | -- AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, --}; -- --static const struct at91_pmc_caps at91sam9x5_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | -- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | -- AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, --}; -- --static const struct at91_pmc_caps sama5d2_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | -- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | -- AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | -- AT91_PMC_CFDEV | AT91_PMC_GCKRDY, --}; -- --static const struct at91_pmc_caps sama5d3_caps = { -- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | -- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | -- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | -- AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | -- AT91_PMC_CFDEV, --}; -- --static struct at91_pmc *__init at91_pmc_init(struct device_node *np, -- void __iomem *regbase, int virq, -- const struct at91_pmc_caps *caps) --{ -- struct at91_pmc *pmc; -- -- if (!regbase || !virq || !caps) -- return NULL; -- -- at91_pmc_base = regbase; -- -- pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); -- if (!pmc) -- return NULL; -- -- spin_lock_init(&pmc->lock); -- pmc->regbase = regbase; -- pmc->virq = virq; -- pmc->caps = caps; -- -- pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc); -- -- if (!pmc->irqdomain) -- goto out_free_pmc; -- -- pmc_write(pmc, AT91_PMC_IDR, 0xffffffff); -- if (request_irq(pmc->virq, pmc_irq_handler, -- IRQF_SHARED | IRQF_COND_SUSPEND, "pmc", pmc)) -- goto out_remove_irqdomain; -- -- return pmc; -- --out_remove_irqdomain: -- irq_domain_remove(pmc->irqdomain); --out_free_pmc: -- kfree(pmc); -- -- return NULL; --} -- --static const struct of_device_id pmc_clk_ids[] __initconst = { -- /* Slow oscillator */ -- { -- .compatible = "atmel,at91sam9260-clk-slow", -- .data = of_at91sam9260_clk_slow_setup, -- }, -- /* Main clock */ -- { -- .compatible = "atmel,at91rm9200-clk-main-osc", -- .data = of_at91rm9200_clk_main_osc_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-main-rc-osc", -- .data = of_at91sam9x5_clk_main_rc_osc_setup, -- }, -- { -- .compatible = "atmel,at91rm9200-clk-main", -- .data = of_at91rm9200_clk_main_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-main", -- .data = of_at91sam9x5_clk_main_setup, -- }, -- /* PLL clocks */ -- { -- .compatible = "atmel,at91rm9200-clk-pll", -- .data = of_at91rm9200_clk_pll_setup, -- }, -- { -- .compatible = "atmel,at91sam9g45-clk-pll", -- .data = of_at91sam9g45_clk_pll_setup, -- }, -- { -- .compatible = "atmel,at91sam9g20-clk-pllb", -- .data = of_at91sam9g20_clk_pllb_setup, -- }, -- { -- .compatible = "atmel,sama5d3-clk-pll", -- .data = of_sama5d3_clk_pll_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-plldiv", -- .data = of_at91sam9x5_clk_plldiv_setup, -- }, -- /* Master clock */ -- { -- .compatible = "atmel,at91rm9200-clk-master", -- .data = of_at91rm9200_clk_master_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-master", -- .data = of_at91sam9x5_clk_master_setup, -- }, -- /* System clocks */ -- { -- .compatible = "atmel,at91rm9200-clk-system", -- .data = of_at91rm9200_clk_sys_setup, -- }, -- /* Peripheral clocks */ -- { -- .compatible = "atmel,at91rm9200-clk-peripheral", -- .data = of_at91rm9200_clk_periph_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-peripheral", -- .data = of_at91sam9x5_clk_periph_setup, -- }, -- /* Programmable clocks */ -- { -- .compatible = "atmel,at91rm9200-clk-programmable", -- .data = of_at91rm9200_clk_prog_setup, -- }, -- { -- .compatible = "atmel,at91sam9g45-clk-programmable", -- .data = of_at91sam9g45_clk_prog_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-programmable", -- .data = of_at91sam9x5_clk_prog_setup, -- }, -- /* UTMI clock */ --#if defined(CONFIG_HAVE_AT91_UTMI) -- { -- .compatible = "atmel,at91sam9x5-clk-utmi", -- .data = of_at91sam9x5_clk_utmi_setup, -- }, --#endif -- /* USB clock */ --#if defined(CONFIG_HAVE_AT91_USB_CLK) -- { -- .compatible = "atmel,at91rm9200-clk-usb", -- .data = of_at91rm9200_clk_usb_setup, -- }, -- { -- .compatible = "atmel,at91sam9x5-clk-usb", -- .data = of_at91sam9x5_clk_usb_setup, -- }, -- { -- .compatible = "atmel,at91sam9n12-clk-usb", -- .data = of_at91sam9n12_clk_usb_setup, -- }, --#endif -- /* SMD clock */ --#if defined(CONFIG_HAVE_AT91_SMD) -- { -- .compatible = "atmel,at91sam9x5-clk-smd", -- .data = of_at91sam9x5_clk_smd_setup, -- }, --#endif --#if defined(CONFIG_HAVE_AT91_H32MX) -- { -- .compatible = "atmel,sama5d4-clk-h32mx", -- .data = of_sama5d4_clk_h32mx_setup, -- }, --#endif --#if defined(CONFIG_HAVE_AT91_GENERATED_CLK) -- { -- .compatible = "atmel,sama5d2-clk-generated", -- .data = of_sama5d2_clk_generated_setup, -- }, --#endif -- { /*sentinel*/ } --}; -- --static void __init of_at91_pmc_setup(struct device_node *np, -- const struct at91_pmc_caps *caps) --{ -- struct at91_pmc *pmc; -- struct device_node *childnp; -- void (*clk_setup)(struct device_node *, struct at91_pmc *); -- const struct of_device_id *clk_id; -- void __iomem *regbase = of_iomap(np, 0); -- int virq; -- -- if (!regbase) -- return; -- -- virq = irq_of_parse_and_map(np, 0); -- if (!virq) -- return; -- -- pmc = at91_pmc_init(np, regbase, virq, caps); -- if (!pmc) -- return; -- for_each_child_of_node(np, childnp) { -- clk_id = of_match_node(pmc_clk_ids, childnp); -- if (!clk_id) -- continue; -- clk_setup = clk_id->data; -- clk_setup(childnp, pmc); -- } --} -- --static void __init of_at91rm9200_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &at91rm9200_caps); --} --CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc", -- of_at91rm9200_pmc_setup); -- --static void __init of_at91sam9260_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &at91sam9260_caps); --} --CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc", -- of_at91sam9260_pmc_setup); -- --static void __init of_at91sam9g45_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &at91sam9g45_caps); --} --CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc", -- of_at91sam9g45_pmc_setup); -- --static void __init of_at91sam9n12_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &at91sam9n12_caps); --} --CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc", -- of_at91sam9n12_pmc_setup); -- --static void __init of_at91sam9x5_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &at91sam9x5_caps); --} --CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc", -- of_at91sam9x5_pmc_setup); -- --static void __init of_sama5d2_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &sama5d2_caps); --} --CLK_OF_DECLARE(sama5d2_clk_pmc, "atmel,sama5d2-pmc", -- of_sama5d2_pmc_setup); -- --static void __init of_sama5d3_pmc_setup(struct device_node *np) --{ -- of_at91_pmc_setup(np, &sama5d3_caps); --} --CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc", -- of_sama5d3_pmc_setup); -diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h -index f657392..5771fff 100644 ---- a/drivers/clk/at91/pmc.h -+++ b/drivers/clk/at91/pmc.h -@@ -14,8 +14,11 @@ - - #include - #include -+#include - #include - -+extern spinlock_t pmc_pcr_lock; -+ - struct clk_range { - unsigned long min; - unsigned long max; -@@ -23,102 +26,7 @@ struct clk_range { - - #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} - --struct at91_pmc_caps { -- u32 available_irqs; --}; -- --struct at91_pmc { -- void __iomem *regbase; -- int virq; -- spinlock_t lock; -- const struct at91_pmc_caps *caps; -- struct irq_domain *irqdomain; -- u32 imr; --}; -- --static inline void pmc_lock(struct at91_pmc *pmc) --{ -- spin_lock(&pmc->lock); --} -- --static inline void pmc_unlock(struct at91_pmc *pmc) --{ -- spin_unlock(&pmc->lock); --} -- --static inline u32 pmc_read(struct at91_pmc *pmc, int offset) --{ -- return readl(pmc->regbase + offset); --} -- --static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) --{ -- writel(value, pmc->regbase + offset); --} -- - int of_at91_get_clk_range(struct device_node *np, const char *propname, - struct clk_range *range); - --void of_at91sam9260_clk_slow_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_main_osc_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91rm9200_clk_main_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_main_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9g45_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9g20_clk_pllb_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_sama5d3_clk_pll_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_plldiv_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_master_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_master_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_sys_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_periph_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_periph_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9g45_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_prog_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91sam9x5_clk_utmi_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91rm9200_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9x5_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc); --void of_at91sam9n12_clk_usb_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_at91sam9x5_clk_smd_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_sama5d4_clk_h32mx_setup(struct device_node *np, -- struct at91_pmc *pmc); -- --void of_sama5d2_clk_generated_setup(struct device_node *np, -- struct at91_pmc *pmc); -- - #endif /* __PMC_H_ */ -diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c -index 7524941..5b6f57f 100644 ---- a/drivers/clocksource/tcb_clksrc.c -+++ b/drivers/clocksource/tcb_clksrc.c -@@ -73,6 +73,7 @@ static struct clocksource clksrc = { - struct tc_clkevt_device { - struct clock_event_device clkevt; - struct clk *clk; -+ bool clk_enabled; - u32 freq; - void __iomem *regs; - }; -@@ -84,6 +85,24 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) - - static u32 timer_clock; - -+static void tc_clk_disable(struct clock_event_device *d) -+{ -+ struct tc_clkevt_device *tcd = to_tc_clkevt(d); -+ -+ clk_disable(tcd->clk); -+ tcd->clk_enabled = false; -+} -+ -+static void tc_clk_enable(struct clock_event_device *d) -+{ -+ struct tc_clkevt_device *tcd = to_tc_clkevt(d); -+ -+ if (tcd->clk_enabled) -+ return; -+ clk_enable(tcd->clk); -+ tcd->clk_enabled = true; -+} -+ - static int tc_shutdown(struct clock_event_device *d) - { - struct tc_clkevt_device *tcd = to_tc_clkevt(d); -@@ -91,8 +110,14 @@ static int tc_shutdown(struct clock_event_device *d) - - __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); - __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); -+ return 0; -+} -+ -+static int tc_shutdown_clk_off(struct clock_event_device *d) -+{ -+ tc_shutdown(d); - if (!clockevent_state_detached(d)) -- clk_disable(tcd->clk); -+ tc_clk_disable(d); - - return 0; - } -@@ -105,7 +130,7 @@ static int tc_set_oneshot(struct clock_event_device *d) - if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) - tc_shutdown(d); - -- clk_enable(tcd->clk); -+ tc_clk_enable(d); - - /* count up to RC, then irq and stop */ - __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE | -@@ -127,7 +152,7 @@ static int tc_set_periodic(struct clock_event_device *d) - /* By not making the gentime core emulate periodic mode on top - * of oneshot, we get lower overhead and improved accuracy. - */ -- clk_enable(tcd->clk); -+ tc_clk_enable(d); - - /* count up to RC, then irq and restart */ - __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, -@@ -165,7 +190,7 @@ static struct tc_clkevt_device clkevt = { - .rating = 200, - #endif - .set_next_event = tc_next_event, -- .set_state_shutdown = tc_shutdown, -+ .set_state_shutdown = tc_shutdown_clk_off, - .set_state_periodic = tc_set_periodic, - .set_state_oneshot = tc_set_oneshot, - }, -diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c -index a7abdb6..7a40f7e 100644 ---- a/drivers/clocksource/timer-atmel-pit.c -+++ b/drivers/clocksource/timer-atmel-pit.c -@@ -46,6 +46,7 @@ struct pit_data { - u32 cycle; - u32 cnt; - unsigned int irq; -+ bool irq_requested; - struct clk *mck; - }; - -@@ -96,7 +97,10 @@ static int pit_clkevt_shutdown(struct clock_event_device *dev) - - /* disable irq, leaving the clocksource active */ - pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN); -- free_irq(data->irq, data); -+ if (data->irq_requested) { -+ free_irq(data->irq, data); -+ data->irq_requested = false; -+ } - return 0; - } - -@@ -115,6 +119,8 @@ static int pit_clkevt_set_periodic(struct clock_event_device *dev) - if (ret) - panic(pr_fmt("Unable to setup IRQ\n")); - -+ data->irq_requested = true; -+ - /* update clocksource counter */ - data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR)); - pit_write(data->base, AT91_PIT_MR, -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 0f42a27..80a1db0 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -812,6 +812,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ -+ preempt_disable_rt(); - - /* Get optional system timestamp before query. */ - if (stime) -@@ -863,6 +864,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, - *etime = ktime_get(); - - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ -+ preempt_enable_rt(); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - -diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c -index 56dc132..8771d66 100644 ---- a/drivers/gpu/drm/i915/intel_sprite.c -+++ b/drivers/gpu/drm/i915/intel_sprite.c -@@ -38,6 +38,7 @@ - #include "intel_drv.h" - #include - #include "i915_drv.h" -+#include - - static bool - format_is_yuv(uint32_t format) -@@ -64,6 +65,8 @@ static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, - 1000 * adjusted_mode->crtc_htotal); - } - -+static DEFINE_LOCAL_IRQ_LOCK(pipe_update_lock); -+ - /** - * intel_pipe_update_start() - start update of a set of display registers - * @crtc: the crtc of which the registers are going to be updated -@@ -96,7 +99,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc) - min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); - max = vblank_start - 1; - -- local_irq_disable(); -+ local_lock_irq(pipe_update_lock); - - if (min <= 0 || max <= 0) - return; -@@ -126,11 +129,11 @@ void intel_pipe_update_start(struct intel_crtc *crtc) - break; - } - -- local_irq_enable(); -+ local_unlock_irq(pipe_update_lock); - - timeout = schedule_timeout(timeout); - -- local_irq_disable(); -+ local_lock_irq(pipe_update_lock); - } - - finish_wait(wq, &wait); -@@ -164,7 +167,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) - - trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); - -- local_irq_enable(); -+ local_unlock_irq(pipe_update_lock); - - if (crtc->debug.start_vbl_count && - crtc->debug.start_vbl_count != end_vbl_count) { -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index 3645b22..642854b 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -1862,6 +1862,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, - struct radeon_device *rdev = dev->dev_private; - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ -+ preempt_disable_rt(); - - /* Get optional system timestamp before query. */ - if (stime) -@@ -1954,6 +1955,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, - *etime = ktime_get(); - - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ -+ preempt_enable_rt(); - - /* Decode into vertical and horizontal scanout position. */ - *vpos = position & 0x1fff; -diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c -index fc836f5..f417aafe 100644 ---- a/drivers/iommu/amd_iommu.c -+++ b/drivers/iommu/amd_iommu.c -@@ -1952,10 +1952,10 @@ static int __attach_device(struct iommu_dev_data *dev_data, - int ret; - - /* -- * Must be called with IRQs disabled. Warn here to detect early -- * when its not. -+ * Must be called with IRQs disabled on a non RT kernel. Warn here to -+ * detect early when its not. - */ -- WARN_ON(!irqs_disabled()); -+ WARN_ON_NONRT(!irqs_disabled()); - - /* lock domain */ - spin_lock(&domain->lock); -@@ -2118,10 +2118,10 @@ static void __detach_device(struct iommu_dev_data *dev_data) - struct protection_domain *domain; - - /* -- * Must be called with IRQs disabled. Warn here to detect early -- * when its not. -+ * Must be called with IRQs disabled on a non RT kernel. Warn here to -+ * detect early when its not. - */ -- WARN_ON(!irqs_disabled()); -+ WARN_ON_NONRT(!irqs_disabled()); - - if (WARN_ON(!dev_data->domain)) - return; -diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c -index edb5305..7d5ee8a 100644 ---- a/drivers/tty/serial/sc16is7xx.c -+++ b/drivers/tty/serial/sc16is7xx.c -@@ -1230,7 +1230,7 @@ static int sc16is7xx_probe(struct device *dev, - - /* Setup interrupt */ - ret = devm_request_irq(dev, irq, sc16is7xx_irq, -- IRQF_ONESHOT | flags, dev_name(dev), s); -+ flags, dev_name(dev), s); - if (!ret) - return 0; - -diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c -index 3ba63db..4d47528 100644 ---- a/drivers/usb/gadget/function/f_fs.c -+++ b/drivers/usb/gadget/function/f_fs.c -@@ -1405,7 +1405,7 @@ static void ffs_data_put(struct ffs_data *ffs) - pr_info("%s(): freeing\n", __func__); - ffs_data_clear(ffs); - BUG_ON(waitqueue_active(&ffs->ev.waitq) || -- swaitqueue_active(&ffs->ep0req_completion.wait)); -+ swait_active(&ffs->ep0req_completion.wait)); - kfree(ffs->dev_name); - kfree(ffs); - } -diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c -index f92f5af..f9bba26 100644 ---- a/drivers/usb/gadget/udc/atmel_usba_udc.c -+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c -@@ -17,7 +17,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -1888,20 +1890,15 @@ static int atmel_usba_stop(struct usb_gadget *gadget) - #ifdef CONFIG_OF - static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on) - { -- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); -- -- if (is_on) -- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN); -- else -- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN)); -+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, -+ is_on ? AT91_PMC_BIASEN : 0); - } - - static void at91sam9g45_pulse_bias(struct usba_udc *udc) - { -- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); -- -- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN)); -- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN); -+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, 0); -+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, -+ AT91_PMC_BIASEN); - } - - static const struct usba_udc_errata at91sam9rl_errata = { -@@ -1938,6 +1935,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, - return ERR_PTR(-EINVAL); - - udc->errata = match->data; -+ udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); -+ if (udc->errata && IS_ERR(udc->pmc)) -+ return ERR_CAST(udc->pmc); - - udc->num_ep = 0; - -diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h -index ea448a3..3e1c9d5 100644 ---- a/drivers/usb/gadget/udc/atmel_usba_udc.h -+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h -@@ -354,6 +354,8 @@ struct usba_udc { - struct dentry *debugfs_root; - struct dentry *debugfs_regs; - #endif -+ -+ struct regmap *pmc; - }; - - static inline struct usba_ep *to_usba_ep(struct usb_ep *ep) -diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c -index 9c62a6f..9e08447 100644 ---- a/fs/btrfs/volumes.c -+++ b/fs/btrfs/volumes.c -@@ -232,7 +232,6 @@ static struct btrfs_device *__alloc_device(void) - spin_lock_init(&dev->reada_lock); - atomic_set(&dev->reada_in_flight, 0); - atomic_set(&dev->dev_stats_ccnt, 0); -- btrfs_device_data_ordered_init(dev); - INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM); - INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM); - -diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h -index 9db5500..5951c49 100644 ---- a/fs/f2fs/f2fs.h -+++ b/fs/f2fs/f2fs.h -@@ -24,7 +24,6 @@ - - #ifdef CONFIG_F2FS_CHECK_FS - #define f2fs_bug_on(sbi, condition) BUG_ON(condition) --#define f2fs_down_write(x, y) down_write_nest_lock(x, y) - #else - #define f2fs_bug_on(sbi, condition) \ - do { \ -@@ -33,7 +32,6 @@ - set_sbi_flag(sbi, SBI_NEED_FSCK); \ - } \ - } while (0) --#define f2fs_down_write(x, y) down_write(x) - #endif - - /* -@@ -959,7 +957,7 @@ static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi) - - static inline void f2fs_lock_all(struct f2fs_sb_info *sbi) - { -- f2fs_down_write(&sbi->cp_rwsem, &sbi->cp_mutex); -+ down_write(&sbi->cp_rwsem); - } - - static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi) -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index fff4ec1..a8f18e0 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -456,7 +456,7 @@ struct request_queue { - struct throtl_data *td; - #endif - struct rcu_head rcu_head; -- struct swait_head mq_freeze_wq; -+ struct swait_queue_head mq_freeze_wq; - struct percpu_ref q_usage_counter; - struct list_head all_q_node; - -diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h -index 1e69322..17f413b 100644 ---- a/include/linux/clk/at91_pmc.h -+++ b/include/linux/clk/at91_pmc.h -@@ -16,18 +16,6 @@ - #ifndef AT91_PMC_H - #define AT91_PMC_H - --#ifndef __ASSEMBLY__ --extern void __iomem *at91_pmc_base; -- --#define at91_pmc_read(field) \ -- readl_relaxed(at91_pmc_base + field) -- --#define at91_pmc_write(field, value) \ -- writel_relaxed(value, at91_pmc_base + field) --#else --.extern at91_pmc_base --#endif -- - #define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ - #define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ - -diff --git a/include/linux/completion.h b/include/linux/completion.h -index 3fe8d14..3bca159 100644 ---- a/include/linux/completion.h -+++ b/include/linux/completion.h -@@ -7,7 +7,7 @@ - * Atomic wait-for-completion handler data structures. - * See kernel/sched/completion.c for details. - */ --#include -+#include - - /* - * struct completion - structure used to maintain state for a "completion" -@@ -23,11 +23,11 @@ - */ - struct completion { - unsigned int done; -- struct swait_head wait; -+ struct swait_queue_head wait; - }; - - #define COMPLETION_INITIALIZER(work) \ -- { 0, SWAIT_HEAD_INITIALIZER((work).wait) } -+ { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait) } - - #define COMPLETION_INITIALIZER_ONSTACK(work) \ - ({ init_completion(&work); work; }) -@@ -72,7 +72,7 @@ struct completion { - static inline void init_completion(struct completion *x) - { - x->done = 0; -- init_swait_head(&x->wait); -+ init_swait_queue_head(&x->wait); - } - - /** -diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h -index 60048c5..f2cd676 100644 ---- a/include/linux/ftrace.h -+++ b/include/linux/ftrace.h -@@ -694,6 +694,18 @@ static inline void __ftrace_enabled_restore(int enabled) - #define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5)) - #define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6)) - -+static inline unsigned long get_lock_parent_ip(void) -+{ -+ unsigned long addr = CALLER_ADDR0; -+ -+ if (!in_lock_functions(addr)) -+ return addr; -+ addr = CALLER_ADDR1; -+ if (!in_lock_functions(addr)) -+ return addr; -+ return CALLER_ADDR2; -+} -+ - #ifdef CONFIG_IRQSOFF_TRACER - extern void time_hardirqs_on(unsigned long a0, unsigned long a1); - extern void time_hardirqs_off(unsigned long a0, unsigned long a1); -diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h -index f606864..8fbcdfa 100644 ---- a/include/linux/hrtimer.h -+++ b/include/linux/hrtimer.h -@@ -91,7 +91,7 @@ enum hrtimer_restart { - * @irqsafe: timer can run in hardirq context - * @praecox: timer expiry time if expired at the time of programming - * @is_rel: Set if the timer was armed relative -- * @start_pid: timer statistics field to store the pid of the task which -+ * @start_pid: timer statistics field to store the pid of the task which - * started the timer - * @start_site: timer statistics field to store the site where the timer - * was started -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index d856ccd..c690acc 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -243,7 +244,7 @@ struct kvm_vcpu { - int fpu_active; - int guest_fpu_loaded, guest_xcr0_loaded; - unsigned char fpu_counter; -- struct swait_head wq; -+ struct swait_queue_head wq; - struct pid *pid; - int sigset_active; - sigset_t sigset; -@@ -794,7 +795,7 @@ static inline bool kvm_arch_has_assigned_device(struct kvm *kvm) - } - #endif - --static inline struct swait_head *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu) -+static inline struct swait_queue_head *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu) - { - #ifdef __KVM_HAVE_ARCH_WQP - return vcpu->arch.wqp; -diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h -index 44f0b55..89ffaa7 100644 ---- a/include/linux/list_bl.h -+++ b/include/linux/list_bl.h -@@ -42,13 +42,15 @@ struct hlist_bl_node { - struct hlist_bl_node *next, **pprev; - }; - --static inline void INIT_HLIST_BL_HEAD(struct hlist_bl_head *h) --{ -- h->first = NULL; - #ifdef CONFIG_PREEMPT_RT_BASE -- raw_spin_lock_init(&h->lock); -+#define INIT_HLIST_BL_HEAD(h) \ -+do { \ -+ (h)->first = NULL; \ -+ raw_spin_lock_init(&(h)->lock); \ -+} while (0) -+#else -+#define INIT_HLIST_BL_HEAD(h) (h)->first = NULL - #endif --} - - static inline void INIT_HLIST_BL_NODE(struct hlist_bl_node *h) - { -diff --git a/include/linux/locallock.h b/include/linux/locallock.h -index 339ba00..6fe5928 100644 ---- a/include/linux/locallock.h -+++ b/include/linux/locallock.h -@@ -43,9 +43,9 @@ struct local_irq_lock { - * for CONFIG_PREEMPT_BASE map to the normal spin_* calls. - */ - #ifdef CONFIG_PREEMPT_RT_FULL --# define spin_lock_local(lock) rt_spin_lock(lock) --# define spin_trylock_local(lock) rt_spin_trylock(lock) --# define spin_unlock_local(lock) rt_spin_unlock(lock) -+# define spin_lock_local(lock) rt_spin_lock__no_mg(lock) -+# define spin_trylock_local(lock) rt_spin_trylock__no_mg(lock) -+# define spin_unlock_local(lock) rt_spin_unlock__no_mg(lock) - #else - # define spin_lock_local(lock) spin_lock(lock) - # define spin_trylock_local(lock) spin_trylock(lock) -diff --git a/include/linux/sched.h b/include/linux/sched.h -index b6a2358..58c5ec8 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -183,8 +183,6 @@ extern void update_cpu_load_nohz(void); - static inline void update_cpu_load_nohz(void) { } - #endif - --extern unsigned long get_parent_ip(unsigned long addr); -- - extern void dump_cpu_task(int cpu); - - struct seq_file; -diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h -index f757096..3b28255 100644 ---- a/include/linux/spinlock_rt.h -+++ b/include/linux/spinlock_rt.h -@@ -18,6 +18,10 @@ do { \ - __rt_spin_lock_init(slock, #slock, &__key); \ - } while (0) - -+void __lockfunc rt_spin_lock__no_mg(spinlock_t *lock); -+void __lockfunc rt_spin_unlock__no_mg(spinlock_t *lock); -+int __lockfunc rt_spin_trylock__no_mg(spinlock_t *lock); -+ - extern void __lockfunc rt_spin_lock(spinlock_t *lock); - extern unsigned long __lockfunc rt_spin_lock_trace_flags(spinlock_t *lock); - extern void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass); -@@ -32,20 +36,16 @@ extern int atomic_dec_and_spin_lock(atomic_t *atomic, spinlock_t *lock); - * lockdep-less calls, for derived types like rwlock: - * (for trylock they can use rt_mutex_trylock() directly. - */ -+extern void __lockfunc __rt_spin_lock__no_mg(struct rt_mutex *lock); - extern void __lockfunc __rt_spin_lock(struct rt_mutex *lock); - extern void __lockfunc __rt_spin_unlock(struct rt_mutex *lock); - extern int __lockfunc __rt_spin_trylock(struct rt_mutex *lock); - --#define spin_lock(lock) \ -- do { \ -- migrate_disable(); \ -- rt_spin_lock(lock); \ -- } while (0) -+#define spin_lock(lock) rt_spin_lock(lock) - - #define spin_lock_bh(lock) \ - do { \ - local_bh_disable(); \ -- migrate_disable(); \ - rt_spin_lock(lock); \ - } while (0) - -@@ -56,24 +56,19 @@ extern int __lockfunc __rt_spin_trylock(struct rt_mutex *lock); - #define spin_trylock(lock) \ - ({ \ - int __locked; \ -- migrate_disable(); \ - __locked = spin_do_trylock(lock); \ -- if (!__locked) \ -- migrate_enable(); \ - __locked; \ - }) - - #ifdef CONFIG_LOCKDEP - # define spin_lock_nested(lock, subclass) \ - do { \ -- migrate_disable(); \ - rt_spin_lock_nested(lock, subclass); \ - } while (0) - - #define spin_lock_bh_nested(lock, subclass) \ - do { \ - local_bh_disable(); \ -- migrate_disable(); \ - rt_spin_lock_nested(lock, subclass); \ - } while (0) - -@@ -81,7 +76,6 @@ extern int __lockfunc __rt_spin_trylock(struct rt_mutex *lock); - do { \ - typecheck(unsigned long, flags); \ - flags = 0; \ -- migrate_disable(); \ - rt_spin_lock_nested(lock, subclass); \ - } while (0) - #else -@@ -117,16 +111,11 @@ static inline unsigned long spin_lock_trace_flags(spinlock_t *lock) - /* FIXME: we need rt_spin_lock_nest_lock */ - #define spin_lock_nest_lock(lock, nest_lock) spin_lock_nested(lock, 0) - --#define spin_unlock(lock) \ -- do { \ -- rt_spin_unlock(lock); \ -- migrate_enable(); \ -- } while (0) -+#define spin_unlock(lock) rt_spin_unlock(lock) - - #define spin_unlock_bh(lock) \ - do { \ - rt_spin_unlock(lock); \ -- migrate_enable(); \ - local_bh_enable(); \ - } while (0) - -diff --git a/include/linux/suspend.h b/include/linux/suspend.h -index 8b6ec7e..9b77d4c 100644 ---- a/include/linux/suspend.h -+++ b/include/linux/suspend.h -@@ -194,6 +194,12 @@ struct platform_freeze_ops { - void (*end)(void); - }; - -+#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION) -+extern bool pm_in_action; -+#else -+# define pm_in_action false -+#endif -+ - #ifdef CONFIG_SUSPEND - /** - * suspend_set_ops - set platform dependent suspend operations -diff --git a/include/linux/swait.h b/include/linux/swait.h -new file mode 100644 -index 0000000..83f004a ---- /dev/null -+++ b/include/linux/swait.h -@@ -0,0 +1,173 @@ -+#ifndef _LINUX_SWAIT_H -+#define _LINUX_SWAIT_H -+ -+#include -+#include -+#include -+#include -+ -+/* -+ * Simple wait queues -+ * -+ * While these are very similar to the other/complex wait queues (wait.h) the -+ * most important difference is that the simple waitqueue allows for -+ * deterministic behaviour -- IOW it has strictly bounded IRQ and lock hold -+ * times. -+ * -+ * In order to make this so, we had to drop a fair number of features of the -+ * other waitqueue code; notably: -+ * -+ * - mixing INTERRUPTIBLE and UNINTERRUPTIBLE sleeps on the same waitqueue; -+ * all wakeups are TASK_NORMAL in order to avoid O(n) lookups for the right -+ * sleeper state. -+ * -+ * - the exclusive mode; because this requires preserving the list order -+ * and this is hard. -+ * -+ * - custom wake functions; because you cannot give any guarantees about -+ * random code. -+ * -+ * As a side effect of this; the data structures are slimmer. -+ * -+ * One would recommend using this wait queue where possible. -+ */ -+ -+struct task_struct; -+ -+struct swait_queue_head { -+ raw_spinlock_t lock; -+ struct list_head task_list; -+}; -+ -+struct swait_queue { -+ struct task_struct *task; -+ struct list_head task_list; -+}; -+ -+#define __SWAITQUEUE_INITIALIZER(name) { \ -+ .task = current, \ -+ .task_list = LIST_HEAD_INIT((name).task_list), \ -+} -+ -+#define DECLARE_SWAITQUEUE(name) \ -+ struct swait_queue name = __SWAITQUEUE_INITIALIZER(name) -+ -+#define __SWAIT_QUEUE_HEAD_INITIALIZER(name) { \ -+ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ -+ .task_list = LIST_HEAD_INIT((name).task_list), \ -+} -+ -+#define DECLARE_SWAIT_QUEUE_HEAD(name) \ -+ struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INITIALIZER(name) -+ -+extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name, -+ struct lock_class_key *key); -+ -+#define init_swait_queue_head(q) \ -+ do { \ -+ static struct lock_class_key __key; \ -+ __init_swait_queue_head((q), #q, &__key); \ -+ } while (0) -+ -+#ifdef CONFIG_LOCKDEP -+# define __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name) \ -+ ({ init_swait_queue_head(&name); name; }) -+# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name) \ -+ struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name) -+#else -+# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name) \ -+ DECLARE_SWAIT_QUEUE_HEAD(name) -+#endif -+ -+static inline int swait_active(struct swait_queue_head *q) -+{ -+ return !list_empty(&q->task_list); -+} -+ -+extern void swake_up(struct swait_queue_head *q); -+extern void swake_up_all(struct swait_queue_head *q); -+extern void swake_up_locked(struct swait_queue_head *q); -+extern void swake_up_all_locked(struct swait_queue_head *q); -+ -+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait); -+extern void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state); -+extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state); -+ -+extern void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait); -+extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait); -+ -+/* as per ___wait_event() but for swait, therefore "exclusive == 0" */ -+#define ___swait_event(wq, condition, state, ret, cmd) \ -+({ \ -+ struct swait_queue __wait; \ -+ long __ret = ret; \ -+ \ -+ INIT_LIST_HEAD(&__wait.task_list); \ -+ for (;;) { \ -+ long __int = prepare_to_swait_event(&wq, &__wait, state);\ -+ \ -+ if (condition) \ -+ break; \ -+ \ -+ if (___wait_is_interruptible(state) && __int) { \ -+ __ret = __int; \ -+ break; \ -+ } \ -+ \ -+ cmd; \ -+ } \ -+ finish_swait(&wq, &__wait); \ -+ __ret; \ -+}) -+ -+#define __swait_event(wq, condition) \ -+ (void)___swait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, \ -+ schedule()) -+ -+#define swait_event(wq, condition) \ -+do { \ -+ if (condition) \ -+ break; \ -+ __swait_event(wq, condition); \ -+} while (0) -+ -+#define __swait_event_timeout(wq, condition, timeout) \ -+ ___swait_event(wq, ___wait_cond_timeout(condition), \ -+ TASK_UNINTERRUPTIBLE, timeout, \ -+ __ret = schedule_timeout(__ret)) -+ -+#define swait_event_timeout(wq, condition, timeout) \ -+({ \ -+ long __ret = timeout; \ -+ if (!___wait_cond_timeout(condition)) \ -+ __ret = __swait_event_timeout(wq, condition, timeout); \ -+ __ret; \ -+}) -+ -+#define __swait_event_interruptible(wq, condition) \ -+ ___swait_event(wq, condition, TASK_INTERRUPTIBLE, 0, \ -+ schedule()) -+ -+#define swait_event_interruptible(wq, condition) \ -+({ \ -+ int __ret = 0; \ -+ if (!(condition)) \ -+ __ret = __swait_event_interruptible(wq, condition); \ -+ __ret; \ -+}) -+ -+#define __swait_event_interruptible_timeout(wq, condition, timeout) \ -+ ___swait_event(wq, ___wait_cond_timeout(condition), \ -+ TASK_INTERRUPTIBLE, timeout, \ -+ __ret = schedule_timeout(__ret)) -+ -+#define swait_event_interruptible_timeout(wq, condition, timeout) \ -+({ \ -+ long __ret = timeout; \ -+ if (!___wait_cond_timeout(condition)) \ -+ __ret = __swait_event_interruptible_timeout(wq, \ -+ condition, timeout); \ -+ __ret; \ -+}) -+ -+#endif /* _LINUX_SWAIT_H */ -diff --git a/include/linux/wait-simple.h b/include/linux/wait-simple.h -deleted file mode 100644 -index f86bca2..0000000 ---- a/include/linux/wait-simple.h -+++ /dev/null -@@ -1,207 +0,0 @@ --#ifndef _LINUX_WAIT_SIMPLE_H --#define _LINUX_WAIT_SIMPLE_H -- --#include --#include -- --#include -- --struct swaiter { -- struct task_struct *task; -- struct list_head node; --}; -- --#define DEFINE_SWAITER(name) \ -- struct swaiter name = { \ -- .task = current, \ -- .node = LIST_HEAD_INIT((name).node), \ -- } -- --struct swait_head { -- raw_spinlock_t lock; -- struct list_head list; --}; -- --#define SWAIT_HEAD_INITIALIZER(name) { \ -- .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ -- .list = LIST_HEAD_INIT((name).list), \ -- } -- --#define DEFINE_SWAIT_HEAD(name) \ -- struct swait_head name = SWAIT_HEAD_INITIALIZER(name) -- --extern void __init_swait_head(struct swait_head *h, struct lock_class_key *key); -- --#define init_swait_head(swh) \ -- do { \ -- static struct lock_class_key __key; \ -- \ -- __init_swait_head((swh), &__key); \ -- } while (0) -- --/* -- * Waiter functions -- */ --extern void swait_prepare_locked(struct swait_head *head, struct swaiter *w); --extern void swait_prepare(struct swait_head *head, struct swaiter *w, int state); --extern void swait_finish_locked(struct swait_head *head, struct swaiter *w); --extern void swait_finish(struct swait_head *head, struct swaiter *w); -- --/* Check whether a head has waiters enqueued */ --static inline bool swaitqueue_active(struct swait_head *h) --{ -- /* Make sure the condition is visible before checking list_empty() */ -- smp_mb(); -- return !list_empty(&h->list); --} -- --/* -- * Wakeup functions -- */ --extern unsigned int __swait_wake(struct swait_head *head, unsigned int state, unsigned int num); --extern unsigned int __swait_wake_locked(struct swait_head *head, unsigned int state, unsigned int num); -- --#define swait_wake(head) __swait_wake(head, TASK_NORMAL, 1) --#define swait_wake_interruptible(head) __swait_wake(head, TASK_INTERRUPTIBLE, 1) --#define swait_wake_all(head) __swait_wake(head, TASK_NORMAL, 0) --#define swait_wake_all_interruptible(head) __swait_wake(head, TASK_INTERRUPTIBLE, 0) -- --/* -- * Event API -- */ --#define __swait_event(wq, condition) \ --do { \ -- DEFINE_SWAITER(__wait); \ -- \ -- for (;;) { \ -- swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ -- if (condition) \ -- break; \ -- schedule(); \ -- } \ -- swait_finish(&wq, &__wait); \ --} while (0) -- --/** -- * swait_event - sleep until a condition gets true -- * @wq: the waitqueue to wait on -- * @condition: a C expression for the event to wait for -- * -- * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the -- * @condition evaluates to true. The @condition is checked each time -- * the waitqueue @wq is woken up. -- * -- * wake_up() has to be called after changing any variable that could -- * change the result of the wait condition. -- */ --#define swait_event(wq, condition) \ --do { \ -- if (condition) \ -- break; \ -- __swait_event(wq, condition); \ --} while (0) -- --#define __swait_event_interruptible(wq, condition, ret) \ --do { \ -- DEFINE_SWAITER(__wait); \ -- \ -- for (;;) { \ -- swait_prepare(&wq, &__wait, TASK_INTERRUPTIBLE); \ -- if (condition) \ -- break; \ -- if (signal_pending(current)) { \ -- ret = -ERESTARTSYS; \ -- break; \ -- } \ -- schedule(); \ -- } \ -- swait_finish(&wq, &__wait); \ --} while (0) -- --#define __swait_event_interruptible_timeout(wq, condition, ret) \ --do { \ -- DEFINE_SWAITER(__wait); \ -- \ -- for (;;) { \ -- swait_prepare(&wq, &__wait, TASK_INTERRUPTIBLE); \ -- if (condition) \ -- break; \ -- if (signal_pending(current)) { \ -- ret = -ERESTARTSYS; \ -- break; \ -- } \ -- ret = schedule_timeout(ret); \ -- if (!ret) \ -- break; \ -- } \ -- swait_finish(&wq, &__wait); \ --} while (0) -- --/** -- * swait_event_interruptible - sleep until a condition gets true -- * @wq: the waitqueue to wait on -- * @condition: a C expression for the event to wait for -- * -- * The process is put to sleep (TASK_INTERRUPTIBLE) until the -- * @condition evaluates to true. The @condition is checked each time -- * the waitqueue @wq is woken up. -- * -- * wake_up() has to be called after changing any variable that could -- * change the result of the wait condition. -- */ --#define swait_event_interruptible(wq, condition) \ --({ \ -- int __ret = 0; \ -- if (!(condition)) \ -- __swait_event_interruptible(wq, condition, __ret); \ -- __ret; \ --}) -- --#define swait_event_interruptible_timeout(wq, condition, timeout) \ --({ \ -- int __ret = timeout; \ -- if (!(condition)) \ -- __swait_event_interruptible_timeout(wq, condition, __ret); \ -- __ret; \ --}) -- --#define __swait_event_timeout(wq, condition, ret) \ --do { \ -- DEFINE_SWAITER(__wait); \ -- \ -- for (;;) { \ -- swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ -- if (condition) \ -- break; \ -- ret = schedule_timeout(ret); \ -- if (!ret) \ -- break; \ -- } \ -- swait_finish(&wq, &__wait); \ --} while (0) -- --/** -- * swait_event_timeout - sleep until a condition gets true or a timeout elapses -- * @wq: the waitqueue to wait on -- * @condition: a C expression for the event to wait for -- * @timeout: timeout, in jiffies -- * -- * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the -- * @condition evaluates to true. The @condition is checked each time -- * the waitqueue @wq is woken up. -- * -- * wake_up() has to be called after changing any variable that could -- * change the result of the wait condition. -- * -- * The function returns 0 if the @timeout elapsed, and the remaining -- * jiffies if the condition evaluated to true before the timeout elapsed. -- */ --#define swait_event_timeout(wq, condition, timeout) \ --({ \ -- long __ret = timeout; \ -- if (!(condition)) \ -- __swait_event_timeout(wq, condition, __ret); \ -- __ret; \ --}) -- --#endif -diff --git a/include/trace/events/hist.h b/include/trace/events/hist.h -index 6122e42..f7710de 100644 ---- a/include/trace/events/hist.h -+++ b/include/trace/events/hist.h -@@ -9,6 +9,7 @@ - - #if !defined(CONFIG_PREEMPT_OFF_HIST) && !defined(CONFIG_INTERRUPT_OFF_HIST) - #define trace_preemptirqsoff_hist(a, b) -+#define trace_preemptirqsoff_hist_rcuidle(a, b) - #else - TRACE_EVENT(preemptirqsoff_hist, - -diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h -index fff846b..73614ce 100644 ---- a/include/trace/events/writeback.h -+++ b/include/trace/events/writeback.h -@@ -134,58 +134,28 @@ DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode, - #ifdef CREATE_TRACE_POINTS - #ifdef CONFIG_CGROUP_WRITEBACK - --static inline size_t __trace_wb_cgroup_size(struct bdi_writeback *wb) -+static inline unsigned int __trace_wb_assign_cgroup(struct bdi_writeback *wb) - { -- return kernfs_path_len(wb->memcg_css->cgroup->kn) + 1; -+ return wb->memcg_css->cgroup->kn->ino; - } - --static inline void __trace_wb_assign_cgroup(char *buf, struct bdi_writeback *wb) --{ -- struct cgroup *cgrp = wb->memcg_css->cgroup; -- char *path; -- -- path = cgroup_path(cgrp, buf, kernfs_path_len(cgrp->kn) + 1); -- WARN_ON_ONCE(path != buf); --} -- --static inline size_t __trace_wbc_cgroup_size(struct writeback_control *wbc) --{ -- if (wbc->wb) -- return __trace_wb_cgroup_size(wbc->wb); -- else -- return 2; --} -- --static inline void __trace_wbc_assign_cgroup(char *buf, -- struct writeback_control *wbc) -+static inline unsigned int __trace_wbc_assign_cgroup(struct writeback_control *wbc) - { - if (wbc->wb) -- __trace_wb_assign_cgroup(buf, wbc->wb); -+ return __trace_wb_assign_cgroup(wbc->wb); - else -- strcpy(buf, "/"); -+ return -1U; - } -- - #else /* CONFIG_CGROUP_WRITEBACK */ - --static inline size_t __trace_wb_cgroup_size(struct bdi_writeback *wb) --{ -- return 2; --} -- --static inline void __trace_wb_assign_cgroup(char *buf, struct bdi_writeback *wb) --{ -- strcpy(buf, "/"); --} -- --static inline size_t __trace_wbc_cgroup_size(struct writeback_control *wbc) -+static inline unsigned int __trace_wb_assign_cgroup(struct bdi_writeback *wb) - { -- return 2; -+ return -1U; - } - --static inline void __trace_wbc_assign_cgroup(char *buf, -- struct writeback_control *wbc) -+static inline unsigned int __trace_wbc_assign_cgroup(struct writeback_control *wbc) - { -- strcpy(buf, "/"); -+ return -1U; - } - - #endif /* CONFIG_CGROUP_WRITEBACK */ -@@ -201,7 +171,7 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template, - __array(char, name, 32) - __field(unsigned long, ino) - __field(int, sync_mode) -- __dynamic_array(char, cgroup, __trace_wbc_cgroup_size(wbc)) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -209,14 +179,14 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template, - dev_name(inode_to_bdi(inode)->dev), 32); - __entry->ino = inode->i_ino; - __entry->sync_mode = wbc->sync_mode; -- __trace_wbc_assign_cgroup(__get_str(cgroup), wbc); -+ __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); - ), - -- TP_printk("bdi %s: ino=%lu sync_mode=%d cgroup=%s", -+ TP_printk("bdi %s: ino=%lu sync_mode=%d cgroup_ino=%u", - __entry->name, - __entry->ino, - __entry->sync_mode, -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -@@ -246,7 +216,7 @@ DECLARE_EVENT_CLASS(writeback_work_class, - __field(int, range_cyclic) - __field(int, for_background) - __field(int, reason) -- __dynamic_array(char, cgroup, __trace_wb_cgroup_size(wb)) -+ __field(unsigned int, cgroup_ino) - ), - TP_fast_assign( - strncpy(__entry->name, -@@ -258,10 +228,10 @@ DECLARE_EVENT_CLASS(writeback_work_class, - __entry->range_cyclic = work->range_cyclic; - __entry->for_background = work->for_background; - __entry->reason = work->reason; -- __trace_wb_assign_cgroup(__get_str(cgroup), wb); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); - ), - TP_printk("bdi %s: sb_dev %d:%d nr_pages=%ld sync_mode=%d " -- "kupdate=%d range_cyclic=%d background=%d reason=%s cgroup=%s", -+ "kupdate=%d range_cyclic=%d background=%d reason=%s cgroup_ino=%u", - __entry->name, - MAJOR(__entry->sb_dev), MINOR(__entry->sb_dev), - __entry->nr_pages, -@@ -270,7 +240,7 @@ DECLARE_EVENT_CLASS(writeback_work_class, - __entry->range_cyclic, - __entry->for_background, - __print_symbolic(__entry->reason, WB_WORK_REASON), -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - #define DEFINE_WRITEBACK_WORK_EVENT(name) \ -@@ -300,15 +270,15 @@ DECLARE_EVENT_CLASS(writeback_class, - TP_ARGS(wb), - TP_STRUCT__entry( - __array(char, name, 32) -- __dynamic_array(char, cgroup, __trace_wb_cgroup_size(wb)) -+ __field(unsigned int, cgroup_ino) - ), - TP_fast_assign( - strncpy(__entry->name, dev_name(wb->bdi->dev), 32); -- __trace_wb_assign_cgroup(__get_str(cgroup), wb); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); - ), -- TP_printk("bdi %s: cgroup=%s", -+ TP_printk("bdi %s: cgroup_ino=%u", - __entry->name, -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - #define DEFINE_WRITEBACK_EVENT(name) \ -@@ -347,7 +317,7 @@ DECLARE_EVENT_CLASS(wbc_class, - __field(int, range_cyclic) - __field(long, range_start) - __field(long, range_end) -- __dynamic_array(char, cgroup, __trace_wbc_cgroup_size(wbc)) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -361,12 +331,12 @@ DECLARE_EVENT_CLASS(wbc_class, - __entry->range_cyclic = wbc->range_cyclic; - __entry->range_start = (long)wbc->range_start; - __entry->range_end = (long)wbc->range_end; -- __trace_wbc_assign_cgroup(__get_str(cgroup), wbc); -+ __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); - ), - - TP_printk("bdi %s: towrt=%ld skip=%ld mode=%d kupd=%d " - "bgrd=%d reclm=%d cyclic=%d " -- "start=0x%lx end=0x%lx cgroup=%s", -+ "start=0x%lx end=0x%lx cgroup_ino=%u", - __entry->name, - __entry->nr_to_write, - __entry->pages_skipped, -@@ -377,7 +347,7 @@ DECLARE_EVENT_CLASS(wbc_class, - __entry->range_cyclic, - __entry->range_start, - __entry->range_end, -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ) - -@@ -398,7 +368,7 @@ TRACE_EVENT(writeback_queue_io, - __field(long, age) - __field(int, moved) - __field(int, reason) -- __dynamic_array(char, cgroup, __trace_wb_cgroup_size(wb)) -+ __field(unsigned int, cgroup_ino) - ), - TP_fast_assign( - unsigned long *older_than_this = work->older_than_this; -@@ -408,15 +378,15 @@ TRACE_EVENT(writeback_queue_io, - (jiffies - *older_than_this) * 1000 / HZ : -1; - __entry->moved = moved; - __entry->reason = work->reason; -- __trace_wb_assign_cgroup(__get_str(cgroup), wb); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); - ), -- TP_printk("bdi %s: older=%lu age=%ld enqueue=%d reason=%s cgroup=%s", -+ TP_printk("bdi %s: older=%lu age=%ld enqueue=%d reason=%s cgroup_ino=%u", - __entry->name, - __entry->older, /* older_than_this in jiffies */ - __entry->age, /* older_than_this in relative milliseconds */ - __entry->moved, - __print_symbolic(__entry->reason, WB_WORK_REASON), -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -@@ -484,7 +454,7 @@ TRACE_EVENT(bdi_dirty_ratelimit, - __field(unsigned long, dirty_ratelimit) - __field(unsigned long, task_ratelimit) - __field(unsigned long, balanced_dirty_ratelimit) -- __dynamic_array(char, cgroup, __trace_wb_cgroup_size(wb)) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -496,13 +466,13 @@ TRACE_EVENT(bdi_dirty_ratelimit, - __entry->task_ratelimit = KBps(task_ratelimit); - __entry->balanced_dirty_ratelimit = - KBps(wb->balanced_dirty_ratelimit); -- __trace_wb_assign_cgroup(__get_str(cgroup), wb); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); - ), - - TP_printk("bdi %s: " - "write_bw=%lu awrite_bw=%lu dirty_rate=%lu " - "dirty_ratelimit=%lu task_ratelimit=%lu " -- "balanced_dirty_ratelimit=%lu cgroup=%s", -+ "balanced_dirty_ratelimit=%lu cgroup_ino=%u", - __entry->bdi, - __entry->write_bw, /* write bandwidth */ - __entry->avg_write_bw, /* avg write bandwidth */ -@@ -510,7 +480,7 @@ TRACE_EVENT(bdi_dirty_ratelimit, - __entry->dirty_ratelimit, /* base ratelimit */ - __entry->task_ratelimit, /* ratelimit with position control */ - __entry->balanced_dirty_ratelimit, /* the balanced ratelimit */ -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -@@ -548,7 +518,7 @@ TRACE_EVENT(balance_dirty_pages, - __field( long, pause) - __field(unsigned long, period) - __field( long, think) -- __dynamic_array(char, cgroup, __trace_wb_cgroup_size(wb)) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -571,7 +541,7 @@ TRACE_EVENT(balance_dirty_pages, - __entry->period = period * 1000 / HZ; - __entry->pause = pause * 1000 / HZ; - __entry->paused = (jiffies - start_time) * 1000 / HZ; -- __trace_wb_assign_cgroup(__get_str(cgroup), wb); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); - ), - - -@@ -580,7 +550,7 @@ TRACE_EVENT(balance_dirty_pages, - "bdi_setpoint=%lu bdi_dirty=%lu " - "dirty_ratelimit=%lu task_ratelimit=%lu " - "dirtied=%u dirtied_pause=%u " -- "paused=%lu pause=%ld period=%lu think=%ld cgroup=%s", -+ "paused=%lu pause=%ld period=%lu think=%ld cgroup_ino=%u", - __entry->bdi, - __entry->limit, - __entry->setpoint, -@@ -595,7 +565,7 @@ TRACE_EVENT(balance_dirty_pages, - __entry->pause, /* ms */ - __entry->period, /* ms */ - __entry->think, /* ms */ -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -@@ -609,8 +579,7 @@ TRACE_EVENT(writeback_sb_inodes_requeue, - __field(unsigned long, ino) - __field(unsigned long, state) - __field(unsigned long, dirtied_when) -- __dynamic_array(char, cgroup, -- __trace_wb_cgroup_size(inode_to_wb(inode))) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -619,16 +588,16 @@ TRACE_EVENT(writeback_sb_inodes_requeue, - __entry->ino = inode->i_ino; - __entry->state = inode->i_state; - __entry->dirtied_when = inode->dirtied_when; -- __trace_wb_assign_cgroup(__get_str(cgroup), inode_to_wb(inode)); -+ __entry->cgroup_ino = __trace_wb_assign_cgroup(inode_to_wb(inode)); - ), - -- TP_printk("bdi %s: ino=%lu state=%s dirtied_when=%lu age=%lu cgroup=%s", -+ TP_printk("bdi %s: ino=%lu state=%s dirtied_when=%lu age=%lu cgroup_ino=%u", - __entry->name, - __entry->ino, - show_inode_state(__entry->state), - __entry->dirtied_when, - (jiffies - __entry->dirtied_when) / HZ, -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -@@ -684,7 +653,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template, - __field(unsigned long, writeback_index) - __field(long, nr_to_write) - __field(unsigned long, wrote) -- __dynamic_array(char, cgroup, __trace_wbc_cgroup_size(wbc)) -+ __field(unsigned int, cgroup_ino) - ), - - TP_fast_assign( -@@ -696,11 +665,11 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template, - __entry->writeback_index = inode->i_mapping->writeback_index; - __entry->nr_to_write = nr_to_write; - __entry->wrote = nr_to_write - wbc->nr_to_write; -- __trace_wbc_assign_cgroup(__get_str(cgroup), wbc); -+ __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); - ), - - TP_printk("bdi %s: ino=%lu state=%s dirtied_when=%lu age=%lu " -- "index=%lu to_write=%ld wrote=%lu cgroup=%s", -+ "index=%lu to_write=%ld wrote=%lu cgroup_ino=%u", - __entry->name, - __entry->ino, - show_inode_state(__entry->state), -@@ -709,7 +678,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template, - __entry->writeback_index, - __entry->nr_to_write, - __entry->wrote, -- __get_str(cgroup) -+ __entry->cgroup_ino - ) - ); - -diff --git a/kernel/cpu.c b/kernel/cpu.c -index 51aafc2..8edd3c7 100644 ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -127,8 +127,8 @@ struct hotplug_pcp { - }; - - #ifdef CONFIG_PREEMPT_RT_FULL --# define hotplug_lock(hp) rt_spin_lock(&(hp)->lock) --# define hotplug_unlock(hp) rt_spin_unlock(&(hp)->lock) -+# define hotplug_lock(hp) rt_spin_lock__no_mg(&(hp)->lock) -+# define hotplug_unlock(hp) rt_spin_unlock__no_mg(&(hp)->lock) - #else - # define hotplug_lock(hp) mutex_lock(&(hp)->mutex) - # define hotplug_unlock(hp) mutex_unlock(&(hp)->mutex) -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 33c8aa8..760f41d 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -802,6 +802,7 @@ static void __perf_mux_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu) - raw_spin_lock_init(&cpuctx->hrtimer_lock); - hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); - timer->function = perf_mux_hrtimer_handler; -+ timer->irqsafe = 1; - } - - static int perf_mux_hrtimer_restart(struct perf_cpu_context *cpuctx) -diff --git a/kernel/futex.c b/kernel/futex.c -index a34e5ee..02bb869 100644 ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -1226,7 +1226,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this, - if (pi_state->owner != current) - return -EINVAL; - -- raw_spin_lock(&pi_state->pi_mutex.wait_lock); -+ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); - new_owner = rt_mutex_next_owner(&pi_state->pi_mutex); - - /* -@@ -1252,22 +1252,22 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this, - else if (curval != uval) - ret = -EINVAL; - if (ret) { -- raw_spin_unlock(&pi_state->pi_mutex.wait_lock); -+ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); - return ret; - } - -- raw_spin_lock_irq(&pi_state->owner->pi_lock); -+ raw_spin_lock(&pi_state->owner->pi_lock); - WARN_ON(list_empty(&pi_state->list)); - list_del_init(&pi_state->list); -- raw_spin_unlock_irq(&pi_state->owner->pi_lock); -+ raw_spin_unlock(&pi_state->owner->pi_lock); - -- raw_spin_lock_irq(&new_owner->pi_lock); -+ raw_spin_lock(&new_owner->pi_lock); - WARN_ON(!list_empty(&pi_state->list)); - list_add(&pi_state->list, &new_owner->pi_state_list); - pi_state->owner = new_owner; -- raw_spin_unlock_irq(&new_owner->pi_lock); -+ raw_spin_unlock(&new_owner->pi_lock); - -- raw_spin_unlock(&pi_state->pi_mutex.wait_lock); -+ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); - - deboost = rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q, - &wake_sleeper_q); -@@ -2144,11 +2144,11 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) - * we returned due to timeout or signal without taking the - * rt_mutex. Too late. - */ -- raw_spin_lock(&q->pi_state->pi_mutex.wait_lock); -+ raw_spin_lock_irq(&q->pi_state->pi_mutex.wait_lock); - owner = rt_mutex_owner(&q->pi_state->pi_mutex); - if (!owner) - owner = rt_mutex_next_owner(&q->pi_state->pi_mutex); -- raw_spin_unlock(&q->pi_state->pi_mutex.wait_lock); -+ raw_spin_unlock_irq(&q->pi_state->pi_mutex.wait_lock); - ret = fixup_pi_state_owner(uaddr, q, owner); - goto out; - } -diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c -index 239e2ae..0b73349 100644 ---- a/kernel/irq/irqdesc.c -+++ b/kernel/irq/irqdesc.c -@@ -24,10 +24,27 @@ - static struct lock_class_key irq_desc_lock_class; - - #if defined(CONFIG_SMP) -+static int __init irq_affinity_setup(char *str) -+{ -+ zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); -+ cpulist_parse(str, irq_default_affinity); -+ /* -+ * Set at least the boot cpu. We don't want to end up with -+ * bugreports caused by random comandline masks -+ */ -+ cpumask_set_cpu(smp_processor_id(), irq_default_affinity); -+ return 1; -+} -+__setup("irqaffinity=", irq_affinity_setup); -+ - static void __init init_irq_default_affinity(void) - { -- alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); -- cpumask_setall(irq_default_affinity); -+#ifdef CONFIG_CPUMASK_OFFSTACK -+ if (!irq_default_affinity) -+ zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); -+#endif -+ if (cpumask_empty(irq_default_affinity)) -+ cpumask_setall(irq_default_affinity); - } - #else - static void __init init_irq_default_affinity(void) -diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c -index ba2a42a..8e89554 100644 ---- a/kernel/irq/manage.c -+++ b/kernel/irq/manage.c -@@ -2060,7 +2060,7 @@ EXPORT_SYMBOL_GPL(irq_get_irqchip_state); - * This call sets the internal irqchip state of an interrupt, - * depending on the value of @which. - * -- * This function should be called with preemption disabled if the -+ * This function should be called with migration disabled if the - * interrupt controller has per-cpu registers. - */ - int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, -diff --git a/kernel/locking/lglock.c b/kernel/locking/lglock.c -index d8be4fc..57e0ea7 100644 ---- a/kernel/locking/lglock.c -+++ b/kernel/locking/lglock.c -@@ -10,7 +10,7 @@ - # define lg_do_unlock(l) arch_spin_unlock(l) - #else - # define lg_lock_ptr struct rt_mutex --# define lg_do_lock(l) __rt_spin_lock(l) -+# define lg_do_lock(l) __rt_spin_lock__no_mg(l) - # define lg_do_unlock(l) __rt_spin_unlock(l) - #endif - /* -@@ -86,7 +86,7 @@ void lg_double_lock(struct lglock *lg, int cpu1, int cpu2) - if (cpu2 < cpu1) - swap(cpu1, cpu2); - -- preempt_disable(); -+ preempt_disable_nort(); - lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_); - lg_do_lock(per_cpu_ptr(lg->lock, cpu1)); - lg_do_lock(per_cpu_ptr(lg->lock, cpu2)); -@@ -97,7 +97,7 @@ void lg_double_unlock(struct lglock *lg, int cpu1, int cpu2) - lock_release(&lg->lock_dep_map, 1, _RET_IP_); - lg_do_unlock(per_cpu_ptr(lg->lock, cpu1)); - lg_do_unlock(per_cpu_ptr(lg->lock, cpu2)); -- preempt_enable(); -+ preempt_enable_nort(); - } - - void lg_global_lock(struct lglock *lg) -diff --git a/kernel/locking/rt.c b/kernel/locking/rt.c -index 1bbbcad5..d4ab61c 100644 ---- a/kernel/locking/rt.c -+++ b/kernel/locking/rt.c -@@ -235,7 +235,6 @@ EXPORT_SYMBOL(rt_read_trylock); - void __lockfunc rt_write_lock(rwlock_t *rwlock) - { - rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_); -- migrate_disable(); - __rt_spin_lock(&rwlock->lock); - } - EXPORT_SYMBOL(rt_write_lock); -@@ -249,7 +248,6 @@ void __lockfunc rt_read_lock(rwlock_t *rwlock) - * recursive read locks succeed when current owns the lock - */ - if (rt_mutex_owner(lock) != current) { -- migrate_disable(); - rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_); - __rt_spin_lock(lock); - } -diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c -index e1ddae3..6697100 100644 ---- a/kernel/locking/rtmutex.c -+++ b/kernel/locking/rtmutex.c -@@ -111,13 +111,14 @@ static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) - * 2) Drop lock->wait_lock - * 3) Try to unlock the lock with cmpxchg - */ --static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock) -+static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock, -+ unsigned long flags) - __releases(lock->wait_lock) - { - struct task_struct *owner = rt_mutex_owner(lock); - - clear_rt_mutex_waiters(lock); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - /* - * If a new waiter comes in between the unlock and the cmpxchg - * we have two situations: -@@ -159,11 +160,12 @@ static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) - /* - * Simple slow path only version: lock->owner is protected by lock->wait_lock. - */ --static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock) -+static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock, -+ unsigned long flags) - __releases(lock->wait_lock) - { - lock->owner = NULL; -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - return true; - } - #endif -@@ -454,7 +456,6 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - int ret = 0, depth = 0; - struct rt_mutex *lock; - bool detect_deadlock; -- unsigned long flags; - bool requeue = true; - - detect_deadlock = rt_mutex_cond_detect_deadlock(orig_waiter, chwalk); -@@ -497,7 +498,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - /* - * [1] Task cannot go away as we did a get_task() before ! - */ -- raw_spin_lock_irqsave(&task->pi_lock, flags); -+ raw_spin_lock_irq(&task->pi_lock); - - /* - * [2] Get the waiter on which @task is blocked on. -@@ -581,7 +582,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - * operations. - */ - if (!raw_spin_trylock(&lock->wait_lock)) { -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock_irq(&task->pi_lock); - cpu_relax(); - goto retry; - } -@@ -612,7 +613,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - /* - * No requeue[7] here. Just release @task [8] - */ -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock(&task->pi_lock); - put_task_struct(task); - - /* -@@ -620,14 +621,14 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - * If there is no owner of the lock, end of chain. - */ - if (!rt_mutex_owner(lock)) { -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - return 0; - } - - /* [10] Grab the next task, i.e. owner of @lock */ - task = rt_mutex_owner(lock); - get_task_struct(task); -- raw_spin_lock_irqsave(&task->pi_lock, flags); -+ raw_spin_lock(&task->pi_lock); - - /* - * No requeue [11] here. We just do deadlock detection. -@@ -642,8 +643,8 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - top_waiter = rt_mutex_top_waiter(lock); - - /* [13] Drop locks */ -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock(&task->pi_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - /* If owner is not blocked, end of chain. */ - if (!next_lock) -@@ -664,7 +665,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - rt_mutex_enqueue(lock, waiter); - - /* [8] Release the task */ -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock(&task->pi_lock); - put_task_struct(task); - - /* -@@ -685,14 +686,14 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - lock_top_waiter = rt_mutex_top_waiter(lock); - if (prerequeue_top_waiter != lock_top_waiter) - rt_mutex_wake_waiter(lock_top_waiter); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - return 0; - } - - /* [10] Grab the next task, i.e. the owner of @lock */ - task = rt_mutex_owner(lock); - get_task_struct(task); -- raw_spin_lock_irqsave(&task->pi_lock, flags); -+ raw_spin_lock(&task->pi_lock); - - /* [11] requeue the pi waiters if necessary */ - if (waiter == rt_mutex_top_waiter(lock)) { -@@ -746,8 +747,8 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - top_waiter = rt_mutex_top_waiter(lock); - - /* [13] Drop the locks */ -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock(&task->pi_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - /* - * Make the actual exit decisions [12], based on the stored -@@ -770,7 +771,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, - goto again; - - out_unlock_pi: -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock_irq(&task->pi_lock); - out_put_task: - put_task_struct(task); - -@@ -799,7 +800,7 @@ static inline int lock_is_stealable(struct task_struct *task, - /* - * Try to take an rt-mutex - * -- * Must be called with lock->wait_lock held. -+ * Must be called with lock->wait_lock held and interrupts disabled - * - * @lock: The lock to be acquired. - * @task: The task which wants to acquire the lock -@@ -810,8 +811,6 @@ static int __try_to_take_rt_mutex(struct rt_mutex *lock, - struct task_struct *task, - struct rt_mutex_waiter *waiter, int mode) - { -- unsigned long flags; -- - /* - * Before testing whether we can acquire @lock, we set the - * RT_MUTEX_HAS_WAITERS bit in @lock->owner. This forces all -@@ -894,7 +893,7 @@ static int __try_to_take_rt_mutex(struct rt_mutex *lock, - * case, but conditionals are more expensive than a redundant - * store. - */ -- raw_spin_lock_irqsave(&task->pi_lock, flags); -+ raw_spin_lock(&task->pi_lock); - task->pi_blocked_on = NULL; - /* - * Finish the lock acquisition. @task is the new owner. If -@@ -903,7 +902,7 @@ static int __try_to_take_rt_mutex(struct rt_mutex *lock, - */ - if (rt_mutex_has_waiters(lock)) - rt_mutex_enqueue_pi(task, rt_mutex_top_waiter(lock)); -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock(&task->pi_lock); - - takeit: - /* We got the lock. */ -@@ -925,14 +924,19 @@ static int __try_to_take_rt_mutex(struct rt_mutex *lock, - * preemptible spin_lock functions: - */ - static inline void rt_spin_lock_fastlock(struct rt_mutex *lock, -- void (*slowfn)(struct rt_mutex *lock)) -+ void (*slowfn)(struct rt_mutex *lock, -+ bool mg_off), -+ bool do_mig_dis) - { - might_sleep_no_state_check(); - -+ if (do_mig_dis) -+ migrate_disable(); -+ - if (likely(rt_mutex_cmpxchg_acquire(lock, NULL, current))) - rt_mutex_deadlock_account_lock(lock, current); - else -- slowfn(lock); -+ slowfn(lock, do_mig_dis); - } - - static inline void rt_spin_lock_fastunlock(struct rt_mutex *lock, -@@ -979,9 +983,6 @@ static int adaptive_wait(struct rt_mutex *lock, - } - #endif - --# define pi_lock(lock) raw_spin_lock_irq(lock) --# define pi_unlock(lock) raw_spin_unlock_irq(lock) -- - static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - struct rt_mutex_waiter *waiter, - struct task_struct *task, -@@ -993,18 +994,20 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - * We store the current state under p->pi_lock in p->saved_state and - * the try_to_wake_up() code handles this accordingly. - */ --static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) -+static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock, -+ bool mg_off) - { - struct task_struct *lock_owner, *self = current; - struct rt_mutex_waiter waiter, *top_waiter; -+ unsigned long flags; - int ret; - - rt_mutex_init_waiter(&waiter, true); - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - - if (__try_to_take_rt_mutex(lock, self, NULL, STEAL_LATERAL)) { -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - return; - } - -@@ -1016,10 +1019,10 @@ static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) - * as well. We are serialized via pi_lock against wakeups. See - * try_to_wake_up(). - */ -- pi_lock(&self->pi_lock); -+ raw_spin_lock(&self->pi_lock); - self->saved_state = self->state; - __set_current_state_no_track(TASK_UNINTERRUPTIBLE); -- pi_unlock(&self->pi_lock); -+ raw_spin_unlock(&self->pi_lock); - - ret = task_blocks_on_rt_mutex(lock, &waiter, self, RT_MUTEX_MIN_CHAINWALK); - BUG_ON(ret); -@@ -1032,18 +1035,23 @@ static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) - top_waiter = rt_mutex_top_waiter(lock); - lock_owner = rt_mutex_owner(lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - - debug_rt_mutex_print_deadlock(&waiter); - -- if (top_waiter != &waiter || adaptive_wait(lock, lock_owner)) -+ if (top_waiter != &waiter || adaptive_wait(lock, lock_owner)) { -+ if (mg_off) -+ migrate_enable(); - schedule(); -+ if (mg_off) -+ migrate_disable(); -+ } - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - -- pi_lock(&self->pi_lock); -+ raw_spin_lock(&self->pi_lock); - __set_current_state_no_track(TASK_UNINTERRUPTIBLE); -- pi_unlock(&self->pi_lock); -+ raw_spin_unlock(&self->pi_lock); - } - - /* -@@ -1053,10 +1061,10 @@ static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) - * happened while we were blocked. Clear saved_state so - * try_to_wakeup() does not get confused. - */ -- pi_lock(&self->pi_lock); -+ raw_spin_lock(&self->pi_lock); - __set_current_state_no_track(self->saved_state); - self->saved_state = TASK_RUNNING; -- pi_unlock(&self->pi_lock); -+ raw_spin_unlock(&self->pi_lock); - - /* - * try_to_take_rt_mutex() sets the waiter bit -@@ -1067,7 +1075,7 @@ static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) - BUG_ON(rt_mutex_has_waiters(lock) && &waiter == rt_mutex_top_waiter(lock)); - BUG_ON(!RB_EMPTY_NODE(&waiter.tree_entry)); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - - debug_rt_mutex_free_waiter(&waiter); - } -@@ -1080,10 +1088,11 @@ static void mark_wakeup_next_waiter(struct wake_q_head *wake_q, - */ - static void noinline __sched rt_spin_lock_slowunlock(struct rt_mutex *lock) - { -+ unsigned long flags; - WAKE_Q(wake_q); - WAKE_Q(wake_sleeper_q); - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - - debug_rt_mutex_unlock(lock); - -@@ -1091,13 +1100,13 @@ static void noinline __sched rt_spin_lock_slowunlock(struct rt_mutex *lock) - - if (!rt_mutex_has_waiters(lock)) { - lock->owner = NULL; -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - return; - } - - mark_wakeup_next_waiter(&wake_q, &wake_sleeper_q, lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - wake_up_q(&wake_q); - wake_up_q_sleeper(&wake_sleeper_q); - -@@ -1105,33 +1114,55 @@ static void noinline __sched rt_spin_lock_slowunlock(struct rt_mutex *lock) - rt_mutex_adjust_prio(current); - } - -+void __lockfunc rt_spin_lock__no_mg(spinlock_t *lock) -+{ -+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock, false); -+ spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); -+} -+EXPORT_SYMBOL(rt_spin_lock__no_mg); -+ - void __lockfunc rt_spin_lock(spinlock_t *lock) - { -- rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock); -+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock, true); - spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); - } - EXPORT_SYMBOL(rt_spin_lock); - - void __lockfunc __rt_spin_lock(struct rt_mutex *lock) - { -- rt_spin_lock_fastlock(lock, rt_spin_lock_slowlock); -+ rt_spin_lock_fastlock(lock, rt_spin_lock_slowlock, true); - } - EXPORT_SYMBOL(__rt_spin_lock); - -+void __lockfunc __rt_spin_lock__no_mg(struct rt_mutex *lock) -+{ -+ rt_spin_lock_fastlock(lock, rt_spin_lock_slowlock, false); -+} -+EXPORT_SYMBOL(__rt_spin_lock__no_mg); -+ - #ifdef CONFIG_DEBUG_LOCK_ALLOC - void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass) - { -- rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock); - spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); -+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock, true); - } - EXPORT_SYMBOL(rt_spin_lock_nested); - #endif - -+void __lockfunc rt_spin_unlock__no_mg(spinlock_t *lock) -+{ -+ /* NOTE: we always pass in '1' for nested, for simplicity */ -+ spin_release(&lock->dep_map, 1, _RET_IP_); -+ rt_spin_lock_fastunlock(&lock->lock, rt_spin_lock_slowunlock); -+} -+EXPORT_SYMBOL(rt_spin_unlock__no_mg); -+ - void __lockfunc rt_spin_unlock(spinlock_t *lock) - { - /* NOTE: we always pass in '1' for nested, for simplicity */ - spin_release(&lock->dep_map, 1, _RET_IP_); - rt_spin_lock_fastunlock(&lock->lock, rt_spin_lock_slowunlock); -+ migrate_enable(); - } - EXPORT_SYMBOL(rt_spin_unlock); - -@@ -1158,12 +1189,27 @@ int __lockfunc __rt_spin_trylock(struct rt_mutex *lock) - return rt_mutex_trylock(lock); - } - -+int __lockfunc rt_spin_trylock__no_mg(spinlock_t *lock) -+{ -+ int ret; -+ -+ ret = rt_mutex_trylock(&lock->lock); -+ if (ret) -+ spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); -+ return ret; -+} -+EXPORT_SYMBOL(rt_spin_trylock__no_mg); -+ - int __lockfunc rt_spin_trylock(spinlock_t *lock) - { -- int ret = rt_mutex_trylock(&lock->lock); -+ int ret; - -+ migrate_disable(); -+ ret = rt_mutex_trylock(&lock->lock); - if (ret) - spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); -+ else -+ migrate_enable(); - return ret; - } - EXPORT_SYMBOL(rt_spin_trylock); -@@ -1202,12 +1248,10 @@ int atomic_dec_and_spin_lock(atomic_t *atomic, spinlock_t *lock) - /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ - if (atomic_add_unless(atomic, -1, 1)) - return 0; -- migrate_disable(); - rt_spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - rt_spin_unlock(lock); -- migrate_enable(); - return 0; - } - EXPORT_SYMBOL(atomic_dec_and_spin_lock); -@@ -1273,7 +1317,7 @@ try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task, - * - * Prepare waiter and propagate pi chain - * -- * This must be called with lock->wait_lock held. -+ * This must be called with lock->wait_lock held and interrupts disabled - */ - static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - struct rt_mutex_waiter *waiter, -@@ -1284,7 +1328,6 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - struct rt_mutex_waiter *top_waiter = waiter; - struct rt_mutex *next_lock; - int chain_walk = 0, res; -- unsigned long flags; - - /* - * Early deadlock detection. We really don't want the task to -@@ -1298,7 +1341,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - if (owner == task) - return -EDEADLK; - -- raw_spin_lock_irqsave(&task->pi_lock, flags); -+ raw_spin_lock(&task->pi_lock); - - /* - * In the case of futex requeue PI, this will be a proxy -@@ -1310,7 +1353,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - * the task if PI_WAKEUP_INPROGRESS is set. - */ - if (task != current && task->pi_blocked_on == PI_WAKEUP_INPROGRESS) { -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock(&task->pi_lock); - return -EAGAIN; - } - -@@ -1328,12 +1371,12 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - - task->pi_blocked_on = waiter; - -- raw_spin_unlock_irqrestore(&task->pi_lock, flags); -+ raw_spin_unlock(&task->pi_lock); - - if (!owner) - return 0; - -- raw_spin_lock_irqsave(&owner->pi_lock, flags); -+ raw_spin_lock(&owner->pi_lock); - if (waiter == rt_mutex_top_waiter(lock)) { - rt_mutex_dequeue_pi(owner, top_waiter); - rt_mutex_enqueue_pi(owner, waiter); -@@ -1348,7 +1391,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - /* Store the lock on which owner is blocked or NULL */ - next_lock = task_blocked_on_lock(owner); - -- raw_spin_unlock_irqrestore(&owner->pi_lock, flags); -+ raw_spin_unlock(&owner->pi_lock); - /* - * Even if full deadlock detection is on, if the owner is not - * blocked itself, we can avoid finding this out in the chain -@@ -1364,12 +1407,12 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - */ - get_task_struct(owner); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - res = rt_mutex_adjust_prio_chain(owner, chwalk, lock, - next_lock, waiter, task); - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irq(&lock->wait_lock); - - return res; - } -@@ -1378,16 +1421,15 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - * Remove the top waiter from the current tasks pi waiter tree and - * queue it up. - * -- * Called with lock->wait_lock held. -+ * Called with lock->wait_lock held and interrupts disabled. - */ - static void mark_wakeup_next_waiter(struct wake_q_head *wake_q, - struct wake_q_head *wake_sleeper_q, - struct rt_mutex *lock) - { - struct rt_mutex_waiter *waiter; -- unsigned long flags; - -- raw_spin_lock_irqsave(¤t->pi_lock, flags); -+ raw_spin_lock(¤t->pi_lock); - - waiter = rt_mutex_top_waiter(lock); - -@@ -1409,7 +1451,7 @@ static void mark_wakeup_next_waiter(struct wake_q_head *wake_q, - */ - lock->owner = (void *) RT_MUTEX_HAS_WAITERS; - -- raw_spin_unlock_irqrestore(¤t->pi_lock, flags); -+ raw_spin_unlock(¤t->pi_lock); - - if (waiter->savestate) - wake_q_add(wake_sleeper_q, waiter->task); -@@ -1420,7 +1462,7 @@ static void mark_wakeup_next_waiter(struct wake_q_head *wake_q, - /* - * Remove a waiter from a lock and give up - * -- * Must be called with lock->wait_lock held and -+ * Must be called with lock->wait_lock held and interrupts disabled. I must - * have just failed to try_to_take_rt_mutex(). - */ - static void remove_waiter(struct rt_mutex *lock, -@@ -1429,12 +1471,11 @@ static void remove_waiter(struct rt_mutex *lock, - bool is_top_waiter = (waiter == rt_mutex_top_waiter(lock)); - struct task_struct *owner = rt_mutex_owner(lock); - struct rt_mutex *next_lock = NULL; -- unsigned long flags; - -- raw_spin_lock_irqsave(¤t->pi_lock, flags); -+ raw_spin_lock(¤t->pi_lock); - rt_mutex_dequeue(lock, waiter); - current->pi_blocked_on = NULL; -- raw_spin_unlock_irqrestore(¤t->pi_lock, flags); -+ raw_spin_unlock(¤t->pi_lock); - - /* - * Only update priority if the waiter was the highest priority -@@ -1443,7 +1484,7 @@ static void remove_waiter(struct rt_mutex *lock, - if (!owner || !is_top_waiter) - return; - -- raw_spin_lock_irqsave(&owner->pi_lock, flags); -+ raw_spin_lock(&owner->pi_lock); - - rt_mutex_dequeue_pi(owner, waiter); - -@@ -1456,7 +1497,7 @@ static void remove_waiter(struct rt_mutex *lock, - if (rt_mutex_real_waiter(owner->pi_blocked_on)) - next_lock = task_blocked_on_lock(owner); - -- raw_spin_unlock_irqrestore(&owner->pi_lock, flags); -+ raw_spin_unlock(&owner->pi_lock); - - /* - * Don't walk the chain, if the owner task is not blocked -@@ -1468,12 +1509,12 @@ static void remove_waiter(struct rt_mutex *lock, - /* gets dropped in rt_mutex_adjust_prio_chain()! */ - get_task_struct(owner); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - rt_mutex_adjust_prio_chain(owner, RT_MUTEX_MIN_CHAINWALK, lock, - next_lock, NULL, current); - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irq(&lock->wait_lock); - } - - /* -@@ -1509,11 +1550,11 @@ void rt_mutex_adjust_pi(struct task_struct *task) - * __rt_mutex_slowlock() - Perform the wait-wake-try-to-take loop - * @lock: the rt_mutex to take - * @state: the state the task should block in (TASK_INTERRUPTIBLE -- * or TASK_UNINTERRUPTIBLE) -+ * or TASK_UNINTERRUPTIBLE) - * @timeout: the pre-initialized and started timer, or NULL for none - * @waiter: the pre-initialized rt_mutex_waiter - * -- * lock->wait_lock must be held by the caller. -+ * Must be called with lock->wait_lock held and interrupts disabled - */ - static int __sched - __rt_mutex_slowlock(struct rt_mutex *lock, int state, -@@ -1548,13 +1589,13 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state, - break; - } - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - debug_rt_mutex_print_deadlock(waiter); - - schedule(); - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irq(&lock->wait_lock); - set_current_state(state); - } - -@@ -1668,17 +1709,26 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, - struct ww_acquire_ctx *ww_ctx) - { - struct rt_mutex_waiter waiter; -+ unsigned long flags; - int ret = 0; - - rt_mutex_init_waiter(&waiter, false); - -- raw_spin_lock(&lock->wait_lock); -+ /* -+ * Technically we could use raw_spin_[un]lock_irq() here, but this can -+ * be called in early boot if the cmpxchg() fast path is disabled -+ * (debug, no architecture support). In this case we will acquire the -+ * rtmutex with lock->wait_lock held. But we cannot unconditionally -+ * enable interrupts in that early boot case. So we need to use the -+ * irqsave/restore variants. -+ */ -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - - /* Try to acquire the lock again: */ - if (try_to_take_rt_mutex(lock, current, NULL)) { - if (ww_ctx) - ww_mutex_account_lock(lock, ww_ctx); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - return 0; - } - -@@ -1717,7 +1767,7 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, - */ - fixup_rt_mutex_waiters(lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - - /* Remove pending timer: */ - if (unlikely(timeout)) -@@ -1733,6 +1783,7 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state, - */ - static inline int rt_mutex_slowtrylock(struct rt_mutex *lock) - { -+ unsigned long flags; - int ret; - - /* -@@ -1744,10 +1795,10 @@ static inline int rt_mutex_slowtrylock(struct rt_mutex *lock) - return 0; - - /* -- * The mutex has currently no owner. Lock the wait lock and -- * try to acquire the lock. -+ * The mutex has currently no owner. Lock the wait lock and try to -+ * acquire the lock. We use irqsave here to support early boot calls. - */ -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - - ret = try_to_take_rt_mutex(lock, current, NULL); - -@@ -1757,7 +1808,7 @@ static inline int rt_mutex_slowtrylock(struct rt_mutex *lock) - */ - fixup_rt_mutex_waiters(lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - - return ret; - } -@@ -1770,7 +1821,10 @@ static bool __sched rt_mutex_slowunlock(struct rt_mutex *lock, - struct wake_q_head *wake_q, - struct wake_q_head *wake_sleeper_q) - { -- raw_spin_lock(&lock->wait_lock); -+ unsigned long flags; -+ -+ /* irqsave required to support early boot calls */ -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - - debug_rt_mutex_unlock(lock); - -@@ -1809,10 +1863,10 @@ static bool __sched rt_mutex_slowunlock(struct rt_mutex *lock, - */ - while (!rt_mutex_has_waiters(lock)) { - /* Drops lock->wait_lock ! */ -- if (unlock_rt_mutex_safe(lock) == true) -+ if (unlock_rt_mutex_safe(lock, flags) == true) - return false; - /* Relock the rtmutex and try again */ -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irqsave(&lock->wait_lock, flags); - } - - /* -@@ -1823,7 +1877,7 @@ static bool __sched rt_mutex_slowunlock(struct rt_mutex *lock, - */ - mark_wakeup_next_waiter(wake_q, wake_sleeper_q, lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags); - - /* check PI boosting */ - return true; -@@ -2135,10 +2189,10 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock, - { - int ret; - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irq(&lock->wait_lock); - - if (try_to_take_rt_mutex(lock, task, NULL)) { -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - return 1; - } - -@@ -2161,14 +2215,14 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock, - * PI_REQUEUE_INPROGRESS, so that if the task is waking up - * it will know that we are in the process of requeuing it. - */ -- raw_spin_lock_irq(&task->pi_lock); -+ raw_spin_lock(&task->pi_lock); - if (task->pi_blocked_on) { -- raw_spin_unlock_irq(&task->pi_lock); -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock(&task->pi_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - return -EAGAIN; - } - task->pi_blocked_on = PI_REQUEUE_INPROGRESS; -- raw_spin_unlock_irq(&task->pi_lock); -+ raw_spin_unlock(&task->pi_lock); - #endif - - /* We enforce deadlock detection for futexes */ -@@ -2188,7 +2242,7 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock, - if (ret && rt_mutex_has_waiters(lock)) - remove_waiter(lock, waiter); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - debug_rt_mutex_print_deadlock(waiter); - -@@ -2236,7 +2290,7 @@ int rt_mutex_finish_proxy_lock(struct rt_mutex *lock, - { - int ret; - -- raw_spin_lock(&lock->wait_lock); -+ raw_spin_lock_irq(&lock->wait_lock); - - set_current_state(TASK_INTERRUPTIBLE); - -@@ -2252,7 +2306,7 @@ int rt_mutex_finish_proxy_lock(struct rt_mutex *lock, - */ - fixup_rt_mutex_waiters(lock); - -- raw_spin_unlock(&lock->wait_lock); -+ raw_spin_unlock_irq(&lock->wait_lock); - - return ret; - } -diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index bfd9e09..fbb23f9 100644 ---- a/kernel/power/hibernate.c -+++ b/kernel/power/hibernate.c -@@ -648,6 +648,10 @@ static void power_down(void) - cpu_relax(); - } - -+#ifndef CONFIG_SUSPEND -+bool pm_in_action; -+#endif -+ - /** - * hibernate - Carry out system hibernation, including saving the image. - */ -@@ -660,6 +664,8 @@ int hibernate(void) - return -EPERM; - } - -+ pm_in_action = true; -+ - lock_system_sleep(); - /* The snapshot device should not be opened while we're running */ - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -@@ -725,6 +731,7 @@ int hibernate(void) - atomic_inc(&snapshot_device_available); - Unlock: - unlock_system_sleep(); -+ pm_in_action = false; - return error; - } - -diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c -index 80ebc07..393bc34 100644 ---- a/kernel/power/suspend.c -+++ b/kernel/power/suspend.c -@@ -522,6 +522,8 @@ static int enter_state(suspend_state_t state) - return error; - } - -+bool pm_in_action; -+ - /** - * pm_suspend - Externally visible function for suspending the system. - * @state: System sleep state to enter. -@@ -536,6 +538,8 @@ int pm_suspend(suspend_state_t state) - if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX) - return -EINVAL; - -+ pm_in_action = true; -+ - error = enter_state(state); - if (error) { - suspend_stats.fail++; -@@ -543,6 +547,7 @@ int pm_suspend(suspend_state_t state) - } else { - suspend_stats.success++; - } -+ pm_in_action = false; - return error; - } - EXPORT_SYMBOL(pm_suspend); -diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c -index 69fbfde..f75e4b0 100644 ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -241,6 +241,65 @@ struct printk_log { - */ - static DEFINE_RAW_SPINLOCK(logbuf_lock); - -+#ifdef CONFIG_EARLY_PRINTK -+struct console *early_console; -+ -+static void early_vprintk(const char *fmt, va_list ap) -+{ -+ if (early_console) { -+ char buf[512]; -+ int n = vscnprintf(buf, sizeof(buf), fmt, ap); -+ -+ early_console->write(early_console, buf, n); -+ } -+} -+ -+asmlinkage void early_printk(const char *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ early_vprintk(fmt, ap); -+ va_end(ap); -+} -+ -+/* -+ * This is independent of any log levels - a global -+ * kill switch that turns off all of printk. -+ * -+ * Used by the NMI watchdog if early-printk is enabled. -+ */ -+static bool __read_mostly printk_killswitch; -+ -+static int __init force_early_printk_setup(char *str) -+{ -+ printk_killswitch = true; -+ return 0; -+} -+early_param("force_early_printk", force_early_printk_setup); -+ -+void printk_kill(void) -+{ -+ printk_killswitch = true; -+} -+ -+#ifdef CONFIG_PRINTK -+static int forced_early_printk(const char *fmt, va_list ap) -+{ -+ if (!printk_killswitch) -+ return 0; -+ early_vprintk(fmt, ap); -+ return 1; -+} -+#endif -+ -+#else -+static inline int forced_early_printk(const char *fmt, va_list ap) -+{ -+ return 0; -+} -+#endif -+ - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); - /* the next printk record to read by syslog(READ) or /proc/kmsg */ -@@ -1692,62 +1751,6 @@ static size_t cont_print_text(char *text, size_t size) - return textlen; - } - --#ifdef CONFIG_EARLY_PRINTK --struct console *early_console; -- --static void early_vprintk(const char *fmt, va_list ap) --{ -- if (early_console) { -- char buf[512]; -- int n = vscnprintf(buf, sizeof(buf), fmt, ap); -- -- early_console->write(early_console, buf, n); -- } --} -- --asmlinkage void early_printk(const char *fmt, ...) --{ -- va_list ap; -- -- va_start(ap, fmt); -- early_vprintk(fmt, ap); -- va_end(ap); --} -- --/* -- * This is independent of any log levels - a global -- * kill switch that turns off all of printk. -- * -- * Used by the NMI watchdog if early-printk is enabled. -- */ --static bool __read_mostly printk_killswitch; -- --static int __init force_early_printk_setup(char *str) --{ -- printk_killswitch = true; -- return 0; --} --early_param("force_early_printk", force_early_printk_setup); -- --void printk_kill(void) --{ -- printk_killswitch = true; --} -- --static int forced_early_printk(const char *fmt, va_list ap) --{ -- if (!printk_killswitch) -- return 0; -- early_vprintk(fmt, ap); -- return 1; --} --#else --static inline int forced_early_printk(const char *fmt, va_list ap) --{ -- return 0; --} --#endif -- - asmlinkage int vprintk_emit(int facility, int level, - const char *dict, size_t dictlen, - const char *fmt, va_list args) -@@ -2410,7 +2413,6 @@ void console_unlock(void) - start_critical_timings(); - local_irq_restore(flags); - #endif -- - if (do_cond_resched) - cond_resched(); - } -diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c -index d89328e..5bb3364 100644 ---- a/kernel/rcu/rcutorture.c -+++ b/kernel/rcu/rcutorture.c -@@ -390,6 +390,7 @@ static struct rcu_torture_ops rcu_ops = { - .name = "rcu" - }; - -+#ifndef CONFIG_PREEMPT_RT_FULL - /* - * Definitions for rcu_bh torture testing. - */ -@@ -429,6 +430,12 @@ static struct rcu_torture_ops rcu_bh_ops = { - .name = "rcu_bh" - }; - -+#else -+static struct rcu_torture_ops rcu_bh_ops = { -+ .ttype = INVALID_RCU_FLAVOR, -+}; -+#endif -+ - /* - * Don't even think about trying any of these in real life!!! - * The names includes "busted", and they really means it! -diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c -index 5359091..d862a20 100644 ---- a/kernel/rcu/tree.c -+++ b/kernel/rcu/tree.c -@@ -454,11 +454,13 @@ EXPORT_SYMBOL_GPL(rcu_batches_started_sched); - /* - * Return the number of RCU BH batches started thus far for debug & stats. - */ -+#ifndef CONFIG_PREEMPT_RT_FULL - unsigned long rcu_batches_started_bh(void) - { - return rcu_bh_state.gpnum; - } - EXPORT_SYMBOL_GPL(rcu_batches_started_bh); -+#endif - - /* - * Return the number of RCU batches completed thus far for debug & stats. -@@ -563,9 +565,11 @@ void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags, - case RCU_FLAVOR: - rsp = rcu_state_p; - break; -+#ifndef CONFIG_PREEMPT_RT_FULL - case RCU_BH_FLAVOR: - rsp = &rcu_bh_state; - break; -+#endif - case RCU_SCHED_FLAVOR: - rsp = &rcu_sched_state; - break; -@@ -1617,7 +1621,6 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) - int needmore; - struct rcu_data *rdp = this_cpu_ptr(rsp->rda); - -- rcu_nocb_gp_cleanup(rsp, rnp); - rnp->need_future_gp[c & 0x1] = 0; - needmore = rnp->need_future_gp[(c + 1) & 0x1]; - trace_rcu_future_gp(rnp, rdp, c, -@@ -1638,7 +1641,7 @@ static void rcu_gp_kthread_wake(struct rcu_state *rsp) - !READ_ONCE(rsp->gp_flags) || - !rsp->gp_kthread) - return; -- swait_wake(&rsp->gp_wq); -+ swake_up(&rsp->gp_wq); - } - - /* -@@ -2018,6 +2021,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) - int nocb = 0; - struct rcu_data *rdp; - struct rcu_node *rnp = rcu_get_root(rsp); -+ struct swait_queue_head *sq; - - WRITE_ONCE(rsp->gp_activity, jiffies); - raw_spin_lock_irq(&rnp->lock); -@@ -2056,7 +2060,9 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) - needgp = __note_gp_changes(rsp, rnp, rdp) || needgp; - /* smp_mb() provided by prior unlock-lock pair. */ - nocb += rcu_future_gp_cleanup(rsp, rnp); -+ sq = rcu_nocb_gp_get(rnp); - raw_spin_unlock_irq(&rnp->lock); -+ rcu_nocb_gp_cleanup(sq); - cond_resched_rcu_qs(); - WRITE_ONCE(rsp->gp_activity, jiffies); - rcu_gp_slow(rsp, gp_cleanup_delay); -@@ -2257,7 +2263,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) - WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); - WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS); - raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); -- rcu_gp_kthread_wake(rsp); -+ swake_up(&rsp->gp_wq); /* Memory barrier implied by swake_up() path. */ - } - - /* -@@ -2918,7 +2924,7 @@ static void force_quiescent_state(struct rcu_state *rsp) - } - WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS); - raw_spin_unlock_irqrestore(&rnp_old->lock, flags); -- rcu_gp_kthread_wake(rsp); -+ swake_up(&rsp->gp_wq); /* Memory barrier implied by swake_up() path. */ - } - - /* -@@ -3641,7 +3647,7 @@ static void __rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, - raw_spin_unlock_irqrestore(&rnp->lock, flags); - if (wake) { - smp_mb(); /* EGP done before wake_up(). */ -- swait_wake(&rsp->expedited_wq); -+ swake_up(&rsp->expedited_wq); - } - break; - } -@@ -3898,7 +3904,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp) - jiffies_start = jiffies; - - for (;;) { -- ret = swait_event_interruptible_timeout( -+ ret = swait_event_timeout( - rsp->expedited_wq, - sync_rcu_preempt_exp_done(rnp_root), - jiffies_stall); -@@ -4574,8 +4580,8 @@ static void __init rcu_init_one(struct rcu_state *rsp, - } - } - -- init_swait_head(&rsp->gp_wq); -- init_swait_head(&rsp->expedited_wq); -+ init_swait_queue_head(&rsp->gp_wq); -+ init_swait_queue_head(&rsp->expedited_wq); - rnp = rsp->level[rcu_num_lvls - 1]; - for_each_possible_cpu(i) { - while (i > rnp->grphi) -@@ -4695,7 +4701,9 @@ void __init rcu_init(void) - - rcu_bootup_announce(); - rcu_init_geometry(); -+#ifndef CONFIG_PREEMPT_RT_FULL - rcu_init_one(&rcu_bh_state, &rcu_bh_data); -+#endif - rcu_init_one(&rcu_sched_state, &rcu_sched_data); - if (dump_tree) - rcu_dump_rcu_node_tree(&rcu_sched_state); -diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h -index 588509d..c75834d 100644 ---- a/kernel/rcu/tree.h -+++ b/kernel/rcu/tree.h -@@ -27,8 +27,8 @@ - #include - #include - #include -+#include - #include --#include - - /* - * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and -@@ -242,7 +242,7 @@ struct rcu_node { - /* Refused to boost: not sure why, though. */ - /* This can happen due to race conditions. */ - #ifdef CONFIG_RCU_NOCB_CPU -- struct swait_head nocb_gp_wq[2]; -+ struct swait_queue_head nocb_gp_wq[2]; - /* Place for rcu_nocb_kthread() to wait GP. */ - #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ - int need_future_gp[2]; -@@ -394,7 +394,7 @@ struct rcu_data { - atomic_long_t nocb_q_count_lazy; /* invocation (all stages). */ - struct rcu_head *nocb_follower_head; /* CBs ready to invoke. */ - struct rcu_head **nocb_follower_tail; -- struct swait_head nocb_wq; /* For nocb kthreads to sleep on. */ -+ struct swait_queue_head nocb_wq; /* For nocb kthreads to sleep on. */ - struct task_struct *nocb_kthread; - int nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */ - -@@ -473,7 +473,7 @@ struct rcu_state { - unsigned long gpnum; /* Current gp number. */ - unsigned long completed; /* # of last completed gp. */ - struct task_struct *gp_kthread; /* Task for grace periods. */ -- struct swait_head gp_wq; /* Where GP task waits. */ -+ struct swait_queue_head gp_wq; /* Where GP task waits. */ - short gp_flags; /* Commands for GP task. */ - short gp_state; /* GP kthread sleep state. */ - -@@ -505,7 +505,7 @@ struct rcu_state { - atomic_long_t expedited_workdone3; /* # done by others #3. */ - atomic_long_t expedited_normal; /* # fallbacks to normal. */ - atomic_t expedited_need_qs; /* # CPUs left to check in. */ -- struct swait_head expedited_wq; /* Wait for check-ins. */ -+ struct swait_queue_head expedited_wq; /* Wait for check-ins. */ - int ncpus_snap; /* # CPUs seen last time. */ - - unsigned long jiffies_force_qs; /* Time at which to invoke */ -@@ -557,7 +557,9 @@ extern struct list_head rcu_struct_flavors; - */ - extern struct rcu_state rcu_sched_state; - -+#ifndef CONFIG_PREEMPT_RT_FULL - extern struct rcu_state rcu_bh_state; -+#endif - - #ifdef CONFIG_PREEMPT_RCU - extern struct rcu_state rcu_preempt_state; -@@ -605,7 +607,8 @@ static void zero_cpu_stall_ticks(struct rcu_data *rdp); - static void increment_cpu_stall_ticks(void); - static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu); - static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq); --static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp); -+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp); -+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq); - static void rcu_init_one_nocb(struct rcu_node *rnp); - static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, - bool lazy, unsigned long flags); -diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h -index 0d2f27f2..8e119cf 100644 ---- a/kernel/rcu/tree_plugin.h -+++ b/kernel/rcu/tree_plugin.h -@@ -1717,9 +1717,9 @@ early_param("rcu_nocb_poll", parse_rcu_nocb_poll); - * Wake up any no-CBs CPUs' kthreads that were waiting on the just-ended - * grace period. - */ --static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) -+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq) - { -- swait_wake_all(&rnp->nocb_gp_wq[rnp->completed & 0x1]); -+ swake_up_all(sq); - } - - /* -@@ -1735,10 +1735,15 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq) - rnp->need_future_gp[(rnp->completed + 1) & 0x1] += nrq; - } - -+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp) -+{ -+ return &rnp->nocb_gp_wq[rnp->completed & 0x1]; -+} -+ - static void rcu_init_one_nocb(struct rcu_node *rnp) - { -- init_swait_head(&rnp->nocb_gp_wq[0]); -- init_swait_head(&rnp->nocb_gp_wq[1]); -+ init_swait_queue_head(&rnp->nocb_gp_wq[0]); -+ init_swait_queue_head(&rnp->nocb_gp_wq[1]); - } - - #ifndef CONFIG_RCU_NOCB_CPU_ALL -@@ -1763,7 +1768,7 @@ static void wake_nocb_leader(struct rcu_data *rdp, bool force) - if (READ_ONCE(rdp_leader->nocb_leader_sleep) || force) { - /* Prior smp_mb__after_atomic() orders against prior enqueue. */ - WRITE_ONCE(rdp_leader->nocb_leader_sleep, false); -- swait_wake(&rdp_leader->nocb_wq); -+ swake_up(&rdp_leader->nocb_wq); - } - } - -@@ -2079,7 +2084,7 @@ static void nocb_leader_wait(struct rcu_data *my_rdp) - * List was empty, wake up the follower. - * Memory barriers supplied by atomic_long_add(). - */ -- swait_wake(&rdp->nocb_wq); -+ swake_up(&rdp->nocb_wq); - } - } - -@@ -2259,7 +2264,7 @@ void __init rcu_init_nohz(void) - static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) - { - rdp->nocb_tail = &rdp->nocb_head; -- init_swait_head(&rdp->nocb_wq); -+ init_swait_queue_head(&rdp->nocb_wq); - rdp->nocb_follower_tail = &rdp->nocb_follower_head; - } - -@@ -2409,7 +2414,7 @@ static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu) - return false; - } - --static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) -+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq) - { - } - -@@ -2417,6 +2422,11 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq) - { - } - -+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp) -+{ -+ return NULL; -+} -+ - static void rcu_init_one_nocb(struct rcu_node *rnp) - { - } -diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile -index a22fdb6..debedbe 100644 ---- a/kernel/sched/Makefile -+++ b/kernel/sched/Makefile -@@ -13,7 +13,7 @@ endif - - obj-y += core.o loadavg.o clock.o cputime.o - obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o --obj-y += wait.o wait-simple.o work-simple.o completion.o idle.o -+obj-y += wait.o swait.o work-simple.o completion.o idle.o - obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o - obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o - obj-$(CONFIG_SCHEDSTATS) += stats.o -diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c -index 45ebcff..b62cf64 100644 ---- a/kernel/sched/completion.c -+++ b/kernel/sched/completion.c -@@ -32,7 +32,7 @@ void complete(struct completion *x) - - raw_spin_lock_irqsave(&x->wait.lock, flags); - x->done++; -- __swait_wake_locked(&x->wait, TASK_NORMAL, 1); -+ swake_up_locked(&x->wait); - raw_spin_unlock_irqrestore(&x->wait.lock, flags); - } - EXPORT_SYMBOL(complete); -@@ -52,7 +52,7 @@ void complete_all(struct completion *x) - - raw_spin_lock_irqsave(&x->wait.lock, flags); - x->done += UINT_MAX/2; -- __swait_wake_locked(&x->wait, TASK_NORMAL, 0); -+ swake_up_all_locked(&x->wait); - raw_spin_unlock_irqrestore(&x->wait.lock, flags); - } - EXPORT_SYMBOL(complete_all); -@@ -62,9 +62,9 @@ do_wait_for_common(struct completion *x, - long (*action)(long), long timeout, int state) - { - if (!x->done) { -- DEFINE_SWAITER(wait); -+ DECLARE_SWAITQUEUE(wait); - -- swait_prepare_locked(&x->wait, &wait); -+ __prepare_to_swait(&x->wait, &wait); - do { - if (signal_pending_state(state, current)) { - timeout = -ERESTARTSYS; -@@ -75,7 +75,7 @@ do_wait_for_common(struct completion *x, - timeout = action(timeout); - raw_spin_lock_irq(&x->wait.lock); - } while (!x->done && timeout); -- swait_finish_locked(&x->wait, &wait); -+ __finish_swait(&x->wait, &wait); - if (!x->done) - return timeout; - } -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index b2959ea..94827a5 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -3039,16 +3039,6 @@ u64 scheduler_tick_max_deferment(void) - } - #endif - --notrace unsigned long get_parent_ip(unsigned long addr) --{ -- if (in_lock_functions(addr)) { -- addr = CALLER_ADDR2; -- if (in_lock_functions(addr)) -- addr = CALLER_ADDR3; -- } -- return addr; --} -- - #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ - defined(CONFIG_PREEMPT_TRACER)) - -@@ -3070,7 +3060,7 @@ void preempt_count_add(int val) - PREEMPT_MASK - 10); - #endif - if (preempt_count() == val) { -- unsigned long ip = get_parent_ip(CALLER_ADDR1); -+ unsigned long ip = get_lock_parent_ip(); - #ifdef CONFIG_DEBUG_PREEMPT - current->preempt_disable_ip = ip; - #endif -@@ -3097,7 +3087,7 @@ void preempt_count_sub(int val) - #endif - - if (preempt_count() == val) -- trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); -+ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); - __preempt_count_sub(val); - } - EXPORT_SYMBOL(preempt_count_sub); -@@ -3157,7 +3147,7 @@ void migrate_disable(void) - { - struct task_struct *p = current; - -- if (in_atomic()) { -+ if (in_atomic() || irqs_disabled()) { - #ifdef CONFIG_SCHED_DEBUG - p->migrate_disable_atomic++; - #endif -@@ -3180,7 +3170,6 @@ void migrate_disable(void) - preempt_lazy_disable(); - pin_current_cpu(); - p->migrate_disable = 1; -- p->nr_cpus_allowed = 1; - preempt_enable(); - } - EXPORT_SYMBOL(migrate_disable); -@@ -3189,7 +3178,7 @@ void migrate_enable(void) - { - struct task_struct *p = current; - -- if (in_atomic()) { -+ if (in_atomic() || irqs_disabled()) { - #ifdef CONFIG_SCHED_DEBUG - p->migrate_disable_atomic--; - #endif -@@ -3470,7 +3459,7 @@ static void __sched notrace preempt_schedule_common(void) - * set by a RT task. Oterwise we try to avoid beeing scheduled out as long as - * preempt_lazy_count counter >0. - */ --static int preemptible_lazy(void) -+static __always_inline int preemptible_lazy(void) - { - if (test_thread_flag(TIF_NEED_RESCHED)) - return 1; -diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c -new file mode 100644 -index 0000000..205fe36 ---- /dev/null -+++ b/kernel/sched/swait.c -@@ -0,0 +1,143 @@ -+#include -+#include -+#include -+ -+void __init_swait_queue_head(struct swait_queue_head *q, const char *name, -+ struct lock_class_key *key) -+{ -+ raw_spin_lock_init(&q->lock); -+ lockdep_set_class_and_name(&q->lock, key, name); -+ INIT_LIST_HEAD(&q->task_list); -+} -+EXPORT_SYMBOL(__init_swait_queue_head); -+ -+/* -+ * The thing about the wake_up_state() return value; I think we can ignore it. -+ * -+ * If for some reason it would return 0, that means the previously waiting -+ * task is already running, so it will observe condition true (or has already). -+ */ -+void swake_up_locked(struct swait_queue_head *q) -+{ -+ struct swait_queue *curr; -+ -+ if (list_empty(&q->task_list)) -+ return; -+ -+ curr = list_first_entry(&q->task_list, typeof(*curr), task_list); -+ wake_up_process(curr->task); -+ list_del_init(&curr->task_list); -+} -+EXPORT_SYMBOL(swake_up_locked); -+ -+void swake_up_all_locked(struct swait_queue_head *q) -+{ -+ struct swait_queue *curr; -+ int wakes = 0; -+ -+ while (!list_empty(&q->task_list)) { -+ -+ curr = list_first_entry(&q->task_list, typeof(*curr), -+ task_list); -+ wake_up_process(curr->task); -+ list_del_init(&curr->task_list); -+ wakes++; -+ } -+ if (pm_in_action) -+ return; -+ WARN(wakes > 2, "complate_all() with %d waiters\n", wakes); -+} -+EXPORT_SYMBOL(swake_up_all_locked); -+ -+void swake_up(struct swait_queue_head *q) -+{ -+ unsigned long flags; -+ -+ if (!swait_active(q)) -+ return; -+ -+ raw_spin_lock_irqsave(&q->lock, flags); -+ swake_up_locked(q); -+ raw_spin_unlock_irqrestore(&q->lock, flags); -+} -+EXPORT_SYMBOL(swake_up); -+ -+/* -+ * Does not allow usage from IRQ disabled, since we must be able to -+ * release IRQs to guarantee bounded hold time. -+ */ -+void swake_up_all(struct swait_queue_head *q) -+{ -+ struct swait_queue *curr; -+ LIST_HEAD(tmp); -+ -+ if (!swait_active(q)) -+ return; -+ -+ raw_spin_lock_irq(&q->lock); -+ list_splice_init(&q->task_list, &tmp); -+ while (!list_empty(&tmp)) { -+ curr = list_first_entry(&tmp, typeof(*curr), task_list); -+ -+ wake_up_state(curr->task, TASK_NORMAL); -+ list_del_init(&curr->task_list); -+ -+ if (list_empty(&tmp)) -+ break; -+ -+ raw_spin_unlock_irq(&q->lock); -+ raw_spin_lock_irq(&q->lock); -+ } -+ raw_spin_unlock_irq(&q->lock); -+} -+EXPORT_SYMBOL(swake_up_all); -+ -+void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait) -+{ -+ wait->task = current; -+ if (list_empty(&wait->task_list)) -+ list_add(&wait->task_list, &q->task_list); -+} -+ -+void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&q->lock, flags); -+ __prepare_to_swait(q, wait); -+ set_current_state(state); -+ raw_spin_unlock_irqrestore(&q->lock, flags); -+} -+EXPORT_SYMBOL(prepare_to_swait); -+ -+long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state) -+{ -+ if (signal_pending_state(state, current)) -+ return -ERESTARTSYS; -+ -+ prepare_to_swait(q, wait, state); -+ -+ return 0; -+} -+EXPORT_SYMBOL(prepare_to_swait_event); -+ -+void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait) -+{ -+ __set_current_state(TASK_RUNNING); -+ if (!list_empty(&wait->task_list)) -+ list_del_init(&wait->task_list); -+} -+ -+void finish_swait(struct swait_queue_head *q, struct swait_queue *wait) -+{ -+ unsigned long flags; -+ -+ __set_current_state(TASK_RUNNING); -+ -+ if (!list_empty_careful(&wait->task_list)) { -+ raw_spin_lock_irqsave(&q->lock, flags); -+ list_del_init(&wait->task_list); -+ raw_spin_unlock_irqrestore(&q->lock, flags); -+ } -+} -+EXPORT_SYMBOL(finish_swait); -diff --git a/kernel/sched/wait-simple.c b/kernel/sched/wait-simple.c -deleted file mode 100644 -index 7dfa86d..0000000 ---- a/kernel/sched/wait-simple.c -+++ /dev/null -@@ -1,115 +0,0 @@ --/* -- * Simple waitqueues without fancy flags and callbacks -- * -- * (C) 2011 Thomas Gleixner -- * -- * Based on kernel/wait.c -- * -- * For licencing details see kernel-base/COPYING -- */ --#include --#include --#include --#include -- --/* Adds w to head->list. Must be called with head->lock locked. */ --static inline void __swait_enqueue(struct swait_head *head, struct swaiter *w) --{ -- list_add(&w->node, &head->list); -- /* We can't let the condition leak before the setting of head */ -- smp_mb(); --} -- --/* Removes w from head->list. Must be called with head->lock locked. */ --static inline void __swait_dequeue(struct swaiter *w) --{ -- list_del_init(&w->node); --} -- --void __init_swait_head(struct swait_head *head, struct lock_class_key *key) --{ -- raw_spin_lock_init(&head->lock); -- lockdep_set_class(&head->lock, key); -- INIT_LIST_HEAD(&head->list); --} --EXPORT_SYMBOL(__init_swait_head); -- --void swait_prepare_locked(struct swait_head *head, struct swaiter *w) --{ -- w->task = current; -- if (list_empty(&w->node)) -- __swait_enqueue(head, w); --} -- --void swait_prepare(struct swait_head *head, struct swaiter *w, int state) --{ -- unsigned long flags; -- -- raw_spin_lock_irqsave(&head->lock, flags); -- swait_prepare_locked(head, w); -- __set_current_state(state); -- raw_spin_unlock_irqrestore(&head->lock, flags); --} --EXPORT_SYMBOL(swait_prepare); -- --void swait_finish_locked(struct swait_head *head, struct swaiter *w) --{ -- __set_current_state(TASK_RUNNING); -- if (w->task) -- __swait_dequeue(w); --} -- --void swait_finish(struct swait_head *head, struct swaiter *w) --{ -- unsigned long flags; -- -- __set_current_state(TASK_RUNNING); -- if (w->task) { -- raw_spin_lock_irqsave(&head->lock, flags); -- __swait_dequeue(w); -- raw_spin_unlock_irqrestore(&head->lock, flags); -- } --} --EXPORT_SYMBOL(swait_finish); -- --unsigned int --__swait_wake_locked(struct swait_head *head, unsigned int state, unsigned int num) --{ -- struct swaiter *curr, *next; -- int woken = 0; -- -- list_for_each_entry_safe(curr, next, &head->list, node) { -- if (wake_up_state(curr->task, state)) { -- __swait_dequeue(curr); -- /* -- * The waiting task can free the waiter as -- * soon as curr->task = NULL is written, -- * without taking any locks. A memory barrier -- * is required here to prevent the following -- * store to curr->task from getting ahead of -- * the dequeue operation. -- */ -- smp_wmb(); -- curr->task = NULL; -- if (++woken == num) -- break; -- } -- } -- return woken; --} -- --unsigned int --__swait_wake(struct swait_head *head, unsigned int state, unsigned int num) --{ -- unsigned long flags; -- int woken; -- -- if (!swaitqueue_active(head)) -- return 0; -- -- raw_spin_lock_irqsave(&head->lock, flags); -- woken = __swait_wake_locked(head, state, num); -- raw_spin_unlock_irqrestore(&head->lock, flags); -- return woken; --} --EXPORT_SYMBOL(__swait_wake); -diff --git a/kernel/sched/work-simple.c b/kernel/sched/work-simple.c -index e57a052..9ffe405 100644 ---- a/kernel/sched/work-simple.c -+++ b/kernel/sched/work-simple.c -@@ -5,7 +5,7 @@ - * PREEMPT_RT_FULL safe. The callbacks are executed in kthread context. - */ - --#include -+#include - #include - #include - #include -@@ -19,7 +19,7 @@ static struct sworker *glob_worker; - - struct sworker { - struct list_head events; -- struct swait_head wq; -+ struct swait_queue_head wq; - - raw_spinlock_t lock; - -@@ -80,7 +80,7 @@ static struct sworker *swork_create(void) - - INIT_LIST_HEAD(&worker->events); - raw_spin_lock_init(&worker->lock); -- init_swait_head(&worker->wq); -+ init_swait_queue_head(&worker->wq); - - worker->task = kthread_run(swork_kthread, worker, "kswork"); - if (IS_ERR(worker->task)) { -@@ -117,7 +117,7 @@ bool swork_queue(struct swork_event *sev) - list_add_tail(&sev->item, &glob_worker->events); - raw_spin_unlock_irqrestore(&glob_worker->lock, flags); - -- swait_wake(&glob_worker->wq); -+ swake_up(&glob_worker->wq); - return true; - } - EXPORT_SYMBOL_GPL(swork_queue); -diff --git a/kernel/softirq.c b/kernel/softirq.c -index d1e999e..cb9c1d5 100644 ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -287,9 +287,9 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) - - if (preempt_count() == cnt) { - #ifdef CONFIG_DEBUG_PREEMPT -- current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1); -+ current->preempt_disable_ip = get_lock_parent_ip(); - #endif -- trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); -+ trace_preempt_off(CALLER_ADDR0, get_lock_parent_ip()); - } - } - EXPORT_SYMBOL(__local_bh_disable_ip); -@@ -563,8 +563,10 @@ static void do_current_softirqs(void) - do_single_softirq(i); - } - softirq_clr_runner(i); -- unlock_softirq(i); - WARN_ON(current->softirq_nestcnt != 1); -+ local_irq_enable(); -+ unlock_softirq(i); -+ local_irq_disable(); - } - } - -diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c -index 2c5acc8..f84d3b4 100644 ---- a/kernel/stop_machine.c -+++ b/kernel/stop_machine.c -@@ -30,7 +30,7 @@ struct cpu_stop_done { - atomic_t nr_todo; /* nr left to execute */ - bool executed; /* actually executed? */ - int ret; /* collected return value */ -- struct task_struct *waiter; /* woken when nr_todo reaches 0 */ -+ struct completion completion; /* fired if nr_todo reaches 0 */ - }; - - /* the actual stopper, one per every possible cpu, enabled on online cpus */ -@@ -59,7 +59,7 @@ static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo) - { - memset(done, 0, sizeof(*done)); - atomic_set(&done->nr_todo, nr_todo); -- done->waiter = current; -+ init_completion(&done->completion); - } - - /* signal completion unless @done is NULL */ -@@ -68,10 +68,8 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed) - if (done) { - if (executed) - done->executed = true; -- if (atomic_dec_and_test(&done->nr_todo)) { -- wake_up_process(done->waiter); -- done->waiter = NULL; -- } -+ if (atomic_dec_and_test(&done->nr_todo)) -+ complete(&done->completion); - } - } - -@@ -96,22 +94,6 @@ static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work) - raw_spin_unlock_irqrestore(&stopper->lock, flags); - } - --static void wait_for_stop_done(struct cpu_stop_done *done) --{ -- set_current_state(TASK_UNINTERRUPTIBLE); -- while (atomic_read(&done->nr_todo)) { -- schedule(); -- set_current_state(TASK_UNINTERRUPTIBLE); -- } -- /* -- * We need to wait until cpu_stop_signal_done() has cleared -- * done->waiter. -- */ -- while (done->waiter) -- cpu_relax(); -- set_current_state(TASK_RUNNING); --} -- - /** - * stop_one_cpu - stop a cpu - * @cpu: cpu to stop -@@ -143,7 +125,7 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg) - - cpu_stop_init_done(&done, 1); - cpu_stop_queue_work(cpu, &work); -- wait_for_stop_done(&done); -+ wait_for_completion(&done.completion); - return done.executed ? done.ret : -ENOENT; - } - -@@ -302,7 +284,7 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void * - - preempt_enable_nort(); - -- wait_for_stop_done(&done); -+ wait_for_completion(&done.completion); - - return done.executed ? done.ret : -ENOENT; - } -@@ -364,7 +346,7 @@ static int __stop_cpus(const struct cpumask *cpumask, - - cpu_stop_init_done(&done, cpumask_weight(cpumask)); - queue_stop_cpus_work(cpumask, fn, arg, &done, false); -- wait_for_stop_done(&done); -+ wait_for_completion(&done.completion); - return done.executed ? done.ret : -ENOENT; - } - -@@ -495,13 +477,7 @@ static void cpu_stopper_thread(unsigned int cpu) - kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL, - ksym_buf), arg); - -- /* -- * Make sure that the wakeup and setting done->waiter -- * to NULL is atomic. -- */ -- local_irq_disable(); - cpu_stop_signal_done(done, true); -- local_irq_enable(); - goto repeat; - } - } -@@ -663,7 +639,7 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, - ret = multi_cpu_stop(&msdata); - - /* Busy wait for completion. */ -- while (atomic_read(&done.nr_todo)) -+ while (!completion_done(&done.completion)) - cpu_relax(); - - mutex_unlock(&stop_cpus_mutex); -diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c -index 53d7184..1b4ac33 100644 ---- a/kernel/time/tick-broadcast-hrtimer.c -+++ b/kernel/time/tick-broadcast-hrtimer.c -@@ -106,5 +106,6 @@ void tick_setup_hrtimer_broadcast(void) - { - hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - bctimer.function = bc_handler; -+ bctimer.irqsafe = true; - clockevents_register_device(&ce_broadcast_hrtimer); - } -diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c -index 36e584f..069942c 100644 ---- a/kernel/trace/trace_irqsoff.c -+++ b/kernel/trace/trace_irqsoff.c -@@ -421,13 +421,13 @@ void start_critical_timings(void) - { - if (preempt_trace() || irq_trace()) - start_critical_timing(CALLER_ADDR0, CALLER_ADDR1); -- trace_preemptirqsoff_hist(TRACE_START, 1); -+ trace_preemptirqsoff_hist_rcuidle(TRACE_START, 1); - } - EXPORT_SYMBOL_GPL(start_critical_timings); - - void stop_critical_timings(void) - { -- trace_preemptirqsoff_hist(TRACE_STOP, 0); -+ trace_preemptirqsoff_hist_rcuidle(TRACE_STOP, 0); - if (preempt_trace() || irq_trace()) - stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1); - } -@@ -437,7 +437,7 @@ EXPORT_SYMBOL_GPL(stop_critical_timings); - #ifdef CONFIG_PROVE_LOCKING - void time_hardirqs_on(unsigned long a0, unsigned long a1) - { -- trace_preemptirqsoff_hist(IRQS_ON, 0); -+ trace_preemptirqsoff_hist_rcuidle(IRQS_ON, 0); - if (!preempt_trace() && irq_trace()) - stop_critical_timing(a0, a1); - } -@@ -446,7 +446,7 @@ void time_hardirqs_off(unsigned long a0, unsigned long a1) - { - if (!preempt_trace() && irq_trace()) - start_critical_timing(a0, a1); -- trace_preemptirqsoff_hist(IRQS_OFF, 1); -+ trace_preemptirqsoff_hist_rcuidle(IRQS_OFF, 1); - } - - #else /* !CONFIG_PROVE_LOCKING */ -diff --git a/lib/dump_stack.c b/lib/dump_stack.c -index 7ccbc6f..6745c62 100644 ---- a/lib/dump_stack.c -+++ b/lib/dump_stack.c -@@ -33,7 +33,7 @@ asmlinkage __visible void dump_stack(void) - * Permit this cpu to perform nested stack dumps while serialising - * against other CPUs - */ -- migrate_disable(); -+ preempt_disable(); - - retry: - cpu = smp_processor_id(); -@@ -52,7 +52,7 @@ asmlinkage __visible void dump_stack(void) - if (!was_locked) - atomic_set(&dump_lock, -1); - -- migrate_enable(); -+ preempt_enable(); - } - #else - asmlinkage __visible void dump_stack(void) -diff --git a/localversion-rt b/localversion-rt -index 5c84f62..76db1e9 100644 ---- a/localversion-rt -+++ b/localversion-rt -@@ -1 +1 @@ --+rt3 -++rt13 -diff --git a/mm/backing-dev.c b/mm/backing-dev.c -index cbe6f0b..6871838 100644 ---- a/mm/backing-dev.c -+++ b/mm/backing-dev.c -@@ -457,9 +457,9 @@ void wb_congested_put(struct bdi_writeback_congested *congested) - { - unsigned long flags; - -- local_irq_save(flags); -+ local_irq_save_nort(flags); - if (!atomic_dec_and_lock(&congested->refcnt, &cgwb_lock)) { -- local_irq_restore(flags); -+ local_irq_restore_nort(flags); - return; - } - -diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c -index fc08399..18cc59f 100644 ---- a/mm/zsmalloc.c -+++ b/mm/zsmalloc.c -@@ -1289,7 +1289,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle, - class = pool->size_class[class_idx]; - off = obj_idx_to_offset(page, obj_idx, class->size); - -- area = &get_cpu_var(zs_map_area); -+ area = per_cpu_ptr(&zs_map_area, get_cpu_light()); - area->vm_mm = mm; - if (off + class->size <= PAGE_SIZE) { - /* this object is contained entirely within a page */ -@@ -1342,7 +1342,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) - - __zs_unmap_object(area, pages, off, class->size); - } -- put_cpu_var(zs_map_area); -+ put_cpu_light(); - unpin_tag(handle); - } - EXPORT_SYMBOL_GPL(zs_unmap_object); -diff --git a/net/core/dev.c b/net/core/dev.c -index 5ec7abf..0e17592 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2891,7 +2891,11 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, - * This permits __QDISC___STATE_RUNNING owner to get the lock more - * often and dequeue packets faster. - */ -+#ifdef CONFIG_PREEMPT_RT_FULL -+ contended = true; -+#else - contended = qdisc_is_running(q); -+#endif - if (unlikely(contended)) - spin_lock(&q->busylock); - -@@ -2983,7 +2987,7 @@ static inline void xmit_rec_inc(void) - __this_cpu_inc(xmit_recursion); - } - --static inline int xmit_rec_dec(void) -+static inline void xmit_rec_dec(void) - { - __this_cpu_dec(xmit_recursion); - } -diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c -index 57d9436..9378d09 100644 ---- a/virt/kvm/async_pf.c -+++ b/virt/kvm/async_pf.c -@@ -98,8 +98,8 @@ static void async_pf_execute(struct work_struct *work) - * This memory barrier pairs with prepare_to_wait's set_current_state() - */ - smp_mb(); -- if (swaitqueue_active(&vcpu->wq)) -- swait_wake_interruptible(&vcpu->wq); -+ if (swait_active(&vcpu->wq)) -+ swake_up(&vcpu->wq); - - mmput(mm); - kvm_put_kvm(vcpu->kvm); -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index a076690..eeed326 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -226,8 +226,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) - vcpu->kvm = kvm; - vcpu->vcpu_id = id; - vcpu->pid = NULL; -- vcpu->halt_poll_ns = 0; -- init_swait_head(&vcpu->wq); -+ init_swait_queue_head(&vcpu->wq); - kvm_async_pf_vcpu_init(vcpu); - - vcpu->pre_pcpu = -1; -@@ -2002,7 +2001,7 @@ static int kvm_vcpu_check_block(struct kvm_vcpu *vcpu) - void kvm_vcpu_block(struct kvm_vcpu *vcpu) - { - ktime_t start, cur; -- DEFINE_SWAITER(wait); -+ DECLARE_SWAITQUEUE(wait); - bool waited = false; - u64 block_ns; - -@@ -2027,7 +2026,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) - kvm_arch_vcpu_blocking(vcpu); - - for (;;) { -- swait_prepare(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); -+ prepare_to_swait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); - - if (kvm_vcpu_check_block(vcpu) < 0) - break; -@@ -2036,7 +2035,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) - schedule(); - } - -- swait_finish(&vcpu->wq, &wait); -+ finish_swait(&vcpu->wq, &wait); - cur = ktime_get(); - - kvm_arch_vcpu_unblocking(vcpu); -@@ -2068,11 +2067,11 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu) - { - int me; - int cpu = vcpu->cpu; -- struct swait_head *wqp; -+ struct swait_queue_head *wqp; - - wqp = kvm_arch_vcpu_wq(vcpu); -- if (swaitqueue_active(wqp)) { -- swait_wake_interruptible(wqp); -+ if (swait_active(wqp)) { -+ swake_up(wqp); - ++vcpu->stat.halt_wakeup; - } - -@@ -2173,7 +2172,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me) - continue; - if (vcpu == me) - continue; -- if (swaitqueue_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu)) -+ if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu)) - continue; - if (!kvm_vcpu_eligible_for_directed_yield(vcpu)) - continue; - -From 7885305d87ec4603480459d48f5f54ebcc71fe20 Mon Sep 17 00:00:00 2001 -From: Jon Nettleton -Date: Tue, 11 Aug 2015 13:36:09 +0200 -Subject: [PATCH 03/13] gpu: galcore: Don't abuse the dma_* apis - -There is no reason we can't pass the device to the dma_* api's, -so do it. This does not follow the traditional vivante syntax -but it is more correct for in kernel drivers. - -(cherry picked from commit 3010fb04e38c5952d156afb1290e69a44c3017b8) -Signed-off-by: Matus Kral ---- - drivers/gpu/galcore/gc_hal_kernel_device.c | 3 +++ - drivers/gpu/galcore/gc_hal_kernel_device.h | 3 +++ - drivers/gpu/galcore/gc_hal_kernel_os.c | 20 ++++++++++---------- - drivers/gpu/galcore/gc_hal_kernel_probe.c | 5 +++-- - 4 files changed, 19 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/galcore/gc_hal_kernel_device.c b/drivers/gpu/galcore/gc_hal_kernel_device.c -index e99d29f..42a0b24 100644 ---- a/drivers/gpu/galcore/gc_hal_kernel_device.c -+++ b/drivers/gpu/galcore/gc_hal_kernel_device.c -@@ -683,6 +683,7 @@ gckGALDEVICE_Construct( - IN gctINT PowerManagement, - IN gctINT GpuProfiler, - IN gcsDEVICE_CONSTRUCT_ARGS * Args, -+ IN struct device *dev, - OUT gckGALDEVICE *Device - ) - { -@@ -729,6 +730,8 @@ gckGALDEVICE_Construct( - - device->platform = Args->platform; - -+ device->dev = dev; -+ - gcmkONERROR(_DebugfsInit(device)); - - if (gckDEBUGFS_CreateNode( -diff --git a/drivers/gpu/galcore/gc_hal_kernel_device.h b/drivers/gpu/galcore/gc_hal_kernel_device.h -index c94d67c..4d66a6a 100644 ---- a/drivers/gpu/galcore/gc_hal_kernel_device.h -+++ b/drivers/gpu/galcore/gc_hal_kernel_device.h -@@ -30,6 +30,8 @@ - - typedef struct _gckGALDEVICE - { -+ struct device *dev; -+ - /* Objects. */ - gckOS os; - gckKERNEL kernels[gcdMAX_GPU_COUNT]; -@@ -175,6 +177,7 @@ gceSTATUS gckGALDEVICE_Construct( - IN gctINT PowerManagement, - IN gctINT GpuProfiler, - IN gcsDEVICE_CONSTRUCT_ARGS * Args, -+ IN struct device *dev, - OUT gckGALDEVICE *Device - ); - -diff --git a/drivers/gpu/galcore/gc_hal_kernel_os.c b/drivers/gpu/galcore/gc_hal_kernel_os.c -index e05262b..0457574 100644 ---- a/drivers/gpu/galcore/gc_hal_kernel_os.c -+++ b/drivers/gpu/galcore/gc_hal_kernel_os.c -@@ -1092,7 +1092,7 @@ gckOS_MapMemory( - } - - #ifndef NO_DMA_COHERENT -- if (dma_mmap_writecombine(gcvNULL, -+ if (dma_mmap_writecombine(Os->device->dev, - mdlMap->vma, - mdl->addr, - mdl->dmaHandle, -@@ -1411,9 +1411,9 @@ gckOS_AllocateNonPagedMemory( - - #ifndef NO_DMA_COHERENT - #ifdef CONFIG_ARM64 -- addr = dma_alloc_coherent(gcvNULL, -+ addr = dma_alloc_coherent(Os->device->dev, - #else -- addr = dma_alloc_writecombine(gcvNULL, -+ addr = dma_alloc_writecombine(Os->device->dev, - #endif - mdl->numPages * PAGE_SIZE, - &mdl->dmaHandle, -@@ -1442,7 +1442,7 @@ gckOS_AllocateNonPagedMemory( - #if !defined(CONFIG_PPC) - /* Cache invalidate. */ - dma_sync_single_for_device( -- gcvNULL, -+ Os->device->dev, - page_to_phys(page), - bytes, - DMA_FROM_DEVICE); -@@ -1523,7 +1523,7 @@ gckOS_AllocateNonPagedMemory( - } - - #ifndef NO_DMA_COHERENT -- if (dma_mmap_coherent(gcvNULL, -+ if (dma_mmap_coherent(Os->device->dev, - mdlMap->vma, - mdl->addr, - mdl->dmaHandle, -@@ -1681,9 +1681,9 @@ gceSTATUS gckOS_FreeNonPagedMemory( - - #ifndef NO_DMA_COHERENT - #ifdef CONFIG_ARM64 -- dma_free_coherent(gcvNULL, -+ dma_free_coherent(Os->device->dev, - #else -- dma_free_writecombine(gcvNULL, -+ dma_free_writecombine(Os->device->dev, - #endif - mdl->numPages * PAGE_SIZE, - mdl->addr, -@@ -5383,7 +5383,7 @@ gckOS_CacheClean( - } - - dma_sync_single_for_device( -- gcvNULL, -+ Os->device->dev, - (dma_addr_t)Physical, - Bytes, - DMA_TO_DEVICE); -@@ -5457,7 +5457,7 @@ gckOS_CacheInvalidate( - } - - dma_sync_single_for_device( -- gcvNULL, -+ Os->device->dev, - (dma_addr_t)Physical, - Bytes, - DMA_FROM_DEVICE); -@@ -5533,7 +5533,7 @@ gckOS_CacheFlush( - if (Physical != gcvINVALID_ADDRESS) - { - dma_sync_single_for_device( -- gcvNULL, -+ Os->device->dev, - (dma_addr_t)Physical, - Bytes, - DMA_BIDIRECTIONAL); -diff --git a/drivers/gpu/galcore/gc_hal_kernel_probe.c b/drivers/gpu/galcore/gc_hal_kernel_probe.c -index 10098c3..9c904bd 100644 ---- a/drivers/gpu/galcore/gc_hal_kernel_probe.c -+++ b/drivers/gpu/galcore/gc_hal_kernel_probe.c -@@ -758,7 +758,7 @@ static int drv_mmap( - } - - --static int drv_init(void) -+static int drv_init(struct platform_device *pdev) - { - int ret; - int result = -EINVAL; -@@ -812,6 +812,7 @@ static int drv_init(void) - powerManagement, - gpuProfiler, - &args, -+ &pdev->dev, - &device - ); - -@@ -975,7 +976,7 @@ static int gpu_probe(struct platform_device *pdev) - _UpdateModuleParam(&moduleParam); - } - -- ret = drv_init(); -+ ret = drv_init(pdev); - - if (!ret) - { - -From 6376b35377c9cdac5465b89c4401b6ceb3dee91e Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Sun, 3 Apr 2016 13:29:34 +0200 -Subject: [PATCH 04/13] gpu: galcore: -rt13 updates - ---- - drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c -index 1685e57..ef8a9d2 100644 ---- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c -+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c -@@ -7730,8 +7730,8 @@ gckOS_WaitSignal( - : Wait * HZ / 1000; - #endif - -- DEFINE_SWAITER(wait); -- swait_prepare_locked(&signal->obj.wait, &wait); -+ DECLARE_SWAITQUEUE(wait); -+ __prepare_to_swait(&signal->obj.wait, &wait); - - while (gcvTRUE) - { -@@ -7809,7 +7809,7 @@ gckOS_WaitSignal( - } - } - -- swait_finish_locked(&signal->obj.wait, &wait); -+ __finish_swait(&signal->obj.wait, &wait); - - #if gcdDETECT_TIMEOUT - if (complained) - -From a665ce6296067e0685b559d9b355d10718c08ff3 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Sun, 3 Apr 2016 13:32:02 +0200 -Subject: [PATCH 05/13] mxc_hdmi: remove blank_state() and abort_stream() - handling - ---- - drivers/video/mxc/mxc_hdmi.c | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c -index 5587165..df91138 100644 ---- a/drivers/video/mxc/mxc_hdmi.c -+++ b/drivers/video/mxc/mxc_hdmi.c -@@ -1904,7 +1904,6 @@ static void mxc_hdmi_phy_disable(struct mxc_hdmi *hdmi) - if (!hdmi->phy_enabled) - return; - -- mxc_hdmi_abort_stream(); - hdmi_disable_overflow_interrupts(); - - /* Setting PHY to reset status */ -@@ -2489,7 +2488,6 @@ static void hotplug_worker(struct work_struct *work) - } else if (!(hdmi_phy_pol0 & hdmi->plug_mask)) { - /* Plugout event */ - dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n"); -- mxc_hdmi_abort_stream(); - mxc_hdmi_cable_disconnected(hdmi); - #if defined(CONFIG_MXC_HDMI_CEC) - mxc_hdmi_cec_handle(0x0); -@@ -2812,13 +2810,10 @@ static int mxc_hdmi_fb_event(struct notifier_block *nb, - - if (hdmi->hp_state > HDMI_HOTPLUG_DISCONNECTED) - mxc_hdmi_setup(hdmi, val); -- hdmi_set_blank_state(1); - - } else if (*((int *)event->data) != hdmi->blank) { - dev_dbg(&hdmi->pdev->dev, - "event=FB_EVENT_BLANK - BLANK\n"); -- mxc_hdmi_abort_stream(); -- hdmi_set_blank_state(0); - - mxc_hdmi_phy_disable(hdmi); - - -From fa3ba4775d9154b53411fbccd4ecc2599d534d26 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Mon, 4 Apr 2016 01:43:46 +0200 -Subject: [PATCH 06/13] clk: cosmetics, reorder - ---- - drivers/clk/imx/clk-imx6q.c | 23 +++++++++++++---------- - 1 file changed, 13 insertions(+), 10 deletions(-) - -diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c -index d3366be..ceb8703 100644 ---- a/drivers/clk/imx/clk-imx6q.c -+++ b/drivers/clk/imx/clk-imx6q.c -@@ -507,6 +507,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) - clk_data.clk_num = ARRAY_SIZE(clk); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - -+ clk_register_clkdev(clk[IMX6QDL_CLK_GPT_3M], "gpt_3m", "imx-gpt.0"); - clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL); - - if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || -@@ -515,6 +516,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) - imx_clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); - } - -+ imx_clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000); -+ if (clk_on_imx6dl()) -+ imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); -+ - imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); - imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); - imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); -@@ -524,8 +529,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) - imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]); - imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]); - -- imx_clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000); -- imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); - imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_ALT_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); - imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_SEL], clk[IMX6QDL_CLK_AXI_ALT_SEL]); - /* set epdc/pxp axi clock to 200Mhz */ -@@ -543,6 +546,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) - */ - imx_clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]); - -+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) -+ imx_clk_prepare_enable(clk[clks_init_on[i]]); -+ -+ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { -+ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]); -+ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]); -+ } -+ - /* gpu clock initilazation */ - /* - * On mx6dl, 2d core clock sources(sel, podf) is from 3d -@@ -588,14 +599,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) - - imx_register_uart_clocks(uart_clks); - -- for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) -- imx_clk_prepare_enable(clk[clks_init_on[i]]); -- -- if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { -- imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]); -- imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]); -- } -- - imx_clk_set_parent(clk[IMX6QDL_CLK_VPU_AXI_SEL], clk[IMX6QDL_CLK_PLL2_PFD0_352M]); - - if (clk_on_imx6dl()) - -From a0d0665879629b6a24dd94f5206434cb9ab00b87 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Mon, 4 Apr 2016 03:16:05 +0200 -Subject: [PATCH 07/13] add mxc_v4l2.h to linux-libc-dev headers - ---- - include/uapi/linux/Kbuild | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild -index 18c9229..ba55082 100644 ---- a/include/uapi/linux/Kbuild -+++ b/include/uapi/linux/Kbuild -@@ -274,6 +274,7 @@ header-y += msg.h - header-y += mtio.h - header-y += mxcfb.h - header-y += mxc_dcic.h -+header-y += mxc_v4l2.h - header-y += ipu.h - header-y += nbd.h - header-y += ncp_fs.h - -From 8274eed9c6004cda725a67d12a0fd781326eb2dc Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Mon, 4 Apr 2016 03:17:07 +0200 -Subject: [PATCH 08/13] ipu_device: do not overlap stripes - ---- - drivers/mxc/ipu3/ipu_device.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c -index e34e1ba..306639d 100644 ---- a/drivers/mxc/ipu3/ipu_device.c -+++ b/drivers/mxc/ipu3/ipu_device.c -@@ -485,6 +485,7 @@ cs_t colorspaceofpixel(int fmt) - } - EXPORT_SYMBOL_GPL(colorspaceofpixel); - -+inline - int need_csc(int ifmt, int ofmt) - { - cs_t ics, ocs; -@@ -501,26 +502,31 @@ int need_csc(int ifmt, int ofmt) - } - EXPORT_SYMBOL_GPL(need_csc); - -+inline - static int soc_max_in_width(u32 is_vdoa) - { - return is_vdoa ? 8192 : 4096; - } - -+inline - static int soc_max_vdi_in_width(void) - { - return IPU_MAX_VDI_IN_WIDTH; - } -+inline - static int soc_max_in_height(void) - { - return 4096; - } - -+inline - static int soc_max_out_width(void) - { - /* mx51/mx53/mx6q is 1024*/ - return 1024; - } - -+inline - static int soc_max_out_height(void) - { - /* mx51/mx53/mx6q is 1024*/ -@@ -859,7 +865,7 @@ static int update_split_setting(struct ipu_task_entry *t, bool vdi_split) - ret = ipu_calc_stripes_sizes(iw, - ow, - max_width, -- (((unsigned long long)1) << 32), /* 32bit for fractional*/ -+ 0,/*no overlap*/ /* 32bit for fractional*/ - 1, /* equal stripes */ - t->input.format, - t->output.format, -@@ -907,7 +913,7 @@ static int update_split_setting(struct ipu_task_entry *t, bool vdi_split) - ret = ipu_calc_stripes_sizes(ih, - oh, - soc_max_out_height(), -- (((unsigned long long)1) << 32), /* 32bit for fractional*/ -+ 0,/*no overlap*/ /* 32bit for fractional*/ - 0x1 | 0x2, /* equal stripes and vertical */ - t->input.format, - t->output.format, - -From ea5643bec4f6265a95528693c06d330092e05cc8 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Mon, 4 Apr 2016 03:43:49 +0200 -Subject: [PATCH 09/13] Revert "printk: do cond_resched() between lines while - outputting to consoles" - -This reverts commit a623f87a72de35096a9eae7cc7764d0c9533c2e9. - -Conflicts: - kernel/printk/printk.c ---- - include/linux/console.h | 1 - - kernel/panic.c | 3 ++- - kernel/printk/printk.c | 34 +--------------------------------- - 3 files changed, 3 insertions(+), 35 deletions(-) - -diff --git a/include/linux/console.h b/include/linux/console.h -index ea731af..bd19434 100644 ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -150,7 +150,6 @@ extern int console_trylock(void); - extern void console_unlock(void); - extern void console_conditional_schedule(void); - extern void console_unblank(void); --extern void console_flush_on_panic(void); - extern struct tty_driver *console_device(int *); - extern void console_stop(struct console *); - extern void console_start(struct console *); -diff --git a/kernel/panic.c b/kernel/panic.c -index 50d4ae2..d74f25d 100644 ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -157,7 +157,8 @@ void panic(const char *fmt, ...) - * panic() is not being callled from OOPS. - */ - debug_locks_off(); -- console_flush_on_panic(); -+ console_trylock(); -+ console_unlock(); - - if (!panic_blink) - panic_blink = no_blink; -diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c -index f75e4b0..88995de 100644 ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2319,24 +2319,13 @@ void console_unlock(void) - static u64 seen_seq; - unsigned long flags; - bool wake_klogd = false; -- bool do_cond_resched, retry; -+ bool retry; - - if (console_suspended) { - up_console_sem(); - return; - } - -- /* -- * Console drivers are called under logbuf_lock, so -- * @console_may_schedule should be cleared before; however, we may -- * end up dumping a lot of lines, for example, if called from -- * console registration path, and should invoke cond_resched() -- * between lines if allowable. Not doing so can cause a very long -- * scheduling stall on a slow console leading to RCU stall and -- * softlockup warnings which exacerbate the issue with more -- * messages practically incapacitating the system. -- */ -- do_cond_resched = console_may_schedule; - console_may_schedule = 0; - - /* flush buffered message fragment immediately to console */ -@@ -2413,8 +2402,6 @@ void console_unlock(void) - start_critical_timings(); - local_irq_restore(flags); - #endif -- if (do_cond_resched) -- cond_resched(); - } - console_locked = 0; - -@@ -2482,25 +2469,6 @@ void console_unblank(void) - console_unlock(); - } - --/** -- * console_flush_on_panic - flush console content on panic -- * -- * Immediately output all pending messages no matter what. -- */ --void console_flush_on_panic(void) --{ -- /* -- * If someone else is holding the console lock, trylock will fail -- * and may_schedule may be set. Ignore and proceed to unlock so -- * that messages are flushed out. As this can be called from any -- * context and we don't want to get preempted while flushing, -- * ensure may_schedule is cleared. -- */ -- console_trylock(); -- console_may_schedule = 0; -- console_unlock(); --} -- - /* - * Return the console tty driver structure and its associated index - */ - -From cf227a4cf2222a7d4fcc93016656a4dce684e5ae Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Tue, 5 Apr 2016 10:37:31 +0200 -Subject: [PATCH 10/13] default configs update for xbian_defconfig_imx6_mvebu - ---- - arch/arm/configs/xbian_defconfig_imx6 | 6550 --------------------------- - arch/arm/configs/xbian_defconfig_imx6_mvebu | 199 +- - 2 files changed, 65 insertions(+), 6684 deletions(-) - delete mode 100644 arch/arm/configs/xbian_defconfig_imx6 - -diff --git a/arch/arm/configs/xbian_defconfig_imx6 b/arch/arm/configs/xbian_defconfig_imx6 -deleted file mode 100644 -index 20d0117..0000000 ---- a/arch/arm/configs/xbian_defconfig_imx6 -+++ /dev/null -@@ -1,6550 +0,0 @@ --# --# Automatically generated file; DO NOT EDIT. --# Linux/arm 4.4.1 Kernel Configuration --# --CONFIG_ARM=y --CONFIG_ARM_HAS_SG_CHAIN=y --CONFIG_MIGHT_HAVE_PCI=y --CONFIG_SYS_SUPPORTS_APM_EMULATION=y --CONFIG_HAVE_PROC_CPU=y --CONFIG_STACKTRACE_SUPPORT=y --CONFIG_LOCKDEP_SUPPORT=y --CONFIG_TRACE_IRQFLAGS_SUPPORT=y --CONFIG_RWSEM_XCHGADD_ALGORITHM=y --CONFIG_FIX_EARLYCON_MEM=y --CONFIG_GENERIC_HWEIGHT=y --CONFIG_GENERIC_CALIBRATE_DELAY=y --CONFIG_ZONE_DMA=y --CONFIG_NEED_DMA_MAP_STATE=y --CONFIG_ARCH_SUPPORTS_UPROBES=y --CONFIG_VECTORS_BASE=0xffff0000 --CONFIG_ARM_PATCH_PHYS_VIRT=y --CONFIG_GENERIC_BUG=y --CONFIG_PGTABLE_LEVELS=2 --CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" --CONFIG_IRQ_WORK=y --CONFIG_BUILDTIME_EXTABLE_SORT=y -- --# --# General setup --# --CONFIG_INIT_ENV_ARG_LIMIT=32 --CONFIG_CROSS_COMPILE="" --# CONFIG_COMPILE_TEST is not set --CONFIG_LOCALVERSION="" --# CONFIG_LOCALVERSION_AUTO is not set --CONFIG_HAVE_KERNEL_GZIP=y --CONFIG_HAVE_KERNEL_LZMA=y --CONFIG_HAVE_KERNEL_XZ=y --CONFIG_HAVE_KERNEL_LZO=y --CONFIG_HAVE_KERNEL_LZ4=y --CONFIG_KERNEL_GZIP=y --# CONFIG_KERNEL_LZMA is not set --# CONFIG_KERNEL_XZ is not set --# CONFIG_KERNEL_LZO is not set --# CONFIG_KERNEL_LZ4 is not set --CONFIG_DEFAULT_HOSTNAME="xbian" --CONFIG_SWAP=y --CONFIG_SYSVIPC=y --CONFIG_SYSVIPC_SYSCTL=y --CONFIG_POSIX_MQUEUE=y --CONFIG_POSIX_MQUEUE_SYSCTL=y --CONFIG_CROSS_MEMORY_ATTACH=y --CONFIG_FHANDLE=y --# CONFIG_USELIB is not set --# CONFIG_AUDIT is not set --CONFIG_HAVE_ARCH_AUDITSYSCALL=y -- --# --# IRQ subsystem --# --CONFIG_GENERIC_IRQ_PROBE=y --CONFIG_GENERIC_IRQ_SHOW=y --CONFIG_GENERIC_IRQ_SHOW_LEVEL=y --CONFIG_HARDIRQS_SW_RESEND=y --CONFIG_GENERIC_IRQ_CHIP=y --CONFIG_IRQ_DOMAIN=y --CONFIG_IRQ_DOMAIN_HIERARCHY=y --CONFIG_HANDLE_DOMAIN_IRQ=y --# CONFIG_IRQ_DOMAIN_DEBUG is not set --CONFIG_IRQ_FORCED_THREADING=y --CONFIG_SPARSE_IRQ=y --CONFIG_GENERIC_TIME_VSYSCALL=y --CONFIG_GENERIC_CLOCKEVENTS=y --CONFIG_ARCH_HAS_TICK_BROADCAST=y --CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -- --# --# Timers subsystem --# --CONFIG_TICK_ONESHOT=y --CONFIG_NO_HZ_COMMON=y --# CONFIG_HZ_PERIODIC is not set --CONFIG_NO_HZ_IDLE=y --# CONFIG_NO_HZ_FULL is not set --# CONFIG_NO_HZ is not set --CONFIG_HIGH_RES_TIMERS=y -- --# --# CPU/Task time and stats accounting --# --# CONFIG_TICK_CPU_ACCOUNTING is not set --# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set --CONFIG_IRQ_TIME_ACCOUNTING=y --CONFIG_BSD_PROCESS_ACCT=y --CONFIG_BSD_PROCESS_ACCT_V3=y --# CONFIG_TASKSTATS is not set -- --# --# RCU Subsystem --# --CONFIG_PREEMPT_RCU=y --# CONFIG_RCU_EXPERT is not set --CONFIG_SRCU=y --# CONFIG_TASKS_RCU is not set --CONFIG_RCU_STALL_COMMON=y --# CONFIG_TREE_RCU_TRACE is not set --# CONFIG_RCU_EXPEDITE_BOOT is not set --CONFIG_BUILD_BIN2C=y --CONFIG_IKCONFIG=y --CONFIG_IKCONFIG_PROC=y --CONFIG_LOG_BUF_SHIFT=16 --CONFIG_LOG_CPU_MAX_BUF_SHIFT=13 --CONFIG_GENERIC_SCHED_CLOCK=y --CONFIG_CGROUPS=y --# CONFIG_CGROUP_DEBUG is not set --# CONFIG_CGROUP_FREEZER is not set --# CONFIG_CGROUP_PIDS is not set --# CONFIG_CGROUP_DEVICE is not set --# CONFIG_CPUSETS is not set --CONFIG_CGROUP_CPUACCT=y --# CONFIG_MEMCG is not set --# CONFIG_CGROUP_PERF is not set --CONFIG_CGROUP_SCHED=y --CONFIG_FAIR_GROUP_SCHED=y --CONFIG_CFS_BANDWIDTH=y --CONFIG_RT_GROUP_SCHED=y --CONFIG_BLK_CGROUP=y --# CONFIG_DEBUG_BLK_CGROUP is not set --# CONFIG_CHECKPOINT_RESTORE is not set --CONFIG_NAMESPACES=y --CONFIG_UTS_NS=y --CONFIG_IPC_NS=y --CONFIG_USER_NS=y --CONFIG_PID_NS=y --CONFIG_NET_NS=y --# CONFIG_SCHED_AUTOGROUP is not set --# CONFIG_SYSFS_DEPRECATED is not set --CONFIG_RELAY=y --CONFIG_BLK_DEV_INITRD=y --CONFIG_INITRAMFS_SOURCE="" --CONFIG_RD_GZIP=y --# CONFIG_RD_BZIP2 is not set --# CONFIG_RD_LZMA is not set --# CONFIG_RD_XZ is not set --CONFIG_RD_LZO=y --# CONFIG_RD_LZ4 is not set --# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set --CONFIG_SYSCTL=y --CONFIG_ANON_INODES=y --CONFIG_HAVE_UID16=y --CONFIG_BPF=y --CONFIG_EXPERT=y --# CONFIG_UID16 is not set --CONFIG_MULTIUSER=y --# CONFIG_SGETMASK_SYSCALL is not set --CONFIG_SYSFS_SYSCALL=y --CONFIG_SYSCTL_SYSCALL=y --CONFIG_KALLSYMS=y --CONFIG_KALLSYMS_ALL=y --CONFIG_PRINTK=y --CONFIG_BUG=y --CONFIG_BASE_FULL=y --CONFIG_FUTEX=y --CONFIG_EPOLL=y --CONFIG_SIGNALFD=y --CONFIG_TIMERFD=y --CONFIG_EVENTFD=y --# CONFIG_BPF_SYSCALL is not set --CONFIG_SHMEM=y --CONFIG_AIO=y --# CONFIG_ADVISE_SYSCALLS is not set --CONFIG_USERFAULTFD=y --CONFIG_PCI_QUIRKS=y --CONFIG_MEMBARRIER=y --CONFIG_EMBEDDED=y --CONFIG_HAVE_PERF_EVENTS=y --CONFIG_PERF_USE_VMALLOC=y -- --# --# Kernel Performance Events And Counters --# --CONFIG_PERF_EVENTS=y --# CONFIG_DEBUG_PERF_USE_VMALLOC is not set --# CONFIG_VM_EVENT_COUNTERS is not set --# CONFIG_SLUB_DEBUG is not set --# CONFIG_COMPAT_BRK is not set --# CONFIG_SLAB is not set --CONFIG_SLUB=y --# CONFIG_SLOB is not set --# CONFIG_SLUB_CPU_PARTIAL is not set --# CONFIG_SYSTEM_DATA_VERIFICATION is not set --# CONFIG_PROFILING is not set --CONFIG_TRACEPOINTS=y --CONFIG_KEXEC_CORE=y --CONFIG_HAVE_OPROFILE=y --# CONFIG_KPROBES is not set --# CONFIG_JUMP_LABEL is not set --# CONFIG_UPROBES is not set --# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set --CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y --CONFIG_ARCH_USE_BUILTIN_BSWAP=y --CONFIG_HAVE_KPROBES=y --CONFIG_HAVE_KRETPROBES=y --CONFIG_HAVE_OPTPROBES=y --CONFIG_HAVE_ARCH_TRACEHOOK=y --CONFIG_HAVE_DMA_ATTRS=y --CONFIG_HAVE_DMA_CONTIGUOUS=y --CONFIG_GENERIC_SMP_IDLE_THREAD=y --CONFIG_GENERIC_IDLE_POLL_SETUP=y --CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y --CONFIG_HAVE_CLK=y --CONFIG_HAVE_DMA_API_DEBUG=y --CONFIG_HAVE_HW_BREAKPOINT=y --CONFIG_HAVE_PERF_REGS=y --CONFIG_HAVE_PERF_USER_STACK_DUMP=y --CONFIG_HAVE_ARCH_JUMP_LABEL=y --CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y --CONFIG_HAVE_ARCH_SECCOMP_FILTER=y --CONFIG_HAVE_CC_STACKPROTECTOR=y --# CONFIG_CC_STACKPROTECTOR is not set --CONFIG_CC_STACKPROTECTOR_NONE=y --# CONFIG_CC_STACKPROTECTOR_REGULAR is not set --# CONFIG_CC_STACKPROTECTOR_STRONG is not set --CONFIG_HAVE_CONTEXT_TRACKING=y --CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y --CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y --CONFIG_HAVE_MOD_ARCH_SPECIFIC=y --CONFIG_MODULES_USE_ELF_REL=y --CONFIG_ARCH_HAS_ELF_RANDOMIZE=y --CONFIG_CLONE_BACKWARDS=y --CONFIG_OLD_SIGSUSPEND3=y --CONFIG_OLD_SIGACTION=y -- --# --# GCOV-based kernel profiling --# --# CONFIG_GCOV_KERNEL is not set --CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y --CONFIG_HAVE_GENERIC_DMA_COHERENT=y --CONFIG_RT_MUTEXES=y --CONFIG_BASE_SMALL=0 --CONFIG_MODULES=y --# CONFIG_MODULE_FORCE_LOAD is not set --CONFIG_MODULE_UNLOAD=y --# CONFIG_MODULE_FORCE_UNLOAD is not set --CONFIG_MODVERSIONS=y --CONFIG_MODULE_SRCVERSION_ALL=y --# CONFIG_MODULE_SIG is not set --# CONFIG_MODULE_COMPRESS is not set --CONFIG_MODULES_TREE_LOOKUP=y --CONFIG_BLOCK=y --CONFIG_LBDAF=y --CONFIG_BLK_DEV_BSG=y --CONFIG_BLK_DEV_BSGLIB=y --CONFIG_BLK_DEV_INTEGRITY=y --# CONFIG_BLK_DEV_THROTTLING is not set --# CONFIG_BLK_CMDLINE_PARSER is not set -- --# --# Partition Types --# --CONFIG_PARTITION_ADVANCED=y --# CONFIG_ACORN_PARTITION is not set --# CONFIG_AIX_PARTITION is not set --# CONFIG_OSF_PARTITION is not set --# CONFIG_AMIGA_PARTITION is not set --# CONFIG_ATARI_PARTITION is not set --CONFIG_MAC_PARTITION=y --CONFIG_MSDOS_PARTITION=y --CONFIG_BSD_DISKLABEL=y --CONFIG_MINIX_SUBPARTITION=y --CONFIG_SOLARIS_X86_PARTITION=y --CONFIG_UNIXWARE_DISKLABEL=y --CONFIG_LDM_PARTITION=y --# CONFIG_LDM_DEBUG is not set --# CONFIG_SGI_PARTITION is not set --# CONFIG_ULTRIX_PARTITION is not set --CONFIG_SUN_PARTITION=y --CONFIG_KARMA_PARTITION=y --CONFIG_EFI_PARTITION=y --# CONFIG_SYSV68_PARTITION is not set --# CONFIG_CMDLINE_PARTITION is not set -- --# --# IO Schedulers --# --CONFIG_IOSCHED_NOOP=y --CONFIG_IOSCHED_DEADLINE=y --CONFIG_IOSCHED_CFQ=y --# CONFIG_CFQ_GROUP_IOSCHED is not set --CONFIG_IOSCHED_BFQ=y --# CONFIG_CGROUP_BFQIO is not set --# CONFIG_DEFAULT_DEADLINE is not set --# CONFIG_DEFAULT_CFQ is not set --CONFIG_DEFAULT_BFQ=y --# CONFIG_DEFAULT_NOOP is not set --CONFIG_DEFAULT_IOSCHED="bfq" --CONFIG_PADATA=y --CONFIG_ASN1=m --CONFIG_UNINLINE_SPIN_UNLOCK=y --CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y --CONFIG_MUTEX_SPIN_ON_OWNER=y --CONFIG_RWSEM_SPIN_ON_OWNER=y --CONFIG_LOCK_SPIN_ON_OWNER=y --CONFIG_FREEZER=y -- --# --# System Type --# --CONFIG_MMU=y --CONFIG_ARCH_MULTIPLATFORM=y --# CONFIG_ARCH_REALVIEW is not set --# CONFIG_ARCH_VERSATILE is not set --# CONFIG_ARCH_CLPS711X is not set --# CONFIG_ARCH_GEMINI is not set --# CONFIG_ARCH_EBSA110 is not set --# CONFIG_ARCH_EP93XX is not set --# CONFIG_ARCH_FOOTBRIDGE is not set --# CONFIG_ARCH_NETX is not set --# CONFIG_ARCH_IOP13XX is not set --# CONFIG_ARCH_IOP32X is not set --# CONFIG_ARCH_IOP33X is not set --# CONFIG_ARCH_IXP4XX is not set --# CONFIG_ARCH_DOVE is not set --# CONFIG_ARCH_MV78XX0 is not set --# CONFIG_ARCH_ORION5X is not set --# CONFIG_ARCH_MMP is not set --# CONFIG_ARCH_KS8695 is not set --# CONFIG_ARCH_W90X900 is not set --# CONFIG_ARCH_LPC32XX is not set --# CONFIG_ARCH_PXA is not set --# CONFIG_ARCH_RPC is not set --# CONFIG_ARCH_SA1100 is not set --# CONFIG_ARCH_S3C24XX is not set --# CONFIG_ARCH_S3C64XX is not set --# CONFIG_ARCH_DAVINCI is not set --# CONFIG_ARCH_OMAP1 is not set -- --# --# Multiple platform selection --# -- --# --# CPU Core family selection --# --# CONFIG_ARCH_MULTI_V6 is not set --CONFIG_ARCH_MULTI_V7=y --CONFIG_ARCH_MULTI_V6_V7=y --# CONFIG_ARCH_MULTI_CPU_AUTO is not set --# CONFIG_ARCH_VIRT is not set --# CONFIG_ARCH_MVEBU is not set --# CONFIG_ARCH_ALPINE is not set --# CONFIG_ARCH_AT91 is not set --# CONFIG_ARCH_BCM is not set --# CONFIG_ARCH_BERLIN is not set --# CONFIG_ARCH_DIGICOLOR is not set --# CONFIG_ARCH_HIGHBANK is not set --# CONFIG_ARCH_HISI is not set --# CONFIG_ARCH_KEYSTONE is not set --# CONFIG_ARCH_MESON is not set --CONFIG_ARCH_MXC=y --CONFIG_HAVE_IMX_ANATOP=y --CONFIG_HAVE_IMX_GPC=y --CONFIG_HAVE_IMX_MMDC=y --CONFIG_HAVE_IMX_SRC=y -- --# --# Device tree only --# -- --# --# Cortex-A platforms --# --# CONFIG_SOC_IMX50 is not set --# CONFIG_SOC_IMX51 is not set --# CONFIG_SOC_IMX53 is not set --CONFIG_SOC_IMX6=y --CONFIG_SOC_IMX6Q=y --# CONFIG_SOC_IMX6SL is not set --# CONFIG_SOC_IMX6SX is not set --# CONFIG_SOC_IMX6UL is not set --# CONFIG_SOC_IMX7D is not set --# CONFIG_SOC_LS1021A is not set -- --# --# Cortex-A/Cortex-M asymmetric multiprocessing platforms --# --# CONFIG_SOC_VF610 is not set --# CONFIG_ARCH_MEDIATEK is not set -- --# --# TI OMAP/AM/DM/DRA Family --# --# CONFIG_ARCH_OMAP3 is not set --# CONFIG_ARCH_OMAP4 is not set --# CONFIG_SOC_OMAP5 is not set --# CONFIG_SOC_AM33XX is not set --# CONFIG_SOC_AM43XX is not set --# CONFIG_SOC_DRA7XX is not set --# CONFIG_ARCH_QCOM is not set --# CONFIG_ARCH_ROCKCHIP is not set --# CONFIG_ARCH_SOCFPGA is not set --# CONFIG_PLAT_SPEAR is not set --# CONFIG_ARCH_STI is not set --# CONFIG_ARCH_S5PV210 is not set --# CONFIG_ARCH_EXYNOS is not set --# CONFIG_ARCH_SHMOBILE_MULTI is not set --# CONFIG_ARCH_SUNXI is not set --# CONFIG_ARCH_SIRF is not set --# CONFIG_ARCH_TEGRA is not set --# CONFIG_ARCH_UNIPHIER is not set --# CONFIG_ARCH_U8500 is not set --# CONFIG_ARCH_VEXPRESS is not set --# CONFIG_ARCH_WM8850 is not set --# CONFIG_ARCH_ZX is not set --# CONFIG_ARCH_ZYNQ is not set -- --# --# Processor Type --# --CONFIG_CPU_V7=y --CONFIG_CPU_32v6K=y --CONFIG_CPU_32v7=y --CONFIG_CPU_ABRT_EV7=y --CONFIG_CPU_PABRT_V7=y --CONFIG_CPU_CACHE_V7=y --CONFIG_CPU_CACHE_VIPT=y --CONFIG_CPU_COPY_V6=y --CONFIG_CPU_TLB_V7=y --CONFIG_CPU_HAS_ASID=y --CONFIG_CPU_CP15=y --CONFIG_CPU_CP15_MMU=y -- --# --# Processor Features --# --# CONFIG_ARM_LPAE is not set --# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set --CONFIG_ARM_THUMB=y --# CONFIG_ARM_THUMBEE is not set --CONFIG_ARM_VIRT_EXT=y --CONFIG_SWP_EMULATE=y --# CONFIG_CPU_ICACHE_DISABLE is not set --# CONFIG_CPU_BPREDICT_DISABLE is not set --CONFIG_KUSER_HELPERS=y --CONFIG_VDSO=y --CONFIG_OUTER_CACHE=y --CONFIG_OUTER_CACHE_SYNC=y --CONFIG_MIGHT_HAVE_CACHE_L2X0=y --CONFIG_CACHE_L2X0=y --# CONFIG_PL310_ERRATA_588369 is not set --# CONFIG_PL310_ERRATA_727915 is not set --# CONFIG_PL310_ERRATA_753970 is not set --CONFIG_PL310_ERRATA_769419=y --CONFIG_ARM_L1_CACHE_SHIFT_6=y --CONFIG_ARM_L1_CACHE_SHIFT=6 --CONFIG_ARM_DMA_MEM_BUFFERABLE=y --CONFIG_ARM_HEAVY_MB=y --# CONFIG_ARM_KERNMEM_PERMS is not set --CONFIG_MULTI_IRQ_HANDLER=y --# CONFIG_ARM_ERRATA_430973 is not set --# CONFIG_ARM_ERRATA_643719 is not set --# CONFIG_ARM_ERRATA_720789 is not set --CONFIG_ARM_ERRATA_754322=y --# CONFIG_ARM_ERRATA_754327 is not set --CONFIG_ARM_ERRATA_764369=y --CONFIG_ARM_ERRATA_775420=y --# CONFIG_ARM_ERRATA_798181 is not set --# CONFIG_ARM_ERRATA_773022 is not set -- --# --# Bus support --# --CONFIG_PCI=y --CONFIG_PCI_DOMAINS=y --CONFIG_PCI_DOMAINS_GENERIC=y --CONFIG_PCI_SYSCALL=y --# CONFIG_PCI_MSI is not set --# CONFIG_PCI_DEBUG is not set --# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set --# CONFIG_PCI_STUB is not set --# CONFIG_PCI_IOV is not set --# CONFIG_PCI_PRI is not set --# CONFIG_PCI_PASID is not set -- --# --# PCI host controller drivers --# --CONFIG_PCIE_DW=y --CONFIG_PCI_IMX6=y --# CONFIG_PCI_HOST_GENERIC is not set --# CONFIG_PCI_LAYERSCAPE is not set --# CONFIG_PCIE_IPROC is not set --# CONFIG_PCIE_ALTERA is not set --CONFIG_PCIEPORTBUS=y --CONFIG_PCIEAER=y --# CONFIG_PCIE_ECRC is not set --# CONFIG_PCIEAER_INJECT is not set --CONFIG_PCIEASPM=y --# CONFIG_PCIEASPM_DEBUG is not set --CONFIG_PCIEASPM_DEFAULT=y --# CONFIG_PCIEASPM_POWERSAVE is not set --# CONFIG_PCIEASPM_PERFORMANCE is not set --CONFIG_PCIE_PME=y --# CONFIG_PCCARD is not set -- --# --# Kernel Features --# --CONFIG_HAVE_SMP=y --CONFIG_SMP=y --CONFIG_SMP_ON_UP=y --CONFIG_ARM_CPU_TOPOLOGY=y --# CONFIG_SCHED_MC is not set --# CONFIG_SCHED_SMT is not set --CONFIG_HAVE_ARM_SCU=y --# CONFIG_HAVE_ARM_ARCH_TIMER is not set --CONFIG_HAVE_ARM_TWD=y --# CONFIG_MCPM is not set --# CONFIG_BIG_LITTLE is not set --# CONFIG_VMSPLIT_3G is not set --# CONFIG_VMSPLIT_3G_OPT is not set --CONFIG_VMSPLIT_2G=y --# CONFIG_VMSPLIT_1G is not set --CONFIG_PAGE_OFFSET=0x80000000 --CONFIG_NR_CPUS=4 --CONFIG_HOTPLUG_CPU=y --# CONFIG_ARM_PSCI is not set --CONFIG_ARCH_NR_GPIO=0 --CONFIG_PREEMPT=y --CONFIG_HAVE_PREEMPT_LAZY=y --# CONFIG_PREEMPT_NONE is not set --# CONFIG_PREEMPT_VOLUNTARY is not set --CONFIG_PREEMPT__LL=y --# CONFIG_PREEMPT_RTB is not set --# CONFIG_PREEMPT_RT_FULL is not set --CONFIG_PREEMPT_COUNT=y --CONFIG_HZ_FIXED=0 --# CONFIG_HZ_100 is not set --# CONFIG_HZ_200 is not set --# CONFIG_HZ_250 is not set --CONFIG_HZ_300=y --# CONFIG_HZ_500 is not set --# CONFIG_HZ_1000 is not set --CONFIG_HZ=300 --CONFIG_SCHED_HRTICK=y --# CONFIG_THUMB2_KERNEL is not set --CONFIG_AEABI=y --# CONFIG_OABI_COMPAT is not set --# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set --# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set --CONFIG_HAVE_ARCH_PFN_VALID=y --CONFIG_HIGHMEM=y --# CONFIG_HIGHPTE is not set --# CONFIG_CPU_SW_DOMAIN_PAN is not set --CONFIG_HW_PERF_EVENTS=y --CONFIG_ARCH_WANT_GENERAL_HUGETLB=y --# CONFIG_ARM_MODULE_PLTS is not set --CONFIG_FLATMEM=y --CONFIG_FLAT_NODE_MEM_MAP=y --CONFIG_HAVE_MEMBLOCK=y --CONFIG_NO_BOOTMEM=y --CONFIG_MEMORY_ISOLATION=y --# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set --CONFIG_SPLIT_PTLOCK_CPUS=4 --CONFIG_COMPACTION=y --CONFIG_MIGRATION=y --# CONFIG_PHYS_ADDR_T_64BIT is not set --CONFIG_ZONE_DMA_FLAG=1 --CONFIG_BOUNCE=y --# CONFIG_KSM is not set --CONFIG_DEFAULT_MMAP_MIN_ADDR=16384 --CONFIG_CLEANCACHE=y --CONFIG_FRONTSWAP=y --CONFIG_CMA=y --# CONFIG_CMA_DEBUG is not set --# CONFIG_CMA_DEBUGFS is not set --CONFIG_CMA_AREAS=7 --# CONFIG_ZSWAP is not set --# CONFIG_ZPOOL is not set --# CONFIG_ZBUD is not set --# CONFIG_ZSMALLOC is not set --# CONFIG_IDLE_PAGE_TRACKING is not set --CONFIG_FRAME_VECTOR=y --CONFIG_FORCE_MAX_ZONEORDER=14 --CONFIG_ALIGNMENT_TRAP=y --# CONFIG_UACCESS_WITH_MEMCPY is not set --# CONFIG_SECCOMP is not set --CONFIG_SWIOTLB=y --CONFIG_IOMMU_HELPER=y --# CONFIG_XEN is not set -- --# --# Boot options --# --CONFIG_USE_OF=y --CONFIG_ATAGS=y --# CONFIG_DEPRECATED_PARAM_STRUCT is not set --CONFIG_ZBOOT_ROM_TEXT=0 --CONFIG_ZBOOT_ROM_BSS=0 --# CONFIG_ARM_APPENDED_DTB is not set --CONFIG_CMDLINE="console=ttymxc0,115200 rw root=/dev/mmcblk0p2 rootwait" --CONFIG_CMDLINE_FROM_BOOTLOADER=y --# CONFIG_CMDLINE_EXTEND is not set --# CONFIG_CMDLINE_FORCE is not set --CONFIG_KEXEC=y --CONFIG_ATAGS_PROC=y --# CONFIG_CRASH_DUMP is not set --CONFIG_AUTO_ZRELADDR=y -- --# --# CPU Power Management --# -- --# --# CPU Frequency scaling --# --CONFIG_CPU_FREQ=y --CONFIG_CPU_FREQ_GOV_COMMON=y --CONFIG_CPU_FREQ_STAT=y --CONFIG_CPU_FREQ_STAT_DETAILS=y --CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y --# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set --# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set --# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set --# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set --CONFIG_CPU_FREQ_GOV_PERFORMANCE=y --CONFIG_CPU_FREQ_GOV_POWERSAVE=y --CONFIG_CPU_FREQ_GOV_USERSPACE=y --CONFIG_CPU_FREQ_GOV_ONDEMAND=y --CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -- --# --# CPU frequency scaling drivers --# --# CONFIG_CPUFREQ_DT is not set --# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set --CONFIG_ARM_IMX6Q_CPUFREQ=y --# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set --# CONFIG_QORIQ_CPUFREQ is not set -- --# --# CPU Idle --# --CONFIG_CPU_IDLE=y --# CONFIG_CPU_IDLE_GOV_LADDER is not set --CONFIG_CPU_IDLE_GOV_MENU=y --CONFIG_DT_IDLE_STATES=y -- --# --# ARM CPU Idle Drivers --# --CONFIG_ARM_CPUIDLE=y --# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set -- --# --# Floating point emulation --# -- --# --# At least one emulation must be selected --# --CONFIG_VFP=y --CONFIG_VFPv3=y --CONFIG_NEON=y --CONFIG_KERNEL_MODE_NEON=y -- --# --# Userspace binary formats --# --CONFIG_BINFMT_ELF=y --CONFIG_BINFMT_SCRIPT=y --# CONFIG_HAVE_AOUT is not set --CONFIG_BINFMT_MISC=m --# CONFIG_COREDUMP is not set -- --# --# Power management options --# --CONFIG_SUSPEND=y --CONFIG_SUSPEND_FREEZER=y --# CONFIG_SUSPEND_SKIP_SYNC is not set --# CONFIG_HIBERNATION is not set --CONFIG_PM_SLEEP=y --CONFIG_PM_SLEEP_SMP=y --# CONFIG_PM_AUTOSLEEP is not set --# CONFIG_PM_WAKELOCKS is not set --CONFIG_PM=y --# CONFIG_PM_DEBUG is not set --# CONFIG_APM_EMULATION is not set --CONFIG_PM_OPP=y --CONFIG_PM_CLK=y --CONFIG_PM_GENERIC_DOMAINS=y --# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set --CONFIG_PM_GENERIC_DOMAINS_SLEEP=y --CONFIG_PM_GENERIC_DOMAINS_OF=y --CONFIG_CPU_PM=y --CONFIG_ARCH_SUSPEND_POSSIBLE=y --CONFIG_ARM_CPU_SUSPEND=y --CONFIG_ARCH_HIBERNATION_POSSIBLE=y --CONFIG_NET=y --CONFIG_NET_INGRESS=y -- --# --# Networking options --# --CONFIG_PACKET=y --CONFIG_PACKET_DIAG=y --CONFIG_UNIX=y --CONFIG_UNIX_DIAG=y --CONFIG_XFRM=y --CONFIG_XFRM_ALGO=y --CONFIG_XFRM_USER=y --CONFIG_XFRM_SUB_POLICY=y --CONFIG_XFRM_MIGRATE=y --CONFIG_XFRM_STATISTICS=y --CONFIG_XFRM_IPCOMP=m --CONFIG_NET_KEY=y --CONFIG_NET_KEY_MIGRATE=y --CONFIG_INET=y --CONFIG_IP_MULTICAST=y --CONFIG_IP_ADVANCED_ROUTER=y --# CONFIG_IP_FIB_TRIE_STATS is not set --CONFIG_IP_MULTIPLE_TABLES=y --CONFIG_IP_ROUTE_MULTIPATH=y --CONFIG_IP_ROUTE_VERBOSE=y --CONFIG_IP_ROUTE_CLASSID=y --CONFIG_IP_PNP=y --CONFIG_IP_PNP_DHCP=y --CONFIG_IP_PNP_BOOTP=y --# CONFIG_IP_PNP_RARP is not set --CONFIG_NET_IPIP=m --CONFIG_NET_IPGRE_DEMUX=m --CONFIG_NET_IP_TUNNEL=m --CONFIG_NET_IPGRE=m --CONFIG_NET_IPGRE_BROADCAST=y --CONFIG_IP_MROUTE=y --CONFIG_IP_MROUTE_MULTIPLE_TABLES=y --CONFIG_IP_PIMSM_V1=y --CONFIG_IP_PIMSM_V2=y --CONFIG_SYN_COOKIES=y --CONFIG_NET_IPVTI=m --CONFIG_NET_UDP_TUNNEL=m --# CONFIG_NET_FOU is not set --# CONFIG_NET_FOU_IP_TUNNELS is not set --CONFIG_INET_AH=m --CONFIG_INET_ESP=m --CONFIG_INET_IPCOMP=m --CONFIG_INET_XFRM_TUNNEL=m --CONFIG_INET_TUNNEL=m --CONFIG_INET_XFRM_MODE_TRANSPORT=m --CONFIG_INET_XFRM_MODE_TUNNEL=m --CONFIG_INET_XFRM_MODE_BEET=m --CONFIG_INET_LRO=m --CONFIG_INET_DIAG=y --CONFIG_INET_TCP_DIAG=y --CONFIG_INET_UDP_DIAG=m --CONFIG_TCP_CONG_ADVANCED=y --CONFIG_TCP_CONG_BIC=m --CONFIG_TCP_CONG_CUBIC=m --CONFIG_TCP_CONG_WESTWOOD=m --CONFIG_TCP_CONG_HTCP=m --CONFIG_TCP_CONG_HSTCP=m --CONFIG_TCP_CONG_HYBLA=m --CONFIG_TCP_CONG_VEGAS=y --CONFIG_TCP_CONG_SCALABLE=m --CONFIG_TCP_CONG_LP=m --CONFIG_TCP_CONG_VENO=m --CONFIG_TCP_CONG_YEAH=y --CONFIG_TCP_CONG_ILLINOIS=m --CONFIG_TCP_CONG_DCTCP=m --# CONFIG_TCP_CONG_CDG is not set --CONFIG_DEFAULT_VEGAS=y --# CONFIG_DEFAULT_RENO is not set --CONFIG_DEFAULT_TCP_CONG="vegas" --CONFIG_TCP_MD5SIG=y --CONFIG_IPV6=m --CONFIG_IPV6_ROUTER_PREF=y --CONFIG_IPV6_ROUTE_INFO=y --CONFIG_IPV6_OPTIMISTIC_DAD=y --CONFIG_INET6_AH=m --CONFIG_INET6_ESP=m --CONFIG_INET6_IPCOMP=m --CONFIG_IPV6_MIP6=m --CONFIG_IPV6_ILA=m --CONFIG_INET6_XFRM_TUNNEL=m --CONFIG_INET6_TUNNEL=m --CONFIG_INET6_XFRM_MODE_TRANSPORT=m --CONFIG_INET6_XFRM_MODE_TUNNEL=m --CONFIG_INET6_XFRM_MODE_BEET=m --CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m --CONFIG_IPV6_VTI=m --CONFIG_IPV6_SIT=m --CONFIG_IPV6_SIT_6RD=y --CONFIG_IPV6_NDISC_NODETYPE=y --CONFIG_IPV6_TUNNEL=m --CONFIG_IPV6_GRE=m --CONFIG_IPV6_MULTIPLE_TABLES=y --CONFIG_IPV6_SUBTREES=y --CONFIG_IPV6_MROUTE=y --CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y --CONFIG_IPV6_PIMSM_V2=y --CONFIG_NETWORK_SECMARK=y --CONFIG_NET_PTP_CLASSIFY=y --# CONFIG_NETWORK_PHY_TIMESTAMPING is not set --CONFIG_NETFILTER=y --# CONFIG_NETFILTER_DEBUG is not set --CONFIG_NETFILTER_ADVANCED=y --CONFIG_BRIDGE_NETFILTER=m -- --# --# Core Netfilter Configuration --# --CONFIG_NETFILTER_INGRESS=y --CONFIG_NETFILTER_NETLINK=m --CONFIG_NETFILTER_NETLINK_ACCT=m --CONFIG_NETFILTER_NETLINK_QUEUE=m --CONFIG_NETFILTER_NETLINK_LOG=m --CONFIG_NF_CONNTRACK=m --CONFIG_NF_LOG_COMMON=m --CONFIG_NF_CONNTRACK_MARK=y --CONFIG_NF_CONNTRACK_SECMARK=y --CONFIG_NF_CONNTRACK_ZONES=y --CONFIG_NF_CONNTRACK_PROCFS=y --CONFIG_NF_CONNTRACK_EVENTS=y --CONFIG_NF_CONNTRACK_TIMEOUT=y --CONFIG_NF_CONNTRACK_TIMESTAMP=y --CONFIG_NF_CONNTRACK_LABELS=y --CONFIG_NF_CT_PROTO_DCCP=m --CONFIG_NF_CT_PROTO_GRE=m --CONFIG_NF_CT_PROTO_SCTP=m --CONFIG_NF_CT_PROTO_UDPLITE=m --CONFIG_NF_CONNTRACK_AMANDA=m --CONFIG_NF_CONNTRACK_FTP=m --CONFIG_NF_CONNTRACK_H323=m --CONFIG_NF_CONNTRACK_IRC=m --CONFIG_NF_CONNTRACK_BROADCAST=m --CONFIG_NF_CONNTRACK_NETBIOS_NS=m --CONFIG_NF_CONNTRACK_SNMP=m --CONFIG_NF_CONNTRACK_PPTP=m --CONFIG_NF_CONNTRACK_SANE=m --CONFIG_NF_CONNTRACK_SIP=m --CONFIG_NF_CONNTRACK_TFTP=m --CONFIG_NF_CT_NETLINK=m --CONFIG_NF_CT_NETLINK_TIMEOUT=m --# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set --CONFIG_NF_NAT=m --CONFIG_NF_NAT_NEEDED=y --CONFIG_NF_NAT_PROTO_DCCP=m --CONFIG_NF_NAT_PROTO_UDPLITE=m --CONFIG_NF_NAT_PROTO_SCTP=m --CONFIG_NF_NAT_AMANDA=m --CONFIG_NF_NAT_FTP=m --CONFIG_NF_NAT_IRC=m --CONFIG_NF_NAT_SIP=m --CONFIG_NF_NAT_TFTP=m --CONFIG_NF_NAT_REDIRECT=m --CONFIG_NETFILTER_SYNPROXY=m --CONFIG_NF_TABLES=m --CONFIG_NF_TABLES_INET=m --CONFIG_NF_TABLES_NETDEV=m --CONFIG_NFT_EXTHDR=m --CONFIG_NFT_META=m --CONFIG_NFT_CT=m --CONFIG_NFT_RBTREE=m --CONFIG_NFT_HASH=m --CONFIG_NFT_COUNTER=m --CONFIG_NFT_LOG=m --CONFIG_NFT_LIMIT=m --CONFIG_NFT_MASQ=m --CONFIG_NFT_REDIR=m --CONFIG_NFT_NAT=m --CONFIG_NFT_QUEUE=m --CONFIG_NFT_REJECT=m --CONFIG_NFT_REJECT_INET=m --CONFIG_NFT_COMPAT=m --CONFIG_NETFILTER_XTABLES=m -- --# --# Xtables combined modules --# --CONFIG_NETFILTER_XT_MARK=m --CONFIG_NETFILTER_XT_CONNMARK=m --CONFIG_NETFILTER_XT_SET=m -- --# --# Xtables targets --# --CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m --CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m --CONFIG_NETFILTER_XT_TARGET_CONNMARK=m --CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m --CONFIG_NETFILTER_XT_TARGET_CT=m --CONFIG_NETFILTER_XT_TARGET_DSCP=m --CONFIG_NETFILTER_XT_TARGET_HL=m --CONFIG_NETFILTER_XT_TARGET_HMARK=m --CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m --CONFIG_NETFILTER_XT_TARGET_LED=m --CONFIG_NETFILTER_XT_TARGET_LOG=m --CONFIG_NETFILTER_XT_TARGET_MARK=m --CONFIG_NETFILTER_XT_NAT=m --CONFIG_NETFILTER_XT_TARGET_NETMAP=m --CONFIG_NETFILTER_XT_TARGET_NFLOG=m --CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m --CONFIG_NETFILTER_XT_TARGET_NOTRACK=m --CONFIG_NETFILTER_XT_TARGET_RATEEST=m --CONFIG_NETFILTER_XT_TARGET_REDIRECT=m --CONFIG_NETFILTER_XT_TARGET_TEE=m --CONFIG_NETFILTER_XT_TARGET_TPROXY=m --CONFIG_NETFILTER_XT_TARGET_TRACE=m --CONFIG_NETFILTER_XT_TARGET_SECMARK=m --CONFIG_NETFILTER_XT_TARGET_TCPMSS=m --CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -- --# --# Xtables matches --# --CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m --CONFIG_NETFILTER_XT_MATCH_BPF=m --CONFIG_NETFILTER_XT_MATCH_CGROUP=m --CONFIG_NETFILTER_XT_MATCH_CLUSTER=m --CONFIG_NETFILTER_XT_MATCH_COMMENT=m --CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m --CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m --CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m --CONFIG_NETFILTER_XT_MATCH_CONNMARK=m --CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m --CONFIG_NETFILTER_XT_MATCH_CPU=m --CONFIG_NETFILTER_XT_MATCH_DCCP=m --CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m --CONFIG_NETFILTER_XT_MATCH_DSCP=m --CONFIG_NETFILTER_XT_MATCH_ECN=m --CONFIG_NETFILTER_XT_MATCH_ESP=m --CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m --CONFIG_NETFILTER_XT_MATCH_HELPER=m --CONFIG_NETFILTER_XT_MATCH_HL=m --CONFIG_NETFILTER_XT_MATCH_IPCOMP=m --CONFIG_NETFILTER_XT_MATCH_IPRANGE=m --CONFIG_NETFILTER_XT_MATCH_IPVS=m --CONFIG_NETFILTER_XT_MATCH_L2TP=m --CONFIG_NETFILTER_XT_MATCH_LENGTH=m --CONFIG_NETFILTER_XT_MATCH_LIMIT=m --CONFIG_NETFILTER_XT_MATCH_MAC=m --CONFIG_NETFILTER_XT_MATCH_MARK=m --CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m --CONFIG_NETFILTER_XT_MATCH_NFACCT=m --CONFIG_NETFILTER_XT_MATCH_OSF=m --CONFIG_NETFILTER_XT_MATCH_OWNER=m --CONFIG_NETFILTER_XT_MATCH_POLICY=m --CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m --CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m --CONFIG_NETFILTER_XT_MATCH_QUOTA=m --CONFIG_NETFILTER_XT_MATCH_RATEEST=m --CONFIG_NETFILTER_XT_MATCH_REALM=m --CONFIG_NETFILTER_XT_MATCH_RECENT=m --CONFIG_NETFILTER_XT_MATCH_SCTP=m --CONFIG_NETFILTER_XT_MATCH_SOCKET=m --CONFIG_NETFILTER_XT_MATCH_STATE=m --CONFIG_NETFILTER_XT_MATCH_STATISTIC=m --CONFIG_NETFILTER_XT_MATCH_STRING=m --CONFIG_NETFILTER_XT_MATCH_TCPMSS=m --CONFIG_NETFILTER_XT_MATCH_TIME=m --CONFIG_NETFILTER_XT_MATCH_U32=m --CONFIG_IP_SET=m --CONFIG_IP_SET_MAX=256 --CONFIG_IP_SET_BITMAP_IP=m --CONFIG_IP_SET_BITMAP_IPMAC=m --CONFIG_IP_SET_BITMAP_PORT=m --CONFIG_IP_SET_HASH_IP=m --CONFIG_IP_SET_HASH_IPMARK=m --CONFIG_IP_SET_HASH_IPPORT=m --CONFIG_IP_SET_HASH_IPPORTIP=m --CONFIG_IP_SET_HASH_IPPORTNET=m --CONFIG_IP_SET_HASH_MAC=m --CONFIG_IP_SET_HASH_NETPORTNET=m --CONFIG_IP_SET_HASH_NET=m --CONFIG_IP_SET_HASH_NETNET=m --CONFIG_IP_SET_HASH_NETPORT=m --CONFIG_IP_SET_HASH_NETIFACE=m --CONFIG_IP_SET_LIST_SET=m --CONFIG_IP_VS=m --CONFIG_IP_VS_IPV6=y --# CONFIG_IP_VS_DEBUG is not set --CONFIG_IP_VS_TAB_BITS=12 -- --# --# IPVS transport protocol load balancing support --# --CONFIG_IP_VS_PROTO_TCP=y --CONFIG_IP_VS_PROTO_UDP=y --CONFIG_IP_VS_PROTO_AH_ESP=y --CONFIG_IP_VS_PROTO_ESP=y --CONFIG_IP_VS_PROTO_AH=y --CONFIG_IP_VS_PROTO_SCTP=y -- --# --# IPVS scheduler --# --CONFIG_IP_VS_RR=m --CONFIG_IP_VS_WRR=m --CONFIG_IP_VS_LC=m --CONFIG_IP_VS_WLC=m --CONFIG_IP_VS_FO=m --CONFIG_IP_VS_OVF=m --CONFIG_IP_VS_LBLC=m --CONFIG_IP_VS_LBLCR=m --CONFIG_IP_VS_DH=m --CONFIG_IP_VS_SH=m --CONFIG_IP_VS_SED=m --CONFIG_IP_VS_NQ=m -- --# --# IPVS SH scheduler --# --CONFIG_IP_VS_SH_TAB_BITS=8 -- --# --# IPVS application helper --# --CONFIG_IP_VS_FTP=m --CONFIG_IP_VS_NFCT=y --CONFIG_IP_VS_PE_SIP=m -- --# --# IP: Netfilter Configuration --# --CONFIG_NF_DEFRAG_IPV4=m --CONFIG_NF_CONNTRACK_IPV4=m --CONFIG_NF_CONNTRACK_PROC_COMPAT=y --CONFIG_NF_TABLES_IPV4=m --CONFIG_NFT_CHAIN_ROUTE_IPV4=m --CONFIG_NFT_REJECT_IPV4=m --CONFIG_NFT_DUP_IPV4=m --CONFIG_NF_TABLES_ARP=m --CONFIG_NF_DUP_IPV4=m --CONFIG_NF_LOG_ARP=m --CONFIG_NF_LOG_IPV4=m --CONFIG_NF_REJECT_IPV4=m --CONFIG_NF_NAT_IPV4=m --CONFIG_NFT_CHAIN_NAT_IPV4=m --CONFIG_NF_NAT_MASQUERADE_IPV4=m --CONFIG_NFT_MASQ_IPV4=m --CONFIG_NFT_REDIR_IPV4=m --CONFIG_NF_NAT_SNMP_BASIC=m --CONFIG_NF_NAT_PROTO_GRE=m --CONFIG_NF_NAT_PPTP=m --CONFIG_NF_NAT_H323=m --CONFIG_IP_NF_IPTABLES=m --CONFIG_IP_NF_MATCH_AH=m --CONFIG_IP_NF_MATCH_ECN=m --CONFIG_IP_NF_MATCH_RPFILTER=m --CONFIG_IP_NF_MATCH_TTL=m --CONFIG_IP_NF_FILTER=m --CONFIG_IP_NF_TARGET_REJECT=m --CONFIG_IP_NF_TARGET_SYNPROXY=m --CONFIG_IP_NF_NAT=m --CONFIG_IP_NF_TARGET_MASQUERADE=m --CONFIG_IP_NF_TARGET_NETMAP=m --CONFIG_IP_NF_TARGET_REDIRECT=m --CONFIG_IP_NF_MANGLE=m --CONFIG_IP_NF_TARGET_CLUSTERIP=m --CONFIG_IP_NF_TARGET_ECN=m --CONFIG_IP_NF_TARGET_TTL=m --CONFIG_IP_NF_RAW=m --CONFIG_IP_NF_ARPTABLES=m --CONFIG_IP_NF_ARPFILTER=m --CONFIG_IP_NF_ARP_MANGLE=m -- --# --# IPv6: Netfilter Configuration --# --CONFIG_NF_DEFRAG_IPV6=m --CONFIG_NF_CONNTRACK_IPV6=m --CONFIG_NF_TABLES_IPV6=m --CONFIG_NFT_CHAIN_ROUTE_IPV6=m --CONFIG_NFT_REJECT_IPV6=m --CONFIG_NFT_DUP_IPV6=m --CONFIG_NF_DUP_IPV6=m --CONFIG_NF_REJECT_IPV6=m --CONFIG_NF_LOG_IPV6=m --CONFIG_NF_NAT_IPV6=m --CONFIG_NFT_CHAIN_NAT_IPV6=m --CONFIG_NF_NAT_MASQUERADE_IPV6=m --CONFIG_NFT_MASQ_IPV6=m --CONFIG_NFT_REDIR_IPV6=m --CONFIG_IP6_NF_IPTABLES=m --CONFIG_IP6_NF_MATCH_AH=m --CONFIG_IP6_NF_MATCH_EUI64=m --CONFIG_IP6_NF_MATCH_FRAG=m --CONFIG_IP6_NF_MATCH_OPTS=m --CONFIG_IP6_NF_MATCH_HL=m --CONFIG_IP6_NF_MATCH_IPV6HEADER=m --CONFIG_IP6_NF_MATCH_MH=m --CONFIG_IP6_NF_MATCH_RPFILTER=m --CONFIG_IP6_NF_MATCH_RT=m --CONFIG_IP6_NF_TARGET_HL=m --CONFIG_IP6_NF_FILTER=m --CONFIG_IP6_NF_TARGET_REJECT=m --CONFIG_IP6_NF_TARGET_SYNPROXY=m --CONFIG_IP6_NF_MANGLE=m --CONFIG_IP6_NF_RAW=m --CONFIG_IP6_NF_NAT=m --CONFIG_IP6_NF_TARGET_MASQUERADE=m --CONFIG_IP6_NF_TARGET_NPT=m --CONFIG_NF_TABLES_BRIDGE=m --CONFIG_NFT_BRIDGE_META=m --CONFIG_NFT_BRIDGE_REJECT=m --CONFIG_NF_LOG_BRIDGE=m --CONFIG_BRIDGE_NF_EBTABLES=m --CONFIG_BRIDGE_EBT_BROUTE=m --CONFIG_BRIDGE_EBT_T_FILTER=m --CONFIG_BRIDGE_EBT_T_NAT=m --CONFIG_BRIDGE_EBT_802_3=m --CONFIG_BRIDGE_EBT_AMONG=m --CONFIG_BRIDGE_EBT_ARP=m --CONFIG_BRIDGE_EBT_IP=m --CONFIG_BRIDGE_EBT_IP6=m --CONFIG_BRIDGE_EBT_LIMIT=m --CONFIG_BRIDGE_EBT_MARK=m --CONFIG_BRIDGE_EBT_PKTTYPE=m --CONFIG_BRIDGE_EBT_STP=m --CONFIG_BRIDGE_EBT_VLAN=m --CONFIG_BRIDGE_EBT_ARPREPLY=m --CONFIG_BRIDGE_EBT_DNAT=m --CONFIG_BRIDGE_EBT_MARK_T=m --CONFIG_BRIDGE_EBT_REDIRECT=m --CONFIG_BRIDGE_EBT_SNAT=m --CONFIG_BRIDGE_EBT_LOG=m --CONFIG_BRIDGE_EBT_NFLOG=m --CONFIG_IP_DCCP=m --CONFIG_INET_DCCP_DIAG=m -- --# --# DCCP CCIDs Configuration --# --# CONFIG_IP_DCCP_CCID2_DEBUG is not set --CONFIG_IP_DCCP_CCID3=y --# CONFIG_IP_DCCP_CCID3_DEBUG is not set --CONFIG_IP_DCCP_TFRC_LIB=y -- --# --# DCCP Kernel Hacking --# --# CONFIG_IP_DCCP_DEBUG is not set --CONFIG_IP_SCTP=m --CONFIG_SCTP_DBG_OBJCNT=y --CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y --# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set --# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set --CONFIG_SCTP_COOKIE_HMAC_MD5=y --CONFIG_SCTP_COOKIE_HMAC_SHA1=y --CONFIG_RDS=m --# CONFIG_RDS_TCP is not set --# CONFIG_RDS_DEBUG is not set --CONFIG_TIPC=m --CONFIG_TIPC_MEDIA_UDP=y --# CONFIG_ATM is not set --CONFIG_L2TP=m --# CONFIG_L2TP_DEBUGFS is not set --CONFIG_L2TP_V3=y --CONFIG_L2TP_IP=m --CONFIG_L2TP_ETH=m --CONFIG_STP=m --CONFIG_BRIDGE=m --CONFIG_BRIDGE_IGMP_SNOOPING=y --CONFIG_BRIDGE_VLAN_FILTERING=y --CONFIG_HAVE_NET_DSA=y --CONFIG_VLAN_8021Q=m --# CONFIG_VLAN_8021Q_GVRP is not set --# CONFIG_VLAN_8021Q_MVRP is not set --# CONFIG_DECNET is not set --CONFIG_LLC=m --CONFIG_LLC2=m --# CONFIG_IPX is not set --CONFIG_ATALK=m --CONFIG_DEV_APPLETALK=m --CONFIG_IPDDP=m --CONFIG_IPDDP_ENCAP=y --# CONFIG_X25 is not set --# CONFIG_LAPB is not set --# CONFIG_PHONET is not set --# CONFIG_6LOWPAN is not set --# CONFIG_IEEE802154 is not set --CONFIG_NET_SCHED=y -- --# --# Queueing/Scheduling --# --CONFIG_NET_SCH_CBQ=y --CONFIG_NET_SCH_HTB=y --CONFIG_NET_SCH_HFSC=m --CONFIG_NET_SCH_PRIO=y --CONFIG_NET_SCH_MULTIQ=m --CONFIG_NET_SCH_RED=m --CONFIG_NET_SCH_SFB=m --CONFIG_NET_SCH_SFQ=y --CONFIG_NET_SCH_TEQL=m --CONFIG_NET_SCH_TBF=m --CONFIG_NET_SCH_GRED=m --CONFIG_NET_SCH_DSMARK=m --CONFIG_NET_SCH_NETEM=m --CONFIG_NET_SCH_DRR=m --CONFIG_NET_SCH_MQPRIO=m --CONFIG_NET_SCH_CHOKE=m --CONFIG_NET_SCH_QFQ=y --CONFIG_NET_SCH_CODEL=m --CONFIG_NET_SCH_FQ_CODEL=m --CONFIG_NET_SCH_FQ=m --CONFIG_NET_SCH_HHF=m --CONFIG_NET_SCH_PIE=m --CONFIG_NET_SCH_INGRESS=m --CONFIG_NET_SCH_PLUG=m -- --# --# Classification --# --CONFIG_NET_CLS=y --CONFIG_NET_CLS_BASIC=m --CONFIG_NET_CLS_TCINDEX=m --CONFIG_NET_CLS_ROUTE4=m --CONFIG_NET_CLS_FW=m --CONFIG_NET_CLS_U32=m --CONFIG_CLS_U32_PERF=y --CONFIG_CLS_U32_MARK=y --CONFIG_NET_CLS_RSVP=m --CONFIG_NET_CLS_RSVP6=m --CONFIG_NET_CLS_FLOW=m --CONFIG_NET_CLS_CGROUP=m --CONFIG_NET_CLS_BPF=m --CONFIG_NET_CLS_FLOWER=m --CONFIG_NET_EMATCH=y --CONFIG_NET_EMATCH_STACK=32 --CONFIG_NET_EMATCH_CMP=m --CONFIG_NET_EMATCH_NBYTE=m --CONFIG_NET_EMATCH_U32=m --CONFIG_NET_EMATCH_META=m --CONFIG_NET_EMATCH_TEXT=m --CONFIG_NET_EMATCH_CANID=m --CONFIG_NET_EMATCH_IPSET=m --CONFIG_NET_CLS_ACT=y --CONFIG_NET_ACT_POLICE=m --CONFIG_NET_ACT_GACT=m --CONFIG_GACT_PROB=y --CONFIG_NET_ACT_MIRRED=m --CONFIG_NET_ACT_IPT=m --CONFIG_NET_ACT_NAT=m --CONFIG_NET_ACT_PEDIT=m --CONFIG_NET_ACT_SIMP=m --CONFIG_NET_ACT_SKBEDIT=m --CONFIG_NET_ACT_CSUM=m --CONFIG_NET_ACT_VLAN=m --CONFIG_NET_ACT_BPF=m --CONFIG_NET_ACT_CONNMARK=m --CONFIG_NET_CLS_IND=y --CONFIG_NET_SCH_FIFO=y --# CONFIG_DCB is not set --CONFIG_DNS_RESOLVER=y --# CONFIG_BATMAN_ADV is not set --CONFIG_OPENVSWITCH=m --CONFIG_OPENVSWITCH_GRE=m --CONFIG_OPENVSWITCH_VXLAN=m --CONFIG_VSOCKETS=m --CONFIG_NETLINK_MMAP=y --CONFIG_NETLINK_DIAG=m --CONFIG_MPLS=y --CONFIG_NET_MPLS_GSO=m --# CONFIG_MPLS_ROUTING is not set --# CONFIG_HSR is not set --# CONFIG_NET_SWITCHDEV is not set --# CONFIG_NET_L3_MASTER_DEV is not set --CONFIG_RPS=y --CONFIG_RFS_ACCEL=y --CONFIG_XPS=y --CONFIG_CGROUP_NET_PRIO=y --CONFIG_CGROUP_NET_CLASSID=y --CONFIG_NET_RX_BUSY_POLL=y --CONFIG_BQL=y --# CONFIG_BPF_JIT is not set --CONFIG_NET_FLOW_LIMIT=y -- --# --# Network testing --# --# CONFIG_NET_PKTGEN is not set --# CONFIG_NET_DROP_MONITOR is not set --# CONFIG_HAMRADIO is not set --CONFIG_CAN=m --CONFIG_CAN_RAW=m --CONFIG_CAN_BCM=m --CONFIG_CAN_GW=m -- --# --# CAN Device Drivers --# --# CONFIG_CAN_VCAN is not set --# CONFIG_CAN_SLCAN is not set --CONFIG_CAN_DEV=m --CONFIG_CAN_CALC_BITTIMING=y --# CONFIG_CAN_LEDS is not set --# CONFIG_CAN_TI_HECC is not set --CONFIG_CAN_FLEXCAN=m --# CONFIG_CAN_GRCAN is not set --# CONFIG_CAN_RCAR is not set --# CONFIG_CAN_SJA1000 is not set --# CONFIG_CAN_C_CAN is not set --# CONFIG_CAN_M_CAN is not set --# CONFIG_CAN_CC770 is not set -- --# --# CAN SPI interfaces --# --# CONFIG_CAN_MCP251X is not set -- --# --# CAN USB interfaces --# --CONFIG_CAN_EMS_USB=m --CONFIG_CAN_ESD_USB2=m --CONFIG_CAN_GS_USB=m --CONFIG_CAN_KVASER_USB=m --CONFIG_CAN_PEAK_USB=m --CONFIG_CAN_8DEV_USB=m --# CONFIG_CAN_SOFTING is not set --# CONFIG_CAN_DEBUG_DEVICES is not set --CONFIG_IRDA=m -- --# --# IrDA protocols --# --CONFIG_IRLAN=m --CONFIG_IRNET=m --CONFIG_IRCOMM=m --CONFIG_IRDA_ULTRA=y -- --# --# IrDA options --# --# CONFIG_IRDA_CACHE_LAST_LSAP is not set --CONFIG_IRDA_FAST_RR=y --# CONFIG_IRDA_DEBUG is not set -- --# --# Infrared-port device drivers --# -- --# --# SIR device drivers --# --CONFIG_IRTTY_SIR=m -- --# --# Dongle support --# --CONFIG_DONGLE=y --CONFIG_ESI_DONGLE=m --CONFIG_ACTISYS_DONGLE=m --CONFIG_TEKRAM_DONGLE=m --CONFIG_TOIM3232_DONGLE=m --CONFIG_LITELINK_DONGLE=m --CONFIG_MA600_DONGLE=m --CONFIG_GIRBIL_DONGLE=m --CONFIG_MCP2120_DONGLE=m --CONFIG_OLD_BELKIN_DONGLE=m --CONFIG_ACT200L_DONGLE=m --CONFIG_KINGSUN_DONGLE=m --CONFIG_KSDAZZLE_DONGLE=m --CONFIG_KS959_DONGLE=m -- --# --# FIR device drivers --# --CONFIG_USB_IRDA=m --CONFIG_SIGMATEL_FIR=m --CONFIG_VLSI_FIR=m --CONFIG_MCS_FIR=m --CONFIG_BT=y --CONFIG_BT_BREDR=y --CONFIG_BT_RFCOMM=m --CONFIG_BT_RFCOMM_TTY=y --CONFIG_BT_BNEP=m --CONFIG_BT_BNEP_MC_FILTER=y --CONFIG_BT_BNEP_PROTO_FILTER=y --CONFIG_BT_CMTP=m --CONFIG_BT_HIDP=y --CONFIG_BT_HS=y --CONFIG_BT_LE=y --# CONFIG_BT_SELFTEST is not set --# CONFIG_BT_DEBUGFS is not set -- --# --# Bluetooth device drivers --# --CONFIG_BT_INTEL=y --CONFIG_BT_BCM=y --CONFIG_BT_RTL=m --CONFIG_BT_QCA=y --CONFIG_BT_HCIBTUSB=m --CONFIG_BT_HCIBTUSB_BCM=y --CONFIG_BT_HCIBTUSB_RTL=y --# CONFIG_BT_HCIBTSDIO is not set --CONFIG_BT_HCIUART=y --CONFIG_BT_HCIUART_H4=y --CONFIG_BT_HCIUART_BCSP=y --CONFIG_BT_HCIUART_ATH3K=y --CONFIG_BT_HCIUART_LL=y --CONFIG_BT_HCIUART_3WIRE=y --CONFIG_BT_HCIUART_INTEL=y --CONFIG_BT_HCIUART_BCM=y --CONFIG_BT_HCIUART_QCA=y --CONFIG_BT_HCIBCM203X=m --CONFIG_BT_HCIBPA10X=m --CONFIG_BT_HCIBFUSB=m --CONFIG_BT_HCIVHCI=m --CONFIG_BT_MRVL=m --CONFIG_BT_MRVL_SDIO=m --CONFIG_BT_ATH3K=m --CONFIG_BT_WILINK=m --CONFIG_AF_RXRPC=m --# CONFIG_AF_RXRPC_DEBUG is not set --# CONFIG_RXKAD is not set --CONFIG_FIB_RULES=y --CONFIG_WIRELESS=y --CONFIG_WIRELESS_EXT=y --CONFIG_WEXT_CORE=y --CONFIG_WEXT_PROC=y --CONFIG_WEXT_SPY=y --CONFIG_WEXT_PRIV=y --CONFIG_CFG80211=m --# CONFIG_NL80211_TESTMODE is not set --# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set --# CONFIG_CFG80211_REG_DEBUG is not set --# CONFIG_CFG80211_CERTIFICATION_ONUS is not set --# CONFIG_CFG80211_DEFAULT_PS is not set --# CONFIG_CFG80211_DEBUGFS is not set --# CONFIG_CFG80211_INTERNAL_REGDB is not set --CONFIG_CFG80211_CRDA_SUPPORT=y --CONFIG_CFG80211_WEXT=y --CONFIG_CFG80211_WEXT_EXPORT=y --CONFIG_LIB80211=m --CONFIG_LIB80211_CRYPT_WEP=m --CONFIG_LIB80211_CRYPT_CCMP=m --CONFIG_LIB80211_CRYPT_TKIP=m --# CONFIG_LIB80211_DEBUG is not set --CONFIG_MAC80211=m --CONFIG_MAC80211_HAS_RC=y --CONFIG_MAC80211_RC_MINSTREL=y --CONFIG_MAC80211_RC_MINSTREL_HT=y --CONFIG_MAC80211_RC_MINSTREL_VHT=y --CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y --CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" --CONFIG_MAC80211_MESH=y --CONFIG_MAC80211_LEDS=y --# CONFIG_MAC80211_DEBUGFS is not set --# CONFIG_MAC80211_MESSAGE_TRACING is not set --# CONFIG_MAC80211_DEBUG_MENU is not set --CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 --# CONFIG_WIMAX is not set --CONFIG_RFKILL=y --CONFIG_RFKILL_LEDS=y --CONFIG_RFKILL_INPUT=y --CONFIG_RFKILL_REGULATOR=y --CONFIG_RFKILL_GPIO=y --# CONFIG_NET_9P is not set --CONFIG_CAIF=m --# CONFIG_CAIF_DEBUG is not set --CONFIG_CAIF_NETDEV=m --CONFIG_CAIF_USB=m --CONFIG_CEPH_LIB=m --# CONFIG_CEPH_LIB_PRETTYDEBUG is not set --CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y --CONFIG_NFC=m --# CONFIG_NFC_DIGITAL is not set --# CONFIG_NFC_NCI is not set --# CONFIG_NFC_HCI is not set -- --# --# Near Field Communication (NFC) devices --# --# CONFIG_NFC_PN533 is not set --# CONFIG_NFC_SIM is not set --CONFIG_LWTUNNEL=y --CONFIG_HAVE_BPF_JIT=y -- --# --# Device Drivers --# -- --# --# Generic Driver Options --# --CONFIG_UEVENT_HELPER=y --CONFIG_UEVENT_HELPER_PATH="" --CONFIG_DEVTMPFS=y --CONFIG_DEVTMPFS_MOUNT=y --# CONFIG_STANDALONE is not set --# CONFIG_PREVENT_FIRMWARE_BUILD is not set --CONFIG_FW_LOADER=y --CONFIG_FIRMWARE_IN_KERNEL=y --CONFIG_EXTRA_FIRMWARE="" --CONFIG_FW_LOADER_USER_HELPER=y --CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y --CONFIG_WANT_DEV_COREDUMP=y --CONFIG_ALLOW_DEV_COREDUMP=y --CONFIG_DEV_COREDUMP=y --# CONFIG_DEBUG_DRIVER is not set --# CONFIG_DEBUG_DEVRES is not set --# CONFIG_SYS_HYPERVISOR is not set --# CONFIG_GENERIC_CPU_DEVICES is not set --CONFIG_SOC_BUS=y --CONFIG_REGMAP=y --CONFIG_REGMAP_I2C=y --CONFIG_REGMAP_SPI=y --CONFIG_REGMAP_MMIO=y --CONFIG_REGMAP_IRQ=y --CONFIG_DMA_SHARED_BUFFER=y --# CONFIG_FENCE_TRACE is not set --CONFIG_DMA_CMA=y -- --# --# Default contiguous memory area size: --# --CONFIG_CMA_SIZE_MBYTES=288 --CONFIG_CMA_SIZE_SEL_MBYTES=y --# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set --# CONFIG_CMA_SIZE_SEL_MIN is not set --# CONFIG_CMA_SIZE_SEL_MAX is not set --CONFIG_CMA_ALIGNMENT=8 -- --# --# Bus devices --# --# CONFIG_ARM_CCI400_PMU is not set --# CONFIG_ARM_CCI500_PMU is not set --# CONFIG_ARM_CCN is not set --# CONFIG_BRCMSTB_GISB_ARB is not set --CONFIG_IMX_WEIM=y --# CONFIG_VEXPRESS_CONFIG is not set --CONFIG_CONNECTOR=y --CONFIG_PROC_EVENTS=y --CONFIG_MTD=y --# CONFIG_MTD_TESTS is not set --# CONFIG_MTD_REDBOOT_PARTS is not set --CONFIG_MTD_CMDLINE_PARTS=y --# CONFIG_MTD_AFS_PARTS is not set --CONFIG_MTD_OF_PARTS=y --# CONFIG_MTD_AR7_PARTS is not set -- --# --# User Modules And Translation Layers --# --CONFIG_MTD_BLKDEVS=y --CONFIG_MTD_BLOCK=y --# CONFIG_FTL is not set --# CONFIG_NFTL is not set --# CONFIG_INFTL is not set --# CONFIG_RFD_FTL is not set --# CONFIG_SSFDC is not set --# CONFIG_SM_FTL is not set --# CONFIG_MTD_OOPS is not set --# CONFIG_MTD_SWAP is not set --# CONFIG_MTD_PARTITIONED_MASTER is not set -- --# --# RAM/ROM/Flash chip drivers --# --CONFIG_MTD_CFI=y --CONFIG_MTD_JEDECPROBE=y --CONFIG_MTD_GEN_PROBE=y --# CONFIG_MTD_CFI_ADV_OPTIONS is not set --CONFIG_MTD_MAP_BANK_WIDTH_1=y --CONFIG_MTD_MAP_BANK_WIDTH_2=y --CONFIG_MTD_MAP_BANK_WIDTH_4=y --# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set --# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set --# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set --CONFIG_MTD_CFI_I1=y --CONFIG_MTD_CFI_I2=y --# CONFIG_MTD_CFI_I4 is not set --# CONFIG_MTD_CFI_I8 is not set --CONFIG_MTD_CFI_INTELEXT=y --CONFIG_MTD_CFI_AMDSTD=y --CONFIG_MTD_CFI_STAA=y --CONFIG_MTD_CFI_UTIL=y --# CONFIG_MTD_RAM is not set --# CONFIG_MTD_ROM is not set --# CONFIG_MTD_ABSENT is not set -- --# --# Mapping drivers for chip access --# --# CONFIG_MTD_COMPLEX_MAPPINGS is not set --# CONFIG_MTD_PHYSMAP is not set --CONFIG_MTD_PHYSMAP_OF=y --# CONFIG_MTD_IMPA7 is not set --# CONFIG_MTD_INTEL_VR_NOR is not set --# CONFIG_MTD_PLATRAM is not set -- --# --# Self-contained MTD device drivers --# --# CONFIG_MTD_PMC551 is not set --CONFIG_MTD_DATAFLASH=y --# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set --# CONFIG_MTD_DATAFLASH_OTP is not set --# CONFIG_MTD_M25P80 is not set --CONFIG_MTD_SST25L=y --# CONFIG_MTD_SLRAM is not set --# CONFIG_MTD_PHRAM is not set --# CONFIG_MTD_MTDRAM is not set --# CONFIG_MTD_BLOCK2MTD is not set -- --# --# Disk-On-Chip Device Drivers --# --# CONFIG_MTD_DOCG3 is not set --CONFIG_MTD_NAND_ECC=y --# CONFIG_MTD_NAND_ECC_SMC is not set --CONFIG_MTD_NAND=y --# CONFIG_MTD_NAND_ECC_BCH is not set --# CONFIG_MTD_SM_COMMON is not set --# CONFIG_MTD_NAND_DENALI_PCI is not set --# CONFIG_MTD_NAND_DENALI_DT is not set --# CONFIG_MTD_NAND_GPIO is not set --# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set --CONFIG_MTD_NAND_IDS=y --# CONFIG_MTD_NAND_RICOH is not set --# CONFIG_MTD_NAND_DISKONCHIP is not set --# CONFIG_MTD_NAND_DOCG4 is not set --# CONFIG_MTD_NAND_CAFE is not set --# CONFIG_MTD_NAND_NANDSIM is not set --# CONFIG_MTD_NAND_GPMI_NAND is not set --# CONFIG_MTD_NAND_BRCMNAND is not set --# CONFIG_MTD_NAND_PLATFORM is not set --CONFIG_MTD_NAND_MXC=y --# CONFIG_MTD_NAND_HISI504 is not set --# CONFIG_MTD_ONENAND is not set -- --# --# LPDDR & LPDDR2 PCM memory drivers --# --# CONFIG_MTD_LPDDR is not set --# CONFIG_MTD_LPDDR2_NVM is not set --CONFIG_MTD_SPI_NOR=m --CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y --CONFIG_SPI_FSL_QUADSPI=m --CONFIG_MTD_UBI=y --CONFIG_MTD_UBI_WL_THRESHOLD=4096 --CONFIG_MTD_UBI_BEB_LIMIT=20 --# CONFIG_MTD_UBI_FASTMAP is not set --# CONFIG_MTD_UBI_GLUEBI is not set --# CONFIG_MTD_UBI_BLOCK is not set --CONFIG_DTC=y --CONFIG_OF=y --# CONFIG_OF_UNITTEST is not set --CONFIG_OF_FLATTREE=y --CONFIG_OF_EARLY_FLATTREE=y --CONFIG_OF_ADDRESS=y --CONFIG_OF_ADDRESS_PCI=y --CONFIG_OF_IRQ=y --CONFIG_OF_NET=y --CONFIG_OF_MDIO=y --CONFIG_OF_PCI=y --CONFIG_OF_PCI_IRQ=y --CONFIG_OF_MTD=y --CONFIG_OF_RESERVED_MEM=y --# CONFIG_OF_OVERLAY is not set --CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y --# CONFIG_PARPORT is not set --CONFIG_BLK_DEV=y --# CONFIG_BLK_DEV_NULL_BLK is not set --# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set --# CONFIG_BLK_CPQ_CISS_DA is not set --# CONFIG_BLK_DEV_DAC960 is not set --# CONFIG_BLK_DEV_UMEM is not set --# CONFIG_BLK_DEV_COW_COMMON is not set --CONFIG_BLK_DEV_LOOP=m --CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 --CONFIG_BLK_DEV_CRYPTOLOOP=m --# CONFIG_BLK_DEV_DRBD is not set --# CONFIG_BLK_DEV_NBD is not set --# CONFIG_BLK_DEV_SX8 is not set --CONFIG_BLK_DEV_RAM=m --CONFIG_BLK_DEV_RAM_COUNT=16 --CONFIG_BLK_DEV_RAM_SIZE=65536 --CONFIG_CDROM_PKTCDVD=m --CONFIG_CDROM_PKTCDVD_BUFFERS=8 --# CONFIG_CDROM_PKTCDVD_WCACHE is not set --# CONFIG_ATA_OVER_ETH is not set --CONFIG_MG_DISK=y --CONFIG_MG_DISK_RES=0 --# CONFIG_BLK_DEV_RBD is not set --# CONFIG_BLK_DEV_RSXX is not set --# CONFIG_BLK_DEV_NVME is not set -- --# --# Misc devices --# --# CONFIG_SENSORS_LIS3LV02D is not set --# CONFIG_AD525X_DPOT is not set --# CONFIG_DUMMY_IRQ is not set --CONFIG_HWLAT_DETECTOR=m --# CONFIG_PHANTOM is not set --# CONFIG_SGI_IOC4 is not set --CONFIG_TIFM_CORE=y --CONFIG_TIFM_7XX1=y --# CONFIG_ICS932S401 is not set --CONFIG_ENCLOSURE_SERVICES=y --# CONFIG_HP_ILO is not set --# CONFIG_APDS9802ALS is not set --# CONFIG_ISL29003 is not set --# CONFIG_ISL29020 is not set --# CONFIG_SENSORS_TSL2550 is not set --# CONFIG_SENSORS_BH1780 is not set --# CONFIG_SENSORS_BH1770 is not set --# CONFIG_SENSORS_APDS990X is not set --# CONFIG_HMC6352 is not set --# CONFIG_DS1682 is not set --# CONFIG_TI_DAC7512 is not set --# CONFIG_BMP085_I2C is not set --# CONFIG_BMP085_SPI is not set --# CONFIG_USB_SWITCH_FSA9480 is not set --# CONFIG_LATTICE_ECP3_CONFIG is not set --CONFIG_SRAM=y --# CONFIG_C2PORT is not set -- --# --# EEPROM support --# --CONFIG_EEPROM_AT24=y --CONFIG_EEPROM_AT25=y --# CONFIG_EEPROM_LEGACY is not set --CONFIG_EEPROM_MAX6875=y --CONFIG_EEPROM_93CX6=m --# CONFIG_EEPROM_93XX46 is not set --CONFIG_CB710_CORE=y --# CONFIG_CB710_DEBUG is not set --CONFIG_CB710_DEBUG_ASSUMPTIONS=y -- --# --# Texas Instruments shared transport line discipline --# --CONFIG_TI_ST=m --# CONFIG_SENSORS_LIS3_SPI is not set --# CONFIG_SENSORS_LIS3_I2C is not set -- --# --# Altera FPGA firmware download module --# --CONFIG_ALTERA_STAPL=m -- --# --# Intel MIC Bus Driver --# -- --# --# SCIF Bus Driver --# -- --# --# Intel MIC Host Driver --# -- --# --# Intel MIC Card Driver --# -- --# --# SCIF Driver --# -- --# --# Intel MIC Coprocessor State Management (COSM) Drivers --# --CONFIG_ECHO=m --# CONFIG_CXL_BASE is not set --# CONFIG_CXL_KERNEL_API is not set --# CONFIG_CXL_EEH is not set --CONFIG_HAVE_IDE=y --# CONFIG_IDE is not set -- --# --# SCSI device support --# --CONFIG_SCSI_MOD=y --# CONFIG_RAID_ATTRS is not set --CONFIG_SCSI=y --CONFIG_SCSI_DMA=y --CONFIG_SCSI_NETLINK=y --# CONFIG_SCSI_MQ_DEFAULT is not set --CONFIG_SCSI_PROC_FS=y -- --# --# SCSI support type (disk, tape, CD-ROM) --# --CONFIG_BLK_DEV_SD=y --# CONFIG_CHR_DEV_ST is not set --# CONFIG_CHR_DEV_OSST is not set --CONFIG_BLK_DEV_SR=y --CONFIG_BLK_DEV_SR_VENDOR=y --CONFIG_CHR_DEV_SG=y --CONFIG_CHR_DEV_SCH=y --CONFIG_SCSI_ENCLOSURE=y --# CONFIG_SCSI_CONSTANTS is not set --CONFIG_SCSI_LOGGING=y --CONFIG_SCSI_SCAN_ASYNC=y -- --# --# SCSI Transports --# --# CONFIG_SCSI_SPI_ATTRS is not set --CONFIG_SCSI_FC_ATTRS=m --CONFIG_SCSI_ISCSI_ATTRS=m --# CONFIG_SCSI_SAS_ATTRS is not set --# CONFIG_SCSI_SAS_LIBSAS is not set --# CONFIG_SCSI_SRP_ATTRS is not set --CONFIG_SCSI_LOWLEVEL=y --CONFIG_ISCSI_TCP=m --CONFIG_ISCSI_BOOT_SYSFS=m --# CONFIG_SCSI_CXGB3_ISCSI is not set --# CONFIG_SCSI_CXGB4_ISCSI is not set --# CONFIG_SCSI_BNX2_ISCSI is not set --# CONFIG_SCSI_BNX2X_FCOE is not set --# CONFIG_BE2ISCSI is not set --# CONFIG_BLK_DEV_3W_XXXX_RAID is not set --# CONFIG_SCSI_HPSA is not set --# CONFIG_SCSI_3W_9XXX is not set --# CONFIG_SCSI_3W_SAS is not set --# CONFIG_SCSI_ACARD is not set --# CONFIG_SCSI_AACRAID is not set --# CONFIG_SCSI_AIC7XXX is not set --# CONFIG_SCSI_AIC79XX is not set --# CONFIG_SCSI_AIC94XX is not set --# CONFIG_SCSI_MVSAS is not set --# CONFIG_SCSI_MVUMI is not set --# CONFIG_SCSI_ADVANSYS is not set --# CONFIG_SCSI_ARCMSR is not set --# CONFIG_SCSI_ESAS2R is not set --# CONFIG_MEGARAID_NEWGEN is not set --# CONFIG_MEGARAID_LEGACY is not set --# CONFIG_MEGARAID_SAS is not set --# CONFIG_SCSI_MPT3SAS is not set --# CONFIG_SCSI_MPT2SAS is not set --CONFIG_SCSI_UFSHCD=m --# CONFIG_SCSI_UFSHCD_PCI is not set --CONFIG_SCSI_UFSHCD_PLATFORM=m --# CONFIG_SCSI_HPTIOP is not set --CONFIG_LIBFC=m --CONFIG_LIBFCOE=m --# CONFIG_FCOE is not set --# CONFIG_SCSI_SNIC is not set --# CONFIG_SCSI_DMX3191D is not set --# CONFIG_SCSI_FUTURE_DOMAIN is not set --# CONFIG_SCSI_IPS is not set --# CONFIG_SCSI_INITIO is not set --# CONFIG_SCSI_INIA100 is not set --# CONFIG_SCSI_STEX is not set --# CONFIG_SCSI_SYM53C8XX_2 is not set --# CONFIG_SCSI_IPR is not set --# CONFIG_SCSI_QLOGIC_1280 is not set --# CONFIG_SCSI_QLA_FC is not set --# CONFIG_SCSI_QLA_ISCSI is not set --# CONFIG_SCSI_LPFC is not set --# CONFIG_SCSI_DC395x is not set --# CONFIG_SCSI_AM53C974 is not set --# CONFIG_SCSI_NSP32 is not set --# CONFIG_SCSI_WD719X is not set --# CONFIG_SCSI_DEBUG is not set --# CONFIG_SCSI_PMCRAID is not set --# CONFIG_SCSI_PM8001 is not set --# CONFIG_SCSI_BFA_FC is not set --# CONFIG_SCSI_CHELSIO_FCOE is not set --# CONFIG_SCSI_DH is not set --CONFIG_SCSI_OSD_INITIATOR=m --# CONFIG_SCSI_OSD_ULD is not set --CONFIG_SCSI_OSD_DPRINT_SENSE=1 --# CONFIG_SCSI_OSD_DEBUG is not set --CONFIG_ATA=y --# CONFIG_ATA_NONSTANDARD is not set --# CONFIG_ATA_VERBOSE_ERROR is not set --CONFIG_SATA_PMP=y -- --# --# Controllers with non-SFF native interface --# --CONFIG_SATA_AHCI=y --CONFIG_SATA_AHCI_PLATFORM=y --CONFIG_AHCI_IMX=y --# CONFIG_AHCI_CEVA is not set --# CONFIG_AHCI_QORIQ is not set --# CONFIG_SATA_INIC162X is not set --# CONFIG_SATA_ACARD_AHCI is not set --# CONFIG_SATA_SIL24 is not set --CONFIG_ATA_SFF=y -- --# --# SFF controllers with custom DMA interface --# --# CONFIG_PDC_ADMA is not set --# CONFIG_SATA_QSTOR is not set --# CONFIG_SATA_SX4 is not set --CONFIG_ATA_BMDMA=y -- --# --# SATA SFF controllers with BMDMA --# --# CONFIG_ATA_PIIX is not set --# CONFIG_SATA_MV is not set --# CONFIG_SATA_NV is not set --# CONFIG_SATA_PROMISE is not set --# CONFIG_SATA_SIL is not set --# CONFIG_SATA_SIS is not set --# CONFIG_SATA_SVW is not set --# CONFIG_SATA_ULI is not set --# CONFIG_SATA_VIA is not set --# CONFIG_SATA_VITESSE is not set -- --# --# PATA SFF controllers with BMDMA --# --# CONFIG_PATA_ALI is not set --# CONFIG_PATA_AMD is not set --# CONFIG_PATA_ARTOP is not set --# CONFIG_PATA_ATIIXP is not set --# CONFIG_PATA_ATP867X is not set --# CONFIG_PATA_CMD64X is not set --# CONFIG_PATA_CYPRESS is not set --# CONFIG_PATA_EFAR is not set --# CONFIG_PATA_HPT366 is not set --# CONFIG_PATA_HPT37X is not set --# CONFIG_PATA_HPT3X2N is not set --# CONFIG_PATA_HPT3X3 is not set --CONFIG_PATA_IMX=y --# CONFIG_PATA_IT8213 is not set --# CONFIG_PATA_IT821X is not set --# CONFIG_PATA_JMICRON is not set --# CONFIG_PATA_MARVELL is not set --# CONFIG_PATA_NETCELL is not set --# CONFIG_PATA_NINJA32 is not set --# CONFIG_PATA_NS87415 is not set --# CONFIG_PATA_OLDPIIX is not set --# CONFIG_PATA_OPTIDMA is not set --# CONFIG_PATA_PDC2027X is not set --# CONFIG_PATA_PDC_OLD is not set --# CONFIG_PATA_RADISYS is not set --# CONFIG_PATA_RDC is not set --# CONFIG_PATA_SCH is not set --# CONFIG_PATA_SERVERWORKS is not set --# CONFIG_PATA_SIL680 is not set --# CONFIG_PATA_SIS is not set --# CONFIG_PATA_TOSHIBA is not set --# CONFIG_PATA_TRIFLEX is not set --# CONFIG_PATA_VIA is not set --# CONFIG_PATA_WINBOND is not set -- --# --# PIO-only SFF controllers --# --# CONFIG_PATA_CMD640_PCI is not set --# CONFIG_PATA_MPIIX is not set --# CONFIG_PATA_NS87410 is not set --# CONFIG_PATA_OPTI is not set --# CONFIG_PATA_PLATFORM is not set --# CONFIG_PATA_RZ1000 is not set -- --# --# Generic fallback / legacy drivers --# --# CONFIG_ATA_GENERIC is not set --# CONFIG_PATA_LEGACY is not set --CONFIG_MD=y --CONFIG_BLK_DEV_MD=y --CONFIG_MD_AUTODETECT=y --CONFIG_MD_LINEAR=y --CONFIG_MD_RAID0=y --CONFIG_MD_RAID1=y --CONFIG_MD_RAID10=y --CONFIG_MD_RAID456=m --CONFIG_MD_MULTIPATH=m --CONFIG_MD_FAULTY=m --# CONFIG_MD_CLUSTER is not set --CONFIG_BCACHE=m --# CONFIG_BCACHE_DEBUG is not set --# CONFIG_BCACHE_CLOSURES_DEBUG is not set --CONFIG_BLK_DEV_DM_BUILTIN=y --CONFIG_BLK_DEV_DM=m --# CONFIG_DM_MQ_DEFAULT is not set --# CONFIG_DM_DEBUG is not set --CONFIG_DM_BUFIO=m --CONFIG_DM_BIO_PRISON=m --CONFIG_DM_PERSISTENT_DATA=m --# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set --CONFIG_DM_CRYPT=m --CONFIG_DM_SNAPSHOT=m --CONFIG_DM_THIN_PROVISIONING=m --CONFIG_DM_CACHE=m --CONFIG_DM_CACHE_MQ=m --CONFIG_DM_CACHE_SMQ=m --CONFIG_DM_CACHE_CLEANER=m --# CONFIG_DM_ERA is not set --CONFIG_DM_MIRROR=m --CONFIG_DM_LOG_USERSPACE=m --CONFIG_DM_RAID=m --CONFIG_DM_ZERO=m --CONFIG_DM_MULTIPATH=m --CONFIG_DM_MULTIPATH_QL=m --CONFIG_DM_MULTIPATH_ST=m --CONFIG_DM_DELAY=m --CONFIG_DM_UEVENT=y --CONFIG_DM_FLAKEY=m --CONFIG_DM_VERITY=m --# CONFIG_DM_SWITCH is not set --# CONFIG_DM_LOG_WRITES is not set --# CONFIG_TARGET_CORE is not set --# CONFIG_FUSION is not set -- --# --# IEEE 1394 (FireWire) support --# --# CONFIG_FIREWIRE is not set --# CONFIG_FIREWIRE_NOSY is not set --CONFIG_NETDEVICES=y --CONFIG_MII=y --CONFIG_NET_CORE=y --CONFIG_BONDING=m --CONFIG_DUMMY=m --# CONFIG_EQUALIZER is not set --# CONFIG_NET_FC is not set --# CONFIG_IFB is not set --CONFIG_NET_TEAM=m --CONFIG_NET_TEAM_MODE_BROADCAST=m --CONFIG_NET_TEAM_MODE_ROUNDROBIN=m --CONFIG_NET_TEAM_MODE_RANDOM=m --CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m --CONFIG_NET_TEAM_MODE_LOADBALANCE=m --CONFIG_MACVLAN=m --CONFIG_MACVTAP=m --CONFIG_IPVLAN=m --CONFIG_VXLAN=m --# CONFIG_GENEVE is not set --CONFIG_NETCONSOLE=m --CONFIG_NETCONSOLE_DYNAMIC=y --CONFIG_NETPOLL=y --CONFIG_NET_POLL_CONTROLLER=y --CONFIG_TUN=m --# CONFIG_TUN_VNET_CROSS_LE is not set --CONFIG_VETH=m --CONFIG_NLMON=m --# CONFIG_ARCNET is not set -- --# --# CAIF transport drivers --# --# CONFIG_CAIF_TTY is not set --# CONFIG_CAIF_SPI_SLAVE is not set --# CONFIG_CAIF_HSI is not set --# CONFIG_CAIF_VIRTIO is not set -- --# --# Distributed Switch Architecture drivers --# --# CONFIG_NET_DSA_MV88E6XXX is not set --# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set --CONFIG_ETHERNET=y --CONFIG_MDIO=y --# CONFIG_NET_VENDOR_3COM is not set --# CONFIG_NET_VENDOR_ADAPTEC is not set --# CONFIG_NET_VENDOR_AGERE is not set --# CONFIG_NET_VENDOR_ALTEON is not set --# CONFIG_ALTERA_TSE is not set --# CONFIG_NET_VENDOR_AMD is not set --# CONFIG_NET_VENDOR_ARC is not set --CONFIG_NET_VENDOR_ATHEROS=y --CONFIG_ATL2=y --CONFIG_ATL1=y --CONFIG_ATL1E=y --CONFIG_ATL1C=y --CONFIG_ALX=y --# CONFIG_NET_VENDOR_AURORA is not set --# CONFIG_NET_CADENCE is not set --# CONFIG_NET_VENDOR_BROADCOM is not set --# CONFIG_NET_VENDOR_BROCADE is not set --# CONFIG_NET_VENDOR_CAVIUM is not set --# CONFIG_NET_VENDOR_CHELSIO is not set --# CONFIG_NET_VENDOR_CIRRUS is not set --# CONFIG_NET_VENDOR_CISCO is not set --# CONFIG_DM9000 is not set --# CONFIG_DNET is not set --# CONFIG_NET_VENDOR_DEC is not set --# CONFIG_NET_VENDOR_DLINK is not set --# CONFIG_NET_VENDOR_EMULEX is not set --# CONFIG_NET_VENDOR_EZCHIP is not set --# CONFIG_NET_VENDOR_EXAR is not set --# CONFIG_NET_VENDOR_FARADAY is not set --CONFIG_NET_VENDOR_FREESCALE=y --CONFIG_FEC=y --CONFIG_FSL_PQ_MDIO=y --CONFIG_FSL_XGMAC_MDIO=y --CONFIG_GIANFAR=y --# CONFIG_NET_VENDOR_HISILICON is not set --# CONFIG_NET_VENDOR_HP is not set --# CONFIG_NET_VENDOR_INTEL is not set --# CONFIG_JME is not set --# CONFIG_NET_VENDOR_MARVELL is not set --# CONFIG_NET_VENDOR_MELLANOX is not set --# CONFIG_NET_VENDOR_MICREL is not set --# CONFIG_NET_VENDOR_MICROCHIP is not set --# CONFIG_NET_VENDOR_MYRI is not set --# CONFIG_FEALNX is not set --# CONFIG_NET_VENDOR_NATSEMI is not set --# CONFIG_NET_VENDOR_NVIDIA is not set --# CONFIG_NET_VENDOR_OKI is not set --# CONFIG_ETHOC is not set --# CONFIG_NET_PACKET_ENGINE is not set --# CONFIG_NET_VENDOR_QLOGIC is not set --# CONFIG_NET_VENDOR_QUALCOMM is not set --# CONFIG_NET_VENDOR_REALTEK is not set --# CONFIG_NET_VENDOR_RENESAS is not set --# CONFIG_NET_VENDOR_RDC is not set --# CONFIG_NET_VENDOR_ROCKER is not set --# CONFIG_NET_VENDOR_SAMSUNG is not set --# CONFIG_NET_VENDOR_SEEQ is not set --# CONFIG_NET_VENDOR_SILAN is not set --# CONFIG_NET_VENDOR_SIS is not set --# CONFIG_SFC is not set --# CONFIG_NET_VENDOR_SMSC is not set --# CONFIG_NET_VENDOR_STMICRO is not set --# CONFIG_NET_VENDOR_SUN is not set --# CONFIG_NET_VENDOR_SYNOPSYS is not set --# CONFIG_NET_VENDOR_TEHUTI is not set --# CONFIG_NET_VENDOR_TI is not set --# CONFIG_NET_VENDOR_VIA is not set --# CONFIG_NET_VENDOR_WIZNET is not set --# CONFIG_FDDI is not set --# CONFIG_HIPPI is not set --CONFIG_PHYLIB=y -- --# --# MII PHY device drivers --# --# CONFIG_AQUANTIA_PHY is not set --CONFIG_AT803X_PHY=y --# CONFIG_AMD_PHY is not set --# CONFIG_MARVELL_PHY is not set --# CONFIG_DAVICOM_PHY is not set --# CONFIG_QSEMI_PHY is not set --# CONFIG_LXT_PHY is not set --# CONFIG_CICADA_PHY is not set --# CONFIG_VITESSE_PHY is not set --# CONFIG_TERANETICS_PHY is not set --# CONFIG_SMSC_PHY is not set --# CONFIG_BROADCOM_PHY is not set --# CONFIG_BCM7XXX_PHY is not set --# CONFIG_BCM87XX_PHY is not set --# CONFIG_ICPLUS_PHY is not set --# CONFIG_REALTEK_PHY is not set --# CONFIG_NATIONAL_PHY is not set --# CONFIG_STE10XP is not set --# CONFIG_LSI_ET1011C_PHY is not set --# CONFIG_MICREL_PHY is not set --# CONFIG_DP83848_PHY is not set --# CONFIG_DP83867_PHY is not set --CONFIG_MICROCHIP_PHY=m --CONFIG_FIXED_PHY=y --CONFIG_MDIO_BITBANG=y --CONFIG_MDIO_GPIO=y --CONFIG_MDIO_BUS_MUX=y --CONFIG_MDIO_BUS_MUX_GPIO=y --CONFIG_MDIO_BUS_MUX_MMIOREG=y --CONFIG_MDIO_BCM_UNIMAC=y --# CONFIG_MICREL_KS8995MA is not set --CONFIG_PPP=m --CONFIG_PPP_BSDCOMP=m --CONFIG_PPP_DEFLATE=m --CONFIG_PPP_FILTER=y --CONFIG_PPP_MPPE=m --CONFIG_PPP_MULTILINK=y --CONFIG_PPPOE=m --CONFIG_PPTP=m --CONFIG_PPPOL2TP=m --CONFIG_PPP_ASYNC=m --CONFIG_PPP_SYNC_TTY=m --CONFIG_SLIP=m --CONFIG_SLHC=m --CONFIG_SLIP_COMPRESSED=y --CONFIG_SLIP_SMART=y --CONFIG_SLIP_MODE_SLIP6=y --CONFIG_USB_NET_DRIVERS=y --CONFIG_USB_CATC=m --CONFIG_USB_KAWETH=m --CONFIG_USB_PEGASUS=m --CONFIG_USB_RTL8150=m --CONFIG_USB_RTL8152=m --CONFIG_USB_LAN78XX=m --CONFIG_USB_USBNET=m --CONFIG_USB_NET_AX8817X=m --CONFIG_USB_NET_AX88179_178A=m --CONFIG_USB_NET_CDCETHER=m --CONFIG_USB_NET_CDC_EEM=m --CONFIG_USB_NET_CDC_NCM=m --CONFIG_USB_NET_HUAWEI_CDC_NCM=m --CONFIG_USB_NET_CDC_MBIM=m --CONFIG_USB_NET_DM9601=m --CONFIG_USB_NET_SR9700=m --CONFIG_USB_NET_SR9800=m --CONFIG_USB_NET_SMSC75XX=m --CONFIG_USB_NET_SMSC95XX=m --CONFIG_USB_NET_GL620A=m --CONFIG_USB_NET_NET1080=m --CONFIG_USB_NET_PLUSB=m --CONFIG_USB_NET_MCS7830=m --CONFIG_USB_NET_RNDIS_HOST=m --CONFIG_USB_NET_CDC_SUBSET=m --CONFIG_USB_ALI_M5632=y --CONFIG_USB_AN2720=y --CONFIG_USB_BELKIN=y --CONFIG_USB_ARMLINUX=y --CONFIG_USB_EPSON2888=y --CONFIG_USB_KC2190=y --CONFIG_USB_NET_ZAURUS=m --CONFIG_USB_NET_CX82310_ETH=m --CONFIG_USB_NET_KALMIA=m --CONFIG_USB_NET_QMI_WWAN=m --CONFIG_USB_HSO=m --CONFIG_USB_NET_INT51X1=m --CONFIG_USB_IPHETH=m --CONFIG_USB_SIERRA_NET=m --CONFIG_USB_VL600=m --CONFIG_USB_NET_CH9200=m --CONFIG_WLAN=y --CONFIG_LIBERTAS_THINFIRM=m --# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set --CONFIG_LIBERTAS_THINFIRM_USB=m --CONFIG_ATMEL=m --CONFIG_PCI_ATMEL=m --CONFIG_AT76C50X_USB=m --CONFIG_PRISM54=m --CONFIG_USB_ZD1201=m --CONFIG_USB_NET_RNDIS_WLAN=m --CONFIG_ADM8211=m --CONFIG_RTL8180=m --CONFIG_RTL8187=m --CONFIG_RTL8187_LEDS=y --CONFIG_MAC80211_HWSIM=m --CONFIG_MWL8K=m --CONFIG_ATH_COMMON=m --CONFIG_ATH_CARDS=m --# CONFIG_ATH_DEBUG is not set --CONFIG_ATH5K=m --# CONFIG_ATH5K_DEBUG is not set --# CONFIG_ATH5K_TRACER is not set --CONFIG_ATH5K_PCI=y --CONFIG_ATH9K_HW=m --CONFIG_ATH9K_COMMON=m --CONFIG_ATH9K_BTCOEX_SUPPORT=y --CONFIG_ATH9K=m --CONFIG_ATH9K_PCI=y --CONFIG_ATH9K_AHB=y --# CONFIG_ATH9K_DEBUGFS is not set --# CONFIG_ATH9K_DYNACK is not set --CONFIG_ATH9K_WOW=y --CONFIG_ATH9K_RFKILL=y --CONFIG_ATH9K_CHANNEL_CONTEXT=y --CONFIG_ATH9K_PCOEM=y --CONFIG_ATH9K_HTC=m --# CONFIG_ATH9K_HTC_DEBUGFS is not set --CONFIG_CARL9170=m --CONFIG_CARL9170_LEDS=y --CONFIG_CARL9170_WPC=y --CONFIG_CARL9170_HWRNG=y --CONFIG_ATH6KL=m --CONFIG_ATH6KL_SDIO=m --CONFIG_ATH6KL_USB=m --# CONFIG_ATH6KL_DEBUG is not set --# CONFIG_ATH6KL_TRACING is not set --CONFIG_AR5523=m --CONFIG_WIL6210=m --CONFIG_WIL6210_ISR_COR=y --CONFIG_WIL6210_TRACING=y --CONFIG_ATH10K=m --CONFIG_ATH10K_PCI=m --# CONFIG_ATH10K_DEBUG is not set --# CONFIG_ATH10K_DEBUGFS is not set --# CONFIG_ATH10K_TRACING is not set --CONFIG_WCN36XX=m --# CONFIG_WCN36XX_DEBUGFS is not set --CONFIG_B43=m --CONFIG_B43_BCMA=y --CONFIG_B43_SSB=y --CONFIG_B43_BUSES_BCMA_AND_SSB=y --# CONFIG_B43_BUSES_BCMA is not set --# CONFIG_B43_BUSES_SSB is not set --CONFIG_B43_PCI_AUTOSELECT=y --CONFIG_B43_PCICORE_AUTOSELECT=y --CONFIG_B43_SDIO=y --CONFIG_B43_BCMA_PIO=y --CONFIG_B43_PIO=y --CONFIG_B43_PHY_G=y --CONFIG_B43_PHY_N=y --CONFIG_B43_PHY_LP=y --CONFIG_B43_PHY_HT=y --CONFIG_B43_LEDS=y --CONFIG_B43_HWRNG=y --# CONFIG_B43_DEBUG is not set --CONFIG_B43LEGACY=m --CONFIG_B43LEGACY_PCI_AUTOSELECT=y --CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y --CONFIG_B43LEGACY_LEDS=y --CONFIG_B43LEGACY_HWRNG=y --# CONFIG_B43LEGACY_DEBUG is not set --CONFIG_B43LEGACY_DMA=y --CONFIG_B43LEGACY_PIO=y --CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y --# CONFIG_B43LEGACY_DMA_MODE is not set --# CONFIG_B43LEGACY_PIO_MODE is not set --CONFIG_BRCMUTIL=m --CONFIG_BRCMSMAC=m --CONFIG_BRCMFMAC=m --CONFIG_BRCMFMAC_PROTO_BCDC=y --CONFIG_BRCMFMAC_PROTO_MSGBUF=y --CONFIG_BRCMFMAC_SDIO=y --CONFIG_BRCMFMAC_USB=y --CONFIG_BRCMFMAC_PCIE=y --# CONFIG_BRCM_TRACING is not set --# CONFIG_BRCMDBG is not set --CONFIG_HOSTAP=m --CONFIG_HOSTAP_FIRMWARE=y --CONFIG_HOSTAP_FIRMWARE_NVRAM=y --CONFIG_HOSTAP_PLX=m --CONFIG_HOSTAP_PCI=m --CONFIG_IPW2100=m --CONFIG_IPW2100_MONITOR=y --# CONFIG_IPW2100_DEBUG is not set --CONFIG_IPW2200=m --CONFIG_IPW2200_MONITOR=y --CONFIG_IPW2200_RADIOTAP=y --CONFIG_IPW2200_PROMISCUOUS=y --CONFIG_IPW2200_QOS=y --CONFIG_IPW2200_DEBUG=y --CONFIG_LIBIPW=m --# CONFIG_LIBIPW_DEBUG is not set --CONFIG_IWLWIFI=m --CONFIG_IWLWIFI_LEDS=y --CONFIG_IWLDVM=m --CONFIG_IWLMVM=m --CONFIG_IWLWIFI_OPMODE_MODULAR=y --CONFIG_IWLWIFI_BCAST_FILTERING=y --CONFIG_IWLWIFI_UAPSD=y -- --# --# Debugging Options --# --# CONFIG_IWLWIFI_DEBUG is not set --CONFIG_IWLWIFI_DEVICE_TRACING=y --CONFIG_IWLEGACY=m --CONFIG_IWL4965=m --CONFIG_IWL3945=m -- --# --# iwl3945 / iwl4965 Debugging Options --# --# CONFIG_IWLEGACY_DEBUG is not set --CONFIG_LIBERTAS=m --CONFIG_LIBERTAS_USB=m --CONFIG_LIBERTAS_SDIO=m --CONFIG_LIBERTAS_SPI=m --# CONFIG_LIBERTAS_DEBUG is not set --CONFIG_LIBERTAS_MESH=y --CONFIG_HERMES=m --CONFIG_HERMES_PRISM=y --CONFIG_HERMES_CACHE_FW_ON_INIT=y --CONFIG_PLX_HERMES=m --CONFIG_TMD_HERMES=m --CONFIG_NORTEL_HERMES=m --CONFIG_PCI_HERMES=m --CONFIG_ORINOCO_USB=m --CONFIG_P54_COMMON=m --CONFIG_P54_USB=m --CONFIG_P54_PCI=m --CONFIG_P54_SPI=m --CONFIG_P54_SPI_DEFAULT_EEPROM=y --CONFIG_P54_LEDS=y --CONFIG_RT2X00=m --CONFIG_RT2400PCI=m --CONFIG_RT2500PCI=m --CONFIG_RT61PCI=m --CONFIG_RT2800PCI=m --CONFIG_RT2800PCI_RT33XX=y --CONFIG_RT2800PCI_RT35XX=y --CONFIG_RT2800PCI_RT53XX=y --CONFIG_RT2800PCI_RT3290=y --CONFIG_RT2500USB=m --CONFIG_RT73USB=m --CONFIG_RT2800USB=m --CONFIG_RT2800USB_RT33XX=y --CONFIG_RT2800USB_RT35XX=y --CONFIG_RT2800USB_RT3573=y --CONFIG_RT2800USB_RT53XX=y --CONFIG_RT2800USB_RT55XX=y --CONFIG_RT2800USB_UNKNOWN=y --CONFIG_RT2800_LIB=m --CONFIG_RT2800_LIB_MMIO=m --CONFIG_RT2X00_LIB_MMIO=m --CONFIG_RT2X00_LIB_PCI=m --CONFIG_RT2X00_LIB_USB=m --CONFIG_RT2X00_LIB=m --CONFIG_RT2X00_LIB_FIRMWARE=y --CONFIG_RT2X00_LIB_CRYPTO=y --CONFIG_RT2X00_LIB_LEDS=y --# CONFIG_RT2X00_DEBUG is not set --CONFIG_WL_MEDIATEK=y --CONFIG_MT7601U=m --CONFIG_RTL_CARDS=m --CONFIG_RTL8192CE=m --CONFIG_RTL8192SE=m --CONFIG_RTL8192DE=m --CONFIG_RTL8723AE=m --CONFIG_RTL8723BE=m --CONFIG_RTL8188EE=m --CONFIG_RTL8192EE=m --CONFIG_RTL8821AE=m --CONFIG_RTL8192CU=m --CONFIG_RTLWIFI=m --CONFIG_RTLWIFI_PCI=m --CONFIG_RTLWIFI_USB=m --CONFIG_RTLWIFI_DEBUG=y --CONFIG_RTL8192C_COMMON=m --CONFIG_RTL8723_COMMON=m --CONFIG_RTLBTCOEXIST=m --# CONFIG_RTL8XXXU is not set --CONFIG_WL_TI=y --CONFIG_WL1251=m --CONFIG_WL1251_SPI=m --CONFIG_WL1251_SDIO=m --CONFIG_WL12XX=m --CONFIG_WL18XX=m --CONFIG_WLCORE=m --CONFIG_WLCORE_SPI=m --CONFIG_WLCORE_SDIO=m --CONFIG_WILINK_PLATFORM_DATA=y --CONFIG_ZD1211RW=m --# CONFIG_ZD1211RW_DEBUG is not set --CONFIG_MWIFIEX=m --CONFIG_MWIFIEX_SDIO=m --CONFIG_MWIFIEX_PCIE=m --CONFIG_MWIFIEX_USB=m --CONFIG_CW1200=m --CONFIG_CW1200_WLAN_SDIO=m --CONFIG_CW1200_WLAN_SPI=m --CONFIG_RSI_91X=m --CONFIG_RSI_DEBUGFS=y --CONFIG_RSI_SDIO=m --CONFIG_RSI_USB=m -- --# --# Enable WiMAX (Networking options) to see the WiMAX drivers --# --CONFIG_WAN=y --CONFIG_HDLC=m --CONFIG_HDLC_RAW=m --CONFIG_HDLC_RAW_ETH=m --CONFIG_HDLC_CISCO=m --CONFIG_HDLC_FR=m --CONFIG_HDLC_PPP=m -- --# --# X.25/LAPB support is disabled --# --# CONFIG_PCI200SYN is not set --CONFIG_WANXL=m --# CONFIG_WANXL_BUILD_FIRMWARE is not set --CONFIG_PC300TOO=m --CONFIG_FARSYNC=m --CONFIG_DSCC4=m --# CONFIG_DSCC4_PCISYNC is not set --# CONFIG_DSCC4_PCI_RST is not set --# CONFIG_DLCI is not set --# CONFIG_VMXNET3 is not set --CONFIG_ISDN=y --CONFIG_ISDN_I4L=m --# CONFIG_ISDN_PPP is not set --# CONFIG_ISDN_AUDIO is not set -- --# --# ISDN feature submodules --# --# CONFIG_ISDN_DIVERSION is not set -- --# --# ISDN4Linux hardware drivers --# -- --# --# Passive cards --# --# CONFIG_ISDN_DRV_HISAX is not set -- --# --# Active cards --# --CONFIG_ISDN_CAPI=m --CONFIG_CAPI_TRACE=y --# CONFIG_ISDN_CAPI_CAPI20 is not set --# CONFIG_ISDN_CAPI_CAPIDRV is not set -- --# --# CAPI hardware drivers --# --# CONFIG_CAPI_AVM is not set --# CONFIG_CAPI_EICON is not set --CONFIG_ISDN_DRV_GIGASET=m --CONFIG_GIGASET_CAPI=y --# CONFIG_GIGASET_I4L is not set --# CONFIG_GIGASET_DUMMYLL is not set --# CONFIG_GIGASET_BASE is not set --# CONFIG_GIGASET_M105 is not set --# CONFIG_GIGASET_M101 is not set --# CONFIG_GIGASET_DEBUG is not set --CONFIG_HYSDN=m --CONFIG_HYSDN_CAPI=y --CONFIG_MISDN=m --CONFIG_MISDN_DSP=m --CONFIG_MISDN_L1OIP=m -- --# --# mISDN hardware drivers --# --CONFIG_MISDN_HFCPCI=m --CONFIG_MISDN_HFCMULTI=m --CONFIG_MISDN_HFCUSB=m --CONFIG_MISDN_AVMFRITZ=m --CONFIG_MISDN_SPEEDFAX=m --CONFIG_MISDN_INFINEON=m --CONFIG_MISDN_W6692=m --CONFIG_MISDN_NETJET=m --CONFIG_MISDN_IPAC=m --CONFIG_MISDN_ISAR=m --CONFIG_ISDN_HDLC=m --# CONFIG_NVM is not set -- --# --# Input device support --# --CONFIG_INPUT=y --CONFIG_INPUT_LEDS=m --CONFIG_INPUT_FF_MEMLESS=m --CONFIG_INPUT_POLLDEV=y --CONFIG_INPUT_SPARSEKMAP=m --CONFIG_INPUT_MATRIXKMAP=y -- --# --# Userland interfaces --# --CONFIG_INPUT_MOUSEDEV=m --# CONFIG_INPUT_MOUSEDEV_PSAUX is not set --CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 --CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 --CONFIG_INPUT_JOYDEV=m --CONFIG_INPUT_EVDEV=y --CONFIG_INPUT_EVBUG=m -- --# --# Input Device Drivers --# --CONFIG_INPUT_KEYBOARD=y --# CONFIG_KEYBOARD_ADP5588 is not set --# CONFIG_KEYBOARD_ADP5589 is not set --# CONFIG_KEYBOARD_ATKBD is not set --# CONFIG_KEYBOARD_QT1070 is not set --# CONFIG_KEYBOARD_QT2160 is not set --# CONFIG_KEYBOARD_LKKBD is not set --CONFIG_KEYBOARD_GPIO=y --CONFIG_KEYBOARD_GPIO_POLLED=y --CONFIG_KEYBOARD_TCA6416=m --CONFIG_KEYBOARD_TCA8418=m --CONFIG_KEYBOARD_MATRIX=m --# CONFIG_KEYBOARD_LM8323 is not set --# CONFIG_KEYBOARD_LM8333 is not set --# CONFIG_KEYBOARD_MAX7359 is not set --# CONFIG_KEYBOARD_MCS is not set --# CONFIG_KEYBOARD_MPR121 is not set --CONFIG_KEYBOARD_IMX=y --# CONFIG_KEYBOARD_NEWTON is not set --# CONFIG_KEYBOARD_OPENCORES is not set --# CONFIG_KEYBOARD_SAMSUNG is not set --# CONFIG_KEYBOARD_STOWAWAY is not set --# CONFIG_KEYBOARD_SUNKBD is not set --# CONFIG_KEYBOARD_OMAP4 is not set --CONFIG_KEYBOARD_XTKBD=m --# CONFIG_KEYBOARD_CAP11XX is not set --# CONFIG_KEYBOARD_BCM is not set --CONFIG_INPUT_MOUSE=y --CONFIG_MOUSE_PS2=m --CONFIG_MOUSE_PS2_ALPS=y --CONFIG_MOUSE_PS2_LOGIPS2PP=y --CONFIG_MOUSE_PS2_SYNAPTICS=y --CONFIG_MOUSE_PS2_CYPRESS=y --CONFIG_MOUSE_PS2_TRACKPOINT=y --CONFIG_MOUSE_PS2_ELANTECH=y --# CONFIG_MOUSE_PS2_SENTELIC is not set --# CONFIG_MOUSE_PS2_TOUCHKIT is not set --CONFIG_MOUSE_PS2_FOCALTECH=y --CONFIG_MOUSE_SERIAL=m --CONFIG_MOUSE_APPLETOUCH=m --CONFIG_MOUSE_BCM5974=m --CONFIG_MOUSE_CYAPA=m --CONFIG_MOUSE_ELAN_I2C=m --CONFIG_MOUSE_ELAN_I2C_I2C=y --# CONFIG_MOUSE_ELAN_I2C_SMBUS is not set --CONFIG_MOUSE_VSXXXAA=m --CONFIG_MOUSE_GPIO=m --CONFIG_MOUSE_SYNAPTICS_I2C=m --CONFIG_MOUSE_SYNAPTICS_USB=m --CONFIG_INPUT_JOYSTICK=y --CONFIG_JOYSTICK_ANALOG=m --CONFIG_JOYSTICK_A3D=m --CONFIG_JOYSTICK_ADI=m --CONFIG_JOYSTICK_COBRA=m --CONFIG_JOYSTICK_GF2K=m --CONFIG_JOYSTICK_GRIP=m --CONFIG_JOYSTICK_GRIP_MP=m --CONFIG_JOYSTICK_GUILLEMOT=m --CONFIG_JOYSTICK_INTERACT=m --CONFIG_JOYSTICK_SIDEWINDER=m --CONFIG_JOYSTICK_TMDC=m --CONFIG_JOYSTICK_IFORCE=m --CONFIG_JOYSTICK_IFORCE_USB=y --CONFIG_JOYSTICK_IFORCE_232=y --CONFIG_JOYSTICK_WARRIOR=m --CONFIG_JOYSTICK_MAGELLAN=m --CONFIG_JOYSTICK_SPACEORB=m --CONFIG_JOYSTICK_SPACEBALL=m --CONFIG_JOYSTICK_STINGER=m --CONFIG_JOYSTICK_TWIDJOY=m --CONFIG_JOYSTICK_ZHENHUA=m --CONFIG_JOYSTICK_AS5011=m --CONFIG_JOYSTICK_JOYDUMP=m --CONFIG_JOYSTICK_XPAD=m --CONFIG_JOYSTICK_XPAD_FF=y --CONFIG_JOYSTICK_XPAD_LEDS=y --# CONFIG_INPUT_TABLET is not set --CONFIG_INPUT_TOUCHSCREEN=y --CONFIG_TOUCHSCREEN_PROPERTIES=y --CONFIG_TOUCHSCREEN_ADS7846=m --CONFIG_TOUCHSCREEN_AD7877=m --CONFIG_TOUCHSCREEN_AD7879=m --CONFIG_TOUCHSCREEN_AD7879_I2C=m --CONFIG_TOUCHSCREEN_AD7879_SPI=m --CONFIG_TOUCHSCREEN_AR1021_I2C=m --CONFIG_TOUCHSCREEN_ATMEL_MXT=m --CONFIG_TOUCHSCREEN_AUO_PIXCIR=m --CONFIG_TOUCHSCREEN_BU21013=m --CONFIG_TOUCHSCREEN_CHIPONE_ICN8318=m --CONFIG_TOUCHSCREEN_CY8CTMG110=m --CONFIG_TOUCHSCREEN_CYTTSP_CORE=m --CONFIG_TOUCHSCREEN_CYTTSP_I2C=m --CONFIG_TOUCHSCREEN_CYTTSP_SPI=m --CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m --CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m --CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m --CONFIG_TOUCHSCREEN_DA9052=m --CONFIG_TOUCHSCREEN_DYNAPRO=m --CONFIG_TOUCHSCREEN_HAMPSHIRE=m --CONFIG_TOUCHSCREEN_EETI=m --CONFIG_TOUCHSCREEN_EGALAX=m --CONFIG_TOUCHSCREEN_FT6236=m --CONFIG_TOUCHSCREEN_FUJITSU=m --CONFIG_TOUCHSCREEN_GOODIX=m --CONFIG_TOUCHSCREEN_ILI210X=m --CONFIG_TOUCHSCREEN_GUNZE=m --CONFIG_TOUCHSCREEN_ELAN=m --CONFIG_TOUCHSCREEN_ELO=m --CONFIG_TOUCHSCREEN_WACOM_W8001=m --CONFIG_TOUCHSCREEN_WACOM_I2C=m --CONFIG_TOUCHSCREEN_MAX11801=m --CONFIG_TOUCHSCREEN_MCS5000=m --CONFIG_TOUCHSCREEN_MMS114=m --CONFIG_TOUCHSCREEN_MTOUCH=m --CONFIG_TOUCHSCREEN_IMX6UL_TSC=m --CONFIG_TOUCHSCREEN_INEXIO=m --CONFIG_TOUCHSCREEN_MK712=m --CONFIG_TOUCHSCREEN_PENMOUNT=m --CONFIG_TOUCHSCREEN_EDT_FT5X06=m --CONFIG_TOUCHSCREEN_TOUCHRIGHT=m --CONFIG_TOUCHSCREEN_TOUCHWIN=m --CONFIG_TOUCHSCREEN_PIXCIR=m --CONFIG_TOUCHSCREEN_WDT87XX_I2C=m --CONFIG_TOUCHSCREEN_WM97XX=m --CONFIG_TOUCHSCREEN_WM9705=y --CONFIG_TOUCHSCREEN_WM9712=y --CONFIG_TOUCHSCREEN_WM9713=y --CONFIG_TOUCHSCREEN_USB_COMPOSITE=m --CONFIG_TOUCHSCREEN_MC13783=m --CONFIG_TOUCHSCREEN_USB_EGALAX=y --CONFIG_TOUCHSCREEN_USB_PANJIT=y --CONFIG_TOUCHSCREEN_USB_3M=y --CONFIG_TOUCHSCREEN_USB_ITM=y --CONFIG_TOUCHSCREEN_USB_ETURBO=y --CONFIG_TOUCHSCREEN_USB_GUNZE=y --CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y --CONFIG_TOUCHSCREEN_USB_IRTOUCH=y --CONFIG_TOUCHSCREEN_USB_IDEALTEK=y --CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y --CONFIG_TOUCHSCREEN_USB_GOTOP=y --CONFIG_TOUCHSCREEN_USB_JASTEC=y --CONFIG_TOUCHSCREEN_USB_ELO=y --CONFIG_TOUCHSCREEN_USB_E2I=y --CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y --CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y --CONFIG_TOUCHSCREEN_USB_NEXIO=y --CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y --CONFIG_TOUCHSCREEN_TOUCHIT213=m --CONFIG_TOUCHSCREEN_TSC_SERIO=m --CONFIG_TOUCHSCREEN_TSC200X_CORE=m --CONFIG_TOUCHSCREEN_TSC2004=m --CONFIG_TOUCHSCREEN_TSC2005=m --CONFIG_TOUCHSCREEN_TSC2007=m --CONFIG_TOUCHSCREEN_ST1232=m --CONFIG_TOUCHSCREEN_SUR40=m --CONFIG_TOUCHSCREEN_SX8654=m --CONFIG_TOUCHSCREEN_TPS6507X=m --CONFIG_TOUCHSCREEN_ZFORCE=m --CONFIG_TOUCHSCREEN_ROHM_BU21023=m --CONFIG_INPUT_MISC=y --CONFIG_INPUT_AD714X=m --CONFIG_INPUT_AD714X_I2C=m --CONFIG_INPUT_AD714X_SPI=m --CONFIG_INPUT_BMA150=m --CONFIG_INPUT_E3X0_BUTTON=m --CONFIG_INPUT_MC13783_PWRBUTTON=m --CONFIG_INPUT_MMA8450=y --CONFIG_INPUT_MPU3050=m --CONFIG_INPUT_GP2A=m --CONFIG_INPUT_GPIO_BEEPER=m --CONFIG_INPUT_GPIO_TILT_POLLED=m --CONFIG_INPUT_ATI_REMOTE2=m --CONFIG_INPUT_KEYSPAN_REMOTE=m --CONFIG_INPUT_KXTJ9=m --CONFIG_INPUT_KXTJ9_POLLED_MODE=y --CONFIG_INPUT_POWERMATE=m --CONFIG_INPUT_YEALINK=m --CONFIG_INPUT_CM109=m --CONFIG_INPUT_REGULATOR_HAPTIC=m --CONFIG_INPUT_UINPUT=m --CONFIG_INPUT_PCF8574=m --CONFIG_INPUT_PWM_BEEPER=m --CONFIG_INPUT_GPIO_ROTARY_ENCODER=m --CONFIG_INPUT_DA9052_ONKEY=m --CONFIG_INPUT_ADXL34X=m --CONFIG_INPUT_ADXL34X_I2C=m --CONFIG_INPUT_ADXL34X_SPI=m --CONFIG_INPUT_IMS_PCU=m --CONFIG_INPUT_CMA3000=m --CONFIG_INPUT_CMA3000_I2C=m --CONFIG_INPUT_SOC_BUTTON_ARRAY=m --CONFIG_INPUT_DRV260X_HAPTICS=m --CONFIG_INPUT_DRV2665_HAPTICS=m --CONFIG_INPUT_DRV2667_HAPTICS=m -- --# --# Hardware I/O ports --# --CONFIG_SERIO=m --CONFIG_SERIO_SERPORT=m --# CONFIG_SERIO_PCIPS2 is not set --CONFIG_SERIO_LIBPS2=m --CONFIG_SERIO_RAW=m --CONFIG_SERIO_ALTERA_PS2=m --# CONFIG_SERIO_PS2MULT is not set --# CONFIG_SERIO_ARC_PS2 is not set --# CONFIG_SERIO_APBPS2 is not set --# CONFIG_USERIO is not set --CONFIG_GAMEPORT=m --# CONFIG_GAMEPORT_NS558 is not set --# CONFIG_GAMEPORT_L4 is not set --# CONFIG_GAMEPORT_EMU10K1 is not set --# CONFIG_GAMEPORT_FM801 is not set -- --# --# Character devices --# --CONFIG_TTY=y --CONFIG_VT=y --CONFIG_CONSOLE_TRANSLATIONS=y --CONFIG_VT_CONSOLE=y --CONFIG_VT_CONSOLE_SLEEP=y --CONFIG_HW_CONSOLE=y --CONFIG_VT_HW_CONSOLE_BINDING=y --CONFIG_UNIX98_PTYS=y --CONFIG_DEVPTS_MULTIPLE_INSTANCES=y --CONFIG_LEGACY_PTYS=y --CONFIG_LEGACY_PTY_COUNT=256 --# CONFIG_SERIAL_NONSTANDARD is not set --# CONFIG_NOZOMI is not set --# CONFIG_N_GSM is not set --# CONFIG_TRACE_SINK is not set --CONFIG_DEVMEM=y --# CONFIG_DEVKMEM is not set -- --# --# Serial drivers --# --CONFIG_SERIAL_EARLYCON=y --CONFIG_SERIAL_8250=m --CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y --CONFIG_SERIAL_8250_DMA=y --CONFIG_SERIAL_8250_PCI=m --CONFIG_SERIAL_8250_NR_UARTS=4 --CONFIG_SERIAL_8250_RUNTIME_UARTS=4 --# CONFIG_SERIAL_8250_EXTENDED is not set --CONFIG_SERIAL_8250_DW=m --# CONFIG_SERIAL_8250_EM is not set --# CONFIG_SERIAL_8250_RT288X is not set --# CONFIG_SERIAL_8250_MID is not set -- --# --# Non-8250 serial port support --# --CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST=y --CONFIG_SERIAL_MAX3100=m --CONFIG_SERIAL_MAX310X=m --CONFIG_SERIAL_IMX=y --CONFIG_SERIAL_IMX_CONSOLE=y --# CONFIG_SERIAL_UARTLITE is not set --CONFIG_SERIAL_CORE=y --CONFIG_SERIAL_CORE_CONSOLE=y --# CONFIG_SERIAL_JSM is not set --# CONFIG_SERIAL_OF_PLATFORM is not set --# CONFIG_SERIAL_SCCNXP is not set --# CONFIG_SERIAL_SC16IS7XX is not set --CONFIG_SERIAL_BCM63XX=y --CONFIG_SERIAL_BCM63XX_CONSOLE=y --# CONFIG_SERIAL_ALTERA_JTAGUART is not set --# CONFIG_SERIAL_ALTERA_UART is not set --# CONFIG_SERIAL_IFX6X60 is not set --# CONFIG_SERIAL_XILINX_PS_UART is not set --CONFIG_SERIAL_ARC=y --CONFIG_SERIAL_ARC_CONSOLE=y --CONFIG_SERIAL_ARC_NR_PORTS=1 --# CONFIG_SERIAL_RP2 is not set --CONFIG_SERIAL_FSL_LPUART=y --CONFIG_SERIAL_FSL_LPUART_CONSOLE=y --# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set --# CONFIG_SERIAL_ST_ASC is not set --# CONFIG_SERIAL_STM32 is not set --CONFIG_TTY_PRINTK=m --CONFIG_HVC_DRIVER=y --CONFIG_HVC_DCC=y --# CONFIG_IPMI_HANDLER is not set --CONFIG_HW_RANDOM=y --CONFIG_HW_RANDOM_TIMERIOMEM=m --# CONFIG_NVRAM is not set --# CONFIG_R3964 is not set --# CONFIG_APPLICOM is not set --CONFIG_RAW_DRIVER=m --CONFIG_MAX_RAW_DEVS=256 --# CONFIG_TCG_TPM is not set --CONFIG_DEVPORT=y --# CONFIG_XILLYBUS is not set -- --# --# I2C support --# --CONFIG_I2C=y --CONFIG_I2C_BOARDINFO=y --CONFIG_I2C_COMPAT=y --CONFIG_I2C_CHARDEV=y --CONFIG_I2C_MUX=y -- --# --# Multiplexer I2C Chip support --# --CONFIG_I2C_ARB_GPIO_CHALLENGE=y --CONFIG_I2C_MUX_GPIO=y --CONFIG_I2C_MUX_PCA9541=y --CONFIG_I2C_MUX_PCA954x=y --CONFIG_I2C_MUX_PINCTRL=y --# CONFIG_I2C_MUX_REG is not set --CONFIG_I2C_HELPER_AUTO=y --CONFIG_I2C_ALGOBIT=y -- --# --# I2C Hardware Bus support --# -- --# --# PC SMBus host controller drivers --# --# CONFIG_I2C_ALI1535 is not set --# CONFIG_I2C_ALI1563 is not set --# CONFIG_I2C_ALI15X3 is not set --# CONFIG_I2C_AMD756 is not set --# CONFIG_I2C_AMD8111 is not set --# CONFIG_I2C_I801 is not set --# CONFIG_I2C_ISCH is not set --# CONFIG_I2C_PIIX4 is not set --# CONFIG_I2C_NFORCE2 is not set --# CONFIG_I2C_SIS5595 is not set --# CONFIG_I2C_SIS630 is not set --# CONFIG_I2C_SIS96X is not set --# CONFIG_I2C_VIA is not set --# CONFIG_I2C_VIAPRO is not set -- --# --# I2C system bus drivers (mostly embedded / system-on-chip) --# --# CONFIG_I2C_CBUS_GPIO is not set --CONFIG_I2C_DESIGNWARE_CORE=m --CONFIG_I2C_DESIGNWARE_PLATFORM=m --# CONFIG_I2C_DESIGNWARE_PCI is not set --# CONFIG_I2C_EMEV2 is not set --CONFIG_I2C_GPIO=y --CONFIG_I2C_IMX=y --CONFIG_I2C_OCORES=y --# CONFIG_I2C_PCA_PLATFORM is not set --# CONFIG_I2C_PXA_PCI is not set --# CONFIG_I2C_RK3X is not set --# CONFIG_I2C_SIMTEC is not set --# CONFIG_I2C_XILINX is not set -- --# --# External I2C/SMBus adapter drivers --# --# CONFIG_I2C_DIOLAN_U2C is not set --# CONFIG_I2C_PARPORT_LIGHT is not set --# CONFIG_I2C_ROBOTFUZZ_OSIF is not set --# CONFIG_I2C_TAOS_EVM is not set --# CONFIG_I2C_TINY_USB is not set -- --# --# Other I2C/SMBus bus drivers --# --# CONFIG_I2C_STUB is not set --CONFIG_I2C_SLAVE=y --CONFIG_I2C_SLAVE_EEPROM=m --# CONFIG_I2C_DEBUG_CORE is not set --# CONFIG_I2C_DEBUG_ALGO is not set --# CONFIG_I2C_DEBUG_BUS is not set --CONFIG_SPI=y --# CONFIG_SPI_DEBUG is not set --CONFIG_SPI_MASTER=y -- --# --# SPI Master Controller Drivers --# --# CONFIG_SPI_ALTERA is not set --CONFIG_SPI_BITBANG=m --# CONFIG_SPI_CADENCE is not set --CONFIG_SPI_GPIO=m --CONFIG_SPI_IMX=m --# CONFIG_SPI_FSL_SPI is not set --# CONFIG_SPI_OC_TINY is not set --# CONFIG_SPI_PXA2XX is not set --# CONFIG_SPI_PXA2XX_PCI is not set --# CONFIG_SPI_ROCKCHIP is not set --# CONFIG_SPI_SC18IS602 is not set --# CONFIG_SPI_XCOMM is not set --# CONFIG_SPI_XILINX is not set --# CONFIG_SPI_ZYNQMP_GQSPI is not set --# CONFIG_SPI_DESIGNWARE is not set -- --# --# SPI Protocol Masters --# --CONFIG_SPI_SPIDEV=y --# CONFIG_SPI_TLE62X0 is not set --# CONFIG_SPMI is not set --# CONFIG_HSI is not set -- --# --# PPS support --# --CONFIG_PPS=y --# CONFIG_PPS_DEBUG is not set --# CONFIG_NTP_PPS is not set -- --# --# PPS clients support --# --# CONFIG_PPS_CLIENT_KTIMER is not set --CONFIG_PPS_CLIENT_LDISC=m --CONFIG_PPS_CLIENT_GPIO=m -- --# --# PPS generators support --# -- --# --# PTP clock support --# --CONFIG_PTP_1588_CLOCK=y --CONFIG_PTP_1588_CLOCK_GIANFAR=y -- --# --# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. --# --CONFIG_PINCTRL=y -- --# --# Pin controllers --# --CONFIG_PINMUX=y --CONFIG_PINCONF=y --CONFIG_GENERIC_PINCONF=y --# CONFIG_DEBUG_PINCTRL is not set --# CONFIG_PINCTRL_AMD is not set --CONFIG_PINCTRL_SINGLE=y --CONFIG_PINCTRL_IMX=y --CONFIG_PINCTRL_IMX6Q=y --CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y --CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y --CONFIG_ARCH_REQUIRE_GPIOLIB=y --CONFIG_GPIOLIB=y --CONFIG_GPIO_DEVRES=y --CONFIG_OF_GPIO=y --CONFIG_GPIOLIB_IRQCHIP=y --# CONFIG_DEBUG_GPIO is not set --CONFIG_GPIO_SYSFS=y --CONFIG_GPIO_GENERIC=y -- --# --# Memory mapped GPIO drivers --# --CONFIG_GPIO_74XX_MMIO=y --# CONFIG_GPIO_ALTERA is not set --# CONFIG_GPIO_DWAPB is not set --# CONFIG_GPIO_EM is not set --CONFIG_GPIO_GENERIC_PLATFORM=y --# CONFIG_GPIO_GRGPIO is not set --CONFIG_GPIO_MXC=y --CONFIG_GPIO_SYSCON=y --# CONFIG_GPIO_VX855 is not set --# CONFIG_GPIO_XILINX is not set --# CONFIG_GPIO_ZEVIO is not set --# CONFIG_GPIO_ZX is not set -- --# --# I2C GPIO expanders --# --CONFIG_GPIO_ADP5588=m --CONFIG_GPIO_ADNP=m --# CONFIG_GPIO_MAX7300 is not set --# CONFIG_GPIO_MAX732X is not set --CONFIG_GPIO_PCA953X=y --CONFIG_GPIO_PCA953X_IRQ=y --CONFIG_GPIO_PCF857X=m --CONFIG_GPIO_SX150X=y -- --# --# MFD GPIO expanders --# --# CONFIG_GPIO_DA9052 is not set -- --# --# PCI GPIO expanders --# --# CONFIG_GPIO_AMD8111 is not set --# CONFIG_GPIO_ML_IOH is not set --# CONFIG_GPIO_RDC321X is not set -- --# --# SPI GPIO expanders --# --CONFIG_GPIO_74X164=y --# CONFIG_GPIO_MAX7301 is not set --CONFIG_GPIO_MC33880=y -- --# --# SPI or I2C GPIO expanders --# --CONFIG_GPIO_MCP23S08=y -- --# --# USB GPIO expanders --# --CONFIG_W1=m --CONFIG_W1_CON=y -- --# --# 1-wire Bus Masters --# --CONFIG_W1_MASTER_MATROX=m --CONFIG_W1_MASTER_DS2490=m --CONFIG_W1_MASTER_DS2482=m --CONFIG_W1_MASTER_MXC=m --CONFIG_W1_MASTER_DS1WM=m --CONFIG_W1_MASTER_GPIO=m -- --# --# 1-wire Slaves --# --CONFIG_W1_SLAVE_THERM=m --CONFIG_W1_SLAVE_SMEM=m --CONFIG_W1_SLAVE_DS2408=m --CONFIG_W1_SLAVE_DS2408_READBACK=y --CONFIG_W1_SLAVE_DS2413=m --CONFIG_W1_SLAVE_DS2406=m --CONFIG_W1_SLAVE_DS2423=m --CONFIG_W1_SLAVE_DS2431=m --CONFIG_W1_SLAVE_DS2433=m --CONFIG_W1_SLAVE_DS2433_CRC=y --CONFIG_W1_SLAVE_DS2760=m --CONFIG_W1_SLAVE_DS2780=m --CONFIG_W1_SLAVE_DS2781=m --CONFIG_W1_SLAVE_DS28E04=m --CONFIG_W1_SLAVE_BQ27000=m --CONFIG_POWER_SUPPLY=y --# CONFIG_POWER_SUPPLY_DEBUG is not set --# CONFIG_PDA_POWER is not set --# CONFIG_GENERIC_ADC_BATTERY is not set --CONFIG_TEST_POWER=m --# CONFIG_BATTERY_DS2760 is not set --# CONFIG_BATTERY_DS2780 is not set --# CONFIG_BATTERY_DS2781 is not set --# CONFIG_BATTERY_DS2782 is not set --# CONFIG_BATTERY_SBS is not set --# CONFIG_BATTERY_BQ27XXX is not set --# CONFIG_BATTERY_DA9052 is not set --# CONFIG_BATTERY_MAX17040 is not set --# CONFIG_BATTERY_MAX17042 is not set --# CONFIG_CHARGER_ISP1704 is not set --# CONFIG_CHARGER_MAX8903 is not set --# CONFIG_CHARGER_LP8727 is not set --CONFIG_CHARGER_GPIO=m --# CONFIG_CHARGER_MANAGER is not set --# CONFIG_CHARGER_BQ2415X is not set --# CONFIG_CHARGER_BQ24190 is not set --# CONFIG_CHARGER_BQ24257 is not set --# CONFIG_CHARGER_BQ24735 is not set --# CONFIG_CHARGER_BQ25890 is not set --# CONFIG_CHARGER_SMB347 is not set --# CONFIG_BATTERY_GAUGE_LTC2941 is not set --# CONFIG_CHARGER_RT9455 is not set --CONFIG_POWER_RESET=y --# CONFIG_POWER_RESET_BRCMSTB is not set --CONFIG_POWER_RESET_GPIO=y --CONFIG_POWER_RESET_GPIO_RESTART=y --CONFIG_POWER_RESET_IMX=y --CONFIG_POWER_RESET_LTC2952=y --CONFIG_POWER_RESET_RESTART=y --CONFIG_POWER_RESET_VERSATILE=y --# CONFIG_POWER_RESET_SNVS is not set --CONFIG_POWER_RESET_SYSCON=y --# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set --CONFIG_POWER_AVS=y --CONFIG_HWMON=y --# CONFIG_HWMON_VID is not set --# CONFIG_HWMON_DEBUG_CHIP is not set -- --# --# Native drivers --# --# CONFIG_SENSORS_AD7314 is not set --# CONFIG_SENSORS_AD7414 is not set --# CONFIG_SENSORS_AD7418 is not set --# CONFIG_SENSORS_ADM1021 is not set --# CONFIG_SENSORS_ADM1025 is not set --# CONFIG_SENSORS_ADM1026 is not set --# CONFIG_SENSORS_ADM1029 is not set --# CONFIG_SENSORS_ADM1031 is not set --# CONFIG_SENSORS_ADM9240 is not set --# CONFIG_SENSORS_ADT7310 is not set --# CONFIG_SENSORS_ADT7410 is not set --# CONFIG_SENSORS_ADT7411 is not set --# CONFIG_SENSORS_ADT7462 is not set --# CONFIG_SENSORS_ADT7470 is not set --# CONFIG_SENSORS_ADT7475 is not set --# CONFIG_SENSORS_ASC7621 is not set --# CONFIG_SENSORS_ATXP1 is not set --# CONFIG_SENSORS_DS620 is not set --# CONFIG_SENSORS_DS1621 is not set --# CONFIG_SENSORS_DA9052_ADC is not set --# CONFIG_SENSORS_I5K_AMB is not set --# CONFIG_SENSORS_F71805F is not set --# CONFIG_SENSORS_F71882FG is not set --# CONFIG_SENSORS_F75375S is not set --CONFIG_SENSORS_MC13783_ADC=y --# CONFIG_SENSORS_GL518SM is not set --# CONFIG_SENSORS_GL520SM is not set --# CONFIG_SENSORS_G760A is not set --# CONFIG_SENSORS_G762 is not set --# CONFIG_SENSORS_GPIO_FAN is not set --# CONFIG_SENSORS_HIH6130 is not set --# CONFIG_SENSORS_IIO_HWMON is not set --# CONFIG_SENSORS_IT87 is not set --# CONFIG_SENSORS_JC42 is not set --# CONFIG_SENSORS_POWR1220 is not set --# CONFIG_SENSORS_LINEAGE is not set --# CONFIG_SENSORS_LTC2945 is not set --# CONFIG_SENSORS_LTC4151 is not set --# CONFIG_SENSORS_LTC4215 is not set --# CONFIG_SENSORS_LTC4222 is not set --# CONFIG_SENSORS_LTC4245 is not set --# CONFIG_SENSORS_LTC4260 is not set --# CONFIG_SENSORS_LTC4261 is not set --CONFIG_SENSORS_MAX1111=y --CONFIG_SENSORS_MAX16065=y --CONFIG_SENSORS_MAX1619=y --CONFIG_SENSORS_MAX1668=y --# CONFIG_SENSORS_MAX197 is not set --# CONFIG_SENSORS_MAX6639 is not set --# CONFIG_SENSORS_MAX6642 is not set --# CONFIG_SENSORS_MAX6650 is not set --# CONFIG_SENSORS_MAX6697 is not set --# CONFIG_SENSORS_MAX31790 is not set --# CONFIG_SENSORS_HTU21 is not set --# CONFIG_SENSORS_MCP3021 is not set --# CONFIG_SENSORS_ADCXX is not set --# CONFIG_SENSORS_LM63 is not set --# CONFIG_SENSORS_LM70 is not set --# CONFIG_SENSORS_LM73 is not set --# CONFIG_SENSORS_LM75 is not set --# CONFIG_SENSORS_LM77 is not set --# CONFIG_SENSORS_LM78 is not set --# CONFIG_SENSORS_LM80 is not set --# CONFIG_SENSORS_LM83 is not set --# CONFIG_SENSORS_LM85 is not set --# CONFIG_SENSORS_LM87 is not set --# CONFIG_SENSORS_LM90 is not set --# CONFIG_SENSORS_LM92 is not set --# CONFIG_SENSORS_LM93 is not set --# CONFIG_SENSORS_LM95234 is not set --# CONFIG_SENSORS_LM95241 is not set --# CONFIG_SENSORS_LM95245 is not set --# CONFIG_SENSORS_PC87360 is not set --# CONFIG_SENSORS_PC87427 is not set --# CONFIG_SENSORS_NTC_THERMISTOR is not set --# CONFIG_SENSORS_NCT6683 is not set --# CONFIG_SENSORS_NCT6775 is not set --# CONFIG_SENSORS_NCT7802 is not set --# CONFIG_SENSORS_NCT7904 is not set --# CONFIG_SENSORS_PCF8591 is not set --# CONFIG_PMBUS is not set --CONFIG_SENSORS_PWM_FAN=y --# CONFIG_SENSORS_SHT15 is not set --# CONFIG_SENSORS_SHT21 is not set --# CONFIG_SENSORS_SHTC1 is not set --# CONFIG_SENSORS_SIS5595 is not set --# CONFIG_SENSORS_DME1737 is not set --# CONFIG_SENSORS_EMC1403 is not set --# CONFIG_SENSORS_EMC2103 is not set --# CONFIG_SENSORS_EMC6W201 is not set --# CONFIG_SENSORS_SMSC47M1 is not set --# CONFIG_SENSORS_SMSC47M192 is not set --# CONFIG_SENSORS_SMSC47B397 is not set --# CONFIG_SENSORS_SCH56XX_COMMON is not set --# CONFIG_SENSORS_SCH5627 is not set --# CONFIG_SENSORS_SCH5636 is not set --# CONFIG_SENSORS_SMM665 is not set --# CONFIG_SENSORS_ADC128D818 is not set --# CONFIG_SENSORS_ADS1015 is not set --# CONFIG_SENSORS_ADS7828 is not set --# CONFIG_SENSORS_ADS7871 is not set --# CONFIG_SENSORS_AMC6821 is not set --# CONFIG_SENSORS_INA209 is not set --# CONFIG_SENSORS_INA2XX is not set --# CONFIG_SENSORS_TC74 is not set --# CONFIG_SENSORS_THMC50 is not set --# CONFIG_SENSORS_TMP102 is not set --# CONFIG_SENSORS_TMP103 is not set --# CONFIG_SENSORS_TMP401 is not set --# CONFIG_SENSORS_TMP421 is not set --# CONFIG_SENSORS_VIA686A is not set --# CONFIG_SENSORS_VT1211 is not set --# CONFIG_SENSORS_VT8231 is not set --# CONFIG_SENSORS_W83781D is not set --# CONFIG_SENSORS_W83791D is not set --# CONFIG_SENSORS_W83792D is not set --# CONFIG_SENSORS_W83793 is not set --# CONFIG_SENSORS_W83795 is not set --# CONFIG_SENSORS_W83L785TS is not set --# CONFIG_SENSORS_W83L786NG is not set --# CONFIG_SENSORS_W83627HF is not set --# CONFIG_SENSORS_W83627EHF is not set --CONFIG_THERMAL=y --CONFIG_THERMAL_HWMON=y --CONFIG_THERMAL_OF=y --# CONFIG_THERMAL_WRITABLE_TRIPS is not set --CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y --# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set --# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set --# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set --CONFIG_THERMAL_GOV_FAIR_SHARE=y --CONFIG_THERMAL_GOV_STEP_WISE=y --# CONFIG_THERMAL_GOV_BANG_BANG is not set --CONFIG_THERMAL_GOV_USER_SPACE=y --# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set --CONFIG_CPU_THERMAL=y --CONFIG_CLOCK_THERMAL=y --# CONFIG_DEVFREQ_THERMAL is not set --# CONFIG_THERMAL_EMULATION is not set --CONFIG_IMX_THERMAL=y --CONFIG_WATCHDOG=y --CONFIG_WATCHDOG_CORE=y --# CONFIG_WATCHDOG_NOWAYOUT is not set -- --# --# Watchdog Device Drivers --# --CONFIG_SOFT_WATCHDOG=m --# CONFIG_DA9052_WATCHDOG is not set --CONFIG_GPIO_WATCHDOG=m --# CONFIG_XILINX_WATCHDOG is not set --# CONFIG_CADENCE_WATCHDOG is not set --# CONFIG_DW_WATCHDOG is not set --# CONFIG_MAX63XX_WATCHDOG is not set --CONFIG_IMX2_WDT=y --# CONFIG_ALIM7101_WDT is not set --# CONFIG_I6300ESB_WDT is not set --# CONFIG_BCM7038_WDT is not set --# CONFIG_MEN_A21_WDT is not set -- --# --# PCI-based Watchdog Cards --# --# CONFIG_PCIPCWATCHDOG is not set --# CONFIG_WDTPCI is not set -- --# --# USB-based Watchdog Cards --# --# CONFIG_USBPCWATCHDOG is not set --CONFIG_SSB_POSSIBLE=y -- --# --# Sonics Silicon Backplane --# --CONFIG_SSB=y --CONFIG_SSB_SPROM=y --CONFIG_SSB_BLOCKIO=y --CONFIG_SSB_PCIHOST_POSSIBLE=y --CONFIG_SSB_PCIHOST=y --CONFIG_SSB_B43_PCI_BRIDGE=y --CONFIG_SSB_SDIOHOST_POSSIBLE=y --CONFIG_SSB_SDIOHOST=y --# CONFIG_SSB_HOST_SOC is not set --# CONFIG_SSB_SILENT is not set --# CONFIG_SSB_DEBUG is not set --CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y --CONFIG_SSB_DRIVER_PCICORE=y --# CONFIG_SSB_DRIVER_GPIO is not set --CONFIG_BCMA_POSSIBLE=y -- --# --# Broadcom specific AMBA --# --CONFIG_BCMA=m --CONFIG_BCMA_BLOCKIO=y --CONFIG_BCMA_HOST_PCI_POSSIBLE=y --# CONFIG_BCMA_HOST_PCI is not set --# CONFIG_BCMA_HOST_SOC is not set --# CONFIG_BCMA_DRIVER_PCI is not set --# CONFIG_BCMA_DRIVER_GMAC_CMN is not set --# CONFIG_BCMA_DRIVER_GPIO is not set --# CONFIG_BCMA_DEBUG is not set -- --# --# Multifunction device drivers --# --CONFIG_MFD_CORE=y --# CONFIG_MFD_AS3711 is not set --# CONFIG_MFD_AS3722 is not set --# CONFIG_PMIC_ADP5520 is not set --# CONFIG_MFD_AAT2870_CORE is not set --# CONFIG_MFD_ATMEL_FLEXCOM is not set --# CONFIG_MFD_ATMEL_HLCDC is not set --# CONFIG_MFD_BCM590XX is not set --# CONFIG_MFD_AXP20X is not set --# CONFIG_MFD_CROS_EC is not set --# CONFIG_MFD_ASIC3 is not set --# CONFIG_PMIC_DA903X is not set --CONFIG_PMIC_DA9052=y --CONFIG_MFD_DA9052_SPI=y --CONFIG_MFD_DA9052_I2C=y --# CONFIG_MFD_DA9055 is not set --# CONFIG_MFD_DA9062 is not set --# CONFIG_MFD_DA9063 is not set --# CONFIG_MFD_DA9150 is not set --CONFIG_MFD_MXC_HDMI=y --# CONFIG_MFD_DLN2 is not set --CONFIG_MFD_MC13XXX=y --CONFIG_MFD_MC13XXX_SPI=y --CONFIG_MFD_MC13XXX_I2C=y --# CONFIG_MFD_HI6421_PMIC is not set --# CONFIG_HTC_EGPIO is not set --# CONFIG_HTC_PASIC3 is not set --# CONFIG_HTC_I2CPLD is not set --# CONFIG_LPC_ICH is not set --# CONFIG_LPC_SCH is not set --# CONFIG_INTEL_SOC_PMIC is not set --# CONFIG_MFD_JANZ_CMODIO is not set --# CONFIG_MFD_KEMPLD is not set --# CONFIG_MFD_88PM800 is not set --# CONFIG_MFD_88PM805 is not set --# CONFIG_MFD_88PM860X is not set --# CONFIG_MFD_MAX14577 is not set --# CONFIG_MFD_MAX77686 is not set --# CONFIG_MFD_MAX77693 is not set --# CONFIG_MFD_MAX77843 is not set --# CONFIG_MFD_MAX8907 is not set --# CONFIG_MFD_MAX8925 is not set --# CONFIG_MFD_MAX8997 is not set --# CONFIG_MFD_MAX8998 is not set --# CONFIG_MFD_MT6397 is not set --# CONFIG_MFD_MENF21BMC is not set --# CONFIG_EZX_PCAP is not set --# CONFIG_MFD_VIPERBOARD is not set --# CONFIG_MFD_RETU is not set --# CONFIG_MFD_PCF50633 is not set --# CONFIG_UCB1400_CORE is not set --# CONFIG_MFD_PM8921_CORE is not set --# CONFIG_MFD_RDC321X is not set --# CONFIG_MFD_RTSX_PCI is not set --# CONFIG_MFD_RT5033 is not set --# CONFIG_MFD_RTSX_USB is not set --# CONFIG_MFD_RC5T583 is not set --# CONFIG_MFD_RK808 is not set --# CONFIG_MFD_RN5T618 is not set --# CONFIG_MFD_SEC_CORE is not set --CONFIG_MFD_SI476X_CORE=y --# CONFIG_MFD_SM501 is not set --# CONFIG_MFD_SKY81452 is not set --# CONFIG_MFD_SMSC is not set --# CONFIG_ABX500_CORE is not set --# CONFIG_MFD_STMPE is not set --CONFIG_MFD_SYSCON=y --# CONFIG_MFD_TI_AM335X_TSCADC is not set --# CONFIG_MFD_LP3943 is not set --# CONFIG_MFD_LP8788 is not set --# CONFIG_MFD_PALMAS is not set --# CONFIG_TPS6105X is not set --# CONFIG_TPS65010 is not set --# CONFIG_TPS6507X is not set --# CONFIG_MFD_TPS65090 is not set --# CONFIG_MFD_TPS65217 is not set --# CONFIG_MFD_TPS65218 is not set --# CONFIG_MFD_TPS6586X is not set --# CONFIG_MFD_TPS65910 is not set --# CONFIG_MFD_TPS65912 is not set --# CONFIG_MFD_TPS65912_I2C is not set --# CONFIG_MFD_TPS65912_SPI is not set --# CONFIG_MFD_TPS80031 is not set --# CONFIG_TWL4030_CORE is not set --# CONFIG_TWL6040_CORE is not set --CONFIG_MFD_WL1273_CORE=m --# CONFIG_MFD_LM3533 is not set --# CONFIG_MFD_TC3589X is not set --# CONFIG_MFD_TMIO is not set --# CONFIG_MFD_T7L66XB is not set --# CONFIG_MFD_TC6387XB is not set --# CONFIG_MFD_TC6393XB is not set --# CONFIG_MFD_VX855 is not set --# CONFIG_MFD_ARIZONA_I2C is not set --# CONFIG_MFD_ARIZONA_SPI is not set --# CONFIG_MFD_WM8400 is not set --# CONFIG_MFD_WM831X_I2C is not set --# CONFIG_MFD_WM831X_SPI is not set --# CONFIG_MFD_WM8350_I2C is not set --# CONFIG_MFD_WM8994 is not set --# CONFIG_MFD_TDA1997X is not set --CONFIG_REGULATOR=y --# CONFIG_REGULATOR_DEBUG is not set --CONFIG_REGULATOR_FIXED_VOLTAGE=y --CONFIG_REGULATOR_VIRTUAL_CONSUMER=y --CONFIG_REGULATOR_USERSPACE_CONSUMER=m --# CONFIG_REGULATOR_ACT8865 is not set --# CONFIG_REGULATOR_AD5398 is not set --CONFIG_REGULATOR_ANATOP=y --# CONFIG_REGULATOR_DA9052 is not set --# CONFIG_REGULATOR_DA9210 is not set --# CONFIG_REGULATOR_DA9211 is not set --# CONFIG_REGULATOR_FAN53555 is not set --CONFIG_REGULATOR_GPIO=y --# CONFIG_REGULATOR_ISL9305 is not set --# CONFIG_REGULATOR_ISL6271A is not set --# CONFIG_REGULATOR_LP3971 is not set --# CONFIG_REGULATOR_LP3972 is not set --# CONFIG_REGULATOR_LP872X is not set --# CONFIG_REGULATOR_LP8755 is not set --# CONFIG_REGULATOR_LTC3589 is not set --# CONFIG_REGULATOR_LTC3676 is not set --# CONFIG_REGULATOR_MAX1586 is not set --# CONFIG_REGULATOR_MAX8649 is not set --# CONFIG_REGULATOR_MAX8660 is not set --# CONFIG_REGULATOR_MAX8952 is not set --# CONFIG_REGULATOR_MAX8973 is not set --CONFIG_REGULATOR_MC13XXX_CORE=y --CONFIG_REGULATOR_MC13783=y --CONFIG_REGULATOR_MC13892=y --# CONFIG_REGULATOR_MT6311 is not set --CONFIG_REGULATOR_PFUZE100=y --CONFIG_REGULATOR_PWM=y --# CONFIG_REGULATOR_TPS51632 is not set --# CONFIG_REGULATOR_TPS62360 is not set --# CONFIG_REGULATOR_TPS65023 is not set --# CONFIG_REGULATOR_TPS6507X is not set --# CONFIG_REGULATOR_TPS6524X is not set --CONFIG_MEDIA_SUPPORT=y -- --# --# Multimedia core support --# --CONFIG_MEDIA_CAMERA_SUPPORT=y --CONFIG_MEDIA_ANALOG_TV_SUPPORT=y --CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y --CONFIG_MEDIA_RADIO_SUPPORT=y --CONFIG_MEDIA_SDR_SUPPORT=y --CONFIG_MEDIA_RC_SUPPORT=y --CONFIG_MEDIA_CONTROLLER=y --CONFIG_VIDEO_DEV=y --CONFIG_VIDEO_V4L2_SUBDEV_API=y --CONFIG_VIDEO_V4L2=y --# CONFIG_VIDEO_ADV_DEBUG is not set --# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set --CONFIG_VIDEO_TUNER=m --CONFIG_V4L2_MEM2MEM_DEV=m --CONFIG_VIDEO_V4L2_INT_DEVICE=m --CONFIG_VIDEOBUF_GEN=y --CONFIG_VIDEOBUF_DMA_SG=m --CONFIG_VIDEOBUF_VMALLOC=m --CONFIG_VIDEOBUF_DMA_CONTIG=y --CONFIG_VIDEOBUF_DVB=m --CONFIG_VIDEOBUF2_CORE=y --CONFIG_VIDEOBUF2_MEMOPS=m --CONFIG_VIDEOBUF2_DMA_CONTIG=m --CONFIG_VIDEOBUF2_VMALLOC=m --CONFIG_VIDEOBUF2_DMA_SG=m --CONFIG_VIDEOBUF2_DVB=m --CONFIG_DVB_CORE=y --CONFIG_DVB_NET=y --CONFIG_TTPCI_EEPROM=m --CONFIG_DVB_MAX_ADAPTERS=8 --# CONFIG_DVB_DYNAMIC_MINORS is not set -- --# --# Media drivers --# --CONFIG_RC_CORE=y --CONFIG_RC_MAP=m --CONFIG_RC_DECODERS=y --CONFIG_LIRC=m --CONFIG_IR_LIRC_CODEC=m --CONFIG_IR_NEC_DECODER=m --CONFIG_IR_RC5_DECODER=m --CONFIG_IR_RC6_DECODER=y --CONFIG_IR_JVC_DECODER=m --CONFIG_IR_SONY_DECODER=m --CONFIG_IR_SANYO_DECODER=m --CONFIG_IR_SHARP_DECODER=m --CONFIG_IR_MCE_KBD_DECODER=m --CONFIG_IR_XMP_DECODER=m --CONFIG_RC_DEVICES=y --CONFIG_RC_ATI_REMOTE=m --CONFIG_IR_HIX5HD2=m --CONFIG_IR_IMON=m --CONFIG_IR_MCEUSB=m --CONFIG_IR_REDRAT3=m --CONFIG_IR_STREAMZAP=m --CONFIG_IR_IGORPLUGUSB=m --CONFIG_IR_IGUANA=m --CONFIG_IR_TTUSBIR=m --CONFIG_RC_LOOPBACK=m --CONFIG_IR_GPIO_CIR=m --CONFIG_MEDIA_USB_SUPPORT=y -- --# --# Webcam devices --# --CONFIG_USB_VIDEO_CLASS=m --CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y --CONFIG_USB_GSPCA=m --CONFIG_USB_M5602=m --CONFIG_USB_STV06XX=m --CONFIG_USB_GL860=m --CONFIG_USB_GSPCA_BENQ=m --CONFIG_USB_GSPCA_CONEX=m --CONFIG_USB_GSPCA_CPIA1=m --CONFIG_USB_GSPCA_DTCS033=m --CONFIG_USB_GSPCA_ETOMS=m --CONFIG_USB_GSPCA_FINEPIX=m --CONFIG_USB_GSPCA_JEILINJ=m --CONFIG_USB_GSPCA_JL2005BCD=m --CONFIG_USB_GSPCA_KINECT=m --CONFIG_USB_GSPCA_KONICA=m --CONFIG_USB_GSPCA_MARS=m --CONFIG_USB_GSPCA_MR97310A=m --CONFIG_USB_GSPCA_NW80X=m --CONFIG_USB_GSPCA_OV519=m --CONFIG_USB_GSPCA_OV534=m --CONFIG_USB_GSPCA_OV534_9=m --CONFIG_USB_GSPCA_PAC207=m --CONFIG_USB_GSPCA_PAC7302=m --CONFIG_USB_GSPCA_PAC7311=m --CONFIG_USB_GSPCA_SE401=m --CONFIG_USB_GSPCA_SN9C2028=m --CONFIG_USB_GSPCA_SN9C20X=m --CONFIG_USB_GSPCA_SONIXB=m --CONFIG_USB_GSPCA_SONIXJ=m --CONFIG_USB_GSPCA_SPCA500=m --CONFIG_USB_GSPCA_SPCA501=m --CONFIG_USB_GSPCA_SPCA505=m --CONFIG_USB_GSPCA_SPCA506=m --CONFIG_USB_GSPCA_SPCA508=m --CONFIG_USB_GSPCA_SPCA561=m --CONFIG_USB_GSPCA_SPCA1528=m --CONFIG_USB_GSPCA_SQ905=m --CONFIG_USB_GSPCA_SQ905C=m --CONFIG_USB_GSPCA_SQ930X=m --CONFIG_USB_GSPCA_STK014=m --CONFIG_USB_GSPCA_STK1135=m --CONFIG_USB_GSPCA_STV0680=m --CONFIG_USB_GSPCA_SUNPLUS=m --CONFIG_USB_GSPCA_T613=m --CONFIG_USB_GSPCA_TOPRO=m --# CONFIG_USB_GSPCA_TOUPTEK is not set --CONFIG_USB_GSPCA_TV8532=m --CONFIG_USB_GSPCA_VC032X=m --CONFIG_USB_GSPCA_VICAM=m --CONFIG_USB_GSPCA_XIRLINK_CIT=m --CONFIG_USB_GSPCA_ZC3XX=m --CONFIG_USB_PWC=m --# CONFIG_USB_PWC_DEBUG is not set --CONFIG_USB_PWC_INPUT_EVDEV=y --CONFIG_VIDEO_CPIA2=m --CONFIG_USB_ZR364XX=m --CONFIG_USB_STKWEBCAM=m --CONFIG_USB_S2255=m --CONFIG_VIDEO_USBTV=m -- --# --# Analog TV USB devices --# --CONFIG_VIDEO_PVRUSB2=m --CONFIG_VIDEO_PVRUSB2_SYSFS=y --CONFIG_VIDEO_PVRUSB2_DVB=y --# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set --CONFIG_VIDEO_HDPVR=m --CONFIG_VIDEO_USBVISION=m --CONFIG_VIDEO_STK1160_COMMON=m --CONFIG_VIDEO_STK1160_AC97=y --CONFIG_VIDEO_STK1160=m --CONFIG_VIDEO_GO7007=m --CONFIG_VIDEO_GO7007_USB=m --CONFIG_VIDEO_GO7007_LOADER=m --CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -- --# --# Analog/digital TV USB devices --# --CONFIG_VIDEO_AU0828=m --CONFIG_VIDEO_AU0828_V4L2=y --CONFIG_VIDEO_AU0828_RC=y --CONFIG_VIDEO_CX231XX=m --CONFIG_VIDEO_CX231XX_RC=y --CONFIG_VIDEO_CX231XX_ALSA=m --CONFIG_VIDEO_CX231XX_DVB=m --CONFIG_VIDEO_TM6000=m --CONFIG_VIDEO_TM6000_ALSA=m --CONFIG_VIDEO_TM6000_DVB=m -- --# --# Digital TV USB devices --# --CONFIG_DVB_USB=m --# CONFIG_DVB_USB_DEBUG is not set --CONFIG_DVB_USB_A800=m --CONFIG_DVB_USB_DIBUSB_MB=m --CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y --CONFIG_DVB_USB_DIBUSB_MC=m --CONFIG_DVB_USB_DIB0700=m --CONFIG_DVB_USB_UMT_010=m --CONFIG_DVB_USB_CXUSB=m --CONFIG_DVB_USB_M920X=m --CONFIG_DVB_USB_DIGITV=m --CONFIG_DVB_USB_VP7045=m --CONFIG_DVB_USB_VP702X=m --CONFIG_DVB_USB_GP8PSK=m --CONFIG_DVB_USB_NOVA_T_USB2=m --CONFIG_DVB_USB_TTUSB2=m --CONFIG_DVB_USB_DTT200U=m --CONFIG_DVB_USB_OPERA1=m --CONFIG_DVB_USB_AF9005=m --CONFIG_DVB_USB_AF9005_REMOTE=m --CONFIG_DVB_USB_PCTV452E=m --CONFIG_DVB_USB_DW2102=m --CONFIG_DVB_USB_CINERGY_T2=m --CONFIG_DVB_USB_DTV5100=m --CONFIG_DVB_USB_FRIIO=m --CONFIG_DVB_USB_AZ6027=m --CONFIG_DVB_USB_TECHNISAT_USB2=m --CONFIG_DVB_USB_V2=m --CONFIG_DVB_USB_AF9015=m --CONFIG_DVB_USB_AF9035=m --CONFIG_DVB_USB_ANYSEE=m --CONFIG_DVB_USB_AU6610=m --CONFIG_DVB_USB_AZ6007=m --CONFIG_DVB_USB_CE6230=m --CONFIG_DVB_USB_EC168=m --CONFIG_DVB_USB_GL861=m --CONFIG_DVB_USB_LME2510=m --CONFIG_DVB_USB_MXL111SF=m --CONFIG_DVB_USB_RTL28XXU=m --CONFIG_DVB_USB_DVBSKY=m --CONFIG_DVB_TTUSB_BUDGET=m --CONFIG_DVB_TTUSB_DEC=m --CONFIG_SMS_USB_DRV=m --CONFIG_DVB_B2C2_FLEXCOP_USB=m --# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set --CONFIG_DVB_AS102=m -- --# --# Webcam, TV (analog/digital) USB devices --# --CONFIG_VIDEO_EM28XX=m --CONFIG_VIDEO_EM28XX_V4L2=m --CONFIG_VIDEO_EM28XX_ALSA=m --CONFIG_VIDEO_EM28XX_DVB=m --CONFIG_VIDEO_EM28XX_RC=m -- --# --# Software defined radio USB devices --# --CONFIG_USB_AIRSPY=m --CONFIG_USB_HACKRF=m --CONFIG_USB_MSI2500=m --CONFIG_MEDIA_PCI_SUPPORT=y -- --# --# Media capture support --# --CONFIG_VIDEO_SOLO6X10=m --CONFIG_VIDEO_TW68=m -- --# --# Media capture/analog TV support --# --CONFIG_VIDEO_IVTV=m --CONFIG_VIDEO_IVTV_ALSA=m --CONFIG_VIDEO_FB_IVTV=m --CONFIG_VIDEO_HEXIUM_GEMINI=m --CONFIG_VIDEO_HEXIUM_ORION=m --CONFIG_VIDEO_MXB=m --CONFIG_VIDEO_DT3155=m -- --# --# Media capture/analog/hybrid TV support --# --CONFIG_VIDEO_CX18=m --CONFIG_VIDEO_CX18_ALSA=m --CONFIG_VIDEO_CX23885=m --CONFIG_MEDIA_ALTERA_CI=m --CONFIG_VIDEO_CX25821=m --CONFIG_VIDEO_CX25821_ALSA=m --CONFIG_VIDEO_CX88=m --CONFIG_VIDEO_CX88_ALSA=m --CONFIG_VIDEO_CX88_BLACKBIRD=m --CONFIG_VIDEO_CX88_DVB=m --CONFIG_VIDEO_CX88_ENABLE_VP3054=y --CONFIG_VIDEO_CX88_VP3054=m --CONFIG_VIDEO_CX88_MPEG=m --CONFIG_VIDEO_BT848=m --CONFIG_DVB_BT8XX=m --CONFIG_VIDEO_SAA7134=m --CONFIG_VIDEO_SAA7134_ALSA=m --CONFIG_VIDEO_SAA7134_RC=y --CONFIG_VIDEO_SAA7134_DVB=m --CONFIG_VIDEO_SAA7134_GO7007=m --CONFIG_VIDEO_SAA7164=m -- --# --# Media digital TV PCI Adapters --# --CONFIG_DVB_AV7110_IR=y --CONFIG_DVB_AV7110=m --CONFIG_DVB_AV7110_OSD=y --CONFIG_DVB_BUDGET_CORE=m --CONFIG_DVB_BUDGET=m --CONFIG_DVB_BUDGET_CI=m --CONFIG_DVB_BUDGET_AV=m --CONFIG_DVB_BUDGET_PATCH=m --CONFIG_DVB_B2C2_FLEXCOP_PCI=m --# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set --CONFIG_DVB_PLUTO2=m --CONFIG_DVB_DM1105=m --CONFIG_DVB_PT1=m --CONFIG_DVB_PT3=m --CONFIG_MANTIS_CORE=m --CONFIG_DVB_MANTIS=m --CONFIG_DVB_HOPPER=m --CONFIG_DVB_NGENE=m --CONFIG_DVB_DDBRIDGE=m --CONFIG_DVB_SMIPCIE=m --# CONFIG_DVB_NETUP_UNIDVB is not set --CONFIG_V4L_PLATFORM_DRIVERS=y --# CONFIG_VIDEO_CAFE_CCIC is not set --CONFIG_VIDEO_MXC_OUTPUT=y --CONFIG_VIDEO_MXC_CAPTURE=m -- --# --# MXC Camera/V4L2 PRP Features support --# --CONFIG_VIDEO_MXC_IPU_CAMERA=y --# CONFIG_VIDEO_MXC_CSI_CAMERA is not set --# CONFIG_MXC_TVIN_TDA1997X is not set --CONFIG_MXC_CAMERA_OV5640=m --CONFIG_MXC_CAMERA_OV5642=m --CONFIG_MXC_CAMERA_OV5640_MIPI=m --CONFIG_MXC_CAMERA_OV5647_MIPI=m --# CONFIG_MXC_HDMI_CSI2_TC358743 is not set --# CONFIG_MXC_TVIN_ADV7180 is not set --CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m --CONFIG_MXC_IPU_PRP_ENC=m --CONFIG_MXC_IPU_CSI_ENC=m --CONFIG_VIDEO_MXC_IPU_OUTPUT=y --CONFIG_VIDEO_MXC_PXP_V4L2=y --CONFIG_SOC_CAMERA=y --CONFIG_SOC_CAMERA_PLATFORM=y --# CONFIG_VIDEO_XILINX is not set --CONFIG_V4L_MEM2MEM_DRIVERS=y --# CONFIG_VIDEO_CODA is not set --CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m --CONFIG_VIDEO_SH_VEU=m --# CONFIG_V4L_TEST_DRIVERS is not set --# CONFIG_DVB_PLATFORM_DRIVERS is not set -- --# --# Supported MMC/SDIO adapters --# --CONFIG_SMS_SDIO_DRV=m --CONFIG_RADIO_ADAPTERS=y --CONFIG_RADIO_TEA575X=m --CONFIG_RADIO_SI470X=y --CONFIG_USB_SI470X=m --CONFIG_I2C_SI470X=m --CONFIG_RADIO_SI4713=m --CONFIG_USB_SI4713=m --CONFIG_PLATFORM_SI4713=m --CONFIG_I2C_SI4713=m --CONFIG_RADIO_SI476X=m --CONFIG_USB_MR800=m --CONFIG_USB_DSBR=m --CONFIG_RADIO_MAXIRADIO=m --CONFIG_RADIO_SHARK=m --CONFIG_RADIO_SHARK2=m --CONFIG_USB_KEENE=m --CONFIG_USB_RAREMONO=m --CONFIG_USB_MA901=m --CONFIG_RADIO_TEA5764=m --CONFIG_RADIO_SAA7706H=m --CONFIG_RADIO_TEF6862=m --CONFIG_RADIO_WL1273=m -- --# --# Texas Instruments WL128x FM driver (ST based) --# --CONFIG_RADIO_WL128X=m --CONFIG_MEDIA_COMMON_OPTIONS=y -- --# --# common driver options --# --CONFIG_VIDEO_CX2341X=m --CONFIG_VIDEO_TVEEPROM=m --CONFIG_CYPRESS_FIRMWARE=m --CONFIG_DVB_B2C2_FLEXCOP=m --CONFIG_VIDEO_SAA7146=m --CONFIG_VIDEO_SAA7146_VV=m --CONFIG_SMS_SIANO_MDTV=m --CONFIG_SMS_SIANO_RC=y --# CONFIG_SMS_SIANO_DEBUGFS is not set -- --# --# Media ancillary drivers (tuners, sensors, i2c, frontends) --# --# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set --CONFIG_MEDIA_ATTACH=y --CONFIG_VIDEO_IR_I2C=m -- --# --# Encoders, decoders, sensors and other helper chips --# -- --# --# Audio decoders, processors and mixers --# --CONFIG_VIDEO_TVAUDIO=m --CONFIG_VIDEO_TDA7432=m --CONFIG_VIDEO_TDA9840=m --CONFIG_VIDEO_TEA6415C=m --CONFIG_VIDEO_TEA6420=m --CONFIG_VIDEO_MSP3400=m --CONFIG_VIDEO_CS5345=m --CONFIG_VIDEO_CS53L32A=m --CONFIG_VIDEO_TLV320AIC23B=m --CONFIG_VIDEO_UDA1342=m --CONFIG_VIDEO_WM8775=m --CONFIG_VIDEO_WM8739=m --CONFIG_VIDEO_VP27SMPX=m --CONFIG_VIDEO_SONY_BTF_MPX=m -- --# --# RDS decoders --# --CONFIG_VIDEO_SAA6588=m -- --# --# Video decoders --# --CONFIG_VIDEO_ADV7180=m --CONFIG_VIDEO_ADV7183=m --CONFIG_VIDEO_ADV7604=m --CONFIG_VIDEO_ADV7842=m --CONFIG_VIDEO_BT819=m --CONFIG_VIDEO_BT856=m --CONFIG_VIDEO_BT866=m --CONFIG_VIDEO_KS0127=m --CONFIG_VIDEO_ML86V7667=m --CONFIG_VIDEO_SAA7110=m --CONFIG_VIDEO_SAA711X=m --CONFIG_VIDEO_TC358743=m --CONFIG_VIDEO_TVP514X=m --CONFIG_VIDEO_TVP5150=m --CONFIG_VIDEO_TVP7002=m --CONFIG_VIDEO_TW2804=m --CONFIG_VIDEO_TW9903=m --CONFIG_VIDEO_TW9906=m --CONFIG_VIDEO_VPX3220=m -- --# --# Video and audio decoders --# --CONFIG_VIDEO_SAA717X=m --CONFIG_VIDEO_CX25840=m -- --# --# Video encoders --# --CONFIG_VIDEO_SAA7127=m --CONFIG_VIDEO_SAA7185=m --CONFIG_VIDEO_ADV7170=m --CONFIG_VIDEO_ADV7175=m --CONFIG_VIDEO_ADV7343=m --CONFIG_VIDEO_ADV7393=m --CONFIG_VIDEO_ADV7511=m --CONFIG_VIDEO_AD9389B=m --CONFIG_VIDEO_AK881X=m --CONFIG_VIDEO_THS8200=m -- --# --# Camera sensor devices --# --CONFIG_VIDEO_APTINA_PLL=m --CONFIG_VIDEO_SMIAPP_PLL=m --CONFIG_VIDEO_OV2659=m --CONFIG_VIDEO_OV7640=m --CONFIG_VIDEO_OV7670=m --CONFIG_VIDEO_OV9650=m --CONFIG_VIDEO_VS6624=m --CONFIG_VIDEO_MT9M032=m --CONFIG_VIDEO_MT9P031=m --CONFIG_VIDEO_MT9T001=m --CONFIG_VIDEO_MT9V011=m --CONFIG_VIDEO_MT9V032=m --CONFIG_VIDEO_SR030PC30=m --CONFIG_VIDEO_NOON010PC30=m --CONFIG_VIDEO_M5MOLS=m --CONFIG_VIDEO_S5K6AA=m --CONFIG_VIDEO_S5K6A3=m --CONFIG_VIDEO_S5K4ECGX=m --CONFIG_VIDEO_S5K5BAF=m --CONFIG_VIDEO_SMIAPP=m --CONFIG_VIDEO_S5C73M3=m -- --# --# Flash devices --# --CONFIG_VIDEO_ADP1653=m --CONFIG_VIDEO_AS3645A=m --CONFIG_VIDEO_LM3560=m --CONFIG_VIDEO_LM3646=m -- --# --# Video improvement chips --# --CONFIG_VIDEO_UPD64031A=m --CONFIG_VIDEO_UPD64083=m -- --# --# Audio/Video compression chips --# --CONFIG_VIDEO_SAA6752HS=m -- --# --# Miscellaneous helper chips --# --CONFIG_VIDEO_THS7303=m --CONFIG_VIDEO_M52790=m -- --# --# Sensors used on soc_camera driver --# -- --# --# soc_camera sensor drivers --# --CONFIG_SOC_CAMERA_IMX074=m --CONFIG_SOC_CAMERA_MT9M001=m --CONFIG_SOC_CAMERA_MT9M111=m --CONFIG_SOC_CAMERA_MT9T031=m --CONFIG_SOC_CAMERA_MT9T112=m --CONFIG_SOC_CAMERA_MT9V022=m --CONFIG_SOC_CAMERA_OV2640=m --CONFIG_SOC_CAMERA_OV5642=m --CONFIG_SOC_CAMERA_OV6650=m --CONFIG_SOC_CAMERA_OV772X=m --CONFIG_SOC_CAMERA_OV9640=m --CONFIG_SOC_CAMERA_OV9740=m --CONFIG_SOC_CAMERA_RJ54N1=m --CONFIG_SOC_CAMERA_TW9910=m --CONFIG_MEDIA_TUNER=y -- --# --# Customize TV tuners --# --CONFIG_MEDIA_TUNER_SIMPLE=m --CONFIG_MEDIA_TUNER_TDA8290=m --CONFIG_MEDIA_TUNER_TDA827X=m --CONFIG_MEDIA_TUNER_TDA18271=m --CONFIG_MEDIA_TUNER_TDA9887=m --CONFIG_MEDIA_TUNER_TEA5761=m --CONFIG_MEDIA_TUNER_TEA5767=m --CONFIG_MEDIA_TUNER_MSI001=m --CONFIG_MEDIA_TUNER_MT20XX=m --CONFIG_MEDIA_TUNER_MT2060=m --CONFIG_MEDIA_TUNER_MT2063=m --CONFIG_MEDIA_TUNER_MT2266=m --CONFIG_MEDIA_TUNER_MT2131=m --CONFIG_MEDIA_TUNER_QT1010=m --CONFIG_MEDIA_TUNER_XC2028=m --CONFIG_MEDIA_TUNER_XC5000=m --CONFIG_MEDIA_TUNER_XC4000=m --CONFIG_MEDIA_TUNER_MXL5005S=m --CONFIG_MEDIA_TUNER_MXL5007T=m --CONFIG_MEDIA_TUNER_MC44S803=m --CONFIG_MEDIA_TUNER_MAX2165=m --CONFIG_MEDIA_TUNER_TDA18218=m --CONFIG_MEDIA_TUNER_FC0011=m --CONFIG_MEDIA_TUNER_FC0012=m --CONFIG_MEDIA_TUNER_FC0013=m --CONFIG_MEDIA_TUNER_TDA18212=m --CONFIG_MEDIA_TUNER_E4000=m --CONFIG_MEDIA_TUNER_FC2580=m --CONFIG_MEDIA_TUNER_M88RS6000T=m --CONFIG_MEDIA_TUNER_TUA9001=m --CONFIG_MEDIA_TUNER_SI2157=m --CONFIG_MEDIA_TUNER_IT913X=m --CONFIG_MEDIA_TUNER_R820T=m --CONFIG_MEDIA_TUNER_MXL301RF=m --CONFIG_MEDIA_TUNER_QM1D1C0042=m -- --# --# Customise DVB Frontends --# -- --# --# Multistandard (satellite) frontends --# --CONFIG_DVB_STB0899=m --CONFIG_DVB_STB6100=m --CONFIG_DVB_STV090x=m --CONFIG_DVB_STV6110x=m --CONFIG_DVB_M88DS3103=m -- --# --# Multistandard (cable + terrestrial) frontends --# --CONFIG_DVB_DRXK=m --CONFIG_DVB_TDA18271C2DD=m --CONFIG_DVB_SI2165=m -- --# --# DVB-S (satellite) frontends --# --CONFIG_DVB_CX24110=m --CONFIG_DVB_CX24123=m --CONFIG_DVB_MT312=m --CONFIG_DVB_ZL10036=m --CONFIG_DVB_ZL10039=m --CONFIG_DVB_S5H1420=m --CONFIG_DVB_STV0288=m --CONFIG_DVB_STB6000=m --CONFIG_DVB_STV0299=m --CONFIG_DVB_STV6110=m --CONFIG_DVB_STV0900=m --CONFIG_DVB_TDA8083=m --CONFIG_DVB_TDA10086=m --CONFIG_DVB_TDA8261=m --CONFIG_DVB_VES1X93=m --CONFIG_DVB_TUNER_ITD1000=m --CONFIG_DVB_TUNER_CX24113=m --CONFIG_DVB_TDA826X=m --CONFIG_DVB_TUA6100=m --CONFIG_DVB_CX24116=m --CONFIG_DVB_CX24117=m --CONFIG_DVB_CX24120=m --CONFIG_DVB_SI21XX=m --CONFIG_DVB_TS2020=m --CONFIG_DVB_DS3000=m --CONFIG_DVB_MB86A16=m --CONFIG_DVB_TDA10071=m -- --# --# DVB-T (terrestrial) frontends --# --CONFIG_DVB_SP8870=m --CONFIG_DVB_SP887X=m --CONFIG_DVB_CX22700=m --CONFIG_DVB_CX22702=m --CONFIG_DVB_S5H1432=m --CONFIG_DVB_DRXD=m --CONFIG_DVB_L64781=m --CONFIG_DVB_TDA1004X=m --CONFIG_DVB_NXT6000=m --CONFIG_DVB_MT352=m --CONFIG_DVB_ZL10353=m --CONFIG_DVB_DIB3000MB=m --CONFIG_DVB_DIB3000MC=m --CONFIG_DVB_DIB7000M=m --CONFIG_DVB_DIB7000P=m --CONFIG_DVB_DIB9000=m --CONFIG_DVB_TDA10048=m --CONFIG_DVB_AF9013=m --CONFIG_DVB_EC100=m --CONFIG_DVB_HD29L2=m --CONFIG_DVB_STV0367=m --CONFIG_DVB_CXD2820R=m --CONFIG_DVB_CXD2841ER=m --CONFIG_DVB_RTL2830=m --CONFIG_DVB_RTL2832=m --CONFIG_DVB_RTL2832_SDR=m --CONFIG_DVB_SI2168=m --CONFIG_DVB_AS102_FE=m -- --# --# DVB-C (cable) frontends --# --CONFIG_DVB_VES1820=m --CONFIG_DVB_TDA10021=m --CONFIG_DVB_TDA10023=m --CONFIG_DVB_STV0297=m -- --# --# ATSC (North American/Korean Terrestrial/Cable DTV) frontends --# --CONFIG_DVB_NXT200X=m --CONFIG_DVB_OR51211=m --CONFIG_DVB_OR51132=m --CONFIG_DVB_BCM3510=m --CONFIG_DVB_LGDT330X=m --CONFIG_DVB_LGDT3305=m --CONFIG_DVB_LGDT3306A=m --CONFIG_DVB_LG2160=m --CONFIG_DVB_S5H1409=m --CONFIG_DVB_AU8522=m --CONFIG_DVB_AU8522_DTV=m --CONFIG_DVB_AU8522_V4L=m --CONFIG_DVB_S5H1411=m -- --# --# ISDB-T (terrestrial) frontends --# --CONFIG_DVB_S921=m --CONFIG_DVB_DIB8000=m --CONFIG_DVB_MB86A20S=m -- --# --# ISDB-S (satellite) & ISDB-T (terrestrial) frontends --# --CONFIG_DVB_TC90522=m -- --# --# Digital terrestrial only tuners/PLL --# --CONFIG_DVB_PLL=m --CONFIG_DVB_TUNER_DIB0070=m --CONFIG_DVB_TUNER_DIB0090=m -- --# --# SEC control devices for DVB-S --# --CONFIG_DVB_DRX39XYJ=m --CONFIG_DVB_LNBH25=m --CONFIG_DVB_LNBP21=m --CONFIG_DVB_LNBP22=m --CONFIG_DVB_ISL6405=m --CONFIG_DVB_ISL6421=m --CONFIG_DVB_ISL6423=m --CONFIG_DVB_A8293=m --CONFIG_DVB_SP2=m --CONFIG_DVB_LGS8GL5=m --CONFIG_DVB_LGS8GXX=m --CONFIG_DVB_ATBM8830=m --CONFIG_DVB_TDA665x=m --CONFIG_DVB_IX2505V=m --CONFIG_DVB_M88RS2000=m --CONFIG_DVB_AF9033=m --CONFIG_DVB_HORUS3A=m --CONFIG_DVB_ASCOT2E=m -- --# --# Tools to develop new frontends --# --CONFIG_DVB_DUMMY_FE=m -- --# --# Graphics support --# --CONFIG_VGA_ARB=y --CONFIG_VGA_ARB_MAX_GPUS=16 --# CONFIG_IMX_IPUV3_CORE is not set --CONFIG_DRM=y --# CONFIG_DRM_FBDEV_EMULATION is not set --# CONFIG_DRM_TDFX is not set --# CONFIG_DRM_R128 is not set --# CONFIG_DRM_RADEON is not set --# CONFIG_DRM_AMDGPU is not set --# CONFIG_DRM_NOUVEAU is not set --# CONFIG_DRM_MGA is not set --# CONFIG_DRM_VIA is not set --# CONFIG_DRM_SAVAGE is not set --# CONFIG_DRM_VGEM is not set --# CONFIG_DRM_EXYNOS is not set --# CONFIG_DRM_UDL is not set --# CONFIG_DRM_AST is not set --# CONFIG_DRM_MGAG200 is not set --# CONFIG_DRM_CIRRUS_QEMU is not set --# CONFIG_DRM_ARMADA is not set --# CONFIG_DRM_TILCDC is not set --# CONFIG_DRM_QXL is not set --# CONFIG_DRM_BOCHS is not set --# CONFIG_DRM_FSL_DCU is not set --CONFIG_DRM_BRIDGE=y -- --# --# Display Interface Bridges --# --# CONFIG_DRM_NXP_PTN3460 is not set --# CONFIG_DRM_PARADE_PS8622 is not set --# CONFIG_DRM_STI is not set --CONFIG_DRM_VIVANTE=m -- --# --# Frame buffer Devices --# --CONFIG_FB=y --CONFIG_FIRMWARE_EDID=y --CONFIG_FB_CMDLINE=y --# CONFIG_FB_DDC is not set --# CONFIG_FB_BOOT_VESA_SUPPORT is not set --CONFIG_FB_CFB_FILLRECT=y --CONFIG_FB_CFB_COPYAREA=y --CONFIG_FB_CFB_IMAGEBLIT=y --# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set --CONFIG_FB_SYS_FILLRECT=m --CONFIG_FB_SYS_COPYAREA=m --CONFIG_FB_SYS_IMAGEBLIT=m --# CONFIG_FB_FOREIGN_ENDIAN is not set --CONFIG_FB_SYS_FOPS=m --CONFIG_FB_DEFERRED_IO=y --# CONFIG_FB_SVGALIB is not set --# CONFIG_FB_MACMODES is not set --CONFIG_FB_BACKLIGHT=y --CONFIG_FB_MODE_HELPERS=y --# CONFIG_FB_TILEBLITTING is not set -- --# --# Frame buffer hardware drivers --# --# CONFIG_FB_CIRRUS is not set --# CONFIG_FB_PM2 is not set --# CONFIG_FB_IMX is not set --# CONFIG_FB_CYBER2000 is not set --# CONFIG_FB_ASILIANT is not set --# CONFIG_FB_IMSTT is not set --# CONFIG_FB_UVESA is not set --# CONFIG_FB_OPENCORES is not set --# CONFIG_FB_S1D13XXX is not set --# CONFIG_FB_NVIDIA is not set --# CONFIG_FB_RIVA is not set --# CONFIG_FB_I740 is not set --# CONFIG_FB_MATROX is not set --# CONFIG_FB_RADEON is not set --# CONFIG_FB_ATY128 is not set --# CONFIG_FB_ATY is not set --# CONFIG_FB_S3 is not set --# CONFIG_FB_SAVAGE is not set --# CONFIG_FB_SIS is not set --# CONFIG_FB_NEOMAGIC is not set --# CONFIG_FB_KYRO is not set --# CONFIG_FB_3DFX is not set --# CONFIG_FB_VOODOO1 is not set --# CONFIG_FB_VT8623 is not set --# CONFIG_FB_TRIDENT is not set --# CONFIG_FB_ARK is not set --# CONFIG_FB_PM3 is not set --# CONFIG_FB_CARMINE is not set --# CONFIG_FB_SMSCUFX is not set --CONFIG_FB_UDL=m --# CONFIG_FB_IBM_GXT4500 is not set --# CONFIG_FB_VIRTUAL is not set --# CONFIG_FB_METRONOME is not set --# CONFIG_FB_MB862XX is not set --# CONFIG_FB_BROADSHEET is not set --# CONFIG_FB_AUO_K190X is not set --# CONFIG_FB_MXS is not set --# CONFIG_FB_SIMPLE is not set --# CONFIG_FB_SSD1307 is not set --# CONFIG_FB_SM712 is not set --CONFIG_FB_MXC=y --CONFIG_FB_MXC_SYNC_PANEL=y --# CONFIG_FB_MXC_TVOUT_ADV739X is not set --CONFIG_FB_MXC_LDB=y --# CONFIG_FB_MXC_MIPI_DSI is not set --CONFIG_FB_MXC_HDMI=y --CONFIG_FB_MXC_DCIC=y --CONFIG_FB_MXC_EDID=y --# CONFIG_FB_MXC_EINK_PANEL is not set --CONFIG_BACKLIGHT_LCD_SUPPORT=y --CONFIG_LCD_CLASS_DEVICE=m --# CONFIG_LCD_L4F00242T03 is not set --# CONFIG_LCD_LMS283GF05 is not set --# CONFIG_LCD_LTV350QV is not set --# CONFIG_LCD_ILI922X is not set --# CONFIG_LCD_ILI9320 is not set --# CONFIG_LCD_TDO24M is not set --# CONFIG_LCD_VGG2432A4 is not set --CONFIG_LCD_PLATFORM=m --# CONFIG_LCD_S6E63M0 is not set --# CONFIG_LCD_LD9040 is not set --# CONFIG_LCD_AMS369FG06 is not set --# CONFIG_LCD_LMS501KF03 is not set --# CONFIG_LCD_HX8357 is not set --CONFIG_BACKLIGHT_CLASS_DEVICE=y --# CONFIG_BACKLIGHT_GENERIC is not set --CONFIG_BACKLIGHT_PWM=m --# CONFIG_BACKLIGHT_DA9052 is not set --# CONFIG_BACKLIGHT_PM8941_WLED is not set --# CONFIG_BACKLIGHT_ADP8860 is not set --# CONFIG_BACKLIGHT_ADP8870 is not set --# CONFIG_BACKLIGHT_LM3630A is not set --# CONFIG_BACKLIGHT_LM3639 is not set --# CONFIG_BACKLIGHT_LP855X is not set --# CONFIG_BACKLIGHT_GPIO is not set --# CONFIG_BACKLIGHT_LV5207LP is not set --# CONFIG_BACKLIGHT_BD6107 is not set --# CONFIG_VGASTATE is not set --CONFIG_VIDEOMODE_HELPERS=y --CONFIG_HDMI=y -- --# --# Console display driver support --# --CONFIG_DUMMY_CONSOLE=y --CONFIG_FRAMEBUFFER_CONSOLE=y --CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y --# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set --# CONFIG_LOGO is not set --CONFIG_SOUND=y --# CONFIG_SOUND_OSS_CORE is not set --CONFIG_SND=y --CONFIG_SND_TIMER=y --CONFIG_SND_PCM=y --CONFIG_SND_DMAENGINE_PCM=y --CONFIG_SND_HWDEP=m --CONFIG_SND_RAWMIDI=m --CONFIG_SND_JACK=y --# CONFIG_SND_SEQUENCER is not set --# CONFIG_SND_MIXER_OSS is not set --# CONFIG_SND_PCM_OSS is not set --CONFIG_SND_PCM_TIMER=y --CONFIG_SND_HRTIMER=y --# CONFIG_SND_DYNAMIC_MINORS is not set --# CONFIG_SND_SUPPORT_OLD_API is not set --CONFIG_SND_PROC_FS=y --# CONFIG_SND_VERBOSE_PROCFS is not set --# CONFIG_SND_VERBOSE_PRINTK is not set --# CONFIG_SND_DEBUG is not set --CONFIG_SND_VMASTER=y --# CONFIG_SND_RAWMIDI_SEQ is not set --# CONFIG_SND_OPL3_LIB_SEQ is not set --# CONFIG_SND_OPL4_LIB_SEQ is not set --# CONFIG_SND_SBAWE_SEQ is not set --# CONFIG_SND_EMU10K1_SEQ is not set --CONFIG_SND_MPU401_UART=m --CONFIG_SND_AC97_CODEC=m --CONFIG_SND_DRIVERS=y --CONFIG_SND_DUMMY=m --CONFIG_SND_ALOOP=m --CONFIG_SND_MTPAV=m --CONFIG_SND_SERIAL_U16550=m --CONFIG_SND_MPU401=m --CONFIG_SND_AC97_POWER_SAVE=y --CONFIG_SND_AC97_POWER_SAVE_DEFAULT=1 --# CONFIG_SND_PCI is not set -- --# --# HD-Audio --# --CONFIG_SND_HDA_PREALLOC_SIZE=64 --CONFIG_SND_ARM=y --CONFIG_SND_SPI=y --CONFIG_SND_USB=y --CONFIG_SND_USB_AUDIO=m --CONFIG_SND_USB_UA101=m --CONFIG_SND_USB_CAIAQ=m --CONFIG_SND_USB_CAIAQ_INPUT=y --CONFIG_SND_USB_6FIRE=m --CONFIG_SND_USB_HIFACE=m --CONFIG_SND_BCD2000=m --CONFIG_SND_USB_LINE6=m --CONFIG_SND_USB_POD=m --CONFIG_SND_USB_PODHD=m --CONFIG_SND_USB_TONEPORT=m --CONFIG_SND_USB_VARIAX=m --CONFIG_SND_SOC=y --CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y --# CONFIG_SND_ATMEL_SOC is not set --# CONFIG_SND_DESIGNWARE_I2S is not set -- --# --# SoC Audio for Freescale CPUs --# -- --# --# Common SoC Audio options for Freescale CPUs: --# --# CONFIG_SND_SOC_FSL_ASRC is not set --CONFIG_SND_SOC_FSL_SAI=y --CONFIG_SND_SOC_FSL_SSI=y --CONFIG_SND_SOC_FSL_SPDIF=y --CONFIG_SND_SOC_FSL_ESAI=y --CONFIG_SND_SOC_FSL_HDMI=y --CONFIG_SND_SOC_FSL_UTILS=y --CONFIG_SND_SOC_IMX_PCM_DMA=y --CONFIG_SND_SOC_IMX_HDMI_DMA=y --CONFIG_SND_SOC_IMX_AUDMUX=y --CONFIG_SND_IMX_SOC=y -- --# --# SoC Audio support for Freescale i.MX boards: --# --# CONFIG_SND_SOC_EUKREA_TLV320 is not set --# CONFIG_SND_SOC_IMX_WM8731 is not set --# CONFIG_SND_SOC_IMX_WM8962 is not set --# CONFIG_SND_SOC_IMX_ES8328 is not set --CONFIG_SND_SOC_IMX_SGTL5000=y --# CONFIG_SND_SOC_IMX_AC97_VT1613 is not set --CONFIG_SND_SOC_IMX_SPDIF=y --# CONFIG_SND_SOC_IMX_MC13783 is not set --CONFIG_SND_SOC_IMX_HDMI=y --CONFIG_SND_SOC_FSL_ASOC_CARD=m --# CONFIG_SND_SOC_IMX_TDA1997X is not set -- --# --# Allwinner SoC Audio support --# --# CONFIG_SND_SUN4I_CODEC is not set --# CONFIG_SND_SOC_XTFPGA_I2S is not set --CONFIG_SND_SOC_I2C_AND_SPI=y -- --# --# CODEC drivers --# --# CONFIG_SND_SOC_AC97_CODEC is not set --# CONFIG_SND_SOC_ADAU1701 is not set --# CONFIG_SND_SOC_AK4104 is not set --# CONFIG_SND_SOC_AK4554 is not set --# CONFIG_SND_SOC_AK4613 is not set --# CONFIG_SND_SOC_AK4642 is not set --# CONFIG_SND_SOC_AK5386 is not set --# CONFIG_SND_SOC_ALC5623 is not set --# CONFIG_SND_SOC_CS35L32 is not set --# CONFIG_SND_SOC_CS42L51_I2C is not set --# CONFIG_SND_SOC_CS42L52 is not set --# CONFIG_SND_SOC_CS42L56 is not set --# CONFIG_SND_SOC_CS42L73 is not set --# CONFIG_SND_SOC_CS4265 is not set --# CONFIG_SND_SOC_CS4270 is not set --# CONFIG_SND_SOC_CS4271_I2C is not set --# CONFIG_SND_SOC_CS4271_SPI is not set --# CONFIG_SND_SOC_CS42XX8_I2C is not set --# CONFIG_SND_SOC_CS4349 is not set --CONFIG_SND_SOC_HDMI_CODEC=y --# CONFIG_SND_SOC_ES8328 is not set --# CONFIG_SND_SOC_GTM601 is not set --# CONFIG_SND_SOC_PCM1681 is not set --# CONFIG_SND_SOC_PCM1792A is not set --# CONFIG_SND_SOC_PCM512x_I2C is not set --# CONFIG_SND_SOC_PCM512x_SPI is not set --# CONFIG_SND_SOC_RT5631 is not set --# CONFIG_SND_SOC_RT5677_SPI is not set --CONFIG_SND_SOC_SGTL5000=y --CONFIG_SND_SOC_SI476X=m --# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set --CONFIG_SND_SOC_SPDIF=y --# CONFIG_SND_SOC_SSM2602_SPI is not set --# CONFIG_SND_SOC_SSM2602_I2C is not set --# CONFIG_SND_SOC_SSM4567 is not set --# CONFIG_SND_SOC_STA32X is not set --# CONFIG_SND_SOC_STA350 is not set --# CONFIG_SND_SOC_STI_SAS is not set --# CONFIG_SND_SOC_TAS2552 is not set --# CONFIG_SND_SOC_TAS5086 is not set --# CONFIG_SND_SOC_TAS571X is not set --# CONFIG_SND_SOC_TFA9879 is not set --# CONFIG_SND_SOC_TLV320AIC23_I2C is not set --# CONFIG_SND_SOC_TLV320AIC23_SPI is not set --# CONFIG_SND_SOC_TLV320AIC31XX is not set --# CONFIG_SND_SOC_TLV320AIC3X is not set --# CONFIG_SND_SOC_TS3A227E is not set --# CONFIG_SND_SOC_WM8510 is not set --# CONFIG_SND_SOC_WM8523 is not set --# CONFIG_SND_SOC_WM8580 is not set --# CONFIG_SND_SOC_WM8711 is not set --# CONFIG_SND_SOC_WM8728 is not set --# CONFIG_SND_SOC_WM8731 is not set --# CONFIG_SND_SOC_WM8737 is not set --# CONFIG_SND_SOC_WM8741 is not set --# CONFIG_SND_SOC_WM8750 is not set --# CONFIG_SND_SOC_WM8753 is not set --# CONFIG_SND_SOC_WM8770 is not set --# CONFIG_SND_SOC_WM8776 is not set --# CONFIG_SND_SOC_WM8804_I2C is not set --# CONFIG_SND_SOC_WM8804_SPI is not set --# CONFIG_SND_SOC_WM8903 is not set --CONFIG_SND_SOC_WM8962=m --# CONFIG_SND_SOC_WM8978 is not set --# CONFIG_SND_SOC_TPA6130A2 is not set --# CONFIG_SND_SIMPLE_CARD is not set --# CONFIG_SOUND_PRIME is not set --CONFIG_AC97_BUS=m -- --# --# HID support --# --CONFIG_HID=y --CONFIG_HID_BATTERY_STRENGTH=y --CONFIG_HIDRAW=y --CONFIG_UHID=m --CONFIG_HID_GENERIC=y -- --# --# Special HID drivers --# --CONFIG_HID_A4TECH=m --CONFIG_HID_ACRUX=m --CONFIG_HID_ACRUX_FF=y --CONFIG_HID_APPLE=m --CONFIG_HID_APPLEIR=m --CONFIG_HID_AUREAL=m --CONFIG_HID_BELKIN=m --CONFIG_HID_BETOP_FF=m --CONFIG_HID_CHERRY=m --CONFIG_HID_CHICONY=m --# CONFIG_HID_CORSAIR is not set --CONFIG_HID_PRODIKEYS=m --CONFIG_HID_CP2112=m --CONFIG_HID_CYPRESS=m --CONFIG_HID_DRAGONRISE=m --CONFIG_DRAGONRISE_FF=y --CONFIG_HID_EMS_FF=m --CONFIG_HID_ELECOM=m --CONFIG_HID_ELO=m --CONFIG_HID_EZKEY=m --# CONFIG_HID_GEMBIRD is not set --# CONFIG_HID_GFRM is not set --CONFIG_HID_HOLTEK=m --CONFIG_HOLTEK_FF=y --CONFIG_HID_GT683R=m --CONFIG_HID_KEYTOUCH=m --CONFIG_HID_KYE=m --CONFIG_HID_UCLOGIC=m --CONFIG_HID_WALTOP=m --CONFIG_HID_GYRATION=m --CONFIG_HID_ICADE=m --CONFIG_HID_TWINHAN=m --CONFIG_HID_KENSINGTON=m --CONFIG_HID_LCPOWER=m --CONFIG_HID_LENOVO=m --CONFIG_HID_LOGITECH=m --CONFIG_HID_LOGITECH_DJ=m --CONFIG_HID_LOGITECH_HIDPP=m --CONFIG_LOGITECH_FF=y --CONFIG_LOGIRUMBLEPAD2_FF=y --CONFIG_LOGIG940_FF=y --CONFIG_LOGIWHEELS_FF=y --CONFIG_HID_MAGICMOUSE=m --CONFIG_HID_MICROSOFT=m --CONFIG_HID_MONTEREY=m --CONFIG_HID_MULTITOUCH=m --CONFIG_HID_NTRIG=m --CONFIG_HID_ORTEK=m --CONFIG_HID_PANTHERLORD=m --CONFIG_PANTHERLORD_FF=y --CONFIG_HID_PENMOUNT=m --CONFIG_HID_PETALYNX=m --CONFIG_HID_PICOLCD=m --CONFIG_HID_PICOLCD_FB=y --CONFIG_HID_PICOLCD_BACKLIGHT=y --CONFIG_HID_PICOLCD_LCD=y --CONFIG_HID_PICOLCD_LEDS=y --CONFIG_HID_PICOLCD_CIR=y --CONFIG_HID_PLANTRONICS=m --CONFIG_HID_PRIMAX=m --CONFIG_HID_ROCCAT=m --CONFIG_HID_SAITEK=m --CONFIG_HID_SAMSUNG=m --CONFIG_HID_SONY=m --CONFIG_SONY_FF=y --CONFIG_HID_SPEEDLINK=m --CONFIG_HID_STEELSERIES=m --CONFIG_HID_SUNPLUS=m --CONFIG_HID_RMI=m --CONFIG_HID_GREENASIA=m --CONFIG_GREENASIA_FF=y --CONFIG_HID_SMARTJOYPLUS=m --CONFIG_SMARTJOYPLUS_FF=y --CONFIG_HID_TIVO=m --CONFIG_HID_TOPSEED=m --CONFIG_HID_THINGM=m --CONFIG_HID_THRUSTMASTER=m --CONFIG_THRUSTMASTER_FF=y --CONFIG_HID_WACOM=m --CONFIG_HID_WIIMOTE=m --CONFIG_HID_XINMO=m --CONFIG_HID_ZEROPLUS=m --CONFIG_ZEROPLUS_FF=y --CONFIG_HID_ZYDACRON=m --CONFIG_HID_SENSOR_HUB=m --CONFIG_HID_SENSOR_CUSTOM_SENSOR=m -- --# --# USB HID support --# --CONFIG_USB_HID=y --CONFIG_HID_PID=y --CONFIG_USB_HIDDEV=y -- --# --# I2C HID support --# --CONFIG_I2C_HID=m --CONFIG_USB_OHCI_LITTLE_ENDIAN=y --CONFIG_USB_SUPPORT=y --CONFIG_USB_COMMON=y --CONFIG_USB_ARCH_HAS_HCD=y --CONFIG_USB=y --# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set -- --# --# Miscellaneous USB options --# --CONFIG_USB_DEFAULT_PERSIST=y --# CONFIG_USB_DYNAMIC_MINORS is not set --CONFIG_USB_OTG=y --# CONFIG_USB_OTG_WHITELIST is not set --# CONFIG_USB_OTG_BLACKLIST_HUB is not set --CONFIG_USB_OTG_FSM=y --# CONFIG_USB_ULPI_BUS is not set --# CONFIG_USB_MON is not set --# CONFIG_USB_WUSB_CBAF is not set -- --# --# USB Host Controller Drivers --# --# CONFIG_USB_C67X00_HCD is not set --# CONFIG_USB_XHCI_HCD is not set --CONFIG_USB_EHCI_HCD=y --CONFIG_USB_EHCI_ROOT_HUB_TT=y --CONFIG_USB_EHCI_TT_NEWSCHED=y --CONFIG_USB_FSL_MPH_DR_OF=m --CONFIG_USB_EHCI_PCI=y --CONFIG_USB_EHCI_MXC=y --CONFIG_USB_EHCI_HCD_PLATFORM=y --# CONFIG_USB_OXU210HP_HCD is not set --# CONFIG_USB_ISP116X_HCD is not set --# CONFIG_USB_ISP1362_HCD is not set --# CONFIG_USB_FOTG210_HCD is not set --# CONFIG_USB_MAX3421_HCD is not set --# CONFIG_USB_OHCI_HCD is not set --# CONFIG_USB_UHCI_HCD is not set --# CONFIG_USB_SL811_HCD is not set --# CONFIG_USB_R8A66597_HCD is not set --# CONFIG_USB_IMX21_HCD is not set --# CONFIG_USB_HCD_BCMA is not set --# CONFIG_USB_HCD_SSB is not set --# CONFIG_USB_HCD_TEST_MODE is not set -- --# --# USB Device Class drivers --# --CONFIG_USB_ACM=m --CONFIG_USB_PRINTER=m --CONFIG_USB_WDM=m --# CONFIG_USB_TMC is not set -- --# --# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may --# -- --# --# also be needed; see USB_STORAGE Help for more info --# --CONFIG_USB_STORAGE=y --# CONFIG_USB_STORAGE_DEBUG is not set --CONFIG_USB_STORAGE_REALTEK=y --CONFIG_REALTEK_AUTOPM=y --CONFIG_USB_STORAGE_DATAFAB=y --CONFIG_USB_STORAGE_FREECOM=y --CONFIG_USB_STORAGE_ISD200=y --CONFIG_USB_STORAGE_USBAT=y --CONFIG_USB_STORAGE_SDDR09=y --CONFIG_USB_STORAGE_SDDR55=y --CONFIG_USB_STORAGE_JUMPSHOT=y --CONFIG_USB_STORAGE_ALAUDA=y --CONFIG_USB_STORAGE_ONETOUCH=y --CONFIG_USB_STORAGE_KARMA=m --CONFIG_USB_STORAGE_CYPRESS_ATACB=y --CONFIG_USB_STORAGE_ENE_UB6250=y --CONFIG_USB_UAS=y -- --# --# USB Imaging devices --# --# CONFIG_USB_MDC800 is not set --# CONFIG_USB_MICROTEK is not set --CONFIG_USBIP_CORE=m --CONFIG_USBIP_VHCI_HCD=m --CONFIG_USBIP_HOST=m --# CONFIG_USBIP_DEBUG is not set --CONFIG_USB_MUSB_HDRC=m --CONFIG_USB_MUSB_HOST=y --# CONFIG_USB_MUSB_GADGET is not set --# CONFIG_USB_MUSB_DUAL_ROLE is not set -- --# --# Platform Glue Layer --# -- --# --# MUSB DMA mode --# --CONFIG_MUSB_PIO_ONLY=y --CONFIG_USB_DWC3=m --# CONFIG_USB_DWC3_HOST is not set --# CONFIG_USB_DWC3_GADGET is not set --CONFIG_USB_DWC3_DUAL_ROLE=y -- --# --# Platform Glue Driver Support --# --CONFIG_USB_DWC3_PCI=m --CONFIG_USB_DWC2=m --# CONFIG_USB_DWC2_HOST is not set -- --# --# Gadget/Dual-role mode requires USB Gadget support to be enabled --# --# CONFIG_USB_DWC2_PERIPHERAL is not set --CONFIG_USB_DWC2_DUAL_ROLE=y --CONFIG_USB_DWC2_PCI=m --# CONFIG_USB_DWC2_DEBUG is not set --# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set --CONFIG_USB_CHIPIDEA=y --CONFIG_USB_CHIPIDEA_OF=y --CONFIG_USB_CHIPIDEA_PCI=y --# CONFIG_USB_CHIPIDEA_UDC is not set --CONFIG_USB_CHIPIDEA_HOST=y --# CONFIG_USB_CHIPIDEA_DEBUG is not set --# CONFIG_USB_ISP1760 is not set -- --# --# USB port drivers --# --CONFIG_USB_SERIAL=y --CONFIG_USB_SERIAL_CONSOLE=y --CONFIG_USB_SERIAL_GENERIC=y --CONFIG_USB_SERIAL_SIMPLE=m --CONFIG_USB_SERIAL_AIRCABLE=m --CONFIG_USB_SERIAL_ARK3116=m --CONFIG_USB_SERIAL_BELKIN=m --CONFIG_USB_SERIAL_CH341=m --CONFIG_USB_SERIAL_WHITEHEAT=m --CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m --CONFIG_USB_SERIAL_CP210X=m --CONFIG_USB_SERIAL_CYPRESS_M8=m --CONFIG_USB_SERIAL_EMPEG=m --CONFIG_USB_SERIAL_FTDI_SIO=m --CONFIG_USB_SERIAL_VISOR=m --CONFIG_USB_SERIAL_IPAQ=m --CONFIG_USB_SERIAL_IR=m --CONFIG_USB_SERIAL_EDGEPORT=m --CONFIG_USB_SERIAL_EDGEPORT_TI=m --CONFIG_USB_SERIAL_F81232=m --CONFIG_USB_SERIAL_GARMIN=m --CONFIG_USB_SERIAL_IPW=m --CONFIG_USB_SERIAL_IUU=m --CONFIG_USB_SERIAL_KEYSPAN_PDA=m --CONFIG_USB_SERIAL_KEYSPAN=m --CONFIG_USB_SERIAL_KEYSPAN_MPR=y --CONFIG_USB_SERIAL_KEYSPAN_USA28=y --CONFIG_USB_SERIAL_KEYSPAN_USA28X=y --CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y --CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y --CONFIG_USB_SERIAL_KEYSPAN_USA19=y --CONFIG_USB_SERIAL_KEYSPAN_USA18X=y --CONFIG_USB_SERIAL_KEYSPAN_USA19W=y --CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y --CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y --CONFIG_USB_SERIAL_KEYSPAN_USA49W=y --CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y --CONFIG_USB_SERIAL_KLSI=m --CONFIG_USB_SERIAL_KOBIL_SCT=m --CONFIG_USB_SERIAL_MCT_U232=m --CONFIG_USB_SERIAL_METRO=m --CONFIG_USB_SERIAL_MOS7720=m --CONFIG_USB_SERIAL_MOS7840=m --CONFIG_USB_SERIAL_MXUPORT=m --CONFIG_USB_SERIAL_NAVMAN=m --CONFIG_USB_SERIAL_PL2303=m --CONFIG_USB_SERIAL_OTI6858=m --CONFIG_USB_SERIAL_QCAUX=m --CONFIG_USB_SERIAL_QUALCOMM=m --CONFIG_USB_SERIAL_SPCP8X5=m --CONFIG_USB_SERIAL_SAFE=m --CONFIG_USB_SERIAL_SAFE_PADDED=y --CONFIG_USB_SERIAL_SIERRAWIRELESS=m --CONFIG_USB_SERIAL_SYMBOL=m --CONFIG_USB_SERIAL_TI=m --CONFIG_USB_SERIAL_CYBERJACK=m --CONFIG_USB_SERIAL_XIRCOM=m --CONFIG_USB_SERIAL_WWAN=m --CONFIG_USB_SERIAL_OPTION=m --CONFIG_USB_SERIAL_OMNINET=m --CONFIG_USB_SERIAL_OPTICON=m --CONFIG_USB_SERIAL_XSENS_MT=m --CONFIG_USB_SERIAL_WISHBONE=m --CONFIG_USB_SERIAL_SSU100=m --CONFIG_USB_SERIAL_QT2=m --CONFIG_USB_SERIAL_DEBUG=m -- --# --# USB Miscellaneous drivers --# --CONFIG_USB_EMI62=m --CONFIG_USB_EMI26=m --# CONFIG_USB_ADUTUX is not set --CONFIG_USB_SEVSEG=m --CONFIG_USB_RIO500=m --CONFIG_USB_LEGOTOWER=m --CONFIG_USB_LCD=m --CONFIG_USB_LED=m --CONFIG_USB_CYPRESS_CY7C63=m --CONFIG_USB_CYTHERM=m --CONFIG_USB_IDMOUSE=m --# CONFIG_USB_FTDI_ELAN is not set --CONFIG_USB_APPLEDISPLAY=m --CONFIG_USB_SISUSBVGA=m --CONFIG_USB_SISUSBVGA_CON=y --CONFIG_USB_LD=m --CONFIG_USB_TRANCEVIBRATOR=m --CONFIG_USB_IOWARRIOR=m --# CONFIG_USB_TEST is not set --# CONFIG_USB_EHSET_TEST_FIXTURE is not set --CONFIG_USB_ISIGHTFW=m --# CONFIG_USB_YUREX is not set --CONFIG_USB_EZUSB_FX2=m --CONFIG_USB_HSIC_USB3503=m --# CONFIG_USB_LINK_LAYER_TEST is not set --# CONFIG_USB_CHAOSKEY is not set -- --# --# USB Physical Layer drivers --# --CONFIG_USB_PHY=y --CONFIG_NOP_USB_XCEIV=y --CONFIG_AM335X_CONTROL_USB=y --CONFIG_AM335X_PHY_USB=y --CONFIG_USB_GPIO_VBUS=y --CONFIG_USB_ISP1301=y --CONFIG_USB_MXS_PHY=y --CONFIG_USB_ULPI=y --CONFIG_USB_ULPI_VIEWPORT=y --CONFIG_USB_GADGET=y --# CONFIG_USB_GADGET_DEBUG is not set --# CONFIG_USB_GADGET_DEBUG_FILES is not set --# CONFIG_USB_GADGET_DEBUG_FS is not set --CONFIG_USB_GADGET_VBUS_DRAW=2 --CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -- --# --# USB Peripheral Controller --# --CONFIG_USB_FSL_USB2=m --# CONFIG_USB_FUSB300 is not set --# CONFIG_USB_FOTG210_UDC is not set --# CONFIG_USB_GR_UDC is not set --# CONFIG_USB_R8A66597 is not set --# CONFIG_USB_PXA27X is not set --# CONFIG_USB_MV_UDC is not set --# CONFIG_USB_MV_U3D is not set --# CONFIG_USB_M66592 is not set --# CONFIG_USB_BDC_UDC is not set --# CONFIG_USB_AMD5536UDC is not set --# CONFIG_USB_NET2272 is not set --# CONFIG_USB_NET2280 is not set --# CONFIG_USB_GOKU is not set --# CONFIG_USB_EG20T is not set --# CONFIG_USB_GADGET_XILINX is not set --# CONFIG_USB_DUMMY_HCD is not set --CONFIG_USB_LIBCOMPOSITE=m --CONFIG_USB_F_ACM=m --CONFIG_USB_F_SS_LB=m --CONFIG_USB_U_SERIAL=m --CONFIG_USB_U_ETHER=m --CONFIG_USB_F_SERIAL=m --CONFIG_USB_F_OBEX=m --CONFIG_USB_F_NCM=m --CONFIG_USB_F_ECM=m --CONFIG_USB_F_EEM=m --CONFIG_USB_F_SUBSET=m --CONFIG_USB_F_RNDIS=m --CONFIG_USB_F_MASS_STORAGE=m --CONFIG_USB_F_FS=m --CONFIG_USB_F_UAC1=m --CONFIG_USB_F_UAC2=m --CONFIG_USB_F_UVC=m --CONFIG_USB_F_MIDI=m --CONFIG_USB_F_HID=m --CONFIG_USB_F_PRINTER=m --CONFIG_USB_CONFIGFS=m --CONFIG_USB_CONFIGFS_SERIAL=y --CONFIG_USB_CONFIGFS_ACM=y --CONFIG_USB_CONFIGFS_OBEX=y --CONFIG_USB_CONFIGFS_NCM=y --CONFIG_USB_CONFIGFS_ECM=y --CONFIG_USB_CONFIGFS_ECM_SUBSET=y --CONFIG_USB_CONFIGFS_RNDIS=y --CONFIG_USB_CONFIGFS_EEM=y --CONFIG_USB_CONFIGFS_MASS_STORAGE=y --CONFIG_USB_CONFIGFS_F_LB_SS=y --CONFIG_USB_CONFIGFS_F_FS=y --CONFIG_USB_CONFIGFS_F_UAC1=y --CONFIG_USB_CONFIGFS_F_UAC2=y --CONFIG_USB_CONFIGFS_F_MIDI=y --CONFIG_USB_CONFIGFS_F_HID=y --CONFIG_USB_CONFIGFS_F_UVC=y --CONFIG_USB_CONFIGFS_F_PRINTER=y --CONFIG_USB_ZERO=m --# CONFIG_USB_ZERO_HNPTEST is not set --CONFIG_USB_AUDIO=m --# CONFIG_GADGET_UAC1 is not set --CONFIG_USB_ETH=m --CONFIG_USB_ETH_RNDIS=y --# CONFIG_USB_ETH_EEM is not set --CONFIG_USB_G_NCM=m --CONFIG_USB_GADGETFS=m --CONFIG_USB_FUNCTIONFS=m --# CONFIG_USB_FUNCTIONFS_ETH is not set --# CONFIG_USB_FUNCTIONFS_RNDIS is not set --CONFIG_USB_FUNCTIONFS_GENERIC=y --CONFIG_USB_MASS_STORAGE=m --CONFIG_USB_G_SERIAL=m --CONFIG_USB_MIDI_GADGET=m --CONFIG_USB_G_PRINTER=m --CONFIG_USB_CDC_COMPOSITE=m --CONFIG_USB_G_ACM_MS=m --CONFIG_USB_G_MULTI=m --CONFIG_USB_G_MULTI_RNDIS=y --# CONFIG_USB_G_MULTI_CDC is not set --CONFIG_USB_G_HID=m --# CONFIG_USB_G_DBGP is not set --CONFIG_USB_G_WEBCAM=m --CONFIG_USB_LED_TRIG=y --# CONFIG_UWB is not set --CONFIG_MMC=y --# CONFIG_MMC_DEBUG is not set -- --# --# MMC/SD/SDIO Card Drivers --# --CONFIG_MMC_BLOCK=y --CONFIG_MMC_BLOCK_MINORS=8 --CONFIG_MMC_BLOCK_BOUNCE=y --CONFIG_SDIO_UART=y --# CONFIG_MMC_TEST is not set -- --# --# MMC/SD/SDIO Host Controller Drivers --# --CONFIG_MMC_SDHCI=y --CONFIG_MMC_SDHCI_IO_ACCESSORS=y --# CONFIG_MMC_SDHCI_PCI is not set --CONFIG_MMC_SDHCI_PLTFM=y --CONFIG_MMC_SDHCI_OF_ARASAN=m --# CONFIG_MMC_SDHCI_OF_AT91 is not set --# CONFIG_MMC_SDHCI_OF_ESDHC is not set --CONFIG_MMC_SDHCI_ESDHC_IMX=y --# CONFIG_MMC_SDHCI_F_SDH30 is not set --# CONFIG_MMC_MXC is not set --CONFIG_MMC_TIFM_SD=m --CONFIG_MMC_CB710=m --# CONFIG_MMC_VIA_SDMMC is not set --# CONFIG_MMC_DW is not set --CONFIG_MMC_VUB300=m --CONFIG_MMC_USHC=y --CONFIG_MMC_USDHI6ROL0=m --CONFIG_MMC_TOSHIBA_PCI=m --# CONFIG_MMC_MTK is not set --# CONFIG_MEMSTICK is not set --CONFIG_NEW_LEDS=y --CONFIG_LEDS_CLASS=y --# CONFIG_LEDS_CLASS_FLASH is not set -- --# --# LED drivers --# --# CONFIG_LEDS_BCM6328 is not set --# CONFIG_LEDS_BCM6358 is not set --# CONFIG_LEDS_LM3530 is not set --# CONFIG_LEDS_LM3642 is not set --# CONFIG_LEDS_PCA9532 is not set --CONFIG_LEDS_GPIO=m --# CONFIG_LEDS_LP3944 is not set --# CONFIG_LEDS_LP5521 is not set --# CONFIG_LEDS_LP5523 is not set --# CONFIG_LEDS_LP5562 is not set --# CONFIG_LEDS_LP8501 is not set --# CONFIG_LEDS_LP8860 is not set --# CONFIG_LEDS_PCA955X is not set --# CONFIG_LEDS_PCA963X is not set --# CONFIG_LEDS_DA9052 is not set --# CONFIG_LEDS_DAC124S085 is not set --CONFIG_LEDS_PWM=y --CONFIG_LEDS_REGULATOR=m --# CONFIG_LEDS_BD2802 is not set --# CONFIG_LEDS_LT3593 is not set --# CONFIG_LEDS_MC13783 is not set --# CONFIG_LEDS_TCA6507 is not set --# CONFIG_LEDS_TLC591XX is not set --# CONFIG_LEDS_LM355x is not set -- --# --# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) --# --# CONFIG_LEDS_BLINKM is not set --# CONFIG_LEDS_SYSCON is not set -- --# --# LED Triggers --# --CONFIG_LEDS_TRIGGERS=y --CONFIG_LEDS_TRIGGER_TIMER=m --CONFIG_LEDS_TRIGGER_ONESHOT=m --CONFIG_LEDS_TRIGGER_HEARTBEAT=y --CONFIG_LEDS_TRIGGER_BACKLIGHT=m --CONFIG_LEDS_TRIGGER_CPU=y --CONFIG_LEDS_TRIGGER_GPIO=m --CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -- --# --# iptables trigger is under Netfilter config (LED target) --# --CONFIG_LEDS_TRIGGER_TRANSIENT=m --CONFIG_LEDS_TRIGGER_CAMERA=m --# CONFIG_ACCESSIBILITY is not set --# CONFIG_INFINIBAND is not set --CONFIG_EDAC_ATOMIC_SCRUB=y --CONFIG_EDAC_SUPPORT=y --# CONFIG_EDAC is not set --CONFIG_RTC_LIB=y --CONFIG_RTC_CLASS=y --CONFIG_RTC_HCTOSYS=y --CONFIG_RTC_HCTOSYS_DEVICE="rtc0" --# CONFIG_RTC_SYSTOHC is not set --# CONFIG_RTC_DEBUG is not set -- --# --# RTC interfaces --# --CONFIG_RTC_INTF_SYSFS=y --CONFIG_RTC_INTF_PROC=y --CONFIG_RTC_INTF_DEV=y --CONFIG_RTC_INTF_DEV_UIE_EMUL=y --# CONFIG_RTC_DRV_TEST is not set -- --# --# I2C RTC drivers --# --# CONFIG_RTC_DRV_ABB5ZES3 is not set --# CONFIG_RTC_DRV_ABX80X is not set --# CONFIG_RTC_DRV_DS1307 is not set --# CONFIG_RTC_DRV_DS1374 is not set --# CONFIG_RTC_DRV_DS1672 is not set --# CONFIG_RTC_DRV_DS3232 is not set --# CONFIG_RTC_DRV_HYM8563 is not set --# CONFIG_RTC_DRV_MAX6900 is not set --# CONFIG_RTC_DRV_RS5C372 is not set --# CONFIG_RTC_DRV_ISL1208 is not set --# CONFIG_RTC_DRV_ISL12022 is not set --# CONFIG_RTC_DRV_ISL12057 is not set --# CONFIG_RTC_DRV_X1205 is not set --# CONFIG_RTC_DRV_PCF2127 is not set --CONFIG_RTC_DRV_PCF8523=y --# CONFIG_RTC_DRV_PCF8563 is not set --# CONFIG_RTC_DRV_PCF85063 is not set --# CONFIG_RTC_DRV_PCF8583 is not set --# CONFIG_RTC_DRV_M41T80 is not set --# CONFIG_RTC_DRV_BQ32K is not set --# CONFIG_RTC_DRV_S35390A is not set --# CONFIG_RTC_DRV_FM3130 is not set --# CONFIG_RTC_DRV_RX8581 is not set --# CONFIG_RTC_DRV_RX8025 is not set --# CONFIG_RTC_DRV_EM3027 is not set --# CONFIG_RTC_DRV_RV3029C2 is not set --# CONFIG_RTC_DRV_RV8803 is not set -- --# --# SPI RTC drivers --# --# CONFIG_RTC_DRV_M41T93 is not set --# CONFIG_RTC_DRV_M41T94 is not set --# CONFIG_RTC_DRV_DS1305 is not set --# CONFIG_RTC_DRV_DS1343 is not set --# CONFIG_RTC_DRV_DS1347 is not set --# CONFIG_RTC_DRV_DS1390 is not set --# CONFIG_RTC_DRV_MAX6902 is not set --# CONFIG_RTC_DRV_R9701 is not set --# CONFIG_RTC_DRV_RS5C348 is not set --# CONFIG_RTC_DRV_DS3234 is not set --# CONFIG_RTC_DRV_PCF2123 is not set --# CONFIG_RTC_DRV_RX4581 is not set --# CONFIG_RTC_DRV_MCP795 is not set -- --# --# Platform RTC drivers --# --CONFIG_RTC_DRV_CMOS=y --# CONFIG_RTC_DRV_DS1286 is not set --# CONFIG_RTC_DRV_DS1511 is not set --# CONFIG_RTC_DRV_DS1553 is not set --# CONFIG_RTC_DRV_DS1685_FAMILY is not set --# CONFIG_RTC_DRV_DS1742 is not set --# CONFIG_RTC_DRV_DS2404 is not set --# CONFIG_RTC_DRV_DA9052 is not set --# CONFIG_RTC_DRV_STK17TA8 is not set --# CONFIG_RTC_DRV_M48T86 is not set --# CONFIG_RTC_DRV_M48T35 is not set --# CONFIG_RTC_DRV_M48T59 is not set --# CONFIG_RTC_DRV_MSM6242 is not set --# CONFIG_RTC_DRV_BQ4802 is not set --# CONFIG_RTC_DRV_RP5C01 is not set --# CONFIG_RTC_DRV_V3020 is not set --# CONFIG_RTC_DRV_ZYNQMP is not set -- --# --# on-CPU RTC drivers --# --CONFIG_RTC_DRV_IMXDI=y --CONFIG_RTC_DRV_MC13XXX=y --CONFIG_RTC_DRV_MXC=y --CONFIG_RTC_DRV_SNVS=y -- --# --# HID Sensor RTC drivers --# --# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set --CONFIG_DMADEVICES=y --# CONFIG_DMADEVICES_DEBUG is not set -- --# --# DMA Devices --# --CONFIG_DMA_ENGINE=y --CONFIG_DMA_VIRTUAL_CHANNELS=m --CONFIG_DMA_OF=y --CONFIG_FSL_EDMA=m --# CONFIG_IMX_DMA is not set --CONFIG_IMX_SDMA=y --# CONFIG_INTEL_IDMA64 is not set --CONFIG_MXS_DMA=y --# CONFIG_MX3_IPU is not set --CONFIG_MXC_PXP_V2=y --CONFIG_MXC_PXP_CLIENT_DEVICE=y --# CONFIG_NBPFAXI_DMA is not set --CONFIG_DW_DMAC_CORE=m --CONFIG_DW_DMAC=m --CONFIG_DW_DMAC_PCI=m -- --# --# DMA Clients --# --CONFIG_ASYNC_TX_DMA=y --# CONFIG_DMATEST is not set --# CONFIG_AUXDISPLAY is not set --# CONFIG_UIO is not set --# CONFIG_VIRT_DRIVERS is not set -- --# --# Virtio drivers --# --# CONFIG_VIRTIO_PCI is not set --# CONFIG_VIRTIO_MMIO is not set -- --# --# Microsoft Hyper-V guest support --# --CONFIG_STAGING=y --CONFIG_PRISM2_USB=m --CONFIG_COMEDI=m --# CONFIG_COMEDI_DEBUG is not set --CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB=2048 --CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB=20480 --# CONFIG_COMEDI_MISC_DRIVERS is not set --# CONFIG_COMEDI_ISA_DRIVERS is not set --# CONFIG_COMEDI_PCI_DRIVERS is not set --# CONFIG_COMEDI_USB_DRIVERS is not set --# CONFIG_COMEDI_8255_SA is not set --# CONFIG_COMEDI_KCOMEDILIB is not set --CONFIG_RTL8192U=m --CONFIG_RTLLIB=m --CONFIG_RTLLIB_CRYPTO_CCMP=m --CONFIG_RTLLIB_CRYPTO_TKIP=m --CONFIG_RTLLIB_CRYPTO_WEP=m --CONFIG_RTL8192E=m --CONFIG_R8712U=m --CONFIG_R8188EU=m --CONFIG_88EU_AP_MODE=y --CONFIG_R8723AU=m --CONFIG_8723AU_AP_MODE=y --CONFIG_8723AU_BT_COEXIST=y --CONFIG_RTS5208=m --# CONFIG_VT6655 is not set --# CONFIG_VT6656 is not set -- --# --# IIO staging drivers --# -- --# --# Accelerometers --# --# CONFIG_ADIS16201 is not set --# CONFIG_ADIS16203 is not set --# CONFIG_ADIS16204 is not set --# CONFIG_ADIS16209 is not set --# CONFIG_ADIS16220 is not set --# CONFIG_ADIS16240 is not set --# CONFIG_LIS3L02DQ is not set --# CONFIG_SCA3000 is not set -- --# --# Analog to digital converters --# --# CONFIG_AD7606 is not set --# CONFIG_AD7780 is not set --# CONFIG_AD7816 is not set --# CONFIG_AD7192 is not set --# CONFIG_AD7280 is not set -- --# --# Analog digital bi-direction converters --# --# CONFIG_ADT7316 is not set -- --# --# Capacitance to digital converters --# --# CONFIG_AD7150 is not set --# CONFIG_AD7152 is not set --# CONFIG_AD7746 is not set -- --# --# Direct Digital Synthesis --# --# CONFIG_AD9832 is not set --# CONFIG_AD9834 is not set -- --# --# Digital gyroscope sensors --# --# CONFIG_ADIS16060 is not set -- --# --# Network Analyzer, Impedance Converters --# --# CONFIG_AD5933 is not set -- --# --# Light sensors --# --# CONFIG_SENSORS_ISL29018 is not set --# CONFIG_SENSORS_ISL29028 is not set --# CONFIG_TSL2583 is not set --# CONFIG_TSL2x7x is not set -- --# --# Magnetometer sensors --# --# CONFIG_SENSORS_HMC5843_I2C is not set --# CONFIG_SENSORS_HMC5843_SPI is not set -- --# --# Active energy metering IC --# --# CONFIG_ADE7753 is not set --# CONFIG_ADE7754 is not set --# CONFIG_ADE7758 is not set --# CONFIG_ADE7759 is not set --# CONFIG_ADE7854 is not set -- --# --# Resolver to digital converters --# --# CONFIG_AD2S90 is not set --# CONFIG_AD2S1200 is not set --# CONFIG_AD2S1210 is not set -- --# --# Triggers - standalone --# --CONFIG_IIO_PERIODIC_RTC_TRIGGER=m --# CONFIG_IIO_SIMPLE_DUMMY is not set --# CONFIG_FB_SM750 is not set --# CONFIG_FB_XGI is not set -- --# --# Speakup console speech --# --CONFIG_SPEAKUP=m --CONFIG_SPEAKUP_SYNTH_ACNTSA=m --CONFIG_SPEAKUP_SYNTH_APOLLO=m --CONFIG_SPEAKUP_SYNTH_AUDPTR=m --CONFIG_SPEAKUP_SYNTH_BNS=m --CONFIG_SPEAKUP_SYNTH_DECTLK=m --CONFIG_SPEAKUP_SYNTH_DECEXT=m --CONFIG_SPEAKUP_SYNTH_LTLK=m --CONFIG_SPEAKUP_SYNTH_SOFT=m --CONFIG_SPEAKUP_SYNTH_SPKOUT=m --CONFIG_SPEAKUP_SYNTH_TXPRT=m --CONFIG_SPEAKUP_SYNTH_DUMMY=m --CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m --CONFIG_STAGING_MEDIA=y --CONFIG_I2C_BCM2048=m --CONFIG_DVB_CXD2099=m --CONFIG_DVB_MN88472=m --CONFIG_DVB_MN88473=m --CONFIG_LIRC_STAGING=y --CONFIG_LIRC_BT829=m --CONFIG_LIRC_IMON=m --CONFIG_LIRC_SASEM=m --CONFIG_LIRC_SERIAL=m --CONFIG_LIRC_SERIAL_TRANSMITTER=y --CONFIG_LIRC_SIR=m --CONFIG_LIRC_ZILOG=m -- --# --# Android --# --# CONFIG_STAGING_BOARD is not set --CONFIG_WIMAX_GDM72XX=m --CONFIG_WIMAX_GDM72XX_QOS=y --CONFIG_WIMAX_GDM72XX_K_MODE=y --CONFIG_WIMAX_GDM72XX_WIMAX2=y --CONFIG_WIMAX_GDM72XX_USB=y --# CONFIG_WIMAX_GDM72XX_SDIO is not set --CONFIG_WIMAX_GDM72XX_USB_PM=y --CONFIG_LTE_GDM724X=m --CONFIG_MTD_SPINAND_MT29F=m --# CONFIG_MTD_SPINAND_ONDIEECC is not set --# CONFIG_LUSTRE_FS is not set --CONFIG_DGNC=m --CONFIG_DGAP=m --# CONFIG_GS_FPGABOOT is not set --# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set --CONFIG_FB_TFT=m --CONFIG_FB_TFT_AGM1264K_FL=m --CONFIG_FB_TFT_BD663474=m --CONFIG_FB_TFT_HX8340BN=m --CONFIG_FB_TFT_HX8347D=m --CONFIG_FB_TFT_HX8353D=m --CONFIG_FB_TFT_HX8357D=m --CONFIG_FB_TFT_ILI9163=m --CONFIG_FB_TFT_ILI9320=m --CONFIG_FB_TFT_ILI9325=m --CONFIG_FB_TFT_ILI9340=m --CONFIG_FB_TFT_ILI9341=m --CONFIG_FB_TFT_ILI9481=m --CONFIG_FB_TFT_ILI9486=m --CONFIG_FB_TFT_PCD8544=m --CONFIG_FB_TFT_RA8875=m --CONFIG_FB_TFT_S6D02A1=m --CONFIG_FB_TFT_S6D1121=m --CONFIG_FB_TFT_SSD1289=m --CONFIG_FB_TFT_SSD1306=m --CONFIG_FB_TFT_SSD1331=m --CONFIG_FB_TFT_SSD1351=m --CONFIG_FB_TFT_ST7735R=m --# CONFIG_FB_TFT_ST7789V is not set --CONFIG_FB_TFT_TINYLCD=m --CONFIG_FB_TFT_TLS8204=m --CONFIG_FB_TFT_UC1611=m --CONFIG_FB_TFT_UC1701=m --CONFIG_FB_TFT_UPD161704=m --CONFIG_FB_TFT_WATTEROTT=m --CONFIG_FB_FLEX=m --CONFIG_FB_TFT_FBTFT_DEVICE=m --# CONFIG_WILC1000_DRIVER is not set --# CONFIG_MOST is not set --# CONFIG_CHROME_PLATFORMS is not set --CONFIG_CLKDEV_LOOKUP=y --CONFIG_HAVE_CLK_PREPARE=y --CONFIG_COMMON_CLK=y -- --# --# Common Clock Framework --# --# CONFIG_COMMON_CLK_SI5351 is not set --# CONFIG_COMMON_CLK_SI514 is not set --# CONFIG_COMMON_CLK_SI570 is not set --# CONFIG_COMMON_CLK_CDCE925 is not set --# CONFIG_CLK_QORIQ is not set --# CONFIG_COMMON_CLK_PWM is not set --# CONFIG_COMMON_CLK_PXA is not set --# CONFIG_COMMON_CLK_CDCE706 is not set -- --# --# Hardware Spinlock drivers --# -- --# --# Clock Source drivers --# --CONFIG_CLKSRC_OF=y --CONFIG_CLKSRC_PROBE=y --CONFIG_CLKSRC_MMIO=y --# CONFIG_ARM_TIMER_SP804 is not set --# CONFIG_ATMEL_PIT is not set --# CONFIG_SH_TIMER_CMT is not set --# CONFIG_SH_TIMER_MTU2 is not set --# CONFIG_SH_TIMER_TMU is not set --# CONFIG_EM_TIMER_STI is not set --CONFIG_CLKSRC_IMX_GPT=y --# CONFIG_MAILBOX is not set --CONFIG_IOMMU_SUPPORT=y -- --# --# Generic IOMMU Pagetable Support --# --# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set --# CONFIG_ARM_SMMU is not set -- --# --# Remoteproc drivers --# --# CONFIG_STE_MODEM_RPROC is not set -- --# --# Rpmsg drivers --# -- --# --# SOC (System On Chip) specific Drivers --# --# CONFIG_SOC_BRCMSTB is not set --# CONFIG_SUNXI_SRAM is not set --# CONFIG_SOC_TI is not set --CONFIG_PM_DEVFREQ=y -- --# --# DEVFREQ Governors --# --CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y --CONFIG_DEVFREQ_GOV_PERFORMANCE=y --CONFIG_DEVFREQ_GOV_POWERSAVE=y --CONFIG_DEVFREQ_GOV_USERSPACE=y -- --# --# DEVFREQ Drivers --# --CONFIG_PM_DEVFREQ_EVENT=y --CONFIG_EXTCON=y -- --# --# Extcon Device Drivers --# --CONFIG_EXTCON_ADC_JACK=m --CONFIG_EXTCON_GPIO=y --CONFIG_EXTCON_RT8973A=m --CONFIG_EXTCON_SM5502=m --CONFIG_EXTCON_USB_GPIO=y --# CONFIG_MEMORY is not set --CONFIG_IIO=m --CONFIG_IIO_BUFFER=y --# CONFIG_IIO_BUFFER_CB is not set --CONFIG_IIO_KFIFO_BUF=m --CONFIG_IIO_TRIGGERED_BUFFER=m --CONFIG_IIO_TRIGGER=y --CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 -- --# --# Accelerometers --# --# CONFIG_BMA180 is not set --# CONFIG_BMC150_ACCEL is not set --# CONFIG_HID_SENSOR_ACCEL_3D is not set --# CONFIG_IIO_ST_ACCEL_3AXIS is not set --# CONFIG_KXSD9 is not set --# CONFIG_KXCJK1013 is not set --# CONFIG_MMA8452 is not set --# CONFIG_MMA9551 is not set --# CONFIG_MMA9553 is not set --# CONFIG_MXC4005 is not set --# CONFIG_STK8312 is not set --# CONFIG_STK8BA50 is not set -- --# --# Analog to digital converters --# --# CONFIG_AD7266 is not set --# CONFIG_AD7291 is not set --# CONFIG_AD7298 is not set --# CONFIG_AD7476 is not set --# CONFIG_AD7791 is not set --# CONFIG_AD7793 is not set --# CONFIG_AD7887 is not set --# CONFIG_AD7923 is not set --# CONFIG_AD799X is not set --# CONFIG_CC10001_ADC is not set --# CONFIG_HI8435 is not set --# CONFIG_MAX1027 is not set --# CONFIG_MAX1363 is not set --# CONFIG_MCP320X is not set --# CONFIG_MCP3422 is not set --# CONFIG_NAU7802 is not set --# CONFIG_TI_ADC081C is not set --# CONFIG_TI_ADC128S052 is not set --# CONFIG_VF610_ADC is not set -- --# --# Amplifiers --# --# CONFIG_AD8366 is not set -- --# --# Chemical Sensors --# --# CONFIG_VZ89X is not set -- --# --# Hid Sensor IIO Common --# --CONFIG_HID_SENSOR_IIO_COMMON=m --CONFIG_HID_SENSOR_IIO_TRIGGER=m -- --# --# SSP Sensor Common --# --# CONFIG_IIO_SSP_SENSORHUB is not set -- --# --# Digital to analog converters --# --# CONFIG_AD5064 is not set --# CONFIG_AD5360 is not set --# CONFIG_AD5380 is not set --# CONFIG_AD5421 is not set --# CONFIG_AD5446 is not set --# CONFIG_AD5449 is not set --# CONFIG_AD5504 is not set --# CONFIG_AD5624R_SPI is not set --# CONFIG_AD5686 is not set --# CONFIG_AD5755 is not set --# CONFIG_AD5764 is not set --# CONFIG_AD5791 is not set --# CONFIG_AD7303 is not set --# CONFIG_M62332 is not set --# CONFIG_MAX517 is not set --# CONFIG_MAX5821 is not set --# CONFIG_MCP4725 is not set --# CONFIG_MCP4922 is not set -- --# --# Frequency Synthesizers DDS/PLL --# -- --# --# Clock Generator/Distribution --# --# CONFIG_AD9523 is not set -- --# --# Phase-Locked Loop (PLL) frequency synthesizers --# --# CONFIG_ADF4350 is not set -- --# --# Digital gyroscope sensors --# --# CONFIG_ADIS16080 is not set --# CONFIG_ADIS16130 is not set --# CONFIG_ADIS16136 is not set --# CONFIG_ADIS16260 is not set --# CONFIG_ADXRS450 is not set --# CONFIG_BMG160 is not set --CONFIG_HID_SENSOR_GYRO_3D=m --# CONFIG_IIO_ST_GYRO_3AXIS is not set --# CONFIG_ITG3200 is not set -- --# --# Humidity sensors --# --CONFIG_DHT11=m --# CONFIG_HDC100X is not set --# CONFIG_HTU21 is not set --# CONFIG_SI7005 is not set --# CONFIG_SI7020 is not set -- --# --# Inertial measurement units --# --# CONFIG_ADIS16400 is not set --# CONFIG_ADIS16480 is not set --# CONFIG_KMX61 is not set --# CONFIG_INV_MPU6050_IIO is not set -- --# --# Light sensors --# --# CONFIG_ADJD_S311 is not set --# CONFIG_AL3320A is not set --# CONFIG_APDS9300 is not set --# CONFIG_APDS9960 is not set --# CONFIG_BH1750 is not set --# CONFIG_CM32181 is not set --# CONFIG_CM3232 is not set --# CONFIG_CM3323 is not set --# CONFIG_CM36651 is not set --# CONFIG_GP2AP020A00F is not set --# CONFIG_ISL29125 is not set --# CONFIG_HID_SENSOR_ALS is not set --# CONFIG_HID_SENSOR_PROX is not set --# CONFIG_JSA1212 is not set --# CONFIG_RPR0521 is not set --# CONFIG_LTR501 is not set --# CONFIG_OPT3001 is not set --# CONFIG_PA12203001 is not set --# CONFIG_STK3310 is not set --# CONFIG_TCS3414 is not set --# CONFIG_TCS3472 is not set --# CONFIG_SENSORS_TSL2563 is not set --# CONFIG_TSL4531 is not set --# CONFIG_US5182D is not set --# CONFIG_VCNL4000 is not set -- --# --# Magnetometer sensors --# --# CONFIG_AK8975 is not set --# CONFIG_AK09911 is not set --# CONFIG_BMC150_MAGN is not set --# CONFIG_MAG3110 is not set --# CONFIG_HID_SENSOR_MAGNETOMETER_3D is not set --# CONFIG_MMC35240 is not set --# CONFIG_IIO_ST_MAGN_3AXIS is not set -- --# --# Inclinometer sensors --# --# CONFIG_HID_SENSOR_INCLINOMETER_3D is not set --# CONFIG_HID_SENSOR_DEVICE_ROTATION is not set -- --# --# Triggers - standalone --# --CONFIG_IIO_INTERRUPT_TRIGGER=m --CONFIG_IIO_SYSFS_TRIGGER=m -- --# --# Digital potentiometers --# --# CONFIG_MCP4531 is not set -- --# --# Pressure sensors --# --# CONFIG_BMP280 is not set --# CONFIG_HID_SENSOR_PRESS is not set --# CONFIG_MPL115 is not set --# CONFIG_MPL3115 is not set --# CONFIG_MS5611 is not set --# CONFIG_MS5637 is not set --# CONFIG_IIO_ST_PRESS is not set --# CONFIG_T5403 is not set -- --# --# Lightning sensors --# --# CONFIG_AS3935 is not set -- --# --# Proximity sensors --# --# CONFIG_LIDAR_LITE_V2 is not set --# CONFIG_SX9500 is not set -- --# --# Temperature sensors --# --# CONFIG_MLX90614 is not set --# CONFIG_TMP006 is not set --# CONFIG_TSYS01 is not set --# CONFIG_TSYS02D is not set --# CONFIG_NTB is not set --# CONFIG_VME_BUS is not set --CONFIG_PWM=y --CONFIG_PWM_SYSFS=y --CONFIG_PWM_FSL_FTM=y --CONFIG_PWM_IMX=y --CONFIG_PWM_PCA9685=y --CONFIG_IRQCHIP=y --CONFIG_ARM_GIC=y --# CONFIG_IPACK_BUS is not set --CONFIG_ARCH_HAS_RESET_CONTROLLER=y --CONFIG_RESET_CONTROLLER=y --# CONFIG_FMC is not set -- --# --# PHY Subsystem --# --CONFIG_GENERIC_PHY=y --# CONFIG_PHY_PXA_28NM_HSIC is not set --# CONFIG_PHY_PXA_28NM_USB2 is not set --# CONFIG_BCM_KONA_USB2_PHY is not set --# CONFIG_PHY_SAMSUNG_USB2 is not set --CONFIG_POWERCAP=y --# CONFIG_MCB is not set -- --# --# Performance monitor support --# --CONFIG_ARM_PMU=y --CONFIG_RAS=y --# CONFIG_THUNDERBOLT is not set -- --# --# Android --# --# CONFIG_ANDROID is not set --CONFIG_NVMEM=y --CONFIG_NVMEM_IMX_OCOTP=m --# CONFIG_STM is not set --# CONFIG_STM_DUMMY is not set --# CONFIG_STM_SOURCE_CONSOLE is not set --# CONFIG_INTEL_TH is not set -- --# --# FPGA Configuration Support --# --# CONFIG_FPGA is not set -- --# --# MXC support drivers --# --CONFIG_MXC_IPU=y -- --# --# Vivante GPU support --# --CONFIG_MXC_GPU_VIV=y --CONFIG_MXC_IPU_V3_FSL=y -- --# --# MXC VPU(Video Processing Unit) support --# --CONFIG_MXC_VPU=y --# CONFIG_MXC_VPU_DEBUG is not set --# CONFIG_MX6_VPU_352M is not set -- --# --# MXC HDMI CEC (Consumer Electronics Control) support --# --CONFIG_MXC_HDMI_CEC=y -- --# --# MXC MIPI Support --# --CONFIG_MXC_MIPI_CSI2=y -- --# --# MXC Media Local Bus Driver --# --CONFIG_MXC_MLB=y --CONFIG_MXC_MLB150=m -- --# --# Firmware Drivers --# --CONFIG_FIRMWARE_MEMMAP=y -- --# --# File systems --# --CONFIG_DCACHE_WORD_ACCESS=y --# CONFIG_EXT2_FS is not set --# CONFIG_EXT3_FS is not set --CONFIG_EXT4_FS=y --CONFIG_EXT4_USE_FOR_EXT2=y --CONFIG_EXT4_FS_POSIX_ACL=y --CONFIG_EXT4_FS_SECURITY=y --CONFIG_EXT4_ENCRYPTION=y --CONFIG_EXT4_FS_ENCRYPTION=y --# CONFIG_EXT4_DEBUG is not set --CONFIG_JBD2=y --# CONFIG_JBD2_DEBUG is not set --CONFIG_FS_MBCACHE=y --CONFIG_REISERFS_FS=m --# CONFIG_REISERFS_CHECK is not set --# CONFIG_REISERFS_PROC_INFO is not set --CONFIG_REISERFS_FS_XATTR=y --CONFIG_REISERFS_FS_POSIX_ACL=y --# CONFIG_REISERFS_FS_SECURITY is not set --CONFIG_JFS_FS=m --CONFIG_JFS_POSIX_ACL=y --CONFIG_JFS_SECURITY=y --# CONFIG_JFS_DEBUG is not set --# CONFIG_JFS_STATISTICS is not set --CONFIG_XFS_FS=m --CONFIG_XFS_QUOTA=y --CONFIG_XFS_POSIX_ACL=y --# CONFIG_XFS_RT is not set --# CONFIG_XFS_WARN is not set --# CONFIG_XFS_DEBUG is not set --# CONFIG_GFS2_FS is not set --# CONFIG_OCFS2_FS is not set --CONFIG_BTRFS_FS=y --CONFIG_BTRFS_FS_POSIX_ACL=y --# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set --# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set --# CONFIG_BTRFS_DEBUG is not set --# CONFIG_BTRFS_ASSERT is not set --# CONFIG_NILFS2_FS is not set --CONFIG_F2FS_FS=m --CONFIG_F2FS_STAT_FS=y --CONFIG_F2FS_FS_XATTR=y --CONFIG_F2FS_FS_POSIX_ACL=y --# CONFIG_F2FS_FS_SECURITY is not set --# CONFIG_F2FS_CHECK_FS is not set --# CONFIG_F2FS_FS_ENCRYPTION is not set --# CONFIG_F2FS_IO_TRACE is not set --CONFIG_FS_POSIX_ACL=y --CONFIG_EXPORTFS=y --CONFIG_FILE_LOCKING=y --CONFIG_FSNOTIFY=y --CONFIG_DNOTIFY=y --CONFIG_INOTIFY_USER=y --CONFIG_FANOTIFY=y --CONFIG_QUOTA=y --# CONFIG_QUOTA_NETLINK_INTERFACE is not set --CONFIG_PRINT_QUOTA_WARNING=y --# CONFIG_QUOTA_DEBUG is not set --CONFIG_QUOTA_TREE=m --CONFIG_QFMT_V1=m --CONFIG_QFMT_V2=m --CONFIG_QUOTACTL=y --CONFIG_AUTOFS4_FS=y --CONFIG_FUSE_FS=y --CONFIG_CUSE=y --CONFIG_OVERLAY_FS=y -- --# --# Caches --# --CONFIG_FSCACHE=m --# CONFIG_FSCACHE_STATS is not set --# CONFIG_FSCACHE_HISTOGRAM is not set --# CONFIG_FSCACHE_DEBUG is not set --# CONFIG_FSCACHE_OBJECT_LIST is not set --CONFIG_CACHEFILES=m --# CONFIG_CACHEFILES_DEBUG is not set --# CONFIG_CACHEFILES_HISTOGRAM is not set -- --# --# CD-ROM/DVD Filesystems --# --CONFIG_ISO9660_FS=y --CONFIG_JOLIET=y --CONFIG_ZISOFS=y --CONFIG_UDF_FS=y --CONFIG_UDF_NLS=y -- --# --# DOS/FAT/NT Filesystems --# --CONFIG_FAT_FS=y --CONFIG_MSDOS_FS=y --CONFIG_VFAT_FS=y --CONFIG_FAT_DEFAULT_CODEPAGE=437 --CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" --CONFIG_NTFS_FS=m --# CONFIG_NTFS_DEBUG is not set --CONFIG_NTFS_RW=y -- --# --# Pseudo filesystems --# --CONFIG_PROC_FS=y --CONFIG_PROC_SYSCTL=y --CONFIG_PROC_PAGE_MONITOR=y --CONFIG_PROC_CHILDREN=y --CONFIG_KERNFS=y --CONFIG_SYSFS=y --CONFIG_TMPFS=y --CONFIG_TMPFS_POSIX_ACL=y --CONFIG_TMPFS_XATTR=y --# CONFIG_HUGETLB_PAGE is not set --CONFIG_CONFIGFS_FS=y --CONFIG_MISC_FILESYSTEMS=y --# CONFIG_ADFS_FS is not set --# CONFIG_AFFS_FS is not set --# CONFIG_ECRYPT_FS is not set --CONFIG_HFS_FS=m --CONFIG_HFSPLUS_FS=m --# CONFIG_HFSPLUS_FS_POSIX_ACL is not set --# CONFIG_BEFS_FS is not set --# CONFIG_BFS_FS is not set --# CONFIG_EFS_FS is not set --CONFIG_JFFS2_FS=m --CONFIG_JFFS2_FS_DEBUG=0 --CONFIG_JFFS2_FS_WRITEBUFFER=y --# CONFIG_JFFS2_FS_WBUF_VERIFY is not set --# CONFIG_JFFS2_SUMMARY is not set --# CONFIG_JFFS2_FS_XATTR is not set --# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set --CONFIG_JFFS2_ZLIB=y --# CONFIG_JFFS2_LZO is not set --CONFIG_JFFS2_RTIME=y --# CONFIG_JFFS2_RUBIN is not set --CONFIG_UBIFS_FS=m --# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set --CONFIG_UBIFS_FS_LZO=y --CONFIG_UBIFS_FS_ZLIB=y --# CONFIG_UBIFS_ATIME_SUPPORT is not set --CONFIG_LOGFS=m --# CONFIG_CRAMFS is not set --CONFIG_SQUASHFS=m --CONFIG_SQUASHFS_FILE_CACHE=y --# CONFIG_SQUASHFS_FILE_DIRECT is not set --CONFIG_SQUASHFS_DECOMP_SINGLE=y --# CONFIG_SQUASHFS_DECOMP_MULTI is not set --# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set --CONFIG_SQUASHFS_XATTR=y --CONFIG_SQUASHFS_ZLIB=y --# CONFIG_SQUASHFS_LZ4 is not set --# CONFIG_SQUASHFS_LZO is not set --# CONFIG_SQUASHFS_XZ is not set --# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set --# CONFIG_SQUASHFS_EMBEDDED is not set --CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 --# CONFIG_VXFS_FS is not set --# CONFIG_MINIX_FS is not set --# CONFIG_OMFS_FS is not set --# CONFIG_HPFS_FS is not set --# CONFIG_QNX4FS_FS is not set --# CONFIG_QNX6FS_FS is not set --CONFIG_ROMFS_FS=m --CONFIG_ROMFS_BACKED_BY_BLOCK=y --# CONFIG_ROMFS_BACKED_BY_MTD is not set --# CONFIG_ROMFS_BACKED_BY_BOTH is not set --CONFIG_ROMFS_ON_BLOCK=y --# CONFIG_PSTORE is not set --CONFIG_SYSV_FS=m --# CONFIG_UFS_FS is not set --CONFIG_NETWORK_FILESYSTEMS=y --CONFIG_NFS_FS=y --CONFIG_NFS_V2=y --CONFIG_NFS_V3=y --CONFIG_NFS_V3_ACL=y --CONFIG_NFS_V4=y --# CONFIG_NFS_SWAP is not set --CONFIG_NFS_V4_1=y --CONFIG_NFS_V4_2=y --CONFIG_PNFS_FILE_LAYOUT=y --CONFIG_PNFS_BLOCK=m --CONFIG_PNFS_FLEXFILE_LAYOUT=m --CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" --CONFIG_NFS_V4_1_MIGRATION=y --CONFIG_ROOT_NFS=y --# CONFIG_NFS_USE_LEGACY_DNS is not set --CONFIG_NFS_USE_KERNEL_DNS=y --CONFIG_NFS_DEBUG=y --CONFIG_NFSD=m --CONFIG_NFSD_V2_ACL=y --CONFIG_NFSD_V3=y --CONFIG_NFSD_V3_ACL=y --CONFIG_NFSD_V4=y --# CONFIG_NFSD_PNFS is not set --# CONFIG_NFSD_FAULT_INJECTION is not set --CONFIG_GRACE_PERIOD=y --CONFIG_LOCKD=y --CONFIG_LOCKD_V4=y --CONFIG_NFS_ACL_SUPPORT=y --CONFIG_NFS_COMMON=y --CONFIG_SUNRPC=y --CONFIG_SUNRPC_GSS=y --CONFIG_SUNRPC_BACKCHANNEL=y --CONFIG_RPCSEC_GSS_KRB5=m --CONFIG_SUNRPC_DEBUG=y --# CONFIG_CEPH_FS is not set --CONFIG_CIFS=m --# CONFIG_CIFS_STATS is not set --CONFIG_CIFS_WEAK_PW_HASH=y --# CONFIG_CIFS_UPCALL is not set --CONFIG_CIFS_XATTR=y --CONFIG_CIFS_POSIX=y --CONFIG_CIFS_ACL=y --# CONFIG_CIFS_DEBUG is not set --CONFIG_CIFS_DFS_UPCALL=y --CONFIG_CIFS_SMB2=y --CONFIG_CIFS_SMB311=y --CONFIG_CIFS_FSCACHE=y --CONFIG_NCP_FS=m --# CONFIG_NCPFS_PACKET_SIGNING is not set --# CONFIG_NCPFS_IOCTL_LOCKING is not set --# CONFIG_NCPFS_STRONG is not set --# CONFIG_NCPFS_NFS_NS is not set --# CONFIG_NCPFS_OS2_NS is not set --# CONFIG_NCPFS_SMALLDOS is not set --# CONFIG_NCPFS_NLS is not set --# CONFIG_NCPFS_EXTRAS is not set --# CONFIG_CODA_FS is not set --# CONFIG_AFS_FS is not set --CONFIG_NLS=y --CONFIG_NLS_DEFAULT="utf8" --CONFIG_NLS_CODEPAGE_437=y --CONFIG_NLS_CODEPAGE_737=m --CONFIG_NLS_CODEPAGE_775=m --CONFIG_NLS_CODEPAGE_850=y --CONFIG_NLS_CODEPAGE_852=y --CONFIG_NLS_CODEPAGE_855=m --CONFIG_NLS_CODEPAGE_857=m --CONFIG_NLS_CODEPAGE_860=m --CONFIG_NLS_CODEPAGE_861=m --CONFIG_NLS_CODEPAGE_862=m --CONFIG_NLS_CODEPAGE_863=m --CONFIG_NLS_CODEPAGE_864=m --CONFIG_NLS_CODEPAGE_865=m --CONFIG_NLS_CODEPAGE_866=m --CONFIG_NLS_CODEPAGE_869=m --CONFIG_NLS_CODEPAGE_936=m --CONFIG_NLS_CODEPAGE_950=m --CONFIG_NLS_CODEPAGE_932=m --CONFIG_NLS_CODEPAGE_949=m --CONFIG_NLS_CODEPAGE_874=m --CONFIG_NLS_ISO8859_8=m --CONFIG_NLS_CODEPAGE_1250=y --CONFIG_NLS_CODEPAGE_1251=y --CONFIG_NLS_ASCII=y --CONFIG_NLS_ISO8859_1=y --CONFIG_NLS_ISO8859_2=y --CONFIG_NLS_ISO8859_3=m --CONFIG_NLS_ISO8859_4=m --CONFIG_NLS_ISO8859_5=m --CONFIG_NLS_ISO8859_6=m --CONFIG_NLS_ISO8859_7=m --CONFIG_NLS_ISO8859_9=m --CONFIG_NLS_ISO8859_13=m --CONFIG_NLS_ISO8859_14=m --CONFIG_NLS_ISO8859_15=y --CONFIG_NLS_KOI8_R=m --CONFIG_NLS_KOI8_U=m --CONFIG_NLS_MAC_ROMAN=m --CONFIG_NLS_MAC_CELTIC=m --CONFIG_NLS_MAC_CENTEURO=m --CONFIG_NLS_MAC_CROATIAN=m --CONFIG_NLS_MAC_CYRILLIC=m --CONFIG_NLS_MAC_GAELIC=m --CONFIG_NLS_MAC_GREEK=m --CONFIG_NLS_MAC_ICELAND=m --CONFIG_NLS_MAC_INUIT=m --CONFIG_NLS_MAC_ROMANIAN=m --CONFIG_NLS_MAC_TURKISH=m --CONFIG_NLS_UTF8=y --CONFIG_DLM=m --# CONFIG_DLM_DEBUG is not set -- --# --# Kernel hacking --# -- --# --# printk and dmesg options --# --CONFIG_PRINTK_TIME=y --CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 --# CONFIG_BOOT_PRINTK_DELAY is not set --CONFIG_DYNAMIC_DEBUG=y -- --# --# Compile-time checks and compiler options --# --# CONFIG_DEBUG_INFO is not set --CONFIG_ENABLE_WARN_DEPRECATED=y --CONFIG_ENABLE_MUST_CHECK=y --CONFIG_FRAME_WARN=1024 --CONFIG_STRIP_ASM_SYMS=y --# CONFIG_READABLE_ASM is not set --# CONFIG_UNUSED_SYMBOLS is not set --# CONFIG_PAGE_OWNER is not set --CONFIG_DEBUG_FS=y --# CONFIG_HEADERS_CHECK is not set --# CONFIG_DEBUG_SECTION_MISMATCH is not set --CONFIG_SECTION_MISMATCH_WARN_ONLY=y --CONFIG_FRAME_POINTER=y --# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set --CONFIG_MAGIC_SYSRQ=y --CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 --CONFIG_DEBUG_KERNEL=y -- --# --# Memory Debugging --# --# CONFIG_PAGE_EXTENSION is not set --# CONFIG_DEBUG_PAGEALLOC is not set --# CONFIG_DEBUG_OBJECTS is not set --# CONFIG_SLUB_STATS is not set --CONFIG_HAVE_DEBUG_KMEMLEAK=y --# CONFIG_DEBUG_KMEMLEAK is not set --# CONFIG_DEBUG_STACK_USAGE is not set --# CONFIG_DEBUG_VM is not set --# CONFIG_DEBUG_MEMORY_INIT is not set --# CONFIG_DEBUG_PER_CPU_MAPS is not set --# CONFIG_DEBUG_HIGHMEM is not set --# CONFIG_DEBUG_SHIRQ is not set -- --# --# Debug Lockups and Hangs --# --# CONFIG_LOCKUP_DETECTOR is not set --# CONFIG_DETECT_HUNG_TASK is not set --CONFIG_PANIC_ON_OOPS=y --CONFIG_PANIC_ON_OOPS_VALUE=1 --CONFIG_PANIC_TIMEOUT=1 --# CONFIG_SCHED_DEBUG is not set --# CONFIG_SCHED_INFO is not set --# CONFIG_SCHEDSTATS is not set --# CONFIG_SCHED_STACK_END_CHECK is not set --# CONFIG_DEBUG_TIMEKEEPING is not set --CONFIG_TIMER_STATS=y --# CONFIG_DEBUG_PREEMPT is not set -- --# --# Lock Debugging (spinlocks, mutexes, etc...) --# --# CONFIG_DEBUG_RT_MUTEXES is not set --# CONFIG_DEBUG_SPINLOCK is not set --# CONFIG_DEBUG_MUTEXES is not set --# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set --# CONFIG_DEBUG_LOCK_ALLOC is not set --# CONFIG_PROVE_LOCKING is not set --# CONFIG_LOCK_STAT is not set --# CONFIG_DEBUG_ATOMIC_SLEEP is not set --# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set --# CONFIG_LOCK_TORTURE_TEST is not set --CONFIG_STACKTRACE=y --# CONFIG_DEBUG_KOBJECT is not set --# CONFIG_DEBUG_BUGVERBOSE is not set --# CONFIG_DEBUG_LIST is not set --# CONFIG_DEBUG_PI_LIST is not set --# CONFIG_DEBUG_SG is not set --# CONFIG_DEBUG_NOTIFIERS is not set --# CONFIG_DEBUG_CREDENTIALS is not set -- --# --# RCU Debugging --# --# CONFIG_PROVE_RCU is not set --# CONFIG_SPARSE_RCU_POINTER is not set --# CONFIG_TORTURE_TEST is not set --# CONFIG_RCU_TORTURE_TEST is not set --CONFIG_RCU_CPU_STALL_TIMEOUT=21 --# CONFIG_RCU_TRACE is not set --# CONFIG_RCU_EQS_DEBUG is not set --# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set --# CONFIG_NOTIFIER_ERROR_INJECTION is not set --# CONFIG_FAULT_INJECTION is not set --CONFIG_NOP_TRACER=y --CONFIG_HAVE_FUNCTION_TRACER=y --CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y --CONFIG_HAVE_DYNAMIC_FTRACE=y --CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y --CONFIG_HAVE_SYSCALL_TRACEPOINTS=y --CONFIG_HAVE_C_RECORDMCOUNT=y --CONFIG_TRACE_CLOCK=y --CONFIG_RING_BUFFER=y --CONFIG_EVENT_TRACING=y --CONFIG_CONTEXT_SWITCH_TRACER=y --CONFIG_TRACING=y --CONFIG_GENERIC_TRACER=y --CONFIG_TRACING_SUPPORT=y --CONFIG_FTRACE=y --CONFIG_FUNCTION_TRACER=y --CONFIG_FUNCTION_GRAPH_TRACER=y --# CONFIG_IRQSOFF_TRACER is not set --# CONFIG_PREEMPT_TRACER is not set --# CONFIG_SCHED_TRACER is not set --# CONFIG_MISSED_TIMER_OFFSETS_HIST is not set --# CONFIG_FTRACE_SYSCALLS is not set --# CONFIG_TRACER_SNAPSHOT is not set --CONFIG_BRANCH_PROFILE_NONE=y --# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set --# CONFIG_PROFILE_ALL_BRANCHES is not set --# CONFIG_STACK_TRACER is not set --# CONFIG_BLK_DEV_IO_TRACE is not set --# CONFIG_UPROBE_EVENT is not set --# CONFIG_PROBE_EVENTS is not set --CONFIG_DYNAMIC_FTRACE=y --# CONFIG_FUNCTION_PROFILER is not set --CONFIG_FTRACE_MCOUNT_RECORD=y --# CONFIG_FTRACE_STARTUP_TEST is not set --# CONFIG_TRACEPOINT_BENCHMARK is not set --# CONFIG_RING_BUFFER_BENCHMARK is not set --# CONFIG_RING_BUFFER_STARTUP_TEST is not set --# CONFIG_TRACE_ENUM_MAP_FILE is not set --# CONFIG_TRACING_EVENTS_GPIO is not set -- --# --# Runtime Testing --# --# CONFIG_LKDTM is not set --# CONFIG_TEST_LIST_SORT is not set --# CONFIG_BACKTRACE_SELF_TEST is not set --# CONFIG_RBTREE_TEST is not set --# CONFIG_INTERVAL_TREE_TEST is not set --# CONFIG_PERCPU_TEST is not set --# CONFIG_ATOMIC64_SELFTEST is not set --# CONFIG_ASYNC_RAID6_TEST is not set --# CONFIG_TEST_HEXDUMP is not set --# CONFIG_TEST_STRING_HELPERS is not set --# CONFIG_TEST_KSTRTOX is not set --# CONFIG_TEST_PRINTF is not set --# CONFIG_TEST_RHASHTABLE is not set --# CONFIG_DMA_API_DEBUG is not set --# CONFIG_TEST_LKM is not set --# CONFIG_TEST_USER_COPY is not set --# CONFIG_TEST_BPF is not set --# CONFIG_TEST_FIRMWARE is not set --# CONFIG_TEST_UDELAY is not set --# CONFIG_MEMTEST is not set --# CONFIG_TEST_STATIC_KEYS is not set --# CONFIG_SAMPLES is not set --CONFIG_HAVE_ARCH_KGDB=y --# CONFIG_KGDB is not set --# CONFIG_ARM_PTDUMP is not set --# CONFIG_STRICT_DEVMEM is not set --CONFIG_ARM_UNWIND=y --CONFIG_OLD_MCOUNT=y --# CONFIG_DEBUG_USER is not set --# CONFIG_DEBUG_LL is not set --CONFIG_DEBUG_IMX_UART_PORT=1 --CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" --# CONFIG_DEBUG_UART_8250 is not set --# CONFIG_DEBUG_UART_BCM63XX is not set --CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" --# CONFIG_PID_IN_CONTEXTIDR is not set --# CONFIG_DEBUG_SET_MODULE_RONX is not set --# CONFIG_CORESIGHT is not set -- --# --# Security options --# --CONFIG_KEYS=y --# CONFIG_PERSISTENT_KEYRINGS is not set --# CONFIG_BIG_KEYS is not set --CONFIG_ENCRYPTED_KEYS=y --# CONFIG_SECURITY_DMESG_RESTRICT is not set --# CONFIG_SECURITY is not set --# CONFIG_SECURITYFS is not set --CONFIG_DEFAULT_SECURITY_DAC=y --CONFIG_DEFAULT_SECURITY="" --CONFIG_XOR_BLOCKS=y --CONFIG_ASYNC_CORE=m --CONFIG_ASYNC_MEMCPY=m --CONFIG_ASYNC_XOR=m --CONFIG_ASYNC_PQ=m --CONFIG_ASYNC_RAID6_RECOV=m --CONFIG_CRYPTO=y -- --# --# Crypto core or helper --# --CONFIG_CRYPTO_ALGAPI=y --CONFIG_CRYPTO_ALGAPI2=y --CONFIG_CRYPTO_AEAD=y --CONFIG_CRYPTO_AEAD2=y --CONFIG_CRYPTO_BLKCIPHER=y --CONFIG_CRYPTO_BLKCIPHER2=y --CONFIG_CRYPTO_HASH=y --CONFIG_CRYPTO_HASH2=y --CONFIG_CRYPTO_RNG=y --CONFIG_CRYPTO_RNG2=y --CONFIG_CRYPTO_RNG_DEFAULT=y --CONFIG_CRYPTO_PCOMP=y --CONFIG_CRYPTO_PCOMP2=y --CONFIG_CRYPTO_AKCIPHER2=y --CONFIG_CRYPTO_AKCIPHER=m --CONFIG_CRYPTO_RSA=m --CONFIG_CRYPTO_CRYPTODEV=y --CONFIG_CRYPTO_MANAGER=y --CONFIG_CRYPTO_MANAGER2=y --CONFIG_CRYPTO_USER=y --CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y --CONFIG_CRYPTO_GF128MUL=y --CONFIG_CRYPTO_NULL=y --CONFIG_CRYPTO_NULL2=y --CONFIG_CRYPTO_PCRYPT=y --CONFIG_CRYPTO_WORKQUEUE=y --CONFIG_CRYPTO_CRYPTD=y --CONFIG_CRYPTO_MCRYPTD=m --CONFIG_CRYPTO_AUTHENC=y --# CONFIG_CRYPTO_TEST is not set --CONFIG_CRYPTO_ABLK_HELPER=m -- --# --# Authenticated Encryption with Associated Data --# --CONFIG_CRYPTO_CCM=y --CONFIG_CRYPTO_GCM=y --CONFIG_CRYPTO_CHACHA20POLY1305=m --CONFIG_CRYPTO_SEQIV=y --CONFIG_CRYPTO_ECHAINIV=m -- --# --# Block modes --# --CONFIG_CRYPTO_CBC=y --CONFIG_CRYPTO_CTR=y --CONFIG_CRYPTO_CTS=y --CONFIG_CRYPTO_ECB=y --CONFIG_CRYPTO_LRW=y --CONFIG_CRYPTO_PCBC=y --CONFIG_CRYPTO_XTS=y --CONFIG_CRYPTO_KEYWRAP=m -- --# --# Hash modes --# --CONFIG_CRYPTO_CMAC=y --CONFIG_CRYPTO_HMAC=y --CONFIG_CRYPTO_XCBC=y --CONFIG_CRYPTO_VMAC=y -- --# --# Digest --# --CONFIG_CRYPTO_CRC32C=y --CONFIG_CRYPTO_CRC32=y --CONFIG_CRYPTO_CRCT10DIF=y --CONFIG_CRYPTO_GHASH=y --CONFIG_CRYPTO_POLY1305=m --CONFIG_CRYPTO_MD4=y --CONFIG_CRYPTO_MD5=y --CONFIG_CRYPTO_MICHAEL_MIC=y --CONFIG_CRYPTO_RMD128=m --CONFIG_CRYPTO_RMD160=m --CONFIG_CRYPTO_RMD256=m --CONFIG_CRYPTO_RMD320=m --CONFIG_CRYPTO_SHA1=y --CONFIG_CRYPTO_SHA256=y --CONFIG_CRYPTO_SHA512=y --CONFIG_CRYPTO_TGR192=m --CONFIG_CRYPTO_WP512=m -- --# --# Ciphers --# --CONFIG_CRYPTO_AES=y --CONFIG_CRYPTO_ANUBIS=m --CONFIG_CRYPTO_ARC4=y --CONFIG_CRYPTO_BLOWFISH=m --CONFIG_CRYPTO_BLOWFISH_COMMON=m --CONFIG_CRYPTO_CAMELLIA=m --CONFIG_CRYPTO_CAST_COMMON=m --CONFIG_CRYPTO_CAST5=m --CONFIG_CRYPTO_CAST6=m --CONFIG_CRYPTO_DES=y --CONFIG_CRYPTO_FCRYPT=m --CONFIG_CRYPTO_KHAZAD=m --CONFIG_CRYPTO_SALSA20=m --CONFIG_CRYPTO_CHACHA20=m --CONFIG_CRYPTO_SEED=m --CONFIG_CRYPTO_SERPENT=m --CONFIG_CRYPTO_TEA=y --CONFIG_CRYPTO_TWOFISH=y --CONFIG_CRYPTO_TWOFISH_COMMON=y -- --# --# Compression --# --CONFIG_CRYPTO_DEFLATE=y --CONFIG_CRYPTO_ZLIB=y --CONFIG_CRYPTO_LZO=y --CONFIG_CRYPTO_842=y --CONFIG_CRYPTO_LZ4=y --CONFIG_CRYPTO_LZ4HC=y -- --# --# Random Number Generation --# --CONFIG_CRYPTO_ANSI_CPRNG=y --CONFIG_CRYPTO_DRBG_MENU=y --CONFIG_CRYPTO_DRBG_HMAC=y --# CONFIG_CRYPTO_DRBG_HASH is not set --# CONFIG_CRYPTO_DRBG_CTR is not set --CONFIG_CRYPTO_DRBG=y --CONFIG_CRYPTO_JITTERENTROPY=y --CONFIG_CRYPTO_USER_API=m --CONFIG_CRYPTO_USER_API_HASH=m --CONFIG_CRYPTO_USER_API_SKCIPHER=m --CONFIG_CRYPTO_USER_API_RNG=m --# CONFIG_CRYPTO_USER_API_AEAD is not set --CONFIG_CRYPTO_HASH_INFO=y --CONFIG_CRYPTO_HW=y --# CONFIG_CRYPTO_DEV_HIFN_795X is not set --CONFIG_CRYPTO_DEV_FSL_CAAM=y --CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y --CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 --# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set --CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y --CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y --CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y --CONFIG_CRYPTO_DEV_FSL_CAAM_IMX=y --CONFIG_CRYPTO_DEV_FSL_CAAM_LE=y --# CONFIG_CRYPTO_DEV_FSL_CAAM_SM is not set --# CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO is not set --# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set --# CONFIG_CRYPTO_DEV_SAHARA is not set --# CONFIG_CRYPTO_DEV_MXS_DCP is not set --CONFIG_ASYMMETRIC_KEY_TYPE=m --CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m --CONFIG_PUBLIC_KEY_ALGO_RSA=m --CONFIG_X509_CERTIFICATE_PARSER=m --CONFIG_PKCS7_MESSAGE_PARSER=m --CONFIG_PKCS7_TEST_KEY=m -- --# --# Certificates for signature checking --# --CONFIG_SYSTEM_TRUSTED_KEYRING=y --CONFIG_SYSTEM_TRUSTED_KEYS="" --CONFIG_ARM_CRYPTO=y --CONFIG_CRYPTO_SHA1_ARM=m --CONFIG_CRYPTO_SHA1_ARM_NEON=m --CONFIG_CRYPTO_SHA1_ARM_CE=m --CONFIG_CRYPTO_SHA2_ARM_CE=m --CONFIG_CRYPTO_SHA256_ARM=y --CONFIG_CRYPTO_SHA512_ARM=m --CONFIG_CRYPTO_AES_ARM=m --CONFIG_CRYPTO_AES_ARM_BS=m --CONFIG_CRYPTO_AES_ARM_CE=m --CONFIG_CRYPTO_GHASH_ARM_CE=m --CONFIG_BINARY_PRINTF=y -- --# --# Library routines --# --CONFIG_RAID6_PQ=y --CONFIG_BITREVERSE=y --CONFIG_HAVE_ARCH_BITREVERSE=y --CONFIG_RATIONAL=y --CONFIG_GENERIC_STRNCPY_FROM_USER=y --CONFIG_GENERIC_STRNLEN_USER=y --CONFIG_GENERIC_NET_UTILS=y --CONFIG_GENERIC_PCI_IOMAP=y --CONFIG_GENERIC_IO=y --CONFIG_STMP_DEVICE=y --CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y --CONFIG_CRC_CCITT=y --CONFIG_CRC16=y --CONFIG_CRC_T10DIF=y --CONFIG_CRC_ITU_T=y --CONFIG_CRC32=y --# CONFIG_CRC32_SELFTEST is not set --CONFIG_CRC32_SLICEBY8=y --# CONFIG_CRC32_SLICEBY4 is not set --# CONFIG_CRC32_SARWATE is not set --# CONFIG_CRC32_BIT is not set --CONFIG_CRC7=y --CONFIG_LIBCRC32C=y --CONFIG_CRC8=m --# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set --# CONFIG_RANDOM32_SELFTEST is not set --CONFIG_842_COMPRESS=y --CONFIG_842_DECOMPRESS=y --CONFIG_ZLIB_INFLATE=y --CONFIG_ZLIB_DEFLATE=y --CONFIG_LZO_COMPRESS=y --CONFIG_LZO_DECOMPRESS=y --CONFIG_LZ4_COMPRESS=y --CONFIG_LZ4HC_COMPRESS=y --CONFIG_LZ4_DECOMPRESS=y --CONFIG_XZ_DEC=m --# CONFIG_XZ_DEC_X86 is not set --# CONFIG_XZ_DEC_POWERPC is not set --# CONFIG_XZ_DEC_IA64 is not set --CONFIG_XZ_DEC_ARM=y --CONFIG_XZ_DEC_ARMTHUMB=y --# CONFIG_XZ_DEC_SPARC is not set --CONFIG_XZ_DEC_BCJ=y --# CONFIG_XZ_DEC_TEST is not set --CONFIG_DECOMPRESS_GZIP=y --CONFIG_DECOMPRESS_LZO=y --CONFIG_GENERIC_ALLOCATOR=y --CONFIG_TEXTSEARCH=y --CONFIG_TEXTSEARCH_KMP=m --CONFIG_TEXTSEARCH_BM=m --CONFIG_TEXTSEARCH_FSM=m --CONFIG_BTREE=y --CONFIG_ASSOCIATIVE_ARRAY=y --CONFIG_HAS_IOMEM=y --CONFIG_HAS_IOPORT_MAP=y --CONFIG_HAS_DMA=y --CONFIG_CPU_RMAP=y --CONFIG_DQL=y --CONFIG_GLOB=y --# CONFIG_GLOB_SELFTEST is not set --CONFIG_NLATTR=y --CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y --CONFIG_CLZ_TAB=y --CONFIG_CORDIC=y --# CONFIG_DDR is not set --CONFIG_MPILIB=m --CONFIG_LIBFDT=y --CONFIG_OID_REGISTRY=y --CONFIG_FONT_SUPPORT=y --# CONFIG_FONTS is not set --CONFIG_FONT_8x8=y --CONFIG_FONT_8x16=y --# CONFIG_SG_SPLIT is not set --CONFIG_ARCH_HAS_SG_CHAIN=y --# CONFIG_VIRTUALIZATION is not set -diff --git a/arch/arm/configs/xbian_defconfig_imx6_mvebu b/arch/arm/configs/xbian_defconfig_imx6_mvebu -index 2bc59d8..83cda36 100644 ---- a/arch/arm/configs/xbian_defconfig_imx6_mvebu -+++ b/arch/arm/configs/xbian_defconfig_imx6_mvebu -@@ -1,6 +1,6 @@ - # - # Automatically generated file; DO NOT EDIT. --# Linux/arm 4.4.1 Kernel Configuration -+# Linux/arm 4.4.6 Kernel Configuration - # - CONFIG_ARM=y - CONFIG_ARM_HAS_SG_CHAIN=y -@@ -83,7 +83,7 @@ CONFIG_NO_HZ_COMMON=y - # CONFIG_HZ_PERIODIC is not set - CONFIG_NO_HZ_IDLE=y - # CONFIG_NO_HZ_FULL is not set --CONFIG_NO_HZ=y -+# CONFIG_NO_HZ is not set - CONFIG_HIGH_RES_TIMERS=y - - # -@@ -104,12 +104,12 @@ CONFIG_RCU_EXPERT=y - CONFIG_SRCU=y - # CONFIG_TASKS_RCU is not set - CONFIG_RCU_STALL_COMMON=y --CONFIG_RCU_FANOUT=16 --CONFIG_RCU_FANOUT_LEAF=8 -+CONFIG_RCU_FANOUT=8 -+CONFIG_RCU_FANOUT_LEAF=2 - # CONFIG_TREE_RCU_TRACE is not set - CONFIG_RCU_BOOST=y - CONFIG_RCU_KTHREAD_PRIO=1 --CONFIG_RCU_BOOST_DELAY=500 -+CONFIG_RCU_BOOST_DELAY=300 - CONFIG_RCU_NOCB_CPU=y - CONFIG_RCU_NOCB_CPU_NONE=y - # CONFIG_RCU_NOCB_CPU_ZERO is not set -@@ -166,7 +166,6 @@ CONFIG_MULTIUSER=y - CONFIG_SYSFS_SYSCALL=y - CONFIG_SYSCTL_SYSCALL=y - CONFIG_KALLSYMS=y --CONFIG_KALLSYMS_ALL=y - CONFIG_PRINTK=y - CONFIG_BUG=y - CONFIG_BASE_FULL=y -@@ -178,7 +177,7 @@ CONFIG_EVENTFD=y - # CONFIG_BPF_SYSCALL is not set - CONFIG_SHMEM=y - CONFIG_AIO=y --# CONFIG_ADVISE_SYSCALLS is not set -+CONFIG_ADVISE_SYSCALLS=y - CONFIG_USERFAULTFD=y - CONFIG_PCI_QUIRKS=y - CONFIG_MEMBARRIER=y -@@ -190,7 +189,6 @@ CONFIG_PERF_USE_VMALLOC=y - # Kernel Performance Events And Counters - # - CONFIG_PERF_EVENTS=y --# CONFIG_DEBUG_PERF_USE_VMALLOC is not set - # CONFIG_VM_EVENT_COUNTERS is not set - # CONFIG_SLUB_DEBUG is not set - CONFIG_COMPAT_BRK=y -@@ -248,8 +246,8 @@ CONFIG_MODULES=y - # CONFIG_MODULE_FORCE_LOAD is not set - CONFIG_MODULE_UNLOAD=y - # CONFIG_MODULE_FORCE_UNLOAD is not set --CONFIG_MODVERSIONS=y --CONFIG_MODULE_SRCVERSION_ALL=y -+# CONFIG_MODVERSIONS is not set -+# CONFIG_MODULE_SRCVERSION_ALL is not set - # CONFIG_MODULE_SIG is not set - # CONFIG_MODULE_COMPRESS is not set - CONFIG_MODULES_TREE_LOOKUP=y -@@ -490,7 +488,6 @@ CONFIG_PCI_DOMAINS=y - CONFIG_PCI_DOMAINS_GENERIC=y - CONFIG_PCI_SYSCALL=y - CONFIG_PCI_MSI=y --# CONFIG_PCI_DEBUG is not set - CONFIG_PCI_REALLOC_ENABLE_AUTO=y - CONFIG_PCI_STUB=y - CONFIG_PCI_ATS=y -@@ -587,14 +584,12 @@ CONFIG_MIGRATION=y - CONFIG_ZONE_DMA_FLAG=1 - CONFIG_BOUNCE=y - # CONFIG_KSM is not set --CONFIG_DEFAULT_MMAP_MIN_ADDR=16384 --CONFIG_CLEANCACHE=y --CONFIG_FRONTSWAP=y -+CONFIG_DEFAULT_MMAP_MIN_ADDR=8192 -+# CONFIG_CLEANCACHE is not set -+# CONFIG_FRONTSWAP is not set - CONFIG_CMA=y --# CONFIG_CMA_DEBUG is not set - # CONFIG_CMA_DEBUGFS is not set - CONFIG_CMA_AREAS=7 --# CONFIG_ZSWAP is not set - # CONFIG_ZPOOL is not set - # CONFIG_ZBUD is not set - # CONFIG_ZSMALLOC is not set -@@ -699,14 +694,18 @@ CONFIG_BINFMT_MISC=m - CONFIG_SUSPEND=y - CONFIG_SUSPEND_FREEZER=y - # CONFIG_SUSPEND_SKIP_SYNC is not set --# CONFIG_HIBERNATION is not set -+CONFIG_HIBERNATE_CALLBACKS=y -+CONFIG_HIBERNATION=y -+CONFIG_PM_STD_PARTITION="" - CONFIG_PM_SLEEP=y - CONFIG_PM_SLEEP_SMP=y - # CONFIG_PM_AUTOSLEEP is not set --# CONFIG_PM_WAKELOCKS is not set -+CONFIG_PM_WAKELOCKS=y -+CONFIG_PM_WAKELOCKS_LIMIT=100 -+CONFIG_PM_WAKELOCKS_GC=y - CONFIG_PM=y - # CONFIG_PM_DEBUG is not set --# CONFIG_APM_EMULATION is not set -+CONFIG_APM_EMULATION=y - CONFIG_PM_OPP=y - CONFIG_PM_CLK=y - CONFIG_PM_GENERIC_DOMAINS=y -@@ -777,7 +776,7 @@ CONFIG_INET_UDP_DIAG=m - CONFIG_TCP_CONG_ADVANCED=y - CONFIG_TCP_CONG_BIC=m - CONFIG_TCP_CONG_CUBIC=m --CONFIG_TCP_CONG_WESTWOOD=m -+CONFIG_TCP_CONG_WESTWOOD=y - CONFIG_TCP_CONG_HTCP=m - CONFIG_TCP_CONG_HSTCP=m - CONFIG_TCP_CONG_HYBLA=m -@@ -789,9 +788,10 @@ CONFIG_TCP_CONG_YEAH=y - CONFIG_TCP_CONG_ILLINOIS=m - CONFIG_TCP_CONG_DCTCP=m - # CONFIG_TCP_CONG_CDG is not set --CONFIG_DEFAULT_VEGAS=y -+# CONFIG_DEFAULT_VEGAS is not set -+CONFIG_DEFAULT_WESTWOOD=y - # CONFIG_DEFAULT_RENO is not set --CONFIG_DEFAULT_TCP_CONG="vegas" -+CONFIG_DEFAULT_TCP_CONG="westwood" - CONFIG_TCP_MD5SIG=y - CONFIG_IPV6=m - CONFIG_IPV6_ROUTER_PREF=y -@@ -821,7 +821,7 @@ CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y - CONFIG_IPV6_PIMSM_V2=y - # CONFIG_NETWORK_SECMARK is not set - CONFIG_NET_PTP_CLASSIFY=y --# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -+CONFIG_NETWORK_PHY_TIMESTAMPING=y - CONFIG_NETFILTER=y - # CONFIG_NETFILTER_DEBUG is not set - CONFIG_NETFILTER_ADVANCED=y -@@ -1153,20 +1153,15 @@ CONFIG_INET_DCCP_DIAG=m - CONFIG_IP_DCCP_CCID3=y - # CONFIG_IP_DCCP_CCID3_DEBUG is not set - CONFIG_IP_DCCP_TFRC_LIB=y -- --# --# DCCP Kernel Hacking --# --# CONFIG_IP_DCCP_DEBUG is not set - CONFIG_IP_SCTP=m - # CONFIG_SCTP_DBG_OBJCNT is not set --CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y -+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set - # CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set --# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set --CONFIG_SCTP_COOKIE_HMAC_MD5=y --CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y -+# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set -+# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set - CONFIG_RDS=m --# CONFIG_RDS_TCP is not set -+CONFIG_RDS_TCP=m - # CONFIG_RDS_DEBUG is not set - CONFIG_TIPC=m - CONFIG_TIPC_MEDIA_UDP=y -@@ -1177,6 +1172,8 @@ CONFIG_L2TP_V3=y - CONFIG_L2TP_IP=m - CONFIG_L2TP_ETH=m - CONFIG_STP=m -+CONFIG_GARP=m -+CONFIG_MRP=m - CONFIG_BRIDGE=m - CONFIG_BRIDGE_IGMP_SNOOPING=y - CONFIG_BRIDGE_VLAN_FILTERING=y -@@ -1185,8 +1182,8 @@ CONFIG_NET_DSA=y - CONFIG_NET_DSA_HWMON=y - CONFIG_NET_DSA_TAG_EDSA=y - CONFIG_VLAN_8021Q=m --# CONFIG_VLAN_8021Q_GVRP is not set --# CONFIG_VLAN_8021Q_MVRP is not set -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_VLAN_8021Q_MVRP=y - # CONFIG_DECNET is not set - CONFIG_LLC=m - CONFIG_LLC2=m -@@ -1197,7 +1194,7 @@ CONFIG_IPDDP=m - CONFIG_IPDDP_ENCAP=y - # CONFIG_X25 is not set - # CONFIG_LAPB is not set --# CONFIG_PHONET is not set -+CONFIG_PHONET=m - # CONFIG_6LOWPAN is not set - # CONFIG_IEEE802154 is not set - CONFIG_NET_SCHED=y -@@ -1286,7 +1283,7 @@ CONFIG_NET_MPLS_GSO=m - # CONFIG_MPLS_ROUTING is not set - # CONFIG_HSR is not set - CONFIG_NET_SWITCHDEV=y --# CONFIG_NET_L3_MASTER_DEV is not set -+CONFIG_NET_L3_MASTER_DEV=y - CONFIG_RPS=y - CONFIG_RFS_ACCEL=y - CONFIG_XPS=y -@@ -1403,7 +1400,6 @@ CONFIG_BT_CMTP=m - CONFIG_BT_HIDP=y - CONFIG_BT_HS=y - CONFIG_BT_LE=y --# CONFIG_BT_SELFTEST is not set - # CONFIG_BT_DEBUGFS is not set - - # -@@ -1523,8 +1519,6 @@ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y - CONFIG_WANT_DEV_COREDUMP=y - CONFIG_ALLOW_DEV_COREDUMP=y - CONFIG_DEV_COREDUMP=y --# CONFIG_DEBUG_DRIVER is not set --# CONFIG_DEBUG_DEVRES is not set - # CONFIG_SYS_HYPERVISOR is not set - # CONFIG_GENERIC_CPU_DEVICES is not set - CONFIG_SOC_BUS=y -@@ -2043,9 +2037,9 @@ CONFIG_DM_VERITY=m - # CONFIG_FIREWIRE is not set - # CONFIG_FIREWIRE_NOSY is not set - CONFIG_NETDEVICES=y --CONFIG_MII=y -+CONFIG_MII=m - CONFIG_NET_CORE=y --CONFIG_BONDING=y -+CONFIG_BONDING=m - CONFIG_DUMMY=m - CONFIG_EQUALIZER=m - # CONFIG_NET_FC is not set -@@ -2070,6 +2064,7 @@ CONFIG_TUN=m - CONFIG_VETH=m - # CONFIG_VIRTIO_NET is not set - CONFIG_NLMON=m -+# CONFIG_NET_VRF is not set - # CONFIG_ARCNET is not set - - # -@@ -2096,7 +2091,7 @@ CONFIG_NET_DSA_MV88E6XXX=y - CONFIG_NET_DSA_MV88E6352=y - # CONFIG_NET_DSA_BCM_SF2 is not set - CONFIG_ETHERNET=y --CONFIG_MDIO=y -+CONFIG_MDIO=m - # CONFIG_NET_VENDOR_3COM is not set - # CONFIG_NET_VENDOR_ADAPTEC is not set - # CONFIG_NET_VENDOR_AGERE is not set -@@ -2105,11 +2100,11 @@ CONFIG_MDIO=y - # CONFIG_NET_VENDOR_AMD is not set - # CONFIG_NET_VENDOR_ARC is not set - CONFIG_NET_VENDOR_ATHEROS=y --CONFIG_ATL2=y --CONFIG_ATL1=y --CONFIG_ATL1E=y --CONFIG_ATL1C=y --CONFIG_ALX=y -+CONFIG_ATL2=m -+CONFIG_ATL1=m -+CONFIG_ATL1E=m -+CONFIG_ATL1C=m -+CONFIG_ALX=m - # CONFIG_NET_VENDOR_AURORA is not set - # CONFIG_NET_CADENCE is not set - # CONFIG_NET_VENDOR_BROADCOM is not set -@@ -2129,7 +2124,7 @@ CONFIG_ALX=y - CONFIG_NET_VENDOR_FREESCALE=y - CONFIG_FEC=y - CONFIG_FSL_PQ_MDIO=y --CONFIG_FSL_XGMAC_MDIO=y -+# CONFIG_FSL_XGMAC_MDIO is not set - CONFIG_GIANFAR=y - # CONFIG_NET_VENDOR_HISILICON is not set - # CONFIG_NET_VENDOR_HP is not set -@@ -2279,6 +2274,7 @@ CONFIG_USB_NET_KALMIA=m - CONFIG_USB_NET_QMI_WWAN=m - CONFIG_USB_HSO=m - CONFIG_USB_NET_INT51X1=m -+# CONFIG_USB_CDC_PHONET is not set - CONFIG_USB_IPHETH=m - CONFIG_USB_SIERRA_NET=m - CONFIG_USB_VL600=m -@@ -2471,24 +2467,9 @@ CONFIG_RT2X00_LIB_LEDS=y - # CONFIG_RT2X00_DEBUG is not set - CONFIG_WL_MEDIATEK=y - CONFIG_MT7601U=m --CONFIG_RTL_CARDS=m --CONFIG_RTL8192CE=m --CONFIG_RTL8192SE=m --CONFIG_RTL8192DE=m --CONFIG_RTL8723AE=m --CONFIG_RTL8723BE=m --CONFIG_RTL8188EE=m --CONFIG_RTL8192EE=m --CONFIG_RTL8821AE=m -+CONFIG_RTL8XXXU=m -+CONFIG_RTL8XXXU_UNTESTED=y - CONFIG_RTL8192CU=m --CONFIG_RTLWIFI=m --CONFIG_RTLWIFI_PCI=m --CONFIG_RTLWIFI_USB=m --CONFIG_RTLWIFI_DEBUG=y --CONFIG_RTL8192C_COMMON=m --CONFIG_RTL8723_COMMON=m --CONFIG_RTLBTCOEXIST=m --# CONFIG_RTL8XXXU is not set - CONFIG_WL_TI=y - CONFIG_WL1251=m - CONFIG_WL1251_SPI=m -@@ -2619,6 +2600,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 - CONFIG_INPUT_JOYDEV=m - CONFIG_INPUT_EVDEV=y - CONFIG_INPUT_EVBUG=m -+# CONFIG_INPUT_APMPOWER is not set - - # - # Input Device Drivers -@@ -3007,7 +2989,6 @@ CONFIG_I2C_SLAVE_EEPROM=m - # CONFIG_I2C_DEBUG_ALGO is not set - # CONFIG_I2C_DEBUG_BUS is not set - CONFIG_SPI=y --# CONFIG_SPI_DEBUG is not set - CONFIG_SPI_MASTER=y - - # -@@ -3016,8 +2997,8 @@ CONFIG_SPI_MASTER=y - # CONFIG_SPI_ALTERA is not set - CONFIG_SPI_BITBANG=y - # CONFIG_SPI_CADENCE is not set --CONFIG_SPI_GPIO=y --CONFIG_SPI_IMX=m -+# CONFIG_SPI_GPIO is not set -+CONFIG_SPI_IMX=y - # CONFIG_SPI_FSL_SPI is not set - # CONFIG_SPI_OC_TINY is not set - CONFIG_SPI_ORION=m -@@ -3043,13 +3024,14 @@ CONFIG_SPI_SPIDEV=y - # - CONFIG_PPS=y - # CONFIG_PPS_DEBUG is not set -+CONFIG_NTP_PPS=y - - # - # PPS clients support - # - # CONFIG_PPS_CLIENT_KTIMER is not set --CONFIG_PPS_CLIENT_LDISC=m --CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_PPS_CLIENT_LDISC=y -+CONFIG_PPS_CLIENT_GPIO=y - - # - # PPS generators support -@@ -3060,10 +3042,7 @@ CONFIG_PPS_CLIENT_GPIO=m - # - CONFIG_PTP_1588_CLOCK=y - CONFIG_PTP_1588_CLOCK_GIANFAR=y -- --# --# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. --# -+# CONFIG_DP83640_PHY is not set - CONFIG_PINCTRL=y - - # -@@ -3072,7 +3051,6 @@ CONFIG_PINCTRL=y - CONFIG_PINMUX=y - CONFIG_PINCONF=y - CONFIG_GENERIC_PINCONF=y --# CONFIG_DEBUG_PINCTRL is not set - # CONFIG_PINCTRL_AMD is not set - CONFIG_PINCTRL_SINGLE=y - CONFIG_PINCTRL_IMX=y -@@ -3087,7 +3065,6 @@ CONFIG_GPIOLIB=y - CONFIG_GPIO_DEVRES=y - CONFIG_OF_GPIO=y - CONFIG_GPIOLIB_IRQCHIP=y --# CONFIG_DEBUG_GPIO is not set - CONFIG_GPIO_SYSFS=y - CONFIG_GPIO_GENERIC=y - -@@ -3101,6 +3078,7 @@ CONFIG_GPIO_74XX_MMIO=y - CONFIG_GPIO_GENERIC_PLATFORM=y - # CONFIG_GPIO_GRGPIO is not set - CONFIG_GPIO_MVEBU=y -+CONFIG_GPIO_MVEBU_PWM=y - CONFIG_GPIO_MXC=y - CONFIG_GPIO_SYSCON=y - # CONFIG_GPIO_VX855 is not set -@@ -3181,6 +3159,7 @@ CONFIG_W1_SLAVE_BQ27000=m - CONFIG_POWER_SUPPLY=y - # CONFIG_POWER_SUPPLY_DEBUG is not set - # CONFIG_PDA_POWER is not set -+# CONFIG_APM_POWER is not set - # CONFIG_GENERIC_ADC_BATTERY is not set - CONFIG_TEST_POWER=m - # CONFIG_BATTERY_88PM860X is not set -@@ -4830,7 +4809,7 @@ CONFIG_USB_XHCI_MVEBU=y - CONFIG_USB_EHCI_HCD=y - CONFIG_USB_EHCI_ROOT_HUB_TT=y - CONFIG_USB_EHCI_TT_NEWSCHED=y --CONFIG_USB_FSL_MPH_DR_OF=m -+CONFIG_USB_FSL_MPH_DR_OF=y - CONFIG_USB_EHCI_PCI=y - CONFIG_USB_EHCI_MXC=y - CONFIG_USB_EHCI_HCD_ORION=y -@@ -5044,7 +5023,6 @@ CONFIG_USB_ISP1301=y - CONFIG_USB_MXS_PHY=y - # CONFIG_USB_ULPI is not set - CONFIG_USB_GADGET=y --# CONFIG_USB_GADGET_DEBUG is not set - # CONFIG_USB_GADGET_DEBUG_FILES is not set - # CONFIG_USB_GADGET_DEBUG_FS is not set - CONFIG_USB_GADGET_VBUS_DRAW=2 -@@ -5053,7 +5031,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 - # - # USB Peripheral Controller - # --CONFIG_USB_FSL_USB2=m -+CONFIG_USB_FSL_USB2=y - # CONFIG_USB_FUSB300 is not set - # CONFIG_USB_FOTG210_UDC is not set - # CONFIG_USB_GR_UDC is not set -@@ -5099,6 +5077,7 @@ CONFIG_USB_CONFIGFS_ECM=y - CONFIG_USB_CONFIGFS_ECM_SUBSET=y - CONFIG_USB_CONFIGFS_RNDIS=y - CONFIG_USB_CONFIGFS_EEM=y -+# CONFIG_USB_CONFIGFS_PHONET is not set - CONFIG_USB_CONFIGFS_MASS_STORAGE=y - CONFIG_USB_CONFIGFS_F_LB_SS=y - CONFIG_USB_CONFIGFS_F_FS=y -@@ -5126,6 +5105,7 @@ CONFIG_USB_G_SERIAL=m - CONFIG_USB_MIDI_GADGET=m - CONFIG_USB_G_PRINTER=m - CONFIG_USB_CDC_COMPOSITE=m -+# CONFIG_USB_G_NOKIA is not set - CONFIG_USB_G_ACM_MS=m - CONFIG_USB_G_MULTI=m - CONFIG_USB_G_MULTI_RNDIS=y -@@ -5531,11 +5511,14 @@ CONFIG_DVB_MN88473=m - CONFIG_LIRC_STAGING=y - CONFIG_LIRC_BT829=m - CONFIG_LIRC_IMON=m -+CONFIG_LIRC_HB=m -+CONFIG_LIRC_XBOX=m - CONFIG_LIRC_SASEM=m - CONFIG_LIRC_SERIAL=m - CONFIG_LIRC_SERIAL_TRANSMITTER=y - CONFIG_LIRC_SIR=m - CONFIG_LIRC_ZILOG=m -+CONFIG_LIRC_ATIUSB=m - - # - # Android -@@ -6177,7 +6160,6 @@ CONFIG_NFSD_V3=y - CONFIG_NFSD_V3_ACL=y - CONFIG_NFSD_V4=y - # CONFIG_NFSD_PNFS is not set --# CONFIG_NFSD_FAULT_INJECTION is not set - CONFIG_GRACE_PERIOD=y - CONFIG_LOCKD=y - CONFIG_LOCKD_V4=y -@@ -6274,83 +6256,47 @@ CONFIG_DLM=m - # - CONFIG_PRINTK_TIME=y - CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 --# CONFIG_BOOT_PRINTK_DELAY is not set - CONFIG_DYNAMIC_DEBUG=y - - # - # Compile-time checks and compiler options - # --# CONFIG_DEBUG_INFO is not set - CONFIG_ENABLE_WARN_DEPRECATED=y - CONFIG_ENABLE_MUST_CHECK=y - CONFIG_FRAME_WARN=1024 - CONFIG_STRIP_ASM_SYMS=y --# CONFIG_READABLE_ASM is not set - # CONFIG_UNUSED_SYMBOLS is not set --# CONFIG_PAGE_OWNER is not set - CONFIG_DEBUG_FS=y - # CONFIG_HEADERS_CHECK is not set - # CONFIG_DEBUG_SECTION_MISMATCH is not set - CONFIG_SECTION_MISMATCH_WARN_ONLY=y - CONFIG_FRAME_POINTER=y --# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set - CONFIG_MAGIC_SYSRQ=y - CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 --CONFIG_DEBUG_KERNEL=y -+# CONFIG_DEBUG_KERNEL is not set - - # - # Memory Debugging - # - # CONFIG_PAGE_EXTENSION is not set --# CONFIG_DEBUG_PAGEALLOC is not set --# CONFIG_DEBUG_OBJECTS is not set - # CONFIG_SLUB_STATS is not set - CONFIG_HAVE_DEBUG_KMEMLEAK=y --# CONFIG_DEBUG_KMEMLEAK is not set --# CONFIG_DEBUG_STACK_USAGE is not set --# CONFIG_DEBUG_VM is not set - # CONFIG_DEBUG_MEMORY_INIT is not set --# CONFIG_DEBUG_PER_CPU_MAPS is not set --# CONFIG_DEBUG_HIGHMEM is not set --# CONFIG_DEBUG_SHIRQ is not set - - # - # Debug Lockups and Hangs - # --# CONFIG_LOCKUP_DETECTOR is not set --# CONFIG_DETECT_HUNG_TASK is not set - CONFIG_PANIC_ON_OOPS=y - CONFIG_PANIC_ON_OOPS_VALUE=1 - CONFIG_PANIC_TIMEOUT=1 --# CONFIG_SCHED_DEBUG is not set - # CONFIG_SCHED_INFO is not set --# CONFIG_SCHEDSTATS is not set --# CONFIG_SCHED_STACK_END_CHECK is not set - # CONFIG_DEBUG_TIMEKEEPING is not set --CONFIG_TIMER_STATS=y --# CONFIG_DEBUG_PREEMPT is not set - - # - # Lock Debugging (spinlocks, mutexes, etc...) - # --# CONFIG_DEBUG_RT_MUTEXES is not set --# CONFIG_DEBUG_SPINLOCK is not set --# CONFIG_DEBUG_MUTEXES is not set --# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set --# CONFIG_DEBUG_LOCK_ALLOC is not set --# CONFIG_PROVE_LOCKING is not set --# CONFIG_LOCK_STAT is not set --# CONFIG_DEBUG_ATOMIC_SLEEP is not set --# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set --# CONFIG_LOCK_TORTURE_TEST is not set - CONFIG_STACKTRACE=y --# CONFIG_DEBUG_KOBJECT is not set --# CONFIG_DEBUG_BUGVERBOSE is not set --# CONFIG_DEBUG_LIST is not set --# CONFIG_DEBUG_PI_LIST is not set --# CONFIG_DEBUG_SG is not set --# CONFIG_DEBUG_NOTIFIERS is not set --# CONFIG_DEBUG_CREDENTIALS is not set -+CONFIG_DEBUG_BUGVERBOSE=y - - # - # RCU Debugging -@@ -6358,13 +6304,7 @@ CONFIG_STACKTRACE=y - # CONFIG_PROVE_RCU is not set - # CONFIG_SPARSE_RCU_POINTER is not set - # CONFIG_TORTURE_TEST is not set --# CONFIG_RCU_TORTURE_TEST is not set - CONFIG_RCU_CPU_STALL_TIMEOUT=21 --# CONFIG_RCU_TRACE is not set --# CONFIG_RCU_EQS_DEBUG is not set --# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set --# CONFIG_NOTIFIER_ERROR_INJECTION is not set --# CONFIG_FAULT_INJECTION is not set - CONFIG_NOP_TRACER=y - CONFIG_HAVE_FUNCTION_TRACER=y - CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -@@ -6409,11 +6349,6 @@ CONFIG_FTRACE_MCOUNT_RECORD=y - # Runtime Testing - # - # CONFIG_LKDTM is not set --# CONFIG_TEST_LIST_SORT is not set --# CONFIG_BACKTRACE_SELF_TEST is not set --# CONFIG_RBTREE_TEST is not set --# CONFIG_INTERVAL_TREE_TEST is not set --# CONFIG_PERCPU_TEST is not set - # CONFIG_ATOMIC64_SELFTEST is not set - # CONFIG_ASYNC_RAID6_TEST is not set - # CONFIG_TEST_HEXDUMP is not set -@@ -6431,17 +6366,13 @@ CONFIG_FTRACE_MCOUNT_RECORD=y - # CONFIG_TEST_STATIC_KEYS is not set - # CONFIG_SAMPLES is not set - CONFIG_HAVE_ARCH_KGDB=y --# CONFIG_KGDB is not set --# CONFIG_ARM_PTDUMP is not set - # CONFIG_STRICT_DEVMEM is not set - CONFIG_ARM_UNWIND=y - CONFIG_OLD_MCOUNT=y - # CONFIG_DEBUG_USER is not set --# CONFIG_DEBUG_LL is not set - CONFIG_DEBUG_IMX_UART_PORT=1 - CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" - # CONFIG_DEBUG_UART_8250 is not set --# CONFIG_DEBUG_UART_BCM63XX is not set - CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" - # CONFIG_PID_IN_CONTEXTIDR is not set - # CONFIG_DEBUG_SET_MODULE_RONX is not set - -From 833b5806b812ad66ada5331c86256c1d43e34505 Mon Sep 17 00:00:00 2001 -From: Troy Kisky -Date: Mon, 8 Jun 2015 09:49:47 -0700 -Subject: [PATCH 11/13] fec: Russell Kings corruption fix - -(cherry picked from commit 43e7d29fd2c0df374a95341146991cc449c016b7) -Signed-off-by: Matus Kral ---- - drivers/net/ethernet/freescale/fec_main.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c -index d9f1ab3..55bab37 100644 ---- a/drivers/net/ethernet/freescale/fec_main.c -+++ b/drivers/net/ethernet/freescale/fec_main.c -@@ -1237,8 +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) - skb = txq->tx_skbuff[index]; - bdnum++; - } -- if (skb_shinfo(skb)->nr_frags && -- (status = bdp_t->cbd_sc) & BD_ENET_TX_READY) -+ if ((status = bdp_t->cbd_sc) & BD_ENET_TX_READY) - break; - - for (i = 0; i < bdnum; i++) { - -From 1a8873f4490146dc03361d30e2d263b823579546 Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Thu, 14 Apr 2016 03:12:49 +0200 -Subject: [PATCH 12/13] sdhci-esdhc-imx: add SDHCI_QUIRK2_TUNING_WORK_AROUND - for imx6q - ---- - drivers/mmc/host/sdhci-esdhc-imx.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c -index 5e23d78..83632d2 100644 ---- a/drivers/mmc/host/sdhci-esdhc-imx.c -+++ b/drivers/mmc/host/sdhci-esdhc-imx.c -@@ -136,6 +136,7 @@ - #define ESDHC_FLAG_HS200 BIT(8) - /* The IP supports HS400 mode */ - #define ESDHC_FLAG_HS400 BIT(9) -+#define ESDHC_FLAG_TUNING_WORK_AROUND BIT(10) - - /* A higher clock ferquency than this rate requires strobell dll control */ - #define ESDHC_STROBE_DLL_CLK_FREQ 100000000 -@@ -161,7 +162,8 @@ static struct esdhc_soc_data esdhc_imx53_data = { - }; - - static struct esdhc_soc_data usdhc_imx6q_data = { -- .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, -+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING -+ | ESDHC_FLAG_TUNING_WORK_AROUND, - }; - - static struct esdhc_soc_data usdhc_imx6sl_data = { -@@ -1020,6 +1022,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, - if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc))) - host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; - -+ if (imx_data->socdata->flags & ESDHC_FLAG_TUNING_WORK_AROUND) -+ host->quirks2 |= SDHCI_QUIRK2_TUNING_WORK_AROUND; -+ - return 0; - } - #else - -From ade5a7b4a7dec8272815ee4253c32427b1e9310c Mon Sep 17 00:00:00 2001 -From: Matus Kral -Date: Thu, 14 Apr 2016 03:14:31 +0200 -Subject: [PATCH 13/13] mxc_hdmi: edit after - 940144cad331dedf7a6f8b38cb28c16a1d11d03f - ---- - drivers/video/mxc/mxc_hdmi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c -index df91138..5cc3c54 100644 ---- a/drivers/video/mxc/mxc_hdmi.c -+++ b/drivers/video/mxc/mxc_hdmi.c -@@ -2296,6 +2296,8 @@ static void mxc_hdmi_set_mode(struct mxc_hdmi *hdmi, int edid_status) - dev_dbg(&hdmi->pdev->dev, "%s: New video mode\n", __func__); - } - -+ hdmi_set_cable_state(1); -+ - console_lock(); - fb_blank(hdmi->fbi, FB_BLANK_UNBLANK); - console_unlock(); -@@ -2311,8 +2313,6 @@ static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) - - dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); - -- hdmi_set_cable_state(1); -- - hdmi->hp_state = HDMI_HOTPLUG_CONNECTED_NO_EDID; - memcpy(edid_old, hdmi->edid, HDMI_EDID_LEN); - diff --git a/projects/imx6/patches/linux/4.4-xbian/linux-000-from-mk01.patch b/projects/imx6/patches/linux/4.4-xbian/linux-000-from-mk01.patch new file mode 100644 index 0000000000..142d111d7e --- /dev/null +++ b/projects/imx6/patches/linux/4.4-xbian/linux-000-from-mk01.patch @@ -0,0 +1,63383 @@ +From 09b4602e20e6792ca1cbad8191a436bec11b0f64 Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Sun, 10 Jul 2016 13:45:21 +0200 +Subject: [PATCH] patch for linux from mk01 + +linux base: linux-4.4-xbian-20160403-d08b62d +linux mk01: + https://github.com/mk01/linux-fslc/tree/imx6-4.4.y b44d3e1999d75af99aa0821b430cb8fe45a6f570 +--- + .../devicetree/bindings/ata/ahci-platform.txt | 4 + + .../devicetree/bindings/clock/imx35-clock.txt | 1 + + .../bindings/pinctrl/img,pistachio-pinctrl.txt | 12 +- + .../devicetree/bindings/sound/fsl,esai.txt | 4 + + .../devicetree/bindings/sound/fsl,spdif.txt | 4 + + .../devicetree/bindings/sound/fsl,ssi.txt | 4 + + Documentation/kernel-parameters.txt | 11 + + Documentation/serial/tty.txt | 3 - + Documentation/sysctl/fs.txt | 23 + + MAINTAINERS | 100 +-- + Makefile | 12 +- + arch/Kconfig | 1 + + arch/arc/include/asm/bitops.h | 15 - + arch/arc/include/asm/io.h | 45 +- + arch/arm/boot/dts/Makefile | 4 + + arch/arm/boot/dts/am43x-epos-evm.dts | 5 + + arch/arm/boot/dts/armada-375.dtsi | 2 +- + arch/arm/boot/dts/armada-385-linksys.dtsi | 2 +- + arch/arm/boot/dts/at91-sama5d3_xplained.dts | 1 + + arch/arm/boot/dts/at91-sama5d4_xplained.dts | 1 + + arch/arm/boot/dts/at91sam9x5.dtsi | 2 +- + arch/arm/boot/dts/exynos4210-trats.dts | 2 + + arch/arm/boot/dts/imx6dl-udoo-15lvds.dts | 63 ++ + arch/arm/boot/dts/imx6dl-udoo-7lvds.dts | 58 ++ + arch/arm/boot/dts/imx6q-tbs2910.dts | 2 +- + arch/arm/boot/dts/imx6q-udoo-15lvds.dts | 67 ++ + arch/arm/boot/dts/imx6q-udoo-7lvds.dts | 62 ++ + arch/arm/boot/dts/imx6qdl-udoo.dtsi | 6 +- + arch/arm/boot/dts/imx6qdl.dtsi | 5 +- + arch/arm/boot/dts/pxa3xx.dtsi | 2 +- + arch/arm/boot/dts/sama5d2-pinfunc.h | 4 +- + arch/arm/configs/xbian_defconfig_imx6_mvebu | 199 ++--- + arch/arm/kernel/entry-armv.S | 6 +- + arch/arm/kernel/ptrace.c | 2 +- + arch/arm/kvm/arm.c | 12 +- + arch/arm/kvm/mmu.c | 17 +- + arch/arm/kvm/psci.c | 4 +- + arch/arm/mach-at91/Kconfig | 1 + + arch/arm/mach-at91/at91rm9200.c | 2 - + arch/arm/mach-at91/at91sam9.c | 2 - + arch/arm/mach-at91/generic.h | 13 +- + arch/arm/mach-at91/pm.c | 70 +- + arch/arm/mach-at91/sama5.c | 2 +- + arch/arm/mach-cns3xxx/pcie.c | 6 +- + arch/arm/mach-exynos/Kconfig | 1 + + arch/arm/mach-exynos/pm_domains.c | 2 +- + arch/arm/mach-imx/Kconfig | 3 +- + arch/arm/mach-imx/common.h | 1 + + arch/arm/mach-imx/gpc.c | 147 +++- + arch/arm/mach-imx/mach-imx6q.c | 118 ++- + arch/arm/mach-imx/mach-imx6sl.c | 11 +- + arch/arm/mach-imx/mach-imx6sx.c | 1 + + arch/arm/mach-imx/mach-imx7d.c | 1 + + arch/arm/mach-omap2/cpuidle34xx.c | 69 +- + arch/arm/mach-omap2/io.c | 1 + + arch/arm/mach-omap2/omap_hwmod.c | 8 +- + arch/arm/mach-prima2/Kconfig | 1 + + arch/arm/mach-s3c64xx/dev-audio.c | 41 +- + arch/arm/mach-s3c64xx/include/mach/dma.h | 52 +- + arch/arm/mach-socfpga/headsmp.S | 1 + + arch/arm/plat-samsung/devs.c | 11 +- + arch/arm64/include/asm/elf.h | 4 +- + arch/arm64/include/asm/opcodes.h | 4 + + arch/arm64/include/asm/pgtable-hwdef.h | 1 - + arch/arm64/include/asm/pgtable.h | 47 +- + arch/arm64/kernel/cpuinfo.c | 11 +- + arch/arm64/kvm/inject_fault.c | 2 +- + arch/arm64/mm/fault.c | 50 ++ + arch/ia64/include/asm/io.h | 1 + + arch/mips/alchemy/devboards/db1000.c | 18 +- + arch/mips/alchemy/devboards/db1550.c | 4 +- + arch/mips/ath79/early_printk.c | 6 +- + arch/mips/include/asm/asmmacro.h | 40 +- + arch/mips/include/asm/cacheflush.h | 6 - + arch/mips/include/asm/kvm_host.h | 2 +- + arch/mips/include/asm/msa.h | 13 + + arch/mips/include/asm/pgtable.h | 26 +- + arch/mips/include/asm/processor.h | 2 +- + arch/mips/include/asm/switch_to.h | 2 +- + arch/mips/include/asm/watch.h | 10 +- + arch/mips/include/uapi/asm/siginfo.h | 22 +- + arch/mips/kernel/mips-r2-to-r6-emul.c | 105 +-- + arch/mips/kernel/pm.c | 2 +- + arch/mips/kernel/process.c | 6 +- + arch/mips/kernel/ptrace.c | 27 +- + arch/mips/kernel/r4k_fpu.S | 10 +- + arch/mips/kernel/setup.c | 3 + + arch/mips/kernel/signal.c | 15 +- + arch/mips/kernel/traps.c | 8 +- + arch/mips/kernel/unaligned.c | 51 +- + arch/mips/kernel/watch.c | 5 +- + arch/mips/kvm/emulate.c | 89 ++- + arch/mips/kvm/mips.c | 8 +- + arch/mips/kvm/trap_emul.c | 2 +- + arch/mips/lib/ashldi3.c | 2 +- + arch/mips/lib/ashrdi3.c | 2 +- + arch/mips/lib/bswapdi.c | 2 +- + arch/mips/lib/bswapsi.c | 2 +- + arch/mips/lib/cmpdi2.c | 2 +- + arch/mips/lib/lshrdi3.c | 2 +- + arch/mips/lib/ucmpdi2.c | 2 +- + arch/mips/loongson64/loongson-3/numa.c | 6 +- + arch/mips/math-emu/cp1emu.c | 8 +- + arch/mips/mm/cache.c | 41 +- + arch/mips/vdso/Makefile | 4 +- + arch/parisc/include/asm/uaccess.h | 1 + + arch/parisc/kernel/asm-offsets.c | 1 + + arch/parisc/kernel/parisc_ksyms.c | 10 +- + arch/parisc/kernel/traps.c | 3 + + arch/parisc/kernel/unaligned.c | 10 +- + arch/parisc/lib/fixup.S | 6 + + arch/parisc/mm/fault.c | 1 + + arch/powerpc/include/asm/kvm_host.h | 4 +- + arch/powerpc/include/asm/reg.h | 6 +- + arch/powerpc/include/asm/word-at-a-time.h | 2 +- + arch/powerpc/include/uapi/asm/cputable.h | 1 + + arch/powerpc/kernel/eeh.c | 2 +- + arch/powerpc/kernel/eeh_driver.c | 26 +- + arch/powerpc/kernel/exceptions-64s.S | 16 +- + arch/powerpc/kernel/process.c | 18 - + arch/powerpc/kernel/prom.c | 26 +- + arch/powerpc/kernel/prom_init.c | 1 + + arch/powerpc/kvm/book3s_hv.c | 22 +- + arch/powerpc/mm/hugetlbpage.c | 4 +- + arch/powerpc/platforms/pseries/eeh_pseries.c | 51 +- + arch/s390/include/asm/kvm_host.h | 2 +- + arch/s390/include/asm/mmu.h | 2 +- + arch/s390/include/asm/mmu_context.h | 28 +- + arch/s390/include/asm/pci.h | 3 +- + arch/s390/include/asm/pgalloc.h | 4 +- + arch/s390/include/asm/processor.h | 2 +- + arch/s390/include/asm/tlbflush.h | 9 +- + arch/s390/kernel/entry.S | 106 +-- + arch/s390/kernel/head64.S | 2 +- + arch/s390/kernel/setup.c | 1 + + arch/s390/kvm/interrupt.c | 4 +- + arch/s390/mm/init.c | 3 +- + arch/s390/mm/mmap.c | 6 +- + arch/s390/mm/pgtable.c | 85 +-- + arch/s390/net/bpf_jit.h | 4 +- + arch/s390/net/bpf_jit_comp.c | 4 +- + arch/s390/pci/pci.c | 5 +- + arch/sh/mm/kmap.c | 2 + + arch/sparc/include/asm/head_64.h | 4 + + arch/sparc/include/asm/pgtable_64.h | 43 +- + arch/sparc/include/asm/tlbflush_64.h | 3 +- + arch/sparc/include/asm/ttable.h | 8 +- + arch/sparc/kernel/Makefile | 1 + + arch/sparc/kernel/cherrs.S | 14 +- + arch/sparc/kernel/entry.S | 17 + + arch/sparc/kernel/fpu_traps.S | 11 +- + arch/sparc/kernel/head_64.S | 24 +- + arch/sparc/kernel/misctrap.S | 12 +- + arch/sparc/kernel/pci.c | 17 + + arch/sparc/kernel/rtrap_64.S | 57 +- + arch/sparc/kernel/signal32.c | 46 +- + arch/sparc/kernel/signal_32.c | 41 +- + arch/sparc/kernel/signal_64.c | 33 +- + arch/sparc/kernel/sigutil_32.c | 9 +- + arch/sparc/kernel/sigutil_64.c | 10 +- + arch/sparc/kernel/spiterrs.S | 18 +- + arch/sparc/kernel/syscalls.S | 36 + + arch/sparc/kernel/urtt_fill.S | 98 +++ + arch/sparc/kernel/utrap.S | 3 +- + arch/sparc/kernel/vmlinux.lds.S | 4 + + arch/sparc/kernel/winfixup.S | 3 +- + arch/sparc/mm/hugetlbpage.c | 33 +- + arch/sparc/mm/init_64.c | 37 +- + arch/sparc/mm/tlb.c | 25 +- + arch/sparc/mm/tsb.c | 32 +- + arch/um/drivers/mconsole_kern.c | 2 +- + arch/x86/Kconfig | 27 +- + arch/x86/crypto/sha-mb/sha1_mb.c | 4 +- + arch/x86/entry/common.c | 23 +- + arch/x86/include/asm/apic.h | 2 +- + arch/x86/include/asm/hugetlb.h | 1 + + arch/x86/include/asm/hw_irq.h | 1 + + arch/x86/include/asm/kvm_host.h | 2 +- + arch/x86/include/asm/microcode.h | 26 + + arch/x86/include/asm/pci_x86.h | 2 + + arch/x86/include/asm/perf_event.h | 1 + + arch/x86/include/asm/xen/hypervisor.h | 2 + + arch/x86/kernel/apic/vector.c | 91 ++- + arch/x86/kernel/cpu/mcheck/mce-genpool.c | 4 +- + arch/x86/kernel/cpu/mcheck/therm_throt.c | 3 + + arch/x86/kernel/cpu/microcode/intel.c | 38 +- + arch/x86/kernel/cpu/perf_event.c | 13 + + arch/x86/kernel/cpu/perf_event.h | 3 + + arch/x86/kernel/cpu/perf_event_intel.c | 27 +- + arch/x86/kernel/cpu/perf_event_intel_ds.c | 24 +- + arch/x86/kernel/cpu/perf_event_intel_pt.c | 2 + + arch/x86/kernel/cpu/perf_event_intel_rapl.c | 20 +- + arch/x86/kernel/cpu/perf_event_knc.c | 4 +- + arch/x86/kernel/ioport.c | 12 +- + arch/x86/kernel/kvm.c | 37 +- + arch/x86/kernel/nmi.c | 16 +- + arch/x86/kernel/process_64.c | 12 + + arch/x86/kernel/reboot.c | 20 + + arch/x86/kernel/smpboot.c | 5 + + arch/x86/kernel/sysfb_efi.c | 14 +- + arch/x86/kernel/traps.c | 20 +- + arch/x86/kernel/tsc_msr.c | 2 +- + arch/x86/kvm/cpuid.c | 1 + + arch/x86/kvm/i8254.c | 12 +- + arch/x86/kvm/lapic.c | 6 +- + arch/x86/kvm/mtrr.c | 2 - + arch/x86/kvm/vmx.c | 18 +- + arch/x86/kvm/x86.c | 36 +- + arch/x86/mm/kmmio.c | 88 ++- + arch/x86/mm/tlb.c | 12 +- + arch/x86/pci/common.c | 26 +- + arch/x86/pci/fixup.c | 7 + + arch/x86/pci/intel_mid_pci.c | 9 +- + arch/x86/pci/irq.c | 23 +- + arch/x86/pci/xen.c | 7 +- + arch/x86/xen/enlighten.c | 2 +- + arch/x86/xen/setup.c | 65 +- + arch/xtensa/kernel/head.S | 2 +- + arch/xtensa/mm/cache.c | 8 +- + arch/xtensa/platforms/iss/console.c | 10 +- + block/blk-core.c | 6 +- + block/blk-mq.c | 4 +- + block/partition-generic.c | 13 +- + crypto/ahash.c | 3 +- + crypto/asymmetric_keys/Kconfig | 1 + + crypto/asymmetric_keys/pkcs7_trust.c | 2 + + crypto/asymmetric_keys/x509_cert_parser.c | 8 +- + crypto/keywrap.c | 4 +- + crypto/testmgr.c | 27 +- + drivers/acpi/acpi_processor.c | 52 ++ + drivers/acpi/acpica/dsmethod.c | 3 + + drivers/acpi/bus.c | 3 + + drivers/acpi/internal.h | 6 + + drivers/acpi/osl.c | 16 +- + drivers/acpi/pci_irq.c | 17 +- + drivers/acpi/resource.c | 14 +- + drivers/acpi/sleep.c | 1 + + drivers/ata/ahci_platform.c | 3 + + drivers/ata/ahci_xgene.c | 4 +- + drivers/ata/libahci.c | 1 + + drivers/base/power/domain.c | 2 +- + drivers/base/power/main.c | 5 +- + drivers/base/power/opp/core.c | 10 +- + drivers/base/power/runtime.c | 9 +- + drivers/base/regmap/regmap-spmi.c | 2 +- + drivers/block/brd.c | 2 +- + drivers/block/loop.c | 6 + + drivers/block/mtip32xx/mtip32xx.c | 267 +++++-- + drivers/block/mtip32xx/mtip32xx.h | 11 +- + drivers/block/nbd.c | 4 +- + drivers/block/paride/pd.c | 4 +- + drivers/block/paride/pt.c | 4 +- + drivers/block/rbd.c | 6 +- + drivers/block/zram/zram_drv.c | 30 +- + drivers/block/zram/zram_drv.h | 41 + + drivers/bluetooth/ath3k.c | 8 + + drivers/bluetooth/btusb.c | 4 + + drivers/bluetooth/hci_vhci.c | 28 +- + drivers/bus/imx-weim.c | 2 +- + drivers/char/hw_random/exynos-rng.c | 10 +- + drivers/char/tpm/tpm-chip.c | 14 +- + drivers/char/tpm/tpm_crb.c | 4 +- + drivers/char/tpm/tpm_eventlog.c | 14 +- + drivers/clk/at91/clk-generated.c | 95 ++- + drivers/clk/at91/clk-h32mx.c | 42 +- + drivers/clk/at91/clk-main.c | 324 ++++---- + drivers/clk/at91/clk-master.c | 94 +-- + drivers/clk/at91/clk-peripheral.c | 136 ++-- + drivers/clk/at91/clk-pll.c | 150 ++-- + drivers/clk/at91/clk-plldiv.c | 44 +- + drivers/clk/at91/clk-programmable.c | 96 +-- + drivers/clk/at91/clk-slow.c | 34 +- + drivers/clk/at91/clk-smd.c | 56 +- + drivers/clk/at91/clk-system.c | 96 +-- + drivers/clk/at91/clk-usb.c | 123 +-- + drivers/clk/at91/clk-utmi.c | 80 +- + drivers/clk/at91/pmc.c | 426 +---------- + drivers/clk/at91/pmc.h | 98 +-- + drivers/clk/bcm/clk-bcm2835.c | 35 +- + drivers/clk/clk-divider.c | 11 +- + drivers/clk/imx/clk-imx35.c | 4 +- + drivers/clk/imx/clk-imx6q.c | 23 +- + drivers/clk/meson/clkc.c | 2 +- + drivers/clk/nxp/clk-lpc18xx-ccu.c | 2 +- + drivers/clk/qcom/gcc-msm8916.c | 2 + + drivers/clk/qcom/gcc-msm8960.c | 4 +- + drivers/clk/rockchip/clk-rk3188.c | 1 + + drivers/clk/rockchip/clk-rk3368.c | 48 +- + drivers/clk/rockchip/clk.c | 13 +- + drivers/clk/versatile/clk-sp810.c | 4 +- + drivers/clocksource/tcb_clksrc.c | 33 +- + drivers/clocksource/timer-atmel-pit.c | 8 +- + drivers/cpufreq/intel_pstate.c | 5 + + drivers/cpuidle/cpuidle-arm.c | 2 +- + drivers/cpuidle/cpuidle.c | 4 +- + drivers/crypto/atmel-aes.c | 4 +- + drivers/crypto/atmel-sha.c | 4 +- + drivers/crypto/atmel-tdes.c | 4 +- + drivers/crypto/caam/jr.c | 2 +- + drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 39 + + drivers/crypto/ccp/ccp-crypto-aes-xts.c | 17 +- + drivers/crypto/ccp/ccp-crypto-sha.c | 43 ++ + drivers/crypto/ccp/ccp-crypto.h | 22 + + drivers/crypto/marvell/cesa.c | 2 +- + drivers/crypto/qat/qat_common/adf_common_drv.h | 11 + + drivers/crypto/qat/qat_common/adf_ctl_drv.c | 6 + + drivers/crypto/qat/qat_common/adf_sriov.c | 26 +- + drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 10 +- + drivers/crypto/talitos.c | 151 +++- + drivers/crypto/ux500/cryp/cryp_core.c | 4 +- + drivers/crypto/ux500/hash/hash_core.c | 4 +- + drivers/dma/dw/core.c | 34 +- + drivers/dma/hsu/hsu.c | 2 +- + drivers/dma/hsu/hsu.h | 3 + + drivers/dma/pxa_dma.c | 39 +- + drivers/edac/amd64_edac.c | 2 +- + drivers/edac/i7core_edac.c | 2 +- + drivers/edac/sb_edac.c | 30 +- + drivers/extcon/extcon-max77843.c | 2 +- + drivers/firmware/efi/efi.c | 1 + + drivers/firmware/efi/vars.c | 37 +- + drivers/gpio/gpio-bcm-kona.c | 4 +- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 10 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 5 + + drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 1 + + drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 4 + + drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 +- + drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 16 +- + drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 23 +- + drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 4 +- + drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 2 +- + drivers/gpu/drm/drm_atomic.c | 2 +- + drivers/gpu/drm/drm_crtc.c | 60 +- + drivers/gpu/drm/drm_dp_helper.c | 27 +- + drivers/gpu/drm/drm_dp_mst_topology.c | 29 +- + drivers/gpu/drm/drm_fb_helper.c | 5 +- + drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c | 2 +- + drivers/gpu/drm/i915/i915_irq.c | 2 + + drivers/gpu/drm/i915/i915_reg.h | 9 +- + drivers/gpu/drm/i915/intel_crt.c | 8 +- + drivers/gpu/drm/i915/intel_csr.c | 3 +- + drivers/gpu/drm/i915/intel_ddi.c | 22 +- + drivers/gpu/drm/i915/intel_display.c | 2 +- + drivers/gpu/drm/i915/intel_dp.c | 4 +- + drivers/gpu/drm/i915/intel_dp_mst.c | 6 +- + drivers/gpu/drm/i915/intel_drv.h | 2 + + drivers/gpu/drm/i915/intel_fbdev.c | 6 +- + drivers/gpu/drm/i915/intel_hdmi.c | 12 +- + drivers/gpu/drm/i915/intel_lrc.c | 6 +- + drivers/gpu/drm/i915/intel_pm.c | 8 + + drivers/gpu/drm/i915/intel_ringbuffer.c | 30 +- + drivers/gpu/drm/i915/intel_sprite.c | 11 +- + drivers/gpu/drm/i915/intel_uncore.c | 6 +- + drivers/gpu/drm/imx/imx-drm-core.c | 8 + + drivers/gpu/drm/imx/ipuv3-crtc.c | 2 +- + drivers/gpu/drm/nouveau/nvkm/core/ramht.c | 6 +- + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 2 + + drivers/gpu/drm/qxl/qxl_display.c | 13 +- + drivers/gpu/drm/qxl/qxl_drv.h | 2 + + drivers/gpu/drm/radeon/atombios_crtc.c | 10 + + drivers/gpu/drm/radeon/atombios_encoders.c | 10 +- + drivers/gpu/drm/radeon/evergreen.c | 154 +++- + drivers/gpu/drm/radeon/evergreen_reg.h | 46 ++ + drivers/gpu/drm/radeon/radeon_connectors.c | 7 +- + drivers/gpu/drm/radeon/radeon_display.c | 2 + + drivers/gpu/drm/radeon/radeon_dp_auxch.c | 2 +- + drivers/gpu/drm/radeon/radeon_ttm.c | 2 + + drivers/gpu/drm/radeon/si_dpm.c | 7 + + drivers/gpu/drm/udl/udl_fb.c | 2 +- + drivers/gpu/drm/udl/udl_gem.c | 2 +- + drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 10 +- + drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 6 +- + drivers/gpu/galcore/Kbuild | 57 +- + .../default/gc_hal_kernel_allocator_array.h | 68 +- + .../default/gc_hal_kernel_allocator_dmabuf.c | 353 +++++++++ + .../freescale/gc_hal_kernel_allocator_array.h | 70 +- + .../freescale/gc_hal_kernel_allocator_cma.c | 54 +- + drivers/gpu/galcore/arch/gc_hal_kernel_context.c | 264 +++++-- + drivers/gpu/galcore/arch/gc_hal_kernel_context.h | 82 +- + drivers/gpu/galcore/arch/gc_hal_kernel_hardware.c | 842 +++++++++++++++------ + drivers/gpu/galcore/arch/gc_hal_kernel_hardware.h | 70 +- + drivers/gpu/galcore/arch/gc_hal_kernel_recorder.c | 58 +- + .../archvg/gc_hal_kernel_hardware_command_vg.c | 50 +- + .../archvg/gc_hal_kernel_hardware_command_vg.h | 50 +- + .../gpu/galcore/archvg/gc_hal_kernel_hardware_vg.c | 157 +++- + .../gpu/galcore/archvg/gc_hal_kernel_hardware_vg.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel.c | 344 +++++++-- + drivers/gpu/galcore/gc_hal_kernel.h | 129 +++- + drivers/gpu/galcore/gc_hal_kernel_allocator.c | 70 +- + drivers/gpu/galcore/gc_hal_kernel_allocator.h | 90 ++- + drivers/gpu/galcore/gc_hal_kernel_command.c | 726 ++++++++++-------- + drivers/gpu/galcore/gc_hal_kernel_command_vg.c | 67 +- + drivers/gpu/galcore/gc_hal_kernel_db.c | 170 +++-- + drivers/gpu/galcore/gc_hal_kernel_debug.c | 68 +- + drivers/gpu/galcore/gc_hal_kernel_debug.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_debugfs.c | 155 ++-- + drivers/gpu/galcore/gc_hal_kernel_debugfs.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_device.c | 238 ++++-- + drivers/gpu/galcore/gc_hal_kernel_device.h | 86 ++- + drivers/gpu/galcore/gc_hal_kernel_event.c | 91 ++- + drivers/gpu/galcore/gc_hal_kernel_interrupt_vg.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_iommu.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_linux.c | 55 +- + drivers/gpu/galcore/gc_hal_kernel_linux.h | 56 +- + drivers/gpu/galcore/gc_hal_kernel_math.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_mmu.c | 97 ++- + drivers/gpu/galcore/gc_hal_kernel_mmu_vg.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_mutex.h | 89 +++ + drivers/gpu/galcore/gc_hal_kernel_os.c | 638 ++++++++++------ + drivers/gpu/galcore/gc_hal_kernel_os.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_platform.h | 83 +- + drivers/gpu/galcore/gc_hal_kernel_power.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_precomp.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_probe.c | 88 ++- + drivers/gpu/galcore/gc_hal_kernel_sync.c | 50 +- + drivers/gpu/galcore/gc_hal_kernel_sync.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_vg.c | 94 ++- + drivers/gpu/galcore/gc_hal_kernel_vg.h | 50 +- + drivers/gpu/galcore/gc_hal_kernel_video_memory.c | 150 +++- + drivers/gpu/galcore/inc/gc_hal.h | 147 +++- + drivers/gpu/galcore/inc/gc_hal_base.h | 253 ++++++- + drivers/gpu/galcore/inc/gc_hal_driver.h | 157 +++- + drivers/gpu/galcore/inc/gc_hal_driver_vg.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_dump.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_eglplatform.h | 95 ++- + drivers/gpu/galcore/inc/gc_hal_eglplatform_type.h | 82 +- + drivers/gpu/galcore/inc/gc_hal_engine.h | 133 +++- + drivers/gpu/galcore/inc/gc_hal_engine_vg.h | 233 ++++-- + drivers/gpu/galcore/inc/gc_hal_enum.h | 131 +++- + drivers/gpu/galcore/inc/gc_hal_kernel_buffer.h | 52 +- + drivers/gpu/galcore/inc/gc_hal_mem.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_options.h | 101 ++- + drivers/gpu/galcore/inc/gc_hal_profiler.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_raster.h | 56 +- + drivers/gpu/galcore/inc/gc_hal_rename.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_statistics.h | 50 +- + drivers/gpu/galcore/inc/gc_hal_types.h | 60 +- + drivers/gpu/galcore/inc/gc_hal_version.h | 58 +- + drivers/gpu/galcore/inc/gc_hal_vg.h | 50 +- + .../freescale/gc_hal_kernel_platform_imx6q14.c | 62 +- + .../gc_hal_kernel_platform_imx6q14.config | 5 + + drivers/gpu/ipu-v3/ipu-common.c | 12 +- + drivers/hid/hid-core.c | 8 +- + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-multitouch.c | 5 + + drivers/hid/i2c-hid/i2c-hid.c | 16 +- + drivers/hid/usbhid/hid-core.c | 73 +- + drivers/hid/usbhid/hid-quirks.c | 1 + + drivers/hid/wacom_wac.c | 16 + + drivers/hwmon/ads7828.c | 10 + + drivers/hwmon/max1111.c | 6 + + drivers/hwtracing/stm/Kconfig | 1 + + drivers/i2c/busses/i2c-cpm.c | 4 +- + drivers/i2c/busses/i2c-exynos5.c | 24 +- + drivers/idle/intel_idle.c | 108 ++- + drivers/iio/accel/bmc150-accel-core.c | 7 +- + drivers/iio/gyro/bmg160_core.c | 9 +- + drivers/iio/magnetometer/ak8975.c | 6 +- + drivers/iio/magnetometer/st_magn.h | 1 + + drivers/infiniband/core/ucm.c | 4 + + drivers/infiniband/core/ucma.c | 3 + + drivers/infiniband/core/uverbs_main.c | 5 + + drivers/infiniband/hw/cxgb4/cq.c | 2 +- + drivers/infiniband/hw/cxgb4/qp.c | 6 +- + drivers/infiniband/hw/mlx5/main.c | 6 +- + drivers/infiniband/hw/qib/qib_file_ops.c | 5 + + drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 24 +- + drivers/infiniband/ulp/isert/ib_isert.c | 122 +-- + drivers/infiniband/ulp/isert/ib_isert.h | 2 +- + drivers/infiniband/ulp/srp/ib_srp.c | 2 +- + drivers/infiniband/ulp/srpt/ib_srpt.c | 59 +- + drivers/input/misc/ati_remote2.c | 36 +- + drivers/input/misc/ims-pcu.c | 4 + + drivers/input/misc/max8997_haptic.c | 6 +- + drivers/input/misc/pmic8xxx-pwrkey.c | 7 +- + drivers/input/misc/powermate.c | 3 + + drivers/input/misc/pwm-beeper.c | 69 +- + drivers/input/misc/uinput.c | 6 + + drivers/input/mouse/synaptics.c | 5 +- + drivers/input/tablet/gtco.c | 10 +- + drivers/input/touchscreen/zforce_ts.c | 4 +- + drivers/iommu/amd_iommu.c | 99 ++- + drivers/iommu/dma-iommu.c | 4 +- + drivers/iommu/iommu.c | 3 +- + drivers/irqchip/irq-gic-v3.c | 19 + + drivers/irqchip/irq-gic.c | 8 + + drivers/irqchip/irq-mxs.c | 2 +- + drivers/irqchip/irq-sunxi-nmi.c | 4 +- + drivers/mcb/mcb-parse.c | 2 +- + drivers/md/bcache/super.c | 46 +- + drivers/md/dm-cache-metadata.c | 122 +-- + drivers/md/dm-cache-metadata.h | 4 +- + drivers/md/dm-cache-target.c | 12 +- + drivers/md/dm-snap.c | 9 + + drivers/md/dm-table.c | 36 +- + drivers/md/dm-thin-metadata.c | 5 +- + drivers/md/dm.c | 15 +- + drivers/md/md.c | 2 + + drivers/md/multipath.c | 4 +- + drivers/md/raid1.c | 7 +- + drivers/md/raid10.c | 7 +- + drivers/md/raid5.c | 51 +- + drivers/md/raid5.h | 4 +- + drivers/media/i2c/adv7511.c | 21 +- + drivers/media/pci/bt8xx/bttv-driver.c | 26 +- + drivers/media/pci/saa7134/saa7134-video.c | 18 +- + drivers/media/platform/coda/coda-bit.c | 2 +- + drivers/media/platform/coda/coda-common.c | 10 +- + drivers/media/platform/vsp1/vsp1_sru.c | 1 + + drivers/media/usb/au0828/au0828-core.c | 2 +- + drivers/media/usb/au0828/au0828-input.c | 4 +- + drivers/media/usb/au0828/au0828-video.c | 63 +- + drivers/media/usb/au0828/au0828.h | 9 +- + drivers/media/usb/pwc/pwc-if.c | 6 + + drivers/media/usb/usbvision/usbvision-video.c | 16 +- + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 26 +- + drivers/media/v4l2-core/videobuf2-core.c | 10 +- + drivers/media/v4l2-core/videobuf2-memops.c | 2 +- + drivers/mfd/intel-lpss.c | 20 +- + drivers/mfd/intel_soc_pmic_core.c | 1 + + drivers/mfd/mxc-hdmi-core.c | 17 +- + drivers/mfd/omap-usb-tll.c | 13 +- + drivers/misc/Kconfig | 2 +- + drivers/misc/ad525x_dpot.c | 2 +- + drivers/misc/cxl/irq.c | 1 - + drivers/misc/mei/amthif.c | 4 +- + drivers/misc/mei/bus.c | 24 +- + drivers/misc/mei/client.c | 4 + + drivers/misc/mei/hbm.c | 3 +- + drivers/misc/mei/interrupt.c | 6 +- + drivers/misc/mei/mei_dev.h | 2 + + drivers/misc/mic/scif/scif_rma.c | 7 +- + drivers/mmc/card/block.c | 29 +- + drivers/mmc/core/core.c | 4 +- + drivers/mmc/core/mmc.c | 7 + + drivers/mmc/host/mmc_spi.c | 6 + + drivers/mmc/host/sdhci-acpi.c | 6 +- + drivers/mmc/host/sdhci-esdhc-imx.c | 63 +- + drivers/mmc/host/sdhci-pci-core.c | 30 +- + drivers/mmc/host/sdhci-pci.h | 3 + + drivers/mmc/host/sdhci.c | 37 +- + drivers/mmc/host/sdhci.h | 3 + + drivers/mmc/host/sh_mmcif.c | 2 +- + drivers/mtd/nand/brcmnand/brcmnand.c | 34 +- + drivers/mtd/nand/nand_base.c | 10 +- + drivers/mtd/onenand/onenand_base.c | 3 +- + drivers/mtd/spi-nor/spi-nor.c | 46 +- + drivers/mtd/ubi/eba.c | 21 +- + drivers/mtd/ubi/fastmap.c | 1 + + drivers/mtd/ubi/ubi.h | 2 + + .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 6 +- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 5 +- + drivers/mxc/ipu3/ipu_device.c | 4 +- + drivers/net/bonding/bond_main.c | 65 +- + drivers/net/can/dev.c | 56 +- + drivers/net/can/m_can/m_can.c | 2 +- + drivers/net/ethernet/atheros/atlx/atl2.c | 2 +- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +- + drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 4 + + drivers/net/ethernet/freescale/fec_main.c | 51 +- + drivers/net/ethernet/jme.c | 26 +- + drivers/net/ethernet/marvell/mvneta.c | 2 +- + drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +- + drivers/net/ethernet/mellanox/mlx4/en_tx.c | 6 +- + .../net/ethernet/mellanox/mlx4/resource_tracker.c | 3 +- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 15 +- + drivers/net/ethernet/mellanox/mlx5/core/port.c | 10 +- + drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 + + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 9 +- + drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 3 +- + .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 24 +- + .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 3 +- + drivers/net/ethernet/qlogic/qlge/qlge_main.c | 11 + + drivers/net/ethernet/qualcomm/qca_spi.c | 2 +- + drivers/net/ethernet/renesas/sh_eth.c | 10 +- + drivers/net/ethernet/rocker/rocker.c | 14 +- + drivers/net/ethernet/sfc/ef10.c | 16 + + drivers/net/geneve.c | 41 +- + drivers/net/irda/irtty-sir.c | 10 - + drivers/net/macvtap.c | 9 +- + drivers/net/ppp/ppp_generic.c | 36 +- + drivers/net/rionet.c | 4 +- + drivers/net/team/team.c | 9 +- + drivers/net/tun.c | 18 +- + drivers/net/usb/asix_common.c | 2 +- + drivers/net/usb/cdc_ether.c | 8 +- + drivers/net/usb/cdc_mbim.c | 9 +- + drivers/net/usb/cdc_ncm.c | 6 +- + drivers/net/usb/qmi_wwan.c | 7 +- + drivers/net/usb/usbnet.c | 7 + + drivers/net/vrf.c | 13 +- + drivers/net/vxlan.c | 64 +- + drivers/net/wan/farsync.c | 2 +- + drivers/net/wireless/ath/ath10k/core.c | 8 +- + drivers/net/wireless/ath/ath10k/debug.c | 7 +- + drivers/net/wireless/ath/ath10k/mac.c | 13 +- + drivers/net/wireless/ath/ath5k/led.c | 2 +- + drivers/net/wireless/ath/ath9k/ar5008_phy.c | 8 +- + drivers/net/wireless/ath/ath9k/ar9002_phy.c | 5 - + drivers/net/wireless/ath/ath9k/eeprom.c | 7 +- + drivers/net/wireless/ath/ath9k/init.c | 7 + + drivers/net/wireless/ath/ath9k/pci.c | 10 + + drivers/net/wireless/iwlwifi/mvm/fw.c | 4 +- + drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 + + drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 + + drivers/net/wireless/iwlwifi/pcie/trans.c | 4 +- + drivers/net/wireless/mwifiex/sta_ioctl.c | 1 + + drivers/net/wireless/realtek/rtlwifi/base.c | 4 +- + .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 9 +- + .../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 27 +- + .../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 2 +- + .../wireless/realtek/rtlwifi/btcoexist/rtl_btc.c | 5 +- + drivers/net/wireless/realtek/rtlwifi/pci.c | 2 +- + .../net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 5 + + .../net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 3 + + drivers/net/wireless/realtek/rtlwifi/wifi.h | 3 + + drivers/nvdimm/bus.c | 10 +- + drivers/nvdimm/pfn_devs.c | 2 +- + drivers/nvmem/mxs-ocotp.c | 4 +- + drivers/of/of_reserved_mem.c | 4 +- + drivers/pci/probe.c | 14 + + drivers/pcmcia/db1xxx_ss.c | 11 +- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- + drivers/pinctrl/freescale/pinctrl-imx.c | 17 +- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 14 +- + drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2 +- + drivers/pinctrl/pinctrl-at91-pio4.c | 2 + + drivers/pinctrl/pinctrl-pistachio.c | 24 +- + drivers/pinctrl/pinctrl-single.c | 6 +- + drivers/pinctrl/samsung/pinctrl-exynos5440.c | 15 +- + drivers/pinctrl/sh-pfc/core.c | 4 +- + drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c | 1 + + drivers/pinctrl/sunxi/pinctrl-sunxi.c | 17 +- + drivers/pinctrl/sunxi/pinctrl-sunxi.h | 21 +- + drivers/platform/x86/dell-rbtn.c | 56 ++ + drivers/platform/x86/ideapad-laptop.c | 14 + + drivers/platform/x86/toshiba_acpi.c | 2 +- + drivers/pwm/pwm-brcmstb.c | 4 +- + drivers/regulator/axp20x-regulator.c | 4 +- + drivers/regulator/core.c | 22 +- + drivers/regulator/s2mps11.c | 28 +- + drivers/regulator/s5m8767.c | 13 +- + drivers/rtc/rtc-ds1685.c | 8 +- + drivers/rtc/rtc-hym8563.c | 2 +- + drivers/rtc/rtc-max77686.c | 2 +- + drivers/rtc/rtc-rx8025.c | 1 - + drivers/rtc/rtc-vr41xx.c | 13 +- + drivers/scsi/aacraid/aacraid.h | 3 + + drivers/scsi/aacraid/comminit.c | 24 + + drivers/scsi/aacraid/commsup.c | 49 +- + drivers/scsi/aacraid/linit.c | 12 +- + drivers/scsi/aacraid/src.c | 30 +- + drivers/scsi/aic7xxx/aic7xxx_osm.c | 1 + + drivers/scsi/be2iscsi/be_main.c | 1 + + drivers/scsi/device_handler/Kconfig | 8 +- + drivers/scsi/ipr.c | 10 +- + drivers/scsi/lpfc/lpfc_init.c | 5 +- + drivers/scsi/megaraid/megaraid_sas_base.c | 3 +- + drivers/scsi/qla1280.c | 2 +- + drivers/scsi/scsi_common.c | 12 +- + drivers/scsi/scsi_devinfo.c | 1 + + drivers/scsi/scsi_lib.c | 7 +- + drivers/scsi/scsi_scan.c | 1 + + drivers/scsi/scsi_sysfs.c | 6 +- + drivers/scsi/sd.c | 30 +- + drivers/scsi/sd.h | 7 +- + drivers/scsi/sg.c | 3 +- + drivers/scsi/storvsc_drv.c | 5 +- + drivers/soc/rockchip/pm_domains.c | 1 + + drivers/spi/spi-pxa2xx.c | 2 +- + drivers/spi/spi-rockchip.c | 7 +- + drivers/spi/spi-ti-qspi.c | 45 +- + drivers/staging/android/ion/ion.c | 4 +- + drivers/staging/android/ion/ion_test.c | 4 +- + drivers/staging/comedi/drivers/das1800.c | 22 +- + drivers/staging/comedi/drivers/ni_mio_common.c | 12 +- + drivers/staging/comedi/drivers/ni_tiocmd.c | 2 +- + drivers/staging/media/lirc/lirc_atiusb.c | 4 +- + drivers/staging/media/lirc/lirc_hb.c | 6 +- + drivers/staging/media/lirc/lirc_xbox.c | 4 +- + drivers/staging/rdma/hfi1/TODO | 2 +- + drivers/staging/rdma/hfi1/file_ops.c | 6 + + drivers/target/target_core_transport.c | 2 - + drivers/thermal/rockchip_thermal.c | 11 +- + drivers/thermal/thermal_core.c | 13 +- + drivers/thunderbolt/eeprom.c | 1 + + drivers/tty/n_gsm.c | 4 +- + drivers/tty/n_hdlc.c | 4 +- + drivers/tty/n_tty.c | 70 +- + drivers/tty/pty.c | 4 +- + drivers/tty/serial/8250/8250_mid.c | 35 +- + drivers/tty/serial/8250/8250_pci.c | 3 + + drivers/tty/serial/8250/8250_port.c | 22 +- + drivers/tty/serial/atmel_serial.c | 14 +- + drivers/tty/serial/samsung.c | 4 +- + drivers/tty/serial/sc16is7xx.c | 2 +- + drivers/tty/serial/sh-sci.c | 39 - + drivers/tty/serial/ucc_uart.c | 3 + + drivers/tty/tty_buffer.c | 34 +- + drivers/tty/vt/vt.c | 5 +- + drivers/usb/class/cdc-acm.c | 3 + + drivers/usb/core/driver.c | 46 +- + drivers/usb/core/hcd-pci.c | 9 + + drivers/usb/core/hub.c | 24 +- + drivers/usb/gadget/function/f_fs.c | 9 +- + drivers/usb/gadget/function/f_mass_storage.c | 36 +- + drivers/usb/gadget/function/f_mass_storage.h | 2 - + drivers/usb/gadget/legacy/acm_ms.c | 4 - + drivers/usb/gadget/legacy/mass_storage.c | 4 - + drivers/usb/gadget/legacy/multi.c | 12 - + drivers/usb/gadget/legacy/nokia.c | 7 - + drivers/usb/gadget/udc/atmel_usba_udc.c | 20 +- + drivers/usb/gadget/udc/atmel_usba_udc.h | 2 + + drivers/usb/gadget/udc/udc-core.c | 2 +- + drivers/usb/host/xhci-mem.c | 6 + + drivers/usb/host/xhci-pci.c | 5 +- + drivers/usb/host/xhci-ring.c | 3 +- + drivers/usb/host/xhci.c | 14 +- + drivers/usb/host/xhci.h | 1 + + drivers/usb/misc/iowarrior.c | 6 + + drivers/usb/misc/usbtest.c | 4 +- + drivers/usb/renesas_usbhs/fifo.c | 4 +- + drivers/usb/renesas_usbhs/mod_gadget.c | 6 +- + drivers/usb/serial/cp210x.c | 5 + + drivers/usb/serial/cypress_m8.c | 11 +- + drivers/usb/serial/digi_acceleport.c | 19 + + drivers/usb/serial/ftdi_sio.c | 4 + + drivers/usb/serial/ftdi_sio_ids.h | 8 + + drivers/usb/serial/io_edgeport.c | 56 +- + drivers/usb/serial/keyspan.c | 4 + + drivers/usb/serial/mct_u232.c | 9 +- + drivers/usb/serial/mxuport.c | 10 + + drivers/usb/serial/option.c | 157 +++- + drivers/usb/serial/quatech2.c | 1 + + drivers/usb/storage/uas.c | 23 +- + drivers/usb/storage/unusual_uas.h | 7 + + drivers/usb/storage/usb.c | 5 +- + drivers/usb/usbip/usbip_common.c | 11 + + drivers/video/fbdev/Kconfig | 1 - + drivers/video/fbdev/da8xx-fb.c | 7 +- + drivers/video/mxc/mxc_edid.c | 13 +- + drivers/video/mxc/mxc_hdmi.c | 15 +- + drivers/virtio/virtio_pci_modern.c | 11 +- + drivers/watchdog/rc32434_wdt.c | 2 +- + drivers/xen/balloon.c | 16 + + drivers/xen/events/events_base.c | 30 +- + drivers/xen/evtchn.c | 20 +- + firmware/imx/sdma/sdma-imx6q.bin.ihex | 255 ++++--- + fs/affs/super.c | 5 +- + fs/btrfs/file.c | 2 +- + fs/btrfs/ioctl.c | 2 +- + fs/btrfs/tree-log.c | 137 ++++ + fs/btrfs/volumes.c | 1 - + fs/cifs/sess.c | 139 ++-- + fs/cifs/smb2glob.h | 1 + + fs/cifs/smb2inode.c | 8 +- + fs/cifs/smb2pdu.c | 16 + + fs/cifs/smb2proto.h | 2 + + fs/coredump.c | 30 +- + fs/dcache.c | 9 +- + fs/debugfs/inode.c | 2 +- + fs/ecryptfs/kthread.c | 13 +- + fs/ext4/ext4.h | 36 + + fs/ext4/extents.c | 133 ++-- + fs/ext4/file.c | 66 +- + fs/ext4/ialloc.c | 59 +- + fs/ext4/inode.c | 77 +- + fs/ext4/mballoc.c | 10 +- + fs/ext4/move_extent.c | 12 +- + fs/ext4/namei.c | 2 +- + fs/ext4/super.c | 48 +- + fs/ext4/truncate.h | 2 + + fs/f2fs/f2fs.h | 4 +- + fs/fhandle.c | 2 +- + fs/fs-writeback.c | 37 +- + fs/fuse/cuse.c | 4 +- + fs/fuse/file.c | 33 +- + fs/fuse/fuse_i.h | 9 + + fs/hpfs/super.c | 42 +- + fs/isofs/rock.c | 13 +- + fs/jbd2/journal.c | 17 +- + fs/namei.c | 26 +- + fs/nfs/dir.c | 6 +- + fs/nfs/inode.c | 2 +- + fs/nfs/nfs4file.c | 4 +- + fs/nfsd/nfs4proc.c | 1 + + fs/nfsd/nfs4xdr.c | 13 +- + fs/ocfs2/acl.c | 87 +++ + fs/ocfs2/acl.h | 5 + + fs/ocfs2/dlm/dlmconvert.c | 24 +- + fs/ocfs2/dlm/dlmrecovery.c | 1 - + fs/ocfs2/file.c | 4 +- + fs/ocfs2/namei.c | 23 +- + fs/ocfs2/refcounttree.c | 17 +- + fs/ocfs2/xattr.c | 14 +- + fs/ocfs2/xattr.h | 4 +- + fs/open.c | 18 +- + fs/overlayfs/super.c | 33 + + fs/pipe.c | 47 +- + fs/pnode.c | 32 +- + fs/proc/base.c | 3 +- + fs/proc/root.c | 7 + + fs/proc/task_mmu.c | 33 +- + fs/proc_namespace.c | 2 + + fs/quota/dquot.c | 3 +- + fs/splice.c | 3 + + fs/xfs/libxfs/xfs_alloc.c | 2 + + fs/xfs/libxfs/xfs_alloc_btree.c | 1 + + fs/xfs/libxfs/xfs_attr_leaf.c | 1 + + fs/xfs/libxfs/xfs_attr_remote.c | 1 + + fs/xfs/libxfs/xfs_bmap_btree.c | 1 + + fs/xfs/libxfs/xfs_da_btree.c | 1 + + fs/xfs/libxfs/xfs_dir2_block.c | 1 + + fs/xfs/libxfs/xfs_dir2_data.c | 2 + + fs/xfs/libxfs/xfs_dir2_leaf.c | 2 + + fs/xfs/libxfs/xfs_dir2_node.c | 1 + + fs/xfs/libxfs/xfs_dquot_buf.c | 37 +- + fs/xfs/libxfs/xfs_ialloc.c | 1 + + fs/xfs/libxfs/xfs_ialloc_btree.c | 1 + + fs/xfs/libxfs/xfs_inode_buf.c | 4 + + fs/xfs/libxfs/xfs_quota_defs.h | 2 +- + fs/xfs/libxfs/xfs_sb.c | 2 + + fs/xfs/libxfs/xfs_shared.h | 1 + + fs/xfs/libxfs/xfs_symlink_remote.c | 1 + + fs/xfs/xfs_attr_list.c | 19 +- + fs/xfs/xfs_buf.h | 1 + + fs/xfs/xfs_error.c | 4 +- + fs/xfs/xfs_fsops.c | 4 +- + fs/xfs/xfs_inode.c | 26 +- + fs/xfs/xfs_log_recover.c | 9 +- + fs/xfs/xfs_super.c | 10 + + include/asm-generic/bitops/lock.h | 14 +- + include/asm-generic/futex.h | 8 +- + include/asm-generic/preempt.h | 4 +- + include/asm-generic/qspinlock.h | 27 +- + include/asm-generic/siginfo.h | 15 - + include/drm/drm_cache.h | 2 + + include/linux/blkdev.h | 2 +- + include/linux/bpf.h | 3 +- + include/linux/can/dev.h | 22 +- + include/linux/cgroup-defs.h | 4 + + include/linux/clk-provider.h | 1 + + include/linux/clk/at91_pmc.h | 12 - + include/linux/compiler-gcc.h | 2 +- + include/linux/completion.h | 8 +- + include/linux/cpuset.h | 6 - + include/linux/dcache.h | 22 + + include/linux/device-mapper.h | 2 + + include/linux/filter.h | 4 + + include/linux/fs.h | 12 +- + include/linux/ftrace.h | 12 + + include/linux/hash.h | 20 +- + include/linux/hrtimer.h | 2 +- + include/linux/if_bridge.h | 4 - + include/linux/init_task.h | 3 +- + include/linux/irqchip/arm-gic-v3.h | 2 +- + include/linux/kernel.h | 15 +- + include/linux/kvm_host.h | 5 +- + include/linux/list_bl.h | 12 +- + include/linux/locallock.h | 6 +- + include/linux/mfd/samsung/s2mps11.h | 2 + + include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 1 + + include/linux/mlx5/device.h | 11 + + include/linux/mlx5/driver.h | 6 +- + include/linux/mm.h | 4 +- + include/linux/net.h | 10 +- + include/linux/netdevice.h | 22 +- + include/linux/netfilter/x_tables.h | 12 +- + include/linux/pci.h | 18 +- + include/linux/pipe_fs_i.h | 4 + + include/linux/platform_data/asoc-s3c.h | 4 + + include/linux/sched.h | 11 +- + include/linux/signal.h | 15 + + include/linux/skbuff.h | 41 + + include/linux/spinlock_rt.h | 25 +- + include/linux/suspend.h | 6 + + include/linux/swait.h | 173 +++++ + include/linux/thermal.h | 2 + + include/linux/tty.h | 4 +- + include/linux/usb.h | 2 +- + include/linux/usb_usual.h | 2 + + include/media/videobuf2-core.h | 1 + + include/net/bonding.h | 1 + + include/net/codel.h | 4 + + include/net/ip_tunnels.h | 1 + + include/net/ip_vs.h | 17 + + include/net/sch_generic.h | 20 +- + include/net/switchdev.h | 2 +- + include/rdma/ib.h | 16 + + include/scsi/scsi_device.h | 1 + + include/trace/events/hist.h | 1 + + include/trace/events/writeback.h | 121 ++- + include/uapi/linux/Kbuild | 1 + + include/uapi/linux/if.h | 28 + + include/uapi/linux/libc-compat.h | 44 ++ + include/uapi/linux/v4l2-dv-timings.h | 30 +- + include/video/imx-ipu-v3.h | 2 + + include/video/mxc_edid.h | 2 +- + include/xen/page.h | 4 +- + kernel/bpf/helpers.c | 2 +- + kernel/bpf/inode.c | 10 +- + kernel/bpf/syscall.c | 24 +- + kernel/bpf/verifier.c | 66 +- + kernel/cgroup.c | 34 +- + kernel/cpu.c | 4 +- + kernel/cpuset.c | 4 +- + kernel/events/core.c | 73 +- + kernel/events/ring_buffer.c | 10 +- + kernel/exit.c | 29 +- + kernel/fork.c | 5 +- + kernel/futex.c | 45 +- + kernel/irq/irqdesc.c | 21 +- + kernel/irq/manage.c | 2 +- + kernel/locking/lglock.c | 6 +- + kernel/locking/mcs_spinlock.h | 8 +- + kernel/locking/rt.c | 2 - + kernel/locking/rtmutex.c | 246 +++--- + kernel/panic.c | 45 +- + kernel/power/hibernate.c | 8 + + kernel/power/suspend.c | 5 + + kernel/printk/printk.c | 126 +-- + kernel/rcu/rcutorture.c | 7 + + kernel/rcu/tree.c | 24 +- + kernel/rcu/tree.h | 15 +- + kernel/rcu/tree_plugin.h | 26 +- + kernel/sched/Makefile | 2 +- + kernel/sched/completion.c | 10 +- + kernel/sched/core.c | 151 ++-- + kernel/sched/cputime.c | 84 +- + kernel/sched/fair.c | 182 ++--- + kernel/sched/loadavg.c | 11 +- + kernel/sched/sched.h | 13 + + kernel/sched/swait.c | 143 ++++ + kernel/sched/work-simple.c | 8 +- + kernel/softirq.c | 8 +- + kernel/stop_machine.c | 40 +- + kernel/sysctl.c | 14 + + kernel/sysctl_binary.c | 2 +- + kernel/time/tick-broadcast-hrtimer.c | 1 + + kernel/trace/ring_buffer.c | 35 +- + kernel/trace/trace.c | 5 +- + kernel/trace/trace_events.c | 9 +- + kernel/trace/trace_irqsoff.c | 16 +- + kernel/trace/trace_printk.c | 3 + + kernel/watchdog.c | 11 +- + kernel/workqueue.c | 40 + + lib/assoc_array.c | 4 +- + lib/dma-debug.c | 2 +- + lib/dump_stack.c | 4 +- + lib/lz4/lz4defs.h | 21 +- + lib/mpi/mpicoder.c | 39 +- + lib/test-string_helpers.c | 67 +- + localversion-rt | 2 +- + mm/backing-dev.c | 4 +- + mm/compaction.c | 10 +- + mm/huge_memory.c | 6 +- + mm/memcontrol.c | 84 +- + mm/memory.c | 40 + + mm/migrate.c | 8 +- + mm/page-writeback.c | 6 +- + mm/page_alloc.c | 50 +- + mm/page_isolation.c | 8 +- + mm/slub.c | 22 +- + mm/vmscan.c | 2 +- + mm/zsmalloc.c | 11 +- + mm/zswap.c | 8 +- + net/ax25/ax25_ip.c | 15 + + net/batman-adv/distributed-arp-table.c | 17 +- + net/batman-adv/routing.c | 9 + + net/batman-adv/send.c | 6 + + net/batman-adv/soft-interface.c | 8 +- + net/bluetooth/mgmt.c | 4 + + net/bridge/br_fdb.c | 2 + + net/bridge/br_ioctl.c | 5 +- + net/bridge/br_multicast.c | 12 +- + net/bridge/br_stp.c | 13 +- + net/core/dev.c | 6 +- + net/core/filter.c | 33 +- + net/core/rtnetlink.c | 19 +- + net/core/skbuff.c | 33 +- + net/dccp/ipv4.c | 2 - + net/decnet/dn_route.c | 9 +- + net/ipv4/devinet.c | 4 + + net/ipv4/fib_frontend.c | 26 +- + net/ipv4/fib_semantics.c | 2 + + net/ipv4/igmp.c | 3 +- + net/ipv4/ip_gre.c | 19 +- + net/ipv4/ip_output.c | 5 +- + net/ipv4/ip_tunnel.c | 23 +- + net/ipv4/netfilter/arp_tables.c | 326 +++----- + net/ipv4/netfilter/ip_tables.c | 356 +++------ + net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 12 +- + net/ipv4/route.c | 12 + + net/ipv4/tcp_ipv4.c | 2 - + net/ipv4/tcp_metrics.c | 2 +- + net/ipv4/tcp_minisocks.c | 3 +- + net/ipv4/tcp_output.c | 6 +- + net/ipv4/udp.c | 14 +- + net/ipv4/udp_tunnel.c | 2 + + net/ipv6/exthdrs_core.c | 6 +- + net/ipv6/ip6_gre.c | 2 + + net/ipv6/ip6_output.c | 19 +- + net/ipv6/ip6_tunnel.c | 4 +- + net/ipv6/mcast.c | 3 +- + net/ipv6/netfilter/ip6_tables.c | 349 +++------ + net/ipv6/reassembly.c | 6 +- + net/ipv6/route.c | 2 + + net/ipv6/tcp_ipv6.c | 4 +- + net/ipv6/udp.c | 12 +- + net/l2tp/l2tp_core.c | 2 +- + net/l2tp/l2tp_ip.c | 8 +- + net/l2tp/l2tp_ip6.c | 8 +- + net/llc/af_llc.c | 1 + + net/mac80211/ibss.c | 22 +- + net/mac80211/iface.c | 7 +- + net/mac80211/rx.c | 5 +- + net/mac80211/sta_info.c | 37 +- + net/mpls/af_mpls.c | 3 + + net/netfilter/ipvs/ip_vs_core.c | 37 +- + net/netfilter/ipvs/ip_vs_pe_sip.c | 6 +- + net/netfilter/nf_conntrack_core.c | 4 +- + net/netfilter/x_tables.c | 245 +++++- + net/netlink/af_netlink.c | 9 +- + net/openvswitch/actions.c | 12 +- + net/openvswitch/vport-netdev.c | 2 +- + net/openvswitch/vport-vxlan.c | 2 + + net/openvswitch/vport.h | 7 - + net/packet/af_packet.c | 38 +- + net/sched/sch_api.c | 8 +- + net/sched/sch_cbq.c | 12 +- + net/sched/sch_choke.c | 6 +- + net/sched/sch_codel.c | 10 +- + net/sched/sch_drr.c | 9 +- + net/sched/sch_dsmark.c | 11 +- + net/sched/sch_fq.c | 4 +- + net/sched/sch_fq_codel.c | 17 +- + net/sched/sch_generic.c | 5 +- + net/sched/sch_hfsc.c | 9 +- + net/sched/sch_hhf.c | 10 +- + net/sched/sch_htb.c | 24 +- + net/sched/sch_multiq.c | 16 +- + net/sched/sch_netem.c | 74 +- + net/sched/sch_pie.c | 5 +- + net/sched/sch_prio.c | 15 +- + net/sched/sch_qfq.c | 9 +- + net/sched/sch_red.c | 10 +- + net/sched/sch_sfb.c | 10 +- + net/sched/sch_sfq.c | 16 +- + net/sched/sch_tbf.c | 15 +- + net/sctp/ipv6.c | 2 + + net/socket.c | 38 +- + net/sunrpc/auth_gss/svcauth_gss.c | 4 +- + net/sunrpc/cache.c | 6 +- + net/switchdev/switchdev.c | 6 +- + net/tipc/netlink_compat.c | 2 +- + net/tipc/socket.c | 36 +- + net/vmw_vsock/af_vsock.c | 21 +- + net/wireless/nl80211.c | 2 +- + net/wireless/wext-core.c | 25 +- + net/x25/x25_facilities.c | 1 + + net/xfrm/xfrm_input.c | 3 + + samples/bpf/trace_output_kern.c | 1 - + scripts/Makefile.extrawarn | 1 + + scripts/coccinelle/iterators/use_after_iter.cocci | 2 +- + scripts/kconfig/Makefile | 4 +- + scripts/kconfig/confdata.c | 12 +- + scripts/package/Makefile | 4 +- + scripts/package/mkspec | 8 +- + sound/core/pcm_lib.c | 2 +- + sound/core/timer.c | 4 +- + sound/pci/hda/hda_generic.c | 6 +- + sound/pci/hda/hda_intel.c | 14 +- + sound/pci/hda/hda_sysfs.c | 8 - + sound/pci/hda/patch_cirrus.c | 22 +- + sound/pci/hda/patch_conexant.c | 7 +- + sound/pci/hda/patch_hdmi.c | 4 + + sound/pci/hda/patch_realtek.c | 180 ++++- + sound/pci/intel8x0.c | 1 + + sound/pci/pcxhr/pcxhr_core.c | 1 + + sound/soc/codecs/ak4642.c | 3 + + sound/soc/codecs/rt5640.c | 2 +- + sound/soc/codecs/rt5640.h | 36 +- + sound/soc/codecs/ssm4567.c | 5 + + sound/soc/fsl/fsl_esai.c | 8 +- + sound/soc/fsl/fsl_sai.c | 6 +- + sound/soc/fsl/fsl_spdif.c | 91 ++- + sound/soc/fsl/fsl_ssi.c | 6 +- + sound/soc/fsl/imx-hdmi-dma.c | 5 +- + sound/soc/fsl/imx-hdmi.c | 1 - + sound/soc/fsl/imx-pcm.h | 4 - + sound/soc/samsung/ac97.c | 26 +- + sound/soc/samsung/dma.h | 2 +- + sound/soc/samsung/dmaengine.c | 4 +- + sound/soc/samsung/i2s.c | 26 +- + sound/soc/samsung/pcm.c | 20 +- + sound/soc/samsung/s3c-i2s-v2.c | 2 +- + sound/soc/samsung/s3c-i2s-v2.h | 2 +- + sound/soc/samsung/s3c2412-i2s.c | 4 +- + sound/soc/samsung/s3c24xx-i2s.c | 4 +- + sound/soc/samsung/spdif.c | 10 +- + sound/soc/soc-dapm.c | 7 + + sound/usb/clock.c | 2 + + sound/usb/endpoint.c | 3 + + sound/usb/mixer_maps.c | 14 + + sound/usb/mixer_quirks.c | 4 + + sound/usb/pcm.c | 2 + + sound/usb/quirks.c | 32 +- + sound/usb/stream.c | 6 +- + tools/hv/Makefile | 2 + + tools/lib/traceevent/parse-filter.c | 4 +- + tools/perf/Documentation/perf-stat.txt | 8 + + tools/perf/tests/bpf.c | 14 +- + tools/perf/tests/llvm.c | 8 +- + tools/perf/ui/browsers/hists.c | 10 +- + tools/perf/util/event.c | 2 +- + tools/perf/util/evlist.c | 4 +- + tools/perf/util/intel-pt.c | 2 +- + tools/perf/util/parse-events.c | 6 +- + tools/perf/util/pmu.c | 15 +- + tools/perf/util/setup.py | 4 + + virt/kvm/arm/arch_timer.c | 49 +- + virt/kvm/async_pf.c | 4 +- + virt/kvm/irqchip.c | 2 +- + virt/kvm/kvm_main.c | 38 +- + 1129 files changed, 19122 insertions(+), 9086 deletions(-) + create mode 100644 arch/arm/boot/dts/imx6dl-udoo-15lvds.dts + create mode 100644 arch/arm/boot/dts/imx6dl-udoo-7lvds.dts + create mode 100644 arch/arm/boot/dts/imx6q-udoo-15lvds.dts + create mode 100644 arch/arm/boot/dts/imx6q-udoo-7lvds.dts + create mode 100644 arch/sparc/kernel/urtt_fill.S + create mode 100644 drivers/gpu/galcore/allocator/default/gc_hal_kernel_allocator_dmabuf.c + create mode 100644 drivers/gpu/galcore/gc_hal_kernel_mutex.h + create mode 100644 include/linux/swait.h + create mode 100644 kernel/sched/swait.c + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index c2340ee..c000832 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -30,6 +30,10 @@ Optional properties: + - target-supply : regulator for SATA target power + - phys : reference to the SATA PHY node + - phy-names : must be "sata-phy" ++- ports-implemented : Mask that indicates which ports that the HBA supports ++ are available for software to use. Useful if PORTS_IMPL ++ is not programmed by the BIOS, which is true with ++ some embedded SOC's. + + Required properties when using sub-nodes: + - #address-cells : number of cells to encode an address +diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.txt b/Documentation/devicetree/bindings/clock/imx35-clock.txt +index a703564..f497832 100644 +--- a/Documentation/devicetree/bindings/clock/imx35-clock.txt ++++ b/Documentation/devicetree/bindings/clock/imx35-clock.txt +@@ -94,6 +94,7 @@ clocks and IDs. + csi_sel 79 + iim_gate 80 + gpu2d_gate 81 ++ ckli_gate 82 + + Examples: + +diff --git a/Documentation/devicetree/bindings/pinctrl/img,pistachio-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/img,pistachio-pinctrl.txt +index 08a4a32..0326154 100644 +--- a/Documentation/devicetree/bindings/pinctrl/img,pistachio-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/img,pistachio-pinctrl.txt +@@ -134,12 +134,12 @@ mfio80 ddr_debug, mips_trace_data, mips_debug + mfio81 dreq0, mips_trace_data, eth_debug + mfio82 dreq1, mips_trace_data, eth_debug + mfio83 mips_pll_lock, mips_trace_data, usb_debug +-mfio84 sys_pll_lock, mips_trace_data, usb_debug +-mfio85 wifi_pll_lock, mips_trace_data, sdhost_debug +-mfio86 bt_pll_lock, mips_trace_data, sdhost_debug +-mfio87 rpu_v_pll_lock, dreq2, socif_debug +-mfio88 rpu_l_pll_lock, dreq3, socif_debug +-mfio89 audio_pll_lock, dreq4, dreq5 ++mfio84 audio_pll_lock, mips_trace_data, usb_debug ++mfio85 rpu_v_pll_lock, mips_trace_data, sdhost_debug ++mfio86 rpu_l_pll_lock, mips_trace_data, sdhost_debug ++mfio87 sys_pll_lock, dreq2, socif_debug ++mfio88 wifi_pll_lock, dreq3, socif_debug ++mfio89 bt_pll_lock, dreq4, dreq5 + tck + trstn + tdi +diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt +index d3b6b5f..80a6ee9 100644 +--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt ++++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt +@@ -41,6 +41,10 @@ Required properties: + will be in use as default, or the big endian mode + will be in use for all the device registers. + ++ - fsl,dma-buffer-size: It specify the audio buffer size of playback and ++ capture. If this property is absent, using the default value of audio buffer ++ size. ++ + Example: + + esai: esai@02024000 { +diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt +index b5ee32e..89dfabd 100644 +--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt ++++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt +@@ -32,6 +32,10 @@ Required properties: + will be in use as default, or the big endian mode + will be in use for all the device registers. + ++ - fsl,dma-buffer-size: It specify the audio buffer size of playback and ++ capture. If this property is absent, using the default value of audio buffer ++ size. ++ + Example: + + spdif: spdif@02004000 { +diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt +index 5b76be4..3ad1096 100644 +--- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt ++++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt +@@ -62,6 +62,10 @@ Optional properties: + "ac97-slave" - AC97 mode, SSI is clock slave + "ac97-master" - AC97 mode, SSI is clock master + ++- fsl,dma-buffer-size: It specify the audio buffer size of playback and ++ capture. If this property is absent, using the default value of audio buffer ++ size. ++ + Child 'codec' node required properties: + - compatible: Compatible list, contains the name of the codec + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 742f69d..26b5f39 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1629,6 +1629,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + ip= [IP_PNP] + See Documentation/filesystems/nfs/nfsroot.txt. + ++ irqaffinity= [SMP] Set the default irq affinity mask ++ Format: ++ ,..., ++ or ++ - ++ (must be a positive range in ascending order) ++ or a mixture ++ ,...,- ++ + irqfixup [HW] + When an interrupt is not handled search all handlers + for it. Intended to get systems with badly broken +@@ -3928,6 +3937,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + sector if the number is odd); + i = IGNORE_DEVICE (don't bind to this + device); ++ j = NO_REPORT_LUNS (don't use report luns ++ command, uas only); + l = NOT_LOCKABLE (don't try to lock and + unlock ejectable media); + m = MAX_SECTORS_64 (don't transfer more +diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt +index bc3842d..e2dea3d 100644 +--- a/Documentation/serial/tty.txt ++++ b/Documentation/serial/tty.txt +@@ -213,9 +213,6 @@ TTY_IO_ERROR If set, causes all subsequent userspace read/write + + TTY_OTHER_CLOSED Device is a pty and the other side has closed. + +-TTY_OTHER_DONE Device is a pty and the other side has closed and +- all pending input processing has been completed. +- + TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into + smaller chunks. + +diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt +index 88152f2..302b5ed 100644 +--- a/Documentation/sysctl/fs.txt ++++ b/Documentation/sysctl/fs.txt +@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: + - nr_open + - overflowuid + - overflowgid ++- pipe-user-pages-hard ++- pipe-user-pages-soft + - protected_hardlinks + - protected_symlinks + - suid_dumpable +@@ -159,6 +161,27 @@ The default is 65534. + + ============================================================== + ++pipe-user-pages-hard: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes. ++Once this limit is reached, no new pipes may be allocated until usage goes ++below the limit again. When set to 0, no limit is applied, which is the default ++setting. ++ ++============================================================== ++ ++pipe-user-pages-soft: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes ++before the pipe size gets limited to a single page. Once this limit is reached, ++new pipes will be limited to a single page in size for this user in order to ++limit total memory usage, and trying to increase them using fcntl() will be ++denied until usage goes below the limit again. The default value allows to ++allocate up to 1024 pipes at their default size. When set to 0, no limit is ++applied. ++ ++============================================================== ++ + protected_hardlinks: + + A long-standing class of security issues is the hardlink-based +diff --git a/MAINTAINERS b/MAINTAINERS +index d826f1b..ab65bbe 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -230,13 +230,13 @@ F: kernel/sys_ni.c + + ABIT UGURU 1,2 HARDWARE MONITOR DRIVER + M: Hans de Goede +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/abituguru.c + + ABIT UGURU 3 HARDWARE MONITOR DRIVER + M: Alistair John Strachan +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/abituguru3.c + +@@ -373,14 +373,14 @@ S: Maintained + + ADM1025 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/adm1025 + F: drivers/hwmon/adm1025.c + + ADM1029 HARDWARE MONITOR DRIVER + M: Corentin Labbe +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/adm1029.c + +@@ -425,7 +425,7 @@ F: drivers/video/backlight/adp8860_bl.c + + ADS1015 HARDWARE MONITOR DRIVER + M: Dirk Eibach +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/ads1015 + F: drivers/hwmon/ads1015.c +@@ -438,7 +438,7 @@ F: drivers/macintosh/therm_adt746x.c + + ADT7475 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/adt7475 + F: drivers/hwmon/adt7475.c +@@ -615,7 +615,7 @@ F: include/linux/ccp.h + + AMD FAM15H PROCESSOR POWER MONITORING DRIVER + M: Andreas Herrmann +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/fam15h_power + F: drivers/hwmon/fam15h_power.c +@@ -779,7 +779,7 @@ F: drivers/input/mouse/bcm5974.c + + APPLE SMC DRIVER + M: Henrik Rydberg +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Odd fixes + F: drivers/hwmon/applesmc.c + +@@ -1777,7 +1777,7 @@ F: include/media/as3645a.h + + ASC7621 HARDWARE MONITOR DRIVER + M: George Joseph +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/asc7621 + F: drivers/hwmon/asc7621.c +@@ -1864,7 +1864,7 @@ F: drivers/net/wireless/ath/carl9170/ + + ATK0110 HWMON DRIVER + M: Luca Tettamanti +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/asus_atk0110.c + +@@ -2984,7 +2984,7 @@ F: mm/swap_cgroup.c + + CORETEMP HARDWARE MONITORING DRIVER + M: Fenghua Yu +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/coretemp + F: drivers/hwmon/coretemp.c +@@ -3549,7 +3549,7 @@ T: git git://git.infradead.org/users/vkoul/slave-dma.git + + DME1737 HARDWARE MONITOR DRIVER + M: Juerg Haefliger +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/dme1737 + F: drivers/hwmon/dme1737.c +@@ -4097,8 +4097,8 @@ F: Documentation/efi-stub.txt + F: arch/ia64/kernel/efi.c + F: arch/x86/boot/compressed/eboot.[ch] + F: arch/x86/include/asm/efi.h +-F: arch/x86/platform/efi/* +-F: drivers/firmware/efi/* ++F: arch/x86/platform/efi/ ++F: drivers/firmware/efi/ + F: include/linux/efi*.h + + EFI VARIABLE FILESYSTEM +@@ -4262,7 +4262,7 @@ F: include/video/exynos_mipi* + + F71805F HARDWARE MONITORING DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/f71805f + F: drivers/hwmon/f71805f.c +@@ -4341,7 +4341,7 @@ F: fs/* + + FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER + M: Riku Voipio +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/f75375s.c + F: include/linux/f75375s.h +@@ -4883,8 +4883,8 @@ F: drivers/media/usb/hackrf/ + HARDWARE MONITORING + M: Jean Delvare + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org +-W: http://www.lm-sensors.org/ ++L: linux-hwmon@vger.kernel.org ++W: http://hwmon.wiki.kernel.org/ + T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/ + T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git + S: Maintained +@@ -5393,7 +5393,7 @@ F: drivers/usb/atm/ueagle-atm.c + + INA209 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/ina209 + F: Documentation/devicetree/bindings/i2c/ina209.txt +@@ -5401,7 +5401,7 @@ F: drivers/hwmon/ina209.c + + INA2XX HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/ina2xx + F: drivers/hwmon/ina2xx.c +@@ -5884,7 +5884,7 @@ F: drivers/isdn/hardware/eicon/ + + IT87 HARDWARE MONITORING DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/it87 + F: drivers/hwmon/it87.c +@@ -5920,7 +5920,7 @@ F: drivers/media/dvb-frontends/ix2505v* + + JC42.4 TEMPERATURE SENSOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/jc42.c + F: Documentation/hwmon/jc42 +@@ -5970,14 +5970,14 @@ F: drivers/tty/serial/jsm/ + + K10TEMP HARDWARE MONITORING DRIVER + M: Clemens Ladisch +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/k10temp + F: drivers/hwmon/k10temp.c + + K8TEMP HARDWARE MONITORING DRIVER + M: Rudolf Marek +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/k8temp + F: drivers/hwmon/k8temp.c +@@ -6485,27 +6485,27 @@ F: net/llc/ + + LM73 HARDWARE MONITOR DRIVER + M: Guillaume Ligneul +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/lm73.c + + LM78 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/lm78 + F: drivers/hwmon/lm78.c + + LM83 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/lm83 + F: drivers/hwmon/lm83.c + + LM90 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/lm90 + F: Documentation/devicetree/bindings/hwmon/lm90.txt +@@ -6513,7 +6513,7 @@ F: drivers/hwmon/lm90.c + + LM95234 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/lm95234 + F: drivers/hwmon/lm95234.c +@@ -6580,7 +6580,7 @@ F: drivers/scsi/sym53c8xx_2/ + + LTC4261 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/ltc4261 + F: drivers/hwmon/ltc4261.c +@@ -6749,28 +6749,28 @@ F: include/uapi/linux/matroxfb.h + + MAX16065 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/max16065 + F: drivers/hwmon/max16065.c + + MAX20751 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/max20751 + F: drivers/hwmon/max20751.c + + MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER + M: "Hans J. Koch" +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/max6650 + F: drivers/hwmon/max6650.c + + MAX6697 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/max6697 + F: Documentation/devicetree/bindings/i2c/max6697.txt +@@ -7303,7 +7303,7 @@ F: drivers/scsi/NCR_D700.* + + NCT6775 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/nct6775 + F: drivers/hwmon/nct6775.c +@@ -8064,7 +8064,7 @@ F: drivers/video/logo/logo_parisc* + + PC87360 HARDWARE MONITORING DRIVER + M: Jim Cromie +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/pc87360 + F: drivers/hwmon/pc87360.c +@@ -8076,7 +8076,7 @@ F: drivers/char/pc8736x_gpio.c + + PC87427 HARDWARE MONITORING DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/pc87427 + F: drivers/hwmon/pc87427.c +@@ -8415,8 +8415,8 @@ F: drivers/rtc/rtc-puv3.c + + PMBUS HARDWARE MONITORING DRIVERS + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org +-W: http://www.lm-sensors.org/ ++L: linux-hwmon@vger.kernel.org ++W: http://hwmon.wiki.kernel.org/ + W: http://www.roeck-us.net/linux/drivers/ + T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git + S: Maintained +@@ -8610,7 +8610,7 @@ F: drivers/media/usb/pwc/* + + PWM FAN DRIVER + M: Kamil Debski +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Supported + F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt + F: Documentation/hwmon/pwm-fan +@@ -9882,28 +9882,28 @@ F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt + + SMM665 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/smm665 + F: drivers/hwmon/smm665.c + + SMSC EMC2103 HARDWARE MONITOR DRIVER + M: Steve Glendinning +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/emc2103 + F: drivers/hwmon/emc2103.c + + SMSC SCH5627 HARDWARE MONITOR DRIVER + M: Hans de Goede +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Supported + F: Documentation/hwmon/sch5627 + F: drivers/hwmon/sch5627.c + + SMSC47B397 HARDWARE MONITOR DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/smsc47b397 + F: drivers/hwmon/smsc47b397.c +@@ -10830,7 +10830,7 @@ F: include/linux/mmc/sh_mobile_sdhi.h + + TMP401 HARDWARE MONITOR DRIVER + M: Guenter Roeck +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/tmp401 + F: drivers/hwmon/tmp401.c +@@ -11564,14 +11564,14 @@ F: Documentation/networking/vrf.txt + + VT1211 HARDWARE MONITOR DRIVER + M: Juerg Haefliger +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/vt1211 + F: drivers/hwmon/vt1211.c + + VT8231 HARDWARE MONITOR DRIVER + M: Roger Lucas +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/vt8231.c + +@@ -11590,21 +11590,21 @@ F: drivers/w1/ + + W83791D HARDWARE MONITORING DRIVER + M: Marc Hulsman +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/w83791d + F: drivers/hwmon/w83791d.c + + W83793 HARDWARE MONITORING DRIVER + M: Rudolf Marek +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: Documentation/hwmon/w83793 + F: drivers/hwmon/w83793.c + + W83795 HARDWARE MONITORING DRIVER + M: Jean Delvare +-L: lm-sensors@lm-sensors.org ++L: linux-hwmon@vger.kernel.org + S: Maintained + F: drivers/hwmon/w83795.c + +diff --git a/Makefile b/Makefile +index 87d12b4..ce2ce88 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 6 ++SUBLEVEL = 14 + EXTRAVERSION = + NAME = Blurry Fish Butt + +@@ -364,7 +364,7 @@ AFLAGS_MODULE = + LDFLAGS_MODULE = + CFLAGS_KERNEL = + AFLAGS_KERNEL = +-CFLAGS_GCOV = -fprofile-arcs -ftest-coverage ++CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im + + + # Use USERINCLUDE when you must reference the UAPI directories only. +@@ -682,9 +682,10 @@ KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,) + KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) + else + +-# This warning generated too much noise in a regular build. +-# Use make W=1 to enable this warning (see scripts/Makefile.build) ++# These warnings generated too much noise in a regular build. ++# Use make W=1 to enable them (see scripts/Makefile.build) + KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) ++KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) + endif + + ifdef CONFIG_FRAME_POINTER +@@ -767,6 +768,9 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=strict-prototypes) + # Prohibit date/time macros, which would make the build non-deterministic + KBUILD_CFLAGS += $(call cc-option,-Werror=date-time) + ++# enforce correct pointer usage ++KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types) ++ + # use the deterministic mode of AR if available + KBUILD_ARFLAGS := $(call ar-option,D) + +diff --git a/arch/Kconfig b/arch/Kconfig +index 81592b3..3b26d76 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -53,6 +53,7 @@ config KPROBES + config JUMP_LABEL + bool "Optimize very unlikely/likely branches" + depends on HAVE_ARCH_JUMP_LABEL ++ depends on (!INTERRUPT_OFF_HIST && !PREEMPT_OFF_HIST && !WAKEUP_LATENCY_HIST && !MISSED_TIMER_OFFSETS_HIST) + help + This option enables a transparent branch optimization that + makes certain almost-always-true or almost-always-false branch +diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h +index 57c1f33..0352fb8 100644 +--- a/arch/arc/include/asm/bitops.h ++++ b/arch/arc/include/asm/bitops.h +@@ -35,21 +35,6 @@ static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\ + \ + m += nr >> 5; \ + \ +- /* \ +- * ARC ISA micro-optimization: \ +- * \ +- * Instructions dealing with bitpos only consider lower 5 bits \ +- * e.g (x << 33) is handled like (x << 1) by ASL instruction \ +- * (mem pointer still needs adjustment to point to next word) \ +- * \ +- * Hence the masking to clamp @nr arg can be elided in general. \ +- * \ +- * However if @nr is a constant (above assumed in a register), \ +- * and greater than 31, gcc can optimize away (x << 33) to 0, \ +- * as overflow, given the 32-bit ISA. Thus masking needs to be \ +- * done for const @nr, but no code is generated due to gcc \ +- * const prop. \ +- */ \ + nr &= 0x1f; \ + \ + __asm__ __volatile__( \ +diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h +index 694ece8..cb69299 100644 +--- a/arch/arc/include/asm/io.h ++++ b/arch/arc/include/asm/io.h +@@ -13,6 +13,15 @@ + #include + #include + ++#ifdef CONFIG_ISA_ARCV2 ++#include ++#define __iormb() rmb() ++#define __iowmb() wmb() ++#else ++#define __iormb() do { } while (0) ++#define __iowmb() do { } while (0) ++#endif ++ + extern void __iomem *ioremap(unsigned long physaddr, unsigned long size); + extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size, + unsigned long flags); +@@ -22,6 +31,15 @@ extern void iounmap(const void __iomem *addr); + #define ioremap_wc(phy, sz) ioremap(phy, sz) + #define ioremap_wt(phy, sz) ioremap(phy, sz) + ++/* ++ * io{read,write}{16,32}be() macros ++ */ ++#define ioread16be(p) ({ u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) ++#define ioread32be(p) ({ u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) ++ ++#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); }) ++#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); }) ++ + /* Change struct page to physical address */ + #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) + +@@ -99,15 +117,6 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr) + + } + +-#ifdef CONFIG_ISA_ARCV2 +-#include +-#define __iormb() rmb() +-#define __iowmb() wmb() +-#else +-#define __iormb() do { } while (0) +-#define __iowmb() do { } while (0) +-#endif +- + /* + * MMIO can also get buffered/optimized in micro-arch, so barriers needed + * Based on ARM model for the typical use case +@@ -129,15 +138,23 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr) + #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) + + /* +- * Relaxed API for drivers which can handle any ordering themselves ++ * Relaxed API for drivers which can handle barrier ordering themselves ++ * ++ * Also these are defined to perform little endian accesses. ++ * To provide the typical device register semantics of fixed endian, ++ * swap the byte order for Big Endian ++ * ++ * http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de + */ + #define readb_relaxed(c) __raw_readb(c) +-#define readw_relaxed(c) __raw_readw(c) +-#define readl_relaxed(c) __raw_readl(c) ++#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ ++ __raw_readw(c)); __r; }) ++#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ ++ __raw_readl(c)); __r; }) + + #define writeb_relaxed(v,c) __raw_writeb(v,c) +-#define writew_relaxed(v,c) __raw_writew(v,c) +-#define writel_relaxed(v,c) __raw_writel(v,c) ++#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c) ++#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) + + #include + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index d240cee..e20073a 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -308,6 +308,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ + imx6dl-tx6u-801x.dtb \ + imx6dl-tx6u-811x.dtb \ + imx6dl-udoo.dtb \ ++ imx6dl-udoo-7lvds.dtb \ ++ imx6dl-udoo-15lvds.dtb \ + imx6dl-sbc-fx6.dtb \ + imx6dl-sbc-fx6m.dtb \ + imx6dl-wandboard.dtb \ +@@ -351,6 +353,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ + imx6q-tx6q-1020-comtft.dtb \ + imx6q-tx6q-1110.dtb \ + imx6q-udoo.dtb \ ++ imx6q-udoo-7lvds.dtb \ ++ imx6q-udoo-15lvds.dtb \ + imx6q-wandboard.dtb \ + imx6q-wandboard-revb1.dtb \ + imx6dl-vero.dtb +diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts +index 47954ed..00707aa 100644 +--- a/arch/arm/boot/dts/am43x-epos-evm.dts ++++ b/arch/arm/boot/dts/am43x-epos-evm.dts +@@ -792,3 +792,8 @@ + tx-num-evt = <32>; + rx-num-evt = <32>; + }; ++ ++&synctimer_32kclk { ++ assigned-clocks = <&mux_synctimer32k_ck>; ++ assigned-clock-parents = <&clkdiv32k_ick>; ++}; +diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi +index 7ccce75..cc952cf 100644 +--- a/arch/arm/boot/dts/armada-375.dtsi ++++ b/arch/arm/boot/dts/armada-375.dtsi +@@ -529,7 +529,7 @@ + }; + + sata@a0000 { +- compatible = "marvell,orion-sata"; ++ compatible = "marvell,armada-370-sata"; + reg = <0xa0000 0x5000>; + interrupts = ; + clocks = <&gateclk 14>, <&gateclk 20>; +diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi +index c2d87f5..dd079d0 100644 +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -117,7 +117,7 @@ + }; + + /* USB part of the eSATA/USB 2.0 port */ +- usb@50000 { ++ usb@58000 { + status = "okay"; + }; + +diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts +index ff888d2..f3e2b96 100644 +--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts ++++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts +@@ -303,6 +303,7 @@ + regulator-name = "mmc0-card-supply"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; ++ regulator-always-on; + }; + + gpio_keys { +diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts +index 569026e..da84e65 100644 +--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts ++++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts +@@ -268,5 +268,6 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_reg>; ++ regulator-always-on; + }; + }; +diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi +index 0827d59..cd0cd5f 100644 +--- a/arch/arm/boot/dts/at91sam9x5.dtsi ++++ b/arch/arm/boot/dts/at91sam9x5.dtsi +@@ -106,7 +106,7 @@ + + pmc: pmc@fffffc00 { + compatible = "atmel,at91sam9x5-pmc", "syscon"; +- reg = <0xfffffc00 0x100>; ++ reg = <0xfffffc00 0x200>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + interrupt-controller; + #address-cells = <1>; +diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts +index a50be64..59411e4 100644 +--- a/arch/arm/boot/dts/exynos4210-trats.dts ++++ b/arch/arm/boot/dts/exynos4210-trats.dts +@@ -298,6 +298,8 @@ + compatible = "maxim,max8997-pmic"; + + reg = <0x66>; ++ interrupt-parent = <&gpx0>; ++ interrupts = <7 0>; + + max8997,pmic-buck1-uses-gpio-dvs; + max8997,pmic-buck2-uses-gpio-dvs; +diff --git a/arch/arm/boot/dts/imx6dl-udoo-15lvds.dts b/arch/arm/boot/dts/imx6dl-udoo-15lvds.dts +new file mode 100644 +index 0000000..3b2c7ce +--- /dev/null ++++ b/arch/arm/boot/dts/imx6dl-udoo-15lvds.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * Author: Fabio Estevam ++ * Author: Ettore Chimenti ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++/dts-v1/; ++#include "imx6dl.dtsi" ++#include "imx6qdl-udoo.dtsi" ++ ++/ { ++ model = "Udoo i.MX6 Dual-lite Board"; ++ compatible = "udoo,imx6dl-udoo", "fsl,imx6dl"; ++ ++ mxcfb2: fb@1 { ++ compatible = "fsl,mxc_sdc_fb"; ++ disp_dev = "ldb"; ++ interface_pix_fmt = "RGB24"; ++ mode_str = "1360x768M@60"; ++ default_bpp = <32>; ++ int_clk = <0>; ++ late_init = <1>; ++ status = "okay"; ++ }; ++ ++ regulators { ++ reg_lcd0_pwr: regulator@1 { ++ status = "okay"; ++ }; ++ ++ reg_lcd0_backlight: regulator@2 { ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&dcic1 { ++ status = "disabled"; ++}; ++ ++&dcic2 { ++ dcic_id = <0>; ++ status = "okay"; ++}; ++ ++&ldb { ++ status = "okay"; ++ ++ lvds-channel@0 { ++ status = "okay"; ++ fsl,data-width = <24>; ++ ++ display-timings { ++ native-mode = <&timing2>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/imx6dl-udoo-7lvds.dts b/arch/arm/boot/dts/imx6dl-udoo-7lvds.dts +new file mode 100644 +index 0000000..65114b7 +--- /dev/null ++++ b/arch/arm/boot/dts/imx6dl-udoo-7lvds.dts +@@ -0,0 +1,58 @@ ++/* ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * Author: Fabio Estevam ++ * Author: Ettore Chimenti ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++/dts-v1/; ++#include "imx6dl.dtsi" ++#include "imx6qdl-udoo.dtsi" ++ ++/ { ++ model = "Udoo i.MX6 Dual-lite Board"; ++ compatible = "udoo,imx6dl-udoo", "fsl,imx6dl"; ++ ++ mxcfb2: fb@1 { ++ compatible = "fsl,mxc_sdc_fb"; ++ disp_dev = "ldb"; ++ interface_pix_fmt = "RGB666"; ++ mode_str = "800x480M@60"; ++ default_bpp = <32>; ++ int_clk = <0>; ++ late_init = <0>; ++ status = "okay"; ++ }; ++ ++ regulators { ++ reg_lcd0_pwr: regulator@1 { ++ status = "okay"; ++ }; ++ ++ reg_lcd0_backlight: regulator@2 { ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&dcic1 { ++ status = "disabled"; ++}; ++ ++&dcic2 { ++ dcic_id = <0>; ++ status = "okay"; ++}; ++ ++&ldb { ++ status = "okay"; ++ ++ lvds-channel@0 { ++ status = "okay"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts +index 5645d52..a910249 100644 +--- a/arch/arm/boot/dts/imx6q-tbs2910.dts ++++ b/arch/arm/boot/dts/imx6q-tbs2910.dts +@@ -154,7 +154,7 @@ + status = "okay"; + }; + +-&hdmi { ++&hdmi_core { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hdmi>; + ddc-i2c-bus = <&i2c2>; +diff --git a/arch/arm/boot/dts/imx6q-udoo-15lvds.dts b/arch/arm/boot/dts/imx6q-udoo-15lvds.dts +new file mode 100644 +index 0000000..182c696 +--- /dev/null ++++ b/arch/arm/boot/dts/imx6q-udoo-15lvds.dts +@@ -0,0 +1,67 @@ ++/* ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * Author: Fabio Estevam ++ * Author: Ettore Chimenti ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++/dts-v1/; ++#include "imx6q.dtsi" ++#include "imx6qdl-udoo.dtsi" ++ ++/ { ++ model = "Udoo i.MX6 Quad Board"; ++ compatible = "udoo,imx6q-udoo", "fsl,imx6q"; ++ ++ mxcfb2: fb@1 { ++ compatible = "fsl,mxc_sdc_fb"; ++ disp_dev = "ldb"; ++ interface_pix_fmt = "RGB24"; ++ mode_str = "1360x768M@60"; ++ default_bpp = <32>; ++ int_clk = <0>; ++ late_init = <1>; ++ status = "okay"; ++ }; ++ ++ regulators { ++ reg_lcd0_pwr: regulator@1 { ++ status = "okay"; ++ }; ++ ++ reg_lcd0_backlight: regulator@2 { ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&sata { ++ status = "okay"; ++}; ++ ++&dcic1 { ++ status = "disabled"; ++}; ++ ++&dcic2 { ++ dcic_id = <0>; ++ status = "okay"; ++}; ++ ++&ldb { ++ status = "okay"; ++ ++ lvds-channel@0 { ++ status = "okay"; ++ fsl,data-width = <24>; ++ ++ display-timings { ++ native-mode = <&timing2>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/imx6q-udoo-7lvds.dts b/arch/arm/boot/dts/imx6q-udoo-7lvds.dts +new file mode 100644 +index 0000000..5ba2ff2 +--- /dev/null ++++ b/arch/arm/boot/dts/imx6q-udoo-7lvds.dts +@@ -0,0 +1,62 @@ ++/* ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * Author: Fabio Estevam ++ * Author: Ettore Chimenti ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++/dts-v1/; ++#include "imx6q.dtsi" ++#include "imx6qdl-udoo.dtsi" ++ ++/ { ++ model = "Udoo i.MX6 Quad Board"; ++ compatible = "udoo,imx6q-udoo", "fsl,imx6q"; ++ ++ mxcfb2: fb@1 { ++ compatible = "fsl,mxc_sdc_fb"; ++ disp_dev = "ldb"; ++ interface_pix_fmt = "RGB666"; ++ mode_str = "800x480M@60"; ++ default_bpp = <32>; ++ int_clk = <0>; ++ late_init = <0>; ++ status = "okay"; ++ }; ++ ++ regulators { ++ reg_lcd0_pwr: regulator@1 { ++ status = "okay"; ++ }; ++ ++ reg_lcd0_backlight: regulator@2 { ++ status = "okay"; ++ }; ++ }; ++}; ++ ++&sata { ++ status = "okay"; ++}; ++ ++&dcic1 { ++ status = "disabled"; ++}; ++ ++&dcic2 { ++ dcic_id = <0>; ++ status = "okay"; ++}; ++ ++&ldb { ++ status = "okay"; ++ ++ lvds-channel@0 { ++ status = "okay"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +index 7c64e72..4c201c6 100755 +--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +@@ -202,7 +202,7 @@ + &dcic2 { + dcic_id = <1>; + dcic_mux = "dcic-lvds1"; +- status = "okay"; ++ status = "disabled"; + }; + + &gpc { // General power controller +@@ -254,9 +254,9 @@ + vsync-len = <2>; + }; + +- timing2: 1366x768 { // 15.6" display ++ timing2: 1360x768 { // 15.6" display + clock-frequency = <76000000>; +- hactive = <1366>; ++ hactive = <1360>; // IPU needs x and y modulo 8 + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; +diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi +index 5e2c93e..74fb390 100644 +--- a/arch/arm/boot/dts/imx6qdl.dtsi ++++ b/arch/arm/boot/dts/imx6qdl.dtsi +@@ -242,12 +242,12 @@ + <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_DUMMY>, + <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>, + <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>, +- <&clks IMX6QDL_CLK_DUMMY>; ++ <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_SPBA>; + clock-names = "core", "rxtx0", + "rxtx1", "rxtx2", + "rxtx3", "rxtx4", + "rxtx5", "rxtx6", +- "rxtx7"; ++ "rxtx7", "dma"; + status = "disabled"; + }; + +@@ -1126,6 +1126,7 @@ + compatible = "fsl,imx6q-vdoa"; + reg = <0x021e4000 0x4000>; + interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "vdoa"; + clocks = <&clks IMX6QDL_CLK_VDOA>; + iram = <&ocram>; + }; +diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi +index cf6998a..564341a 100644 +--- a/arch/arm/boot/dts/pxa3xx.dtsi ++++ b/arch/arm/boot/dts/pxa3xx.dtsi +@@ -30,7 +30,7 @@ + reg = <0x43100000 90>; + interrupts = <45>; + clocks = <&clks CLK_NAND>; +- dmas = <&pdma 97>; ++ dmas = <&pdma 97 3>; + dma-names = "data"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h +index b0c912f..8a394f3 100644 +--- a/arch/arm/boot/dts/sama5d2-pinfunc.h ++++ b/arch/arm/boot/dts/sama5d2-pinfunc.h +@@ -837,8 +837,8 @@ + #define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4) + #define PIN_PD24 120 + #define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) +-#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD23, 1, 2) +-#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD23, 3, 3) ++#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD24, 1, 2) ++#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD24, 3, 3) + #define PIN_PD25 121 + #define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) + #define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3) +diff --git a/arch/arm/configs/xbian_defconfig_imx6_mvebu b/arch/arm/configs/xbian_defconfig_imx6_mvebu +index 2bc59d8..83cda36 100644 +--- a/arch/arm/configs/xbian_defconfig_imx6_mvebu ++++ b/arch/arm/configs/xbian_defconfig_imx6_mvebu +@@ -1,6 +1,6 @@ + # + # Automatically generated file; DO NOT EDIT. +-# Linux/arm 4.4.1 Kernel Configuration ++# Linux/arm 4.4.6 Kernel Configuration + # + CONFIG_ARM=y + CONFIG_ARM_HAS_SG_CHAIN=y +@@ -83,7 +83,7 @@ CONFIG_NO_HZ_COMMON=y + # CONFIG_HZ_PERIODIC is not set + CONFIG_NO_HZ_IDLE=y + # CONFIG_NO_HZ_FULL is not set +-CONFIG_NO_HZ=y ++# CONFIG_NO_HZ is not set + CONFIG_HIGH_RES_TIMERS=y + + # +@@ -104,12 +104,12 @@ CONFIG_RCU_EXPERT=y + CONFIG_SRCU=y + # CONFIG_TASKS_RCU is not set + CONFIG_RCU_STALL_COMMON=y +-CONFIG_RCU_FANOUT=16 +-CONFIG_RCU_FANOUT_LEAF=8 ++CONFIG_RCU_FANOUT=8 ++CONFIG_RCU_FANOUT_LEAF=2 + # CONFIG_TREE_RCU_TRACE is not set + CONFIG_RCU_BOOST=y + CONFIG_RCU_KTHREAD_PRIO=1 +-CONFIG_RCU_BOOST_DELAY=500 ++CONFIG_RCU_BOOST_DELAY=300 + CONFIG_RCU_NOCB_CPU=y + CONFIG_RCU_NOCB_CPU_NONE=y + # CONFIG_RCU_NOCB_CPU_ZERO is not set +@@ -166,7 +166,6 @@ CONFIG_MULTIUSER=y + CONFIG_SYSFS_SYSCALL=y + CONFIG_SYSCTL_SYSCALL=y + CONFIG_KALLSYMS=y +-CONFIG_KALLSYMS_ALL=y + CONFIG_PRINTK=y + CONFIG_BUG=y + CONFIG_BASE_FULL=y +@@ -178,7 +177,7 @@ CONFIG_EVENTFD=y + # CONFIG_BPF_SYSCALL is not set + CONFIG_SHMEM=y + CONFIG_AIO=y +-# CONFIG_ADVISE_SYSCALLS is not set ++CONFIG_ADVISE_SYSCALLS=y + CONFIG_USERFAULTFD=y + CONFIG_PCI_QUIRKS=y + CONFIG_MEMBARRIER=y +@@ -190,7 +189,6 @@ CONFIG_PERF_USE_VMALLOC=y + # Kernel Performance Events And Counters + # + CONFIG_PERF_EVENTS=y +-# CONFIG_DEBUG_PERF_USE_VMALLOC is not set + # CONFIG_VM_EVENT_COUNTERS is not set + # CONFIG_SLUB_DEBUG is not set + CONFIG_COMPAT_BRK=y +@@ -248,8 +246,8 @@ CONFIG_MODULES=y + # CONFIG_MODULE_FORCE_LOAD is not set + CONFIG_MODULE_UNLOAD=y + # CONFIG_MODULE_FORCE_UNLOAD is not set +-CONFIG_MODVERSIONS=y +-CONFIG_MODULE_SRCVERSION_ALL=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set + # CONFIG_MODULE_SIG is not set + # CONFIG_MODULE_COMPRESS is not set + CONFIG_MODULES_TREE_LOOKUP=y +@@ -490,7 +488,6 @@ CONFIG_PCI_DOMAINS=y + CONFIG_PCI_DOMAINS_GENERIC=y + CONFIG_PCI_SYSCALL=y + CONFIG_PCI_MSI=y +-# CONFIG_PCI_DEBUG is not set + CONFIG_PCI_REALLOC_ENABLE_AUTO=y + CONFIG_PCI_STUB=y + CONFIG_PCI_ATS=y +@@ -587,14 +584,12 @@ CONFIG_MIGRATION=y + CONFIG_ZONE_DMA_FLAG=1 + CONFIG_BOUNCE=y + # CONFIG_KSM is not set +-CONFIG_DEFAULT_MMAP_MIN_ADDR=16384 +-CONFIG_CLEANCACHE=y +-CONFIG_FRONTSWAP=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=8192 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set + CONFIG_CMA=y +-# CONFIG_CMA_DEBUG is not set + # CONFIG_CMA_DEBUGFS is not set + CONFIG_CMA_AREAS=7 +-# CONFIG_ZSWAP is not set + # CONFIG_ZPOOL is not set + # CONFIG_ZBUD is not set + # CONFIG_ZSMALLOC is not set +@@ -699,14 +694,18 @@ CONFIG_BINFMT_MISC=m + CONFIG_SUSPEND=y + CONFIG_SUSPEND_FREEZER=y + # CONFIG_SUSPEND_SKIP_SYNC is not set +-# CONFIG_HIBERNATION is not set ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" + CONFIG_PM_SLEEP=y + CONFIG_PM_SLEEP_SMP=y + # CONFIG_PM_AUTOSLEEP is not set +-# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM_WAKELOCKS=y ++CONFIG_PM_WAKELOCKS_LIMIT=100 ++CONFIG_PM_WAKELOCKS_GC=y + CONFIG_PM=y + # CONFIG_PM_DEBUG is not set +-# CONFIG_APM_EMULATION is not set ++CONFIG_APM_EMULATION=y + CONFIG_PM_OPP=y + CONFIG_PM_CLK=y + CONFIG_PM_GENERIC_DOMAINS=y +@@ -777,7 +776,7 @@ CONFIG_INET_UDP_DIAG=m + CONFIG_TCP_CONG_ADVANCED=y + CONFIG_TCP_CONG_BIC=m + CONFIG_TCP_CONG_CUBIC=m +-CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_WESTWOOD=y + CONFIG_TCP_CONG_HTCP=m + CONFIG_TCP_CONG_HSTCP=m + CONFIG_TCP_CONG_HYBLA=m +@@ -789,9 +788,10 @@ CONFIG_TCP_CONG_YEAH=y + CONFIG_TCP_CONG_ILLINOIS=m + CONFIG_TCP_CONG_DCTCP=m + # CONFIG_TCP_CONG_CDG is not set +-CONFIG_DEFAULT_VEGAS=y ++# CONFIG_DEFAULT_VEGAS is not set ++CONFIG_DEFAULT_WESTWOOD=y + # CONFIG_DEFAULT_RENO is not set +-CONFIG_DEFAULT_TCP_CONG="vegas" ++CONFIG_DEFAULT_TCP_CONG="westwood" + CONFIG_TCP_MD5SIG=y + CONFIG_IPV6=m + CONFIG_IPV6_ROUTER_PREF=y +@@ -821,7 +821,7 @@ CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y + CONFIG_IPV6_PIMSM_V2=y + # CONFIG_NETWORK_SECMARK is not set + CONFIG_NET_PTP_CLASSIFY=y +-# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETWORK_PHY_TIMESTAMPING=y + CONFIG_NETFILTER=y + # CONFIG_NETFILTER_DEBUG is not set + CONFIG_NETFILTER_ADVANCED=y +@@ -1153,20 +1153,15 @@ CONFIG_INET_DCCP_DIAG=m + CONFIG_IP_DCCP_CCID3=y + # CONFIG_IP_DCCP_CCID3_DEBUG is not set + CONFIG_IP_DCCP_TFRC_LIB=y +- +-# +-# DCCP Kernel Hacking +-# +-# CONFIG_IP_DCCP_DEBUG is not set + CONFIG_IP_SCTP=m + # CONFIG_SCTP_DBG_OBJCNT is not set +-CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y ++# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set + # CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +-# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +-CONFIG_SCTP_COOKIE_HMAC_MD5=y +-CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y ++# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set ++# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set + CONFIG_RDS=m +-# CONFIG_RDS_TCP is not set ++CONFIG_RDS_TCP=m + # CONFIG_RDS_DEBUG is not set + CONFIG_TIPC=m + CONFIG_TIPC_MEDIA_UDP=y +@@ -1177,6 +1172,8 @@ CONFIG_L2TP_V3=y + CONFIG_L2TP_IP=m + CONFIG_L2TP_ETH=m + CONFIG_STP=m ++CONFIG_GARP=m ++CONFIG_MRP=m + CONFIG_BRIDGE=m + CONFIG_BRIDGE_IGMP_SNOOPING=y + CONFIG_BRIDGE_VLAN_FILTERING=y +@@ -1185,8 +1182,8 @@ CONFIG_NET_DSA=y + CONFIG_NET_DSA_HWMON=y + CONFIG_NET_DSA_TAG_EDSA=y + CONFIG_VLAN_8021Q=m +-# CONFIG_VLAN_8021Q_GVRP is not set +-# CONFIG_VLAN_8021Q_MVRP is not set ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_VLAN_8021Q_MVRP=y + # CONFIG_DECNET is not set + CONFIG_LLC=m + CONFIG_LLC2=m +@@ -1197,7 +1194,7 @@ CONFIG_IPDDP=m + CONFIG_IPDDP_ENCAP=y + # CONFIG_X25 is not set + # CONFIG_LAPB is not set +-# CONFIG_PHONET is not set ++CONFIG_PHONET=m + # CONFIG_6LOWPAN is not set + # CONFIG_IEEE802154 is not set + CONFIG_NET_SCHED=y +@@ -1286,7 +1283,7 @@ CONFIG_NET_MPLS_GSO=m + # CONFIG_MPLS_ROUTING is not set + # CONFIG_HSR is not set + CONFIG_NET_SWITCHDEV=y +-# CONFIG_NET_L3_MASTER_DEV is not set ++CONFIG_NET_L3_MASTER_DEV=y + CONFIG_RPS=y + CONFIG_RFS_ACCEL=y + CONFIG_XPS=y +@@ -1403,7 +1400,6 @@ CONFIG_BT_CMTP=m + CONFIG_BT_HIDP=y + CONFIG_BT_HS=y + CONFIG_BT_LE=y +-# CONFIG_BT_SELFTEST is not set + # CONFIG_BT_DEBUGFS is not set + + # +@@ -1523,8 +1519,6 @@ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y + CONFIG_WANT_DEV_COREDUMP=y + CONFIG_ALLOW_DEV_COREDUMP=y + CONFIG_DEV_COREDUMP=y +-# CONFIG_DEBUG_DRIVER is not set +-# CONFIG_DEBUG_DEVRES is not set + # CONFIG_SYS_HYPERVISOR is not set + # CONFIG_GENERIC_CPU_DEVICES is not set + CONFIG_SOC_BUS=y +@@ -2043,9 +2037,9 @@ CONFIG_DM_VERITY=m + # CONFIG_FIREWIRE is not set + # CONFIG_FIREWIRE_NOSY is not set + CONFIG_NETDEVICES=y +-CONFIG_MII=y ++CONFIG_MII=m + CONFIG_NET_CORE=y +-CONFIG_BONDING=y ++CONFIG_BONDING=m + CONFIG_DUMMY=m + CONFIG_EQUALIZER=m + # CONFIG_NET_FC is not set +@@ -2070,6 +2064,7 @@ CONFIG_TUN=m + CONFIG_VETH=m + # CONFIG_VIRTIO_NET is not set + CONFIG_NLMON=m ++# CONFIG_NET_VRF is not set + # CONFIG_ARCNET is not set + + # +@@ -2096,7 +2091,7 @@ CONFIG_NET_DSA_MV88E6XXX=y + CONFIG_NET_DSA_MV88E6352=y + # CONFIG_NET_DSA_BCM_SF2 is not set + CONFIG_ETHERNET=y +-CONFIG_MDIO=y ++CONFIG_MDIO=m + # CONFIG_NET_VENDOR_3COM is not set + # CONFIG_NET_VENDOR_ADAPTEC is not set + # CONFIG_NET_VENDOR_AGERE is not set +@@ -2105,11 +2100,11 @@ CONFIG_MDIO=y + # CONFIG_NET_VENDOR_AMD is not set + # CONFIG_NET_VENDOR_ARC is not set + CONFIG_NET_VENDOR_ATHEROS=y +-CONFIG_ATL2=y +-CONFIG_ATL1=y +-CONFIG_ATL1E=y +-CONFIG_ATL1C=y +-CONFIG_ALX=y ++CONFIG_ATL2=m ++CONFIG_ATL1=m ++CONFIG_ATL1E=m ++CONFIG_ATL1C=m ++CONFIG_ALX=m + # CONFIG_NET_VENDOR_AURORA is not set + # CONFIG_NET_CADENCE is not set + # CONFIG_NET_VENDOR_BROADCOM is not set +@@ -2129,7 +2124,7 @@ CONFIG_ALX=y + CONFIG_NET_VENDOR_FREESCALE=y + CONFIG_FEC=y + CONFIG_FSL_PQ_MDIO=y +-CONFIG_FSL_XGMAC_MDIO=y ++# CONFIG_FSL_XGMAC_MDIO is not set + CONFIG_GIANFAR=y + # CONFIG_NET_VENDOR_HISILICON is not set + # CONFIG_NET_VENDOR_HP is not set +@@ -2279,6 +2274,7 @@ CONFIG_USB_NET_KALMIA=m + CONFIG_USB_NET_QMI_WWAN=m + CONFIG_USB_HSO=m + CONFIG_USB_NET_INT51X1=m ++# CONFIG_USB_CDC_PHONET is not set + CONFIG_USB_IPHETH=m + CONFIG_USB_SIERRA_NET=m + CONFIG_USB_VL600=m +@@ -2471,24 +2467,9 @@ CONFIG_RT2X00_LIB_LEDS=y + # CONFIG_RT2X00_DEBUG is not set + CONFIG_WL_MEDIATEK=y + CONFIG_MT7601U=m +-CONFIG_RTL_CARDS=m +-CONFIG_RTL8192CE=m +-CONFIG_RTL8192SE=m +-CONFIG_RTL8192DE=m +-CONFIG_RTL8723AE=m +-CONFIG_RTL8723BE=m +-CONFIG_RTL8188EE=m +-CONFIG_RTL8192EE=m +-CONFIG_RTL8821AE=m ++CONFIG_RTL8XXXU=m ++CONFIG_RTL8XXXU_UNTESTED=y + CONFIG_RTL8192CU=m +-CONFIG_RTLWIFI=m +-CONFIG_RTLWIFI_PCI=m +-CONFIG_RTLWIFI_USB=m +-CONFIG_RTLWIFI_DEBUG=y +-CONFIG_RTL8192C_COMMON=m +-CONFIG_RTL8723_COMMON=m +-CONFIG_RTLBTCOEXIST=m +-# CONFIG_RTL8XXXU is not set + CONFIG_WL_TI=y + CONFIG_WL1251=m + CONFIG_WL1251_SPI=m +@@ -2619,6 +2600,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 + CONFIG_INPUT_JOYDEV=m + CONFIG_INPUT_EVDEV=y + CONFIG_INPUT_EVBUG=m ++# CONFIG_INPUT_APMPOWER is not set + + # + # Input Device Drivers +@@ -3007,7 +2989,6 @@ CONFIG_I2C_SLAVE_EEPROM=m + # CONFIG_I2C_DEBUG_ALGO is not set + # CONFIG_I2C_DEBUG_BUS is not set + CONFIG_SPI=y +-# CONFIG_SPI_DEBUG is not set + CONFIG_SPI_MASTER=y + + # +@@ -3016,8 +2997,8 @@ CONFIG_SPI_MASTER=y + # CONFIG_SPI_ALTERA is not set + CONFIG_SPI_BITBANG=y + # CONFIG_SPI_CADENCE is not set +-CONFIG_SPI_GPIO=y +-CONFIG_SPI_IMX=m ++# CONFIG_SPI_GPIO is not set ++CONFIG_SPI_IMX=y + # CONFIG_SPI_FSL_SPI is not set + # CONFIG_SPI_OC_TINY is not set + CONFIG_SPI_ORION=m +@@ -3043,13 +3024,14 @@ CONFIG_SPI_SPIDEV=y + # + CONFIG_PPS=y + # CONFIG_PPS_DEBUG is not set ++CONFIG_NTP_PPS=y + + # + # PPS clients support + # + # CONFIG_PPS_CLIENT_KTIMER is not set +-CONFIG_PPS_CLIENT_LDISC=m +-CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_PPS_CLIENT_LDISC=y ++CONFIG_PPS_CLIENT_GPIO=y + + # + # PPS generators support +@@ -3060,10 +3042,7 @@ CONFIG_PPS_CLIENT_GPIO=m + # + CONFIG_PTP_1588_CLOCK=y + CONFIG_PTP_1588_CLOCK_GIANFAR=y +- +-# +-# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +-# ++# CONFIG_DP83640_PHY is not set + CONFIG_PINCTRL=y + + # +@@ -3072,7 +3051,6 @@ CONFIG_PINCTRL=y + CONFIG_PINMUX=y + CONFIG_PINCONF=y + CONFIG_GENERIC_PINCONF=y +-# CONFIG_DEBUG_PINCTRL is not set + # CONFIG_PINCTRL_AMD is not set + CONFIG_PINCTRL_SINGLE=y + CONFIG_PINCTRL_IMX=y +@@ -3087,7 +3065,6 @@ CONFIG_GPIOLIB=y + CONFIG_GPIO_DEVRES=y + CONFIG_OF_GPIO=y + CONFIG_GPIOLIB_IRQCHIP=y +-# CONFIG_DEBUG_GPIO is not set + CONFIG_GPIO_SYSFS=y + CONFIG_GPIO_GENERIC=y + +@@ -3101,6 +3078,7 @@ CONFIG_GPIO_74XX_MMIO=y + CONFIG_GPIO_GENERIC_PLATFORM=y + # CONFIG_GPIO_GRGPIO is not set + CONFIG_GPIO_MVEBU=y ++CONFIG_GPIO_MVEBU_PWM=y + CONFIG_GPIO_MXC=y + CONFIG_GPIO_SYSCON=y + # CONFIG_GPIO_VX855 is not set +@@ -3181,6 +3159,7 @@ CONFIG_W1_SLAVE_BQ27000=m + CONFIG_POWER_SUPPLY=y + # CONFIG_POWER_SUPPLY_DEBUG is not set + # CONFIG_PDA_POWER is not set ++# CONFIG_APM_POWER is not set + # CONFIG_GENERIC_ADC_BATTERY is not set + CONFIG_TEST_POWER=m + # CONFIG_BATTERY_88PM860X is not set +@@ -4830,7 +4809,7 @@ CONFIG_USB_XHCI_MVEBU=y + CONFIG_USB_EHCI_HCD=y + CONFIG_USB_EHCI_ROOT_HUB_TT=y + CONFIG_USB_EHCI_TT_NEWSCHED=y +-CONFIG_USB_FSL_MPH_DR_OF=m ++CONFIG_USB_FSL_MPH_DR_OF=y + CONFIG_USB_EHCI_PCI=y + CONFIG_USB_EHCI_MXC=y + CONFIG_USB_EHCI_HCD_ORION=y +@@ -5044,7 +5023,6 @@ CONFIG_USB_ISP1301=y + CONFIG_USB_MXS_PHY=y + # CONFIG_USB_ULPI is not set + CONFIG_USB_GADGET=y +-# CONFIG_USB_GADGET_DEBUG is not set + # CONFIG_USB_GADGET_DEBUG_FILES is not set + # CONFIG_USB_GADGET_DEBUG_FS is not set + CONFIG_USB_GADGET_VBUS_DRAW=2 +@@ -5053,7 +5031,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + # + # USB Peripheral Controller + # +-CONFIG_USB_FSL_USB2=m ++CONFIG_USB_FSL_USB2=y + # CONFIG_USB_FUSB300 is not set + # CONFIG_USB_FOTG210_UDC is not set + # CONFIG_USB_GR_UDC is not set +@@ -5099,6 +5077,7 @@ CONFIG_USB_CONFIGFS_ECM=y + CONFIG_USB_CONFIGFS_ECM_SUBSET=y + CONFIG_USB_CONFIGFS_RNDIS=y + CONFIG_USB_CONFIGFS_EEM=y ++# CONFIG_USB_CONFIGFS_PHONET is not set + CONFIG_USB_CONFIGFS_MASS_STORAGE=y + CONFIG_USB_CONFIGFS_F_LB_SS=y + CONFIG_USB_CONFIGFS_F_FS=y +@@ -5126,6 +5105,7 @@ CONFIG_USB_G_SERIAL=m + CONFIG_USB_MIDI_GADGET=m + CONFIG_USB_G_PRINTER=m + CONFIG_USB_CDC_COMPOSITE=m ++# CONFIG_USB_G_NOKIA is not set + CONFIG_USB_G_ACM_MS=m + CONFIG_USB_G_MULTI=m + CONFIG_USB_G_MULTI_RNDIS=y +@@ -5531,11 +5511,14 @@ CONFIG_DVB_MN88473=m + CONFIG_LIRC_STAGING=y + CONFIG_LIRC_BT829=m + CONFIG_LIRC_IMON=m ++CONFIG_LIRC_HB=m ++CONFIG_LIRC_XBOX=m + CONFIG_LIRC_SASEM=m + CONFIG_LIRC_SERIAL=m + CONFIG_LIRC_SERIAL_TRANSMITTER=y + CONFIG_LIRC_SIR=m + CONFIG_LIRC_ZILOG=m ++CONFIG_LIRC_ATIUSB=m + + # + # Android +@@ -6177,7 +6160,6 @@ CONFIG_NFSD_V3=y + CONFIG_NFSD_V3_ACL=y + CONFIG_NFSD_V4=y + # CONFIG_NFSD_PNFS is not set +-# CONFIG_NFSD_FAULT_INJECTION is not set + CONFIG_GRACE_PERIOD=y + CONFIG_LOCKD=y + CONFIG_LOCKD_V4=y +@@ -6274,83 +6256,47 @@ CONFIG_DLM=m + # + CONFIG_PRINTK_TIME=y + CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +-# CONFIG_BOOT_PRINTK_DELAY is not set + CONFIG_DYNAMIC_DEBUG=y + + # + # Compile-time checks and compiler options + # +-# CONFIG_DEBUG_INFO is not set + CONFIG_ENABLE_WARN_DEPRECATED=y + CONFIG_ENABLE_MUST_CHECK=y + CONFIG_FRAME_WARN=1024 + CONFIG_STRIP_ASM_SYMS=y +-# CONFIG_READABLE_ASM is not set + # CONFIG_UNUSED_SYMBOLS is not set +-# CONFIG_PAGE_OWNER is not set + CONFIG_DEBUG_FS=y + # CONFIG_HEADERS_CHECK is not set + # CONFIG_DEBUG_SECTION_MISMATCH is not set + CONFIG_SECTION_MISMATCH_WARN_ONLY=y + CONFIG_FRAME_POINTER=y +-# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set + CONFIG_MAGIC_SYSRQ=y + CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +-CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_KERNEL is not set + + # + # Memory Debugging + # + # CONFIG_PAGE_EXTENSION is not set +-# CONFIG_DEBUG_PAGEALLOC is not set +-# CONFIG_DEBUG_OBJECTS is not set + # CONFIG_SLUB_STATS is not set + CONFIG_HAVE_DEBUG_KMEMLEAK=y +-# CONFIG_DEBUG_KMEMLEAK is not set +-# CONFIG_DEBUG_STACK_USAGE is not set +-# CONFIG_DEBUG_VM is not set + # CONFIG_DEBUG_MEMORY_INIT is not set +-# CONFIG_DEBUG_PER_CPU_MAPS is not set +-# CONFIG_DEBUG_HIGHMEM is not set +-# CONFIG_DEBUG_SHIRQ is not set + + # + # Debug Lockups and Hangs + # +-# CONFIG_LOCKUP_DETECTOR is not set +-# CONFIG_DETECT_HUNG_TASK is not set + CONFIG_PANIC_ON_OOPS=y + CONFIG_PANIC_ON_OOPS_VALUE=1 + CONFIG_PANIC_TIMEOUT=1 +-# CONFIG_SCHED_DEBUG is not set + # CONFIG_SCHED_INFO is not set +-# CONFIG_SCHEDSTATS is not set +-# CONFIG_SCHED_STACK_END_CHECK is not set + # CONFIG_DEBUG_TIMEKEEPING is not set +-CONFIG_TIMER_STATS=y +-# CONFIG_DEBUG_PREEMPT is not set + + # + # Lock Debugging (spinlocks, mutexes, etc...) + # +-# CONFIG_DEBUG_RT_MUTEXES is not set +-# CONFIG_DEBUG_SPINLOCK is not set +-# CONFIG_DEBUG_MUTEXES is not set +-# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +-# CONFIG_DEBUG_LOCK_ALLOC is not set +-# CONFIG_PROVE_LOCKING is not set +-# CONFIG_LOCK_STAT is not set +-# CONFIG_DEBUG_ATOMIC_SLEEP is not set +-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +-# CONFIG_LOCK_TORTURE_TEST is not set + CONFIG_STACKTRACE=y +-# CONFIG_DEBUG_KOBJECT is not set +-# CONFIG_DEBUG_BUGVERBOSE is not set +-# CONFIG_DEBUG_LIST is not set +-# CONFIG_DEBUG_PI_LIST is not set +-# CONFIG_DEBUG_SG is not set +-# CONFIG_DEBUG_NOTIFIERS is not set +-# CONFIG_DEBUG_CREDENTIALS is not set ++CONFIG_DEBUG_BUGVERBOSE=y + + # + # RCU Debugging +@@ -6358,13 +6304,7 @@ CONFIG_STACKTRACE=y + # CONFIG_PROVE_RCU is not set + # CONFIG_SPARSE_RCU_POINTER is not set + # CONFIG_TORTURE_TEST is not set +-# CONFIG_RCU_TORTURE_TEST is not set + CONFIG_RCU_CPU_STALL_TIMEOUT=21 +-# CONFIG_RCU_TRACE is not set +-# CONFIG_RCU_EQS_DEBUG is not set +-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +-# CONFIG_NOTIFIER_ERROR_INJECTION is not set +-# CONFIG_FAULT_INJECTION is not set + CONFIG_NOP_TRACER=y + CONFIG_HAVE_FUNCTION_TRACER=y + CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +@@ -6409,11 +6349,6 @@ CONFIG_FTRACE_MCOUNT_RECORD=y + # Runtime Testing + # + # CONFIG_LKDTM is not set +-# CONFIG_TEST_LIST_SORT is not set +-# CONFIG_BACKTRACE_SELF_TEST is not set +-# CONFIG_RBTREE_TEST is not set +-# CONFIG_INTERVAL_TREE_TEST is not set +-# CONFIG_PERCPU_TEST is not set + # CONFIG_ATOMIC64_SELFTEST is not set + # CONFIG_ASYNC_RAID6_TEST is not set + # CONFIG_TEST_HEXDUMP is not set +@@ -6431,17 +6366,13 @@ CONFIG_FTRACE_MCOUNT_RECORD=y + # CONFIG_TEST_STATIC_KEYS is not set + # CONFIG_SAMPLES is not set + CONFIG_HAVE_ARCH_KGDB=y +-# CONFIG_KGDB is not set +-# CONFIG_ARM_PTDUMP is not set + # CONFIG_STRICT_DEVMEM is not set + CONFIG_ARM_UNWIND=y + CONFIG_OLD_MCOUNT=y + # CONFIG_DEBUG_USER is not set +-# CONFIG_DEBUG_LL is not set + CONFIG_DEBUG_IMX_UART_PORT=1 + CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" + # CONFIG_DEBUG_UART_8250 is not set +-# CONFIG_DEBUG_UART_BCM63XX is not set + CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" + # CONFIG_PID_IN_CONTEXTIDR is not set + # CONFIG_DEBUG_SET_MODULE_RONX is not set +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index d66b1ae..d044cea 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -244,7 +244,11 @@ svc_preempt: + bne 1b + tst r0, #_TIF_NEED_RESCHED_LAZY + reteq r8 @ go again +- b 1b ++ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count ++ teq r0, #0 @ if preempt lazy count != 0 ++ beq 1b ++ ret r8 @ go again ++ + #endif + + __und_fault: +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index ef9119f..4d93758 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target, + if (ret) + return ret; + +- vfp_flush_hwstate(thread); + thread->vfpstate.hard = new_vfp; ++ vfp_flush_hwstate(thread); + + return 0; + } +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index 4f5c42a..bb43bc3 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -498,16 +498,16 @@ static void kvm_arm_resume_guest(struct kvm *kvm) + struct kvm_vcpu *vcpu; + + kvm_for_each_vcpu(i, vcpu, kvm) { +- struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); ++ struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); + + vcpu->arch.pause = false; +- swait_wake_interruptible(wq); ++ swake_up(wq); + } + } + + static void vcpu_sleep(struct kvm_vcpu *vcpu) + { +- struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); ++ struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); + + swait_event_interruptible(*wq, ((!vcpu->arch.power_off) && + (!vcpu->arch.pause))); +@@ -568,7 +568,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + * involves poking the GIC, which must be done in a + * non-preemptible context. + */ +- preempt_disable(); ++ migrate_disable(); + kvm_timer_flush_hwstate(vcpu); + kvm_vgic_flush_hwstate(vcpu); + +@@ -587,7 +587,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + local_irq_enable(); + kvm_timer_sync_hwstate(vcpu); + kvm_vgic_sync_hwstate(vcpu); +- preempt_enable(); ++ migrate_enable(); + continue; + } + +@@ -641,7 +641,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + + kvm_vgic_sync_hwstate(vcpu); + +- preempt_enable(); ++ migrate_enable(); + + ret = handle_exit(vcpu, run, ret); + } +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 61d96a6..12d727f 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -886,11 +886,14 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache + VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd)); + + old_pmd = *pmd; +- kvm_set_pmd(pmd, *new_pmd); +- if (pmd_present(old_pmd)) ++ if (pmd_present(old_pmd)) { ++ pmd_clear(pmd); + kvm_tlb_flush_vmid_ipa(kvm, addr); +- else ++ } else { + get_page(virt_to_page(pmd)); ++ } ++ ++ kvm_set_pmd(pmd, *new_pmd); + return 0; + } + +@@ -939,12 +942,14 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, + + /* Create 2nd stage page table mapping - Level 3 */ + old_pte = *pte; +- kvm_set_pte(pte, *new_pte); +- if (pte_present(old_pte)) ++ if (pte_present(old_pte)) { ++ kvm_set_pte(pte, __pte(0)); + kvm_tlb_flush_vmid_ipa(kvm, addr); +- else ++ } else { + get_page(virt_to_page(pte)); ++ } + ++ kvm_set_pte(pte, *new_pte); + return 0; + } + +diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c +index 08148c4..c2b1315 100644 +--- a/arch/arm/kvm/psci.c ++++ b/arch/arm/kvm/psci.c +@@ -70,7 +70,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + { + struct kvm *kvm = source_vcpu->kvm; + struct kvm_vcpu *vcpu = NULL; +- struct swait_head *wq; ++ struct swait_queue_head *wq; + unsigned long cpu_id; + unsigned long context_id; + phys_addr_t target_pc; +@@ -119,7 +119,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + smp_mb(); /* Make sure the above is visible */ + + wq = kvm_arch_vcpu_wq(vcpu); +- swait_wake_interruptible(wq); ++ swake_up(wq); + + return PSCI_RET_SUCCESS; + } +diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig +index 28656c2..3f50130 100644 +--- a/arch/arm/mach-at91/Kconfig ++++ b/arch/arm/mach-at91/Kconfig +@@ -99,6 +99,7 @@ config HAVE_AT91_USB_CLK + config COMMON_CLK_AT91 + bool + select COMMON_CLK ++ select MFD_SYSCON + + config HAVE_AT91_SMD + bool +diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c +index c1a7c6c..63b4fa2 100644 +--- a/arch/arm/mach-at91/at91rm9200.c ++++ b/arch/arm/mach-at91/at91rm9200.c +@@ -12,7 +12,6 @@ + #include + + #include +-#include + + #include "generic.h" + #include "soc.h" +@@ -33,7 +32,6 @@ static void __init at91rm9200_dt_device_init(void) + + of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); + +- arm_pm_idle = at91rm9200_idle; + at91rm9200_pm_init(); + } + +diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c +index 7eb64f7..cada2a6 100644 +--- a/arch/arm/mach-at91/at91sam9.c ++++ b/arch/arm/mach-at91/at91sam9.c +@@ -62,8 +62,6 @@ static void __init at91sam9_common_init(void) + soc_dev = soc_device_to_device(soc); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); +- +- arm_pm_idle = at91sam9_idle; + } + + static void __init at91sam9_dt_device_init(void) +diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h +index b0fa7dc..28ca57a 100644 +--- a/arch/arm/mach-at91/generic.h ++++ b/arch/arm/mach-at91/generic.h +@@ -11,27 +11,18 @@ + #ifndef _AT91_GENERIC_H + #define _AT91_GENERIC_H + +-#include +-#include +- +- /* Map io */ +-extern void __init at91_map_io(void); +-extern void __init at91_alt_map_io(void); +- +-/* idle */ +-extern void at91rm9200_idle(void); +-extern void at91sam9_idle(void); +- + #ifdef CONFIG_PM + extern void __init at91rm9200_pm_init(void); + extern void __init at91sam9260_pm_init(void); + extern void __init at91sam9g45_pm_init(void); + extern void __init at91sam9x5_pm_init(void); ++extern void __init sama5_pm_init(void); + #else + static inline void __init at91rm9200_pm_init(void) { } + static inline void __init at91sam9260_pm_init(void) { } + static inline void __init at91sam9g45_pm_init(void) { } + static inline void __init at91sam9x5_pm_init(void) { } ++static inline void __init sama5_pm_init(void) { } + #endif + + #endif /* _AT91_GENERIC_H */ +diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c +index 23726fb..f062701 100644 +--- a/arch/arm/mach-at91/pm.c ++++ b/arch/arm/mach-at91/pm.c +@@ -31,10 +31,13 @@ + #include + #include + #include ++#include + + #include "generic.h" + #include "pm.h" + ++static void __iomem *pmc; ++ + /* + * FIXME: this is needed to communicate between the pinctrl driver and + * the PM implementation in the machine. Possibly part of the PM +@@ -87,7 +90,7 @@ static int at91_pm_verify_clocks(void) + unsigned long scsr; + int i; + +- scsr = at91_pmc_read(AT91_PMC_SCSR); ++ scsr = readl(pmc + AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { +@@ -101,8 +104,7 @@ static int at91_pm_verify_clocks(void) + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; +- +- css = at91_pmc_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; ++ css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); + return 0; +@@ -145,8 +147,8 @@ static void at91_pm_suspend(suspend_state_t state) + flush_cache_all(); + outer_disable(); + +- at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], +- at91_ramc_base[1], pm_data); ++ at91_suspend_sram_fn(pmc, at91_ramc_base[0], ++ at91_ramc_base[1], pm_data); + + outer_resume(); + } +@@ -353,6 +355,21 @@ static __init void at91_dt_ramc(void) + at91_pm_set_standby(standby); + } + ++void at91rm9200_idle(void) ++{ ++ /* ++ * Disable the processor clock. The processor will be automatically ++ * re-enabled by an interrupt or by a reset. ++ */ ++ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); ++} ++ ++void at91sam9_idle(void) ++{ ++ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); ++ cpu_do_idle(); ++} ++ + static void __init at91_pm_sram_init(void) + { + struct gen_pool *sram_pool; +@@ -399,13 +416,36 @@ static void __init at91_pm_sram_init(void) + &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); + } + +-static void __init at91_pm_init(void) ++static const struct of_device_id atmel_pmc_ids[] __initconst = { ++ { .compatible = "atmel,at91rm9200-pmc" }, ++ { .compatible = "atmel,at91sam9260-pmc" }, ++ { .compatible = "atmel,at91sam9g45-pmc" }, ++ { .compatible = "atmel,at91sam9n12-pmc" }, ++ { .compatible = "atmel,at91sam9x5-pmc" }, ++ { .compatible = "atmel,sama5d3-pmc" }, ++ { .compatible = "atmel,sama5d2-pmc" }, ++ { /* sentinel */ }, ++}; ++ ++static void __init at91_pm_init(void (*pm_idle)(void)) + { +- at91_pm_sram_init(); ++ struct device_node *pmc_np; + + if (at91_cpuidle_device.dev.platform_data) + platform_device_register(&at91_cpuidle_device); + ++ pmc_np = of_find_matching_node(NULL, atmel_pmc_ids); ++ pmc = of_iomap(pmc_np, 0); ++ if (!pmc) { ++ pr_err("AT91: PM not supported, PMC not found\n"); ++ return; ++ } ++ ++ if (pm_idle) ++ arm_pm_idle = pm_idle; ++ ++ at91_pm_sram_init(); ++ + if (at91_suspend_sram_fn) + suspend_set_ops(&at91_pm_ops); + else +@@ -424,7 +464,7 @@ void __init at91rm9200_pm_init(void) + at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_MC; + +- at91_pm_init(); ++ at91_pm_init(at91rm9200_idle); + } + + void __init at91sam9260_pm_init(void) +@@ -432,7 +472,7 @@ void __init at91sam9260_pm_init(void) + at91_dt_ramc(); + at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); + } + + void __init at91sam9g45_pm_init(void) +@@ -440,7 +480,7 @@ void __init at91sam9g45_pm_init(void) + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); + } + + void __init at91sam9x5_pm_init(void) +@@ -448,5 +488,13 @@ void __init at91sam9x5_pm_init(void) + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); ++} ++ ++void __init sama5_pm_init(void) ++{ ++ at91_dt_ramc(); ++ at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; ++ at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; ++ at91_pm_init(NULL); + } +diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c +index d9cf679..df8fdf1 100644 +--- a/arch/arm/mach-at91/sama5.c ++++ b/arch/arm/mach-at91/sama5.c +@@ -51,7 +51,7 @@ static void __init sama5_dt_device_init(void) + soc_dev = soc_device_to_device(soc); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); +- at91sam9x5_pm_init(); ++ sama5_pm_init(); + } + + static const char *const sama5_dt_board_compat[] __initconst = { +diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c +index 47905a5..318394e 100644 +--- a/arch/arm/mach-cns3xxx/pcie.c ++++ b/arch/arm/mach-cns3xxx/pcie.c +@@ -220,13 +220,13 @@ static void cns3xxx_write_config(struct cns3xxx_pcie *cnspci, + u32 mask = (0x1ull << (size * 8)) - 1; + int shift = (where % 4) * 8; + +- v = readl_relaxed(base + (where & 0xffc)); ++ v = readl_relaxed(base); + + v &= ~(mask << shift); + v |= (val & mask) << shift; + +- writel_relaxed(v, base + (where & 0xffc)); +- readl_relaxed(base + (where & 0xffc)); ++ writel_relaxed(v, base); ++ readl_relaxed(base); + } + + static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci) +diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig +index 3a10f1a..bfd8bb3 100644 +--- a/arch/arm/mach-exynos/Kconfig ++++ b/arch/arm/mach-exynos/Kconfig +@@ -26,6 +26,7 @@ menuconfig ARCH_EXYNOS + select S5P_DEV_MFC + select SRAM + select THERMAL ++ select THERMAL_OF + select MFD_SYSCON + help + Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5) +diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c +index 7c21760..875a2ba 100644 +--- a/arch/arm/mach-exynos/pm_domains.c ++++ b/arch/arm/mach-exynos/pm_domains.c +@@ -92,7 +92,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) + if (IS_ERR(pd->clk[i])) + break; + +- if (IS_ERR(pd->clk[i])) ++ if (IS_ERR(pd->pclk[i])) + continue; /* Skip on first power up */ + if (clk_set_parent(pd->clk[i], pd->pclk[i])) + pr_err("%s: error setting parent to clock%d\n", +diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig +index 8bee527..dfcadee 100644 +--- a/arch/arm/mach-imx/Kconfig ++++ b/arch/arm/mach-imx/Kconfig +@@ -8,7 +8,6 @@ menuconfig ARCH_MXC + select PM_OPP if PM + select SOC_BUS + select SRAM +- select ZONE_DMA + help + Support for Freescale MXC/iMX-based family of processors + +@@ -526,7 +525,7 @@ config SOC_IMX6Q + bool "i.MX6 Quad/DualLite support" + select ARM_ERRATA_764369 if SMP + select HAVE_ARM_SCU if SMP +- select HAVE_ARM_TWD if SMP ++ select HAVE_ARM_TWD + select PCI_DOMAINS if PCI + select PINCTRL_IMX6Q + select SOC_IMX6 +diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h +index 75d2a4f..396b9fa 100644 +--- a/arch/arm/mach-imx/common.h ++++ b/arch/arm/mach-imx/common.h +@@ -112,6 +112,7 @@ void imx_anatop_post_resume(void); + int imx6_set_lpm(enum mxc_cpu_pwr_mode mode); + void imx6q_set_int_mem_clk_lpm(bool enable); + void imx6sl_set_wait_clk(bool enter); ++void imx6_enet_mac_init(const char *enet_compat, const char *ocotp_compat); + int imx_mmdc_get_ddr_type(void); + + void imx_cpu_die(unsigned int cpu); +diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c +index ae14184..3cb7c48 100644 +--- a/arch/arm/mach-imx/gpc.c ++++ b/arch/arm/mach-imx/gpc.c +@@ -35,6 +35,10 @@ + #define GPC_PGC_CPU_PDNSCR 0x2a8 + #define GPC_PGC_SW2ISO_SHIFT 0x8 + #define GPC_PGC_SW_SHIFT 0x0 ++#define GPC_PGC_DISP_PGCR_OFFSET 0x240 ++#define GPC_PGC_DISP_PUPSCR_OFFSET 0x244 ++#define GPC_PGC_DISP_PDNSCR_OFFSET 0x248 ++#define GPC_PGC_DISP_SR_OFFSET 0x24c + + #define IMR_NUM 4 + #define GPC_MAX_IRQS (IMR_NUM * 32) +@@ -43,6 +47,8 @@ + #define GPU_VPU_PDN_REQ BIT(0) + + #define GPC_CLK_MAX 10 ++#define DEFAULT_IPG_RATE 66000000 ++#define GPC_PU_UP_DELAY_MARGIN 2 + + struct pu_domain { + struct generic_pm_domain base; +@@ -51,9 +57,16 @@ struct pu_domain { + int num_clks; + }; + ++struct disp_domain { ++ struct generic_pm_domain base; ++ struct clk *clk[GPC_CLK_MAX]; ++ int num_clks; ++}; ++ + static void __iomem *gpc_base; + static u32 gpc_wake_irqs[IMR_NUM]; + static u32 gpc_saved_imrs[IMR_NUM]; ++static struct clk *ipg; + + void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) + { +@@ -365,6 +378,67 @@ static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd) + return 0; + } + ++static int imx_pm_dispmix_on(struct generic_pm_domain *genpd) ++{ ++ struct disp_domain *disp = container_of(genpd, struct disp_domain, base); ++ u32 val = readl_relaxed(gpc_base + GPC_CNTR); ++ int i; ++ u32 ipg_rate = clk_get_rate(ipg); ++ ++ if ((cpu_is_imx6sl() && ++ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) { ++ ++ /* Enable reset clocks for all devices in the disp domain */ ++ for (i = 0; i < disp->num_clks; i++) ++ clk_prepare_enable(disp->clk[i]); ++ ++ writel_relaxed(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET); ++ writel_relaxed(0x20 | val, gpc_base + GPC_CNTR); ++ while (readl_relaxed(gpc_base + GPC_CNTR) & 0x20) ++ ; ++ ++ writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET); ++ ++ /* Wait power switch done */ ++ udelay(2 * DEFAULT_IPG_RATE / ipg_rate + ++ GPC_PU_UP_DELAY_MARGIN); ++ ++ /* Disable reset clocks for all devices in the disp domain */ ++ for (i = 0; i < disp->num_clks; i++) ++ clk_disable_unprepare(disp->clk[i]); ++ } ++ return 0; ++} ++ ++static int imx_pm_dispmix_off(struct generic_pm_domain *genpd) ++{ ++ struct disp_domain *disp = container_of(genpd, struct disp_domain, base); ++ u32 val = readl_relaxed(gpc_base + GPC_CNTR); ++ int i; ++ ++ if ((cpu_is_imx6sl() && ++ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) { ++ ++ /* Enable reset clocks for all devices in the disp domain */ ++ for (i = 0; i < disp->num_clks; i++) ++ clk_prepare_enable(disp->clk[i]); ++ ++ writel_relaxed(0xFFFFFFFF, ++ gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET); ++ writel_relaxed(0xFFFFFFFF, ++ gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET); ++ writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET); ++ writel_relaxed(0x10 | val, gpc_base + GPC_CNTR); ++ while (readl_relaxed(gpc_base + GPC_CNTR) & 0x10) ++ ; ++ ++ /* Disable reset clocks for all devices in the disp domain */ ++ for (i = 0; i < disp->num_clks; i++) ++ clk_disable_unprepare(disp->clk[i]); ++ } ++ return 0; ++} ++ + static struct generic_pm_domain imx6q_arm_domain = { + .name = "ARM", + }; +@@ -379,14 +453,18 @@ static struct pu_domain imx6q_pu_domain = { + }, + }; + +-static struct generic_pm_domain imx6sl_display_domain = { +- .name = "DISPLAY", ++static struct disp_domain imx6s_display_domain = { ++ .base = { ++ .name = "DISPLAY", ++ .power_off = imx_pm_dispmix_off, ++ .power_on = imx_pm_dispmix_on, ++ }, + }; + + static struct generic_pm_domain *imx_gpc_domains[] = { + &imx6q_arm_domain, + &imx6q_pu_domain.base, +- &imx6sl_display_domain, ++ &imx6s_display_domain.base, + }; + + static struct genpd_onecell_data imx_gpc_onecell_data = { +@@ -397,42 +475,68 @@ static struct genpd_onecell_data imx_gpc_onecell_data = { + static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg) + { + struct clk *clk; +- int i; ++ bool is_off; ++ int pu_clks, disp_clks, ipg_clks = 1; ++ int i = 0, k = 0; + + imx6q_pu_domain.reg = pu_reg; + +- for (i = 0; ; i++) { ++ if ((cpu_is_imx6sl() && ++ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2)) { ++ pu_clks = 2 ; ++ disp_clks = 5; ++ } else if (cpu_is_imx6sx()) { ++ pu_clks = 1; ++ disp_clks = 7; ++ } else { ++ pu_clks = 6; ++ disp_clks = 0; ++ } ++ ++ /* Get pu domain clks */ ++ for (i = 0; i < pu_clks ; i++) { + clk = of_clk_get(dev->of_node, i); + if (IS_ERR(clk)) + break; +- if (i >= GPC_CLK_MAX) { +- dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); +- goto clk_err; +- } + imx6q_pu_domain.clk[i] = clk; + } + imx6q_pu_domain.num_clks = i; + +- /* Enable power always in case bootloader disabled it. */ +- imx6q_pm_pu_power_on(&imx6q_pu_domain.base); ++ ipg = of_clk_get(dev->of_node, pu_clks); + +- if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) +- return 0; ++ /* Get disp domain clks */ ++ for (k = 0, i = pu_clks + ipg_clks; i < pu_clks + ipg_clks + disp_clks; ++ i++, k++) { ++ clk = of_clk_get(dev->of_node, i); ++ if (IS_ERR(clk)) ++ break; ++ imx6s_display_domain.clk[k] = clk; ++ } ++ imx6s_display_domain.num_clks = k; ++ ++ is_off = IS_ENABLED(CONFIG_PM); ++ if (is_off) { ++ _imx6q_pm_pu_power_off(&imx6q_pu_domain.base); ++ } else { ++ /* ++ * Enable power if compiled without CONFIG_PM in case the ++ * bootloader disabled it. ++ */ ++ imx6q_pm_pu_power_on(&imx6q_pu_domain.base); ++ } ++ ++ pm_genpd_init(&imx6q_pu_domain.base, NULL, is_off); ++ pm_genpd_init(&imx6s_display_domain.base, NULL, is_off); + +- pm_genpd_init(&imx6q_pu_domain.base, NULL, false); + return of_genpd_add_provider_onecell(dev->of_node, + &imx_gpc_onecell_data); +- +-clk_err: +- while (i--) +- clk_put(imx6q_pu_domain.clk[i]); +- return -EINVAL; + } + + static int imx_gpc_probe(struct platform_device *pdev) + { + struct regulator *pu_reg; + int ret; ++ u32 bypass = 0; + + /* bail out if DT too old and doesn't provide the necessary info */ + if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells")) +@@ -447,6 +551,11 @@ static int imx_gpc_probe(struct platform_device *pdev) + return ret; + } + ++ of_property_read_u32(pdev->dev.of_node, "fsl,ldo-bypass", &bypass); ++ /* We only bypass pu since arm and soc has been set in u-boot */ ++ if (pu_reg && bypass) ++ regulator_allow_bypass(pu_reg, true); ++ + return imx_gpc_genpd_init(&pdev->dev, pu_reg); + } + +diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c +index 8766316..945072f 100644 +--- a/arch/arm/mach-imx/mach-imx6q.c ++++ b/arch/arm/mach-imx/mach-imx6q.c +@@ -1,5 +1,5 @@ + /* +- * Copyright 2011-2013 Freescale Semiconductor, Inc. ++ * Copyright 2011-2015 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -125,6 +126,10 @@ static int ar8031_phy_fixup(struct phy_device *dev) + { + u16 val; + ++ /* Set RGMII IO voltage to 1.8V */ ++ phy_write(dev, 0x1d, 0x1f); ++ phy_write(dev, 0x1e, 0x8); ++ + /* disable phy AR8031 SmartEEE function. */ + phy_write(dev, 0xd, 0x3); + phy_write(dev, 0xe, 0x805d); +@@ -221,9 +226,7 @@ static void __init imx6q_1588_init(void) + { + struct device_node *np; + struct clk *ptp_clk; +- struct clk *enet_ref; + struct regmap *gpr; +- u32 clksel; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec"); + if (!np) { +@@ -237,30 +240,19 @@ static void __init imx6q_1588_init(void) + goto put_node; + } + +- enet_ref = clk_get_sys(NULL, "enet_ref"); +- if (IS_ERR(enet_ref)) { +- pr_warn("%s: failed to get enet clock\n", __func__); +- goto put_ptp_clk; +- } +- + /* + * If enet_ref from ANATOP/CCM is the PTP clock source, we need to + * set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad + * (external OSC), and we need to clear the bit. + */ +- clksel = clk_is_match(ptp_clk, enet_ref) ? +- IMX6Q_GPR1_ENET_CLK_SEL_ANATOP : +- IMX6Q_GPR1_ENET_CLK_SEL_PAD; + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (!IS_ERR(gpr)) + regmap_update_bits(gpr, IOMUXC_GPR1, + IMX6Q_GPR1_ENET_CLK_SEL_MASK, +- clksel); ++ IMX6Q_GPR1_ENET_CLK_SEL_ANATOP); + else + pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); + +- clk_put(enet_ref); +-put_ptp_clk: + clk_put(ptp_clk); + put_node: + of_node_put(np); +@@ -334,6 +326,18 @@ static const struct of_dev_auxdata imx6q_auxdata_lookup[] __initconst = { + { /* sentinel */ } + }; + ++static void __init imx6q_enet_clk_sel(void) ++{ ++ struct regmap *gpr; ++ ++ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); ++ if (!IS_ERR(gpr)) ++ regmap_update_bits(gpr, IOMUXC_GPR5, ++ IMX6Q_GPR5_ENET_TX_CLK_SEL, IMX6Q_GPR5_ENET_TX_CLK_SEL); ++ else ++ pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); ++} ++ + static void imx6q_fec_sleep_enable(int enabled) + { + struct regmap *gpr; +@@ -358,6 +362,87 @@ static void __init imx6q_enet_plt_init(void) + np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); + if (np && of_get_property(np, "fsl,magic-packet", NULL)) + fec_pdata.sleep_mode_enable = imx6q_fec_sleep_enable; ++ ++ if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0) ++ imx6q_enet_clk_sel(); ++} ++ ++#define OCOTP_MACn(n) (0x00000620 + (n) * 0x10) ++void __init imx6_enet_mac_init(const char *enet_compat, const char *ocotp_compat) ++{ ++ struct device_node *ocotp_np, *enet_np, *from = NULL; ++ void __iomem *base; ++ struct property *newmac; ++ u32 macaddr_low; ++ u32 macaddr_high = 0; ++ u32 macaddr1_high = 0; ++ u8 *macaddr; ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ enet_np = of_find_compatible_node(from, NULL, enet_compat); ++ if (!enet_np) ++ return; ++ ++ from = enet_np; ++ ++ if (of_get_mac_address(enet_np)) ++ goto put_enet_node; ++ ++ ocotp_np = of_find_compatible_node(NULL, NULL, ocotp_compat); ++ if (!ocotp_np) { ++ pr_warn("failed to find ocotp node\n"); ++ goto put_enet_node; ++ } ++ ++ base = of_iomap(ocotp_np, 0); ++ if (!base) { ++ pr_warn("failed to map ocotp\n"); ++ goto put_ocotp_node; ++ } ++ ++ macaddr_low = readl_relaxed(base + OCOTP_MACn(1)); ++ if (i) ++ macaddr1_high = readl_relaxed(base + OCOTP_MACn(2)); ++ else ++ macaddr_high = readl_relaxed(base + OCOTP_MACn(0)); ++ ++ newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); ++ if (!newmac) ++ goto put_ocotp_node; ++ ++ newmac->value = newmac + 1; ++ newmac->length = 6; ++ newmac->name = kstrdup("local-mac-address", GFP_KERNEL); ++ if (!newmac->name) { ++ kfree(newmac); ++ goto put_ocotp_node; ++ } ++ ++ macaddr = newmac->value; ++ if (i) { ++ macaddr[5] = (macaddr_low >> 16) & 0xff; ++ macaddr[4] = (macaddr_low >> 24) & 0xff; ++ macaddr[3] = macaddr1_high & 0xff; ++ macaddr[2] = (macaddr1_high >> 8) & 0xff; ++ macaddr[1] = (macaddr1_high >> 16) & 0xff; ++ macaddr[0] = (macaddr1_high >> 24) & 0xff; ++ } else { ++ macaddr[5] = macaddr_high & 0xff; ++ macaddr[4] = (macaddr_high >> 8) & 0xff; ++ macaddr[3] = (macaddr_high >> 16) & 0xff; ++ macaddr[2] = (macaddr_high >> 24) & 0xff; ++ macaddr[1] = macaddr_low & 0xff; ++ macaddr[0] = (macaddr_low >> 8) & 0xff; ++ } ++ ++ of_update_property(enet_np, newmac); ++ ++put_ocotp_node: ++ of_node_put(ocotp_np); ++put_enet_node: ++ of_node_put(enet_np); ++ } + } + + static void __init imx6q_init_machine(void) +@@ -381,8 +466,11 @@ static void __init imx6q_init_machine(void) + imx_anatop_init(); + imx6q_csi_mux_init(); + cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); ++ + imx6q_1588_init(); + imx6q_enet_plt_init(); ++ imx6_enet_mac_init("fsl,imx6q-fec", "fsl,imx6q-ocotp"); ++ + imx6q_axi_init(); + + p = ioremap(0x21b0000, SZ_4K); +diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c +index e5371e9..005becf 100644 +--- a/arch/arm/mach-imx/mach-imx6sl.c ++++ b/arch/arm/mach-imx/mach-imx6sl.c +@@ -19,7 +19,7 @@ + #include "common.h" + #include "cpuidle.h" + +-static void __init imx6sl_fec_init(void) ++static void __init imx6sl_fec_clk_init(void) + { + struct regmap *gpr; + +@@ -30,9 +30,14 @@ static void __init imx6sl_fec_init(void) + IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0); + regmap_update_bits(gpr, IOMUXC_GPR1, + IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0); +- } else { ++ } else + pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n"); +- } ++} ++ ++static inline void imx6sl_fec_init(void) ++{ ++ imx6sl_fec_clk_init(); ++ imx6_enet_mac_init("fsl,imx6sl-fec", "fsl,imx6sl-ocotp"); + } + + static void __init imx6sl_init_late(void) +diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c +index 3f56432..49d4e8e 100644 +--- a/arch/arm/mach-imx/mach-imx6sx.c ++++ b/arch/arm/mach-imx/mach-imx6sx.c +@@ -60,6 +60,7 @@ static void __init imx6sx_enet_clk_sel(void) + + static inline void imx6sx_enet_init(void) + { ++ imx6_enet_mac_init("fsl,imx6sx-fec", "fsl,imx6sx-ocotp"); + imx6sx_enet_phy_init(); + imx6sx_enet_clk_sel(); + } +diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c +index b450f52..68a5a58 100644 +--- a/arch/arm/mach-imx/mach-imx7d.c ++++ b/arch/arm/mach-imx/mach-imx7d.c +@@ -81,6 +81,7 @@ static void __init imx7d_enet_clk_sel(void) + + static inline void imx7d_enet_init(void) + { ++ imx6_enet_mac_init("fsl,imx7d-fec", "fsl,imx7d-ocotp"); + imx7d_enet_phy_init(); + imx7d_enet_clk_sel(); + } +diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c +index aa7b379..2a3db0b 100644 +--- a/arch/arm/mach-omap2/cpuidle34xx.c ++++ b/arch/arm/mach-omap2/cpuidle34xx.c +@@ -34,6 +34,7 @@ + #include "pm.h" + #include "control.h" + #include "common.h" ++#include "soc.h" + + /* Mach specific information to be recorded in the C-state driver_data */ + struct omap3_idle_statedata { +@@ -315,6 +316,69 @@ static struct cpuidle_driver omap3_idle_driver = { + .safe_state_index = 0, + }; + ++/* ++ * Numbers based on measurements made in October 2009 for PM optimized kernel ++ * with CPU freq enabled on device Nokia N900. Assumes OPP2 (main idle OPP, ++ * and worst case latencies). ++ */ ++static struct cpuidle_driver omap3430_idle_driver = { ++ .name = "omap3430_idle", ++ .owner = THIS_MODULE, ++ .states = { ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 110 + 162, ++ .target_residency = 5, ++ .name = "C1", ++ .desc = "MPU ON + CORE ON", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 106 + 180, ++ .target_residency = 309, ++ .name = "C2", ++ .desc = "MPU ON + CORE ON", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 107 + 410, ++ .target_residency = 46057, ++ .name = "C3", ++ .desc = "MPU RET + CORE ON", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 121 + 3374, ++ .target_residency = 46057, ++ .name = "C4", ++ .desc = "MPU OFF + CORE ON", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 855 + 1146, ++ .target_residency = 46057, ++ .name = "C5", ++ .desc = "MPU RET + CORE RET", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 7580 + 4134, ++ .target_residency = 484329, ++ .name = "C6", ++ .desc = "MPU OFF + CORE RET", ++ }, ++ { ++ .enter = omap3_enter_idle_bm, ++ .exit_latency = 7505 + 15274, ++ .target_residency = 484329, ++ .name = "C7", ++ .desc = "MPU OFF + CORE OFF", ++ }, ++ }, ++ .state_count = ARRAY_SIZE(omap3_idle_data), ++ .safe_state_index = 0, ++}; ++ + /* Public functions */ + + /** +@@ -333,5 +397,8 @@ int __init omap3_idle_init(void) + if (!mpu_pd || !core_pd || !per_pd || !cam_pd) + return -ENODEV; + +- return cpuidle_register(&omap3_idle_driver, NULL); ++ if (cpu_is_omap3430()) ++ return cpuidle_register(&omap3430_idle_driver, NULL); ++ else ++ return cpuidle_register(&omap3_idle_driver, NULL); + } +diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index 3eaeaca..3a911d8 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -368,6 +368,7 @@ void __init omap5_map_io(void) + void __init dra7xx_map_io(void) + { + iotable_init(dra7xx_io_desc, ARRAY_SIZE(dra7xx_io_desc)); ++ omap_barriers_init(); + } + #endif + /* +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 8e0bd59..147c90e 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -1416,9 +1416,7 @@ static void _enable_sysc(struct omap_hwmod *oh) + (sf & SYSC_HAS_CLOCKACTIVITY)) + _set_clockactivity(oh, oh->class->sysc->clockact, &v); + +- /* If the cached value is the same as the new value, skip the write */ +- if (oh->_sysc_cache != v) +- _write_sysconfig(v, oh); ++ _write_sysconfig(v, oh); + + /* + * Set the autoidle bit only after setting the smartidle bit +@@ -1481,7 +1479,9 @@ static void _idle_sysc(struct omap_hwmod *oh) + _set_master_standbymode(oh, idlemode, &v); + } + +- _write_sysconfig(v, oh); ++ /* If the cached value is the same as the new value, skip the write */ ++ if (oh->_sysc_cache != v) ++ _write_sysconfig(v, oh); + } + + /** +diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig +index 9ab8932..56e55fd 100644 +--- a/arch/arm/mach-prima2/Kconfig ++++ b/arch/arm/mach-prima2/Kconfig +@@ -1,6 +1,7 @@ + menuconfig ARCH_SIRF + bool "CSR SiRF" if ARCH_MULTI_V7 + select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER + select ARCH_REQUIRE_GPIOLIB + select GENERIC_IRQ_CHIP + select NO_IOPORT_MAP +diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c +index ff780a8..9a42736 100644 +--- a/arch/arm/mach-s3c64xx/dev-audio.c ++++ b/arch/arm/mach-s3c64xx/dev-audio.c +@@ -54,12 +54,12 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev) + + static struct resource s3c64xx_iis0_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_I2S0_OUT), +- [2] = DEFINE_RES_DMA(DMACH_I2S0_IN), + }; + +-static struct s3c_audio_pdata i2sv3_pdata = { ++static struct s3c_audio_pdata i2s0_pdata = { + .cfg_gpio = s3c64xx_i2s_cfg_gpio, ++ .dma_playback = DMACH_I2S0_OUT, ++ .dma_capture = DMACH_I2S0_IN, + }; + + struct platform_device s3c64xx_device_iis0 = { +@@ -68,15 +68,19 @@ struct platform_device s3c64xx_device_iis0 = { + .num_resources = ARRAY_SIZE(s3c64xx_iis0_resource), + .resource = s3c64xx_iis0_resource, + .dev = { +- .platform_data = &i2sv3_pdata, ++ .platform_data = &i2s0_pdata, + }, + }; + EXPORT_SYMBOL(s3c64xx_device_iis0); + + static struct resource s3c64xx_iis1_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_I2S1_OUT), +- [2] = DEFINE_RES_DMA(DMACH_I2S1_IN), ++}; ++ ++static struct s3c_audio_pdata i2s1_pdata = { ++ .cfg_gpio = s3c64xx_i2s_cfg_gpio, ++ .dma_playback = DMACH_I2S1_OUT, ++ .dma_capture = DMACH_I2S1_IN, + }; + + struct platform_device s3c64xx_device_iis1 = { +@@ -85,19 +89,19 @@ struct platform_device s3c64xx_device_iis1 = { + .num_resources = ARRAY_SIZE(s3c64xx_iis1_resource), + .resource = s3c64xx_iis1_resource, + .dev = { +- .platform_data = &i2sv3_pdata, ++ .platform_data = &i2s1_pdata, + }, + }; + EXPORT_SYMBOL(s3c64xx_device_iis1); + + static struct resource s3c64xx_iisv4_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX), +- [2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX), + }; + + static struct s3c_audio_pdata i2sv4_pdata = { + .cfg_gpio = s3c64xx_i2s_cfg_gpio, ++ .dma_playback = DMACH_HSI_I2SV40_TX, ++ .dma_capture = DMACH_HSI_I2SV40_RX, + .type = { + .i2s = { + .quirks = QUIRK_PRI_6CHAN, +@@ -142,12 +146,12 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) + + static struct resource s3c64xx_pcm0_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX), +- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX), + }; + + static struct s3c_audio_pdata s3c_pcm0_pdata = { + .cfg_gpio = s3c64xx_pcm_cfg_gpio, ++ .dma_capture = DMACH_PCM0_RX, ++ .dma_playback = DMACH_PCM0_TX, + }; + + struct platform_device s3c64xx_device_pcm0 = { +@@ -163,12 +167,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0); + + static struct resource s3c64xx_pcm1_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_PCM1_TX), +- [2] = DEFINE_RES_DMA(DMACH_PCM1_RX), + }; + + static struct s3c_audio_pdata s3c_pcm1_pdata = { + .cfg_gpio = s3c64xx_pcm_cfg_gpio, ++ .dma_playback = DMACH_PCM1_TX, ++ .dma_capture = DMACH_PCM1_RX, + }; + + struct platform_device s3c64xx_device_pcm1 = { +@@ -196,13 +200,14 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) + + static struct resource s3c64xx_ac97_resource[] = { + [0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256), +- [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT), +- [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN), +- [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN), +- [4] = DEFINE_RES_IRQ(IRQ_AC97), ++ [1] = DEFINE_RES_IRQ(IRQ_AC97), + }; + +-static struct s3c_audio_pdata s3c_ac97_pdata; ++static struct s3c_audio_pdata s3c_ac97_pdata = { ++ .dma_playback = DMACH_AC97_PCMOUT, ++ .dma_capture = DMACH_AC97_PCMIN, ++ .dma_capture_mic = DMACH_AC97_MICIN, ++}; + + static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32); + +diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h +index 096e140..9c739ea 100644 +--- a/arch/arm/mach-s3c64xx/include/mach/dma.h ++++ b/arch/arm/mach-s3c64xx/include/mach/dma.h +@@ -14,38 +14,38 @@ + #define S3C64XX_DMA_CHAN(name) ((unsigned long)(name)) + + /* DMA0/SDMA0 */ +-#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx") +-#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx") +-#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx") +-#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx") +-#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx") +-#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx") +-#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx") +-#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx") +-#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx") +-#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx") +-#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx") +-#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx") ++#define DMACH_UART0 "uart0_tx" ++#define DMACH_UART0_SRC2 "uart0_rx" ++#define DMACH_UART1 "uart1_tx" ++#define DMACH_UART1_SRC2 "uart1_rx" ++#define DMACH_UART2 "uart2_tx" ++#define DMACH_UART2_SRC2 "uart2_rx" ++#define DMACH_UART3 "uart3_tx" ++#define DMACH_UART3_SRC2 "uart3_rx" ++#define DMACH_PCM0_TX "pcm0_tx" ++#define DMACH_PCM0_RX "pcm0_rx" ++#define DMACH_I2S0_OUT "i2s0_tx" ++#define DMACH_I2S0_IN "i2s0_rx" + #define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx") + #define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx") +-#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx") +-#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx") ++#define DMACH_HSI_I2SV40_TX "i2s2_tx" ++#define DMACH_HSI_I2SV40_RX "i2s2_rx" + + /* DMA1/SDMA1 */ +-#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx") +-#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx") +-#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx") +-#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx") ++#define DMACH_PCM1_TX "pcm1_tx" ++#define DMACH_PCM1_RX "pcm1_rx" ++#define DMACH_I2S1_OUT "i2s1_tx" ++#define DMACH_I2S1_IN "i2s1_rx" + #define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx") + #define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx") +-#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out") +-#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in") +-#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic") +-#define DMACH_PWM S3C64XX_DMA_CHAN("pwm") +-#define DMACH_IRDA S3C64XX_DMA_CHAN("irda") +-#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external") +-#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx") +-#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx") ++#define DMACH_AC97_PCMOUT "ac97_out" ++#define DMACH_AC97_PCMIN "ac97_in" ++#define DMACH_AC97_MICIN "ac97_mic" ++#define DMACH_PWM "pwm" ++#define DMACH_IRDA "irda" ++#define DMACH_EXTERNAL "external" ++#define DMACH_SECURITY_RX "sec_rx" ++#define DMACH_SECURITY_TX "sec_tx" + + enum dma_ch { + DMACH_MAX = 32 +diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S +index 5d94b7a..c160fa3 100644 +--- a/arch/arm/mach-socfpga/headsmp.S ++++ b/arch/arm/mach-socfpga/headsmp.S +@@ -13,6 +13,7 @@ + #include + + .arch armv7-a ++ .arm + + ENTRY(secondary_trampoline) + /* CPU1 will always fetch from 0x0 when it is brought out of reset. +diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c +index 8207462..e212f9d 100644 +--- a/arch/arm/plat-samsung/devs.c ++++ b/arch/arm/plat-samsung/devs.c +@@ -65,6 +65,7 @@ + #include + #include + #include ++#include + #include + + static u64 samsung_device_dma_mask = DMA_BIT_MASK(32); +@@ -74,9 +75,12 @@ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32); + static struct resource s3c_ac97_resource[] = { + [0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97), + [1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97), +- [2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"), +- [3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"), +- [4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"), ++}; ++ ++static struct s3c_audio_pdata s3c_ac97_pdata = { ++ .dma_playback = (void *)DMACH_PCM_OUT, ++ .dma_capture = (void *)DMACH_PCM_IN, ++ .dma_capture_mic = (void *)DMACH_MIC_IN, + }; + + struct platform_device s3c_device_ac97 = { +@@ -87,6 +91,7 @@ struct platform_device s3c_device_ac97 = { + .dev = { + .dma_mask = &samsung_device_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &s3c_ac97_pdata, + } + }; + #endif /* CONFIG_CPU_S3C2440 */ +diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h +index faad6df..bc6492b 100644 +--- a/arch/arm64/include/asm/elf.h ++++ b/arch/arm64/include/asm/elf.h +@@ -156,14 +156,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, + #define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12)) + #endif + +-#ifdef CONFIG_COMPAT +- + #ifdef __AARCH64EB__ + #define COMPAT_ELF_PLATFORM ("v8b") + #else + #define COMPAT_ELF_PLATFORM ("v8l") + #endif + ++#ifdef CONFIG_COMPAT ++ + #define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3) + + /* AArch32 registers. */ +diff --git a/arch/arm64/include/asm/opcodes.h b/arch/arm64/include/asm/opcodes.h +index 4e603ea..123f45d 100644 +--- a/arch/arm64/include/asm/opcodes.h ++++ b/arch/arm64/include/asm/opcodes.h +@@ -1 +1,5 @@ ++#ifdef CONFIG_CPU_BIG_ENDIAN ++#define CONFIG_CPU_ENDIAN_BE8 CONFIG_CPU_BIG_ENDIAN ++#endif ++ + #include <../../arm/include/asm/opcodes.h> +diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h +index d6739e8..b9da954 100644 +--- a/arch/arm64/include/asm/pgtable-hwdef.h ++++ b/arch/arm64/include/asm/pgtable-hwdef.h +@@ -117,7 +117,6 @@ + * Section + */ + #define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) +-#define PMD_SECT_PROT_NONE (_AT(pmdval_t, 1) << 58) + #define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */ + #define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */ + #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index eaa9cab..67c2ad6 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -69,11 +69,11 @@ extern void __pgd_error(const char *file, int line, unsigned long val); + #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) + #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) + +-#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) +-#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +-#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC)) +-#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_WT)) +-#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL)) ++#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) ++#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) ++#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) ++#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT)) ++#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) + + #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) + #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) +@@ -83,7 +83,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); + + #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) + #define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) +-#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY) ++#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY) + #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) + #define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT) + +@@ -155,6 +155,7 @@ extern struct page *empty_zero_page; + #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) + #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) + #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT)) ++#define pte_user(pte) (!!(pte_val(pte) & PTE_USER)) + + #ifdef CONFIG_ARM64_HW_AFDBM + #define pte_hw_dirty(pte) (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY)) +@@ -165,8 +166,6 @@ extern struct page *empty_zero_page; + #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte)) + + #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) +-#define pte_valid_user(pte) \ +- ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) + #define pte_valid_not_user(pte) \ + ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) + +@@ -264,13 +263,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); + static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) + { +- if (pte_valid_user(pte)) { +- if (!pte_special(pte) && pte_exec(pte)) +- __sync_icache_dcache(pte, addr); ++ if (pte_present(pte)) { + if (pte_sw_dirty(pte) && pte_write(pte)) + pte_val(pte) &= ~PTE_RDONLY; + else + pte_val(pte) |= PTE_RDONLY; ++ if (pte_user(pte) && pte_exec(pte) && !pte_special(pte)) ++ __sync_icache_dcache(pte, addr); + } + + /* +@@ -348,6 +347,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address, + #endif /* CONFIG_HAVE_RCU_TABLE_FREE */ + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + ++#define pmd_present(pmd) pte_present(pmd_pte(pmd)) + #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd)) + #define pmd_young(pmd) pte_young(pmd_pte(pmd)) + #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd))) +@@ -356,7 +356,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address, + #define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) + #define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) + #define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) +-#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK)) ++#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_SECT_VALID)) + + #define __HAVE_ARCH_PMD_WRITE + #define pmd_write(pmd) pte_write(pmd_pte(pmd)) +@@ -395,7 +395,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); + + #define pmd_none(pmd) (!pmd_val(pmd)) +-#define pmd_present(pmd) (pmd_val(pmd)) + + #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) + +@@ -539,6 +538,21 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) + } + + #ifdef CONFIG_ARM64_HW_AFDBM ++#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS ++extern int ptep_set_access_flags(struct vm_area_struct *vma, ++ unsigned long address, pte_t *ptep, ++ pte_t entry, int dirty); ++ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS ++static inline int pmdp_set_access_flags(struct vm_area_struct *vma, ++ unsigned long address, pmd_t *pmdp, ++ pmd_t entry, int dirty) ++{ ++ return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty); ++} ++#endif ++ + /* + * Atomic pte/pmd modifications. + */ +@@ -591,9 +605,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR +-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, +- unsigned long address, pmd_t *pmdp) ++#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR ++static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, ++ unsigned long address, pmd_t *pmdp) + { + return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp)); + } +@@ -641,6 +655,7 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; + * bits 0-1: present (must be zero) + * bits 2-7: swap type + * bits 8-57: swap offset ++ * bit 58: PTE_PROT_NONE (must be zero) + */ + #define __SWP_TYPE_SHIFT 2 + #define __SWP_TYPE_BITS 6 +diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c +index 212ae63..0166cfb 100644 +--- a/arch/arm64/kernel/cpuinfo.c ++++ b/arch/arm64/kernel/cpuinfo.c +@@ -22,6 +22,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -85,7 +87,8 @@ static const char *const compat_hwcap_str[] = { + "idivt", + "vfpd32", + "lpae", +- "evtstrm" ++ "evtstrm", ++ NULL + }; + + static const char *const compat_hwcap2_str[] = { +@@ -101,6 +104,7 @@ static const char *const compat_hwcap2_str[] = { + static int c_show(struct seq_file *m, void *v) + { + int i, j; ++ bool compat = personality(current->personality) == PER_LINUX32; + + for_each_online_cpu(i) { + struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); +@@ -112,6 +116,9 @@ static int c_show(struct seq_file *m, void *v) + * "processor". Give glibc what it expects. + */ + seq_printf(m, "processor\t: %d\n", i); ++ if (compat) ++ seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n", ++ MIDR_REVISION(midr), COMPAT_ELF_PLATFORM); + + seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", + loops_per_jiffy / (500000UL/HZ), +@@ -124,7 +131,7 @@ static int c_show(struct seq_file *m, void *v) + * software which does already (at least for 32-bit). + */ + seq_puts(m, "Features\t:"); +- if (personality(current->personality) == PER_LINUX32) { ++ if (compat) { + #ifdef CONFIG_COMPAT + for (j = 0; compat_hwcap_str[j]; j++) + if (compat_elf_hwcap & (1 << j)) +diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c +index 648112e..3972e65 100644 +--- a/arch/arm64/kvm/inject_fault.c ++++ b/arch/arm64/kvm/inject_fault.c +@@ -130,7 +130,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr + esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT); + + if (!is_iabt) +- esr |= ESR_ELx_EC_DABT_LOW; ++ esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT; + + vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT; + } +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index 92ddac1..4c1a118 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -81,6 +81,56 @@ void show_pte(struct mm_struct *mm, unsigned long addr) + printk("\n"); + } + ++#ifdef CONFIG_ARM64_HW_AFDBM ++/* ++ * This function sets the access flags (dirty, accessed), as well as write ++ * permission, and only to a more permissive setting. ++ * ++ * It needs to cope with hardware update of the accessed/dirty state by other ++ * agents in the system and can safely skip the __sync_icache_dcache() call as, ++ * like set_pte_at(), the PTE is never changed from no-exec to exec here. ++ * ++ * Returns whether or not the PTE actually changed. ++ */ ++int ptep_set_access_flags(struct vm_area_struct *vma, ++ unsigned long address, pte_t *ptep, ++ pte_t entry, int dirty) ++{ ++ pteval_t old_pteval; ++ unsigned int tmp; ++ ++ if (pte_same(*ptep, entry)) ++ return 0; ++ ++ /* only preserve the access flags and write permission */ ++ pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY; ++ ++ /* ++ * PTE_RDONLY is cleared by default in the asm below, so set it in ++ * back if necessary (read-only or clean PTE). ++ */ ++ if (!pte_write(entry) || !pte_sw_dirty(entry)) ++ pte_val(entry) |= PTE_RDONLY; ++ ++ /* ++ * Setting the flags must be done atomically to avoid racing with the ++ * hardware update of the access/dirty state. ++ */ ++ asm volatile("// ptep_set_access_flags\n" ++ " prfm pstl1strm, %2\n" ++ "1: ldxr %0, %2\n" ++ " and %0, %0, %3 // clear PTE_RDONLY\n" ++ " orr %0, %0, %4 // set flags\n" ++ " stxr %w1, %0, %2\n" ++ " cbnz %w1, 1b\n" ++ : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)) ++ : "L" (~PTE_RDONLY), "r" (pte_val(entry))); ++ ++ flush_tlb_fix_spurious_fault(vma, address); ++ return 1; ++} ++#endif ++ + /* + * The kernel tried to access some page that wasn't present. + */ +diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h +index 9041bbe..8fdb9c7 100644 +--- a/arch/ia64/include/asm/io.h ++++ b/arch/ia64/include/asm/io.h +@@ -436,6 +436,7 @@ static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned lo + return ioremap(phys_addr, size); + } + #define ioremap_cache ioremap_cache ++#define ioremap_uc ioremap_nocache + + + /* +diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c +index bdeed9d..433c4b9 100644 +--- a/arch/mips/alchemy/devboards/db1000.c ++++ b/arch/mips/alchemy/devboards/db1000.c +@@ -503,15 +503,15 @@ int __init db1000_dev_setup(void) + if (board == BCSR_WHOAMI_DB1500) { + c0 = AU1500_GPIO2_INT; + c1 = AU1500_GPIO5_INT; +- d0 = AU1500_GPIO0_INT; +- d1 = AU1500_GPIO3_INT; ++ d0 = 0; /* GPIO number, NOT irq! */ ++ d1 = 3; /* GPIO number, NOT irq! */ + s0 = AU1500_GPIO1_INT; + s1 = AU1500_GPIO4_INT; + } else if (board == BCSR_WHOAMI_DB1100) { + c0 = AU1100_GPIO2_INT; + c1 = AU1100_GPIO5_INT; +- d0 = AU1100_GPIO0_INT; +- d1 = AU1100_GPIO3_INT; ++ d0 = 0; /* GPIO number, NOT irq! */ ++ d1 = 3; /* GPIO number, NOT irq! */ + s0 = AU1100_GPIO1_INT; + s1 = AU1100_GPIO4_INT; + +@@ -545,15 +545,15 @@ int __init db1000_dev_setup(void) + } else if (board == BCSR_WHOAMI_DB1000) { + c0 = AU1000_GPIO2_INT; + c1 = AU1000_GPIO5_INT; +- d0 = AU1000_GPIO0_INT; +- d1 = AU1000_GPIO3_INT; ++ d0 = 0; /* GPIO number, NOT irq! */ ++ d1 = 3; /* GPIO number, NOT irq! */ + s0 = AU1000_GPIO1_INT; + s1 = AU1000_GPIO4_INT; + platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs)); + } else if ((board == BCSR_WHOAMI_PB1500) || + (board == BCSR_WHOAMI_PB1500R2)) { + c0 = AU1500_GPIO203_INT; +- d0 = AU1500_GPIO201_INT; ++ d0 = 1; /* GPIO number, NOT irq! */ + s0 = AU1500_GPIO202_INT; + twosocks = 0; + flashsize = 64; +@@ -566,7 +566,7 @@ int __init db1000_dev_setup(void) + */ + } else if (board == BCSR_WHOAMI_PB1100) { + c0 = AU1100_GPIO11_INT; +- d0 = AU1100_GPIO9_INT; ++ d0 = 9; /* GPIO number, NOT irq! */ + s0 = AU1100_GPIO10_INT; + twosocks = 0; + flashsize = 64; +@@ -583,7 +583,6 @@ int __init db1000_dev_setup(void) + } else + return 0; /* unknown board, no further dev setup to do */ + +- irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH); + irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW); + irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW); + +@@ -597,7 +596,6 @@ int __init db1000_dev_setup(void) + c0, d0, /*s0*/0, 0, 0); + + if (twosocks) { +- irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH); + irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW); + irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW); + +diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c +index 5740bcf..6c37b93 100644 +--- a/arch/mips/alchemy/devboards/db1550.c ++++ b/arch/mips/alchemy/devboards/db1550.c +@@ -514,7 +514,7 @@ static void __init db1550_devices(void) + AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1, + AU1000_PCMCIA_IO_PHYS_ADDR, + AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1, +- AU1550_GPIO3_INT, AU1550_GPIO0_INT, ++ AU1550_GPIO3_INT, 0, + /*AU1550_GPIO21_INT*/0, 0, 0); + + db1x_register_pcmcia_socket( +@@ -524,7 +524,7 @@ static void __init db1550_devices(void) + AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1, + AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000, + AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1, +- AU1550_GPIO5_INT, AU1550_GPIO1_INT, ++ AU1550_GPIO5_INT, 1, + /*AU1550_GPIO22_INT*/0, 0, 1); + + platform_device_register(&db1550_nand_dev); +diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c +index b955faf..d1adc59 100644 +--- a/arch/mips/ath79/early_printk.c ++++ b/arch/mips/ath79/early_printk.c +@@ -31,13 +31,15 @@ static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val) + } while (1); + } + ++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) ++ + static void prom_putchar_ar71xx(unsigned char ch) + { + void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); + +- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); ++ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY); + __raw_writel(ch, base + UART_TX * 4); +- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE); ++ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY); + } + + static void prom_putchar_ar933x(unsigned char ch) +diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h +index 867f924..e689b89 100644 +--- a/arch/mips/include/asm/asmmacro.h ++++ b/arch/mips/include/asm/asmmacro.h +@@ -298,21 +298,21 @@ + .set pop + .endm + +- .macro copy_u_w ws, n ++ .macro copy_s_w ws, n + .set push + .set mips32r2 + .set fp=64 + .set msa +- copy_u.w $1, $w\ws[\n] ++ copy_s.w $1, $w\ws[\n] + .set pop + .endm + +- .macro copy_u_d ws, n ++ .macro copy_s_d ws, n + .set push + .set mips64r2 + .set fp=64 + .set msa +- copy_u.d $1, $w\ws[\n] ++ copy_s.d $1, $w\ws[\n] + .set pop + .endm + +@@ -346,8 +346,8 @@ + #define STH_MSA_INSN 0x5800081f + #define STW_MSA_INSN 0x5800082f + #define STD_MSA_INSN 0x5800083f +-#define COPY_UW_MSA_INSN 0x58f00056 +-#define COPY_UD_MSA_INSN 0x58f80056 ++#define COPY_SW_MSA_INSN 0x58b00056 ++#define COPY_SD_MSA_INSN 0x58b80056 + #define INSERT_W_MSA_INSN 0x59300816 + #define INSERT_D_MSA_INSN 0x59380816 + #else +@@ -361,8 +361,8 @@ + #define STH_MSA_INSN 0x78000825 + #define STW_MSA_INSN 0x78000826 + #define STD_MSA_INSN 0x78000827 +-#define COPY_UW_MSA_INSN 0x78f00059 +-#define COPY_UD_MSA_INSN 0x78f80059 ++#define COPY_SW_MSA_INSN 0x78b00059 ++#define COPY_SD_MSA_INSN 0x78b80059 + #define INSERT_W_MSA_INSN 0x79300819 + #define INSERT_D_MSA_INSN 0x79380819 + #endif +@@ -393,7 +393,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word LDB_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -402,7 +402,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word LDH_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -411,7 +411,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word LDW_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -420,7 +420,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word LDD_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -429,7 +429,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word STB_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -438,7 +438,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word STH_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -447,7 +447,7 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word STW_MSA_INSN | (\wd << 6) + .set pop + .endm +@@ -456,26 +456,26 @@ + .set push + .set noat + SET_HARDFLOAT +- addu $1, \base, \off ++ PTR_ADDU $1, \base, \off + .word STD_MSA_INSN | (\wd << 6) + .set pop + .endm + +- .macro copy_u_w ws, n ++ .macro copy_s_w ws, n + .set push + .set noat + SET_HARDFLOAT + .insn +- .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11) ++ .word COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11) + .set pop + .endm + +- .macro copy_u_d ws, n ++ .macro copy_s_d ws, n + .set push + .set noat + SET_HARDFLOAT + .insn +- .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11) ++ .word COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11) + .set pop + .endm + +diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h +index 723229f..176de58 100644 +--- a/arch/mips/include/asm/cacheflush.h ++++ b/arch/mips/include/asm/cacheflush.h +@@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, + unsigned long start, unsigned long end); + extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); + extern void __flush_dcache_page(struct page *page); +-extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page); + + #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 + static inline void flush_dcache_page(struct page *page) +@@ -77,11 +76,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma, + static inline void flush_icache_page(struct vm_area_struct *vma, + struct page *page) + { +- if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) && +- Page_dcache_dirty(page)) { +- __flush_icache_page(vma, page); +- ClearPageDcacheDirty(page); +- } + } + + extern void (*flush_icache_range)(unsigned long start, unsigned long end); +diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h +index 6ded8d3..4e956b3 100644 +--- a/arch/mips/include/asm/kvm_host.h ++++ b/arch/mips/include/asm/kvm_host.h +@@ -784,7 +784,7 @@ extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, + + uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu); + void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count); +-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare); ++void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack); + void kvm_mips_init_count(struct kvm_vcpu *vcpu); + int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl); + int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume); +diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h +index bbb85fe..6e4effa 100644 +--- a/arch/mips/include/asm/msa.h ++++ b/arch/mips/include/asm/msa.h +@@ -147,6 +147,19 @@ static inline void restore_msa(struct task_struct *t) + _restore_msa(t); + } + ++static inline void init_msa_upper(void) ++{ ++ /* ++ * Check cpu_has_msa only if it's a constant. This will allow the ++ * compiler to optimise out code for CPUs without MSA without adding ++ * an extra redundant check for CPUs with MSA. ++ */ ++ if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa) ++ return; ++ ++ _init_msa_upper(); ++} ++ + #ifdef TOOLCHAIN_SUPPORTS_MSA + + #define __BUILD_MSA_CTL_REG(name, cs) \ +diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h +index 18826aa..4e68c64 100644 +--- a/arch/mips/include/asm/pgtable.h ++++ b/arch/mips/include/asm/pgtable.h +@@ -127,10 +127,14 @@ do { \ + } \ + } while(0) + ++static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pteval); ++ + #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) + + #define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) + #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) ++#define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) + + static inline void set_pte(pte_t *ptep, pte_t pte) + { +@@ -148,7 +152,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte) + buddy->pte_high |= _PAGE_GLOBAL; + } + } +-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) + + static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) + { +@@ -166,6 +169,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt + + #define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) + #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) ++#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC) + + /* + * Certain architectures need to do special things when pte's +@@ -218,7 +222,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) + } + #endif + } +-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) + + static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) + { +@@ -234,6 +237,22 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt + } + #endif + ++static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pteval) ++{ ++ extern void __update_cache(unsigned long address, pte_t pte); ++ ++ if (!pte_present(pteval)) ++ goto cache_sync_done; ++ ++ if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval))) ++ goto cache_sync_done; ++ ++ __update_cache(addr, pteval); ++cache_sync_done: ++ set_pte(ptep, pteval); ++} ++ + /* + * (pmds are folded into puds so this doesn't get actually called, + * but the define is needed for a generic inline function.) +@@ -430,15 +449,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) + + extern void __update_tlb(struct vm_area_struct *vma, unsigned long address, + pte_t pte); +-extern void __update_cache(struct vm_area_struct *vma, unsigned long address, +- pte_t pte); + + static inline void update_mmu_cache(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep) + { + pte_t pte = *ptep; + __update_tlb(vma, address, pte); +- __update_cache(vma, address, pte); + } + + static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, +diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h +index 3f832c3..041153f 100644 +--- a/arch/mips/include/asm/processor.h ++++ b/arch/mips/include/asm/processor.h +@@ -45,7 +45,7 @@ extern unsigned int vced_count, vcei_count; + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + */ +-#define TASK_SIZE 0x7fff8000UL ++#define TASK_SIZE 0x80000000UL + #endif + + #define STACK_TOP_MAX TASK_SIZE +diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h +index 28b5d84..ebb5c0f 100644 +--- a/arch/mips/include/asm/switch_to.h ++++ b/arch/mips/include/asm/switch_to.h +@@ -105,7 +105,7 @@ do { \ + __clear_software_ll_bit(); \ + if (cpu_has_userlocal) \ + write_c0_userlocal(task_thread_info(next)->tp_value); \ +- __restore_watch(); \ ++ __restore_watch(next); \ + (last) = resume(prev, next, task_thread_info(next)); \ + } while (0) + +diff --git a/arch/mips/include/asm/watch.h b/arch/mips/include/asm/watch.h +index 20126ec..6ffe3ea 100644 +--- a/arch/mips/include/asm/watch.h ++++ b/arch/mips/include/asm/watch.h +@@ -12,21 +12,21 @@ + + #include + +-void mips_install_watch_registers(void); ++void mips_install_watch_registers(struct task_struct *t); + void mips_read_watch_registers(void); + void mips_clear_watch_registers(void); + void mips_probe_watch_registers(struct cpuinfo_mips *c); + + #ifdef CONFIG_HARDWARE_WATCHPOINTS +-#define __restore_watch() do { \ ++#define __restore_watch(task) do { \ + if (unlikely(test_bit(TIF_LOAD_WATCH, \ +- ¤t_thread_info()->flags))) { \ +- mips_install_watch_registers(); \ ++ &task_thread_info(task)->flags))) { \ ++ mips_install_watch_registers(task); \ + } \ + } while (0) + + #else +-#define __restore_watch() do {} while (0) ++#define __restore_watch(task) do {} while (0) + #endif + + #endif /* _ASM_WATCH_H */ +diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h +index 2cb7fde..e2b5337 100644 +--- a/arch/mips/include/uapi/asm/siginfo.h ++++ b/arch/mips/include/uapi/asm/siginfo.h +@@ -28,7 +28,7 @@ + + #define __ARCH_SIGSYS + +-#include ++#include + + /* We can't use generic siginfo_t, because our si_code and si_errno are swapped */ + typedef struct siginfo { +@@ -42,13 +42,13 @@ typedef struct siginfo { + + /* kill() */ + struct { +- pid_t _pid; /* sender's pid */ ++ __kernel_pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { +- timer_t _tid; /* timer id */ ++ __kernel_timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; + sigval_t _sigval; /* same as below */ +@@ -57,26 +57,26 @@ typedef struct siginfo { + + /* POSIX.1b signals */ + struct { +- pid_t _pid; /* sender's pid */ ++ __kernel_pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { +- pid_t _pid; /* which child */ ++ __kernel_pid_t _pid; /* which child */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + int _status; /* exit code */ +- clock_t _utime; +- clock_t _stime; ++ __kernel_clock_t _utime; ++ __kernel_clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { +- pid_t _pid; /* which child */ +- clock_t _utime; ++ __kernel_pid_t _pid; /* which child */ ++ __kernel_clock_t _utime; + int _status; /* exit code */ +- clock_t _stime; ++ __kernel_clock_t _stime; + } _irix_sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ +@@ -118,6 +118,4 @@ typedef struct siginfo { + #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */ + #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */ + +-#include +- + #endif /* _UAPI_ASM_SIGINFO_H */ +diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c +index 1f5aac7..4674a74 100644 +--- a/arch/mips/kernel/mips-r2-to-r6-emul.c ++++ b/arch/mips/kernel/mips-r2-to-r6-emul.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -1251,10 +1252,10 @@ fpu_emul: + " j 10b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1326,10 +1327,10 @@ fpu_emul: + " j 10b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1397,10 +1398,10 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1467,10 +1468,10 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1582,14 +1583,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" +- " .word 5b,8b\n" +- " .word 6b,8b\n" +- " .word 7b,8b\n" +- " .word 0b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" ++ STR(PTR) " 5b,8b\n" ++ STR(PTR) " 6b,8b\n" ++ STR(PTR) " 7b,8b\n" ++ STR(PTR) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1701,14 +1702,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" +- " .word 5b,8b\n" +- " .word 6b,8b\n" +- " .word 7b,8b\n" +- " .word 0b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" ++ STR(PTR) " 5b,8b\n" ++ STR(PTR) " 6b,8b\n" ++ STR(PTR) " 7b,8b\n" ++ STR(PTR) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1820,14 +1821,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" +- " .word 5b,8b\n" +- " .word 6b,8b\n" +- " .word 7b,8b\n" +- " .word 0b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" ++ STR(PTR) " 5b,8b\n" ++ STR(PTR) " 6b,8b\n" ++ STR(PTR) " 7b,8b\n" ++ STR(PTR) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1938,14 +1939,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .word 1b,8b\n" +- " .word 2b,8b\n" +- " .word 3b,8b\n" +- " .word 4b,8b\n" +- " .word 5b,8b\n" +- " .word 6b,8b\n" +- " .word 7b,8b\n" +- " .word 0b,8b\n" ++ STR(PTR) " 1b,8b\n" ++ STR(PTR) " 2b,8b\n" ++ STR(PTR) " 3b,8b\n" ++ STR(PTR) " 4b,8b\n" ++ STR(PTR) " 5b,8b\n" ++ STR(PTR) " 6b,8b\n" ++ STR(PTR) " 7b,8b\n" ++ STR(PTR) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -2000,7 +2001,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- ".word 1b, 3b\n" ++ STR(PTR) " 1b,3b\n" + ".previous\n" + : "=&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV) +@@ -2058,7 +2059,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- ".word 1b, 3b\n" ++ STR(PTR) " 1b,3b\n" + ".previous\n" + : "+&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV)); +@@ -2119,7 +2120,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- ".word 1b, 3b\n" ++ STR(PTR) " 1b,3b\n" + ".previous\n" + : "=&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV) +@@ -2182,7 +2183,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- ".word 1b, 3b\n" ++ STR(PTR) " 1b,3b\n" + ".previous\n" + : "+&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV)); +diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c +index fefdf39..dc81489 100644 +--- a/arch/mips/kernel/pm.c ++++ b/arch/mips/kernel/pm.c +@@ -56,7 +56,7 @@ static void mips_cpu_restore(void) + write_c0_userlocal(current_thread_info()->tp_value); + + /* Restore watch registers */ +- __restore_watch(); ++ __restore_watch(current); + } + + /** +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index f2975d4..89847be 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -457,7 +457,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, + *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) { + regs = (struct pt_regs *)*sp; + pc = regs->cp0_epc; +- if (__kernel_text_address(pc)) { ++ if (!user_mode(regs) && __kernel_text_address(pc)) { + *sp = regs->regs[29]; + *ra = regs->regs[31]; + return pc; +@@ -603,6 +603,9 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6) + return -EOPNOTSUPP; + ++ /* Proceed with the mode switch */ ++ preempt_disable(); ++ + /* Save FP & vector context, then disable FPU & MSA */ + if (task->signal == current->signal) + lose_fpu(1); +@@ -661,6 +664,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + + /* Allow threads to use FP again */ + atomic_set(&task->mm->context.fp_mode_switching, 0); ++ preempt_enable(); + + return 0; + } +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index 4f0ac78..74d5815 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_struct *target) + /* Begin with data registers set to all 1s... */ + memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr)); + +- /* ...and FCSR zeroed */ +- target->thread.fpu.fcr31 = 0; ++ /* FCSR has been preset by `mips_set_personality_nan'. */ + + /* + * Record that the target has "used" math, such that the context +@@ -80,6 +79,22 @@ void ptrace_disable(struct task_struct *child) + } + + /* ++ * Poke at FCSR according to its mask. Don't set the cause bits as ++ * this is currently not handled correctly in FP context restoration ++ * and will cause an oops if a corresponding enable bit is set. ++ */ ++static void ptrace_setfcr31(struct task_struct *child, u32 value) ++{ ++ u32 fcr31; ++ u32 mask; ++ ++ value &= ~FPU_CSR_ALL_X; ++ fcr31 = child->thread.fpu.fcr31; ++ mask = boot_cpu_data.fpu_msk31; ++ child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); ++} ++ ++/* + * Read a general register set. We always use the 64-bit format, even + * for 32-bit kernels and for 32-bit processes on a 64-bit kernel. + * Registers are sign extended to fill the available space. +@@ -159,9 +174,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) + { + union fpureg *fregs; + u64 fpr_val; +- u32 fcr31; + u32 value; +- u32 mask; + int i; + + if (!access_ok(VERIFY_READ, data, 33 * 8)) +@@ -176,9 +189,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) + } + + __get_user(value, data + 64); +- fcr31 = child->thread.fpu.fcr31; +- mask = boot_cpu_data.fpu_msk31; +- child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); ++ ptrace_setfcr31(child, value); + + /* FIR may not be written. */ + +@@ -808,7 +819,7 @@ long arch_ptrace(struct task_struct *child, long request, + break; + #endif + case FPC_CSR: +- child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X; ++ ptrace_setfcr31(child, data); + break; + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; +diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S +index f09546e..bc74485 100644 +--- a/arch/mips/kernel/r4k_fpu.S ++++ b/arch/mips/kernel/r4k_fpu.S +@@ -244,17 +244,17 @@ LEAF(\name) + .set push + .set noat + #ifdef CONFIG_64BIT +- copy_u_d \wr, 1 ++ copy_s_d \wr, 1 + EX sd $1, \off(\base) + #elif defined(CONFIG_CPU_LITTLE_ENDIAN) +- copy_u_w \wr, 2 ++ copy_s_w \wr, 2 + EX sw $1, \off(\base) +- copy_u_w \wr, 3 ++ copy_s_w \wr, 3 + EX sw $1, (\off+4)(\base) + #else /* CONFIG_CPU_BIG_ENDIAN */ +- copy_u_w \wr, 2 ++ copy_s_w \wr, 2 + EX sw $1, (\off+4)(\base) +- copy_u_w \wr, 3 ++ copy_s_w \wr, 3 + EX sw $1, \off(\base) + #endif + .set pop +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index 66aac55..8acae31 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -706,6 +706,9 @@ static void __init arch_mem_init(char **cmdline_p) + for_each_memblock(reserved, reg) + if (reg->size != 0) + reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); ++ ++ reserve_bootmem_region(__pa_symbol(&__nosave_begin), ++ __pa_symbol(&__nosave_end)); /* Reserve for hibernation */ + } + + static void __init resource_init(void) +diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c +index bf792e2..9e35b6b 100644 +--- a/arch/mips/kernel/signal.c ++++ b/arch/mips/kernel/signal.c +@@ -195,6 +195,9 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size) + unsigned int csr; + int i, err; + ++ if (!config_enabled(CONFIG_CPU_HAS_MSA)) ++ return SIGSYS; ++ + if (size != sizeof(*msa)) + return -EINVAL; + +@@ -398,8 +401,8 @@ int protected_restore_fp_context(void __user *sc) + } + + fp_done: +- if (used & USED_EXTCONTEXT) +- err |= restore_extcontext(sc_to_extcontext(sc)); ++ if (!err && (used & USED_EXTCONTEXT)) ++ err = restore_extcontext(sc_to_extcontext(sc)); + + return err ?: sig; + } +@@ -767,15 +770,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) + sigset_t *oldset = sigmask_to_save(); + int ret; + struct mips_abi *abi = current->thread.abi; +-#ifdef CONFIG_CPU_MICROMIPS +- void *vdso; +- unsigned long tmp = (unsigned long)current->mm->context.vdso; +- +- set_isa16_mode(tmp); +- vdso = (void *)tmp; +-#else + void *vdso = current->mm->context.vdso; +-#endif + + if (regs->regs[0]) { + switch(regs->regs[2]) { +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index ca9a810..99a4022 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -144,7 +144,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) + if (!task) + task = current; + +- if (raw_show_trace || !__kernel_text_address(pc)) { ++ if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) { + show_raw_backtrace(sp); + return; + } +@@ -1241,7 +1241,7 @@ static int enable_restore_fp_context(int msa) + err = init_fpu(); + if (msa && !err) { + enable_msa(); +- _init_msa_upper(); ++ init_msa_upper(); + set_thread_flag(TIF_USEDMSA); + set_thread_flag(TIF_MSA_CTX_LIVE); + } +@@ -1304,7 +1304,7 @@ static int enable_restore_fp_context(int msa) + */ + prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE); + if (!prior_msa && was_fpu_owner) { +- _init_msa_upper(); ++ init_msa_upper(); + + goto out; + } +@@ -1321,7 +1321,7 @@ static int enable_restore_fp_context(int msa) + * of each vector register such that it cannot see data left + * behind by another task. + */ +- _init_msa_upper(); ++ init_msa_upper(); + } else { + /* We need to restore the vector context. */ + restore_msa(current); +diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c +index 490cea5..5c62065 100644 +--- a/arch/mips/kernel/unaligned.c ++++ b/arch/mips/kernel/unaligned.c +@@ -885,7 +885,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, + { + union mips_instruction insn; + unsigned long value; +- unsigned int res; ++ unsigned int res, preempted; + unsigned long origpc; + unsigned long orig31; + void __user *fault_addr = NULL; +@@ -1226,27 +1226,36 @@ static void emulate_load_store_insn(struct pt_regs *regs, + if (!access_ok(VERIFY_READ, addr, sizeof(*fpr))) + goto sigbus; + +- /* +- * Disable preemption to avoid a race between copying +- * state from userland, migrating to another CPU and +- * updating the hardware vector register below. +- */ +- preempt_disable(); +- +- res = __copy_from_user_inatomic(fpr, addr, +- sizeof(*fpr)); +- if (res) +- goto fault; +- +- /* +- * Update the hardware register if it is in use by the +- * task in this quantum, in order to avoid having to +- * save & restore the whole vector context. +- */ +- if (test_thread_flag(TIF_USEDMSA)) +- write_msa_wr(wd, fpr, df); ++ do { ++ /* ++ * If we have live MSA context keep track of ++ * whether we get preempted in order to avoid ++ * the register context we load being clobbered ++ * by the live context as it's saved during ++ * preemption. If we don't have live context ++ * then it can't be saved to clobber the value ++ * we load. ++ */ ++ preempted = test_thread_flag(TIF_USEDMSA); ++ ++ res = __copy_from_user_inatomic(fpr, addr, ++ sizeof(*fpr)); ++ if (res) ++ goto fault; + +- preempt_enable(); ++ /* ++ * Update the hardware register if it is in use ++ * by the task in this quantum, in order to ++ * avoid having to save & restore the whole ++ * vector context. ++ */ ++ preempt_disable(); ++ if (test_thread_flag(TIF_USEDMSA)) { ++ write_msa_wr(wd, fpr, df); ++ preempted = 0; ++ } ++ preempt_enable(); ++ } while (preempted); + break; + + case msa_st_op: +diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c +index 2a03abb..9b78e37 100644 +--- a/arch/mips/kernel/watch.c ++++ b/arch/mips/kernel/watch.c +@@ -15,10 +15,9 @@ + * Install the watch registers for the current thread. A maximum of + * four registers are installed although the machine may have more. + */ +-void mips_install_watch_registers(void) ++void mips_install_watch_registers(struct task_struct *t) + { +- struct mips3264_watch_reg_state *watches = +- ¤t->thread.watch.mips3264; ++ struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; + switch (current_cpu_data.watch_reg_use_cnt) { + default: + BUG(); +diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c +index 41b1b09..dc10c77 100644 +--- a/arch/mips/kvm/emulate.c ++++ b/arch/mips/kvm/emulate.c +@@ -302,12 +302,31 @@ static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu) + */ + static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) + { +- ktime_t expires; ++ struct mips_coproc *cop0 = vcpu->arch.cop0; ++ ktime_t expires, threshold; ++ uint32_t count, compare; + int running; + +- /* Is the hrtimer pending? */ ++ /* Calculate the biased and scaled guest CP0_Count */ ++ count = vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now); ++ compare = kvm_read_c0_guest_compare(cop0); ++ ++ /* ++ * Find whether CP0_Count has reached the closest timer interrupt. If ++ * not, we shouldn't inject it. ++ */ ++ if ((int32_t)(count - compare) < 0) ++ return count; ++ ++ /* ++ * The CP0_Count we're going to return has already reached the closest ++ * timer interrupt. Quickly check if it really is a new interrupt by ++ * looking at whether the interval until the hrtimer expiry time is ++ * less than 1/4 of the timer period. ++ */ + expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer); +- if (ktime_compare(now, expires) >= 0) { ++ threshold = ktime_add_ns(now, vcpu->arch.count_period / 4); ++ if (ktime_before(expires, threshold)) { + /* + * Cancel it while we handle it so there's no chance of + * interference with the timeout handler. +@@ -329,8 +348,7 @@ static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) + } + } + +- /* Return the biased and scaled guest CP0_Count */ +- return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now); ++ return count; + } + + /** +@@ -420,32 +438,6 @@ static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu, + } + + /** +- * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer. +- * @vcpu: Virtual CPU. +- * +- * Recalculates and updates the expiry time of the hrtimer. This can be used +- * after timer parameters have been altered which do not depend on the time that +- * the change occurs (in those cases kvm_mips_freeze_hrtimer() and +- * kvm_mips_resume_hrtimer() are used directly). +- * +- * It is guaranteed that no timer interrupts will be lost in the process. +- * +- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running). +- */ +-static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu) +-{ +- ktime_t now; +- uint32_t count; +- +- /* +- * freeze_hrtimer takes care of a timer interrupts <= count, and +- * resume_hrtimer the hrtimer takes care of a timer interrupts > count. +- */ +- now = kvm_mips_freeze_hrtimer(vcpu, &count); +- kvm_mips_resume_hrtimer(vcpu, now, count); +-} +- +-/** + * kvm_mips_write_count() - Modify the count and update timer. + * @vcpu: Virtual CPU. + * @count: Guest CP0_Count value to set. +@@ -540,23 +532,42 @@ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz) + * kvm_mips_write_compare() - Modify compare and update timer. + * @vcpu: Virtual CPU. + * @compare: New CP0_Compare value. ++ * @ack: Whether to acknowledge timer interrupt. + * + * Update CP0_Compare to a new value and update the timeout. ++ * If @ack, atomically acknowledge any pending timer interrupt, otherwise ensure ++ * any pending timer interrupt is preserved. + */ +-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare) ++void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack) + { + struct mips_coproc *cop0 = vcpu->arch.cop0; ++ int dc; ++ u32 old_compare = kvm_read_c0_guest_compare(cop0); ++ ktime_t now; ++ uint32_t count; + + /* if unchanged, must just be an ack */ +- if (kvm_read_c0_guest_compare(cop0) == compare) ++ if (old_compare == compare) { ++ if (!ack) ++ return; ++ kvm_mips_callbacks->dequeue_timer_int(vcpu); ++ kvm_write_c0_guest_compare(cop0, compare); + return; ++ } ++ ++ /* freeze_hrtimer() takes care of timer interrupts <= count */ ++ dc = kvm_mips_count_disabled(vcpu); ++ if (!dc) ++ now = kvm_mips_freeze_hrtimer(vcpu, &count); ++ ++ if (ack) ++ kvm_mips_callbacks->dequeue_timer_int(vcpu); + +- /* Update compare */ + kvm_write_c0_guest_compare(cop0, compare); + +- /* Update timeout if count enabled */ +- if (!kvm_mips_count_disabled(vcpu)) +- kvm_mips_update_hrtimer(vcpu); ++ /* resume_hrtimer() takes care of timer interrupts > count */ ++ if (!dc) ++ kvm_mips_resume_hrtimer(vcpu, now, count); + } + + /** +@@ -1095,9 +1106,9 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, + + /* If we are writing to COMPARE */ + /* Clear pending timer interrupt, if any */ +- kvm_mips_callbacks->dequeue_timer_int(vcpu); + kvm_mips_write_compare(vcpu, +- vcpu->arch.gprs[rt]); ++ vcpu->arch.gprs[rt], ++ true); + } else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) { + unsigned int old_val, val, change; + +diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c +index 2683d04..8a11329 100644 +--- a/arch/mips/kvm/mips.c ++++ b/arch/mips/kvm/mips.c +@@ -445,8 +445,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, + + dvcpu->arch.wait = 0; + +- if (waitqueue_active(&dvcpu->wq)) +- wake_up_interruptible(&dvcpu->wq); ++ if (swait_active(&dvcpu->wq)) ++ swake_up(&dvcpu->wq); + + return 0; + } +@@ -1174,8 +1174,8 @@ static void kvm_mips_comparecount_func(unsigned long data) + kvm_mips_callbacks->queue_timer_int(vcpu); + + vcpu->arch.wait = 0; +- if (waitqueue_active(&vcpu->wq)) +- wake_up_interruptible(&vcpu->wq); ++ if (swait_active(&vcpu->wq)) ++ swake_up(&vcpu->wq); + } + + /* low level hrtimer wake routine */ +diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c +index d836ed5..307cc4c 100644 +--- a/arch/mips/kvm/trap_emul.c ++++ b/arch/mips/kvm/trap_emul.c +@@ -547,7 +547,7 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu, + kvm_mips_write_count(vcpu, v); + break; + case KVM_REG_MIPS_CP0_COMPARE: +- kvm_mips_write_compare(vcpu, v); ++ kvm_mips_write_compare(vcpu, v, false); + break; + case KVM_REG_MIPS_CP0_CAUSE: + /* +diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c +index beb80f3..927dc94 100644 +--- a/arch/mips/lib/ashldi3.c ++++ b/arch/mips/lib/ashldi3.c +@@ -2,7 +2,7 @@ + + #include "libgcc.h" + +-long long __ashldi3(long long u, word_type b) ++long long notrace __ashldi3(long long u, word_type b) + { + DWunion uu, w; + word_type bm; +diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c +index c884a91..9fdf1a5 100644 +--- a/arch/mips/lib/ashrdi3.c ++++ b/arch/mips/lib/ashrdi3.c +@@ -2,7 +2,7 @@ + + #include "libgcc.h" + +-long long __ashrdi3(long long u, word_type b) ++long long notrace __ashrdi3(long long u, word_type b) + { + DWunion uu, w; + word_type bm; +diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c +index 77e5f9c..e3e77aa 100644 +--- a/arch/mips/lib/bswapdi.c ++++ b/arch/mips/lib/bswapdi.c +@@ -1,6 +1,6 @@ + #include + +-unsigned long long __bswapdi2(unsigned long long u) ++unsigned long long notrace __bswapdi2(unsigned long long u) + { + return (((u) & 0xff00000000000000ull) >> 56) | + (((u) & 0x00ff000000000000ull) >> 40) | +diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c +index 2b302ff..530a8af 100644 +--- a/arch/mips/lib/bswapsi.c ++++ b/arch/mips/lib/bswapsi.c +@@ -1,6 +1,6 @@ + #include + +-unsigned int __bswapsi2(unsigned int u) ++unsigned int notrace __bswapsi2(unsigned int u) + { + return (((u) & 0xff000000) >> 24) | + (((u) & 0x00ff0000) >> 8) | +diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c +index 8c13064..06857da 100644 +--- a/arch/mips/lib/cmpdi2.c ++++ b/arch/mips/lib/cmpdi2.c +@@ -2,7 +2,7 @@ + + #include "libgcc.h" + +-word_type __cmpdi2(long long a, long long b) ++word_type notrace __cmpdi2(long long a, long long b) + { + const DWunion au = { + .ll = a +diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c +index dcf8d68..3645474 100644 +--- a/arch/mips/lib/lshrdi3.c ++++ b/arch/mips/lib/lshrdi3.c +@@ -2,7 +2,7 @@ + + #include "libgcc.h" + +-long long __lshrdi3(long long u, word_type b) ++long long notrace __lshrdi3(long long u, word_type b) + { + DWunion uu, w; + word_type bm; +diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c +index bb4cb2f..bd599f5 100644 +--- a/arch/mips/lib/ucmpdi2.c ++++ b/arch/mips/lib/ucmpdi2.c +@@ -2,7 +2,7 @@ + + #include "libgcc.h" + +-word_type __ucmpdi2(unsigned long long a, unsigned long long b) ++word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b) + { + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; +diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c +index 6f9e010..282c5a8 100644 +--- a/arch/mips/loongson64/loongson-3/numa.c ++++ b/arch/mips/loongson64/loongson-3/numa.c +@@ -213,10 +213,10 @@ static void __init node_mem_init(unsigned int node) + BOOTMEM_DEFAULT); + + if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) { +- /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */ ++ /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ + reserve_bootmem_node(NODE_DATA(node), +- (node_addrspace_offset | 0xff800000), +- 8 << 20, BOOTMEM_DEFAULT); ++ (node_addrspace_offset | 0xfe000000), ++ 32 << 20, BOOTMEM_DEFAULT); + } + + sparse_memory_present_with_active_regions(node); +diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c +index 32f0e19..734a2c7 100644 +--- a/arch/mips/math-emu/cp1emu.c ++++ b/arch/mips/math-emu/cp1emu.c +@@ -445,9 +445,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, + case spec_op: + switch (insn.r_format.func) { + case jalr_op: +- regs->regs[insn.r_format.rd] = +- regs->cp0_epc + dec_insn.pc_inc + +- dec_insn.next_pc_inc; ++ if (insn.r_format.rd != 0) { ++ regs->regs[insn.r_format.rd] = ++ regs->cp0_epc + dec_insn.pc_inc + ++ dec_insn.next_pc_inc; ++ } + /* Fall through */ + case jr_op: + /* For R6, JR already emulated in jalr_op */ +diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c +index aab218c..e87bccd 100644 +--- a/arch/mips/mm/cache.c ++++ b/arch/mips/mm/cache.c +@@ -16,6 +16,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -83,8 +84,6 @@ void __flush_dcache_page(struct page *page) + struct address_space *mapping = page_mapping(page); + unsigned long addr; + +- if (PageHighMem(page)) +- return; + if (mapping && !mapping_mapped(mapping)) { + SetPageDcacheDirty(page); + return; +@@ -95,8 +94,15 @@ void __flush_dcache_page(struct page *page) + * case is for exec env/arg pages and those are %99 certainly going to + * get faulted into the tlb (and thus flushed) anyways. + */ +- addr = (unsigned long) page_address(page); ++ if (PageHighMem(page)) ++ addr = (unsigned long)kmap_atomic(page); ++ else ++ addr = (unsigned long)page_address(page); ++ + flush_data_cache_page(addr); ++ ++ if (PageHighMem(page)) ++ __kunmap_atomic((void *)addr); + } + + EXPORT_SYMBOL(__flush_dcache_page); +@@ -119,33 +125,28 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) + + EXPORT_SYMBOL(__flush_anon_page); + +-void __flush_icache_page(struct vm_area_struct *vma, struct page *page) +-{ +- unsigned long addr; +- +- if (PageHighMem(page)) +- return; +- +- addr = (unsigned long) page_address(page); +- flush_data_cache_page(addr); +-} +-EXPORT_SYMBOL_GPL(__flush_icache_page); +- +-void __update_cache(struct vm_area_struct *vma, unsigned long address, +- pte_t pte) ++void __update_cache(unsigned long address, pte_t pte) + { + struct page *page; + unsigned long pfn, addr; +- int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; ++ int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc; + + pfn = pte_pfn(pte); + if (unlikely(!pfn_valid(pfn))) + return; + page = pfn_to_page(pfn); +- if (page_mapping(page) && Page_dcache_dirty(page)) { +- addr = (unsigned long) page_address(page); ++ if (Page_dcache_dirty(page)) { ++ if (PageHighMem(page)) ++ addr = (unsigned long)kmap_atomic(page); ++ else ++ addr = (unsigned long)page_address(page); ++ + if (exec || pages_do_alias(addr, address & PAGE_MASK)) + flush_data_cache_page(addr); ++ ++ if (PageHighMem(page)) ++ __kunmap_atomic((void *)addr); ++ + ClearPageDcacheDirty(page); + } + } +diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile +index 1456890..090393a 100644 +--- a/arch/mips/vdso/Makefile ++++ b/arch/mips/vdso/Makefile +@@ -5,10 +5,12 @@ obj-vdso-y := elf.o gettimeofday.o sigreturn.o + ccflags-vdso := \ + $(filter -I%,$(KBUILD_CFLAGS)) \ + $(filter -E%,$(KBUILD_CFLAGS)) \ ++ $(filter -mmicromips,$(KBUILD_CFLAGS)) \ + $(filter -march=%,$(KBUILD_CFLAGS)) + cflags-vdso := $(ccflags-vdso) \ + $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ +- -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \ ++ -O2 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \ ++ -DDISABLE_BRANCH_PROFILING \ + $(call cc-option, -fno-stack-protector) + aflags-vdso := $(ccflags-vdso) \ + $(filter -I%,$(KBUILD_CFLAGS)) \ +diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h +index 0abdd4c..1960b87 100644 +--- a/arch/parisc/include/asm/uaccess.h ++++ b/arch/parisc/include/asm/uaccess.h +@@ -76,6 +76,7 @@ struct exception_table_entry { + */ + struct exception_data { + unsigned long fault_ip; ++ unsigned long fault_gp; + unsigned long fault_space; + unsigned long fault_addr; + }; +diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c +index d2f6257..78d30d2 100644 +--- a/arch/parisc/kernel/asm-offsets.c ++++ b/arch/parisc/kernel/asm-offsets.c +@@ -299,6 +299,7 @@ int main(void) + #endif + BLANK(); + DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); ++ DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp)); + DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); + DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); + BLANK(); +diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c +index 568b2c6..3cad8aa 100644 +--- a/arch/parisc/kernel/parisc_ksyms.c ++++ b/arch/parisc/kernel/parisc_ksyms.c +@@ -47,11 +47,11 @@ EXPORT_SYMBOL(__cmpxchg_u64); + EXPORT_SYMBOL(lclear_user); + EXPORT_SYMBOL(lstrnlen_user); + +-/* Global fixups */ +-extern void fixup_get_user_skip_1(void); +-extern void fixup_get_user_skip_2(void); +-extern void fixup_put_user_skip_1(void); +-extern void fixup_put_user_skip_2(void); ++/* Global fixups - defined as int to avoid creation of function pointers */ ++extern int fixup_get_user_skip_1; ++extern int fixup_get_user_skip_2; ++extern int fixup_put_user_skip_1; ++extern int fixup_put_user_skip_2; + EXPORT_SYMBOL(fixup_get_user_skip_1); + EXPORT_SYMBOL(fixup_get_user_skip_2); + EXPORT_SYMBOL(fixup_put_user_skip_1); +diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c +index 553b098..77e2262 100644 +--- a/arch/parisc/kernel/traps.c ++++ b/arch/parisc/kernel/traps.c +@@ -798,6 +798,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs) + + if (fault_space == 0 && !faulthandler_disabled()) + { ++ /* Clean up and return if in exception table. */ ++ if (fixup_exception(regs)) ++ return; + pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); + parisc_terminate("Kernel Fault", regs, code, fault_address); + } +diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c +index d7c0acb..8d49614 100644 +--- a/arch/parisc/kernel/unaligned.c ++++ b/arch/parisc/kernel/unaligned.c +@@ -666,7 +666,7 @@ void handle_unaligned(struct pt_regs *regs) + break; + } + +- if (modify && R1(regs->iir)) ++ if (ret == 0 && modify && R1(regs->iir)) + regs->gr[R1(regs->iir)] = newbase; + + +@@ -677,6 +677,14 @@ void handle_unaligned(struct pt_regs *regs) + + if (ret) + { ++ /* ++ * The unaligned handler failed. ++ * If we were called by __get_user() or __put_user() jump ++ * to it's exception fixup handler instead of crashing. ++ */ ++ if (!user_mode(regs) && fixup_exception(regs)) ++ return; ++ + printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); + die_if_kernel("Unaligned data reference", regs, 28); + +diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S +index 536ef66..1052b74 100644 +--- a/arch/parisc/lib/fixup.S ++++ b/arch/parisc/lib/fixup.S +@@ -26,6 +26,7 @@ + + #ifdef CONFIG_SMP + .macro get_fault_ip t1 t2 ++ loadgp + addil LT%__per_cpu_offset,%r27 + LDREG RT%__per_cpu_offset(%r1),\t1 + /* t2 = smp_processor_id() */ +@@ -40,14 +41,19 @@ + LDREG RT%exception_data(%r1),\t1 + /* t1 = this_cpu_ptr(&exception_data) */ + add,l \t1,\t2,\t1 ++ /* %r27 = t1->fault_gp - restore gp */ ++ LDREG EXCDATA_GP(\t1), %r27 + /* t1 = t1->fault_ip */ + LDREG EXCDATA_IP(\t1), \t1 + .endm + #else + .macro get_fault_ip t1 t2 ++ loadgp + /* t1 = this_cpu_ptr(&exception_data) */ + addil LT%exception_data,%r27 + LDREG RT%exception_data(%r1),\t2 ++ /* %r27 = t2->fault_gp - restore gp */ ++ LDREG EXCDATA_GP(\t2), %r27 + /* t1 = t2->fault_ip */ + LDREG EXCDATA_IP(\t2), \t1 + .endm +diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c +index a762864..f906444 100644 +--- a/arch/parisc/mm/fault.c ++++ b/arch/parisc/mm/fault.c +@@ -151,6 +151,7 @@ int fixup_exception(struct pt_regs *regs) + struct exception_data *d; + d = this_cpu_ptr(&exception_data); + d->fault_ip = regs->iaoq[0]; ++ d->fault_gp = regs->gr[27]; + d->fault_space = regs->isr; + d->fault_addr = regs->ior; + +diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h +index b439518..f8673ff 100644 +--- a/arch/powerpc/include/asm/kvm_host.h ++++ b/arch/powerpc/include/asm/kvm_host.h +@@ -286,7 +286,7 @@ struct kvmppc_vcore { + struct list_head runnable_threads; + struct list_head preempt_list; + spinlock_t lock; +- struct swait_head wq; ++ struct swait_queue_head wq; + spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */ + u64 stolen_tb; + u64 preempt_tb; +@@ -626,7 +626,7 @@ struct kvm_vcpu_arch { + u8 prodded; + u32 last_inst; + +- struct swait_head *wqp; ++ struct swait_queue_head *wqp; + struct kvmppc_vcore *vcore; + int ret; + int trap; +diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h +index 2220f7a..070fa85 100644 +--- a/arch/powerpc/include/asm/reg.h ++++ b/arch/powerpc/include/asm/reg.h +@@ -707,7 +707,7 @@ + #define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ + #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ + #define SPRN_MMCR1 798 +-#define SPRN_MMCR2 769 ++#define SPRN_MMCR2 785 + #define SPRN_MMCRA 0x312 + #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ + #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL +@@ -744,13 +744,13 @@ + #define SPRN_PMC6 792 + #define SPRN_PMC7 793 + #define SPRN_PMC8 794 +-#define SPRN_SIAR 780 +-#define SPRN_SDAR 781 + #define SPRN_SIER 784 + #define SIER_SIPR 0x2000000 /* Sampled MSR_PR */ + #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */ + #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */ + #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */ ++#define SPRN_SIAR 796 ++#define SPRN_SDAR 797 + #define SPRN_TACR 888 + #define SPRN_TCSCR 889 + #define SPRN_CSIGR 890 +diff --git a/arch/powerpc/include/asm/word-at-a-time.h b/arch/powerpc/include/asm/word-at-a-time.h +index e4396a7..4afe66a 100644 +--- a/arch/powerpc/include/asm/word-at-a-time.h ++++ b/arch/powerpc/include/asm/word-at-a-time.h +@@ -82,7 +82,7 @@ static inline unsigned long create_zero_mask(unsigned long bits) + "andc %1,%1,%2\n\t" + "popcntd %0,%1" + : "=r" (leading_zero_bits), "=&r" (trailing_zero_bit_mask) +- : "r" (bits)); ++ : "b" (bits)); + + return leading_zero_bits; + } +diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h +index 4368604..2734c00 100644 +--- a/arch/powerpc/include/uapi/asm/cputable.h ++++ b/arch/powerpc/include/uapi/asm/cputable.h +@@ -31,6 +31,7 @@ + #define PPC_FEATURE_PSERIES_PERFMON_COMPAT \ + 0x00000040 + ++/* Reserved - do not use 0x00000004 */ + #define PPC_FEATURE_TRUE_LE 0x00000002 + #define PPC_FEATURE_PPC_LE 0x00000001 + +diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c +index 40e4d4a..b34e8a5 100644 +--- a/arch/powerpc/kernel/eeh.c ++++ b/arch/powerpc/kernel/eeh.c +@@ -1072,7 +1072,7 @@ void eeh_add_device_early(struct pci_dn *pdn) + struct pci_controller *phb; + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); + +- if (!edev || !eeh_enabled()) ++ if (!edev) + return; + + if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) +diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c +index 52c1e27..247a0dc 100644 +--- a/arch/powerpc/kernel/eeh_driver.c ++++ b/arch/powerpc/kernel/eeh_driver.c +@@ -166,6 +166,16 @@ static void *eeh_dev_save_state(void *data, void *userdata) + if (!edev) + return NULL; + ++ /* ++ * We cannot access the config space on some adapters. ++ * Otherwise, it will cause fenced PHB. We don't save ++ * the content in their config space and will restore ++ * from the initial config space saved when the EEH ++ * device is created. ++ */ ++ if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) ++ return NULL; ++ + pdev = eeh_dev_to_pci_dev(edev); + if (!pdev) + return NULL; +@@ -305,6 +315,19 @@ static void *eeh_dev_restore_state(void *data, void *userdata) + if (!edev) + return NULL; + ++ /* ++ * The content in the config space isn't saved because ++ * the blocked config space on some adapters. We have ++ * to restore the initial saved config space when the ++ * EEH device is created. ++ */ ++ if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) { ++ if (list_is_last(&edev->list, &edev->pe->edevs)) ++ eeh_pe_restore_bars(edev->pe); ++ ++ return NULL; ++ } ++ + pdev = eeh_dev_to_pci_dev(edev); + if (!pdev) + return NULL; +@@ -504,9 +527,6 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe) + /* Save states */ + eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL); + +- /* Report error */ +- eeh_pe_dev_traverse(pe, eeh_report_error, &result); +- + /* Issue reset */ + ret = eeh_reset_pe(pe); + if (ret) { +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index 0a0399c..b81ccc5 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -962,11 +962,6 @@ hv_facility_unavailable_relon_trampoline: + #endif + STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist) + +- /* Other future vectors */ +- .align 7 +- .globl __end_interrupts +-__end_interrupts: +- + .align 7 + system_call_entry: + b system_call_common +@@ -1253,6 +1248,17 @@ __end_handlers: + STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable) + STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable) + ++ /* ++ * The __end_interrupts marker must be past the out-of-line (OOL) ++ * handlers, so that they are copied to real address 0x100 when running ++ * a relocatable kernel. This ensures they can be reached from the short ++ * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch ++ * directly, without using LOAD_HANDLER(). ++ */ ++ .align 7 ++ .globl __end_interrupts ++__end_interrupts: ++ + #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) + /* + * Data area reserved for FWNMI option. +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index ef2ad2d..646bf4d 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -569,24 +569,6 @@ static void tm_reclaim_thread(struct thread_struct *thr, + if (!MSR_TM_SUSPENDED(mfmsr())) + return; + +- /* +- * Use the current MSR TM suspended bit to track if we have +- * checkpointed state outstanding. +- * On signal delivery, we'd normally reclaim the checkpointed +- * state to obtain stack pointer (see:get_tm_stackpointer()). +- * This will then directly return to userspace without going +- * through __switch_to(). However, if the stack frame is bad, +- * we need to exit this thread which calls __switch_to() which +- * will again attempt to reclaim the already saved tm state. +- * Hence we need to check that we've not already reclaimed +- * this state. +- * We do this using the current MSR, rather tracking it in +- * some specific thread_struct bit, as it has the additional +- * benifit of checking for a potential TM bad thing exception. +- */ +- if (!MSR_TM_SUSPENDED(mfmsr())) +- return; +- + tm_reclaim(thr, thr->regs->msr, cause); + + /* Having done the reclaim, we now have the checkpointed +diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c +index 7030b03..a15fe1d 100644 +--- a/arch/powerpc/kernel/prom.c ++++ b/arch/powerpc/kernel/prom.c +@@ -148,23 +148,25 @@ static struct ibm_pa_feature { + unsigned long cpu_features; /* CPU_FTR_xxx bit */ + unsigned long mmu_features; /* MMU_FTR_xxx bit */ + unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */ ++ unsigned int cpu_user_ftrs2; /* PPC_FEATURE2_xxx bit */ + unsigned char pabyte; /* byte number in ibm,pa-features */ + unsigned char pabit; /* bit number (big-endian) */ + unsigned char invert; /* if 1, pa bit set => clear feature */ + } ibm_pa_features[] __initdata = { +- {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, +- {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, +- {CPU_FTR_CTRL, 0, 0, 0, 3, 0}, +- {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0}, +- {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, +- {0, MMU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, +- {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, ++ {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0, 0}, ++ {0, 0, PPC_FEATURE_HAS_FPU, 0, 0, 1, 0}, ++ {CPU_FTR_CTRL, 0, 0, 0, 0, 3, 0}, ++ {CPU_FTR_NOEXECUTE, 0, 0, 0, 0, 6, 0}, ++ {CPU_FTR_NODSISRALIGN, 0, 0, 0, 1, 1, 1}, ++ {0, MMU_FTR_CI_LARGE_PAGE, 0, 0, 1, 2, 0}, ++ {CPU_FTR_REAL_LE, 0, PPC_FEATURE_TRUE_LE, 0, 5, 0, 0}, + /* +- * If the kernel doesn't support TM (ie. CONFIG_PPC_TRANSACTIONAL_MEM=n), +- * we don't want to turn on CPU_FTR_TM here, so we use CPU_FTR_TM_COMP +- * which is 0 if the kernel doesn't support TM. ++ * If the kernel doesn't support TM (ie CONFIG_PPC_TRANSACTIONAL_MEM=n), ++ * we don't want to turn on TM here, so we use the *_COMP versions ++ * which are 0 if the kernel doesn't support TM. + */ +- {CPU_FTR_TM_COMP, 0, 0, 22, 0, 0}, ++ {CPU_FTR_TM_COMP, 0, 0, ++ PPC_FEATURE2_HTM_COMP|PPC_FEATURE2_HTM_NOSC_COMP, 22, 0, 0}, + }; + + static void __init scan_features(unsigned long node, const unsigned char *ftrs, +@@ -195,10 +197,12 @@ static void __init scan_features(unsigned long node, const unsigned char *ftrs, + if (bit ^ fp->invert) { + cur_cpu_spec->cpu_features |= fp->cpu_features; + cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; ++ cur_cpu_spec->cpu_user_features2 |= fp->cpu_user_ftrs2; + cur_cpu_spec->mmu_features |= fp->mmu_features; + } else { + cur_cpu_spec->cpu_features &= ~fp->cpu_features; + cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs; ++ cur_cpu_spec->cpu_user_features2 &= ~fp->cpu_user_ftrs2; + cur_cpu_spec->mmu_features &= ~fp->mmu_features; + } + } +diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c +index 92dea8d..e52b82b 100644 +--- a/arch/powerpc/kernel/prom_init.c ++++ b/arch/powerpc/kernel/prom_init.c +@@ -655,6 +655,7 @@ unsigned char ibm_architecture_vec[] = { + W(0xffff0000), W(0x003e0000), /* POWER6 */ + W(0xffff0000), W(0x003f0000), /* POWER7 */ + W(0xffff0000), W(0x004b0000), /* POWER8E */ ++ W(0xffff0000), W(0x004c0000), /* POWER8NVL */ + W(0xffff0000), W(0x004d0000), /* POWER8 */ + W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ + W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 32be32b..df34a64 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -114,11 +114,11 @@ static bool kvmppc_ipi_thread(int cpu) + static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) + { + int cpu; +- struct swait_head *wqp; ++ struct swait_queue_head *wqp; + + wqp = kvm_arch_vcpu_wq(vcpu); +- if (swaitqueue_active(wqp)) { +- swait_wake_interruptible(wqp); ++ if (swait_active(wqp)) { ++ swake_up(wqp); + ++vcpu->stat.halt_wakeup; + } + +@@ -707,8 +707,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) + tvcpu->arch.prodded = 1; + smp_mb(); + if (vcpu->arch.ceded) { +- if (swaitqueue_active(&vcpu->wq)) { +- swait_wake_interruptible(&vcpu->wq); ++ if (swait_active(&vcpu->wq)) { ++ swake_up(&vcpu->wq); + vcpu->stat.halt_wakeup++; + } + } +@@ -1447,7 +1447,7 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core) + INIT_LIST_HEAD(&vcore->runnable_threads); + spin_lock_init(&vcore->lock); + spin_lock_init(&vcore->stoltb_lock); +- init_swait_head(&vcore->wq); ++ init_swait_queue_head(&vcore->wq); + vcore->preempt_tb = TB_NIL; + vcore->lpcr = kvm->arch.lpcr; + vcore->first_vcpuid = core * threads_per_subcore; +@@ -2519,9 +2519,9 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) + { + struct kvm_vcpu *vcpu; + int do_sleep = 1; +- DEFINE_SWAITER(wait); ++ DECLARE_SWAITQUEUE(wait); + +- swait_prepare(&vc->wq, &wait, TASK_INTERRUPTIBLE); ++ prepare_to_swait(&vc->wq, &wait, TASK_INTERRUPTIBLE); + + /* + * Check one last time for pending exceptions and ceded state after +@@ -2535,7 +2535,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) + } + + if (!do_sleep) { +- swait_finish(&vc->wq, &wait); ++ finish_swait(&vc->wq, &wait); + return; + } + +@@ -2543,7 +2543,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) + trace_kvmppc_vcore_blocked(vc, 0); + spin_unlock(&vc->lock); + schedule(); +- swait_finish(&vc->wq, &wait); ++ finish_swait(&vc->wq, &wait); + spin_lock(&vc->lock); + vc->vcore_state = VCORE_INACTIVE; + trace_kvmppc_vcore_blocked(vc, 1); +@@ -2599,7 +2599,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) + kvmppc_start_thread(vcpu, vc); + trace_kvm_guest_enter(vcpu); + } else if (vc->vcore_state == VCORE_SLEEPING) { +- swait_wake(&vc->wq); ++ swake_up(&vc->wq); + } + + } +diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c +index 9833fee..807f159 100644 +--- a/arch/powerpc/mm/hugetlbpage.c ++++ b/arch/powerpc/mm/hugetlbpage.c +@@ -486,13 +486,13 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte) + { + struct hugepd_freelist **batchp; + +- batchp = this_cpu_ptr(&hugepd_freelist_cur); ++ batchp = &get_cpu_var(hugepd_freelist_cur); + + if (atomic_read(&tlb->mm->mm_users) < 2 || + cpumask_equal(mm_cpumask(tlb->mm), + cpumask_of(smp_processor_id()))) { + kmem_cache_free(hugepte_cache, hugepte); +- put_cpu_var(hugepd_freelist_cur); ++ put_cpu_var(hugepd_freelist_cur); + return; + } + +diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c +index ac3ffd9..405baaf 100644 +--- a/arch/powerpc/platforms/pseries/eeh_pseries.c ++++ b/arch/powerpc/platforms/pseries/eeh_pseries.c +@@ -615,29 +615,50 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) + { + int config_addr; + int ret; ++ /* Waiting 0.2s maximum before skipping configuration */ ++ int max_wait = 200; + + /* Figure out the PE address */ + config_addr = pe->config_addr; + if (pe->addr) + config_addr = pe->addr; + +- /* Use new configure-pe function, if supported */ +- if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { +- ret = rtas_call(ibm_configure_pe, 3, 1, NULL, +- config_addr, BUID_HI(pe->phb->buid), +- BUID_LO(pe->phb->buid)); +- } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { +- ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, +- config_addr, BUID_HI(pe->phb->buid), +- BUID_LO(pe->phb->buid)); +- } else { +- return -EFAULT; +- } ++ while (max_wait > 0) { ++ /* Use new configure-pe function, if supported */ ++ if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { ++ ret = rtas_call(ibm_configure_pe, 3, 1, NULL, ++ config_addr, BUID_HI(pe->phb->buid), ++ BUID_LO(pe->phb->buid)); ++ } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { ++ ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, ++ config_addr, BUID_HI(pe->phb->buid), ++ BUID_LO(pe->phb->buid)); ++ } else { ++ return -EFAULT; ++ } + +- if (ret) +- pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", +- __func__, pe->phb->global_number, pe->addr, ret); ++ if (!ret) ++ return ret; ++ ++ /* ++ * If RTAS returns a delay value that's above 100ms, cut it ++ * down to 100ms in case firmware made a mistake. For more ++ * on how these delay values work see rtas_busy_delay_time ++ */ ++ if (ret > RTAS_EXTENDED_DELAY_MIN+2 && ++ ret <= RTAS_EXTENDED_DELAY_MAX) ++ ret = RTAS_EXTENDED_DELAY_MIN+2; ++ ++ max_wait -= rtas_busy_delay_time(ret); ++ ++ if (max_wait < 0) ++ break; ++ ++ rtas_busy_delay(ret); ++ } + ++ pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", ++ __func__, pe->phb->global_number, pe->addr, ret); + return ret; + } + +diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h +index 2a84c76..bbdc539 100644 +--- a/arch/s390/include/asm/kvm_host.h ++++ b/arch/s390/include/asm/kvm_host.h +@@ -427,7 +427,7 @@ struct kvm_s390_irq_payload { + struct kvm_s390_local_interrupt { + spinlock_t lock; + struct kvm_s390_float_interrupt *float_int; +- struct swait_head *wq; ++ struct swait_queue_head *wq; + atomic_t *cpuflags; + DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS); + struct kvm_s390_irq_payload irq; +diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h +index d29ad95..081b2ad 100644 +--- a/arch/s390/include/asm/mmu.h ++++ b/arch/s390/include/asm/mmu.h +@@ -11,7 +11,7 @@ typedef struct { + spinlock_t list_lock; + struct list_head pgtable_list; + struct list_head gmap_list; +- unsigned long asce_bits; ++ unsigned long asce; + unsigned long asce_limit; + unsigned long vdso_base; + /* The mmu context allocates 4K page tables. */ +diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h +index e485817..22877c9 100644 +--- a/arch/s390/include/asm/mmu_context.h ++++ b/arch/s390/include/asm/mmu_context.h +@@ -26,12 +26,28 @@ static inline int init_new_context(struct task_struct *tsk, + mm->context.has_pgste = 0; + mm->context.use_skey = 0; + #endif +- if (mm->context.asce_limit == 0) { ++ switch (mm->context.asce_limit) { ++ case 1UL << 42: ++ /* ++ * forked 3-level task, fall through to set new asce with new ++ * mm->pgd ++ */ ++ case 0: + /* context created by exec, set asce limit to 4TB */ +- mm->context.asce_bits = _ASCE_TABLE_LENGTH | +- _ASCE_USER_BITS | _ASCE_TYPE_REGION3; + mm->context.asce_limit = STACK_TOP_MAX; +- } else if (mm->context.asce_limit == (1UL << 31)) { ++ mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | ++ _ASCE_USER_BITS | _ASCE_TYPE_REGION3; ++ break; ++ case 1UL << 53: ++ /* forked 4-level task, set new asce with new mm->pgd */ ++ mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | ++ _ASCE_USER_BITS | _ASCE_TYPE_REGION2; ++ break; ++ case 1UL << 31: ++ /* forked 2-level compat task, set new asce with new mm->pgd */ ++ mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | ++ _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; ++ /* pgd_alloc() did not increase mm->nr_pmds */ + mm_inc_nr_pmds(mm); + } + crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); +@@ -42,7 +58,7 @@ static inline int init_new_context(struct task_struct *tsk, + + static inline void set_user_asce(struct mm_struct *mm) + { +- S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd); ++ S390_lowcore.user_asce = mm->context.asce; + if (current->thread.mm_segment.ar4) + __ctl_load(S390_lowcore.user_asce, 7, 7); + set_cpu_flag(CIF_ASCE); +@@ -71,7 +87,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + { + int cpu = smp_processor_id(); + +- S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd); ++ S390_lowcore.user_asce = next->context.asce; + if (prev == next) + return; + if (MACHINE_HAS_TLB_LC) +diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h +index c873e68..6dafabb 100644 +--- a/arch/s390/include/asm/pci.h ++++ b/arch/s390/include/asm/pci.h +@@ -45,7 +45,8 @@ struct zpci_fmb { + u64 rpcit_ops; + u64 dma_rbytes; + u64 dma_wbytes; +-} __packed __aligned(16); ++ u64 pad[2]; ++} __packed __aligned(128); + + enum zpci_state { + ZPCI_FN_STATE_RESERVED, +diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h +index d7cc79f..5991cdcb5 100644 +--- a/arch/s390/include/asm/pgalloc.h ++++ b/arch/s390/include/asm/pgalloc.h +@@ -56,8 +56,8 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm) + return _REGION2_ENTRY_EMPTY; + } + +-int crst_table_upgrade(struct mm_struct *, unsigned long limit); +-void crst_table_downgrade(struct mm_struct *, unsigned long limit); ++int crst_table_upgrade(struct mm_struct *); ++void crst_table_downgrade(struct mm_struct *); + + static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) + { +diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h +index b16c3d0..c1ea67d 100644 +--- a/arch/s390/include/asm/processor.h ++++ b/arch/s390/include/asm/processor.h +@@ -163,7 +163,7 @@ extern __vector128 init_task_fpu_regs[__NUM_VXRS]; + regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \ + regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ + regs->gprs[15] = new_stackp; \ +- crst_table_downgrade(current->mm, 1UL << 31); \ ++ crst_table_downgrade(current->mm); \ + execve_tail(); \ + } while (0) + +diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h +index ca148f7..a2e6ef3 100644 +--- a/arch/s390/include/asm/tlbflush.h ++++ b/arch/s390/include/asm/tlbflush.h +@@ -110,8 +110,7 @@ static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce) + static inline void __tlb_flush_kernel(void) + { + if (MACHINE_HAS_IDTE) +- __tlb_flush_idte((unsigned long) init_mm.pgd | +- init_mm.context.asce_bits); ++ __tlb_flush_idte(init_mm.context.asce); + else + __tlb_flush_global(); + } +@@ -133,8 +132,7 @@ static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce) + static inline void __tlb_flush_kernel(void) + { + if (MACHINE_HAS_TLB_LC) +- __tlb_flush_idte_local((unsigned long) init_mm.pgd | +- init_mm.context.asce_bits); ++ __tlb_flush_idte_local(init_mm.context.asce); + else + __tlb_flush_local(); + } +@@ -148,8 +146,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) + * only ran on the local cpu. + */ + if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list)) +- __tlb_flush_asce(mm, (unsigned long) mm->pgd | +- mm->context.asce_bits); ++ __tlb_flush_asce(mm, mm->context.asce); + else + __tlb_flush_full(mm); + } +diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S +index 857b652..424e680 100644 +--- a/arch/s390/kernel/entry.S ++++ b/arch/s390/kernel/entry.S +@@ -1197,114 +1197,12 @@ cleanup_critical: + .quad .Lpsw_idle_lpsw + + .Lcleanup_save_fpu_regs: +- TSTMSK __LC_CPU_FLAGS,_CIF_FPU +- bor %r14 +- clg %r9,BASED(.Lcleanup_save_fpu_regs_done) +- jhe 5f +- clg %r9,BASED(.Lcleanup_save_fpu_regs_fp) +- jhe 4f +- clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_high) +- jhe 3f +- clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_low) +- jhe 2f +- clg %r9,BASED(.Lcleanup_save_fpu_fpc_end) +- jhe 1f +- lg %r2,__LC_CURRENT +- aghi %r2,__TASK_thread +-0: # Store floating-point controls +- stfpc __THREAD_FPU_fpc(%r2) +-1: # Load register save area and check if VX is active +- lg %r3,__THREAD_FPU_regs(%r2) +- TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX +- jz 4f # no VX -> store FP regs +-2: # Store vector registers (V0-V15) +- VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3) +-3: # Store vector registers (V16-V31) +- VSTM %v16,%v31,256,%r3 # vstm 16,31,256(3) +- j 5f # -> done, set CIF_FPU flag +-4: # Store floating-point registers +- std 0,0(%r3) +- std 1,8(%r3) +- std 2,16(%r3) +- std 3,24(%r3) +- std 4,32(%r3) +- std 5,40(%r3) +- std 6,48(%r3) +- std 7,56(%r3) +- std 8,64(%r3) +- std 9,72(%r3) +- std 10,80(%r3) +- std 11,88(%r3) +- std 12,96(%r3) +- std 13,104(%r3) +- std 14,112(%r3) +- std 15,120(%r3) +-5: # Set CIF_FPU flag +- oi __LC_CPU_FLAGS+7,_CIF_FPU +- lg %r9,48(%r11) # return from save_fpu_regs ++ larl %r9,save_fpu_regs + br %r14 +-.Lcleanup_save_fpu_fpc_end: +- .quad .Lsave_fpu_regs_fpc_end +-.Lcleanup_save_fpu_regs_vx_low: +- .quad .Lsave_fpu_regs_vx_low +-.Lcleanup_save_fpu_regs_vx_high: +- .quad .Lsave_fpu_regs_vx_high +-.Lcleanup_save_fpu_regs_fp: +- .quad .Lsave_fpu_regs_fp +-.Lcleanup_save_fpu_regs_done: +- .quad .Lsave_fpu_regs_done + + .Lcleanup_load_fpu_regs: +- TSTMSK __LC_CPU_FLAGS,_CIF_FPU +- bnor %r14 +- clg %r9,BASED(.Lcleanup_load_fpu_regs_done) +- jhe 1f +- clg %r9,BASED(.Lcleanup_load_fpu_regs_fp) +- jhe 2f +- clg %r9,BASED(.Lcleanup_load_fpu_regs_vx_high) +- jhe 3f +- clg %r9,BASED(.Lcleanup_load_fpu_regs_vx) +- jhe 4f +- lg %r4,__LC_CURRENT +- aghi %r4,__TASK_thread +- lfpc __THREAD_FPU_fpc(%r4) +- TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX +- lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area +- jz 2f # -> no VX, load FP regs +-4: # Load V0 ..V15 registers +- VLM %v0,%v15,0,%r4 +-3: # Load V16..V31 registers +- VLM %v16,%v31,256,%r4 +- j 1f +-2: # Load floating-point registers +- ld 0,0(%r4) +- ld 1,8(%r4) +- ld 2,16(%r4) +- ld 3,24(%r4) +- ld 4,32(%r4) +- ld 5,40(%r4) +- ld 6,48(%r4) +- ld 7,56(%r4) +- ld 8,64(%r4) +- ld 9,72(%r4) +- ld 10,80(%r4) +- ld 11,88(%r4) +- ld 12,96(%r4) +- ld 13,104(%r4) +- ld 14,112(%r4) +- ld 15,120(%r4) +-1: # Clear CIF_FPU bit +- ni __LC_CPU_FLAGS+7,255-_CIF_FPU +- lg %r9,48(%r11) # return from load_fpu_regs ++ larl %r9,load_fpu_regs + br %r14 +-.Lcleanup_load_fpu_regs_vx: +- .quad .Lload_fpu_regs_vx +-.Lcleanup_load_fpu_regs_vx_high: +- .quad .Lload_fpu_regs_vx_high +-.Lcleanup_load_fpu_regs_fp: +- .quad .Lload_fpu_regs_fp +-.Lcleanup_load_fpu_regs_done: +- .quad .Lload_fpu_regs_done + + /* + * Integer constants +diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S +index 58b719f..1ad2407 100644 +--- a/arch/s390/kernel/head64.S ++++ b/arch/s390/kernel/head64.S +@@ -16,7 +16,7 @@ + + __HEAD + ENTRY(startup_continue) +- tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ? ++ tm __LC_STFL_FAC_LIST+5,0x80 # LPP available ? + jz 0f + xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid + mvi __LC_LPP,0x80 # and set LPP_MAGIC +diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c +index c837bca..1f581eb 100644 +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -329,6 +329,7 @@ static void __init setup_lowcore(void) + + PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); + lc->current_task = (unsigned long) init_thread_union.thread_info.task; + lc->thread_info = (unsigned long) &init_thread_union; ++ lc->lpp = LPP_MAGIC; + lc->machine_flags = S390_lowcore.machine_flags; + lc->stfl_fac_list = S390_lowcore.stfl_fac_list; + memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, +diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c +index 8b4516b..cc862c4 100644 +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -868,13 +868,13 @@ no_timer: + + void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) + { +- if (swaitqueue_active(&vcpu->wq)) { ++ if (swait_active(&vcpu->wq)) { + /* + * The vcpu gave up the cpu voluntarily, mark it as a good + * yield-candidate. + */ + vcpu->preempted = true; +- swait_wake_interruptible(&vcpu->wq); ++ swake_up(&vcpu->wq); + vcpu->stat.halt_wakeup++; + } + } +diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c +index c722400..feff9ca 100644 +--- a/arch/s390/mm/init.c ++++ b/arch/s390/mm/init.c +@@ -89,7 +89,8 @@ void __init paging_init(void) + asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; + pgd_type = _REGION3_ENTRY_EMPTY; + } +- S390_lowcore.kernel_asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits; ++ init_mm.context.asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits; ++ S390_lowcore.kernel_asce = init_mm.context.asce; + clear_table((unsigned long *) init_mm.pgd, pgd_type, + sizeof(unsigned long)*2048); + vmem_map_init(); +diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c +index ea01477..f2b6b1d 100644 +--- a/arch/s390/mm/mmap.c ++++ b/arch/s390/mm/mmap.c +@@ -174,7 +174,7 @@ int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) + if (!(flags & MAP_FIXED)) + addr = 0; + if ((addr + len) >= TASK_SIZE) +- return crst_table_upgrade(current->mm, 1UL << 53); ++ return crst_table_upgrade(current->mm); + return 0; + } + +@@ -191,7 +191,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr, + return area; + if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) { + /* Upgrade the page table to 4 levels and retry. */ +- rc = crst_table_upgrade(mm, 1UL << 53); ++ rc = crst_table_upgrade(mm); + if (rc) + return (unsigned long) rc; + area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); +@@ -213,7 +213,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, + return area; + if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) { + /* Upgrade the page table to 4 levels and retry. */ +- rc = crst_table_upgrade(mm, 1UL << 53); ++ rc = crst_table_upgrade(mm); + if (rc) + return (unsigned long) rc; + area = arch_get_unmapped_area_topdown(filp, addr, len, +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index 54ef3bc..471a370 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -49,81 +49,52 @@ static void __crst_table_upgrade(void *arg) + __tlb_flush_local(); + } + +-int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) ++int crst_table_upgrade(struct mm_struct *mm) + { + unsigned long *table, *pgd; +- unsigned long entry; +- int flush; + +- BUG_ON(limit > (1UL << 53)); +- flush = 0; +-repeat: ++ /* upgrade should only happen from 3 to 4 levels */ ++ BUG_ON(mm->context.asce_limit != (1UL << 42)); ++ + table = crst_table_alloc(mm); + if (!table) + return -ENOMEM; ++ + spin_lock_bh(&mm->page_table_lock); +- if (mm->context.asce_limit < limit) { +- pgd = (unsigned long *) mm->pgd; +- if (mm->context.asce_limit <= (1UL << 31)) { +- entry = _REGION3_ENTRY_EMPTY; +- mm->context.asce_limit = 1UL << 42; +- mm->context.asce_bits = _ASCE_TABLE_LENGTH | +- _ASCE_USER_BITS | +- _ASCE_TYPE_REGION3; +- } else { +- entry = _REGION2_ENTRY_EMPTY; +- mm->context.asce_limit = 1UL << 53; +- mm->context.asce_bits = _ASCE_TABLE_LENGTH | +- _ASCE_USER_BITS | +- _ASCE_TYPE_REGION2; +- } +- crst_table_init(table, entry); +- pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd); +- mm->pgd = (pgd_t *) table; +- mm->task_size = mm->context.asce_limit; +- table = NULL; +- flush = 1; +- } ++ pgd = (unsigned long *) mm->pgd; ++ crst_table_init(table, _REGION2_ENTRY_EMPTY); ++ pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd); ++ mm->pgd = (pgd_t *) table; ++ mm->context.asce_limit = 1UL << 53; ++ mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | ++ _ASCE_USER_BITS | _ASCE_TYPE_REGION2; ++ mm->task_size = mm->context.asce_limit; + spin_unlock_bh(&mm->page_table_lock); +- if (table) +- crst_table_free(mm, table); +- if (mm->context.asce_limit < limit) +- goto repeat; +- if (flush) +- on_each_cpu(__crst_table_upgrade, mm, 0); ++ ++ on_each_cpu(__crst_table_upgrade, mm, 0); + return 0; + } + +-void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) ++void crst_table_downgrade(struct mm_struct *mm) + { + pgd_t *pgd; + ++ /* downgrade should only happen from 3 to 2 levels (compat only) */ ++ BUG_ON(mm->context.asce_limit != (1UL << 42)); ++ + if (current->active_mm == mm) { + clear_user_asce(); + __tlb_flush_mm(mm); + } +- while (mm->context.asce_limit > limit) { +- pgd = mm->pgd; +- switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { +- case _REGION_ENTRY_TYPE_R2: +- mm->context.asce_limit = 1UL << 42; +- mm->context.asce_bits = _ASCE_TABLE_LENGTH | +- _ASCE_USER_BITS | +- _ASCE_TYPE_REGION3; +- break; +- case _REGION_ENTRY_TYPE_R3: +- mm->context.asce_limit = 1UL << 31; +- mm->context.asce_bits = _ASCE_TABLE_LENGTH | +- _ASCE_USER_BITS | +- _ASCE_TYPE_SEGMENT; +- break; +- default: +- BUG(); +- } +- mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN); +- mm->task_size = mm->context.asce_limit; +- crst_table_free(mm, (unsigned long *) pgd); +- } ++ ++ pgd = mm->pgd; ++ mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN); ++ mm->context.asce_limit = 1UL << 31; ++ mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | ++ _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; ++ mm->task_size = mm->context.asce_limit; ++ crst_table_free(mm, (unsigned long *) pgd); ++ + if (current->active_mm == mm) + set_user_asce(mm); + } +diff --git a/arch/s390/net/bpf_jit.h b/arch/s390/net/bpf_jit.h +index f010c93..fda605d 100644 +--- a/arch/s390/net/bpf_jit.h ++++ b/arch/s390/net/bpf_jit.h +@@ -37,7 +37,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[]; + * | | | + * +---------------+ | + * | 8 byte skbp | | +- * R15+170 -> +---------------+ | ++ * R15+176 -> +---------------+ | + * | 8 byte hlen | | + * R15+168 -> +---------------+ | + * | 4 byte align | | +@@ -58,7 +58,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[]; + #define STK_OFF (STK_SPACE - STK_160_UNUSED) + #define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */ + #define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */ +-#define STK_OFF_SKBP 170 /* Offset of SKB pointer on stack */ ++#define STK_OFF_SKBP 176 /* Offset of SKB pointer on stack */ + + #define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */ + #define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */ +diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c +index 9a0c4c2..0e2919d 100644 +--- a/arch/s390/net/bpf_jit_comp.c ++++ b/arch/s390/net/bpf_jit_comp.c +@@ -45,7 +45,7 @@ struct bpf_jit { + int labels[1]; /* Labels for local jumps */ + }; + +-#define BPF_SIZE_MAX 0x7ffff /* Max size for program (20 bit signed displ) */ ++#define BPF_SIZE_MAX 0xffff /* Max size for program (16 bit branches) */ + + #define SEEN_SKB 1 /* skb access */ + #define SEEN_MEM 2 /* use mem[] for temporary storage */ +@@ -446,7 +446,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic) + emit_load_skb_data_hlen(jit); + if (jit->seen & SEEN_SKB_CHANGE) + /* stg %b1,ST_OFF_SKBP(%r0,%r15) */ +- EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, ++ EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15, + STK_OFF_SKBP); + /* Clear A (%b0) and X (%b7) registers for converted BPF programs */ + if (is_classic) { +diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c +index 7ef12a3..1944239 100644 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -871,8 +871,11 @@ static inline int barsize(u8 size) + + static int zpci_mem_init(void) + { ++ BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) || ++ __alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb)); ++ + zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb), +- 16, 0, NULL); ++ __alignof__(struct zpci_fmb), 0, NULL); + if (!zdev_fmb_cache) + goto error_zdev; + +diff --git a/arch/sh/mm/kmap.c b/arch/sh/mm/kmap.c +index ec29e14..bf25d7c 100644 +--- a/arch/sh/mm/kmap.c ++++ b/arch/sh/mm/kmap.c +@@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) + + BUG_ON(!test_bit(PG_dcache_clean, &page->flags)); + ++ preempt_disable(); + pagefault_disable(); + + idx = FIX_CMAP_END - +@@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr) + } + + pagefault_enable(); ++ preempt_enable(); + } +diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h +index 10e9dab..f0700cf 100644 +--- a/arch/sparc/include/asm/head_64.h ++++ b/arch/sparc/include/asm/head_64.h +@@ -15,6 +15,10 @@ + + #define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ) + ++#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) ++#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) ++#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) ++ + #define __CHEETAH_ID 0x003e0014 + #define __JALAPENO_ID 0x003e0016 + #define __SERRANO_ID 0x003e0022 +diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h +index 131d36f..408b715 100644 +--- a/arch/sparc/include/asm/pgtable_64.h ++++ b/arch/sparc/include/asm/pgtable_64.h +@@ -375,7 +375,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot) + #define pgprot_noncached pgprot_noncached + + #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +-static inline pte_t pte_mkhuge(pte_t pte) ++static inline unsigned long __pte_huge_mask(void) + { + unsigned long mask; + +@@ -390,8 +390,19 @@ static inline pte_t pte_mkhuge(pte_t pte) + : "=r" (mask) + : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V)); + +- return __pte(pte_val(pte) | mask); ++ return mask; ++} ++ ++static inline pte_t pte_mkhuge(pte_t pte) ++{ ++ return __pte(pte_val(pte) | __pte_huge_mask()); ++} ++ ++static inline bool is_hugetlb_pte(pte_t pte) ++{ ++ return !!(pte_val(pte) & __pte_huge_mask()); + } ++ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + static inline pmd_t pmd_mkhuge(pmd_t pmd) + { +@@ -403,6 +414,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) + return __pmd(pte_val(pte)); + } + #endif ++#else ++static inline bool is_hugetlb_pte(pte_t pte) ++{ ++ return false; ++} + #endif + + static inline pte_t pte_mkdirty(pte_t pte) +@@ -865,6 +881,19 @@ static inline unsigned long pud_pfn(pud_t pud) + void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, + pte_t *ptep, pte_t orig, int fullmm); + ++static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, ++ pte_t *ptep, pte_t orig, int fullmm) ++{ ++ /* It is more efficient to let flush_tlb_kernel_range() ++ * handle init_mm tlb flushes. ++ * ++ * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U ++ * and SUN4V pte layout, so this inline test is fine. ++ */ ++ if (likely(mm != &init_mm) && pte_accessible(mm, orig)) ++ tlb_batch_add(mm, vaddr, ptep, orig, fullmm); ++} ++ + #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR + static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, + unsigned long addr, +@@ -881,15 +910,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t orig = *ptep; + + *ptep = pte; +- +- /* It is more efficient to let flush_tlb_kernel_range() +- * handle init_mm tlb flushes. +- * +- * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U +- * and SUN4V pte layout, so this inline test is fine. +- */ +- if (likely(mm != &init_mm) && pte_accessible(mm, orig)) +- tlb_batch_add(mm, addr, ptep, orig, fullmm); ++ maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm); + } + + #define set_pte_at(mm,addr,ptep,pte) \ +diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h +index dea1cfa..a8e192e 100644 +--- a/arch/sparc/include/asm/tlbflush_64.h ++++ b/arch/sparc/include/asm/tlbflush_64.h +@@ -8,6 +8,7 @@ + #define TLB_BATCH_NR 192 + + struct tlb_batch { ++ bool huge; + struct mm_struct *mm; + unsigned long tlb_nr; + unsigned long active; +@@ -16,7 +17,7 @@ struct tlb_batch { + + void flush_tsb_kernel_range(unsigned long start, unsigned long end); + void flush_tsb_user(struct tlb_batch *tb); +-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr); ++void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge); + + /* TLB flush operations. */ + +diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h +index 71b5a67..781b9f1 100644 +--- a/arch/sparc/include/asm/ttable.h ++++ b/arch/sparc/include/asm/ttable.h +@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \ + restored; \ + nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \ + ba,a,pt %xcc, user_rtt_fill_fixup; + + +@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \ + restored; \ + nop; nop; nop; nop; nop; \ + nop; nop; nop; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \ + ba,a,pt %xcc, user_rtt_fill_fixup; + + +diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile +index 7cf9c6e..fdb1332 100644 +--- a/arch/sparc/kernel/Makefile ++++ b/arch/sparc/kernel/Makefile +@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg + CFLAGS_REMOVE_pcr.o := -pg + endif + ++obj-$(CONFIG_SPARC64) += urtt_fill.o + obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o + obj-$(CONFIG_SPARC32) += etrap_32.o + obj-$(CONFIG_SPARC32) += rtrap_32.o +diff --git a/arch/sparc/kernel/cherrs.S b/arch/sparc/kernel/cherrs.S +index 4ee1ad4..655628d 100644 +--- a/arch/sparc/kernel/cherrs.S ++++ b/arch/sparc/kernel/cherrs.S +@@ -214,8 +214,7 @@ do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + subcc %g1, %g2, %g1 ! Next cacheline + bge,pt %icc, 1b + nop +- ba,pt %xcc, dcpe_icpe_tl1_common +- nop ++ ba,a,pt %xcc, dcpe_icpe_tl1_common + + do_dcpe_tl1_fatal: + sethi %hi(1f), %g7 +@@ -224,8 +223,7 @@ do_dcpe_tl1_fatal: + mov 0x2, %o0 + call cheetah_plus_parity_error + add %sp, PTREGS_OFF, %o1 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_dcpe_tl1,.-do_dcpe_tl1 + + .globl do_icpe_tl1 +@@ -259,8 +257,7 @@ do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + subcc %g1, %g2, %g1 + bge,pt %icc, 1b + nop +- ba,pt %xcc, dcpe_icpe_tl1_common +- nop ++ ba,a,pt %xcc, dcpe_icpe_tl1_common + + do_icpe_tl1_fatal: + sethi %hi(1f), %g7 +@@ -269,8 +266,7 @@ do_icpe_tl1_fatal: + mov 0x3, %o0 + call cheetah_plus_parity_error + add %sp, PTREGS_OFF, %o1 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_icpe_tl1,.-do_icpe_tl1 + + .type dcpe_icpe_tl1_common,#function +@@ -456,7 +452,7 @@ __cheetah_log_error: + cmp %g2, 0x63 + be c_cee + nop +- ba,pt %xcc, c_deferred ++ ba,a,pt %xcc, c_deferred + .size __cheetah_log_error,.-__cheetah_log_error + + /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc +diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S +index 33c02b1..a83707c 100644 +--- a/arch/sparc/kernel/entry.S ++++ b/arch/sparc/kernel/entry.S +@@ -948,7 +948,24 @@ linux_syscall_trace: + cmp %o0, 0 + bne 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ld [%sp + STACKFRAME_SZ + PT_G1], %g1 ++ sethi %hi(sys_call_table), %l7 ++ ld [%sp + STACKFRAME_SZ + PT_I0], %i0 ++ or %l7, %lo(sys_call_table), %l7 ++ ld [%sp + STACKFRAME_SZ + PT_I1], %i1 ++ ld [%sp + STACKFRAME_SZ + PT_I2], %i2 ++ ld [%sp + STACKFRAME_SZ + PT_I3], %i3 ++ ld [%sp + STACKFRAME_SZ + PT_I4], %i4 ++ ld [%sp + STACKFRAME_SZ + PT_I5], %i5 ++ cmp %g1, NR_syscalls ++ bgeu 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + mov %i0, %o0 ++ ld [%l7 + %l4], %l7 + mov %i1, %o1 + mov %i2, %o2 + mov %i3, %o3 +diff --git a/arch/sparc/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S +index a686482..336d275 100644 +--- a/arch/sparc/kernel/fpu_traps.S ++++ b/arch/sparc/kernel/fpu_traps.S +@@ -100,8 +100,8 @@ do_fpdis: + fmuld %f0, %f2, %f26 + faddd %f0, %f2, %f28 + fmuld %f0, %f2, %f30 +- b,pt %xcc, fpdis_exit +- nop ++ ba,a,pt %xcc, fpdis_exit ++ + 2: andcc %g5, FPRS_DU, %g0 + bne,pt %icc, 3f + fzero %f32 +@@ -144,8 +144,8 @@ do_fpdis: + fmuld %f32, %f34, %f58 + faddd %f32, %f34, %f60 + fmuld %f32, %f34, %f62 +- ba,pt %xcc, fpdis_exit +- nop ++ ba,a,pt %xcc, fpdis_exit ++ + 3: mov SECONDARY_CONTEXT, %g3 + add %g6, TI_FPREGS, %g1 + +@@ -197,8 +197,7 @@ fpdis_exit2: + fp_other_bounce: + call do_fpother + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size fp_other_bounce,.-fp_other_bounce + + .align 32 +diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S +index f2d30ca..51faf92 100644 +--- a/arch/sparc/kernel/head_64.S ++++ b/arch/sparc/kernel/head_64.S +@@ -461,9 +461,8 @@ sun4v_chip_type: + subcc %g3, 1, %g3 + bne,pt %xcc, 41b + add %g1, 1, %g1 +- mov SUN4V_CHIP_SPARC64X, %g4 + ba,pt %xcc, 5f +- nop ++ mov SUN4V_CHIP_SPARC64X, %g4 + + 49: + mov SUN4V_CHIP_UNKNOWN, %g4 +@@ -548,8 +547,7 @@ sun4u_init: + stxa %g0, [%g7] ASI_DMMU + membar #Sync + +- ba,pt %xcc, sun4u_continue +- nop ++ ba,a,pt %xcc, sun4u_continue + + sun4v_init: + /* Set ctx 0 */ +@@ -560,14 +558,12 @@ sun4v_init: + mov SECONDARY_CONTEXT, %g7 + stxa %g0, [%g7] ASI_MMU + membar #Sync +- ba,pt %xcc, niagara_tlb_fixup +- nop ++ ba,a,pt %xcc, niagara_tlb_fixup + + sun4u_continue: + BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup) + +- ba,pt %xcc, spitfire_tlb_fixup +- nop ++ ba,a,pt %xcc, spitfire_tlb_fixup + + niagara_tlb_fixup: + mov 3, %g2 /* Set TLB type to hypervisor. */ +@@ -639,8 +635,7 @@ niagara_patch: + call hypervisor_patch_cachetlbops + nop + +- ba,pt %xcc, tlb_fixup_done +- nop ++ ba,a,pt %xcc, tlb_fixup_done + + cheetah_tlb_fixup: + mov 2, %g2 /* Set TLB type to cheetah+. */ +@@ -659,8 +654,7 @@ cheetah_tlb_fixup: + call cheetah_patch_cachetlbops + nop + +- ba,pt %xcc, tlb_fixup_done +- nop ++ ba,a,pt %xcc, tlb_fixup_done + + spitfire_tlb_fixup: + /* Set TLB type to spitfire. */ +@@ -782,8 +776,7 @@ setup_trap_table: + call %o1 + add %sp, (2047 + 128), %o0 + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + 1: sethi %hi(sparc64_ttable_tl0), %o0 + set prom_set_trap_table_name, %g2 +@@ -822,8 +815,7 @@ setup_trap_table: + + BRANCH_IF_ANY_CHEETAH(o2, o3, 1f) + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + /* Disable STICK_INT interrupts. */ + 1: +diff --git a/arch/sparc/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S +index 753b4f0..34b4933 100644 +--- a/arch/sparc/kernel/misctrap.S ++++ b/arch/sparc/kernel/misctrap.S +@@ -18,8 +18,7 @@ __do_privact: + 109: or %g7, %lo(109b), %g7 + call do_privact + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __do_privact,.-__do_privact + + .type do_mna,#function +@@ -46,8 +45,7 @@ do_mna: + mov %l5, %o2 + call mem_address_unaligned + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_mna,.-do_mna + + .type do_lddfmna,#function +@@ -65,8 +63,7 @@ do_lddfmna: + mov %l5, %o2 + call handle_lddfmna + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_lddfmna,.-do_lddfmna + + .type do_stdfmna,#function +@@ -84,8 +81,7 @@ do_stdfmna: + mov %l5, %o2 + call handle_stdfmna + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_stdfmna,.-do_stdfmna + + .type breakpoint_trap,#function +diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c +index badf095..9f9614d 100644 +--- a/arch/sparc/kernel/pci.c ++++ b/arch/sparc/kernel/pci.c +@@ -994,6 +994,23 @@ void pcibios_set_master(struct pci_dev *dev) + /* No special bus mastering setup handling */ + } + ++#ifdef CONFIG_PCI_IOV ++int pcibios_add_device(struct pci_dev *dev) ++{ ++ struct pci_dev *pdev; ++ ++ /* Add sriov arch specific initialization here. ++ * Copy dev_archdata from PF to VF ++ */ ++ if (dev->is_virtfn) { ++ pdev = dev->physfn; ++ memcpy(&dev->dev.archdata, &pdev->dev.archdata, ++ sizeof(struct dev_archdata)); ++ } ++ return 0; ++} ++#endif /* CONFIG_PCI_IOV */ ++ + static int __init pcibios_init(void) + { + pci_dfl_cache_line_size = 64 >> 2; +diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S +index d08bdaf..216948c 100644 +--- a/arch/sparc/kernel/rtrap_64.S ++++ b/arch/sparc/kernel/rtrap_64.S +@@ -14,10 +14,6 @@ + #include + #include + +-#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) +-#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) +-#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) +- + #ifdef CONFIG_CONTEXT_TRACKING + # define SCHEDULE_USER schedule_user + #else +@@ -242,52 +238,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 + wrpr %g1, %cwp + ba,a,pt %xcc, user_rtt_fill_64bit + +-user_rtt_fill_fixup: +- rdpr %cwp, %g1 +- add %g1, 1, %g1 +- wrpr %g1, 0x0, %cwp +- +- rdpr %wstate, %g2 +- sll %g2, 3, %g2 +- wrpr %g2, 0x0, %wstate +- +- /* We know %canrestore and %otherwin are both zero. */ +- +- sethi %hi(sparc64_kern_pri_context), %g2 +- ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2 +- mov PRIMARY_CONTEXT, %g1 +- +-661: stxa %g2, [%g1] ASI_DMMU +- .section .sun4v_1insn_patch, "ax" +- .word 661b +- stxa %g2, [%g1] ASI_MMU +- .previous +- +- sethi %hi(KERNBASE), %g1 +- flush %g1 ++user_rtt_fill_fixup_dax: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ mov 1, %g3 + +- or %g4, FAULT_CODE_WINFIXUP, %g4 +- stb %g4, [%g6 + TI_FAULT_CODE] +- stx %g5, [%g6 + TI_FAULT_ADDR] ++user_rtt_fill_fixup_mna: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ mov 2, %g3 + +- mov %g6, %l1 +- wrpr %g0, 0x0, %tl +- +-661: nop +- .section .sun4v_1insn_patch, "ax" +- .word 661b +- SET_GL(0) +- .previous +- +- wrpr %g0, RTRAP_PSTATE, %pstate +- +- mov %l1, %g6 +- ldx [%g6 + TI_TASK], %g4 +- LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3) +- call do_sparc64_fault +- add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++user_rtt_fill_fixup: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ clr %g3 + + user_rtt_pre_restore: + add %g1, 1, %g1 +diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c +index 4eed773..77655f0 100644 +--- a/arch/sparc/kernel/signal32.c ++++ b/arch/sparc/kernel/signal32.c +@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + return 0; + } + ++/* Checks if the fp is valid. We always build signal frames which are ++ * 16-byte aligned, therefore we can always enforce that the restore ++ * frame has that property as well. ++ */ ++static bool invalid_frame_pointer(void __user *fp, int fplen) ++{ ++ if ((((unsigned long) fp) & 15) || ++ ((unsigned long)fp) > 0x100000000ULL - fplen) ++ return true; ++ return false; ++} ++ + void do_sigreturn32(struct pt_regs *regs) + { + struct signal_frame32 __user *sf; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; +- unsigned int psr; ++ unsigned int psr, ufp; + unsigned pc, npc; + sigset_t set; + compat_sigset_t seta; +@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs) + sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 3)) ++ if (invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv; ++ ++ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) + goto segv; + +- if (get_user(pc, &sf->info.si_regs.pc) || ++ if (__get_user(pc, &sf->info.si_regs.pc) || + __get_user(npc, &sf->info.si_regs.npc)) + goto segv; + +@@ -227,7 +244,7 @@ segv: + asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) + { + struct rt_signal_frame32 __user *sf; +- unsigned int psr, pc, npc; ++ unsigned int psr, pc, npc, ufp; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; + sigset_t set; +@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) + sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 3)) ++ if (invalid_frame_pointer(sf, sizeof(*sf))) + goto segv; + +- if (get_user(pc, &sf->regs.pc) || ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) ++ goto segv; ++ ++ if (__get_user(pc, &sf->regs.pc) || + __get_user(npc, &sf->regs.npc)) + goto segv; + +@@ -307,14 +329,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static int invalid_frame_pointer(void __user *fp, int fplen) +-{ +- if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen) +- return 1; +- return 0; +-} +- + static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp; +diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c +index 52aa5e4..c3c12ef 100644 +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -60,10 +60,22 @@ struct rt_signal_frame { + #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) + #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) + ++/* Checks if the fp is valid. We always build signal frames which are ++ * 16-byte aligned, therefore we can always enforce that the restore ++ * frame has that property as well. ++ */ ++static inline bool invalid_frame_pointer(void __user *fp, int fplen) ++{ ++ if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen)) ++ return true; ++ ++ return false; ++} ++ + asmlinkage void do_sigreturn(struct pt_regs *regs) + { ++ unsigned long up_psr, pc, npc, ufp; + struct signal_frame __user *sf; +- unsigned long up_psr, pc, npc; + sigset_t set; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; +@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) + sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) ++ if (!invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv_and_exit; ++ ++ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP])) + goto segv_and_exit; + +- if (((unsigned long) sf) & 3) ++ if (ufp & 0x7) + goto segv_and_exit; + + err = __get_user(pc, &sf->info.si_regs.pc); +@@ -127,7 +142,7 @@ segv_and_exit: + asmlinkage void do_rt_sigreturn(struct pt_regs *regs) + { + struct rt_signal_frame __user *sf; +- unsigned int psr, pc, npc; ++ unsigned int psr, pc, npc, ufp; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; + sigset_t set; +@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) + + synchronize_user_stack(); + sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 0x03)) ++ if (!invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv; ++ ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) + goto segv; + + err = __get_user(pc, &sf->regs.pc); +@@ -178,15 +198,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static inline int invalid_frame_pointer(void __user *fp, int fplen) +-{ +- if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen)) +- return 1; +- +- return 0; +-} +- + static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp = regs->u_regs[UREG_FP]; +diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c +index d88beff..5ee930c 100644 +--- a/arch/sparc/kernel/signal_64.c ++++ b/arch/sparc/kernel/signal_64.c +@@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) + unsigned char fenab; + int err; + +- flush_user_windows(); ++ synchronize_user_stack(); + if (get_thread_wsaved() || + (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || + (!__access_ok(ucp, sizeof(*ucp)))) +@@ -234,6 +234,17 @@ do_sigsegv: + goto out; + } + ++/* Checks if the fp is valid. We always build rt signal frames which ++ * are 16-byte aligned, therefore we can always enforce that the ++ * restore frame has that property as well. ++ */ ++static bool invalid_frame_pointer(void __user *fp) ++{ ++ if (((unsigned long) fp) & 15) ++ return true; ++ return false; ++} ++ + struct rt_signal_frame { + struct sparc_stackf ss; + siginfo_t info; +@@ -246,8 +257,8 @@ struct rt_signal_frame { + + void do_rt_sigreturn(struct pt_regs *regs) + { ++ unsigned long tpc, tnpc, tstate, ufp; + struct rt_signal_frame __user *sf; +- unsigned long tpc, tnpc, tstate; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; + sigset_t set; +@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *regs) + (regs->u_regs [UREG_FP] + STACK_BIAS); + + /* 1. Make sure we are not getting garbage from the user */ +- if (((unsigned long) sf) & 3) ++ if (invalid_frame_pointer(sf)) ++ goto segv; ++ ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) + goto segv; + +- err = get_user(tpc, &sf->regs.tpc); ++ if ((ufp + STACK_BIAS) & 0x7) ++ goto segv; ++ ++ err = __get_user(tpc, &sf->regs.tpc); + err |= __get_user(tnpc, &sf->regs.tnpc); + if (test_thread_flag(TIF_32BIT)) { + tpc &= 0xffffffff; +@@ -308,14 +325,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static int invalid_frame_pointer(void __user *fp) +-{ +- if (((unsigned long) fp) & 15) +- return 1; +- return 0; +-} +- + static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; +diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c +index 0f6eebe..e5fe8ce 100644 +--- a/arch/sparc/kernel/sigutil_32.c ++++ b/arch/sparc/kernel/sigutil_32.c +@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + { + int err; ++ ++ if (((unsigned long) fpu) & 3) ++ return -EFAULT; ++ + #ifdef CONFIG_SMP + if (test_tsk_thread_flag(current, TIF_USEDFPU)) + regs->psr &= ~PSR_EF; +@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + +- __get_user(wsaved, &rp->wsaved); ++ if (((unsigned long) rp) & 3) ++ return -EFAULT; ++ ++ get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + +diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c +index 387834a..36aadcb 100644 +--- a/arch/sparc/kernel/sigutil_64.c ++++ b/arch/sparc/kernel/sigutil_64.c +@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + unsigned long fprs; + int err; + +- err = __get_user(fprs, &fpu->si_fprs); ++ if (((unsigned long) fpu) & 7) ++ return -EFAULT; ++ ++ err = get_user(fprs, &fpu->si_fprs); + fprs_write(0); + regs->tstate &= ~TSTATE_PEF; + if (fprs & FPRS_DL) +@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + +- __get_user(wsaved, &rp->wsaved); ++ if (((unsigned long) rp) & 7) ++ return -EFAULT; ++ ++ get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + +diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S +index c357e40..4a73009 100644 +--- a/arch/sparc/kernel/spiterrs.S ++++ b/arch/sparc/kernel/spiterrs.S +@@ -85,8 +85,7 @@ __spitfire_cee_trap_continue: + ba,pt %xcc, etraptl1 + rd %pc, %g7 + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + 1: ba,pt %xcc, etrap_irq + rd %pc, %g7 +@@ -100,8 +99,7 @@ __spitfire_cee_trap_continue: + mov %l5, %o2 + call spitfire_access_error + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_access_error,.-__spitfire_access_error + + /* This is the trap handler entry point for ECC correctable +@@ -179,8 +177,7 @@ __spitfire_data_access_exception_tl1: + mov %l5, %o2 + call spitfire_data_access_exception_tl1 + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1 + + .type __spitfire_data_access_exception,#function +@@ -200,8 +197,7 @@ __spitfire_data_access_exception: + mov %l5, %o2 + call spitfire_data_access_exception + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_data_access_exception,.-__spitfire_data_access_exception + + .type __spitfire_insn_access_exception_tl1,#function +@@ -220,8 +216,7 @@ __spitfire_insn_access_exception_tl1: + mov %l5, %o2 + call spitfire_insn_access_exception_tl1 + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1 + + .type __spitfire_insn_access_exception,#function +@@ -240,6 +235,5 @@ __spitfire_insn_access_exception: + mov %l5, %o2 + call spitfire_insn_access_exception + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception +diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S +index bb00089..c4a1b5c 100644 +--- a/arch/sparc/kernel/syscalls.S ++++ b/arch/sparc/kernel/syscalls.S +@@ -158,7 +158,25 @@ linux_syscall_trace32: + add %sp, PTREGS_OFF, %o0 + brnz,pn %o0, 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ++ sethi %hi(sys_call_table32), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ++ or %l7, %lo(sys_call_table32), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ++ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ++ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ++ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ++ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ++ ++ cmp %g1, NR_syscalls ++ bgeu,pn %xcc, 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + srl %i0, 0, %o0 ++ lduw [%l7 + %l4], %l7 + srl %i4, 0, %o4 + srl %i1, 0, %o1 + srl %i2, 0, %o2 +@@ -170,7 +188,25 @@ linux_syscall_trace: + add %sp, PTREGS_OFF, %o0 + brnz,pn %o0, 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ++ sethi %hi(sys_call_table64), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ++ or %l7, %lo(sys_call_table64), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ++ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ++ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ++ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ++ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ++ ++ cmp %g1, NR_syscalls ++ bgeu,pn %xcc, 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + mov %i0, %o0 ++ lduw [%l7 + %l4], %l7 + mov %i1, %o1 + mov %i2, %o2 + mov %i3, %o3 +diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S +new file mode 100644 +index 0000000..5604a2b +--- /dev/null ++++ b/arch/sparc/kernel/urtt_fill.S +@@ -0,0 +1,98 @@ ++#include ++#include ++#include ++#include ++#include ++ ++ .text ++ .align 8 ++ .globl user_rtt_fill_fixup_common ++user_rtt_fill_fixup_common: ++ rdpr %cwp, %g1 ++ add %g1, 1, %g1 ++ wrpr %g1, 0x0, %cwp ++ ++ rdpr %wstate, %g2 ++ sll %g2, 3, %g2 ++ wrpr %g2, 0x0, %wstate ++ ++ /* We know %canrestore and %otherwin are both zero. */ ++ ++ sethi %hi(sparc64_kern_pri_context), %g2 ++ ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2 ++ mov PRIMARY_CONTEXT, %g1 ++ ++661: stxa %g2, [%g1] ASI_DMMU ++ .section .sun4v_1insn_patch, "ax" ++ .word 661b ++ stxa %g2, [%g1] ASI_MMU ++ .previous ++ ++ sethi %hi(KERNBASE), %g1 ++ flush %g1 ++ ++ mov %g4, %l4 ++ mov %g5, %l5 ++ brnz,pn %g3, 1f ++ mov %g3, %l3 ++ ++ or %g4, FAULT_CODE_WINFIXUP, %g4 ++ stb %g4, [%g6 + TI_FAULT_CODE] ++ stx %g5, [%g6 + TI_FAULT_ADDR] ++1: ++ mov %g6, %l1 ++ wrpr %g0, 0x0, %tl ++ ++661: nop ++ .section .sun4v_1insn_patch, "ax" ++ .word 661b ++ SET_GL(0) ++ .previous ++ ++ wrpr %g0, RTRAP_PSTATE, %pstate ++ ++ mov %l1, %g6 ++ ldx [%g6 + TI_TASK], %g4 ++ LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3) ++ ++ brnz,pn %l3, 1f ++ nop ++ ++ call do_sparc64_fault ++ add %sp, PTREGS_OFF, %o0 ++ ba,pt %xcc, rtrap ++ nop ++ ++1: cmp %g3, 2 ++ bne,pn %xcc, 2f ++ nop ++ ++ sethi %hi(tlb_type), %g1 ++ lduw [%g1 + %lo(tlb_type)], %g1 ++ cmp %g1, 3 ++ bne,pt %icc, 1f ++ add %sp, PTREGS_OFF, %o0 ++ mov %l4, %o2 ++ call sun4v_do_mna ++ mov %l5, %o1 ++ ba,a,pt %xcc, rtrap ++1: mov %l4, %o1 ++ mov %l5, %o2 ++ call mem_address_unaligned ++ nop ++ ba,a,pt %xcc, rtrap ++ ++2: sethi %hi(tlb_type), %g1 ++ mov %l4, %o1 ++ lduw [%g1 + %lo(tlb_type)], %g1 ++ mov %l5, %o2 ++ cmp %g1, 3 ++ bne,pt %icc, 1f ++ add %sp, PTREGS_OFF, %o0 ++ call sun4v_data_access_exception ++ nop ++ ba,a,pt %xcc, rtrap ++ ++1: call spitfire_data_access_exception ++ nop ++ ba,a,pt %xcc, rtrap +diff --git a/arch/sparc/kernel/utrap.S b/arch/sparc/kernel/utrap.S +index b7f0f3f..c731e80 100644 +--- a/arch/sparc/kernel/utrap.S ++++ b/arch/sparc/kernel/utrap.S +@@ -11,8 +11,7 @@ utrap_trap: /* %g3=handler,%g4=level */ + mov %l4, %o1 + call bad_trap + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + + invoke_utrap: + sllx %g3, 3, %g3 +diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S +index f1a2f68..4a41d41 100644 +--- a/arch/sparc/kernel/vmlinux.lds.S ++++ b/arch/sparc/kernel/vmlinux.lds.S +@@ -33,6 +33,10 @@ ENTRY(_start) + jiffies = jiffies_64; + #endif + ++#ifdef CONFIG_SPARC64 ++ASSERT((swapper_tsb == 0x0000000000408000), "Error: sparc64 early assembler too large") ++#endif ++ + SECTIONS + { + #ifdef CONFIG_SPARC64 +diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S +index 1e67ce9..855019a 100644 +--- a/arch/sparc/kernel/winfixup.S ++++ b/arch/sparc/kernel/winfixup.S +@@ -32,8 +32,7 @@ fill_fixup: + rd %pc, %g7 + call do_sparc64_fault + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + + /* Be very careful about usage of the trap globals here. + * You cannot touch %g5 as that has the fault information. +diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c +index 131eaf4..364d093 100644 +--- a/arch/sparc/mm/hugetlbpage.c ++++ b/arch/sparc/mm/hugetlbpage.c +@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t entry) + { + int i; ++ pte_t orig[2]; ++ unsigned long nptes; + + if (!pte_present(*ptep) && pte_present(entry)) + mm->context.huge_pte_count++; + + addr &= HPAGE_MASK; +- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { +- set_pte_at(mm, addr, ptep, entry); ++ ++ nptes = 1 << HUGETLB_PAGE_ORDER; ++ orig[0] = *ptep; ++ orig[1] = *(ptep + nptes / 2); ++ for (i = 0; i < nptes; i++) { ++ *ptep = entry; + ptep++; + addr += PAGE_SIZE; + pte_val(entry) += PAGE_SIZE; + } ++ ++ /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ ++ addr -= REAL_HPAGE_SIZE; ++ ptep -= nptes / 2; ++ maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0); ++ addr -= REAL_HPAGE_SIZE; ++ ptep -= nptes / 2; ++ maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0); + } + + pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, +@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, + { + pte_t entry; + int i; ++ unsigned long nptes; + + entry = *ptep; + if (pte_present(entry)) + mm->context.huge_pte_count--; + + addr &= HPAGE_MASK; +- +- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { +- pte_clear(mm, addr, ptep); ++ nptes = 1 << HUGETLB_PAGE_ORDER; ++ for (i = 0; i < nptes; i++) { ++ *ptep = __pte(0UL); + addr += PAGE_SIZE; + ptep++; + } + ++ /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ ++ addr -= REAL_HPAGE_SIZE; ++ ptep -= nptes / 2; ++ maybe_tlb_batch_add(mm, addr, ptep, entry, 0); ++ addr -= REAL_HPAGE_SIZE; ++ ptep -= nptes / 2; ++ maybe_tlb_batch_add(mm, addr, ptep, entry, 0); ++ + return entry; + } + +diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c +index 3025bd5..3c4b897 100644 +--- a/arch/sparc/mm/init_64.c ++++ b/arch/sparc/mm/init_64.c +@@ -324,18 +324,6 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde + tsb_insert(tsb, tag, tte); + } + +-#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +-static inline bool is_hugetlb_pte(pte_t pte) +-{ +- if ((tlb_type == hypervisor && +- (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) || +- (tlb_type != hypervisor && +- (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U)) +- return true; +- return false; +-} +-#endif +- + void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) + { + struct mm_struct *mm; +@@ -1267,13 +1255,6 @@ static int __init numa_parse_mdesc(void) + int i, j, err, count; + u64 node; + +- /* Some sane defaults for numa latency values */ +- for (i = 0; i < MAX_NUMNODES; i++) { +- for (j = 0; j < MAX_NUMNODES; j++) +- numa_latency[i][j] = (i == j) ? +- LOCAL_DISTANCE : REMOTE_DISTANCE; +- } +- + node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups"); + if (node == MDESC_NODE_NULL) { + mdesc_release(md); +@@ -1369,10 +1350,18 @@ static int __init numa_parse_sun4u(void) + + static int __init bootmem_init_numa(void) + { ++ int i, j; + int err = -1; + + numadbg("bootmem_init_numa()\n"); + ++ /* Some sane defaults for numa latency values */ ++ for (i = 0; i < MAX_NUMNODES; i++) { ++ for (j = 0; j < MAX_NUMNODES; j++) ++ numa_latency[i][j] = (i == j) ? ++ LOCAL_DISTANCE : REMOTE_DISTANCE; ++ } ++ + if (numa_enabled) { + if (tlb_type == hypervisor) + err = numa_parse_mdesc(); +@@ -2832,9 +2821,10 @@ void hugetlb_setup(struct pt_regs *regs) + * the Data-TLB for huge pages. + */ + if (tlb_type == cheetah_plus) { ++ bool need_context_reload = false; + unsigned long ctx; + +- spin_lock(&ctx_alloc_lock); ++ spin_lock_irq(&ctx_alloc_lock); + ctx = mm->context.sparc64_ctx_val; + ctx &= ~CTX_PGSZ_MASK; + ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT; +@@ -2853,9 +2843,12 @@ void hugetlb_setup(struct pt_regs *regs) + * also executing in this address space. + */ + mm->context.sparc64_ctx_val = ctx; +- on_each_cpu(context_reload, mm, 0); ++ need_context_reload = true; + } +- spin_unlock(&ctx_alloc_lock); ++ spin_unlock_irq(&ctx_alloc_lock); ++ ++ if (need_context_reload) ++ on_each_cpu(context_reload, mm, 0); + } + } + #endif +diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c +index 9df2190..f81cd97 100644 +--- a/arch/sparc/mm/tlb.c ++++ b/arch/sparc/mm/tlb.c +@@ -67,7 +67,7 @@ void arch_leave_lazy_mmu_mode(void) + } + + static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, +- bool exec) ++ bool exec, bool huge) + { + struct tlb_batch *tb = &get_cpu_var(tlb_batch); + unsigned long nr; +@@ -84,13 +84,21 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, + } + + if (!tb->active) { +- flush_tsb_user_page(mm, vaddr); ++ flush_tsb_user_page(mm, vaddr, huge); + global_flush_tlb_page(mm, vaddr); + goto out; + } + +- if (nr == 0) ++ if (nr == 0) { + tb->mm = mm; ++ tb->huge = huge; ++ } ++ ++ if (tb->huge != huge) { ++ flush_tlb_pending(); ++ tb->huge = huge; ++ nr = 0; ++ } + + tb->vaddrs[nr] = vaddr; + tb->tlb_nr = ++nr; +@@ -104,6 +112,8 @@ out: + void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, + pte_t *ptep, pte_t orig, int fullmm) + { ++ bool huge = is_hugetlb_pte(orig); ++ + if (tlb_type != hypervisor && + pte_dirty(orig)) { + unsigned long paddr, pfn = pte_pfn(orig); +@@ -129,7 +139,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, + + no_cache_flush: + if (!fullmm) +- tlb_batch_add_one(mm, vaddr, pte_exec(orig)); ++ tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge); + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +@@ -145,7 +155,7 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, + if (pte_val(*pte) & _PAGE_VALID) { + bool exec = pte_exec(*pte); + +- tlb_batch_add_one(mm, vaddr, exec); ++ tlb_batch_add_one(mm, vaddr, exec, false); + } + pte++; + vaddr += PAGE_SIZE; +@@ -185,8 +195,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, + pte_t orig_pte = __pte(pmd_val(orig)); + bool exec = pte_exec(orig_pte); + +- tlb_batch_add_one(mm, addr, exec); +- tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); ++ tlb_batch_add_one(mm, addr, exec, true); ++ tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec, ++ true); + } else { + tlb_batch_pmd_scan(mm, addr, orig); + } +diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c +index a065766..a0604a4 100644 +--- a/arch/sparc/mm/tsb.c ++++ b/arch/sparc/mm/tsb.c +@@ -76,14 +76,15 @@ void flush_tsb_user(struct tlb_batch *tb) + + spin_lock_irqsave(&mm->context.lock, flags); + +- base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; +- nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; +- if (tlb_type == cheetah_plus || tlb_type == hypervisor) +- base = __pa(base); +- __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); +- ++ if (!tb->huge) { ++ base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; ++ nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; ++ if (tlb_type == cheetah_plus || tlb_type == hypervisor) ++ base = __pa(base); ++ __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); ++ } + #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +- if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { ++ if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) { + base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; + nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) +@@ -94,20 +95,21 @@ void flush_tsb_user(struct tlb_batch *tb) + spin_unlock_irqrestore(&mm->context.lock, flags); + } + +-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr) ++void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge) + { + unsigned long nentries, base, flags; + + spin_lock_irqsave(&mm->context.lock, flags); + +- base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; +- nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; +- if (tlb_type == cheetah_plus || tlb_type == hypervisor) +- base = __pa(base); +- __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries); +- ++ if (!huge) { ++ base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; ++ nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; ++ if (tlb_type == cheetah_plus || tlb_type == hypervisor) ++ base = __pa(base); ++ __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries); ++ } + #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +- if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { ++ if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) { + base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; + nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) +diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c +index 29880c9..e22e572 100644 +--- a/arch/um/drivers/mconsole_kern.c ++++ b/arch/um/drivers/mconsole_kern.c +@@ -133,7 +133,7 @@ void mconsole_proc(struct mc_request *req) + ptr += strlen("proc"); + ptr = skip_spaces(ptr); + +- file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); ++ file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0); + if (IS_ERR(file)) { + mconsole_reply(req, "Failed to open file", 1, 0); + printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index d8a1650..6ee1dd0 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1130,22 +1130,23 @@ config MICROCODE + bool "CPU microcode loading support" + default y + depends on CPU_SUP_AMD || CPU_SUP_INTEL +- depends on BLK_DEV_INITRD + select FW_LOADER + ---help--- +- + If you say Y here, you will be able to update the microcode on +- certain Intel and AMD processors. The Intel support is for the +- IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, +- Xeon etc. The AMD support is for families 0x10 and later. You will +- obviously need the actual microcode binary data itself which is not +- shipped with the Linux kernel. +- +- This option selects the general module only, you need to select +- at least one vendor specific module as well. +- +- To compile this driver as a module, choose M here: the module +- will be called microcode. ++ Intel and AMD processors. The Intel support is for the IA32 family, ++ e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The ++ AMD support is for families 0x10 and later. You will obviously need ++ the actual microcode binary data itself which is not shipped with ++ the Linux kernel. ++ ++ The preferred method to load microcode from a detached initrd is described ++ in Documentation/x86/early-microcode.txt. For that you need to enable ++ CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the ++ initrd for microcode blobs. ++ ++ In addition, you can build-in the microcode into the kernel. For that you ++ need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode ++ to the CONFIG_EXTRA_FIRMWARE config option. + + config MICROCODE_INTEL + bool "Intel microcode loading support" +diff --git a/arch/x86/crypto/sha-mb/sha1_mb.c b/arch/x86/crypto/sha-mb/sha1_mb.c +index a841e97..8381c09 100644 +--- a/arch/x86/crypto/sha-mb/sha1_mb.c ++++ b/arch/x86/crypto/sha-mb/sha1_mb.c +@@ -453,10 +453,10 @@ static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx, + + req = cast_mcryptd_ctx_to_req(req_ctx); + if (irqs_disabled()) +- rctx->complete(&req->base, ret); ++ req_ctx->complete(&req->base, ret); + else { + local_bh_disable(); +- rctx->complete(&req->base, ret); ++ req_ctx->complete(&req->base, ret); + local_bh_enable(); + } + } +diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c +index 3ec240f..75a301b 100644 +--- a/arch/x86/entry/common.c ++++ b/arch/x86/entry/common.c +@@ -275,6 +275,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags) + /* Called with IRQs disabled. */ + __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) + { ++ struct thread_info *ti = pt_regs_to_thread_info(regs); + u32 cached_flags; + + if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled())) +@@ -282,12 +283,22 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) + + lockdep_sys_exit(); + +- cached_flags = +- READ_ONCE(pt_regs_to_thread_info(regs)->flags); ++ cached_flags = READ_ONCE(ti->flags); + + if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS)) + exit_to_usermode_loop(regs, cached_flags); + ++#ifdef CONFIG_COMPAT ++ /* ++ * Compat syscalls set TS_COMPAT. Make sure we clear it before ++ * returning to user mode. We need to clear it *after* signal ++ * handling, because syscall restart has a fixup for compat ++ * syscalls. The fixup is exercised by the ptrace_syscall_32 ++ * selftest. ++ */ ++ ti->status &= ~TS_COMPAT; ++#endif ++ + user_enter(); + } + +@@ -339,14 +350,6 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs) + if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS)) + syscall_slow_exit_work(regs, cached_flags); + +-#ifdef CONFIG_COMPAT +- /* +- * Compat syscalls set TS_COMPAT. Make sure we clear it before +- * returning to user mode. +- */ +- ti->status &= ~TS_COMPAT; +-#endif +- + local_irq_disable(); + prepare_exit_to_usermode(regs); + } +diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h +index a30316b..163769d 100644 +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -638,8 +638,8 @@ static inline void entering_irq(void) + + static inline void entering_ack_irq(void) + { +- ack_APIC_irq(); + entering_irq(); ++ ack_APIC_irq(); + } + + static inline void ipi_entering_ack_irq(void) +diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h +index f8a29d2..e6a8613 100644 +--- a/arch/x86/include/asm/hugetlb.h ++++ b/arch/x86/include/asm/hugetlb.h +@@ -4,6 +4,7 @@ + #include + #include + ++#define hugepages_supported() cpu_has_pse + + static inline int is_hugepage_only_range(struct mm_struct *mm, + unsigned long addr, +diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h +index 1e3408e..59caa55 100644 +--- a/arch/x86/include/asm/hw_irq.h ++++ b/arch/x86/include/asm/hw_irq.h +@@ -136,6 +136,7 @@ struct irq_alloc_info { + struct irq_cfg { + unsigned int dest_apicid; + u8 vector; ++ u8 old_vector; + }; + + extern struct irq_cfg *irq_cfg(unsigned int irq); +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 30cfd64..9d2abb2 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -41,7 +41,7 @@ + + #define KVM_PIO_PAGE_OFFSET 1 + #define KVM_COALESCED_MMIO_PAGE_OFFSET 2 +-#define KVM_HALT_POLL_NS_DEFAULT 500000 ++#define KVM_HALT_POLL_NS_DEFAULT 400000 + + #define KVM_IRQCHIP_NUM_PINS KVM_IOAPIC_NUM_PINS + +diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h +index 34e62b1..712b24e 100644 +--- a/arch/x86/include/asm/microcode.h ++++ b/arch/x86/include/asm/microcode.h +@@ -2,6 +2,7 @@ + #define _ASM_X86_MICROCODE_H + + #include ++#include + + #define native_rdmsr(msr, val1, val2) \ + do { \ +@@ -168,4 +169,29 @@ static inline void reload_early_microcode(void) { } + static inline bool + get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } + #endif ++ ++static inline unsigned long get_initrd_start(void) ++{ ++#ifdef CONFIG_BLK_DEV_INITRD ++ return initrd_start; ++#else ++ return 0; ++#endif ++} ++ ++static inline unsigned long get_initrd_start_addr(void) ++{ ++#ifdef CONFIG_BLK_DEV_INITRD ++#ifdef CONFIG_X86_32 ++ unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); ++ ++ return (unsigned long)__pa_nodebug(*initrd_start_p); ++#else ++ return get_initrd_start(); ++#endif ++#else /* CONFIG_BLK_DEV_INITRD */ ++ return 0; ++#endif ++} ++ + #endif /* _ASM_X86_MICROCODE_H */ +diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h +index fa1195d..164e3f8 100644 +--- a/arch/x86/include/asm/pci_x86.h ++++ b/arch/x86/include/asm/pci_x86.h +@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock; + extern int (*pcibios_enable_irq)(struct pci_dev *dev); + extern void (*pcibios_disable_irq)(struct pci_dev *dev); + ++extern bool mp_should_keep_irq(struct device *dev); ++ + struct pci_raw_ops { + int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *val); +diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h +index 7bcb861..5a2ed3e 100644 +--- a/arch/x86/include/asm/perf_event.h ++++ b/arch/x86/include/asm/perf_event.h +@@ -165,6 +165,7 @@ struct x86_pmu_capability { + #define GLOBAL_STATUS_ASIF BIT_ULL(60) + #define GLOBAL_STATUS_COUNTERS_FROZEN BIT_ULL(59) + #define GLOBAL_STATUS_LBRS_FROZEN BIT_ULL(58) ++#define GLOBAL_STATUS_TRACE_TOPAPMI BIT_ULL(55) + + /* + * IBS cpuid feature detection +diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h +index 8b2d4be..39171b3 100644 +--- a/arch/x86/include/asm/xen/hypervisor.h ++++ b/arch/x86/include/asm/xen/hypervisor.h +@@ -62,4 +62,6 @@ void xen_arch_register_cpu(int num); + void xen_arch_unregister_cpu(int num); + #endif + ++extern void xen_set_iopl_mask(unsigned mask); ++ + #endif /* _ASM_X86_XEN_HYPERVISOR_H */ +diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c +index a35f6b5..df6b4ee 100644 +--- a/arch/x86/kernel/apic/vector.c ++++ b/arch/x86/kernel/apic/vector.c +@@ -211,6 +211,7 @@ update: + */ + cpumask_and(d->old_domain, d->old_domain, cpu_online_mask); + d->move_in_progress = !cpumask_empty(d->old_domain); ++ d->cfg.old_vector = d->move_in_progress ? d->cfg.vector : 0; + d->cfg.vector = vector; + cpumask_copy(d->domain, vector_cpumask); + success: +@@ -253,7 +254,8 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data) + struct irq_desc *desc; + int cpu, vector; + +- BUG_ON(!data->cfg.vector); ++ if (!data->cfg.vector) ++ return; + + vector = data->cfg.vector; + for_each_cpu_and(cpu, data->domain, cpu_online_mask) +@@ -653,46 +655,97 @@ void irq_complete_move(struct irq_cfg *cfg) + } + + /* +- * Called with @desc->lock held and interrupts disabled. ++ * Called from fixup_irqs() with @desc->lock held and interrupts disabled. + */ + void irq_force_complete_move(struct irq_desc *desc) + { + struct irq_data *irqdata = irq_desc_get_irq_data(desc); + struct apic_chip_data *data = apic_chip_data(irqdata); + struct irq_cfg *cfg = data ? &data->cfg : NULL; ++ unsigned int cpu; + + if (!cfg) + return; + +- __irq_complete_move(cfg, cfg->vector); +- + /* + * This is tricky. If the cleanup of @data->old_domain has not been + * done yet, then the following setaffinity call will fail with + * -EBUSY. This can leave the interrupt in a stale state. + * +- * The cleanup cannot make progress because we hold @desc->lock. So in +- * case @data->old_domain is not yet cleaned up, we need to drop the +- * lock and acquire it again. @desc cannot go away, because the +- * hotplug code holds the sparse irq lock. ++ * All CPUs are stuck in stop machine with interrupts disabled so ++ * calling __irq_complete_move() would be completely pointless. + */ + raw_spin_lock(&vector_lock); +- /* Clean out all offline cpus (including ourself) first. */ ++ /* ++ * Clean out all offline cpus (including the outgoing one) from the ++ * old_domain mask. ++ */ + cpumask_and(data->old_domain, data->old_domain, cpu_online_mask); +- while (!cpumask_empty(data->old_domain)) { ++ ++ /* ++ * If move_in_progress is cleared and the old_domain mask is empty, ++ * then there is nothing to cleanup. fixup_irqs() will take care of ++ * the stale vectors on the outgoing cpu. ++ */ ++ if (!data->move_in_progress && cpumask_empty(data->old_domain)) { + raw_spin_unlock(&vector_lock); +- raw_spin_unlock(&desc->lock); +- cpu_relax(); +- raw_spin_lock(&desc->lock); ++ return; ++ } ++ ++ /* ++ * 1) The interrupt is in move_in_progress state. That means that we ++ * have not seen an interrupt since the io_apic was reprogrammed to ++ * the new vector. ++ * ++ * 2) The interrupt has fired on the new vector, but the cleanup IPIs ++ * have not been processed yet. ++ */ ++ if (data->move_in_progress) { + /* +- * Reevaluate apic_chip_data. It might have been cleared after +- * we dropped @desc->lock. ++ * In theory there is a race: ++ * ++ * set_ioapic(new_vector) <-- Interrupt is raised before update ++ * is effective, i.e. it's raised on ++ * the old vector. ++ * ++ * So if the target cpu cannot handle that interrupt before ++ * the old vector is cleaned up, we get a spurious interrupt ++ * and in the worst case the ioapic irq line becomes stale. ++ * ++ * But in case of cpu hotplug this should be a non issue ++ * because if the affinity update happens right before all ++ * cpus rendevouz in stop machine, there is no way that the ++ * interrupt can be blocked on the target cpu because all cpus ++ * loops first with interrupts enabled in stop machine, so the ++ * old vector is not yet cleaned up when the interrupt fires. ++ * ++ * So the only way to run into this issue is if the delivery ++ * of the interrupt on the apic/system bus would be delayed ++ * beyond the point where the target cpu disables interrupts ++ * in stop machine. I doubt that it can happen, but at least ++ * there is a theroretical chance. Virtualization might be ++ * able to expose this, but AFAICT the IOAPIC emulation is not ++ * as stupid as the real hardware. ++ * ++ * Anyway, there is nothing we can do about that at this point ++ * w/o refactoring the whole fixup_irq() business completely. ++ * We print at least the irq number and the old vector number, ++ * so we have the necessary information when a problem in that ++ * area arises. + */ +- data = apic_chip_data(irqdata); +- if (!data) +- return; +- raw_spin_lock(&vector_lock); ++ pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n", ++ irqdata->irq, cfg->old_vector); + } ++ /* ++ * If old_domain is not empty, then other cpus still have the irq ++ * descriptor set in their vector array. Clean it up. ++ */ ++ for_each_cpu(cpu, data->old_domain) ++ per_cpu(vector_irq, cpu)[cfg->old_vector] = VECTOR_UNUSED; ++ ++ /* Cleanup the left overs of the (half finished) move */ ++ cpumask_clear(data->old_domain); ++ data->move_in_progress = 0; + raw_spin_unlock(&vector_lock); + } + #endif +diff --git a/arch/x86/kernel/cpu/mcheck/mce-genpool.c b/arch/x86/kernel/cpu/mcheck/mce-genpool.c +index 0a85010..2658e2a 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce-genpool.c ++++ b/arch/x86/kernel/cpu/mcheck/mce-genpool.c +@@ -29,7 +29,7 @@ static char gen_pool_buf[MCE_POOLSZ]; + void mce_gen_pool_process(void) + { + struct llist_node *head; +- struct mce_evt_llist *node; ++ struct mce_evt_llist *node, *tmp; + struct mce *mce; + + head = llist_del_all(&mce_event_llist); +@@ -37,7 +37,7 @@ void mce_gen_pool_process(void) + return; + + head = llist_reverse_order(head); +- llist_for_each_entry(node, head, llnode) { ++ llist_for_each_entry_safe(node, tmp, head, llnode) { + mce = &node->mce; + atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); + gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node)); +diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c +index 2c5aaf8..0553858 100644 +--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c ++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c +@@ -385,6 +385,9 @@ static void intel_thermal_interrupt(void) + { + __u64 msr_val; + ++ if (static_cpu_has(X86_FEATURE_HWP)) ++ wrmsrl_safe(MSR_HWP_STATUS, 0); ++ + rdmsrl(MSR_IA32_THERM_STATUS, msr_val); + + /* Check for violation of core thermal thresholds*/ +diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c +index ce47402..ac8975a 100644 +--- a/arch/x86/kernel/cpu/microcode/intel.c ++++ b/arch/x86/kernel/cpu/microcode/intel.c +@@ -555,10 +555,14 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, + cd.data = NULL; + cd.size = 0; + +- cd = find_cpio_data(p, (void *)start, size, &offset); +- if (!cd.data) { ++ /* try built-in microcode if no initrd */ ++ if (!size) { + if (!load_builtin_intel_microcode(&cd)) + return UCODE_ERROR; ++ } else { ++ cd = find_cpio_data(p, (void *)start, size, &offset); ++ if (!cd.data) ++ return UCODE_ERROR; + } + + return get_matching_model_microcode(0, start, cd.data, cd.size, +@@ -694,7 +698,7 @@ int __init save_microcode_in_initrd_intel(void) + if (count == 0) + return ret; + +- copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count); ++ copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, get_initrd_start(), count); + ret = save_microcode(&mc_saved_data, mc_saved, count); + if (ret) + pr_err("Cannot save microcode patches from initrd.\n"); +@@ -732,16 +736,20 @@ void __init load_ucode_intel_bsp(void) + struct boot_params *p; + + p = (struct boot_params *)__pa_nodebug(&boot_params); +- start = p->hdr.ramdisk_image; + size = p->hdr.ramdisk_size; + +- _load_ucode_intel_bsp( +- (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), +- (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), +- start, size); ++ /* ++ * Set start only if we have an initrd image. We cannot use initrd_start ++ * because it is not set that early yet. ++ */ ++ start = (size ? p->hdr.ramdisk_image : 0); ++ ++ _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data), ++ (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), ++ start, size); + #else +- start = boot_params.hdr.ramdisk_image + PAGE_OFFSET; + size = boot_params.hdr.ramdisk_size; ++ start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0); + + _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size); + #endif +@@ -752,20 +760,14 @@ void load_ucode_intel_ap(void) + struct mc_saved_data *mc_saved_data_p; + struct ucode_cpu_info uci; + unsigned long *mc_saved_in_initrd_p; +- unsigned long initrd_start_addr; + enum ucode_state ret; + #ifdef CONFIG_X86_32 +- unsigned long *initrd_start_p; + +- mc_saved_in_initrd_p = +- (unsigned long *)__pa_nodebug(mc_saved_in_initrd); ++ mc_saved_in_initrd_p = (unsigned long *)__pa_nodebug(mc_saved_in_initrd); + mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); +- initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); +- initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p); + #else +- mc_saved_data_p = &mc_saved_data; + mc_saved_in_initrd_p = mc_saved_in_initrd; +- initrd_start_addr = initrd_start; ++ mc_saved_data_p = &mc_saved_data; + #endif + + /* +@@ -777,7 +779,7 @@ void load_ucode_intel_ap(void) + + collect_cpu_info_early(&uci); + ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, +- initrd_start_addr, &uci); ++ get_initrd_start_addr(), &uci); + + if (ret != UCODE_OK) + return; +diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c +index 2bf79d7..a3aeb2c 100644 +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -593,6 +593,19 @@ void x86_pmu_disable_all(void) + } + } + ++/* ++ * There may be PMI landing after enabled=0. The PMI hitting could be before or ++ * after disable_all. ++ * ++ * If PMI hits before disable_all, the PMU will be disabled in the NMI handler. ++ * It will not be re-enabled in the NMI handler again, because enabled=0. After ++ * handling the NMI, disable_all will be called, which will not change the ++ * state either. If PMI hits after disable_all, the PMU is already disabled ++ * before entering NMI handler. The NMI handler will not change the state ++ * either. ++ * ++ * So either situation is harmless. ++ */ + static void x86_pmu_disable(struct pmu *pmu) + { + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); +diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h +index d0e35eb..ee70445 100644 +--- a/arch/x86/kernel/cpu/perf_event.h ++++ b/arch/x86/kernel/cpu/perf_event.h +@@ -591,6 +591,7 @@ struct x86_pmu { + pebs_active :1, + pebs_broken :1; + int pebs_record_size; ++ int pebs_buffer_size; + void (*drain_pebs)(struct pt_regs *regs); + struct event_constraint *pebs_constraints; + void (*pebs_aliases)(struct perf_event *event); +@@ -907,6 +908,8 @@ void intel_pmu_lbr_init_hsw(void); + + void intel_pmu_lbr_init_skl(void); + ++void intel_pmu_pebs_data_source_nhm(void); ++ + int intel_pmu_setup_lbr_filter(struct perf_event *event); + + void intel_pt_interrupt(void); +diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c +index e2a4300..078de2e 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel.c ++++ b/arch/x86/kernel/cpu/perf_event_intel.c +@@ -1458,7 +1458,15 @@ static __initconst const u64 slm_hw_cache_event_ids + }; + + /* +- * Use from PMIs where the LBRs are already disabled. ++ * Used from PMIs where the LBRs are already disabled. ++ * ++ * This function could be called consecutively. It is required to remain in ++ * disabled state if called consecutively. ++ * ++ * During consecutive calls, the same disable value will be written to related ++ * registers, so the PMU state remains unchanged. hw.state in ++ * intel_bts_disable_local will remain PERF_HES_STOPPED too in consecutive ++ * calls. + */ + static void __intel_pmu_disable_all(void) + { +@@ -1840,6 +1848,16 @@ again: + if (__test_and_clear_bit(62, (unsigned long *)&status)) { + handled++; + x86_pmu.drain_pebs(regs); ++ /* ++ * There are cases where, even though, the PEBS ovfl bit is set ++ * in GLOBAL_OVF_STATUS, the PEBS events may also have their ++ * overflow bits set for their counters. We must clear them ++ * here because they have been processed as exact samples in ++ * the drain_pebs() routine. They must not be processed again ++ * in the for_each_bit_set() loop for regular samples below. ++ */ ++ status &= ~cpuc->pebs_enabled; ++ status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI; + } + + /* +@@ -1885,7 +1903,10 @@ again: + goto again; + + done: +- __intel_pmu_enable_all(0, true); ++ /* Only restore PMU state when it's active. See x86_pmu_disable(). */ ++ if (cpuc->enabled) ++ __intel_pmu_enable_all(0, true); ++ + /* + * Only unmask the NMI after the overflow counters + * have been reset. This avoids spurious NMIs on +@@ -3315,6 +3336,7 @@ __init int intel_pmu_init(void) + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = + X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1); + ++ intel_pmu_pebs_data_source_nhm(); + x86_add_quirk(intel_nehalem_quirk); + + pr_cont("Nehalem events, "); +@@ -3377,6 +3399,7 @@ __init int intel_pmu_init(void) + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = + X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1); + ++ intel_pmu_pebs_data_source_nhm(); + pr_cont("Westmere events, "); + break; + +diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c +index 5db1c77..7abb2b8 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c +@@ -51,7 +51,8 @@ union intel_x86_pebs_dse { + #define OP_LH (P(OP, LOAD) | P(LVL, HIT)) + #define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS)) + +-static const u64 pebs_data_source[] = { ++/* Version for Sandy Bridge and later */ ++static u64 pebs_data_source[] = { + P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */ + OP_LH | P(LVL, L1) | P(SNOOP, NONE), /* 0x01: L1 local */ + OP_LH | P(LVL, LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */ +@@ -70,6 +71,14 @@ static const u64 pebs_data_source[] = { + OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */ + }; + ++/* Patch up minor differences in the bits */ ++void __init intel_pmu_pebs_data_source_nhm(void) ++{ ++ pebs_data_source[0x05] = OP_LH | P(LVL, L3) | P(SNOOP, HIT); ++ pebs_data_source[0x06] = OP_LH | P(LVL, L3) | P(SNOOP, HITM); ++ pebs_data_source[0x07] = OP_LH | P(LVL, L3) | P(SNOOP, HITM); ++} ++ + static u64 precise_store_data(u64 status) + { + union intel_x86_pebs_dse dse; +@@ -269,7 +278,7 @@ static int alloc_pebs_buffer(int cpu) + if (!x86_pmu.pebs) + return 0; + +- buffer = kzalloc_node(PEBS_BUFFER_SIZE, GFP_KERNEL, node); ++ buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node); + if (unlikely(!buffer)) + return -ENOMEM; + +@@ -286,7 +295,7 @@ static int alloc_pebs_buffer(int cpu) + per_cpu(insn_buffer, cpu) = ibuffer; + } + +- max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size; ++ max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size; + + ds->pebs_buffer_base = (u64)(unsigned long)buffer; + ds->pebs_index = ds->pebs_buffer_base; +@@ -1296,6 +1305,7 @@ void __init intel_ds_init(void) + + x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS); + x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS); ++ x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE; + if (x86_pmu.pebs) { + char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-'; + int format = x86_pmu.intel_cap.pebs_format; +@@ -1304,6 +1314,14 @@ void __init intel_ds_init(void) + case 0: + printk(KERN_CONT "PEBS fmt0%c, ", pebs_type); + x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); ++ /* ++ * Using >PAGE_SIZE buffers makes the WRMSR to ++ * PERF_GLOBAL_CTRL in intel_pmu_enable_all() ++ * mysteriously hang on Core2. ++ * ++ * As a workaround, we don't do this. ++ */ ++ x86_pmu.pebs_buffer_size = PAGE_SIZE; + x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; + break; + +diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c +index 868e119..49e35d0 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c +@@ -694,6 +694,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, + + /* clear STOP and INT from current entry */ + buf->topa_index[buf->stop_pos]->stop = 0; ++ buf->topa_index[buf->stop_pos]->intr = 0; + buf->topa_index[buf->intr_pos]->intr = 0; + + /* how many pages till the STOP marker */ +@@ -718,6 +719,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, + buf->intr_pos = idx; + + buf->topa_index[buf->stop_pos]->stop = 1; ++ buf->topa_index[buf->stop_pos]->intr = 1; + buf->topa_index[buf->intr_pos]->intr = 1; + + return 0; +diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +index ed446bd..d2ac364 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +@@ -117,7 +117,7 @@ static struct perf_pmu_events_attr event_attr_##v = { \ + }; + + struct rapl_pmu { +- spinlock_t lock; ++ raw_spinlock_t lock; + int n_active; /* number of active events */ + struct list_head active_list; + struct pmu *pmu; /* pointer to rapl_pmu_class */ +@@ -220,13 +220,13 @@ static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer) + if (!pmu->n_active) + return HRTIMER_NORESTART; + +- spin_lock_irqsave(&pmu->lock, flags); ++ raw_spin_lock_irqsave(&pmu->lock, flags); + + list_for_each_entry(event, &pmu->active_list, active_entry) { + rapl_event_update(event); + } + +- spin_unlock_irqrestore(&pmu->lock, flags); ++ raw_spin_unlock_irqrestore(&pmu->lock, flags); + + hrtimer_forward_now(hrtimer, pmu->timer_interval); + +@@ -263,9 +263,9 @@ static void rapl_pmu_event_start(struct perf_event *event, int mode) + struct rapl_pmu *pmu = __this_cpu_read(rapl_pmu); + unsigned long flags; + +- spin_lock_irqsave(&pmu->lock, flags); ++ raw_spin_lock_irqsave(&pmu->lock, flags); + __rapl_pmu_event_start(pmu, event); +- spin_unlock_irqrestore(&pmu->lock, flags); ++ raw_spin_unlock_irqrestore(&pmu->lock, flags); + } + + static void rapl_pmu_event_stop(struct perf_event *event, int mode) +@@ -274,7 +274,7 @@ static void rapl_pmu_event_stop(struct perf_event *event, int mode) + struct hw_perf_event *hwc = &event->hw; + unsigned long flags; + +- spin_lock_irqsave(&pmu->lock, flags); ++ raw_spin_lock_irqsave(&pmu->lock, flags); + + /* mark event as deactivated and stopped */ + if (!(hwc->state & PERF_HES_STOPPED)) { +@@ -299,7 +299,7 @@ static void rapl_pmu_event_stop(struct perf_event *event, int mode) + hwc->state |= PERF_HES_UPTODATE; + } + +- spin_unlock_irqrestore(&pmu->lock, flags); ++ raw_spin_unlock_irqrestore(&pmu->lock, flags); + } + + static int rapl_pmu_event_add(struct perf_event *event, int mode) +@@ -308,14 +308,14 @@ static int rapl_pmu_event_add(struct perf_event *event, int mode) + struct hw_perf_event *hwc = &event->hw; + unsigned long flags; + +- spin_lock_irqsave(&pmu->lock, flags); ++ raw_spin_lock_irqsave(&pmu->lock, flags); + + hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; + + if (mode & PERF_EF_START) + __rapl_pmu_event_start(pmu, event); + +- spin_unlock_irqrestore(&pmu->lock, flags); ++ raw_spin_unlock_irqrestore(&pmu->lock, flags); + + return 0; + } +@@ -603,7 +603,7 @@ static int rapl_cpu_prepare(int cpu) + pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu)); + if (!pmu) + return -1; +- spin_lock_init(&pmu->lock); ++ raw_spin_lock_init(&pmu->lock); + + INIT_LIST_HEAD(&pmu->active_list); + +diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c +index 5b0c232..b931095 100644 +--- a/arch/x86/kernel/cpu/perf_event_knc.c ++++ b/arch/x86/kernel/cpu/perf_event_knc.c +@@ -263,7 +263,9 @@ again: + goto again; + + done: +- knc_pmu_enable_all(0); ++ /* Only restore PMU state when it's active. See x86_pmu_disable(). */ ++ if (cpuc->enabled) ++ knc_pmu_enable_all(0); + + return handled; + } +diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c +index 37dae79..589b319 100644 +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -96,9 +96,14 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) + SYSCALL_DEFINE1(iopl, unsigned int, level) + { + struct pt_regs *regs = current_pt_regs(); +- unsigned int old = (regs->flags >> 12) & 3; + struct thread_struct *t = ¤t->thread; + ++ /* ++ * Careful: the IOPL bits in regs->flags are undefined under Xen PV ++ * and changing them has no effect. ++ */ ++ unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT; ++ + if (level > 3) + return -EINVAL; + /* Trying to gain more privileges? */ +@@ -106,8 +111,9 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + } +- regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); +- t->iopl = level << 12; ++ regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | ++ (level << X86_EFLAGS_IOPL_BIT); ++ t->iopl = level << X86_EFLAGS_IOPL_BIT; + set_iopl_mask(t->iopl); + + return 0; +diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c +index 47190bd..8079508 100644 +--- a/arch/x86/kernel/kvm.c ++++ b/arch/x86/kernel/kvm.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -91,14 +92,14 @@ static void kvm_io_delay(void) + + struct kvm_task_sleep_node { + struct hlist_node link; +- wait_queue_head_t wq; ++ struct swait_queue_head wq; + u32 token; + int cpu; + bool halted; + }; + + static struct kvm_task_sleep_head { +- spinlock_t lock; ++ raw_spinlock_t lock; + struct hlist_head list; + } async_pf_sleepers[KVM_TASK_SLEEP_HASHSIZE]; + +@@ -122,17 +123,17 @@ void kvm_async_pf_task_wait(u32 token) + u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS); + struct kvm_task_sleep_head *b = &async_pf_sleepers[key]; + struct kvm_task_sleep_node n, *e; +- DEFINE_WAIT(wait); ++ DECLARE_SWAITQUEUE(wait); + + rcu_irq_enter(); + +- spin_lock(&b->lock); ++ raw_spin_lock(&b->lock); + e = _find_apf_task(b, token); + if (e) { + /* dummy entry exist -> wake up was delivered ahead of PF */ + hlist_del(&e->link); + kfree(e); +- spin_unlock(&b->lock); ++ raw_spin_unlock(&b->lock); + + rcu_irq_exit(); + return; +@@ -141,13 +142,13 @@ void kvm_async_pf_task_wait(u32 token) + n.token = token; + n.cpu = smp_processor_id(); + n.halted = is_idle_task(current) || preempt_count() > 1; +- init_waitqueue_head(&n.wq); ++ init_swait_queue_head(&n.wq); + hlist_add_head(&n.link, &b->list); +- spin_unlock(&b->lock); ++ raw_spin_unlock(&b->lock); + + for (;;) { + if (!n.halted) +- prepare_to_wait(&n.wq, &wait, TASK_UNINTERRUPTIBLE); ++ prepare_to_swait(&n.wq, &wait, TASK_UNINTERRUPTIBLE); + if (hlist_unhashed(&n.link)) + break; + +@@ -166,7 +167,7 @@ void kvm_async_pf_task_wait(u32 token) + } + } + if (!n.halted) +- finish_wait(&n.wq, &wait); ++ finish_swait(&n.wq, &wait); + + rcu_irq_exit(); + return; +@@ -178,8 +179,8 @@ static void apf_task_wake_one(struct kvm_task_sleep_node *n) + hlist_del_init(&n->link); + if (n->halted) + smp_send_reschedule(n->cpu); +- else if (waitqueue_active(&n->wq)) +- wake_up(&n->wq); ++ else if (swait_active(&n->wq)) ++ swake_up(&n->wq); + } + + static void apf_task_wake_all(void) +@@ -189,14 +190,14 @@ static void apf_task_wake_all(void) + for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++) { + struct hlist_node *p, *next; + struct kvm_task_sleep_head *b = &async_pf_sleepers[i]; +- spin_lock(&b->lock); ++ raw_spin_lock(&b->lock); + hlist_for_each_safe(p, next, &b->list) { + struct kvm_task_sleep_node *n = + hlist_entry(p, typeof(*n), link); + if (n->cpu == smp_processor_id()) + apf_task_wake_one(n); + } +- spin_unlock(&b->lock); ++ raw_spin_unlock(&b->lock); + } + } + +@@ -212,7 +213,7 @@ void kvm_async_pf_task_wake(u32 token) + } + + again: +- spin_lock(&b->lock); ++ raw_spin_lock(&b->lock); + n = _find_apf_task(b, token); + if (!n) { + /* +@@ -225,17 +226,17 @@ again: + * Allocation failed! Busy wait while other cpu + * handles async PF. + */ +- spin_unlock(&b->lock); ++ raw_spin_unlock(&b->lock); + cpu_relax(); + goto again; + } + n->token = token; + n->cpu = smp_processor_id(); +- init_waitqueue_head(&n->wq); ++ init_swait_queue_head(&n->wq); + hlist_add_head(&n->link, &b->list); + } else + apf_task_wake_one(n); +- spin_unlock(&b->lock); ++ raw_spin_unlock(&b->lock); + return; + } + EXPORT_SYMBOL_GPL(kvm_async_pf_task_wake); +@@ -486,7 +487,7 @@ void __init kvm_guest_init(void) + paravirt_ops_setup(); + register_reboot_notifier(&kvm_pv_reboot_nb); + for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++) +- spin_lock_init(&async_pf_sleepers[i].lock); ++ raw_spin_lock_init(&async_pf_sleepers[i].lock); + if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF)) + x86_init.irqs.trap_init = kvm_apf_trap_init; + +diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c +index 697f90d..424aec4 100644 +--- a/arch/x86/kernel/nmi.c ++++ b/arch/x86/kernel/nmi.c +@@ -231,7 +231,7 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs) + #endif + + if (panic_on_unrecovered_nmi) +- panic("NMI: Not continuing"); ++ nmi_panic(regs, "NMI: Not continuing"); + + pr_emerg("Dazed and confused, but trying to continue\n"); + +@@ -255,8 +255,16 @@ io_check_error(unsigned char reason, struct pt_regs *regs) + reason, smp_processor_id()); + show_regs(regs); + +- if (panic_on_io_nmi) +- panic("NMI IOCK error: Not continuing"); ++ if (panic_on_io_nmi) { ++ nmi_panic(regs, "NMI IOCK error: Not continuing"); ++ ++ /* ++ * If we end up here, it means we have received an NMI while ++ * processing panic(). Simply return without delaying and ++ * re-enabling NMIs. ++ */ ++ return; ++ } + + /* Re-enable the IOCK line, wait for a few seconds */ + reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK; +@@ -297,7 +305,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) + + pr_emerg("Do you have a strange power saving mode enabled?\n"); + if (unknown_nmi_panic || panic_on_unrecovered_nmi) +- panic("NMI: Not continuing"); ++ nmi_panic(regs, "NMI: Not continuing"); + + pr_emerg("Dazed and confused, but trying to continue\n"); + } +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index e835d26..4cbb60f 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + asmlinkage extern void ret_from_fork(void); + +@@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) + __switch_to_xtra(prev_p, next_p, tss); + ++#ifdef CONFIG_XEN ++ /* ++ * On Xen PV, IOPL bits in pt_regs->flags have no effect, and ++ * current_pt_regs()->flags may not match the current task's ++ * intended IOPL. We need to switch it manually. ++ */ ++ if (unlikely(static_cpu_has(X86_FEATURE_XENPV) && ++ prev->iopl != next->iopl)) ++ xen_set_iopl_mask(next->iopl); ++#endif ++ + if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) { + /* + * AMD CPUs have a misfeature: SYSRET sets the SS selector but +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index f660d63..8384207 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -726,6 +726,7 @@ static int crashing_cpu; + static nmi_shootdown_cb shootdown_callback; + + static atomic_t waiting_for_crash_ipi; ++static int crash_ipi_issued; + + static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) + { +@@ -788,6 +789,9 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) + + smp_send_nmi_allbutself(); + ++ /* Kick CPUs looping in NMI context. */ ++ WRITE_ONCE(crash_ipi_issued, 1); ++ + msecs = 1000; /* Wait at most a second for the other cpus to stop */ + while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { + mdelay(1); +@@ -796,6 +800,22 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) + + /* Leave the nmi callback set */ + } ++ ++/* Override the weak function in kernel/panic.c */ ++void nmi_panic_self_stop(struct pt_regs *regs) ++{ ++ while (1) { ++ /* ++ * Wait for the crash dumping IPI to be issued, and then ++ * call its callback directly. ++ */ ++ if (READ_ONCE(crash_ipi_issued)) ++ crash_nmi_callback(0, regs); /* Don't return */ ++ ++ cpu_relax(); ++ } ++} ++ + #else /* !CONFIG_SMP */ + void nmi_shootdown_cpus(nmi_shootdown_cb callback) + { +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index fbabe4f..b0256e0 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -429,7 +429,12 @@ void set_cpu_sibling_map(int cpu) + } else if (i != cpu && !c->booted_cores) + c->booted_cores = cpu_data(i).booted_cores; + } ++#ifndef CONFIG_NUMA + if (match_die(c, o) && !topology_same_node(c, o)) ++#else ++ if (match_die(c, o) && !topology_same_node(c, o) ++ && sched_max_numa_distance == -1) ++#endif + primarily_use_numa_for_topology(); + } + } +diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c +index b285d4e..5da924b 100644 +--- a/arch/x86/kernel/sysfb_efi.c ++++ b/arch/x86/kernel/sysfb_efi.c +@@ -106,14 +106,24 @@ static int __init efifb_set_system(const struct dmi_system_id *id) + continue; + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + resource_size_t start, end; ++ unsigned long flags; ++ ++ flags = pci_resource_flags(dev, i); ++ if (!(flags & IORESOURCE_MEM)) ++ continue; ++ ++ if (flags & IORESOURCE_UNSET) ++ continue; ++ ++ if (pci_resource_len(dev, i) == 0) ++ continue; + + start = pci_resource_start(dev, i); +- if (start == 0) +- break; + end = pci_resource_end(dev, i); + if (screen_info.lfb_base >= start && + screen_info.lfb_base < end) { + found_bar = 1; ++ break; + } + } + } +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index ade185a..679302c 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -109,6 +109,12 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) + preempt_count_dec(); + } + ++/* ++ * In IST context, we explicitly disable preemption. This serves two ++ * purposes: it makes it much less likely that we would accidentally ++ * schedule in IST context and it will force a warning if we somehow ++ * manage to schedule by accident. ++ */ + void ist_enter(struct pt_regs *regs) + { + if (user_mode(regs)) { +@@ -123,13 +129,7 @@ void ist_enter(struct pt_regs *regs) + rcu_nmi_enter(); + } + +- /* +- * We are atomic because we're on the IST stack; or we're on +- * x86_32, in which case we still shouldn't schedule; or we're +- * on x86_64 and entered from user mode, in which case we're +- * still atomic unless ist_begin_non_atomic is called. +- */ +- preempt_count_add(HARDIRQ_OFFSET); ++ preempt_disable(); + + /* This code is a bit fragile. Test it. */ + RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work"); +@@ -137,7 +137,7 @@ void ist_enter(struct pt_regs *regs) + + void ist_exit(struct pt_regs *regs) + { +- preempt_count_sub(HARDIRQ_OFFSET); ++ preempt_enable_no_resched(); + + if (!user_mode(regs)) + rcu_nmi_exit(); +@@ -168,7 +168,7 @@ void ist_begin_non_atomic(struct pt_regs *regs) + BUG_ON((unsigned long)(current_top_of_stack() - + current_stack_pointer()) >= THREAD_SIZE); + +- preempt_count_sub(HARDIRQ_OFFSET); ++ preempt_enable_no_resched(); + } + + /** +@@ -178,7 +178,7 @@ void ist_begin_non_atomic(struct pt_regs *regs) + */ + void ist_end_non_atomic(void) + { +- preempt_count_add(HARDIRQ_OFFSET); ++ preempt_disable(); + } + + static nokprobe_inline int +diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c +index 92ae6ac..6aa0f4d 100644 +--- a/arch/x86/kernel/tsc_msr.c ++++ b/arch/x86/kernel/tsc_msr.c +@@ -92,7 +92,7 @@ unsigned long try_msr_calibrate_tsc(void) + + if (freq_desc_tables[cpu_index].msr_plat) { + rdmsr(MSR_PLATFORM_INFO, lo, hi); +- ratio = (lo >> 8) & 0x1f; ++ ratio = (lo >> 8) & 0xff; + } else { + rdmsr(MSR_IA32_PERF_STATUS, lo, hi); + ratio = (hi >> 8) & 0x1f; +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index 6525e92..2e1fd58 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -509,6 +509,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, + do_cpuid_1_ent(&entry[i], function, idx); + if (idx == 1) { + entry[i].eax &= kvm_supported_word10_x86_features; ++ cpuid_mask(&entry[i].eax, 10); + entry[i].ebx = 0; + if (entry[i].eax & (F(XSAVES)|F(XSAVEC))) + entry[i].ebx = +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index b0ea42b..ab53187 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -245,7 +245,7 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian) + * PIC is being reset. Handle it gracefully here + */ + atomic_inc(&ps->pending); +- else if (value > 0) ++ else if (value > 0 && ps->reinject) + /* in this case, we had multiple outstanding pit interrupts + * that we needed to inject. Reinject + */ +@@ -288,7 +288,9 @@ static void pit_do_work(struct kthread_work *work) + * last one has been acked. + */ + spin_lock(&ps->inject_lock); +- if (ps->irq_ack) { ++ if (!ps->reinject) ++ inject = 1; ++ else if (ps->irq_ack) { + ps->irq_ack = 0; + inject = 1; + } +@@ -317,10 +319,10 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) + struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer); + struct kvm_pit *pt = ps->kvm->arch.vpit; + +- if (ps->reinject || !atomic_read(&ps->pending)) { ++ if (ps->reinject) + atomic_inc(&ps->pending); +- queue_kthread_work(&pt->worker, &pt->expired); +- } ++ ++ queue_kthread_work(&pt->worker, &pt->expired); + + if (ps->is_periodic) { + hrtimer_add_expires_ns(&ps->timer, ps->period); +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 906a1ec..20d9e9f 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1195,7 +1195,7 @@ static void apic_update_lvtt(struct kvm_lapic *apic) + static void apic_timer_expired(struct kvm_lapic *apic) + { + struct kvm_vcpu *vcpu = apic->vcpu; +- struct swait_head *q = &vcpu->wq; ++ struct swait_queue_head *q = &vcpu->wq; + struct kvm_timer *ktimer = &apic->lapic_timer; + + if (atomic_read(&apic->lapic_timer.pending)) +@@ -1204,8 +1204,8 @@ static void apic_timer_expired(struct kvm_lapic *apic) + atomic_inc(&apic->lapic_timer.pending); + kvm_set_pending_timer(vcpu); + +- if (swaitqueue_active(q)) +- swait_wake_interruptible(q); ++ if (swait_active(q)) ++ swake_up(q); + + if (apic_lvtt_tscdeadline(apic)) + ktimer->expired_tscdeadline = ktimer->tscdeadline; +diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c +index 3f8c732..c146f3c 100644 +--- a/arch/x86/kvm/mtrr.c ++++ b/arch/x86/kvm/mtrr.c +@@ -44,8 +44,6 @@ static bool msr_mtrr_valid(unsigned msr) + case MSR_MTRRdefType: + case MSR_IA32_CR_PAT: + return true; +- case 0x2f8: +- return true; + } + return false; + } +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 0958fa2..f314e9b 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2637,8 +2637,15 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) + } else + vmx->nested.nested_vmx_ept_caps = 0; + ++ /* ++ * Old versions of KVM use the single-context version without ++ * checking for support, so declare that it is supported even ++ * though it is treated as global context. The alternative is ++ * not failing the single-context invvpid, and it is worse. ++ */ + if (enable_vpid) + vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT | ++ VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT | + VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT; + else + vmx->nested.nested_vmx_vpid_caps = 0; +@@ -4947,8 +4954,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) + vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); + + cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; +- vmx_set_cr0(vcpu, cr0); /* enter rmode */ + vmx->vcpu.arch.cr0 = cr0; ++ vmx_set_cr0(vcpu, cr0); /* enter rmode */ + vmx_set_cr4(vcpu, 0); + vmx_set_efer(vcpu, 0); + vmx_fpu_activate(vcpu); +@@ -7340,6 +7347,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) + if (!(types & (1UL << type))) { + nested_vmx_failValid(vcpu, + VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); ++ skip_emulated_instruction(vcpu); + return 1; + } + +@@ -7398,6 +7406,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) + if (!(types & (1UL << type))) { + nested_vmx_failValid(vcpu, + VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); ++ skip_emulated_instruction(vcpu); + return 1; + } + +@@ -7414,12 +7423,17 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) + } + + switch (type) { ++ case VMX_VPID_EXTENT_SINGLE_CONTEXT: ++ /* ++ * Old versions of KVM use the single-context version so we ++ * have to support it; just treat it the same as all-context. ++ */ + case VMX_VPID_EXTENT_ALL_CONTEXT: + __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02); + nested_vmx_succeed(vcpu); + break; + default: +- /* Trap single context invalidation invvpid calls */ ++ /* Trap individual address invalidation invvpid calls */ + BUG_ON(1); + break; + } +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 27419ba..6974578 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -697,7 +697,6 @@ static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) + if ((xcr0 & XFEATURE_MASK_AVX512) != XFEATURE_MASK_AVX512) + return 1; + } +- kvm_put_guest_xcr0(vcpu); + vcpu->arch.xcr0 = xcr0; + + if ((xcr0 ^ old_xcr0) & XFEATURE_MASK_EXTEND) +@@ -2736,6 +2735,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + } + + kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); ++ vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD; + } + + void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +@@ -3014,6 +3014,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, + if (dbgregs->flags) + return -EINVAL; + ++ if (dbgregs->dr6 & ~0xffffffffull) ++ return -EINVAL; ++ if (dbgregs->dr7 & ~0xffffffffull) ++ return -EINVAL; ++ + memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db)); + kvm_update_dr0123(vcpu); + vcpu->arch.dr6 = dbgregs->dr6; +@@ -6030,12 +6035,10 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win) + } + + /* try to inject new event if pending */ +- if (vcpu->arch.nmi_pending) { +- if (kvm_x86_ops->nmi_allowed(vcpu)) { +- --vcpu->arch.nmi_pending; +- vcpu->arch.nmi_injected = true; +- kvm_x86_ops->set_nmi(vcpu); +- } ++ if (vcpu->arch.nmi_pending && kvm_x86_ops->nmi_allowed(vcpu)) { ++ --vcpu->arch.nmi_pending; ++ vcpu->arch.nmi_injected = true; ++ kvm_x86_ops->set_nmi(vcpu); + } else if (kvm_cpu_has_injectable_intr(vcpu)) { + /* + * Because interrupts can be injected asynchronously, we are +@@ -6480,10 +6483,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + if (inject_pending_event(vcpu, req_int_win) != 0) + req_immediate_exit = true; + /* enable NMI/IRQ window open exits if needed */ +- else if (vcpu->arch.nmi_pending) +- kvm_x86_ops->enable_nmi_window(vcpu); +- else if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win) +- kvm_x86_ops->enable_irq_window(vcpu); ++ else { ++ if (vcpu->arch.nmi_pending) ++ kvm_x86_ops->enable_nmi_window(vcpu); ++ if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win) ++ kvm_x86_ops->enable_irq_window(vcpu); ++ } + + if (kvm_lapic_enabled(vcpu)) { + update_cr8_intercept(vcpu); +@@ -6501,8 +6506,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + kvm_x86_ops->prepare_guest_switch(vcpu); + if (vcpu->fpu_active) + kvm_load_guest_fpu(vcpu); +- kvm_load_guest_xcr0(vcpu); +- + vcpu->mode = IN_GUEST_MODE; + + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); +@@ -6525,6 +6528,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + goto cancel_injection; + } + ++ kvm_load_guest_xcr0(vcpu); ++ + if (req_immediate_exit) + smp_send_reschedule(vcpu->cpu); + +@@ -6574,6 +6579,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + vcpu->mode = OUTSIDE_GUEST_MODE; + smp_wmb(); + ++ kvm_put_guest_xcr0(vcpu); ++ + /* Interrupt is enabled by handle_external_intr() */ + kvm_x86_ops->handle_external_intr(vcpu); + +@@ -7221,7 +7228,6 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) + * and assume host would use all available bits. + * Guest xcr0 would be loaded later. + */ +- kvm_put_guest_xcr0(vcpu); + vcpu->guest_fpu_loaded = 1; + __kernel_fpu_begin(); + __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu.state); +@@ -7230,8 +7236,6 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) + + void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) + { +- kvm_put_guest_xcr0(vcpu); +- + if (!vcpu->guest_fpu_loaded) { + vcpu->fpu_counter = 0; + return; +diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c +index 637ab34..ddb2244 100644 +--- a/arch/x86/mm/kmmio.c ++++ b/arch/x86/mm/kmmio.c +@@ -33,7 +33,7 @@ + struct kmmio_fault_page { + struct list_head list; + struct kmmio_fault_page *release_next; +- unsigned long page; /* location of the fault page */ ++ unsigned long addr; /* the requested address */ + pteval_t old_presence; /* page presence prior to arming */ + bool armed; + +@@ -70,9 +70,16 @@ unsigned int kmmio_count; + static struct list_head kmmio_page_table[KMMIO_PAGE_TABLE_SIZE]; + static LIST_HEAD(kmmio_probes); + +-static struct list_head *kmmio_page_list(unsigned long page) ++static struct list_head *kmmio_page_list(unsigned long addr) + { +- return &kmmio_page_table[hash_long(page, KMMIO_PAGE_HASH_BITS)]; ++ unsigned int l; ++ pte_t *pte = lookup_address(addr, &l); ++ ++ if (!pte) ++ return NULL; ++ addr &= page_level_mask(l); ++ ++ return &kmmio_page_table[hash_long(addr, KMMIO_PAGE_HASH_BITS)]; + } + + /* Accessed per-cpu */ +@@ -98,15 +105,19 @@ static struct kmmio_probe *get_kmmio_probe(unsigned long addr) + } + + /* You must be holding RCU read lock. */ +-static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page) ++static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long addr) + { + struct list_head *head; + struct kmmio_fault_page *f; ++ unsigned int l; ++ pte_t *pte = lookup_address(addr, &l); + +- page &= PAGE_MASK; +- head = kmmio_page_list(page); ++ if (!pte) ++ return NULL; ++ addr &= page_level_mask(l); ++ head = kmmio_page_list(addr); + list_for_each_entry_rcu(f, head, list) { +- if (f->page == page) ++ if (f->addr == addr) + return f; + } + return NULL; +@@ -137,10 +148,10 @@ static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old) + static int clear_page_presence(struct kmmio_fault_page *f, bool clear) + { + unsigned int level; +- pte_t *pte = lookup_address(f->page, &level); ++ pte_t *pte = lookup_address(f->addr, &level); + + if (!pte) { +- pr_err("no pte for page 0x%08lx\n", f->page); ++ pr_err("no pte for addr 0x%08lx\n", f->addr); + return -1; + } + +@@ -156,7 +167,7 @@ static int clear_page_presence(struct kmmio_fault_page *f, bool clear) + return -1; + } + +- __flush_tlb_one(f->page); ++ __flush_tlb_one(f->addr); + return 0; + } + +@@ -176,12 +187,12 @@ static int arm_kmmio_fault_page(struct kmmio_fault_page *f) + int ret; + WARN_ONCE(f->armed, KERN_ERR pr_fmt("kmmio page already armed.\n")); + if (f->armed) { +- pr_warning("double-arm: page 0x%08lx, ref %d, old %d\n", +- f->page, f->count, !!f->old_presence); ++ pr_warning("double-arm: addr 0x%08lx, ref %d, old %d\n", ++ f->addr, f->count, !!f->old_presence); + } + ret = clear_page_presence(f, true); +- WARN_ONCE(ret < 0, KERN_ERR pr_fmt("arming 0x%08lx failed.\n"), +- f->page); ++ WARN_ONCE(ret < 0, KERN_ERR pr_fmt("arming at 0x%08lx failed.\n"), ++ f->addr); + f->armed = true; + return ret; + } +@@ -191,7 +202,7 @@ static void disarm_kmmio_fault_page(struct kmmio_fault_page *f) + { + int ret = clear_page_presence(f, false); + WARN_ONCE(ret < 0, +- KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page); ++ KERN_ERR "kmmio disarming at 0x%08lx failed.\n", f->addr); + f->armed = false; + } + +@@ -215,6 +226,12 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) + struct kmmio_context *ctx; + struct kmmio_fault_page *faultpage; + int ret = 0; /* default to fault not handled */ ++ unsigned long page_base = addr; ++ unsigned int l; ++ pte_t *pte = lookup_address(addr, &l); ++ if (!pte) ++ return -EINVAL; ++ page_base &= page_level_mask(l); + + /* + * Preemption is now disabled to prevent process switch during +@@ -227,7 +244,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) + preempt_disable(); + rcu_read_lock(); + +- faultpage = get_kmmio_fault_page(addr); ++ faultpage = get_kmmio_fault_page(page_base); + if (!faultpage) { + /* + * Either this page fault is not caused by kmmio, or +@@ -239,7 +256,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) + + ctx = &get_cpu_var(kmmio_ctx); + if (ctx->active) { +- if (addr == ctx->addr) { ++ if (page_base == ctx->addr) { + /* + * A second fault on the same page means some other + * condition needs handling by do_page_fault(), the +@@ -267,9 +284,9 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) + ctx->active++; + + ctx->fpage = faultpage; +- ctx->probe = get_kmmio_probe(addr); ++ ctx->probe = get_kmmio_probe(page_base); + ctx->saved_flags = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF)); +- ctx->addr = addr; ++ ctx->addr = page_base; + + if (ctx->probe && ctx->probe->pre_handler) + ctx->probe->pre_handler(ctx->probe, regs, addr); +@@ -354,12 +371,11 @@ out: + } + + /* You must be holding kmmio_lock. */ +-static int add_kmmio_fault_page(unsigned long page) ++static int add_kmmio_fault_page(unsigned long addr) + { + struct kmmio_fault_page *f; + +- page &= PAGE_MASK; +- f = get_kmmio_fault_page(page); ++ f = get_kmmio_fault_page(addr); + if (f) { + if (!f->count) + arm_kmmio_fault_page(f); +@@ -372,26 +388,25 @@ static int add_kmmio_fault_page(unsigned long page) + return -1; + + f->count = 1; +- f->page = page; ++ f->addr = addr; + + if (arm_kmmio_fault_page(f)) { + kfree(f); + return -1; + } + +- list_add_rcu(&f->list, kmmio_page_list(f->page)); ++ list_add_rcu(&f->list, kmmio_page_list(f->addr)); + + return 0; + } + + /* You must be holding kmmio_lock. */ +-static void release_kmmio_fault_page(unsigned long page, ++static void release_kmmio_fault_page(unsigned long addr, + struct kmmio_fault_page **release_list) + { + struct kmmio_fault_page *f; + +- page &= PAGE_MASK; +- f = get_kmmio_fault_page(page); ++ f = get_kmmio_fault_page(addr); + if (!f) + return; + +@@ -420,18 +435,27 @@ int register_kmmio_probe(struct kmmio_probe *p) + int ret = 0; + unsigned long size = 0; + const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK); ++ unsigned int l; ++ pte_t *pte; + + spin_lock_irqsave(&kmmio_lock, flags); + if (get_kmmio_probe(p->addr)) { + ret = -EEXIST; + goto out; + } ++ ++ pte = lookup_address(p->addr, &l); ++ if (!pte) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + kmmio_count++; + list_add_rcu(&p->list, &kmmio_probes); + while (size < size_lim) { + if (add_kmmio_fault_page(p->addr + size)) + pr_err("Unable to set page fault.\n"); +- size += PAGE_SIZE; ++ size += page_level_size(l); + } + out: + spin_unlock_irqrestore(&kmmio_lock, flags); +@@ -506,11 +530,17 @@ void unregister_kmmio_probe(struct kmmio_probe *p) + const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK); + struct kmmio_fault_page *release_list = NULL; + struct kmmio_delayed_release *drelease; ++ unsigned int l; ++ pte_t *pte; ++ ++ pte = lookup_address(p->addr, &l); ++ if (!pte) ++ return; + + spin_lock_irqsave(&kmmio_lock, flags); + while (size < size_lim) { + release_kmmio_fault_page(p->addr + size, &release_list); +- size += PAGE_SIZE; ++ size += page_level_size(l); + } + list_del_rcu(&p->list); + kmmio_count--; +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index 8f4cc3d..5fb6ada 100644 +--- a/arch/x86/mm/tlb.c ++++ b/arch/x86/mm/tlb.c +@@ -106,8 +106,6 @@ static void flush_tlb_func(void *info) + + if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) + return; +- if (!f->flush_end) +- f->flush_end = f->flush_start + PAGE_SIZE; + + count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED); + if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { +@@ -135,12 +133,20 @@ void native_flush_tlb_others(const struct cpumask *cpumask, + unsigned long end) + { + struct flush_tlb_info info; ++ ++ if (end == 0) ++ end = start + PAGE_SIZE; + info.flush_mm = mm; + info.flush_start = start; + info.flush_end = end; + + count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); +- trace_tlb_flush(TLB_REMOTE_SEND_IPI, end - start); ++ if (end == TLB_FLUSH_ALL) ++ trace_tlb_flush(TLB_REMOTE_SEND_IPI, TLB_FLUSH_ALL); ++ else ++ trace_tlb_flush(TLB_REMOTE_SEND_IPI, ++ (end - start) >> PAGE_SHIFT); ++ + if (is_uv_system()) { + unsigned int cpu; + +diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c +index eccd4d9..8fd6f44 100644 +--- a/arch/x86/pci/common.c ++++ b/arch/x86/pci/common.c +@@ -673,28 +673,22 @@ int pcibios_add_device(struct pci_dev *dev) + return 0; + } + +-int pcibios_alloc_irq(struct pci_dev *dev) ++int pcibios_enable_device(struct pci_dev *dev, int mask) + { +- /* +- * If the PCI device was already claimed by core code and has +- * MSI enabled, probing of the pcibios IRQ will overwrite +- * dev->irq. So bail out if MSI is already enabled. +- */ +- if (pci_dev_msi_enabled(dev)) +- return -EBUSY; ++ int err; + +- return pcibios_enable_irq(dev); +-} ++ if ((err = pci_enable_resources(dev, mask)) < 0) ++ return err; + +-void pcibios_free_irq(struct pci_dev *dev) +-{ +- if (pcibios_disable_irq) +- pcibios_disable_irq(dev); ++ if (!pci_dev_msi_enabled(dev)) ++ return pcibios_enable_irq(dev); ++ return 0; + } + +-int pcibios_enable_device(struct pci_dev *dev, int mask) ++void pcibios_disable_device (struct pci_dev *dev) + { +- return pci_enable_resources(dev, mask); ++ if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) ++ pcibios_disable_irq(dev); + } + + int pci_ext_cfg_avail(void) +diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c +index e585655..0ae7e9f 100644 +--- a/arch/x86/pci/fixup.c ++++ b/arch/x86/pci/fixup.c +@@ -540,3 +540,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev) + } + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone); ++ ++static void pci_bdwep_bar(struct pci_dev *dev) ++{ ++ dev->non_compliant_bars = 1; ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar); ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar); +diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c +index 0d24e7c..8b93e63 100644 +--- a/arch/x86/pci/intel_mid_pci.c ++++ b/arch/x86/pci/intel_mid_pci.c +@@ -215,7 +215,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) + int polarity; + int ret; + +- if (pci_has_managed_irq(dev)) ++ if (dev->irq_managed && dev->irq > 0) + return 0; + + switch (intel_mid_identify_cpu()) { +@@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) + + static void intel_mid_pci_irq_disable(struct pci_dev *dev) + { +- if (pci_has_managed_irq(dev)) { ++ if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed && ++ dev->irq > 0) { + mp_unmap_irq(dev->irq); + dev->irq_managed = 0; +- /* +- * Don't reset dev->irq here, otherwise +- * intel_mid_pci_irq_enable() will fail on next call. +- */ + } + } + +diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c +index 32e7034..9bd1154 100644 +--- a/arch/x86/pci/irq.c ++++ b/arch/x86/pci/irq.c +@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev) + struct pci_dev *temp_dev; + int irq; + +- if (pci_has_managed_irq(dev)) ++ if (dev->irq_managed && dev->irq > 0) + return 0; + + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, +@@ -1230,7 +1230,8 @@ static int pirq_enable_irq(struct pci_dev *dev) + } + dev = temp_dev; + if (irq >= 0) { +- pci_set_managed_irq(dev, irq); ++ dev->irq_managed = 1; ++ dev->irq = irq; + dev_info(&dev->dev, "PCI->APIC IRQ transform: " + "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); + return 0; +@@ -1256,10 +1257,24 @@ static int pirq_enable_irq(struct pci_dev *dev) + return 0; + } + ++bool mp_should_keep_irq(struct device *dev) ++{ ++ if (dev->power.is_prepared) ++ return true; ++#ifdef CONFIG_PM ++ if (dev->power.runtime_status == RPM_SUSPENDING) ++ return true; ++#endif ++ ++ return false; ++} ++ + static void pirq_disable_irq(struct pci_dev *dev) + { +- if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) { ++ if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && ++ dev->irq_managed && dev->irq) { + mp_unmap_irq(dev->irq); +- pci_reset_managed_irq(dev); ++ dev->irq = 0; ++ dev->irq_managed = 0; + } + } +diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c +index ff31ab4..c6d6efe 100644 +--- a/arch/x86/pci/xen.c ++++ b/arch/x86/pci/xen.c +@@ -488,8 +488,11 @@ int __init pci_xen_initial_domain(void) + #endif + __acpi_register_gsi = acpi_register_gsi_xen; + __acpi_unregister_gsi = NULL; +- /* Pre-allocate legacy irqs */ +- for (irq = 0; irq < nr_legacy_irqs(); irq++) { ++ /* ++ * Pre-allocate the legacy IRQs. Use NR_LEGACY_IRQS here ++ * because we don't have a PIC and thus nr_legacy_irqs() is zero. ++ */ ++ for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { + int trigger, polarity; + + if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index b7de78b..beab8c7 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -961,7 +961,7 @@ static void xen_load_sp0(struct tss_struct *tss, + tss->x86_tss.sp0 = thread->sp0; + } + +-static void xen_set_iopl_mask(unsigned mask) ++void xen_set_iopl_mask(unsigned mask) + { + struct physdev_set_iopl set_iopl; + +diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c +index 7ab2951..e345891 100644 +--- a/arch/x86/xen/setup.c ++++ b/arch/x86/xen/setup.c +@@ -393,6 +393,9 @@ static unsigned long __init xen_set_identity_and_remap_chunk( + unsigned long i = 0; + unsigned long n = end_pfn - start_pfn; + ++ if (remap_pfn == 0) ++ remap_pfn = nr_pages; ++ + while (i < n) { + unsigned long cur_pfn = start_pfn + i; + unsigned long left = n - i; +@@ -438,17 +441,29 @@ static unsigned long __init xen_set_identity_and_remap_chunk( + return remap_pfn; + } + +-static void __init xen_set_identity_and_remap(unsigned long nr_pages) ++static unsigned long __init xen_count_remap_pages( ++ unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, ++ unsigned long remap_pages) ++{ ++ if (start_pfn >= nr_pages) ++ return remap_pages; ++ ++ return remap_pages + min(end_pfn, nr_pages) - start_pfn; ++} ++ ++static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, ++ unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn, ++ unsigned long nr_pages, unsigned long last_val)) + { + phys_addr_t start = 0; +- unsigned long last_pfn = nr_pages; ++ unsigned long ret_val = 0; + const struct e820entry *entry = xen_e820_map; + int i; + + /* + * Combine non-RAM regions and gaps until a RAM region (or the +- * end of the map) is reached, then set the 1:1 map and +- * remap the memory in those non-RAM regions. ++ * end of the map) is reached, then call the provided function ++ * to perform its duty on the non-RAM region. + * + * The combined non-RAM regions are rounded to a whole number + * of pages so any partial pages are accessible via the 1:1 +@@ -466,14 +481,13 @@ static void __init xen_set_identity_and_remap(unsigned long nr_pages) + end_pfn = PFN_UP(entry->addr); + + if (start_pfn < end_pfn) +- last_pfn = xen_set_identity_and_remap_chunk( +- start_pfn, end_pfn, nr_pages, +- last_pfn); ++ ret_val = func(start_pfn, end_pfn, nr_pages, ++ ret_val); + start = end; + } + } + +- pr_info("Released %ld page(s)\n", xen_released_pages); ++ return ret_val; + } + + /* +@@ -596,35 +610,6 @@ static void __init xen_ignore_unusable(void) + } + } + +-static unsigned long __init xen_count_remap_pages(unsigned long max_pfn) +-{ +- unsigned long extra = 0; +- unsigned long start_pfn, end_pfn; +- const struct e820entry *entry = xen_e820_map; +- int i; +- +- end_pfn = 0; +- for (i = 0; i < xen_e820_map_entries; i++, entry++) { +- start_pfn = PFN_DOWN(entry->addr); +- /* Adjacent regions on non-page boundaries handling! */ +- end_pfn = min(end_pfn, start_pfn); +- +- if (start_pfn >= max_pfn) +- return extra + max_pfn - end_pfn; +- +- /* Add any holes in map to result. */ +- extra += start_pfn - end_pfn; +- +- end_pfn = PFN_UP(entry->addr + entry->size); +- end_pfn = min(end_pfn, max_pfn); +- +- if (entry->type != E820_RAM) +- extra += end_pfn - start_pfn; +- } +- +- return extra; +-} +- + bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) + { + struct e820entry *entry; +@@ -804,7 +789,7 @@ char * __init xen_memory_setup(void) + max_pages = xen_get_max_pages(); + + /* How many extra pages do we need due to remapping? */ +- max_pages += xen_count_remap_pages(max_pfn); ++ max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages); + + if (max_pages > max_pfn) + extra_pages += max_pages - max_pfn; +@@ -922,7 +907,9 @@ char * __init xen_memory_setup(void) + * Set identity map on non-RAM pages and prepare remapping the + * underlying RAM. + */ +- xen_set_identity_and_remap(max_pfn); ++ xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk); ++ ++ pr_info("Released %ld page(s)\n", xen_released_pages); + + return "Xen"; + } +diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S +index 9ed5564..05e1df9 100644 +--- a/arch/xtensa/kernel/head.S ++++ b/arch/xtensa/kernel/head.S +@@ -128,7 +128,7 @@ ENTRY(_startup) + wsr a0, icountlevel + + .set _index, 0 +- .rept XCHAL_NUM_DBREAK - 1 ++ .rept XCHAL_NUM_DBREAK + wsr a0, SREG_DBREAKC + _index + .set _index, _index + 1 + .endr +diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c +index d75aa14..1a804a2 100644 +--- a/arch/xtensa/mm/cache.c ++++ b/arch/xtensa/mm/cache.c +@@ -97,11 +97,11 @@ void clear_user_highpage(struct page *page, unsigned long vaddr) + unsigned long paddr; + void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr); + +- pagefault_disable(); ++ preempt_disable(); + kmap_invalidate_coherent(page, vaddr); + set_bit(PG_arch_1, &page->flags); + clear_page_alias(kvaddr, paddr); +- pagefault_enable(); ++ preempt_enable(); + } + + void copy_user_highpage(struct page *dst, struct page *src, +@@ -113,11 +113,11 @@ void copy_user_highpage(struct page *dst, struct page *src, + void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr, + &src_paddr); + +- pagefault_disable(); ++ preempt_disable(); + kmap_invalidate_coherent(dst, vaddr); + set_bit(PG_arch_1, &dst->flags); + copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr); +- pagefault_enable(); ++ preempt_enable(); + } + + #endif /* DCACHE_WAY_SIZE > PAGE_SIZE */ +diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c +index 70cb408..92d785f 100644 +--- a/arch/xtensa/platforms/iss/console.c ++++ b/arch/xtensa/platforms/iss/console.c +@@ -100,21 +100,23 @@ static void rs_poll(unsigned long priv) + { + struct tty_port *port = (struct tty_port *)priv; + int i = 0; ++ int rd = 1; + unsigned char c; + + spin_lock(&timer_lock); + + while (simc_poll(0)) { +- simc_read(0, &c, 1); ++ rd = simc_read(0, &c, 1); ++ if (rd <= 0) ++ break; + tty_insert_flip_char(port, c, TTY_NORMAL); + i++; + } + + if (i) + tty_flip_buffer_push(port); +- +- +- mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); ++ if (rd) ++ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); + spin_unlock(&timer_lock); + } + +diff --git a/block/blk-core.c b/block/blk-core.c +index 4c8cefd..842cfe4 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -680,7 +680,7 @@ static void blk_queue_usage_counter_release(struct percpu_ref *ref) + struct request_queue *q = + container_of(ref, struct request_queue, q_usage_counter); + +- swait_wake_all(&q->mq_freeze_wq); ++ swake_up_all(&q->mq_freeze_wq); + } + + struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) +@@ -742,7 +742,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) + q->bypass_depth = 1; + __set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags); + +- init_swait_head(&q->mq_freeze_wq); ++ init_swait_queue_head(&q->mq_freeze_wq); + + /* + * Init percpu_ref in atomic mode so that it's faster to shutdown. +@@ -2192,7 +2192,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) + if (q->mq_ops) { + if (blk_queue_io_stat(q)) + blk_account_io_start(rq, true); +- blk_mq_insert_request(rq, false, true, true); ++ blk_mq_insert_request(rq, false, true, false); + return 0; + } + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 3c70813..7cdf19e 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -130,7 +130,7 @@ void blk_mq_unfreeze_queue(struct request_queue *q) + WARN_ON_ONCE(freeze_depth < 0); + if (!freeze_depth) { + percpu_ref_reinit(&q->q_usage_counter); +- swait_wake_all(&q->mq_freeze_wq); ++ swake_up_all(&q->mq_freeze_wq); + } + } + EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); +@@ -149,7 +149,7 @@ void blk_mq_wake_waiters(struct request_queue *q) + * dying, we need to ensure that processes currently waiting on + * the queue are notified as well. + */ +- swait_wake_all(&q->mq_freeze_wq); ++ swake_up_all(&q->mq_freeze_wq); + } + + bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx) +diff --git a/block/partition-generic.c b/block/partition-generic.c +index 746935a..a241e39 100644 +--- a/block/partition-generic.c ++++ b/block/partition-generic.c +@@ -349,15 +349,20 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, + goto out_del; + } + ++ err = hd_ref_init(p); ++ if (err) { ++ if (flags & ADDPART_FLAG_WHOLEDISK) ++ goto out_remove_file; ++ goto out_del; ++ } ++ + /* everything is up and running, commence */ + rcu_assign_pointer(ptbl->part[partno], p); + + /* suppress uevent if the disk suppresses it */ + if (!dev_get_uevent_suppress(ddev)) + kobject_uevent(&pdev->kobj, KOBJ_ADD); +- +- if (!hd_ref_init(p)) +- return p; ++ return p; + + out_free_info: + free_part_info(p); +@@ -366,6 +371,8 @@ out_free_stats: + out_free: + kfree(p); + return ERR_PTR(err); ++out_remove_file: ++ device_remove_file(pdev, &dev_attr_whole_disk); + out_del: + kobject_put(p->holder_dir); + device_del(pdev); +diff --git a/crypto/ahash.c b/crypto/ahash.c +index d19b523..dac1c24 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -69,8 +69,9 @@ static int hash_walk_new_entry(struct crypto_hash_walk *walk) + struct scatterlist *sg; + + sg = walk->sg; +- walk->pg = sg_page(sg); + walk->offset = sg->offset; ++ walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT); ++ walk->offset = offset_in_page(walk->offset); + walk->entrylen = sg->length; + + if (walk->entrylen > walk->total) +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 4870f28..05bfe56 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -14,6 +14,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select MPILIB + select PUBLIC_KEY_ALGO_RSA + select CRYPTO_HASH_INFO ++ select CRYPTO_AKCIPHER + help + This option provides support for asymmetric public key type handling. + If signature generation and/or verification are to be used, +diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c +index 90d6d47..ecdb5a2 100644 +--- a/crypto/asymmetric_keys/pkcs7_trust.c ++++ b/crypto/asymmetric_keys/pkcs7_trust.c +@@ -178,6 +178,8 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, + int cached_ret = -ENOKEY; + int ret; + ++ *_trusted = false; ++ + for (p = pkcs7->certs; p; p = p->next) + p->seen = false; + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 021d39c..13c4e5a 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -494,7 +494,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, + unsigned char tag, + const unsigned char *value, size_t vlen) + { +- static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30, ++ static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 }; + const unsigned char *p = value; + unsigned year, mon, day, hour, min, sec, mon_len; +@@ -540,9 +540,9 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, + if (year % 4 == 0) { + mon_len = 29; + if (year % 100 == 0) { +- year /= 100; +- if (year % 4 != 0) +- mon_len = 28; ++ mon_len = 28; ++ if (year % 400 == 0) ++ mon_len = 29; + } + } + } +diff --git a/crypto/keywrap.c b/crypto/keywrap.c +index b1d106c..72014f9 100644 +--- a/crypto/keywrap.c ++++ b/crypto/keywrap.c +@@ -212,7 +212,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, + SEMIBSIZE)) + ret = -EBADMSG; + +- memzero_explicit(&block, sizeof(struct crypto_kw_block)); ++ memzero_explicit(block, sizeof(struct crypto_kw_block)); + + return ret; + } +@@ -297,7 +297,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, + /* establish the IV for the caller to pick up */ + memcpy(desc->info, block->A, SEMIBSIZE); + +- memzero_explicit(&block, sizeof(struct crypto_kw_block)); ++ memzero_explicit(block, sizeof(struct crypto_kw_block)); + + return 0; + } +diff --git a/crypto/testmgr.c b/crypto/testmgr.c +index ae8c57f..d494431 100644 +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -1849,6 +1849,7 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, + static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) + { ++ char *xbuf[XBUFSIZE]; + struct akcipher_request *req; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; +@@ -1857,9 +1858,12 @@ static int do_test_rsa(struct crypto_akcipher *tfm, + int err = -ENOMEM; + struct scatterlist src, dst, src_tab[2]; + ++ if (testmgr_alloc_buf(xbuf)) ++ return err; ++ + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) +- return err; ++ goto free_xbuf; + + init_completion(&result.completion); + +@@ -1877,9 +1881,14 @@ static int do_test_rsa(struct crypto_akcipher *tfm, + if (!outbuf_enc) + goto free_req; + ++ if (WARN_ON(vecs->m_size > PAGE_SIZE)) ++ goto free_all; ++ ++ memcpy(xbuf[0], vecs->m, vecs->m_size); ++ + sg_init_table(src_tab, 2); +- sg_set_buf(&src_tab[0], vecs->m, 8); +- sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8); ++ sg_set_buf(&src_tab[0], xbuf[0], 8); ++ sg_set_buf(&src_tab[1], xbuf[0] + 8, vecs->m_size - 8); + sg_init_one(&dst, outbuf_enc, out_len_max); + akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size, + out_len_max); +@@ -1898,7 +1907,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm, + goto free_all; + } + /* verify that encrypted message is equal to expected */ +- if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) { ++ if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) { + pr_err("alg: rsa: encrypt test failed. Invalid output\n"); + err = -EINVAL; + goto free_all; +@@ -1913,7 +1922,13 @@ static int do_test_rsa(struct crypto_akcipher *tfm, + err = -ENOMEM; + goto free_all; + } +- sg_init_one(&src, vecs->c, vecs->c_size); ++ ++ if (WARN_ON(vecs->c_size > PAGE_SIZE)) ++ goto free_all; ++ ++ memcpy(xbuf[0], vecs->c, vecs->c_size); ++ ++ sg_init_one(&src, xbuf[0], vecs->c_size); + sg_init_one(&dst, outbuf_dec, out_len_max); + init_completion(&result.completion); + akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max); +@@ -1940,6 +1955,8 @@ free_all: + kfree(outbuf_enc); + free_req: + akcipher_request_free(req); ++free_xbuf: ++ testmgr_free_buf(xbuf); + return err; + } + +diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c +index 6979186..9f77943 100644 +--- a/drivers/acpi/acpi_processor.c ++++ b/drivers/acpi/acpi_processor.c +@@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device) + } + #endif /* CONFIG_ACPI_HOTPLUG_CPU */ + ++#ifdef CONFIG_X86 ++static bool acpi_hwp_native_thermal_lvt_set; ++static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, ++ u32 lvl, ++ void *context, ++ void **rv) ++{ ++ u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; ++ u32 capbuf[2]; ++ struct acpi_osc_context osc_context = { ++ .uuid_str = sb_uuid_str, ++ .rev = 1, ++ .cap.length = 8, ++ .cap.pointer = capbuf, ++ }; ++ ++ if (acpi_hwp_native_thermal_lvt_set) ++ return AE_CTRL_TERMINATE; ++ ++ capbuf[0] = 0x0000; ++ capbuf[1] = 0x1000; /* set bit 12 */ ++ ++ if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { ++ if (osc_context.ret.pointer && osc_context.ret.length > 1) { ++ u32 *capbuf_ret = osc_context.ret.pointer; ++ ++ if (capbuf_ret[1] & 0x1000) { ++ acpi_handle_info(handle, ++ "_OSC native thermal LVT Acked\n"); ++ acpi_hwp_native_thermal_lvt_set = true; ++ } ++ } ++ kfree(osc_context.ret.pointer); ++ } ++ ++ return AE_OK; ++} ++ ++void __init acpi_early_processor_osc(void) ++{ ++ if (boot_cpu_has(X86_FEATURE_HWP)) { ++ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ++ ACPI_UINT32_MAX, ++ acpi_hwp_native_thermal_lvt_osc, ++ NULL, NULL, NULL); ++ acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, ++ acpi_hwp_native_thermal_lvt_osc, ++ NULL, NULL); ++ } ++} ++#endif ++ + /* + * The following ACPI IDs are known to be suitable for representing as + * processor devices. +diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c +index bc32f31..28c50c6 100644 +--- a/drivers/acpi/acpica/dsmethod.c ++++ b/drivers/acpi/acpica/dsmethod.c +@@ -417,6 +417,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, + obj_desc->method.mutex->mutex. + original_sync_level = + obj_desc->method.mutex->mutex.sync_level; ++ ++ obj_desc->method.mutex->mutex.thread_id = ++ acpi_os_get_thread_id(); + } + } + +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index a212cef..ca4f284 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -1004,6 +1004,9 @@ static int __init acpi_bus_init(void) + goto error1; + } + ++ /* Set capability bits for _OSC under processor scope */ ++ acpi_early_processor_osc(); ++ + /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION +diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h +index 11d87bf..0f3f41c 100644 +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -130,6 +130,12 @@ void acpi_early_processor_set_pdc(void); + static inline void acpi_early_processor_set_pdc(void) {} + #endif + ++#ifdef CONFIG_X86 ++void acpi_early_processor_osc(void); ++#else ++static inline void acpi_early_processor_osc(void) {} ++#endif ++ + /* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index 32d684a..a000ecb 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -135,7 +135,7 @@ static struct osi_linux { + unsigned int enable:1; + unsigned int dmi:1; + unsigned int cmdline:1; +- unsigned int default_disabling:1; ++ u8 default_disabling; + } osi_linux = {0, 0, 0, 0}; + + static u32 acpi_osi_handler(acpi_string interface, u32 supported) +@@ -1444,10 +1444,13 @@ void __init acpi_osi_setup(char *str) + if (*str == '!') { + str++; + if (*str == '\0') { +- osi_linux.default_disabling = 1; ++ /* Do not override acpi_osi=!* */ ++ if (!osi_linux.default_disabling) ++ osi_linux.default_disabling = ++ ACPI_DISABLE_ALL_VENDOR_STRINGS; + return; + } else if (*str == '*') { +- acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS); ++ osi_linux.default_disabling = ACPI_DISABLE_ALL_STRINGS; + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + osi->enable = false; +@@ -1520,10 +1523,13 @@ static void __init acpi_osi_setup_late(void) + acpi_status status; + + if (osi_linux.default_disabling) { +- status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); ++ status = acpi_update_interfaces(osi_linux.default_disabling); + + if (ACPI_SUCCESS(status)) +- printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n"); ++ printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors%s\n", ++ osi_linux.default_disabling == ++ ACPI_DISABLE_ALL_STRINGS ? ++ " and feature groups" : ""); + } + + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { +diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c +index c933675..8a10a7a 100644 +--- a/drivers/acpi/pci_irq.c ++++ b/drivers/acpi/pci_irq.c +@@ -409,7 +409,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) + return 0; + } + +- if (pci_has_managed_irq(dev)) ++ if (dev->irq_managed && dev->irq > 0) + return 0; + + entry = acpi_pci_irq_lookup(dev, pin); +@@ -454,7 +454,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) + kfree(entry); + return rc; + } +- pci_set_managed_irq(dev, rc); ++ dev->irq = rc; ++ dev->irq_managed = 1; + + if (link) + snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); +@@ -477,9 +478,17 @@ void acpi_pci_irq_disable(struct pci_dev *dev) + u8 pin; + + pin = dev->pin; +- if (!pin || !pci_has_managed_irq(dev)) ++ if (!pin || !dev->irq_managed || dev->irq <= 0) + return; + ++ /* Keep IOAPIC pin configuration when suspending */ ++ if (dev->dev.power.is_prepared) ++ return; ++#ifdef CONFIG_PM ++ if (dev->dev.power.runtime_status == RPM_SUSPENDING) ++ return; ++#endif ++ + entry = acpi_pci_irq_lookup(dev, pin); + if (!entry) + return; +@@ -499,6 +508,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) + dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); + if (gsi >= 0) { + acpi_unregister_gsi(gsi); +- pci_reset_managed_irq(dev); ++ dev->irq_managed = 0; + } + } +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index cdc5c25..627f8fb 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -26,8 +26,20 @@ + + #ifdef CONFIG_X86 + #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) ++static inline bool acpi_iospace_resource_valid(struct resource *res) ++{ ++ /* On X86 IO space is limited to the [0 - 64K] IO port range */ ++ return res->end < 0x10003; ++} + #else + #define valid_IRQ(i) (true) ++/* ++ * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical ++ * addresses mapping IO space in CPU physical address space, IO space ++ * resources can be placed anywhere in the 64-bit physical address space. ++ */ ++static inline bool ++acpi_iospace_resource_valid(struct resource *res) { return true; } + #endif + + static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) +@@ -126,7 +138,7 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len, + if (!acpi_dev_resource_len_valid(res->start, res->end, len, true)) + res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; + +- if (res->end >= 0x10003) ++ if (!acpi_iospace_resource_valid(res)) + res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; + + if (io_decode == ACPI_DECODE_16) +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 0d94621..e3322ad 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -714,6 +714,7 @@ static int acpi_hibernation_enter(void) + + static void acpi_hibernation_leave(void) + { ++ pm_set_resume_via_firmware(); + /* + * If ACPI is not enabled by the BIOS and the boot kernel, we need to + * enable it here. +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 04975b8..639adb1 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -51,6 +51,9 @@ static int ahci_probe(struct platform_device *pdev) + if (rc) + return rc; + ++ of_property_read_u32(dev->of_node, ++ "ports-implemented", &hpriv->force_port_map); ++ + if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) + hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; + +diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c +index e2c6d9e..e916bff 100644 +--- a/drivers/ata/ahci_xgene.c ++++ b/drivers/ata/ahci_xgene.c +@@ -739,9 +739,9 @@ static int xgene_ahci_probe(struct platform_device *pdev) + dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n", + __func__); + version = XGENE_AHCI_V1; +- } +- if (info->valid & ACPI_VALID_CID) ++ } else if (info->valid & ACPI_VALID_CID) { + version = XGENE_AHCI_V2; ++ } + } + } + #endif +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 998c6a8..9628fa1 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -467,6 +467,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) + dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", + port_map, hpriv->force_port_map); + port_map = hpriv->force_port_map; ++ hpriv->saved_port_map = port_map; + } + + if (hpriv->mask_port_map) { +diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c +index 65f50ec..a48824d 100644 +--- a/drivers/base/power/domain.c ++++ b/drivers/base/power/domain.c +@@ -1381,7 +1381,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, + + mutex_lock(&genpd->lock); + +- if (!list_empty(&subdomain->slave_links) || subdomain->device_count) { ++ if (!list_empty(&subdomain->master_links) || subdomain->device_count) { + pr_warn("%s: unable to remove subdomain %s\n", genpd->name, + subdomain->name); + ret = -EBUSY; +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index 1710c26..ae60e63 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -1262,14 +1262,15 @@ int dpm_suspend_late(pm_message_t state) + error = device_suspend_late(dev); + + mutex_lock(&dpm_list_mtx); ++ if (!list_empty(&dev->power.entry)) ++ list_move(&dev->power.entry, &dpm_late_early_list); ++ + if (error) { + pm_dev_err(dev, state, " late", error); + dpm_save_failed_dev(dev_name(dev)); + put_device(dev); + break; + } +- if (!list_empty(&dev->power.entry)) +- list_move(&dev->power.entry, &dpm_late_early_list); + put_device(dev); + + if (async_error) +diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c +index b8e76f7..f858090 100644 +--- a/drivers/base/power/opp/core.c ++++ b/drivers/base/power/opp/core.c +@@ -809,8 +809,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev) + } + + opp->u_volt = microvolt[0]; +- opp->u_volt_min = microvolt[1]; +- opp->u_volt_max = microvolt[2]; ++ ++ if (count == 1) { ++ opp->u_volt_min = opp->u_volt; ++ opp->u_volt_max = opp->u_volt; ++ } else { ++ opp->u_volt_min = microvolt[1]; ++ opp->u_volt_max = microvolt[2]; ++ } + + if (!of_property_read_u32(opp->np, "opp-microamp", &val)) + opp->u_amp = val; +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index e1a10a0..9796a1a 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -1468,11 +1468,16 @@ int pm_runtime_force_resume(struct device *dev) + goto out; + } + +- ret = callback(dev); ++ ret = pm_runtime_set_active(dev); + if (ret) + goto out; + +- pm_runtime_set_active(dev); ++ ret = callback(dev); ++ if (ret) { ++ pm_runtime_set_suspended(dev); ++ goto out; ++ } ++ + pm_runtime_mark_last_busy(dev); + out: + pm_runtime_enable(dev); +diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c +index 7e58f65..4a36e41 100644 +--- a/drivers/base/regmap/regmap-spmi.c ++++ b/drivers/base/regmap/regmap-spmi.c +@@ -142,7 +142,7 @@ static int regmap_spmi_ext_read(void *context, + while (val_size) { + len = min_t(size_t, val_size, 8); + +- err = spmi_ext_register_readl(context, addr, val, val_size); ++ err = spmi_ext_register_readl(context, addr, val, len); + if (err) + goto err_out; + +diff --git a/drivers/block/brd.c b/drivers/block/brd.c +index a5880f4..1914c63 100644 +--- a/drivers/block/brd.c ++++ b/drivers/block/brd.c +@@ -338,7 +338,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) + + if (unlikely(bio->bi_rw & REQ_DISCARD)) { + if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) || +- bio->bi_iter.bi_size & PAGE_MASK) ++ bio->bi_iter.bi_size & ~PAGE_MASK) + goto io_error; + discard_from_brd(brd, sector, bio->bi_iter.bi_size); + goto out; +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 423f4ca..80cf8ad 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -488,6 +488,12 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, + bvec = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); + iov_iter_bvec(&iter, ITER_BVEC | rw, bvec, + bio_segments(bio), blk_rq_bytes(cmd->rq)); ++ /* ++ * This bio may be started from the middle of the 'bvec' ++ * because of bio splitting, so offset from the bvec must ++ * be passed to iov iterator ++ */ ++ iter.iov_offset = bio->bi_iter.bi_bvec_done; + + cmd->iocb.ki_pos = pos; + cmd->iocb.ki_filp = file; +diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c +index 3457ac8..55d3d1d 100644 +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd) + { + struct request *rq; + ++ if (mtip_check_surprise_removal(dd->pdev)) ++ return NULL; ++ + rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true); ++ if (IS_ERR(rq)) ++ return NULL; ++ + return blk_mq_rq_to_pdu(rq); + } + +@@ -233,15 +239,9 @@ static void mtip_async_complete(struct mtip_port *port, + "Command tag %d failed due to TFE\n", tag); + } + +- /* Unmap the DMA scatter list entries */ +- dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction); +- + rq = mtip_rq_from_tag(dd, tag); + +- if (unlikely(cmd->unaligned)) +- up(&port->cmd_slot_unal); +- +- blk_mq_end_request(rq, status ? -EIO : 0); ++ blk_mq_complete_request(rq, status); + } + + /* +@@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_port *port, + dev_warn(&port->dd->pdev->dev, + "Internal command %d completed with TFE\n", tag); + ++ command->comp_func = NULL; ++ command->comp_data = NULL; + complete(waiting); + } + +@@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd) + + port = dd->port; + +- set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); +- + if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { + cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); + dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n"); +@@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct driver_data *dd) + cmd->comp_func(port, MTIP_TAG_INTERNAL, + cmd, PORT_IRQ_TF_ERR); + } +- goto handle_tfe_exit; ++ return; + } + + /* clear the tag accumulator */ +@@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct driver_data *dd) + fail_reason = "thermal shutdown"; + } + if (buf[288] == 0xBF) { +- set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag); ++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed. Secure erase required.\n"); + fail_all_ncq_cmds = 1; +@@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct driver_data *dd) + } + } + print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); +- +-handle_tfe_exit: +- /* clear eh_active */ +- clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); +- wake_up_interruptible(&port->svc_wait); + } + + /* +@@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_port *port, + (fis->features == 0x27 || fis->features == 0x72 || + fis->features == 0x62 || fis->features == 0x26))) { + clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); ++ clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag); + /* Com reset after secure erase or lowlevel format */ + mtip_restart_port(port); + clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); +@@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_port *port, + * + * @port Pointer to port data structure + * @timeout Max duration to wait (ms) ++ * @atomic gfp_t flag to indicate blockable context or not + * + * return value + * 0 Success + * -EBUSY Commands still active + */ +-static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) ++static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout, ++ gfp_t atomic) + { + unsigned long to; + unsigned int n; +@@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) + to = jiffies + msecs_to_jiffies(timeout); + do { + if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) && +- test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { ++ test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) && ++ atomic == GFP_KERNEL) { + msleep(20); + continue; /* svc thd is actively issuing commands */ + } + +- msleep(100); ++ if (atomic == GFP_KERNEL) ++ msleep(100); ++ else { ++ cpu_relax(); ++ udelay(100); ++ } ++ + if (mtip_check_surprise_removal(port->dd->pdev)) + goto err_fault; +- if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) +- goto err_fault; + + /* + * Ignore s_active bit 0 of array element 0. +@@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, + struct mtip_cmd *int_cmd; + struct driver_data *dd = port->dd; + int rv = 0; ++ unsigned long start; + + /* Make sure the buffer is 8 byte aligned. This is asic specific. */ + if (buffer & 0x00000007) { +@@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(struct mtip_port *port, + } + + int_cmd = mtip_get_int_command(dd); ++ if (!int_cmd) { ++ dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n"); ++ return -EFAULT; ++ } + + set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); + +@@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, + if (fis->command != ATA_CMD_STANDBYNOW1) { + /* wait for io to complete if non atomic */ + if (mtip_quiesce_io(port, +- MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) { ++ MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) { + dev_warn(&dd->pdev->dev, + "Failed to quiesce IO\n"); + mtip_put_int_command(dd, int_cmd); +@@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(struct mtip_port *port, + /* Populate the command header */ + int_cmd->command_header->byte_count = 0; + ++ start = jiffies; ++ + /* Issue the command to the hardware */ + mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); + +@@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(struct mtip_port *port, + if ((rv = wait_for_completion_interruptible_timeout( + &wait, + msecs_to_jiffies(timeout))) <= 0) { ++ + if (rv == -ERESTARTSYS) { /* interrupted */ + dev_err(&dd->pdev->dev, +- "Internal command [%02X] was interrupted after %lu ms\n", +- fis->command, timeout); ++ "Internal command [%02X] was interrupted after %u ms\n", ++ fis->command, ++ jiffies_to_msecs(jiffies - start)); + rv = -EINTR; + goto exec_ic_exit; + } else if (rv == 0) /* timeout */ +@@ -2897,6 +2909,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) + return -EFAULT; + } + ++static void mtip_softirq_done_fn(struct request *rq) ++{ ++ struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq); ++ struct driver_data *dd = rq->q->queuedata; ++ ++ /* Unmap the DMA scatter list entries */ ++ dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, ++ cmd->direction); ++ ++ if (unlikely(cmd->unaligned)) ++ up(&dd->port->cmd_slot_unal); ++ ++ blk_mq_end_request(rq, rq->errors); ++} ++ ++static void mtip_abort_cmd(struct request *req, void *data, ++ bool reserved) ++{ ++ struct driver_data *dd = data; ++ ++ dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag); ++ ++ clear_bit(req->tag, dd->port->cmds_to_issue); ++ req->errors = -EIO; ++ mtip_softirq_done_fn(req); ++} ++ ++static void mtip_queue_cmd(struct request *req, void *data, ++ bool reserved) ++{ ++ struct driver_data *dd = data; ++ ++ set_bit(req->tag, dd->port->cmds_to_issue); ++ blk_abort_request(req); ++} ++ + /* + * service thread to issue queued commands + * +@@ -2909,7 +2957,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) + static int mtip_service_thread(void *data) + { + struct driver_data *dd = (struct driver_data *)data; +- unsigned long slot, slot_start, slot_wrap; ++ unsigned long slot, slot_start, slot_wrap, to; + unsigned int num_cmd_slots = dd->slot_groups * 32; + struct mtip_port *port = dd->port; + +@@ -2924,9 +2972,7 @@ static int mtip_service_thread(void *data) + * is in progress nor error handling is active + */ + wait_event_interruptible(port->svc_wait, (port->flags) && +- !(port->flags & MTIP_PF_PAUSE_IO)); +- +- set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); ++ (port->flags & MTIP_PF_SVC_THD_WORK)); + + if (kthread_should_stop() || + test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) +@@ -2936,6 +2982,8 @@ static int mtip_service_thread(void *data) + &dd->dd_flag))) + goto st_out; + ++ set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); ++ + restart_eh: + /* Demux bits: start with error handling */ + if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) { +@@ -2946,6 +2994,32 @@ restart_eh: + if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) + goto restart_eh; + ++ if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) { ++ to = jiffies + msecs_to_jiffies(5000); ++ ++ do { ++ mdelay(100); ++ } while (atomic_read(&dd->irq_workers_active) != 0 && ++ time_before(jiffies, to)); ++ ++ if (atomic_read(&dd->irq_workers_active) != 0) ++ dev_warn(&dd->pdev->dev, ++ "Completion workers still active!"); ++ ++ spin_lock(dd->queue->queue_lock); ++ blk_mq_all_tag_busy_iter(*dd->tags.tags, ++ mtip_queue_cmd, dd); ++ spin_unlock(dd->queue->queue_lock); ++ ++ set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags); ++ ++ if (mtip_device_reset(dd)) ++ blk_mq_all_tag_busy_iter(*dd->tags.tags, ++ mtip_abort_cmd, dd); ++ ++ clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags); ++ } ++ + if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { + slot = 1; + /* used to restrict the loop to one iteration */ +@@ -2978,10 +3052,8 @@ restart_eh: + } + + if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { +- if (mtip_ftl_rebuild_poll(dd) < 0) +- set_bit(MTIP_DDF_REBUILD_FAILED_BIT, +- &dd->dd_flag); +- clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); ++ if (mtip_ftl_rebuild_poll(dd) == 0) ++ clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); + } + } + +@@ -3096,7 +3168,7 @@ static int mtip_hw_get_identify(struct driver_data *dd) + if (buf[288] == 0xBF) { + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed.\n"); +- /* TODO */ ++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); + } + } + +@@ -3270,20 +3342,25 @@ out1: + return rv; + } + +-static void mtip_standby_drive(struct driver_data *dd) ++static int mtip_standby_drive(struct driver_data *dd) + { +- if (dd->sr) +- return; ++ int rv = 0; + ++ if (dd->sr || !dd->port) ++ return -ENODEV; + /* + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ + if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) && +- !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) +- if (mtip_standby_immediate(dd->port)) ++ !test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) && ++ !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) { ++ rv = mtip_standby_immediate(dd->port); ++ if (rv) + dev_warn(&dd->pdev->dev, + "STANDBY IMMEDIATE failed\n"); ++ } ++ return rv; + } + + /* +@@ -3296,10 +3373,6 @@ static void mtip_standby_drive(struct driver_data *dd) + */ + static int mtip_hw_exit(struct driver_data *dd) + { +- /* +- * Send standby immediate (E0h) to the drive so that it +- * saves its state. +- */ + if (!dd->sr) { + /* de-initialize the port. */ + mtip_deinit_port(dd->port); +@@ -3341,8 +3414,7 @@ static int mtip_hw_shutdown(struct driver_data *dd) + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ +- if (!dd->sr && dd->port) +- mtip_standby_immediate(dd->port); ++ mtip_standby_drive(dd); + + return 0; + } +@@ -3365,7 +3437,7 @@ static int mtip_hw_suspend(struct driver_data *dd) + * Send standby immediate (E0h) to the drive + * so that it saves its state. + */ +- if (mtip_standby_immediate(dd->port) != 0) { ++ if (mtip_standby_drive(dd) != 0) { + dev_err(&dd->pdev->dev, + "Failed standby-immediate command\n"); + return -EFAULT; +@@ -3603,6 +3675,28 @@ static int mtip_block_getgeo(struct block_device *dev, + return 0; + } + ++static int mtip_block_open(struct block_device *dev, fmode_t mode) ++{ ++ struct driver_data *dd; ++ ++ if (dev && dev->bd_disk) { ++ dd = (struct driver_data *) dev->bd_disk->private_data; ++ ++ if (dd) { ++ if (test_bit(MTIP_DDF_REMOVAL_BIT, ++ &dd->dd_flag)) { ++ return -ENODEV; ++ } ++ return 0; ++ } ++ } ++ return -ENODEV; ++} ++ ++void mtip_block_release(struct gendisk *disk, fmode_t mode) ++{ ++} ++ + /* + * Block device operation function. + * +@@ -3610,6 +3704,8 @@ static int mtip_block_getgeo(struct block_device *dev, + * layer. + */ + static const struct block_device_operations mtip_block_ops = { ++ .open = mtip_block_open, ++ .release = mtip_block_release, + .ioctl = mtip_block_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = mtip_block_compat_ioctl, +@@ -3671,10 +3767,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq) + rq_data_dir(rq))) { + return -ENODATA; + } +- if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) ++ if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) || ++ test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))) + return -ENODATA; +- if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) +- return -ENXIO; + } + + if (rq->cmd_flags & REQ_DISCARD) { +@@ -3786,11 +3881,33 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx, + return 0; + } + ++static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req, ++ bool reserved) ++{ ++ struct driver_data *dd = req->q->queuedata; ++ int ret = BLK_EH_RESET_TIMER; ++ ++ if (reserved) ++ goto exit_handler; ++ ++ if (test_bit(req->tag, dd->port->cmds_to_issue)) ++ goto exit_handler; ++ ++ if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags)) ++ goto exit_handler; ++ ++ wake_up_interruptible(&dd->port->svc_wait); ++exit_handler: ++ return ret; ++} ++ + static struct blk_mq_ops mtip_mq_ops = { + .queue_rq = mtip_queue_rq, + .map_queue = blk_mq_map_queue, + .init_request = mtip_init_cmd, + .exit_request = mtip_free_cmd, ++ .complete = mtip_softirq_done_fn, ++ .timeout = mtip_cmd_timeout, + }; + + /* +@@ -3857,7 +3974,6 @@ static int mtip_block_initialize(struct driver_data *dd) + + mtip_hw_debugfs_init(dd); + +-skip_create_disk: + memset(&dd->tags, 0, sizeof(dd->tags)); + dd->tags.ops = &mtip_mq_ops; + dd->tags.nr_hw_queues = 1; +@@ -3867,12 +3983,13 @@ skip_create_disk: + dd->tags.numa_node = dd->numa_node; + dd->tags.flags = BLK_MQ_F_SHOULD_MERGE; + dd->tags.driver_data = dd; ++ dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS; + + rv = blk_mq_alloc_tag_set(&dd->tags); + if (rv) { + dev_err(&dd->pdev->dev, + "Unable to allocate request queue\n"); +- goto block_queue_alloc_init_error; ++ goto block_queue_alloc_tag_error; + } + + /* Allocate the request queue. */ +@@ -3887,6 +4004,7 @@ skip_create_disk: + dd->disk->queue = dd->queue; + dd->queue->queuedata = dd; + ++skip_create_disk: + /* Initialize the protocol layer. */ + wait_for_rebuild = mtip_hw_get_identify(dd); + if (wait_for_rebuild < 0) { +@@ -3983,8 +4101,9 @@ kthread_run_error: + read_capacity_error: + init_hw_cmds_error: + blk_cleanup_queue(dd->queue); +- blk_mq_free_tag_set(&dd->tags); + block_queue_alloc_init_error: ++ blk_mq_free_tag_set(&dd->tags); ++block_queue_alloc_tag_error: + mtip_hw_debugfs_exit(dd); + disk_index_error: + spin_lock(&rssd_index_lock); +@@ -4001,6 +4120,22 @@ protocol_init_error: + return rv; + } + ++static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv) ++{ ++ struct driver_data *dd = (struct driver_data *)data; ++ struct mtip_cmd *cmd; ++ ++ if (likely(!reserv)) ++ blk_mq_complete_request(rq, -ENODEV); ++ else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) { ++ ++ cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); ++ if (cmd->comp_func) ++ cmd->comp_func(dd->port, MTIP_TAG_INTERNAL, ++ cmd, -ENODEV); ++ } ++} ++ + /* + * Block layer deinitialization function. + * +@@ -4032,12 +4167,23 @@ static int mtip_block_remove(struct driver_data *dd) + } + } + +- if (!dd->sr) +- mtip_standby_drive(dd); ++ if (!dd->sr) { ++ /* ++ * Explicitly wait here for IOs to quiesce, ++ * as mtip_standby_drive usually won't wait for IOs. ++ */ ++ if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS, ++ GFP_KERNEL)) ++ mtip_standby_drive(dd); ++ } + else + dev_info(&dd->pdev->dev, "device %s surprise removal\n", + dd->disk->disk_name); + ++ blk_mq_freeze_queue_start(dd->queue); ++ blk_mq_stop_hw_queues(dd->queue); ++ blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd); ++ + /* + * Delete our gendisk structure. This also removes the device + * from /dev +@@ -4047,7 +4193,8 @@ static int mtip_block_remove(struct driver_data *dd) + dd->bdev = NULL; + } + if (dd->disk) { +- del_gendisk(dd->disk); ++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) ++ del_gendisk(dd->disk); + if (dd->disk->queue) { + blk_cleanup_queue(dd->queue); + blk_mq_free_tag_set(&dd->tags); +@@ -4088,7 +4235,8 @@ static int mtip_block_shutdown(struct driver_data *dd) + dev_info(&dd->pdev->dev, + "Shutting down %s ...\n", dd->disk->disk_name); + +- del_gendisk(dd->disk); ++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) ++ del_gendisk(dd->disk); + if (dd->disk->queue) { + blk_cleanup_queue(dd->queue); + blk_mq_free_tag_set(&dd->tags); +@@ -4433,7 +4581,7 @@ static void mtip_pci_remove(struct pci_dev *pdev) + struct driver_data *dd = pci_get_drvdata(pdev); + unsigned long flags, to; + +- set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); ++ set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag); + + spin_lock_irqsave(&dev_lock, flags); + list_del_init(&dd->online_list); +@@ -4450,12 +4598,17 @@ static void mtip_pci_remove(struct pci_dev *pdev) + } while (atomic_read(&dd->irq_workers_active) != 0 && + time_before(jiffies, to)); + ++ if (!dd->sr) ++ fsync_bdev(dd->bdev); ++ + if (atomic_read(&dd->irq_workers_active) != 0) { + dev_warn(&dd->pdev->dev, + "Completion workers still active!\n"); + } + +- blk_mq_stop_hw_queues(dd->queue); ++ blk_set_queue_dying(dd->queue); ++ set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); ++ + /* Clean up the block layer. */ + mtip_block_remove(dd); + +diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h +index 3274784..7617888 100644 +--- a/drivers/block/mtip32xx/mtip32xx.h ++++ b/drivers/block/mtip32xx/mtip32xx.h +@@ -134,16 +134,24 @@ enum { + MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ + MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ + MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ ++ MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */ + MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | + (1 << MTIP_PF_EH_ACTIVE_BIT) | + (1 << MTIP_PF_SE_ACTIVE_BIT) | +- (1 << MTIP_PF_DM_ACTIVE_BIT)), ++ (1 << MTIP_PF_DM_ACTIVE_BIT) | ++ (1 << MTIP_PF_TO_ACTIVE_BIT)), + + MTIP_PF_SVC_THD_ACTIVE_BIT = 4, + MTIP_PF_ISSUE_CMDS_BIT = 5, + MTIP_PF_REBUILD_BIT = 6, + MTIP_PF_SVC_THD_STOP_BIT = 8, + ++ MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | ++ (1 << MTIP_PF_ISSUE_CMDS_BIT) | ++ (1 << MTIP_PF_REBUILD_BIT) | ++ (1 << MTIP_PF_SVC_THD_STOP_BIT) | ++ (1 << MTIP_PF_TO_ACTIVE_BIT)), ++ + /* below are bit numbers in 'dd_flag' defined in driver_data */ + MTIP_DDF_SEC_LOCK_BIT = 0, + MTIP_DDF_REMOVE_PENDING_BIT = 1, +@@ -153,6 +161,7 @@ enum { + MTIP_DDF_RESUME_BIT = 6, + MTIP_DDF_INIT_DONE_BIT = 7, + MTIP_DDF_REBUILD_FAILED_BIT = 8, ++ MTIP_DDF_REMOVAL_BIT = 9, + + MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | + (1 << MTIP_DDF_SEC_LOCK_BIT) | +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 93b3f99..8f1ce6d 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -618,8 +618,8 @@ static void nbd_request_handler(struct request_queue *q) + req, req->cmd_type); + + if (unlikely(!nbd->sock)) { +- dev_err(disk_to_dev(nbd->disk), +- "Attempted send on closed socket\n"); ++ dev_err_ratelimited(disk_to_dev(nbd->disk), ++ "Attempted send on closed socket\n"); + req->errors++; + nbd_end_request(nbd, req); + spin_lock_irq(q->queue_lock); +diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c +index 562b5a4..78a39f7 100644 +--- a/drivers/block/paride/pd.c ++++ b/drivers/block/paride/pd.c +@@ -126,7 +126,7 @@ + */ + #include + +-static bool verbose = 0; ++static int verbose = 0; + static int major = PD_MAJOR; + static char *name = PD_NAME; + static int cluster = 64; +@@ -161,7 +161,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; + static DEFINE_MUTEX(pd_mutex); + static DEFINE_SPINLOCK(pd_lock); + +-module_param(verbose, bool, 0); ++module_param(verbose, int, 0); + module_param(major, int, 0); + module_param(name, charp, 0); + module_param(cluster, int, 0); +diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c +index 1740d75..216a94f 100644 +--- a/drivers/block/paride/pt.c ++++ b/drivers/block/paride/pt.c +@@ -117,7 +117,7 @@ + + */ + +-static bool verbose = 0; ++static int verbose = 0; + static int major = PT_MAJOR; + static char *name = PT_NAME; + static int disable = 0; +@@ -152,7 +152,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; + + #include + +-module_param(verbose, bool, 0); ++module_param(verbose, int, 0); + module_param(major, int, 0); + module_param(name, charp, 0); + module_param_array(drive0, int, NULL, 0); +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 81ea69f..fbdddd6 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -1955,7 +1955,7 @@ static struct ceph_osd_request *rbd_osd_req_create( + + osdc = &rbd_dev->rbd_client->client->osdc; + osd_req = ceph_osdc_alloc_request(osdc, snapc, num_ops, false, +- GFP_ATOMIC); ++ GFP_NOIO); + if (!osd_req) + return NULL; /* ENOMEM */ + +@@ -2004,7 +2004,7 @@ rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request) + rbd_dev = img_request->rbd_dev; + osdc = &rbd_dev->rbd_client->client->osdc; + osd_req = ceph_osdc_alloc_request(osdc, snapc, num_osd_ops, +- false, GFP_ATOMIC); ++ false, GFP_NOIO); + if (!osd_req) + return NULL; /* ENOMEM */ + +@@ -2506,7 +2506,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, + bio_chain_clone_range(&bio_list, + &bio_offset, + clone_size, +- GFP_ATOMIC); ++ GFP_NOIO); + if (!obj_request->bio_list) + goto out_unwind; + } else if (type == OBJ_REQUEST_PAGES) { +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index 370c2f7..65e0b37 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -520,6 +520,8 @@ static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) + goto out_error; + } + ++ zram_meta_init_table_locks(meta, disksize); ++ + return meta; + + out_error: +@@ -568,12 +570,12 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) + unsigned long handle; + size_t size; + +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + handle = meta->table[index].handle; + size = zram_get_obj_size(meta, index); + + if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + clear_page(mem); + return 0; + } +@@ -584,7 +586,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) + else + ret = zcomp_decompress(zram->comp, cmem, size, mem); + zs_unmap_object(meta->mem_pool, handle); +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret)) { +@@ -604,14 +606,14 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, + struct zram_meta *meta = zram->meta; + page = bvec->bv_page; + +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + if (unlikely(!meta->table[index].handle) || + zram_test_flag(meta, index, ZRAM_ZERO)) { +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + handle_zero_page(bvec); + return 0; + } +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + + if (is_partial_io(bvec)) + /* Use a temporary buffer to decompress the page */ +@@ -689,10 +691,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + if (user_mem) + kunmap_atomic(user_mem); + /* Free memory associated with this sector now. */ +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + zram_free_page(zram, index); + zram_set_flag(meta, index, ZRAM_ZERO); +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + + atomic64_inc(&zram->stats.zero_pages); + ret = 0; +@@ -752,12 +754,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + * Free memory associated with this sector + * before overwriting unused sectors. + */ +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + zram_free_page(zram, index); + + meta->table[index].handle = handle; + zram_set_obj_size(meta, index, clen); +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + + /* Update stats */ + atomic64_add(clen, &zram->stats.compr_data_size); +@@ -800,9 +802,9 @@ static void zram_bio_discard(struct zram *zram, u32 index, + } + + while (n >= PAGE_SIZE) { +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + zram_free_page(zram, index); +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + atomic64_inc(&zram->stats.notify_free); + index++; + n -= PAGE_SIZE; +@@ -928,9 +930,9 @@ static void zram_slot_free_notify(struct block_device *bdev, + zram = bdev->bd_disk->private_data; + meta = zram->meta; + +- bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_lock_table(&meta->table[index]); + zram_free_page(zram, index); +- bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); ++ zram_unlock_table(&meta->table[index]); + atomic64_inc(&zram->stats.notify_free); + } + +diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h +index 8e92339..9e3e953 100644 +--- a/drivers/block/zram/zram_drv.h ++++ b/drivers/block/zram/zram_drv.h +@@ -72,6 +72,9 @@ enum zram_pageflags { + struct zram_table_entry { + unsigned long handle; + unsigned long value; ++#ifdef CONFIG_PREEMPT_RT_BASE ++ spinlock_t lock; ++#endif + }; + + struct zram_stats { +@@ -119,4 +122,42 @@ struct zram { + */ + bool claim; /* Protected by bdev->bd_mutex */ + }; ++ ++#ifndef CONFIG_PREEMPT_RT_BASE ++static inline void zram_lock_table(struct zram_table_entry *table) ++{ ++ bit_spin_lock(ZRAM_ACCESS, &table->value); ++} ++ ++static inline void zram_unlock_table(struct zram_table_entry *table) ++{ ++ bit_spin_unlock(ZRAM_ACCESS, &table->value); ++} ++ ++static inline void zram_meta_init_table_locks(struct zram_meta *meta, u64 disksize) { } ++#else /* CONFIG_PREEMPT_RT_BASE */ ++static inline void zram_lock_table(struct zram_table_entry *table) ++{ ++ spin_lock(&table->lock); ++ __set_bit(ZRAM_ACCESS, &table->value); ++} ++ ++static inline void zram_unlock_table(struct zram_table_entry *table) ++{ ++ __clear_bit(ZRAM_ACCESS, &table->value); ++ spin_unlock(&table->lock); ++} ++ ++static inline void zram_meta_init_table_locks(struct zram_meta *meta, u64 disksize) ++{ ++ size_t num_pages = disksize >> PAGE_SHIFT; ++ size_t index; ++ ++ for (index = 0; index < num_pages; index++) { ++ spinlock_t *lock = &meta->table[index].lock; ++ spin_lock_init(lock); ++ } ++} ++#endif /* CONFIG_PREEMPT_RT_BASE */ ++ + #endif +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index fa893c3..0beaa52 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0489, 0xe05f) }, + { USB_DEVICE(0x0489, 0xe076) }, + { USB_DEVICE(0x0489, 0xe078) }, ++ { USB_DEVICE(0x0489, 0xe095) }, + { USB_DEVICE(0x04c5, 0x1330) }, + { USB_DEVICE(0x04CA, 0x3004) }, + { USB_DEVICE(0x04CA, 0x3005) }, +@@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x04CA, 0x300d) }, + { USB_DEVICE(0x04CA, 0x300f) }, + { USB_DEVICE(0x04CA, 0x3010) }, ++ { USB_DEVICE(0x04CA, 0x3014) }, + { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0930, 0x021c) }, + { USB_DEVICE(0x0930, 0x0220) }, +@@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x13d3, 0x3362) }, + { USB_DEVICE(0x13d3, 0x3375) }, + { USB_DEVICE(0x13d3, 0x3393) }, ++ { USB_DEVICE(0x13d3, 0x3395) }, + { USB_DEVICE(0x13d3, 0x3402) }, + { USB_DEVICE(0x13d3, 0x3408) }, + { USB_DEVICE(0x13d3, 0x3423) }, + { USB_DEVICE(0x13d3, 0x3432) }, ++ { USB_DEVICE(0x13d3, 0x3472) }, + { USB_DEVICE(0x13d3, 0x3474) }, + + /* Atheros AR5BBU12 with sflash firmware */ +@@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, +@@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +@@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 9688971..7910759 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -196,6 +196,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, +@@ -206,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +@@ -227,10 +229,12 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index ed888e3..597b2d1 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -50,6 +50,7 @@ struct vhci_data { + wait_queue_head_t read_wait; + struct sk_buff_head readq; + ++ struct mutex open_mutex; + struct delayed_work open_timeout; + }; + +@@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) + return 0; + } + +-static int vhci_create_device(struct vhci_data *data, __u8 opcode) ++static int __vhci_create_device(struct vhci_data *data, __u8 opcode) + { + struct hci_dev *hdev; + struct sk_buff *skb; + __u8 dev_type; + ++ if (data->hdev) ++ return -EBADFD; ++ + /* bits 0-1 are dev_type (BR/EDR or AMP) */ + dev_type = opcode & 0x03; + +@@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode) + return 0; + } + ++static int vhci_create_device(struct vhci_data *data, __u8 opcode) ++{ ++ int err; ++ ++ mutex_lock(&data->open_mutex); ++ err = __vhci_create_device(data, opcode); ++ mutex_unlock(&data->open_mutex); ++ ++ return err; ++} ++ + static inline ssize_t vhci_get_user(struct vhci_data *data, + struct iov_iter *from) + { +@@ -189,11 +204,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, + break; + + case HCI_VENDOR_PKT: +- if (data->hdev) { +- kfree_skb(skb); +- return -EBADFD; +- } +- + cancel_delayed_work_sync(&data->open_timeout); + + opcode = *((__u8 *) skb->data); +@@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file) + skb_queue_head_init(&data->readq); + init_waitqueue_head(&data->read_wait); + ++ mutex_init(&data->open_mutex); + INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout); + + file->private_data = data; +@@ -333,15 +344,18 @@ static int vhci_open(struct inode *inode, struct file *file) + static int vhci_release(struct inode *inode, struct file *file) + { + struct vhci_data *data = file->private_data; +- struct hci_dev *hdev = data->hdev; ++ struct hci_dev *hdev; + + cancel_delayed_work_sync(&data->open_timeout); + ++ hdev = data->hdev; ++ + if (hdev) { + hci_unregister_dev(hdev); + hci_free_dev(hdev); + } + ++ skb_queue_purge(&data->readq); + file->private_data = NULL; + kfree(data); + +diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c +index e98d15e..1827fc4 100644 +--- a/drivers/bus/imx-weim.c ++++ b/drivers/bus/imx-weim.c +@@ -150,7 +150,7 @@ static int __init weim_parse_dt(struct platform_device *pdev, + return ret; + } + +- for_each_child_of_node(pdev->dev.of_node, child) { ++ for_each_available_child_of_node(pdev->dev.of_node, child) { + if (!child->name) + continue; + +diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c +index 30cf462..aa30af5 100644 +--- a/drivers/char/hw_random/exynos-rng.c ++++ b/drivers/char/hw_random/exynos-rng.c +@@ -89,6 +89,7 @@ static int exynos_read(struct hwrng *rng, void *buf, + struct exynos_rng, rng); + u32 *data = buf; + int retry = 100; ++ int ret = 4; + + pm_runtime_get_sync(exynos_rng->dev); + +@@ -97,17 +98,20 @@ static int exynos_read(struct hwrng *rng, void *buf, + while (!(exynos_rng_readl(exynos_rng, + EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry) + cpu_relax(); +- if (!retry) +- return -ETIMEDOUT; ++ if (!retry) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } + + exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET); + + *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET); + ++out: + pm_runtime_mark_last_busy(exynos_rng->dev); + pm_runtime_put_sync_autosuspend(exynos_rng->dev); + +- return 4; ++ return ret; + } + + static int exynos_rng_probe(struct platform_device *pdev) +diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c +index 45cc39a..2521425 100644 +--- a/drivers/char/tpm/tpm-chip.c ++++ b/drivers/char/tpm/tpm-chip.c +@@ -136,11 +136,13 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, + chip->cdev.owner = chip->pdev->driver->owner; + chip->cdev.kobj.parent = &chip->dev.kobj; + ++ devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); ++ + return chip; + } + EXPORT_SYMBOL_GPL(tpmm_chip_alloc); + +-static int tpm_dev_add_device(struct tpm_chip *chip) ++static int tpm_add_char_device(struct tpm_chip *chip) + { + int rc; + +@@ -151,7 +153,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip) + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + +- device_unregister(&chip->dev); + return rc; + } + +@@ -162,16 +163,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip) + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + ++ cdev_del(&chip->cdev); + return rc; + } + + return rc; + } + +-static void tpm_dev_del_device(struct tpm_chip *chip) ++static void tpm_del_char_device(struct tpm_chip *chip) + { + cdev_del(&chip->cdev); +- device_unregister(&chip->dev); ++ device_del(&chip->dev); + } + + static int tpm1_chip_register(struct tpm_chip *chip) +@@ -222,7 +224,7 @@ int tpm_chip_register(struct tpm_chip *chip) + + tpm_add_ppi(chip); + +- rc = tpm_dev_add_device(chip); ++ rc = tpm_add_char_device(chip); + if (rc) + goto out_err; + +@@ -274,6 +276,6 @@ void tpm_chip_unregister(struct tpm_chip *chip) + sysfs_remove_link(&chip->pdev->kobj, "ppi"); + + tpm1_chip_unregister(chip); +- tpm_dev_del_device(chip); ++ tpm_del_char_device(chip); + } + EXPORT_SYMBOL_GPL(tpm_chip_unregister); +diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c +index 4bb9727..61e6429 100644 +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -310,11 +310,11 @@ static int crb_acpi_remove(struct acpi_device *device) + struct device *dev = &device->dev; + struct tpm_chip *chip = dev_get_drvdata(dev); + +- tpm_chip_unregister(chip); +- + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_shutdown(chip, TPM2_SU_CLEAR); + ++ tpm_chip_unregister(chip); ++ + return 0; + } + +diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c +index bd72fb0..4e6940a 100644 +--- a/drivers/char/tpm/tpm_eventlog.c ++++ b/drivers/char/tpm/tpm_eventlog.c +@@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) + { + struct tcpa_event *event = v; + struct tcpa_event temp_event; +- char *tempPtr; ++ char *temp_ptr; + int i; + + memcpy(&temp_event, event, sizeof(struct tcpa_event)); +@@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) + temp_event.event_type = do_endian_conversion(event->event_type); + temp_event.event_size = do_endian_conversion(event->event_size); + +- tempPtr = (char *)&temp_event; ++ temp_ptr = (char *) &temp_event; + +- for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) +- seq_putc(m, tempPtr[i]); ++ for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) ++ seq_putc(m, temp_ptr[i]); ++ ++ temp_ptr = (char *) v; ++ ++ for (i = (sizeof(struct tcpa_event) - 1); ++ i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) ++ seq_putc(m, temp_ptr[i]); + + return 0; + +diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c +index abc8094..4ad3298 100644 +--- a/drivers/clk/at91/clk-generated.c ++++ b/drivers/clk/at91/clk-generated.c +@@ -15,8 +15,8 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -28,8 +28,9 @@ + + struct clk_generated { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + struct clk_range range; ++ spinlock_t *lock; + u32 id; + u32 gckdiv; + u8 parent_id; +@@ -41,49 +42,52 @@ struct clk_generated { + static int clk_generated_enable(struct clk_hw *hw) + { + struct clk_generated *gck = to_clk_generated(hw); +- struct at91_pmc *pmc = gck->pmc; +- u32 tmp; ++ unsigned long flags; + + pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n", + __func__, gck->gckdiv, gck->parent_id); + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR) & +- ~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK); +- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id) +- | AT91_PMC_PCR_CMD +- | AT91_PMC_PCR_GCKDIV(gck->gckdiv) +- | AT91_PMC_PCR_GCKEN); +- pmc_unlock(pmc); ++ spin_lock_irqsave(gck->lock, flags); ++ regmap_write(gck->regmap, AT91_PMC_PCR, ++ (gck->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_update_bits(gck->regmap, AT91_PMC_PCR, ++ AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK | ++ AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, ++ AT91_PMC_PCR_GCKCSS(gck->parent_id) | ++ AT91_PMC_PCR_CMD | ++ AT91_PMC_PCR_GCKDIV(gck->gckdiv) | ++ AT91_PMC_PCR_GCKEN); ++ spin_unlock_irqrestore(gck->lock, flags); + return 0; + } + + static void clk_generated_disable(struct clk_hw *hw) + { + struct clk_generated *gck = to_clk_generated(hw); +- struct at91_pmc *pmc = gck->pmc; +- u32 tmp; +- +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN; +- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD); +- pmc_unlock(pmc); ++ unsigned long flags; ++ ++ spin_lock_irqsave(gck->lock, flags); ++ regmap_write(gck->regmap, AT91_PMC_PCR, ++ (gck->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_update_bits(gck->regmap, AT91_PMC_PCR, ++ AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, ++ AT91_PMC_PCR_CMD); ++ spin_unlock_irqrestore(gck->lock, flags); + } + + static int clk_generated_is_enabled(struct clk_hw *hw) + { + struct clk_generated *gck = to_clk_generated(hw); +- struct at91_pmc *pmc = gck->pmc; +- int ret; ++ unsigned long flags; ++ unsigned int status; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); +- ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN); +- pmc_unlock(pmc); ++ spin_lock_irqsave(gck->lock, flags); ++ regmap_write(gck->regmap, AT91_PMC_PCR, ++ (gck->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_read(gck->regmap, AT91_PMC_PCR, &status); ++ spin_unlock_irqrestore(gck->lock, flags); + +- return ret; ++ return status & AT91_PMC_PCR_GCKEN ? 1 : 0; + } + + static unsigned long +@@ -214,13 +218,14 @@ static const struct clk_ops generated_ops = { + */ + static void clk_generated_startup(struct clk_generated *gck) + { +- struct at91_pmc *pmc = gck->pmc; + u32 tmp; ++ unsigned long flags; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR); +- pmc_unlock(pmc); ++ spin_lock_irqsave(gck->lock, flags); ++ regmap_write(gck->regmap, AT91_PMC_PCR, ++ (gck->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_read(gck->regmap, AT91_PMC_PCR, &tmp); ++ spin_unlock_irqrestore(gck->lock, flags); + + gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK) + >> AT91_PMC_PCR_GCKCSS_OFFSET; +@@ -229,8 +234,8 @@ static void clk_generated_startup(struct clk_generated *gck) + } + + static struct clk * __init +-at91_clk_register_generated(struct at91_pmc *pmc, const char *name, +- const char **parent_names, u8 num_parents, ++at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const char ++ *name, const char **parent_names, u8 num_parents, + u8 id, const struct clk_range *range) + { + struct clk_generated *gck; +@@ -249,7 +254,8 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, + + gck->id = id; + gck->hw.init = &init; +- gck->pmc = pmc; ++ gck->regmap = regmap; ++ gck->lock = lock; + gck->range = *range; + + clk = clk_register(NULL, &gck->hw); +@@ -261,8 +267,7 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, + return clk; + } + +-void __init of_sama5d2_clk_generated_setup(struct device_node *np, +- struct at91_pmc *pmc) ++void __init of_sama5d2_clk_generated_setup(struct device_node *np) + { + int num; + u32 id; +@@ -272,6 +277,7 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, + const char *parent_names[GENERATED_SOURCE_MAX]; + struct device_node *gcknp; + struct clk_range range = CLK_RANGE(0, 0); ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > GENERATED_SOURCE_MAX) +@@ -283,6 +289,10 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, + if (!num || num > PERIPHERAL_MAX) + return; + ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ + for_each_child_of_node(np, gcknp) { + if (of_property_read_u32(gcknp, "reg", &id)) + continue; +@@ -296,11 +306,14 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, + of_at91_get_clk_range(gcknp, "atmel,clk-output-range", + &range); + +- clk = at91_clk_register_generated(pmc, name, parent_names, +- num_parents, id, &range); ++ clk = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, ++ parent_names, num_parents, ++ id, &range); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(gcknp, of_clk_src_simple_get, clk); + } + } ++CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated", ++ of_sama5d2_clk_generated_setup); +diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c +index 61566bc..8e20c8a 100644 +--- a/drivers/clk/at91/clk-h32mx.c ++++ b/drivers/clk/at91/clk-h32mx.c +@@ -15,15 +15,9 @@ + #include + #include + #include +-#include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -31,7 +25,7 @@ + + struct clk_sama5d4_h32mx { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + #define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw) +@@ -40,8 +34,10 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); ++ unsigned int mckr; + +- if (pmc_read(h32mxclk->pmc, AT91_PMC_MCKR) & AT91_PMC_H32MXDIV) ++ regmap_read(h32mxclk->regmap, AT91_PMC_MCKR, &mckr); ++ if (mckr & AT91_PMC_H32MXDIV) + return parent_rate / 2; + + if (parent_rate > H32MX_MAX_FREQ) +@@ -70,18 +66,16 @@ static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { + struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); +- struct at91_pmc *pmc = h32mxclk->pmc; +- u32 tmp; ++ u32 mckr = 0; + + if (parent_rate != rate && (parent_rate / 2) != rate) + return -EINVAL; + +- pmc_lock(pmc); +- tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_H32MXDIV; + if ((parent_rate / 2) == rate) +- tmp |= AT91_PMC_H32MXDIV; +- pmc_write(pmc, AT91_PMC_MCKR, tmp); +- pmc_unlock(pmc); ++ mckr = AT91_PMC_H32MXDIV; ++ ++ regmap_update_bits(h32mxclk->regmap, AT91_PMC_MCKR, ++ AT91_PMC_H32MXDIV, mckr); + + return 0; + } +@@ -92,14 +86,18 @@ static const struct clk_ops h32mx_ops = { + .set_rate = clk_sama5d4_h32mx_set_rate, + }; + +-void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) + { + struct clk_sama5d4_h32mx *h32mxclk; + struct clk_init_data init; + const char *parent_name; ++ struct regmap *regmap; + struct clk *clk; + ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ + h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL); + if (!h32mxclk) + return; +@@ -113,13 +111,15 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, + init.flags = CLK_SET_RATE_GATE; + + h32mxclk->hw.init = &init; +- h32mxclk->pmc = pmc; ++ h32mxclk->regmap = regmap; + + clk = clk_register(NULL, &h32mxclk->hw); +- if (!clk) { ++ if (IS_ERR(clk)) { + kfree(h32mxclk); + return; + } + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx", ++ of_sama5d4_clk_h32mx_setup); +diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c +index fd7247d..4bfc94d 100644 +--- a/drivers/clk/at91/clk-main.c ++++ b/drivers/clk/at91/clk-main.c +@@ -13,13 +13,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -34,18 +29,14 @@ + + struct clk_main_osc { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + }; + + #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw) + + struct clk_main_rc_osc { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + unsigned long frequency; + unsigned long accuracy; + }; +@@ -54,51 +45,47 @@ struct clk_main_rc_osc { + + struct clk_rm9200_main { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw) + + struct clk_sam9x5_main { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + u8 parent; + }; + + #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw) + +-static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id) ++static inline bool clk_main_osc_ready(struct regmap *regmap) + { +- struct clk_main_osc *osc = dev_id; ++ unsigned int status; + +- wake_up(&osc->wait); +- disable_irq_nosync(osc->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & AT91_PMC_MOSCS; + } + + static int clk_main_osc_prepare(struct clk_hw *hw) + { + struct clk_main_osc *osc = to_clk_main_osc(hw); +- struct at91_pmc *pmc = osc->pmc; ++ struct regmap *regmap = osc->regmap; + u32 tmp; + +- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; ++ regmap_read(regmap, AT91_CKGR_MOR, &tmp); ++ tmp &= ~MOR_KEY_MASK; ++ + if (tmp & AT91_PMC_OSCBYPASS) + return 0; + + if (!(tmp & AT91_PMC_MOSCEN)) { + tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY; +- pmc_write(pmc, AT91_CKGR_MOR, tmp); ++ regmap_write(regmap, AT91_CKGR_MOR, tmp); + } + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { +- enable_irq(osc->irq); +- wait_event(osc->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); +- } ++ while (!clk_main_osc_ready(regmap)) ++ cpu_relax(); + + return 0; + } +@@ -106,9 +93,10 @@ static int clk_main_osc_prepare(struct clk_hw *hw) + static void clk_main_osc_unprepare(struct clk_hw *hw) + { + struct clk_main_osc *osc = to_clk_main_osc(hw); +- struct at91_pmc *pmc = osc->pmc; +- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); ++ struct regmap *regmap = osc->regmap; ++ u32 tmp; + ++ regmap_read(regmap, AT91_CKGR_MOR, &tmp); + if (tmp & AT91_PMC_OSCBYPASS) + return; + +@@ -116,20 +104,22 @@ static void clk_main_osc_unprepare(struct clk_hw *hw) + return; + + tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); +- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); ++ regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); + } + + static int clk_main_osc_is_prepared(struct clk_hw *hw) + { + struct clk_main_osc *osc = to_clk_main_osc(hw); +- struct at91_pmc *pmc = osc->pmc; +- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); ++ struct regmap *regmap = osc->regmap; ++ u32 tmp, status; + ++ regmap_read(regmap, AT91_CKGR_MOR, &tmp); + if (tmp & AT91_PMC_OSCBYPASS) + return 1; + +- return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) && +- (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN)); ++ regmap_read(regmap, AT91_PMC_SR, &status); ++ ++ return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN); + } + + static const struct clk_ops main_osc_ops = { +@@ -139,18 +129,16 @@ static const struct clk_ops main_osc_ops = { + }; + + static struct clk * __init +-at91_clk_register_main_osc(struct at91_pmc *pmc, +- unsigned int irq, ++at91_clk_register_main_osc(struct regmap *regmap, + const char *name, + const char *parent_name, + bool bypass) + { +- int ret; + struct clk_main_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !irq || !name || !parent_name) ++ if (!name || !parent_name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); +@@ -164,85 +152,70 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, + init.flags = CLK_IGNORE_UNUSED; + + osc->hw.init = &init; +- osc->pmc = pmc; +- osc->irq = irq; +- +- init_waitqueue_head(&osc->wait); +- irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); +- ret = request_irq(osc->irq, clk_main_osc_irq_handler, +- IRQF_TRIGGER_HIGH, name, osc); +- if (ret) { +- kfree(osc); +- return ERR_PTR(ret); +- } ++ osc->regmap = regmap; + + if (bypass) +- pmc_write(pmc, AT91_CKGR_MOR, +- (pmc_read(pmc, AT91_CKGR_MOR) & +- ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) | +- AT91_PMC_OSCBYPASS | AT91_PMC_KEY); ++ regmap_update_bits(regmap, ++ AT91_CKGR_MOR, MOR_KEY_MASK | ++ AT91_PMC_MOSCEN, ++ AT91_PMC_OSCBYPASS | AT91_PMC_KEY); + + clk = clk_register(NULL, &osc->hw); +- if (IS_ERR(clk)) { +- free_irq(irq, osc); ++ if (IS_ERR(clk)) + kfree(osc); +- } + + return clk; + } + +-void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np) + { + struct clk *clk; +- unsigned int irq; + const char *name = np->name; + const char *parent_name; ++ struct regmap *regmap; + bool bypass; + + of_property_read_string(np, "clock-output-names", &name); + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + parent_name = of_clk_get_parent_name(np, 0); + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) + return; + +- clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass); ++ clk = at91_clk_register_main_osc(regmap, name, parent_name, bypass); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc", ++ of_at91rm9200_clk_main_osc_setup); + +-static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id) ++static bool clk_main_rc_osc_ready(struct regmap *regmap) + { +- struct clk_main_rc_osc *osc = dev_id; ++ unsigned int status; + +- wake_up(&osc->wait); +- disable_irq_nosync(osc->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & AT91_PMC_MOSCRCS; + } + + static int clk_main_rc_osc_prepare(struct clk_hw *hw) + { + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); +- struct at91_pmc *pmc = osc->pmc; +- u32 tmp; ++ struct regmap *regmap = osc->regmap; ++ unsigned int mor; + +- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; ++ regmap_read(regmap, AT91_CKGR_MOR, &mor); + +- if (!(tmp & AT91_PMC_MOSCRCEN)) { +- tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY; +- pmc_write(pmc, AT91_CKGR_MOR, tmp); +- } ++ if (!(mor & AT91_PMC_MOSCRCEN)) ++ regmap_update_bits(regmap, AT91_CKGR_MOR, ++ MOR_KEY_MASK | AT91_PMC_MOSCRCEN, ++ AT91_PMC_MOSCRCEN | AT91_PMC_KEY); + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) { +- enable_irq(osc->irq); +- wait_event(osc->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS); +- } ++ while (!clk_main_rc_osc_ready(regmap)) ++ cpu_relax(); + + return 0; + } +@@ -250,23 +223,28 @@ static int clk_main_rc_osc_prepare(struct clk_hw *hw) + static void clk_main_rc_osc_unprepare(struct clk_hw *hw) + { + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); +- struct at91_pmc *pmc = osc->pmc; +- u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); ++ struct regmap *regmap = osc->regmap; ++ unsigned int mor; ++ ++ regmap_read(regmap, AT91_CKGR_MOR, &mor); + +- if (!(tmp & AT91_PMC_MOSCRCEN)) ++ if (!(mor & AT91_PMC_MOSCRCEN)) + return; + +- tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN); +- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); ++ regmap_update_bits(regmap, AT91_CKGR_MOR, ++ MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); + } + + static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) + { + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); +- struct at91_pmc *pmc = osc->pmc; ++ struct regmap *regmap = osc->regmap; ++ unsigned int mor, status; + +- return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) && +- (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN)); ++ regmap_read(regmap, AT91_CKGR_MOR, &mor); ++ regmap_read(regmap, AT91_PMC_SR, &status); ++ ++ return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS); + } + + static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, +@@ -294,17 +272,15 @@ static const struct clk_ops main_rc_osc_ops = { + }; + + static struct clk * __init +-at91_clk_register_main_rc_osc(struct at91_pmc *pmc, +- unsigned int irq, ++at91_clk_register_main_rc_osc(struct regmap *regmap, + const char *name, + u32 frequency, u32 accuracy) + { +- int ret; + struct clk_main_rc_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !irq || !name || !frequency) ++ if (!name || !frequency) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); +@@ -318,63 +294,53 @@ at91_clk_register_main_rc_osc(struct at91_pmc *pmc, + init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED; + + osc->hw.init = &init; +- osc->pmc = pmc; +- osc->irq = irq; ++ osc->regmap = regmap; + osc->frequency = frequency; + osc->accuracy = accuracy; + +- init_waitqueue_head(&osc->wait); +- irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); +- ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler, +- IRQF_TRIGGER_HIGH, name, osc); +- if (ret) +- return ERR_PTR(ret); +- + clk = clk_register(NULL, &osc->hw); +- if (IS_ERR(clk)) { +- free_irq(irq, osc); ++ if (IS_ERR(clk)) + kfree(osc); +- } + + return clk; + } + +-void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np) + { + struct clk *clk; +- unsigned int irq; + u32 frequency = 0; + u32 accuracy = 0; + const char *name = np->name; ++ struct regmap *regmap; + + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &frequency); + of_property_read_u32(np, "clock-accuracy", &accuracy); + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) + return; + +- clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency, +- accuracy); ++ clk = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc", ++ of_at91sam9x5_clk_main_rc_osc_setup); + + +-static int clk_main_probe_frequency(struct at91_pmc *pmc) ++static int clk_main_probe_frequency(struct regmap *regmap) + { + unsigned long prep_time, timeout; +- u32 tmp; ++ unsigned int mcfr; + + timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); + do { + prep_time = jiffies; +- tmp = pmc_read(pmc, AT91_CKGR_MCFR); +- if (tmp & AT91_PMC_MAINRDY) ++ regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); ++ if (mcfr & AT91_PMC_MAINRDY) + return 0; + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); + } while (time_before(prep_time, timeout)); +@@ -382,34 +348,37 @@ static int clk_main_probe_frequency(struct at91_pmc *pmc) + return -ETIMEDOUT; + } + +-static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc, ++static unsigned long clk_main_recalc_rate(struct regmap *regmap, + unsigned long parent_rate) + { +- u32 tmp; ++ unsigned int mcfr; + + if (parent_rate) + return parent_rate; + + pr_warn("Main crystal frequency not set, using approximate value\n"); +- tmp = pmc_read(pmc, AT91_CKGR_MCFR); +- if (!(tmp & AT91_PMC_MAINRDY)) ++ regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); ++ if (!(mcfr & AT91_PMC_MAINRDY)) + return 0; + +- return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; ++ return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; + } + + static int clk_rm9200_main_prepare(struct clk_hw *hw) + { + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); + +- return clk_main_probe_frequency(clkmain->pmc); ++ return clk_main_probe_frequency(clkmain->regmap); + } + + static int clk_rm9200_main_is_prepared(struct clk_hw *hw) + { + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); ++ unsigned int status; ++ ++ regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status); + +- return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY); ++ return status & AT91_PMC_MAINRDY ? 1 : 0; + } + + static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, +@@ -417,7 +386,7 @@ static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, + { + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); + +- return clk_main_recalc_rate(clkmain->pmc, parent_rate); ++ return clk_main_recalc_rate(clkmain->regmap, parent_rate); + } + + static const struct clk_ops rm9200_main_ops = { +@@ -427,7 +396,7 @@ static const struct clk_ops rm9200_main_ops = { + }; + + static struct clk * __init +-at91_clk_register_rm9200_main(struct at91_pmc *pmc, ++at91_clk_register_rm9200_main(struct regmap *regmap, + const char *name, + const char *parent_name) + { +@@ -435,7 +404,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !name) ++ if (!name) + return ERR_PTR(-EINVAL); + + if (!parent_name) +@@ -452,7 +421,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, + init.flags = 0; + + clkmain->hw.init = &init; +- clkmain->pmc = pmc; ++ clkmain->regmap = regmap; + + clk = clk_register(NULL, &clkmain->hw); + if (IS_ERR(clk)) +@@ -461,52 +430,54 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc, + return clk; + } + +-void __init of_at91rm9200_clk_main_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_main_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_name; + const char *name = np->name; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91_clk_register_rm9200_main(pmc, name, parent_name); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ ++ clk = at91_clk_register_rm9200_main(regmap, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main", ++ of_at91rm9200_clk_main_setup); + +-static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id) ++static inline bool clk_sam9x5_main_ready(struct regmap *regmap) + { +- struct clk_sam9x5_main *clkmain = dev_id; ++ unsigned int status; + +- wake_up(&clkmain->wait); +- disable_irq_nosync(clkmain->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & AT91_PMC_MOSCSELS ? 1 : 0; + } + + static int clk_sam9x5_main_prepare(struct clk_hw *hw) + { + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); +- struct at91_pmc *pmc = clkmain->pmc; ++ struct regmap *regmap = clkmain->regmap; + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { +- enable_irq(clkmain->irq); +- wait_event(clkmain->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); +- } ++ while (!clk_sam9x5_main_ready(regmap)) ++ cpu_relax(); + +- return clk_main_probe_frequency(pmc); ++ return clk_main_probe_frequency(regmap); + } + + static int clk_sam9x5_main_is_prepared(struct clk_hw *hw) + { + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); + +- return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); ++ return clk_sam9x5_main_ready(clkmain->regmap); + } + + static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, +@@ -514,30 +485,28 @@ static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, + { + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); + +- return clk_main_recalc_rate(clkmain->pmc, parent_rate); ++ return clk_main_recalc_rate(clkmain->regmap, parent_rate); + } + + static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) + { + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); +- struct at91_pmc *pmc = clkmain->pmc; +- u32 tmp; ++ struct regmap *regmap = clkmain->regmap; ++ unsigned int tmp; + + if (index > 1) + return -EINVAL; + +- tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; ++ regmap_read(regmap, AT91_CKGR_MOR, &tmp); ++ tmp &= ~MOR_KEY_MASK; + + if (index && !(tmp & AT91_PMC_MOSCSEL)) +- pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); ++ regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); + else if (!index && (tmp & AT91_PMC_MOSCSEL)) +- pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); ++ regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { +- enable_irq(clkmain->irq); +- wait_event(clkmain->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); +- } ++ while (!clk_sam9x5_main_ready(regmap)) ++ cpu_relax(); + + return 0; + } +@@ -545,8 +514,11 @@ static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) + static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw) + { + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); ++ unsigned int status; ++ ++ regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); + +- return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN); ++ return status & AT91_PMC_MOSCEN ? 1 : 0; + } + + static const struct clk_ops sam9x5_main_ops = { +@@ -558,18 +530,17 @@ static const struct clk_ops sam9x5_main_ops = { + }; + + static struct clk * __init +-at91_clk_register_sam9x5_main(struct at91_pmc *pmc, +- unsigned int irq, ++at91_clk_register_sam9x5_main(struct regmap *regmap, + const char *name, + const char **parent_names, + int num_parents) + { +- int ret; + struct clk_sam9x5_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; ++ unsigned int status; + +- if (!pmc || !irq || !name) ++ if (!name) + return ERR_PTR(-EINVAL); + + if (!parent_names || !num_parents) +@@ -586,51 +557,42 @@ at91_clk_register_sam9x5_main(struct at91_pmc *pmc, + init.flags = CLK_SET_PARENT_GATE; + + clkmain->hw.init = &init; +- clkmain->pmc = pmc; +- clkmain->irq = irq; +- clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & +- AT91_PMC_MOSCEN); +- init_waitqueue_head(&clkmain->wait); +- irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); +- ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler, +- IRQF_TRIGGER_HIGH, name, clkmain); +- if (ret) +- return ERR_PTR(ret); ++ clkmain->regmap = regmap; ++ regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); ++ clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0; + + clk = clk_register(NULL, &clkmain->hw); +- if (IS_ERR(clk)) { +- free_irq(clkmain->irq, clkmain); ++ if (IS_ERR(clk)) + kfree(clkmain); +- } + + return clk; + } + +-void __init of_at91sam9x5_clk_main_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_main_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_names[2]; + int num_parents; +- unsigned int irq; + const char *name = np->name; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > 2) + return; + + of_clk_parent_fill(np, parent_names, num_parents); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; + + of_property_read_string(np, "clock-output-names", &name); + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) +- return; +- +- clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names, ++ clk = at91_clk_register_sam9x5_main(regmap, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main", ++ of_at91sam9x5_clk_main_setup); +diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c +index 620ea32..7d4a186 100644 +--- a/drivers/clk/at91/clk-master.c ++++ b/drivers/clk/at91/clk-master.c +@@ -12,13 +12,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -44,32 +39,26 @@ struct clk_master_layout { + + struct clk_master { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + const struct clk_master_layout *layout; + const struct clk_master_characteristics *characteristics; + }; + +-static irqreturn_t clk_master_irq_handler(int irq, void *dev_id) ++static inline bool clk_master_ready(struct regmap *regmap) + { +- struct clk_master *master = (struct clk_master *)dev_id; ++ unsigned int status; + +- wake_up(&master->wait); +- disable_irq_nosync(master->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & AT91_PMC_MCKRDY ? 1 : 0; + } ++ + static int clk_master_prepare(struct clk_hw *hw) + { + struct clk_master *master = to_clk_master(hw); +- struct at91_pmc *pmc = master->pmc; + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) { +- enable_irq(master->irq); +- wait_event(master->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); +- } ++ while (!clk_master_ready(master->regmap)) ++ cpu_relax(); + + return 0; + } +@@ -78,7 +67,7 @@ static int clk_master_is_prepared(struct clk_hw *hw) + { + struct clk_master *master = to_clk_master(hw); + +- return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); ++ return clk_master_ready(master->regmap); + } + + static unsigned long clk_master_recalc_rate(struct clk_hw *hw, +@@ -88,18 +77,16 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw, + u8 div; + unsigned long rate = parent_rate; + struct clk_master *master = to_clk_master(hw); +- struct at91_pmc *pmc = master->pmc; + const struct clk_master_layout *layout = master->layout; + const struct clk_master_characteristics *characteristics = + master->characteristics; +- u32 tmp; ++ unsigned int mckr; + +- pmc_lock(pmc); +- tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask; +- pmc_unlock(pmc); ++ regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); ++ mckr &= layout->mask; + +- pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK; +- div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; ++ pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK; ++ div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; + + if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX) + rate /= 3; +@@ -119,9 +106,11 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw, + static u8 clk_master_get_parent(struct clk_hw *hw) + { + struct clk_master *master = to_clk_master(hw); +- struct at91_pmc *pmc = master->pmc; ++ unsigned int mckr; + +- return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS; ++ regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); ++ ++ return mckr & AT91_PMC_CSS; + } + + static const struct clk_ops master_ops = { +@@ -132,18 +121,17 @@ static const struct clk_ops master_ops = { + }; + + static struct clk * __init +-at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, ++at91_clk_register_master(struct regmap *regmap, + const char *name, int num_parents, + const char **parent_names, + const struct clk_master_layout *layout, + const struct clk_master_characteristics *characteristics) + { +- int ret; + struct clk_master *master; + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !irq || !name || !num_parents || !parent_names) ++ if (!name || !num_parents || !parent_names) + return ERR_PTR(-EINVAL); + + master = kzalloc(sizeof(*master), GFP_KERNEL); +@@ -159,20 +147,10 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, + master->hw.init = &init; + master->layout = layout; + master->characteristics = characteristics; +- master->pmc = pmc; +- master->irq = irq; +- init_waitqueue_head(&master->wait); +- irq_set_status_flags(master->irq, IRQ_NOAUTOEN); +- ret = request_irq(master->irq, clk_master_irq_handler, +- IRQF_TRIGGER_HIGH, "clk-master", master); +- if (ret) { +- kfree(master); +- return ERR_PTR(ret); +- } ++ master->regmap = regmap; + + clk = clk_register(NULL, &master->hw); + if (IS_ERR(clk)) { +- free_irq(master->irq, master); + kfree(master); + } + +@@ -217,15 +195,15 @@ out_free_characteristics: + } + + static void __init +-of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, ++of_at91_clk_master_setup(struct device_node *np, + const struct clk_master_layout *layout) + { + struct clk *clk; + int num_parents; +- unsigned int irq; + const char *parent_names[MASTER_SOURCE_MAX]; + const char *name = np->name; + struct clk_master_characteristics *characteristics; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX) +@@ -239,11 +217,11 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, + if (!characteristics) + return; + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) +- goto out_free_characteristics; ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; + +- clk = at91_clk_register_master(pmc, irq, name, num_parents, ++ clk = at91_clk_register_master(regmap, name, num_parents, + parent_names, layout, + characteristics); + if (IS_ERR(clk)) +@@ -256,14 +234,16 @@ out_free_characteristics: + kfree(characteristics); + } + +-void __init of_at91rm9200_clk_master_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_master_setup(struct device_node *np) + { +- of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout); ++ of_at91_clk_master_setup(np, &at91rm9200_master_layout); + } ++CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master", ++ of_at91rm9200_clk_master_setup); + +-void __init of_at91sam9x5_clk_master_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_master_setup(struct device_node *np) + { +- of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout); ++ of_at91_clk_master_setup(np, &at91sam9x5_master_layout); + } ++CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master", ++ of_at91sam9x5_clk_master_setup); +diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c +index 58f3b56..d69cd2a 100644 +--- a/drivers/clk/at91/clk-peripheral.c ++++ b/drivers/clk/at91/clk-peripheral.c +@@ -12,11 +12,13 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + + #include "pmc.h" + ++DEFINE_SPINLOCK(pmc_pcr_lock); ++ + #define PERIPHERAL_MAX 64 + + #define PERIPHERAL_AT91RM9200 0 +@@ -33,7 +35,7 @@ + + struct clk_peripheral { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + u32 id; + }; + +@@ -41,8 +43,9 @@ struct clk_peripheral { + + struct clk_sam9x5_peripheral { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + struct clk_range range; ++ spinlock_t *lock; + u32 id; + u32 div; + bool auto_div; +@@ -54,7 +57,6 @@ struct clk_sam9x5_peripheral { + static int clk_peripheral_enable(struct clk_hw *hw) + { + struct clk_peripheral *periph = to_clk_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCER; + u32 id = periph->id; + +@@ -62,14 +64,14 @@ static int clk_peripheral_enable(struct clk_hw *hw) + return 0; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCER1; +- pmc_write(pmc, offset, PERIPHERAL_MASK(id)); ++ regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id)); ++ + return 0; + } + + static void clk_peripheral_disable(struct clk_hw *hw) + { + struct clk_peripheral *periph = to_clk_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCDR; + u32 id = periph->id; + +@@ -77,21 +79,23 @@ static void clk_peripheral_disable(struct clk_hw *hw) + return; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCDR1; +- pmc_write(pmc, offset, PERIPHERAL_MASK(id)); ++ regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id)); + } + + static int clk_peripheral_is_enabled(struct clk_hw *hw) + { + struct clk_peripheral *periph = to_clk_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCSR; ++ unsigned int status; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return 1; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCSR1; +- return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id)); ++ regmap_read(periph->regmap, offset, &status); ++ ++ return status & PERIPHERAL_MASK(id) ? 1 : 0; + } + + static const struct clk_ops peripheral_ops = { +@@ -101,14 +105,14 @@ static const struct clk_ops peripheral_ops = { + }; + + static struct clk * __init +-at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, ++at91_clk_register_peripheral(struct regmap *regmap, const char *name, + const char *parent_name, u32 id) + { + struct clk_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX) ++ if (!name || !parent_name || id > PERIPHERAL_ID_MAX) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); +@@ -123,7 +127,7 @@ at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, + + periph->id = id; + periph->hw.init = &init; +- periph->pmc = pmc; ++ periph->regmap = regmap; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) +@@ -160,53 +164,58 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) + static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) + { + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; +- u32 tmp; ++ unsigned long flags; + + if (periph->id < PERIPHERAL_ID_MIN) + return 0; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_DIV_MASK; +- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_DIV(periph->div) +- | AT91_PMC_PCR_CMD +- | AT91_PMC_PCR_EN); +- pmc_unlock(pmc); ++ spin_lock_irqsave(periph->lock, flags); ++ regmap_write(periph->regmap, AT91_PMC_PCR, ++ (periph->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_update_bits(periph->regmap, AT91_PMC_PCR, ++ AT91_PMC_PCR_DIV_MASK | AT91_PMC_PCR_CMD | ++ AT91_PMC_PCR_EN, ++ AT91_PMC_PCR_DIV(periph->div) | ++ AT91_PMC_PCR_CMD | ++ AT91_PMC_PCR_EN); ++ spin_unlock_irqrestore(periph->lock, flags); ++ + return 0; + } + + static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) + { + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; +- u32 tmp; ++ unsigned long flags; + + if (periph->id < PERIPHERAL_ID_MIN) + return; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_EN; +- pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD); +- pmc_unlock(pmc); ++ spin_lock_irqsave(periph->lock, flags); ++ regmap_write(periph->regmap, AT91_PMC_PCR, ++ (periph->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_update_bits(periph->regmap, AT91_PMC_PCR, ++ AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD, ++ AT91_PMC_PCR_CMD); ++ spin_unlock_irqrestore(periph->lock, flags); + } + + static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) + { + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; +- int ret; ++ unsigned long flags; ++ unsigned int status; + + if (periph->id < PERIPHERAL_ID_MIN) + return 1; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); +- ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN); +- pmc_unlock(pmc); ++ spin_lock_irqsave(periph->lock, flags); ++ regmap_write(periph->regmap, AT91_PMC_PCR, ++ (periph->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_read(periph->regmap, AT91_PMC_PCR, &status); ++ spin_unlock_irqrestore(periph->lock, flags); + +- return ret; ++ return status & AT91_PMC_PCR_EN ? 1 : 0; + } + + static unsigned long +@@ -214,19 +223,20 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); +- struct at91_pmc *pmc = periph->pmc; +- u32 tmp; ++ unsigned long flags; ++ unsigned int status; + + if (periph->id < PERIPHERAL_ID_MIN) + return parent_rate; + +- pmc_lock(pmc); +- pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK)); +- tmp = pmc_read(pmc, AT91_PMC_PCR); +- pmc_unlock(pmc); ++ spin_lock_irqsave(periph->lock, flags); ++ regmap_write(periph->regmap, AT91_PMC_PCR, ++ (periph->id & AT91_PMC_PCR_PID_MASK)); ++ regmap_read(periph->regmap, AT91_PMC_PCR, &status); ++ spin_unlock_irqrestore(periph->lock, flags); + +- if (tmp & AT91_PMC_PCR_EN) { +- periph->div = PERIPHERAL_RSHIFT(tmp); ++ if (status & AT91_PMC_PCR_EN) { ++ periph->div = PERIPHERAL_RSHIFT(status); + periph->auto_div = false; + } else { + clk_sam9x5_peripheral_autodiv(periph); +@@ -318,15 +328,15 @@ static const struct clk_ops sam9x5_peripheral_ops = { + }; + + static struct clk * __init +-at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, +- const char *parent_name, u32 id, +- const struct clk_range *range) ++at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, ++ const char *name, const char *parent_name, ++ u32 id, const struct clk_range *range) + { + struct clk_sam9x5_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !name || !parent_name) ++ if (!name || !parent_name) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); +@@ -342,7 +352,8 @@ at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, + periph->id = id; + periph->hw.init = &init; + periph->div = 0; +- periph->pmc = pmc; ++ periph->regmap = regmap; ++ periph->lock = lock; + periph->auto_div = true; + periph->range = *range; + +@@ -356,7 +367,7 @@ at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, + } + + static void __init +-of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) ++of_at91_clk_periph_setup(struct device_node *np, u8 type) + { + int num; + u32 id; +@@ -364,6 +375,7 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) + const char *parent_name; + const char *name; + struct device_node *periphclknp; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) +@@ -373,6 +385,10 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) + if (!num || num > PERIPHERAL_MAX) + return; + ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ + for_each_child_of_node(np, periphclknp) { + if (of_property_read_u32(periphclknp, "reg", &id)) + continue; +@@ -384,7 +400,7 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) + name = periphclknp->name; + + if (type == PERIPHERAL_AT91RM9200) { +- clk = at91_clk_register_peripheral(pmc, name, ++ clk = at91_clk_register_peripheral(regmap, name, + parent_name, id); + } else { + struct clk_range range = CLK_RANGE(0, 0); +@@ -393,7 +409,9 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) + "atmel,clk-output-range", + &range); + +- clk = at91_clk_register_sam9x5_peripheral(pmc, name, ++ clk = at91_clk_register_sam9x5_peripheral(regmap, ++ &pmc_pcr_lock, ++ name, + parent_name, + id, &range); + } +@@ -405,14 +423,16 @@ of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) + } + } + +-void __init of_at91rm9200_clk_periph_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_periph_setup(struct device_node *np) + { +- of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200); ++ of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200); + } ++CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral", ++ of_at91rm9200_clk_periph_setup); + +-void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np) + { +- of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5); ++ of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5); + } ++CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral", ++ of_at91sam9x5_clk_periph_setup); +diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c +index 18b60f4..fb2e0b5 100644 +--- a/drivers/clk/at91/clk-pll.c ++++ b/drivers/clk/at91/clk-pll.c +@@ -12,14 +12,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -58,9 +52,7 @@ struct clk_pll_layout { + + struct clk_pll { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + u8 id; + u8 div; + u8 range; +@@ -69,20 +61,19 @@ struct clk_pll { + const struct clk_pll_characteristics *characteristics; + }; + +-static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id) ++static inline bool clk_pll_ready(struct regmap *regmap, int id) + { +- struct clk_pll *pll = (struct clk_pll *)dev_id; ++ unsigned int status; + +- wake_up(&pll->wait); +- disable_irq_nosync(pll->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & PLL_STATUS_MASK(id) ? 1 : 0; + } + + static int clk_pll_prepare(struct clk_hw *hw) + { + struct clk_pll *pll = to_clk_pll(hw); +- struct at91_pmc *pmc = pll->pmc; ++ struct regmap *regmap = pll->regmap; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; +@@ -90,39 +81,34 @@ static int clk_pll_prepare(struct clk_hw *hw) + u32 mask = PLL_STATUS_MASK(id); + int offset = PLL_REG(id); + u8 out = 0; +- u32 pllr, icpr; ++ unsigned int pllr; ++ unsigned int status; + u8 div; + u16 mul; + +- pllr = pmc_read(pmc, offset); ++ regmap_read(regmap, offset, &pllr); + div = PLL_DIV(pllr); + mul = PLL_MUL(pllr, layout); + +- if ((pmc_read(pmc, AT91_PMC_SR) & mask) && ++ regmap_read(regmap, AT91_PMC_SR, &status); ++ if ((status & mask) && + (div == pll->div && mul == pll->mul)) + return 0; + + if (characteristics->out) + out = characteristics->out[pll->range]; +- if (characteristics->icpll) { +- icpr = pmc_read(pmc, AT91_PMC_PLLICPR) & ~PLL_ICPR_MASK(id); +- icpr |= (characteristics->icpll[pll->range] << +- PLL_ICPR_SHIFT(id)); +- pmc_write(pmc, AT91_PMC_PLLICPR, icpr); +- } + +- pllr &= ~layout->pllr_mask; +- pllr |= layout->pllr_mask & +- (pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | +- (out << PLL_OUT_SHIFT) | +- ((pll->mul & layout->mul_mask) << layout->mul_shift)); +- pmc_write(pmc, offset, pllr); +- +- while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { +- enable_irq(pll->irq); +- wait_event(pll->wait, +- pmc_read(pmc, AT91_PMC_SR) & mask); +- } ++ if (characteristics->icpll) ++ regmap_update_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), ++ characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id)); ++ ++ regmap_update_bits(regmap, offset, layout->pllr_mask, ++ pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | ++ (out << PLL_OUT_SHIFT) | ++ ((pll->mul & layout->mul_mask) << layout->mul_shift)); ++ ++ while (!clk_pll_ready(regmap, pll->id)) ++ cpu_relax(); + + return 0; + } +@@ -130,32 +116,35 @@ static int clk_pll_prepare(struct clk_hw *hw) + static int clk_pll_is_prepared(struct clk_hw *hw) + { + struct clk_pll *pll = to_clk_pll(hw); +- struct at91_pmc *pmc = pll->pmc; + +- return !!(pmc_read(pmc, AT91_PMC_SR) & +- PLL_STATUS_MASK(pll->id)); ++ return clk_pll_ready(pll->regmap, pll->id); + } + + static void clk_pll_unprepare(struct clk_hw *hw) + { + struct clk_pll *pll = to_clk_pll(hw); +- struct at91_pmc *pmc = pll->pmc; +- const struct clk_pll_layout *layout = pll->layout; +- int offset = PLL_REG(pll->id); +- u32 tmp = pmc_read(pmc, offset) & ~(layout->pllr_mask); ++ unsigned int mask = pll->layout->pllr_mask; + +- pmc_write(pmc, offset, tmp); ++ regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); + } + + static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_pll *pll = to_clk_pll(hw); ++ unsigned int pllr; ++ u16 mul; ++ u8 div; + +- if (!pll->div || !pll->mul) ++ regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); ++ ++ div = PLL_DIV(pllr); ++ mul = PLL_MUL(pllr, pll->layout); ++ ++ if (!div || !mul) + return 0; + +- return (parent_rate / pll->div) * (pll->mul + 1); ++ return (parent_rate / div) * (mul + 1); + } + + static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, +@@ -308,7 +297,7 @@ static const struct clk_ops pll_ops = { + }; + + static struct clk * __init +-at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, ++at91_clk_register_pll(struct regmap *regmap, const char *name, + const char *parent_name, u8 id, + const struct clk_pll_layout *layout, + const struct clk_pll_characteristics *characteristics) +@@ -316,9 +305,8 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, + struct clk_pll *pll; + struct clk *clk = NULL; + struct clk_init_data init; +- int ret; + int offset = PLL_REG(id); +- u32 tmp; ++ unsigned int pllr; + + if (id > PLL_MAX_ID) + return ERR_PTR(-EINVAL); +@@ -337,23 +325,13 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, + pll->hw.init = &init; + pll->layout = layout; + pll->characteristics = characteristics; +- pll->pmc = pmc; +- pll->irq = irq; +- tmp = pmc_read(pmc, offset) & layout->pllr_mask; +- pll->div = PLL_DIV(tmp); +- pll->mul = PLL_MUL(tmp, layout); +- init_waitqueue_head(&pll->wait); +- irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); +- ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, +- id ? "clk-pllb" : "clk-plla", pll); +- if (ret) { +- kfree(pll); +- return ERR_PTR(ret); +- } ++ pll->regmap = regmap; ++ regmap_read(regmap, offset, &pllr); ++ pll->div = PLL_DIV(pllr); ++ pll->mul = PLL_MUL(pllr, layout); + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { +- free_irq(pll->irq, pll); + kfree(pll); + } + +@@ -483,12 +461,12 @@ out_free_characteristics: + } + + static void __init +-of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, ++of_at91_clk_pll_setup(struct device_node *np, + const struct clk_pll_layout *layout) + { + u32 id; +- unsigned int irq; + struct clk *clk; ++ struct regmap *regmap; + const char *parent_name; + const char *name = np->name; + struct clk_pll_characteristics *characteristics; +@@ -500,15 +478,15 @@ of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, + + of_property_read_string(np, "clock-output-names", &name); + +- characteristics = of_at91_clk_pll_get_characteristics(np); +- if (!characteristics) ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) + return; + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) ++ characteristics = of_at91_clk_pll_get_characteristics(np); ++ if (!characteristics) + return; + +- clk = at91_clk_register_pll(pmc, irq, name, parent_name, id, layout, ++ clk = at91_clk_register_pll(regmap, name, parent_name, id, layout, + characteristics); + if (IS_ERR(clk)) + goto out_free_characteristics; +@@ -520,26 +498,30 @@ out_free_characteristics: + kfree(characteristics); + } + +-void __init of_at91rm9200_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_pll_setup(struct device_node *np) + { +- of_at91_clk_pll_setup(np, pmc, &at91rm9200_pll_layout); ++ of_at91_clk_pll_setup(np, &at91rm9200_pll_layout); + } ++CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll", ++ of_at91rm9200_clk_pll_setup); + +-void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np) + { +- of_at91_clk_pll_setup(np, pmc, &at91sam9g45_pll_layout); ++ of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout); + } ++CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll", ++ of_at91sam9g45_clk_pll_setup); + +-void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np) + { +- of_at91_clk_pll_setup(np, pmc, &at91sam9g20_pllb_layout); ++ of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout); + } ++CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb", ++ of_at91sam9g20_clk_pllb_setup); + +-void __init of_sama5d3_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_sama5d3_clk_pll_setup(struct device_node *np) + { +- of_at91_clk_pll_setup(np, pmc, &sama5d3_pll_layout); ++ of_at91_clk_pll_setup(np, &sama5d3_pll_layout); + } ++CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll", ++ of_sama5d3_clk_pll_setup); +diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c +index ea22656..2bed264 100644 +--- a/drivers/clk/at91/clk-plldiv.c ++++ b/drivers/clk/at91/clk-plldiv.c +@@ -12,8 +12,8 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -21,16 +21,18 @@ + + struct clk_plldiv { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_plldiv *plldiv = to_clk_plldiv(hw); +- struct at91_pmc *pmc = plldiv->pmc; ++ unsigned int mckr; + +- if (pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_PLLADIV2) ++ regmap_read(plldiv->regmap, AT91_PMC_MCKR, &mckr); ++ ++ if (mckr & AT91_PMC_PLLADIV2) + return parent_rate / 2; + + return parent_rate; +@@ -57,18 +59,12 @@ static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { + struct clk_plldiv *plldiv = to_clk_plldiv(hw); +- struct at91_pmc *pmc = plldiv->pmc; +- u32 tmp; + +- if (parent_rate != rate && (parent_rate / 2) != rate) ++ if ((parent_rate != rate) && (parent_rate / 2 != rate)) + return -EINVAL; + +- pmc_lock(pmc); +- tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_PLLADIV2; +- if ((parent_rate / 2) == rate) +- tmp |= AT91_PMC_PLLADIV2; +- pmc_write(pmc, AT91_PMC_MCKR, tmp); +- pmc_unlock(pmc); ++ regmap_update_bits(plldiv->regmap, AT91_PMC_MCKR, AT91_PMC_PLLADIV2, ++ parent_rate != rate ? AT91_PMC_PLLADIV2 : 0); + + return 0; + } +@@ -80,7 +76,7 @@ static const struct clk_ops plldiv_ops = { + }; + + static struct clk * __init +-at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, ++at91_clk_register_plldiv(struct regmap *regmap, const char *name, + const char *parent_name) + { + struct clk_plldiv *plldiv; +@@ -98,7 +94,7 @@ at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, + init.flags = CLK_SET_RATE_GATE; + + plldiv->hw.init = &init; +- plldiv->pmc = pmc; ++ plldiv->regmap = regmap; + + clk = clk_register(NULL, &plldiv->hw); + +@@ -109,27 +105,27 @@ at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, + } + + static void __init +-of_at91_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc) ++of_at91sam9x5_clk_plldiv_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_name; + const char *name = np->name; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91_clk_register_plldiv(pmc, name, parent_name); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; + ++ clk = at91_clk_register_plldiv(regmap, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + } +- +-void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, +- struct at91_pmc *pmc) +-{ +- of_at91_clk_plldiv_setup(np, pmc); +-} ++CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv", ++ of_at91sam9x5_clk_plldiv_setup); +diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c +index 14b270b..bc0be62 100644 +--- a/drivers/clk/at91/clk-programmable.c ++++ b/drivers/clk/at91/clk-programmable.c +@@ -12,10 +12,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -24,6 +22,7 @@ + + #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) + #define PROG_PRES_MASK 0x7 ++#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) + #define PROG_MAX_RM9200_CSS 3 + + struct clk_programmable_layout { +@@ -34,7 +33,7 @@ struct clk_programmable_layout { + + struct clk_programmable { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + u8 id; + const struct clk_programmable_layout *layout; + }; +@@ -44,14 +43,12 @@ struct clk_programmable { + static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- u32 pres; + struct clk_programmable *prog = to_clk_programmable(hw); +- struct at91_pmc *pmc = prog->pmc; +- const struct clk_programmable_layout *layout = prog->layout; ++ unsigned int pckr; ++ ++ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); + +- pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) & +- PROG_PRES_MASK; +- return parent_rate >> pres; ++ return parent_rate >> PROG_PRES(prog->layout, pckr); + } + + static int clk_programmable_determine_rate(struct clk_hw *hw, +@@ -101,36 +98,36 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) + { + struct clk_programmable *prog = to_clk_programmable(hw); + const struct clk_programmable_layout *layout = prog->layout; +- struct at91_pmc *pmc = prog->pmc; +- u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask; ++ unsigned int mask = layout->css_mask; ++ unsigned int pckr = 0; + + if (layout->have_slck_mck) +- tmp &= AT91_PMC_CSSMCK_MCK; ++ mask |= AT91_PMC_CSSMCK_MCK; + + if (index > layout->css_mask) { +- if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { +- tmp |= AT91_PMC_CSSMCK_MCK; +- return 0; +- } else { ++ if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck) + return -EINVAL; +- } ++ ++ pckr |= AT91_PMC_CSSMCK_MCK; + } + +- pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index); ++ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr); ++ + return 0; + } + + static u8 clk_programmable_get_parent(struct clk_hw *hw) + { +- u32 tmp; +- u8 ret; + struct clk_programmable *prog = to_clk_programmable(hw); +- struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; ++ unsigned int pckr; ++ u8 ret; ++ ++ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); ++ ++ ret = pckr & layout->css_mask; + +- tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); +- ret = tmp & layout->css_mask; +- if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret) ++ if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret) + ret = PROG_MAX_RM9200_CSS + 1; + + return ret; +@@ -140,26 +137,27 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { + struct clk_programmable *prog = to_clk_programmable(hw); +- struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + unsigned long div = parent_rate / rate; ++ unsigned int pckr; + int shift = 0; +- u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & +- ~(PROG_PRES_MASK << layout->pres_shift); ++ ++ regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); + + if (!div) + return -EINVAL; + + shift = fls(div) - 1; + +- if (div != (1<= PROG_PRES_MASK) + return -EINVAL; + +- pmc_write(pmc, AT91_PMC_PCKR(prog->id), +- tmp | (shift << layout->pres_shift)); ++ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), ++ PROG_PRES_MASK << layout->pres_shift, ++ shift << layout->pres_shift); + + return 0; + } +@@ -173,7 +171,7 @@ static const struct clk_ops programmable_ops = { + }; + + static struct clk * __init +-at91_clk_register_programmable(struct at91_pmc *pmc, ++at91_clk_register_programmable(struct regmap *regmap, + const char *name, const char **parent_names, + u8 num_parents, u8 id, + const struct clk_programmable_layout *layout) +@@ -198,7 +196,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, + prog->id = id; + prog->layout = layout; + prog->hw.init = &init; +- prog->pmc = pmc; ++ prog->regmap = regmap; + + clk = clk_register(NULL, &prog->hw); + if (IS_ERR(clk)) +@@ -226,7 +224,7 @@ static const struct clk_programmable_layout at91sam9x5_programmable_layout = { + }; + + static void __init +-of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, ++of_at91_clk_prog_setup(struct device_node *np, + const struct clk_programmable_layout *layout) + { + int num; +@@ -236,6 +234,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + const char *parent_names[PROG_SOURCE_MAX]; + const char *name; + struct device_node *progclknp; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX) +@@ -247,6 +246,10 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + if (!num || num > (PROG_ID_MAX + 1)) + return; + ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ + for_each_child_of_node(np, progclknp) { + if (of_property_read_u32(progclknp, "reg", &id)) + continue; +@@ -254,7 +257,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + if (of_property_read_string(np, "clock-output-names", &name)) + name = progclknp->name; + +- clk = at91_clk_register_programmable(pmc, name, ++ clk = at91_clk_register_programmable(regmap, name, + parent_names, num_parents, + id, layout); + if (IS_ERR(clk)) +@@ -265,20 +268,23 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + } + + +-void __init of_at91rm9200_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_prog_setup(struct device_node *np) + { +- of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); ++ of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout); + } ++CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable", ++ of_at91rm9200_clk_prog_setup); + +-void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np) + { +- of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); ++ of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout); + } ++CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable", ++ of_at91sam9g45_clk_prog_setup); + +-void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np) + { +- of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); ++ of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout); + } ++CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable", ++ of_at91sam9x5_clk_prog_setup); +diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c +index d0d5076..221c096 100644 +--- a/drivers/clk/at91/clk-slow.c ++++ b/drivers/clk/at91/clk-slow.c +@@ -13,17 +13,11 @@ + #include + #include + #include +-#include + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + #include "sckc.h" +@@ -59,7 +53,7 @@ struct clk_slow_rc_osc { + + struct clk_sam9260_slow { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) +@@ -393,8 +387,11 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, + static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) + { + struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); ++ unsigned int status; + +- return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL); ++ regmap_read(slowck->regmap, AT91_PMC_SR, &status); ++ ++ return status & AT91_PMC_OSCSEL ? 1 : 0; + } + + static const struct clk_ops sam9260_slow_ops = { +@@ -402,7 +399,7 @@ static const struct clk_ops sam9260_slow_ops = { + }; + + static struct clk * __init +-at91_clk_register_sam9260_slow(struct at91_pmc *pmc, ++at91_clk_register_sam9260_slow(struct regmap *regmap, + const char *name, + const char **parent_names, + int num_parents) +@@ -411,7 +408,7 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, + struct clk *clk = NULL; + struct clk_init_data init; + +- if (!pmc || !name) ++ if (!name) + return ERR_PTR(-EINVAL); + + if (!parent_names || !num_parents) +@@ -428,7 +425,7 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, + init.flags = 0; + + slowck->hw.init = &init; +- slowck->pmc = pmc; ++ slowck->regmap = regmap; + + clk = clk_register(NULL, &slowck->hw); + if (IS_ERR(clk)) +@@ -439,29 +436,34 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, + return clk; + } + +-void __init of_at91sam9260_clk_slow_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9260_clk_slow_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_names[2]; + int num_parents; + const char *name = np->name; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents != 2) + return; + + of_clk_parent_fill(np, parent_names, num_parents); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91_clk_register_sam9260_slow(pmc, name, parent_names, ++ clk = at91_clk_register_sam9260_slow(regmap, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow", ++ of_at91sam9260_clk_slow_setup); + + /* + * FIXME: All slow clk users are not properly claiming it (get + prepare + +diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c +index a7f8501..e6948a5 100644 +--- a/drivers/clk/at91/clk-smd.c ++++ b/drivers/clk/at91/clk-smd.c +@@ -12,8 +12,8 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -24,7 +24,7 @@ + + struct at91sam9x5_clk_smd { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + #define to_at91sam9x5_clk_smd(hw) \ +@@ -33,13 +33,13 @@ struct at91sam9x5_clk_smd { + static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- u32 tmp; +- u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); +- struct at91_pmc *pmc = smd->pmc; ++ unsigned int smdr; ++ u8 smddiv; ++ ++ regmap_read(smd->regmap, AT91_PMC_SMD, &smdr); ++ smddiv = (smdr & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; + +- tmp = pmc_read(pmc, AT91_PMC_SMD); +- smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); + } + +@@ -67,40 +67,38 @@ static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + + static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) + { +- u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); +- struct at91_pmc *pmc = smd->pmc; + + if (index > 1) + return -EINVAL; +- tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS; +- if (index) +- tmp |= AT91_PMC_SMDS; +- pmc_write(pmc, AT91_PMC_SMD, tmp); ++ ++ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMDS, ++ index ? AT91_PMC_SMDS : 0); ++ + return 0; + } + + static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) + { + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); +- struct at91_pmc *pmc = smd->pmc; ++ unsigned int smdr; + +- return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS; ++ regmap_read(smd->regmap, AT91_PMC_SMD, &smdr); ++ ++ return smdr & AT91_PMC_SMDS; + } + + static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +- u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); +- struct at91_pmc *pmc = smd->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1)) + return -EINVAL; +- tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV; +- tmp |= (div - 1) << SMD_DIV_SHIFT; +- pmc_write(pmc, AT91_PMC_SMD, tmp); ++ ++ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMD_DIV, ++ (div - 1) << SMD_DIV_SHIFT); + + return 0; + } +@@ -114,7 +112,7 @@ static const struct clk_ops at91sam9x5_smd_ops = { + }; + + static struct clk * __init +-at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, ++at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, + const char **parent_names, u8 num_parents) + { + struct at91sam9x5_clk_smd *smd; +@@ -132,7 +130,7 @@ at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + smd->hw.init = &init; +- smd->pmc = pmc; ++ smd->regmap = regmap; + + clk = clk_register(NULL, &smd->hw); + if (IS_ERR(clk)) +@@ -141,13 +139,13 @@ at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, + return clk; + } + +-void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np) + { + struct clk *clk; + int num_parents; + const char *parent_names[SMD_SOURCE_MAX]; + const char *name = np->name; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX) +@@ -157,10 +155,16 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91sam9x5_clk_register_smd(pmc, name, parent_names, ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ ++ clk = at91sam9x5_clk_register_smd(regmap, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd", ++ of_at91sam9x5_clk_smd_setup); +diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c +index 3f53143..8f35d81 100644 +--- a/drivers/clk/at91/clk-system.c ++++ b/drivers/clk/at91/clk-system.c +@@ -12,13 +12,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -29,9 +24,7 @@ + #define to_clk_system(hw) container_of(hw, struct clk_system, hw) + struct clk_system { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + u8 id; + }; + +@@ -39,58 +32,54 @@ static inline int is_pck(int id) + { + return (id >= 8) && (id <= 15); + } +-static irqreturn_t clk_system_irq_handler(int irq, void *dev_id) ++ ++static inline bool clk_system_ready(struct regmap *regmap, int id) + { +- struct clk_system *sys = (struct clk_system *)dev_id; ++ unsigned int status; + +- wake_up(&sys->wait); +- disable_irq_nosync(sys->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & (1 << id) ? 1 : 0; + } + + static int clk_system_prepare(struct clk_hw *hw) + { + struct clk_system *sys = to_clk_system(hw); +- struct at91_pmc *pmc = sys->pmc; +- u32 mask = 1 << sys->id; + +- pmc_write(pmc, AT91_PMC_SCER, mask); ++ regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id); + + if (!is_pck(sys->id)) + return 0; + +- while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { +- if (sys->irq) { +- enable_irq(sys->irq); +- wait_event(sys->wait, +- pmc_read(pmc, AT91_PMC_SR) & mask); +- } else +- cpu_relax(); +- } ++ while (!clk_system_ready(sys->regmap, sys->id)) ++ cpu_relax(); ++ + return 0; + } + + static void clk_system_unprepare(struct clk_hw *hw) + { + struct clk_system *sys = to_clk_system(hw); +- struct at91_pmc *pmc = sys->pmc; + +- pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); ++ regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id); + } + + static int clk_system_is_prepared(struct clk_hw *hw) + { + struct clk_system *sys = to_clk_system(hw); +- struct at91_pmc *pmc = sys->pmc; ++ unsigned int status; ++ ++ regmap_read(sys->regmap, AT91_PMC_SCSR, &status); + +- if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id))) ++ if (!(status & (1 << sys->id))) + return 0; + + if (!is_pck(sys->id)) + return 1; + +- return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id)); ++ regmap_read(sys->regmap, AT91_PMC_SR, &status); ++ ++ return status & (1 << sys->id) ? 1 : 0; + } + + static const struct clk_ops system_ops = { +@@ -100,13 +89,12 @@ static const struct clk_ops system_ops = { + }; + + static struct clk * __init +-at91_clk_register_system(struct at91_pmc *pmc, const char *name, +- const char *parent_name, u8 id, int irq) ++at91_clk_register_system(struct regmap *regmap, const char *name, ++ const char *parent_name, u8 id) + { + struct clk_system *sys; + struct clk *clk = NULL; + struct clk_init_data init; +- int ret; + + if (!parent_name || id > SYSTEM_MAX_ID) + return ERR_PTR(-EINVAL); +@@ -123,44 +111,33 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, + + sys->id = id; + sys->hw.init = &init; +- sys->pmc = pmc; +- sys->irq = irq; +- if (irq) { +- init_waitqueue_head(&sys->wait); +- irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); +- ret = request_irq(sys->irq, clk_system_irq_handler, +- IRQF_TRIGGER_HIGH, name, sys); +- if (ret) { +- kfree(sys); +- return ERR_PTR(ret); +- } +- } ++ sys->regmap = regmap; + + clk = clk_register(NULL, &sys->hw); +- if (IS_ERR(clk)) { +- if (irq) +- free_irq(sys->irq, sys); ++ if (IS_ERR(clk)) + kfree(sys); +- } + + return clk; + } + +-static void __init +-of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) + { + int num; +- int irq = 0; + u32 id; + struct clk *clk; + const char *name; + struct device_node *sysclknp; + const char *parent_name; ++ struct regmap *regmap; + + num = of_get_child_count(np); + if (num > (SYSTEM_MAX_ID + 1)) + return; + ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ + for_each_child_of_node(np, sysclknp) { + if (of_property_read_u32(sysclknp, "reg", &id)) + continue; +@@ -168,21 +145,14 @@ of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) + if (of_property_read_string(np, "clock-output-names", &name)) + name = sysclknp->name; + +- if (is_pck(id)) +- irq = irq_of_parse_and_map(sysclknp, 0); +- + parent_name = of_clk_get_parent_name(sysclknp, 0); + +- clk = at91_clk_register_system(pmc, name, parent_name, id, irq); ++ clk = at91_clk_register_system(regmap, name, parent_name, id); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); + } + } +- +-void __init of_at91rm9200_clk_sys_setup(struct device_node *np, +- struct at91_pmc *pmc) +-{ +- of_at91_clk_sys_setup(np, pmc); +-} ++CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system", ++ of_at91rm9200_clk_sys_setup); +diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c +index 8ab8502..650ca45 100644 +--- a/drivers/clk/at91/clk-usb.c ++++ b/drivers/clk/at91/clk-usb.c +@@ -12,8 +12,8 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -27,7 +27,7 @@ + + struct at91sam9x5_clk_usb { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + }; + + #define to_at91sam9x5_clk_usb(hw) \ +@@ -35,7 +35,7 @@ struct at91sam9x5_clk_usb { + + struct at91rm9200_clk_usb { + struct clk_hw hw; +- struct at91_pmc *pmc; ++ struct regmap *regmap; + u32 divisors[4]; + }; + +@@ -45,13 +45,12 @@ struct at91rm9200_clk_usb { + static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- u32 tmp; +- u8 usbdiv; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; ++ unsigned int usbr; ++ u8 usbdiv; + +- tmp = pmc_read(pmc, AT91_PMC_USB); +- usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; ++ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); ++ usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; + + return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); + } +@@ -109,33 +108,31 @@ static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw, + + static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) + { +- u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; + + if (index > 1) + return -EINVAL; +- tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS; +- if (index) +- tmp |= AT91_PMC_USBS; +- pmc_write(pmc, AT91_PMC_USB, tmp); ++ ++ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, ++ index ? AT91_PMC_USBS : 0); ++ + return 0; + } + + static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) + { + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; ++ unsigned int usbr; + +- return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS; ++ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); ++ ++ return usbr & AT91_PMC_USBS; + } + + static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +- u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; + unsigned long div; + + if (!rate) +@@ -145,9 +142,8 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + if (div > SAM9X5_USB_MAX_DIV + 1 || !div) + return -EINVAL; + +- tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; +- tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT; +- pmc_write(pmc, AT91_PMC_USB, tmp); ++ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV, ++ (div - 1) << SAM9X5_USB_DIV_SHIFT); + + return 0; + } +@@ -163,28 +159,28 @@ static const struct clk_ops at91sam9x5_usb_ops = { + static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) + { + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; + +- pmc_write(pmc, AT91_PMC_USB, +- pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS); ++ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, ++ AT91_PMC_USBS); ++ + return 0; + } + + static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) + { + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; + +- pmc_write(pmc, AT91_PMC_USB, +- pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS); ++ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0); + } + + static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) + { + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; ++ unsigned int usbr; + +- return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS); ++ regmap_read(usb->regmap, AT91_PMC_USB, &usbr); ++ ++ return usbr & AT91_PMC_USBS; + } + + static const struct clk_ops at91sam9n12_usb_ops = { +@@ -197,7 +193,7 @@ static const struct clk_ops at91sam9n12_usb_ops = { + }; + + static struct clk * __init +-at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, ++at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, + const char **parent_names, u8 num_parents) + { + struct at91sam9x5_clk_usb *usb; +@@ -216,7 +212,7 @@ at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, + CLK_SET_RATE_PARENT; + + usb->hw.init = &init; +- usb->pmc = pmc; ++ usb->regmap = regmap; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) +@@ -226,7 +222,7 @@ at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, + } + + static struct clk * __init +-at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, ++at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, + const char *parent_name) + { + struct at91sam9x5_clk_usb *usb; +@@ -244,7 +240,7 @@ at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, + init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; + + usb->hw.init = &init; +- usb->pmc = pmc; ++ usb->regmap = regmap; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) +@@ -257,12 +253,12 @@ static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; +- u32 tmp; ++ unsigned int pllbr; + u8 usbdiv; + +- tmp = pmc_read(pmc, AT91_CKGR_PLLBR); +- usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; ++ regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr); ++ ++ usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; + if (usb->divisors[usbdiv]) + return parent_rate / usb->divisors[usbdiv]; + +@@ -310,10 +306,8 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, + static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +- u32 tmp; + int i; + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); +- struct at91_pmc *pmc = usb->pmc; + unsigned long div; + + if (!rate) +@@ -323,10 +317,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + + for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { + if (usb->divisors[i] == div) { +- tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & +- ~AT91_PMC_USBDIV; +- tmp |= i << RM9200_USB_DIV_SHIFT; +- pmc_write(pmc, AT91_CKGR_PLLBR, tmp); ++ regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR, ++ AT91_PMC_USBDIV, ++ i << RM9200_USB_DIV_SHIFT); ++ + return 0; + } + } +@@ -341,7 +335,7 @@ static const struct clk_ops at91rm9200_usb_ops = { + }; + + static struct clk * __init +-at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, ++at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, + const char *parent_name, const u32 *divisors) + { + struct at91rm9200_clk_usb *usb; +@@ -359,7 +353,7 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, + init.flags = CLK_SET_RATE_PARENT; + + usb->hw.init = &init; +- usb->pmc = pmc; ++ usb->regmap = regmap; + memcpy(usb->divisors, divisors, sizeof(usb->divisors)); + + clk = clk_register(NULL, &usb->hw); +@@ -369,13 +363,13 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, + return clk; + } + +-void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np) + { + struct clk *clk; + int num_parents; + const char *parent_names[USB_SOURCE_MAX]; + const char *name = np->name; ++ struct regmap *regmap; + + num_parents = of_clk_get_parent_count(np); + if (num_parents <= 0 || num_parents > USB_SOURCE_MAX) +@@ -385,19 +379,26 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ ++ clk = at91sam9x5_clk_register_usb(regmap, name, parent_names, ++ num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb", ++ of_at91sam9x5_clk_usb_setup); + +-void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_name; + const char *name = np->name; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) +@@ -405,20 +406,26 @@ void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91sam9n12_clk_register_usb(pmc, name, parent_name); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ ++ clk = at91sam9n12_clk_register_usb(regmap, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb", ++ of_at91sam9n12_clk_usb_setup); + +-void __init of_at91rm9200_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc) ++static void __init of_at91rm9200_clk_usb_setup(struct device_node *np) + { + struct clk *clk; + const char *parent_name; + const char *name = np->name; + u32 divisors[4] = {0, 0, 0, 0}; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) +@@ -430,9 +437,15 @@ void __init of_at91rm9200_clk_usb_setup(struct device_node *np, + + of_property_read_string(np, "clock-output-names", &name); + +- clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors); ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) ++ return; ++ ++ clk = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + } ++CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb", ++ of_at91rm9200_clk_usb_setup); +diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c +index ca561e9..61fcf39 100644 +--- a/drivers/clk/at91/clk-utmi.c ++++ b/drivers/clk/at91/clk-utmi.c +@@ -11,14 +11,9 @@ + #include + #include + #include +-#include +-#include + #include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include "pmc.h" + +@@ -26,37 +21,30 @@ + + struct clk_utmi { + struct clk_hw hw; +- struct at91_pmc *pmc; +- unsigned int irq; +- wait_queue_head_t wait; ++ struct regmap *regmap; + }; + + #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) + +-static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) ++static inline bool clk_utmi_ready(struct regmap *regmap) + { +- struct clk_utmi *utmi = (struct clk_utmi *)dev_id; ++ unsigned int status; + +- wake_up(&utmi->wait); +- disable_irq_nosync(utmi->irq); ++ regmap_read(regmap, AT91_PMC_SR, &status); + +- return IRQ_HANDLED; ++ return status & AT91_PMC_LOCKU; + } + + static int clk_utmi_prepare(struct clk_hw *hw) + { + struct clk_utmi *utmi = to_clk_utmi(hw); +- struct at91_pmc *pmc = utmi->pmc; +- u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | +- AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; ++ unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | ++ AT91_PMC_BIASEN; + +- pmc_write(pmc, AT91_CKGR_UCKR, tmp); ++ regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr); + +- while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) { +- enable_irq(utmi->irq); +- wait_event(utmi->wait, +- pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); +- } ++ while (!clk_utmi_ready(utmi->regmap)) ++ cpu_relax(); + + return 0; + } +@@ -64,18 +52,15 @@ static int clk_utmi_prepare(struct clk_hw *hw) + static int clk_utmi_is_prepared(struct clk_hw *hw) + { + struct clk_utmi *utmi = to_clk_utmi(hw); +- struct at91_pmc *pmc = utmi->pmc; + +- return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); ++ return clk_utmi_ready(utmi->regmap); + } + + static void clk_utmi_unprepare(struct clk_hw *hw) + { + struct clk_utmi *utmi = to_clk_utmi(hw); +- struct at91_pmc *pmc = utmi->pmc; +- u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN; + +- pmc_write(pmc, AT91_CKGR_UCKR, tmp); ++ regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0); + } + + static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, +@@ -93,10 +78,9 @@ static const struct clk_ops utmi_ops = { + }; + + static struct clk * __init +-at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, ++at91_clk_register_utmi(struct regmap *regmap, + const char *name, const char *parent_name) + { +- int ret; + struct clk_utmi *utmi; + struct clk *clk = NULL; + struct clk_init_data init; +@@ -112,52 +96,36 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, + init.flags = CLK_SET_RATE_GATE; + + utmi->hw.init = &init; +- utmi->pmc = pmc; +- utmi->irq = irq; +- init_waitqueue_head(&utmi->wait); +- irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); +- ret = request_irq(utmi->irq, clk_utmi_irq_handler, +- IRQF_TRIGGER_HIGH, "clk-utmi", utmi); +- if (ret) { +- kfree(utmi); +- return ERR_PTR(ret); +- } ++ utmi->regmap = regmap; + + clk = clk_register(NULL, &utmi->hw); +- if (IS_ERR(clk)) { +- free_irq(utmi->irq, utmi); ++ if (IS_ERR(clk)) + kfree(utmi); +- } + + return clk; + } + +-static void __init +-of_at91_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc) ++static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) + { +- unsigned int irq; + struct clk *clk; + const char *parent_name; + const char *name = np->name; ++ struct regmap *regmap; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) ++ regmap = syscon_node_to_regmap(of_get_parent(np)); ++ if (IS_ERR(regmap)) + return; + +- clk = at91_clk_register_utmi(pmc, irq, name, parent_name); ++ clk = at91_clk_register_utmi(regmap, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + } +- +-void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, +- struct at91_pmc *pmc) +-{ +- of_at91_clk_utmi_setup(np, pmc); +-} ++CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi", ++ of_at91sam9x5_clk_utmi_setup); +diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c +index 8476b57..526df5b 100644 +--- a/drivers/clk/at91/pmc.c ++++ b/drivers/clk/at91/pmc.c +@@ -12,36 +12,13 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + + #include + + #include "pmc.h" + +-void __iomem *at91_pmc_base; +-EXPORT_SYMBOL_GPL(at91_pmc_base); +- +-void at91rm9200_idle(void) +-{ +- /* +- * Disable the processor clock. The processor will be automatically +- * re-enabled by an interrupt or by a reset. +- */ +- at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); +-} +- +-void at91sam9_idle(void) +-{ +- at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); +- cpu_do_idle(); +-} +- + int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range) + { +@@ -64,402 +41,3 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, + return 0; + } + EXPORT_SYMBOL_GPL(of_at91_get_clk_range); +- +-static void pmc_irq_mask(struct irq_data *d) +-{ +- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); +- +- pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq); +-} +- +-static void pmc_irq_unmask(struct irq_data *d) +-{ +- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); +- +- pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq); +-} +- +-static int pmc_irq_set_type(struct irq_data *d, unsigned type) +-{ +- if (type != IRQ_TYPE_LEVEL_HIGH) { +- pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static void pmc_irq_suspend(struct irq_data *d) +-{ +- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); +- +- pmc->imr = pmc_read(pmc, AT91_PMC_IMR); +- pmc_write(pmc, AT91_PMC_IDR, pmc->imr); +-} +- +-static void pmc_irq_resume(struct irq_data *d) +-{ +- struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); +- +- pmc_write(pmc, AT91_PMC_IER, pmc->imr); +-} +- +-static struct irq_chip pmc_irq = { +- .name = "PMC", +- .irq_disable = pmc_irq_mask, +- .irq_mask = pmc_irq_mask, +- .irq_unmask = pmc_irq_unmask, +- .irq_set_type = pmc_irq_set_type, +- .irq_suspend = pmc_irq_suspend, +- .irq_resume = pmc_irq_resume, +-}; +- +-static struct lock_class_key pmc_lock_class; +- +-static int pmc_irq_map(struct irq_domain *h, unsigned int virq, +- irq_hw_number_t hw) +-{ +- struct at91_pmc *pmc = h->host_data; +- +- irq_set_lockdep_class(virq, &pmc_lock_class); +- +- irq_set_chip_and_handler(virq, &pmc_irq, +- handle_level_irq); +- irq_set_chip_data(virq, pmc); +- +- return 0; +-} +- +-static int pmc_irq_domain_xlate(struct irq_domain *d, +- struct device_node *ctrlr, +- const u32 *intspec, unsigned int intsize, +- irq_hw_number_t *out_hwirq, +- unsigned int *out_type) +-{ +- struct at91_pmc *pmc = d->host_data; +- const struct at91_pmc_caps *caps = pmc->caps; +- +- if (WARN_ON(intsize < 1)) +- return -EINVAL; +- +- *out_hwirq = intspec[0]; +- +- if (!(caps->available_irqs & (1 << *out_hwirq))) +- return -EINVAL; +- +- *out_type = IRQ_TYPE_LEVEL_HIGH; +- +- return 0; +-} +- +-static const struct irq_domain_ops pmc_irq_ops = { +- .map = pmc_irq_map, +- .xlate = pmc_irq_domain_xlate, +-}; +- +-static irqreturn_t pmc_irq_handler(int irq, void *data) +-{ +- struct at91_pmc *pmc = (struct at91_pmc *)data; +- unsigned long sr; +- int n; +- +- sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR); +- if (!sr) +- return IRQ_NONE; +- +- for_each_set_bit(n, &sr, BITS_PER_LONG) +- generic_handle_irq(irq_find_mapping(pmc->irqdomain, n)); +- +- return IRQ_HANDLED; +-} +- +-static const struct at91_pmc_caps at91rm9200_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | +- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | +- AT91_PMC_PCK3RDY, +-}; +- +-static const struct at91_pmc_caps at91sam9260_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | +- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY, +-}; +- +-static const struct at91_pmc_caps at91sam9g45_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | +- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY, +-}; +- +-static const struct at91_pmc_caps at91sam9n12_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | +- AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | +- AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +-}; +- +-static const struct at91_pmc_caps at91sam9x5_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | +- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | +- AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +-}; +- +-static const struct at91_pmc_caps sama5d2_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | +- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | +- AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | +- AT91_PMC_CFDEV | AT91_PMC_GCKRDY, +-}; +- +-static const struct at91_pmc_caps sama5d3_caps = { +- .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | +- AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | +- AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | +- AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | +- AT91_PMC_CFDEV, +-}; +- +-static struct at91_pmc *__init at91_pmc_init(struct device_node *np, +- void __iomem *regbase, int virq, +- const struct at91_pmc_caps *caps) +-{ +- struct at91_pmc *pmc; +- +- if (!regbase || !virq || !caps) +- return NULL; +- +- at91_pmc_base = regbase; +- +- pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); +- if (!pmc) +- return NULL; +- +- spin_lock_init(&pmc->lock); +- pmc->regbase = regbase; +- pmc->virq = virq; +- pmc->caps = caps; +- +- pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc); +- +- if (!pmc->irqdomain) +- goto out_free_pmc; +- +- pmc_write(pmc, AT91_PMC_IDR, 0xffffffff); +- if (request_irq(pmc->virq, pmc_irq_handler, +- IRQF_SHARED | IRQF_COND_SUSPEND, "pmc", pmc)) +- goto out_remove_irqdomain; +- +- return pmc; +- +-out_remove_irqdomain: +- irq_domain_remove(pmc->irqdomain); +-out_free_pmc: +- kfree(pmc); +- +- return NULL; +-} +- +-static const struct of_device_id pmc_clk_ids[] __initconst = { +- /* Slow oscillator */ +- { +- .compatible = "atmel,at91sam9260-clk-slow", +- .data = of_at91sam9260_clk_slow_setup, +- }, +- /* Main clock */ +- { +- .compatible = "atmel,at91rm9200-clk-main-osc", +- .data = of_at91rm9200_clk_main_osc_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-main-rc-osc", +- .data = of_at91sam9x5_clk_main_rc_osc_setup, +- }, +- { +- .compatible = "atmel,at91rm9200-clk-main", +- .data = of_at91rm9200_clk_main_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-main", +- .data = of_at91sam9x5_clk_main_setup, +- }, +- /* PLL clocks */ +- { +- .compatible = "atmel,at91rm9200-clk-pll", +- .data = of_at91rm9200_clk_pll_setup, +- }, +- { +- .compatible = "atmel,at91sam9g45-clk-pll", +- .data = of_at91sam9g45_clk_pll_setup, +- }, +- { +- .compatible = "atmel,at91sam9g20-clk-pllb", +- .data = of_at91sam9g20_clk_pllb_setup, +- }, +- { +- .compatible = "atmel,sama5d3-clk-pll", +- .data = of_sama5d3_clk_pll_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-plldiv", +- .data = of_at91sam9x5_clk_plldiv_setup, +- }, +- /* Master clock */ +- { +- .compatible = "atmel,at91rm9200-clk-master", +- .data = of_at91rm9200_clk_master_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-master", +- .data = of_at91sam9x5_clk_master_setup, +- }, +- /* System clocks */ +- { +- .compatible = "atmel,at91rm9200-clk-system", +- .data = of_at91rm9200_clk_sys_setup, +- }, +- /* Peripheral clocks */ +- { +- .compatible = "atmel,at91rm9200-clk-peripheral", +- .data = of_at91rm9200_clk_periph_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-peripheral", +- .data = of_at91sam9x5_clk_periph_setup, +- }, +- /* Programmable clocks */ +- { +- .compatible = "atmel,at91rm9200-clk-programmable", +- .data = of_at91rm9200_clk_prog_setup, +- }, +- { +- .compatible = "atmel,at91sam9g45-clk-programmable", +- .data = of_at91sam9g45_clk_prog_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-programmable", +- .data = of_at91sam9x5_clk_prog_setup, +- }, +- /* UTMI clock */ +-#if defined(CONFIG_HAVE_AT91_UTMI) +- { +- .compatible = "atmel,at91sam9x5-clk-utmi", +- .data = of_at91sam9x5_clk_utmi_setup, +- }, +-#endif +- /* USB clock */ +-#if defined(CONFIG_HAVE_AT91_USB_CLK) +- { +- .compatible = "atmel,at91rm9200-clk-usb", +- .data = of_at91rm9200_clk_usb_setup, +- }, +- { +- .compatible = "atmel,at91sam9x5-clk-usb", +- .data = of_at91sam9x5_clk_usb_setup, +- }, +- { +- .compatible = "atmel,at91sam9n12-clk-usb", +- .data = of_at91sam9n12_clk_usb_setup, +- }, +-#endif +- /* SMD clock */ +-#if defined(CONFIG_HAVE_AT91_SMD) +- { +- .compatible = "atmel,at91sam9x5-clk-smd", +- .data = of_at91sam9x5_clk_smd_setup, +- }, +-#endif +-#if defined(CONFIG_HAVE_AT91_H32MX) +- { +- .compatible = "atmel,sama5d4-clk-h32mx", +- .data = of_sama5d4_clk_h32mx_setup, +- }, +-#endif +-#if defined(CONFIG_HAVE_AT91_GENERATED_CLK) +- { +- .compatible = "atmel,sama5d2-clk-generated", +- .data = of_sama5d2_clk_generated_setup, +- }, +-#endif +- { /*sentinel*/ } +-}; +- +-static void __init of_at91_pmc_setup(struct device_node *np, +- const struct at91_pmc_caps *caps) +-{ +- struct at91_pmc *pmc; +- struct device_node *childnp; +- void (*clk_setup)(struct device_node *, struct at91_pmc *); +- const struct of_device_id *clk_id; +- void __iomem *regbase = of_iomap(np, 0); +- int virq; +- +- if (!regbase) +- return; +- +- virq = irq_of_parse_and_map(np, 0); +- if (!virq) +- return; +- +- pmc = at91_pmc_init(np, regbase, virq, caps); +- if (!pmc) +- return; +- for_each_child_of_node(np, childnp) { +- clk_id = of_match_node(pmc_clk_ids, childnp); +- if (!clk_id) +- continue; +- clk_setup = clk_id->data; +- clk_setup(childnp, pmc); +- } +-} +- +-static void __init of_at91rm9200_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &at91rm9200_caps); +-} +-CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc", +- of_at91rm9200_pmc_setup); +- +-static void __init of_at91sam9260_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &at91sam9260_caps); +-} +-CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc", +- of_at91sam9260_pmc_setup); +- +-static void __init of_at91sam9g45_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &at91sam9g45_caps); +-} +-CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc", +- of_at91sam9g45_pmc_setup); +- +-static void __init of_at91sam9n12_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &at91sam9n12_caps); +-} +-CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc", +- of_at91sam9n12_pmc_setup); +- +-static void __init of_at91sam9x5_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &at91sam9x5_caps); +-} +-CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc", +- of_at91sam9x5_pmc_setup); +- +-static void __init of_sama5d2_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &sama5d2_caps); +-} +-CLK_OF_DECLARE(sama5d2_clk_pmc, "atmel,sama5d2-pmc", +- of_sama5d2_pmc_setup); +- +-static void __init of_sama5d3_pmc_setup(struct device_node *np) +-{ +- of_at91_pmc_setup(np, &sama5d3_caps); +-} +-CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc", +- of_sama5d3_pmc_setup); +diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h +index f657392..5771fff 100644 +--- a/drivers/clk/at91/pmc.h ++++ b/drivers/clk/at91/pmc.h +@@ -14,8 +14,11 @@ + + #include + #include ++#include + #include + ++extern spinlock_t pmc_pcr_lock; ++ + struct clk_range { + unsigned long min; + unsigned long max; +@@ -23,102 +26,7 @@ struct clk_range { + + #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} + +-struct at91_pmc_caps { +- u32 available_irqs; +-}; +- +-struct at91_pmc { +- void __iomem *regbase; +- int virq; +- spinlock_t lock; +- const struct at91_pmc_caps *caps; +- struct irq_domain *irqdomain; +- u32 imr; +-}; +- +-static inline void pmc_lock(struct at91_pmc *pmc) +-{ +- spin_lock(&pmc->lock); +-} +- +-static inline void pmc_unlock(struct at91_pmc *pmc) +-{ +- spin_unlock(&pmc->lock); +-} +- +-static inline u32 pmc_read(struct at91_pmc *pmc, int offset) +-{ +- return readl(pmc->regbase + offset); +-} +- +-static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) +-{ +- writel(value, pmc->regbase + offset); +-} +- + int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range); + +-void of_at91sam9260_clk_slow_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_main_osc_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91rm9200_clk_main_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_main_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9g45_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9g20_clk_pllb_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_sama5d3_clk_pll_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_plldiv_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_master_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_master_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_sys_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_periph_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_periph_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9g45_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_prog_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91sam9x5_clk_utmi_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91rm9200_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9x5_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc); +-void of_at91sam9n12_clk_usb_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_at91sam9x5_clk_smd_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_sama5d4_clk_h32mx_setup(struct device_node *np, +- struct at91_pmc *pmc); +- +-void of_sama5d2_clk_generated_setup(struct device_node *np, +- struct at91_pmc *pmc); +- + #endif /* __PMC_H_ */ +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 39bf582..6029313 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -890,8 +890,14 @@ static void bcm2835_pll_off(struct clk_hw *hw) + struct bcm2835_cprman *cprman = pll->cprman; + const struct bcm2835_pll_data *data = pll->data; + +- cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST); +- cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN); ++ spin_lock(&cprman->regs_lock); ++ cprman_write(cprman, data->cm_ctrl_reg, ++ cprman_read(cprman, data->cm_ctrl_reg) | ++ CM_PLL_ANARST); ++ cprman_write(cprman, data->a2w_ctrl_reg, ++ cprman_read(cprman, data->a2w_ctrl_reg) | ++ A2W_PLL_CTRL_PWRDN); ++ spin_unlock(&cprman->regs_lock); + } + + static int bcm2835_pll_on(struct clk_hw *hw) +@@ -901,6 +907,10 @@ static int bcm2835_pll_on(struct clk_hw *hw) + const struct bcm2835_pll_data *data = pll->data; + ktime_t timeout; + ++ cprman_write(cprman, data->a2w_ctrl_reg, ++ cprman_read(cprman, data->a2w_ctrl_reg) & ++ ~A2W_PLL_CTRL_PWRDN); ++ + /* Take the PLL out of reset. */ + cprman_write(cprman, data->cm_ctrl_reg, + cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST); +@@ -1068,10 +1078,12 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw) + struct bcm2835_cprman *cprman = divider->cprman; + const struct bcm2835_pll_divider_data *data = divider->data; + ++ spin_lock(&cprman->regs_lock); + cprman_write(cprman, data->cm_reg, + (cprman_read(cprman, data->cm_reg) & + ~data->load_mask) | data->hold_mask); + cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE); ++ spin_unlock(&cprman->regs_lock); + } + + static int bcm2835_pll_divider_on(struct clk_hw *hw) +@@ -1080,12 +1092,14 @@ static int bcm2835_pll_divider_on(struct clk_hw *hw) + struct bcm2835_cprman *cprman = divider->cprman; + const struct bcm2835_pll_divider_data *data = divider->data; + ++ spin_lock(&cprman->regs_lock); + cprman_write(cprman, data->a2w_reg, + cprman_read(cprman, data->a2w_reg) & + ~A2W_PLL_CHANNEL_DISABLE); + + cprman_write(cprman, data->cm_reg, + cprman_read(cprman, data->cm_reg) & ~data->hold_mask); ++ spin_unlock(&cprman->regs_lock); + + return 0; + } +@@ -1097,13 +1111,15 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw, + struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); + struct bcm2835_cprman *cprman = divider->cprman; + const struct bcm2835_pll_divider_data *data = divider->data; +- u32 cm; +- int ret; ++ u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS; + +- ret = clk_divider_ops.set_rate(hw, rate, parent_rate); +- if (ret) +- return ret; ++ div = DIV_ROUND_UP_ULL(parent_rate, rate); ++ ++ div = min(div, max_div); ++ if (div == max_div) ++ div = 0; + ++ cprman_write(cprman, data->a2w_reg, div); + cm = cprman_read(cprman, data->cm_reg); + cprman_write(cprman, data->cm_reg, cm | data->load_mask); + cprman_write(cprman, data->cm_reg, cm & ~data->load_mask); +@@ -1165,8 +1181,9 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, + div &= ~unused_frac_mask; + } + +- /* Clamp to the limits. */ +- div = max(div, unused_frac_mask + 1); ++ /* clamp to min divider of 1 */ ++ div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS); ++ /* clamp to the highest possible fractional divider */ + div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, + CM_DIV_FRAC_BITS - data->frac_bits)); + +diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c +index 3ace102..bbf206e 100644 +--- a/drivers/clk/clk-divider.c ++++ b/drivers/clk/clk-divider.c +@@ -422,6 +422,12 @@ const struct clk_ops clk_divider_ops = { + }; + EXPORT_SYMBOL_GPL(clk_divider_ops); + ++const struct clk_ops clk_divider_ro_ops = { ++ .recalc_rate = clk_divider_recalc_rate, ++ .round_rate = clk_divider_round_rate, ++}; ++EXPORT_SYMBOL_GPL(clk_divider_ro_ops); ++ + static struct clk *_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, +@@ -445,7 +451,10 @@ static struct clk *_register_divider(struct device *dev, const char *name, + return ERR_PTR(-ENOMEM); + + init.name = name; +- init.ops = &clk_divider_ops; ++ if (clk_divider_flags & CLK_DIVIDER_READ_ONLY) ++ init.ops = &clk_divider_ro_ops; ++ else ++ init.ops = &clk_divider_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = (parent_name ? &parent_name: NULL); + init.num_parents = (parent_name ? 1 : 0); +diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c +index a71d24c..b0978d3 100644 +--- a/drivers/clk/imx/clk-imx35.c ++++ b/drivers/clk/imx/clk-imx35.c +@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"}; + static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"}; + + enum mx35_clks { +- ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, ++ ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, + arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel, + esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre, + spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre, +@@ -79,7 +79,7 @@ enum mx35_clks { + rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate, + ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate, + wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate, +- gpu2d_gate, clk_max ++ gpu2d_gate, ckil, clk_max + }; + + static struct clk *clk[clk_max]; +diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c +index d3366be..ceb8703 100644 +--- a/drivers/clk/imx/clk-imx6q.c ++++ b/drivers/clk/imx/clk-imx6q.c +@@ -507,6 +507,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + ++ clk_register_clkdev(clk[IMX6QDL_CLK_GPT_3M], "gpt_3m", "imx-gpt.0"); + clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL); + + if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || +@@ -515,6 +516,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + imx_clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); + } + ++ imx_clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000); ++ if (clk_on_imx6dl()) ++ imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); ++ + imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); + imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); + imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); +@@ -524,8 +529,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]); + imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]); + +- imx_clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000); +- imx_clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); + imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_ALT_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]); + imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_SEL], clk[IMX6QDL_CLK_AXI_ALT_SEL]); + /* set epdc/pxp axi clock to 200Mhz */ +@@ -543,6 +546,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + */ + imx_clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]); + ++ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) ++ imx_clk_prepare_enable(clk[clks_init_on[i]]); ++ ++ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { ++ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]); ++ imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]); ++ } ++ + /* gpu clock initilazation */ + /* + * On mx6dl, 2d core clock sources(sel, podf) is from 3d +@@ -588,14 +599,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + + imx_register_uart_clocks(uart_clks); + +- for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) +- imx_clk_prepare_enable(clk[clks_init_on[i]]); +- +- if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { +- imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]); +- imx_clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]); +- } +- + imx_clk_set_parent(clk[IMX6QDL_CLK_VPU_AXI_SEL], clk[IMX6QDL_CLK_PLL2_PFD0_352M]); + + if (clk_on_imx6dl()) +diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c +index c83ae13..d920d41 100644 +--- a/drivers/clk/meson/clkc.c ++++ b/drivers/clk/meson/clkc.c +@@ -198,7 +198,7 @@ meson_clk_register_fixed_rate(const struct clk_conf *clk_conf, + } + + void __init meson_clk_register_clks(const struct clk_conf *clk_confs, +- size_t nr_confs, ++ unsigned int nr_confs, + void __iomem *clk_base) + { + unsigned int i; +diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c +index 13aabbb..558da89 100644 +--- a/drivers/clk/nxp/clk-lpc18xx-ccu.c ++++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c +@@ -222,7 +222,7 @@ static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *bran + div->width = 1; + + div_hw = &div->hw; +- div_ops = &clk_divider_ops; ++ div_ops = &clk_divider_ro_ops; + } + + branch->gate.reg = branch->offset + reg_base; +diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c +index d0a0313..2e7f03d 100644 +--- a/drivers/clk/qcom/gcc-msm8916.c ++++ b/drivers/clk/qcom/gcc-msm8916.c +@@ -2346,6 +2346,7 @@ static struct clk_branch gcc_crypto_ahb_clk = { + "pcnoc_bfdcd_clk_src", + }, + .num_parents = 1, ++ .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +@@ -2381,6 +2382,7 @@ static struct clk_branch gcc_crypto_clk = { + "crypto_clk_src", + }, + .num_parents = 1, ++ .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c +index 66c18bc..bdc4b2d 100644 +--- a/drivers/clk/qcom/gcc-msm8960.c ++++ b/drivers/clk/qcom/gcc-msm8960.c +@@ -2753,7 +2753,7 @@ static struct clk_rcg ce3_src = { + }, + .freq_tbl = clk_tbl_ce3, + .clkr = { +- .enable_reg = 0x2c08, ++ .enable_reg = 0x36c0, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "ce3_src", +@@ -2769,7 +2769,7 @@ static struct clk_branch ce3_core_clk = { + .halt_reg = 0x2fdc, + .halt_bit = 5, + .clkr = { +- .enable_reg = 0x36c4, ++ .enable_reg = 0x36cc, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "ce3_core_clk", +diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c +index abb4760..fe728f8 100644 +--- a/drivers/clk/rockchip/clk-rk3188.c ++++ b/drivers/clk/rockchip/clk-rk3188.c +@@ -718,6 +718,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { + "hclk_peri", + "pclk_cpu", + "pclk_peri", ++ "hclk_cpubus" + }; + + static void __init rk3188_common_clk_init(struct device_node *np) +diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c +index 7e6b783..1b14869 100644 +--- a/drivers/clk/rockchip/clk-rk3368.c ++++ b/drivers/clk/rockchip/clk-rk3368.c +@@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { + .core_reg = RK3368_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, +- .mux_core_shift = 15, ++ .mux_core_shift = 7, + }; + + static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { +@@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { + } + + static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = { +- RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6), +- RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5), +- RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5), +- RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4), +- RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4), +- RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3), +- RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3), +- RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2), +- RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2), +- RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2), ++ RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5), ++ RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4), ++ RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4), ++ RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3), ++ RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3), ++ RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2), ++ RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2), ++ RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1), ++ RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1), ++ RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1), + }; + + static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = { +- RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7), +- RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6), +- RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6), +- RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5), +- RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5), +- RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4), +- RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3), +- RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3), +- RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2), +- RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2), ++ RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6), ++ RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5), ++ RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5), ++ RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4), ++ RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4), ++ RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3), ++ RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2), ++ RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2), ++ RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1), ++ RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1), + }; + + static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { +@@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { + * Clock-Architecture Diagram 3 + */ + +- COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0, ++ COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0, + RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3368_CLKGATE_CON(4), 6, GFLAGS), +- COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0, ++ COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0, + RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3368_CLKGATE_CON(4), 7, GFLAGS), + +@@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { + GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0, + RK3368_CLKGATE_CON(4), 13, GFLAGS), + GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0, +- RK3368_CLKGATE_CON(5), 12, GFLAGS), ++ RK3368_CLKGATE_CON(4), 12, GFLAGS), + + COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, + RK3368_CLKSEL_CON(21), 15, 1, MFLAGS, +diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c +index be6c7fd..9b6c818 100644 +--- a/drivers/clk/rockchip/clk.c ++++ b/drivers/clk/rockchip/clk.c +@@ -70,7 +70,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, + if (gate_offset >= 0) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) +- return ERR_PTR(-ENOMEM); ++ goto err_gate; + + gate->flags = gate_flags; + gate->reg = base + gate_offset; +@@ -82,7 +82,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, + if (div_width > 0) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) +- return ERR_PTR(-ENOMEM); ++ goto err_div; + + div->flags = div_flags; + div->reg = base + muxdiv_offset; +@@ -90,7 +90,9 @@ static struct clk *rockchip_clk_register_branch(const char *name, + div->width = div_width; + div->lock = lock; + div->table = div_table; +- div_ops = &clk_divider_ops; ++ div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) ++ ? &clk_divider_ro_ops ++ : &clk_divider_ops; + } + + clk = clk_register_composite(NULL, name, parent_names, num_parents, +@@ -100,6 +102,11 @@ static struct clk *rockchip_clk_register_branch(const char *name, + flags); + + return clk; ++err_div: ++ kfree(gate); ++err_gate: ++ kfree(mux); ++ return ERR_PTR(-ENOMEM); + } + + static struct clk *rockchip_clk_register_frac_branch(const char *name, +diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c +index a1cdef6..897c36c 100644 +--- a/drivers/clk/versatile/clk-sp810.c ++++ b/drivers/clk/versatile/clk-sp810.c +@@ -92,6 +92,7 @@ static void __init clk_sp810_of_setup(struct device_node *node) + int num = ARRAY_SIZE(parent_names); + char name[12]; + struct clk_init_data init; ++ static int instance; + int i; + bool deprecated; + +@@ -118,7 +119,7 @@ static void __init clk_sp810_of_setup(struct device_node *node) + deprecated = !of_find_property(node, "assigned-clock-parents", NULL); + + for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) { +- snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); ++ snprintf(name, sizeof(name), "sp810_%d_%d", instance, i); + + sp810->timerclken[i].sp810 = sp810; + sp810->timerclken[i].channel = i; +@@ -139,5 +140,6 @@ static void __init clk_sp810_of_setup(struct device_node *node) + } + + of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810); ++ instance++; + } + CLK_OF_DECLARE(sp810, "arm,sp810", clk_sp810_of_setup); +diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c +index 7524941..5b6f57f 100644 +--- a/drivers/clocksource/tcb_clksrc.c ++++ b/drivers/clocksource/tcb_clksrc.c +@@ -73,6 +73,7 @@ static struct clocksource clksrc = { + struct tc_clkevt_device { + struct clock_event_device clkevt; + struct clk *clk; ++ bool clk_enabled; + u32 freq; + void __iomem *regs; + }; +@@ -84,6 +85,24 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) + + static u32 timer_clock; + ++static void tc_clk_disable(struct clock_event_device *d) ++{ ++ struct tc_clkevt_device *tcd = to_tc_clkevt(d); ++ ++ clk_disable(tcd->clk); ++ tcd->clk_enabled = false; ++} ++ ++static void tc_clk_enable(struct clock_event_device *d) ++{ ++ struct tc_clkevt_device *tcd = to_tc_clkevt(d); ++ ++ if (tcd->clk_enabled) ++ return; ++ clk_enable(tcd->clk); ++ tcd->clk_enabled = true; ++} ++ + static int tc_shutdown(struct clock_event_device *d) + { + struct tc_clkevt_device *tcd = to_tc_clkevt(d); +@@ -91,8 +110,14 @@ static int tc_shutdown(struct clock_event_device *d) + + __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); + __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); ++ return 0; ++} ++ ++static int tc_shutdown_clk_off(struct clock_event_device *d) ++{ ++ tc_shutdown(d); + if (!clockevent_state_detached(d)) +- clk_disable(tcd->clk); ++ tc_clk_disable(d); + + return 0; + } +@@ -105,7 +130,7 @@ static int tc_set_oneshot(struct clock_event_device *d) + if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) + tc_shutdown(d); + +- clk_enable(tcd->clk); ++ tc_clk_enable(d); + + /* count up to RC, then irq and stop */ + __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE | +@@ -127,7 +152,7 @@ static int tc_set_periodic(struct clock_event_device *d) + /* By not making the gentime core emulate periodic mode on top + * of oneshot, we get lower overhead and improved accuracy. + */ +- clk_enable(tcd->clk); ++ tc_clk_enable(d); + + /* count up to RC, then irq and restart */ + __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, +@@ -165,7 +190,7 @@ static struct tc_clkevt_device clkevt = { + .rating = 200, + #endif + .set_next_event = tc_next_event, +- .set_state_shutdown = tc_shutdown, ++ .set_state_shutdown = tc_shutdown_clk_off, + .set_state_periodic = tc_set_periodic, + .set_state_oneshot = tc_set_oneshot, + }, +diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c +index a7abdb6..7a40f7e 100644 +--- a/drivers/clocksource/timer-atmel-pit.c ++++ b/drivers/clocksource/timer-atmel-pit.c +@@ -46,6 +46,7 @@ struct pit_data { + u32 cycle; + u32 cnt; + unsigned int irq; ++ bool irq_requested; + struct clk *mck; + }; + +@@ -96,7 +97,10 @@ static int pit_clkevt_shutdown(struct clock_event_device *dev) + + /* disable irq, leaving the clocksource active */ + pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN); +- free_irq(data->irq, data); ++ if (data->irq_requested) { ++ free_irq(data->irq, data); ++ data->irq_requested = false; ++ } + return 0; + } + +@@ -115,6 +119,8 @@ static int pit_clkevt_set_periodic(struct clock_event_device *dev) + if (ret) + panic(pr_fmt("Unable to setup IRQ\n")); + ++ data->irq_requested = true; ++ + /* update clocksource counter */ + data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR)); + pit_write(data->base, AT91_PIT_MR, +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index 98fb882..f53b02a 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -667,6 +667,11 @@ static int core_get_max_pstate(void) + if (err) + goto skip_tar; + ++ /* For level 1 and 2, bits[23:16] contain the ratio */ ++ if (tdp_ctrl) ++ tdp_ratio >>= 16; ++ ++ tdp_ratio &= 0xff; /* ratios are only 8 bits long */ + if (tdp_ratio - 1 == tar) { + max_pstate = tar; + pr_debug("max_pstate=TAC %x\n", max_pstate); +diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c +index 545069d..e342565 100644 +--- a/drivers/cpuidle/cpuidle-arm.c ++++ b/drivers/cpuidle/cpuidle-arm.c +@@ -50,7 +50,7 @@ static int arm_enter_idle_state(struct cpuidle_device *dev, + * call the CPU ops suspend protocol with idle index as a + * parameter. + */ +- arm_cpuidle_suspend(idx); ++ ret = arm_cpuidle_suspend(idx); + + cpu_pm_exit(); + } +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index 17a6dc0..d40b2c0 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -214,7 +214,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, + tick_broadcast_exit(); + } + +- if (!cpuidle_state_is_coupled(drv, entered_state)) ++ if (!cpuidle_state_is_coupled(drv, index)) + local_irq_enable(); + + diff = ktime_to_us(ktime_sub(time_end, time_start)); +@@ -433,6 +433,8 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev) + list_del(&dev->device_list); + per_cpu(cpuidle_devices, dev->cpu) = NULL; + module_put(drv->owner); ++ ++ dev->registered = 0; + } + + static void __cpuidle_device_init(struct cpuidle_device *dev) +diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c +index fb16d81..1dffb13 100644 +--- a/drivers/crypto/atmel-aes.c ++++ b/drivers/crypto/atmel-aes.c +@@ -1396,9 +1396,9 @@ static int atmel_aes_probe(struct platform_device *pdev) + } + + aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res); +- if (!aes_dd->io_base) { ++ if (IS_ERR(aes_dd->io_base)) { + dev_err(dev, "can't ioremap\n"); +- err = -ENOMEM; ++ err = PTR_ERR(aes_dd->io_base); + goto res_err; + } + +diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c +index 3178f84..0dadb63 100644 +--- a/drivers/crypto/atmel-sha.c ++++ b/drivers/crypto/atmel-sha.c +@@ -1405,9 +1405,9 @@ static int atmel_sha_probe(struct platform_device *pdev) + } + + sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res); +- if (!sha_dd->io_base) { ++ if (IS_ERR(sha_dd->io_base)) { + dev_err(dev, "can't ioremap\n"); +- err = -ENOMEM; ++ err = PTR_ERR(sha_dd->io_base); + goto res_err; + } + +diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c +index 2c7a628..bf467d7 100644 +--- a/drivers/crypto/atmel-tdes.c ++++ b/drivers/crypto/atmel-tdes.c +@@ -1417,9 +1417,9 @@ static int atmel_tdes_probe(struct platform_device *pdev) + } + + tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res); +- if (!tdes_dd->io_base) { ++ if (IS_ERR(tdes_dd->io_base)) { + dev_err(dev, "can't ioremap\n"); +- err = -ENOMEM; ++ err = PTR_ERR(tdes_dd->io_base); + goto res_err; + } + +diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c +index 2085cb5..efa8cad 100644 +--- a/drivers/crypto/caam/jr.c ++++ b/drivers/crypto/caam/jr.c +@@ -248,7 +248,7 @@ static void caam_jr_dequeue(unsigned long devarg) + struct device *caam_jr_alloc(void) + { + struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL; +- struct device *dev = NULL; ++ struct device *dev = ERR_PTR(-ENODEV); + int min_tfm_cnt = INT_MAX; + int tfm_cnt; + +diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +index d89f20c..60fc0fa 100644 +--- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c ++++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +@@ -220,6 +220,42 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) + return ccp_aes_cmac_finup(req); + } + ++static int ccp_aes_cmac_export(struct ahash_request *req, void *out) ++{ ++ struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); ++ struct ccp_aes_cmac_exp_ctx state; ++ ++ /* Don't let anything leak to 'out' */ ++ memset(&state, 0, sizeof(state)); ++ ++ state.null_msg = rctx->null_msg; ++ memcpy(state.iv, rctx->iv, sizeof(state.iv)); ++ state.buf_count = rctx->buf_count; ++ memcpy(state.buf, rctx->buf, sizeof(state.buf)); ++ ++ /* 'out' may not be aligned so memcpy from local variable */ ++ memcpy(out, &state, sizeof(state)); ++ ++ return 0; ++} ++ ++static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) ++{ ++ struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); ++ struct ccp_aes_cmac_exp_ctx state; ++ ++ /* 'in' may not be aligned so memcpy to local variable */ ++ memcpy(&state, in, sizeof(state)); ++ ++ memset(rctx, 0, sizeof(*rctx)); ++ rctx->null_msg = state.null_msg; ++ memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); ++ rctx->buf_count = state.buf_count; ++ memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); ++ ++ return 0; ++} ++ + static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int key_len) + { +@@ -352,10 +388,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head) + alg->final = ccp_aes_cmac_final; + alg->finup = ccp_aes_cmac_finup; + alg->digest = ccp_aes_cmac_digest; ++ alg->export = ccp_aes_cmac_export; ++ alg->import = ccp_aes_cmac_import; + alg->setkey = ccp_aes_cmac_setkey; + + halg = &alg->halg; + halg->digestsize = AES_BLOCK_SIZE; ++ halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); + + base = &halg->base; + snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); +diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c +index 52c7395..0d0d452 100644 +--- a/drivers/crypto/ccp/ccp-crypto-aes-xts.c ++++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c +@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req, + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + unsigned int unit; ++ u32 unit_size; + int ret; + + if (!ctx->u.aes.key_len) +@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req, + if (!req->info) + return -EINVAL; + +- for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) +- if (!(req->nbytes & (unit_size_map[unit].size - 1))) +- break; ++ unit_size = CCP_XTS_AES_UNIT_SIZE__LAST; ++ if (req->nbytes <= unit_size_map[0].size) { ++ for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) { ++ if (!(req->nbytes & (unit_size_map[unit].size - 1))) { ++ unit_size = unit_size_map[unit].value; ++ break; ++ } ++ } ++ } + +- if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) || ++ if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) || + (ctx->u.aes.key_len != AES_KEYSIZE_128)) { + /* Use the fallback to process the request for any + * unsupported unit sizes or key sizes +@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req, + rctx->cmd.engine = CCP_ENGINE_XTS_AES_128; + rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT + : CCP_AES_ACTION_DECRYPT; +- rctx->cmd.u.xts.unit_size = unit_size_map[unit].value; ++ rctx->cmd.u.xts.unit_size = unit_size; + rctx->cmd.u.xts.key = &ctx->u.aes.key_sg; + rctx->cmd.u.xts.key_len = ctx->u.aes.key_len; + rctx->cmd.u.xts.iv = &rctx->iv_sg; +diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c +index d14b3f2..ab9945f 100644 +--- a/drivers/crypto/ccp/ccp-crypto-sha.c ++++ b/drivers/crypto/ccp/ccp-crypto-sha.c +@@ -207,6 +207,46 @@ static int ccp_sha_digest(struct ahash_request *req) + return ccp_sha_finup(req); + } + ++static int ccp_sha_export(struct ahash_request *req, void *out) ++{ ++ struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); ++ struct ccp_sha_exp_ctx state; ++ ++ /* Don't let anything leak to 'out' */ ++ memset(&state, 0, sizeof(state)); ++ ++ state.type = rctx->type; ++ state.msg_bits = rctx->msg_bits; ++ state.first = rctx->first; ++ memcpy(state.ctx, rctx->ctx, sizeof(state.ctx)); ++ state.buf_count = rctx->buf_count; ++ memcpy(state.buf, rctx->buf, sizeof(state.buf)); ++ ++ /* 'out' may not be aligned so memcpy from local variable */ ++ memcpy(out, &state, sizeof(state)); ++ ++ return 0; ++} ++ ++static int ccp_sha_import(struct ahash_request *req, const void *in) ++{ ++ struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); ++ struct ccp_sha_exp_ctx state; ++ ++ /* 'in' may not be aligned so memcpy to local variable */ ++ memcpy(&state, in, sizeof(state)); ++ ++ memset(rctx, 0, sizeof(*rctx)); ++ rctx->type = state.type; ++ rctx->msg_bits = state.msg_bits; ++ rctx->first = state.first; ++ memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx)); ++ rctx->buf_count = state.buf_count; ++ memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); ++ ++ return 0; ++} ++ + static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int key_len) + { +@@ -403,9 +443,12 @@ static int ccp_register_sha_alg(struct list_head *head, + alg->final = ccp_sha_final; + alg->finup = ccp_sha_finup; + alg->digest = ccp_sha_digest; ++ alg->export = ccp_sha_export; ++ alg->import = ccp_sha_import; + + halg = &alg->halg; + halg->digestsize = def->digest_size; ++ halg->statesize = sizeof(struct ccp_sha_exp_ctx); + + base = &halg->base; + snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); +diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h +index 76a96f0..a326ec2 100644 +--- a/drivers/crypto/ccp/ccp-crypto.h ++++ b/drivers/crypto/ccp/ccp-crypto.h +@@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx { + struct ccp_cmd cmd; + }; + ++struct ccp_aes_cmac_exp_ctx { ++ unsigned int null_msg; ++ ++ u8 iv[AES_BLOCK_SIZE]; ++ ++ unsigned int buf_count; ++ u8 buf[AES_BLOCK_SIZE]; ++}; ++ + /***** SHA related defines *****/ + #define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE + #define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE +@@ -171,6 +180,19 @@ struct ccp_sha_req_ctx { + struct ccp_cmd cmd; + }; + ++struct ccp_sha_exp_ctx { ++ enum ccp_sha_type type; ++ ++ u64 msg_bits; ++ ++ unsigned int first; ++ ++ u8 ctx[MAX_SHA_CONTEXT_SIZE]; ++ ++ unsigned int buf_count; ++ u8 buf[MAX_SHA_BLOCK_SIZE]; ++}; ++ + /***** Common Context Structure *****/ + struct ccp_ctx { + int (*complete)(struct crypto_async_request *req, int ret); +diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c +index c0656e7..80239ae 100644 +--- a/drivers/crypto/marvell/cesa.c ++++ b/drivers/crypto/marvell/cesa.c +@@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); + cesa->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(cesa->regs)) +- return -ENOMEM; ++ return PTR_ERR(cesa->regs); + + ret = mv_cesa_dev_dma_init(cesa); + if (ret) +diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h +index 3f76bd4..aa1dbea 100644 +--- a/drivers/crypto/qat/qat_common/adf_common_drv.h ++++ b/drivers/crypto/qat/qat_common/adf_common_drv.h +@@ -227,6 +227,8 @@ void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, + uint32_t vf_mask); + void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, + uint32_t vf_mask); ++int adf_init_pf_wq(void); ++void adf_exit_pf_wq(void); + #else + static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs) + { +@@ -236,5 +238,14 @@ static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs) + static inline void adf_disable_sriov(struct adf_accel_dev *accel_dev) + { + } ++ ++static inline int adf_init_pf_wq(void) ++{ ++ return 0; ++} ++ ++static inline void adf_exit_pf_wq(void) ++{ ++} + #endif + #endif +diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c +index 473d36d..e7480f3 100644 +--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c ++++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c +@@ -469,12 +469,17 @@ static int __init adf_register_ctl_device_driver(void) + if (adf_init_aer()) + goto err_aer; + ++ if (adf_init_pf_wq()) ++ goto err_pf_wq; ++ + if (qat_crypto_register()) + goto err_crypto_register; + + return 0; + + err_crypto_register: ++ adf_exit_pf_wq(); ++err_pf_wq: + adf_exit_aer(); + err_aer: + adf_chr_drv_destroy(); +@@ -487,6 +492,7 @@ static void __exit adf_unregister_ctl_device_driver(void) + { + adf_chr_drv_destroy(); + adf_exit_aer(); ++ adf_exit_pf_wq(); + qat_crypto_unregister(); + adf_clean_vf_map(false); + mutex_destroy(&adf_ctl_lock); +diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c +index 1117a8b..38a0415 100644 +--- a/drivers/crypto/qat/qat_common/adf_sriov.c ++++ b/drivers/crypto/qat/qat_common/adf_sriov.c +@@ -119,11 +119,6 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev) + int i; + u32 reg; + +- /* Workqueue for PF2VF responses */ +- pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq"); +- if (!pf2vf_resp_wq) +- return -ENOMEM; +- + for (i = 0, vf_info = accel_dev->pf.vf_info; i < totalvfs; + i++, vf_info++) { + /* This ptr will be populated when VFs will be created */ +@@ -216,11 +211,6 @@ void adf_disable_sriov(struct adf_accel_dev *accel_dev) + + kfree(accel_dev->pf.vf_info); + accel_dev->pf.vf_info = NULL; +- +- if (pf2vf_resp_wq) { +- destroy_workqueue(pf2vf_resp_wq); +- pf2vf_resp_wq = NULL; +- } + } + EXPORT_SYMBOL_GPL(adf_disable_sriov); + +@@ -304,3 +294,19 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs) + return numvfs; + } + EXPORT_SYMBOL_GPL(adf_sriov_configure); ++ ++int __init adf_init_pf_wq(void) ++{ ++ /* Workqueue for PF2VF responses */ ++ pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq"); ++ ++ return !pf2vf_resp_wq ? -ENOMEM : 0; ++} ++ ++void adf_exit_pf_wq(void) ++{ ++ if (pf2vf_resp_wq) { ++ destroy_workqueue(pf2vf_resp_wq); ++ pf2vf_resp_wq = NULL; ++ } ++} +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +index a19ee12..e72fea7 100644 +--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +@@ -35,6 +35,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) + unsigned int todo; + struct sg_mapping_iter mi, mo; + unsigned int oi, oo; /* offset for in and out */ ++ unsigned long flags; + + if (areq->nbytes == 0) + return 0; +@@ -49,7 +50,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) + return -EINVAL; + } + +- spin_lock_bh(&ss->slock); ++ spin_lock_irqsave(&ss->slock, flags); + + for (i = 0; i < op->keylen; i += 4) + writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); +@@ -117,7 +118,7 @@ release_ss: + sg_miter_stop(&mi); + sg_miter_stop(&mo); + writel(0, ss->base + SS_CTL); +- spin_unlock_bh(&ss->slock); ++ spin_unlock_irqrestore(&ss->slock, flags); + return err; + } + +@@ -149,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) + unsigned int ob = 0; /* offset in buf */ + unsigned int obo = 0; /* offset in bufo*/ + unsigned int obl = 0; /* length of data in bufo */ ++ unsigned long flags; + + if (areq->nbytes == 0) + return 0; +@@ -181,7 +183,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) + if (no_chunk == 1) + return sun4i_ss_opti_poll(areq); + +- spin_lock_bh(&ss->slock); ++ spin_lock_irqsave(&ss->slock, flags); + + for (i = 0; i < op->keylen; i += 4) + writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); +@@ -308,7 +310,7 @@ release_ss: + sg_miter_stop(&mi); + sg_miter_stop(&mo); + writel(0, ss->base + SS_CTL); +- spin_unlock_bh(&ss->slock); ++ spin_unlock_irqrestore(&ss->slock, flags); + + return err; + } +diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c +index b6f9f42..9a8a18a 100644 +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -63,6 +63,14 @@ static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr, + ptr->eptr = upper_32_bits(dma_addr); + } + ++static void copy_talitos_ptr(struct talitos_ptr *dst_ptr, ++ struct talitos_ptr *src_ptr, bool is_sec1) ++{ ++ dst_ptr->ptr = src_ptr->ptr; ++ if (!is_sec1) ++ dst_ptr->eptr = src_ptr->eptr; ++} ++ + static void to_talitos_ptr_len(struct talitos_ptr *ptr, unsigned int len, + bool is_sec1) + { +@@ -827,6 +835,16 @@ struct talitos_ahash_req_ctx { + struct scatterlist *psrc; + }; + ++struct talitos_export_state { ++ u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; ++ u8 buf[HASH_MAX_BLOCK_SIZE]; ++ unsigned int swinit; ++ unsigned int first; ++ unsigned int last; ++ unsigned int to_hash_later; ++ unsigned int nbuf; ++}; ++ + static int aead_setkey(struct crypto_aead *authenc, + const u8 *key, unsigned int keylen) + { +@@ -1083,21 +1101,20 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, + sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ?: 1, + (areq->src == areq->dst) ? DMA_BIDIRECTIONAL + : DMA_TO_DEVICE); +- + /* hmac data */ + desc->ptr[1].len = cpu_to_be16(areq->assoclen); + if (sg_count > 1 && + (ret = sg_to_link_tbl_offset(areq->src, sg_count, 0, + areq->assoclen, + &edesc->link_tbl[tbl_off])) > 1) { +- tbl_off += ret; +- + to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off * + sizeof(struct talitos_ptr), 0); + desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP; + + dma_sync_single_for_device(dev, edesc->dma_link_tbl, + edesc->dma_len, DMA_BIDIRECTIONAL); ++ ++ tbl_off += ret; + } else { + to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->src), 0); + desc->ptr[1].j_extent = 0; +@@ -1126,11 +1143,13 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, + if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV) + sg_link_tbl_len += authsize; + +- if (sg_count > 1 && +- (ret = sg_to_link_tbl_offset(areq->src, sg_count, areq->assoclen, +- sg_link_tbl_len, +- &edesc->link_tbl[tbl_off])) > 1) { +- tbl_off += ret; ++ if (sg_count == 1) { ++ to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src) + ++ areq->assoclen, 0); ++ } else if ((ret = sg_to_link_tbl_offset(areq->src, sg_count, ++ areq->assoclen, sg_link_tbl_len, ++ &edesc->link_tbl[tbl_off])) > ++ 1) { + desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP; + to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl + + tbl_off * +@@ -1138,8 +1157,10 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, + dma_sync_single_for_device(dev, edesc->dma_link_tbl, + edesc->dma_len, + DMA_BIDIRECTIONAL); +- } else +- to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src), 0); ++ tbl_off += ret; ++ } else { ++ copy_talitos_ptr(&desc->ptr[4], &edesc->link_tbl[tbl_off], 0); ++ } + + /* cipher out */ + desc->ptr[5].len = cpu_to_be16(cryptlen); +@@ -1151,11 +1172,13 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, + + edesc->icv_ool = false; + +- if (sg_count > 1 && +- (sg_count = sg_to_link_tbl_offset(areq->dst, sg_count, ++ if (sg_count == 1) { ++ to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst) + ++ areq->assoclen, 0); ++ } else if ((sg_count = ++ sg_to_link_tbl_offset(areq->dst, sg_count, + areq->assoclen, cryptlen, +- &edesc->link_tbl[tbl_off])) > +- 1) { ++ &edesc->link_tbl[tbl_off])) > 1) { + struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; + + to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl + +@@ -1178,8 +1201,9 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, + edesc->dma_len, DMA_BIDIRECTIONAL); + + edesc->icv_ool = true; +- } else +- to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst), 0); ++ } else { ++ copy_talitos_ptr(&desc->ptr[5], &edesc->link_tbl[tbl_off], 0); ++ } + + /* iv out */ + map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, +@@ -1940,6 +1964,46 @@ static int ahash_digest(struct ahash_request *areq) + return ahash_process_req(areq, areq->nbytes); + } + ++static int ahash_export(struct ahash_request *areq, void *out) ++{ ++ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); ++ struct talitos_export_state *export = out; ++ ++ memcpy(export->hw_context, req_ctx->hw_context, ++ req_ctx->hw_context_size); ++ memcpy(export->buf, req_ctx->buf, req_ctx->nbuf); ++ export->swinit = req_ctx->swinit; ++ export->first = req_ctx->first; ++ export->last = req_ctx->last; ++ export->to_hash_later = req_ctx->to_hash_later; ++ export->nbuf = req_ctx->nbuf; ++ ++ return 0; ++} ++ ++static int ahash_import(struct ahash_request *areq, const void *in) ++{ ++ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ const struct talitos_export_state *export = in; ++ ++ memset(req_ctx, 0, sizeof(*req_ctx)); ++ req_ctx->hw_context_size = ++ (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) ++ ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 ++ : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; ++ memcpy(req_ctx->hw_context, export->hw_context, ++ req_ctx->hw_context_size); ++ memcpy(req_ctx->buf, export->buf, export->nbuf); ++ req_ctx->swinit = export->swinit; ++ req_ctx->first = export->first; ++ req_ctx->last = export->last; ++ req_ctx->to_hash_later = export->to_hash_later; ++ req_ctx->nbuf = export->nbuf; ++ ++ return 0; ++} ++ + struct keyhash_result { + struct completion completion; + int err; +@@ -2334,6 +2398,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = MD5_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "md5", + .cra_driver_name = "md5-talitos", +@@ -2349,6 +2414,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA1_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "sha1", + .cra_driver_name = "sha1-talitos", +@@ -2364,6 +2430,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA224_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "sha224", + .cra_driver_name = "sha224-talitos", +@@ -2379,6 +2446,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA256_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "sha256", + .cra_driver_name = "sha256-talitos", +@@ -2394,6 +2462,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA384_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "sha384", + .cra_driver_name = "sha384-talitos", +@@ -2409,6 +2478,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA512_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "sha512", + .cra_driver_name = "sha512-talitos", +@@ -2424,6 +2494,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = MD5_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(md5)", + .cra_driver_name = "hmac-md5-talitos", +@@ -2439,6 +2510,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA1_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(sha1)", + .cra_driver_name = "hmac-sha1-talitos", +@@ -2454,6 +2526,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA224_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(sha224)", + .cra_driver_name = "hmac-sha224-talitos", +@@ -2469,6 +2542,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA256_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(sha256)", + .cra_driver_name = "hmac-sha256-talitos", +@@ -2484,6 +2558,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA384_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(sha384)", + .cra_driver_name = "hmac-sha384-talitos", +@@ -2499,6 +2574,7 @@ static struct talitos_alg_template driver_algs[] = { + { .type = CRYPTO_ALG_TYPE_AHASH, + .alg.hash = { + .halg.digestsize = SHA512_DIGEST_SIZE, ++ .halg.statesize = sizeof(struct talitos_export_state), + .halg.base = { + .cra_name = "hmac(sha512)", + .cra_driver_name = "hmac-sha512-talitos", +@@ -2519,21 +2595,11 @@ struct talitos_crypto_alg { + struct talitos_alg_template algt; + }; + +-static int talitos_cra_init(struct crypto_tfm *tfm) ++static int talitos_init_common(struct talitos_ctx *ctx, ++ struct talitos_crypto_alg *talitos_alg) + { +- struct crypto_alg *alg = tfm->__crt_alg; +- struct talitos_crypto_alg *talitos_alg; +- struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); + struct talitos_private *priv; + +- if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) +- talitos_alg = container_of(__crypto_ahash_alg(alg), +- struct talitos_crypto_alg, +- algt.alg.hash); +- else +- talitos_alg = container_of(alg, struct talitos_crypto_alg, +- algt.alg.crypto); +- + /* update context with ptr to dev */ + ctx->dev = talitos_alg->dev; + +@@ -2551,10 +2617,33 @@ static int talitos_cra_init(struct crypto_tfm *tfm) + return 0; + } + ++static int talitos_cra_init(struct crypto_tfm *tfm) ++{ ++ struct crypto_alg *alg = tfm->__crt_alg; ++ struct talitos_crypto_alg *talitos_alg; ++ struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); ++ ++ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) ++ talitos_alg = container_of(__crypto_ahash_alg(alg), ++ struct talitos_crypto_alg, ++ algt.alg.hash); ++ else ++ talitos_alg = container_of(alg, struct talitos_crypto_alg, ++ algt.alg.crypto); ++ ++ return talitos_init_common(ctx, talitos_alg); ++} ++ + static int talitos_cra_init_aead(struct crypto_aead *tfm) + { +- talitos_cra_init(crypto_aead_tfm(tfm)); +- return 0; ++ struct aead_alg *alg = crypto_aead_alg(tfm); ++ struct talitos_crypto_alg *talitos_alg; ++ struct talitos_ctx *ctx = crypto_aead_ctx(tfm); ++ ++ talitos_alg = container_of(alg, struct talitos_crypto_alg, ++ algt.alg.aead); ++ ++ return talitos_init_common(ctx, talitos_alg); + } + + static int talitos_cra_init_ahash(struct crypto_tfm *tfm) +@@ -2677,6 +2766,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, + t_alg->algt.alg.hash.finup = ahash_finup; + t_alg->algt.alg.hash.digest = ahash_digest; + t_alg->algt.alg.hash.setkey = ahash_setkey; ++ t_alg->algt.alg.hash.import = ahash_import; ++ t_alg->algt.alg.hash.export = ahash_export; + + if (!(priv->features & TALITOS_FTR_HMAC_OK) && + !strncmp(alg->cra_name, "hmac", 4)) { +diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c +index 4c243c1..790f7ca 100644 +--- a/drivers/crypto/ux500/cryp/cryp_core.c ++++ b/drivers/crypto/ux500/cryp/cryp_core.c +@@ -1440,9 +1440,9 @@ static int ux500_cryp_probe(struct platform_device *pdev) + + device_data->phybase = res->start; + device_data->base = devm_ioremap_resource(dev, res); +- if (!device_data->base) { ++ if (IS_ERR(device_data->base)) { + dev_err(dev, "[%s]: ioremap failed!", __func__); +- ret = -ENOMEM; ++ ret = PTR_ERR(device_data->base); + goto out; + } + +diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c +index f47d112..66b1c33 100644 +--- a/drivers/crypto/ux500/hash/hash_core.c ++++ b/drivers/crypto/ux500/hash/hash_core.c +@@ -1675,9 +1675,9 @@ static int ux500_hash_probe(struct platform_device *pdev) + + device_data->phybase = res->start; + device_data->base = devm_ioremap_resource(dev, res); +- if (!device_data->base) { ++ if (IS_ERR(device_data->base)) { + dev_err(dev, "%s: ioremap() failed!\n", __func__); +- ret = -ENOMEM; ++ ret = PTR_ERR(device_data->base); + goto out; + } + spin_lock_init(&device_data->ctx_lock); +diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c +index 4f099ea..c66133b 100644 +--- a/drivers/dma/dw/core.c ++++ b/drivers/dma/dw/core.c +@@ -130,26 +130,14 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) + static void dwc_initialize(struct dw_dma_chan *dwc) + { + struct dw_dma *dw = to_dw_dma(dwc->chan.device); +- struct dw_dma_slave *dws = dwc->chan.private; + u32 cfghi = DWC_CFGH_FIFO_MODE; + u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); + + if (dwc->initialized == true) + return; + +- if (dws) { +- /* +- * We need controller-specific data to set up slave +- * transfers. +- */ +- BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); +- +- cfghi |= DWC_CFGH_DST_PER(dws->dst_id); +- cfghi |= DWC_CFGH_SRC_PER(dws->src_id); +- } else { +- cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); +- cfghi |= DWC_CFGH_SRC_PER(dwc->src_id); +- } ++ cfghi |= DWC_CFGH_DST_PER(dwc->dst_id); ++ cfghi |= DWC_CFGH_SRC_PER(dwc->src_id); + + channel_writel(dwc, CFG_LO, cfglo); + channel_writel(dwc, CFG_HI, cfghi); +@@ -936,7 +924,7 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma_slave *dws = param; + +- if (!dws || dws->dma_dev != chan->device->dev) ++ if (dws->dma_dev != chan->device->dev) + return false; + + /* We have to copy data since dws can be temporary storage */ +@@ -1160,6 +1148,14 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) + * doesn't mean what you think it means), and status writeback. + */ + ++ /* ++ * We need controller-specific data to set up slave transfers. ++ */ ++ if (chan->private && !dw_dma_filter(chan, chan->private)) { ++ dev_warn(chan2dev(chan), "Wrong controller-specific data\n"); ++ return -EINVAL; ++ } ++ + /* Enable controller here if needed */ + if (!dw->in_use) + dw_dma_on(dw); +@@ -1221,6 +1217,14 @@ static void dwc_free_chan_resources(struct dma_chan *chan) + spin_lock_irqsave(&dwc->lock, flags); + list_splice_init(&dwc->free_list, &list); + dwc->descs_allocated = 0; ++ ++ /* Clear custom channel configuration */ ++ dwc->src_id = 0; ++ dwc->dst_id = 0; ++ ++ dwc->src_master = 0; ++ dwc->dst_master = 0; ++ + dwc->initialized = false; + + /* Disable interrupts */ +diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c +index 823ad72..efc02b9 100644 +--- a/drivers/dma/hsu/hsu.c ++++ b/drivers/dma/hsu/hsu.c +@@ -135,7 +135,7 @@ static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc) + sr = hsu_chan_readl(hsuc, HSU_CH_SR); + spin_unlock_irqrestore(&hsuc->vchan.lock, flags); + +- return sr; ++ return sr & ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY); + } + + irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr) +diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h +index f06579c..26da286 100644 +--- a/drivers/dma/hsu/hsu.h ++++ b/drivers/dma/hsu/hsu.h +@@ -41,6 +41,9 @@ + #define HSU_CH_SR_DESCTO(x) BIT(8 + (x)) + #define HSU_CH_SR_DESCTO_ANY (BIT(11) | BIT(10) | BIT(9) | BIT(8)) + #define HSU_CH_SR_CHE BIT(15) ++#define HSU_CH_SR_DESCE(x) BIT(16 + (x)) ++#define HSU_CH_SR_DESCE_ANY (BIT(19) | BIT(18) | BIT(17) | BIT(16)) ++#define HSU_CH_SR_CDESC_ANY (BIT(31) | BIT(30)) + + /* Bits in HSU_CH_CR */ + #define HSU_CH_CR_CHA BIT(0) +diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c +index a59061e..55f5d33 100644 +--- a/drivers/dma/pxa_dma.c ++++ b/drivers/dma/pxa_dma.c +@@ -122,6 +122,7 @@ struct pxad_chan { + struct pxad_device { + struct dma_device slave; + int nr_chans; ++ int nr_requestors; + void __iomem *base; + struct pxad_phy *phys; + spinlock_t phy_lock; /* Phy association */ +@@ -473,7 +474,7 @@ static void pxad_free_phy(struct pxad_chan *chan) + return; + + /* clear the channel mapping in DRCMR */ +- if (chan->drcmr <= DRCMR_CHLNUM) { ++ if (chan->drcmr <= pdev->nr_requestors) { + reg = pxad_drcmr(chan->drcmr); + writel_relaxed(0, chan->phy->base + reg); + } +@@ -509,6 +510,7 @@ static bool is_running_chan_misaligned(struct pxad_chan *chan) + + static void phy_enable(struct pxad_phy *phy, bool misaligned) + { ++ struct pxad_device *pdev; + u32 reg, dalgn; + + if (!phy->vchan) +@@ -518,7 +520,8 @@ static void phy_enable(struct pxad_phy *phy, bool misaligned) + "%s(); phy=%p(%d) misaligned=%d\n", __func__, + phy, phy->idx, misaligned); + +- if (phy->vchan->drcmr <= DRCMR_CHLNUM) { ++ pdev = to_pxad_dev(phy->vchan->vc.chan.device); ++ if (phy->vchan->drcmr <= pdev->nr_requestors) { + reg = pxad_drcmr(phy->vchan->drcmr); + writel_relaxed(DRCMR_MAPVLD | phy->idx, phy->base + reg); + } +@@ -914,6 +917,7 @@ static void pxad_get_config(struct pxad_chan *chan, + { + u32 maxburst = 0, dev_addr = 0; + enum dma_slave_buswidth width = DMA_SLAVE_BUSWIDTH_UNDEFINED; ++ struct pxad_device *pdev = to_pxad_dev(chan->vc.chan.device); + + *dcmd = 0; + if (dir == DMA_DEV_TO_MEM) { +@@ -922,7 +926,7 @@ static void pxad_get_config(struct pxad_chan *chan, + dev_addr = chan->cfg.src_addr; + *dev_src = dev_addr; + *dcmd |= PXA_DCMD_INCTRGADDR; +- if (chan->drcmr <= DRCMR_CHLNUM) ++ if (chan->drcmr <= pdev->nr_requestors) + *dcmd |= PXA_DCMD_FLOWSRC; + } + if (dir == DMA_MEM_TO_DEV) { +@@ -931,7 +935,7 @@ static void pxad_get_config(struct pxad_chan *chan, + dev_addr = chan->cfg.dst_addr; + *dev_dst = dev_addr; + *dcmd |= PXA_DCMD_INCSRCADDR; +- if (chan->drcmr <= DRCMR_CHLNUM) ++ if (chan->drcmr <= pdev->nr_requestors) + *dcmd |= PXA_DCMD_FLOWTRG; + } + if (dir == DMA_MEM_TO_MEM) +@@ -1341,13 +1345,15 @@ static struct dma_chan *pxad_dma_xlate(struct of_phandle_args *dma_spec, + + static int pxad_init_dmadev(struct platform_device *op, + struct pxad_device *pdev, +- unsigned int nr_phy_chans) ++ unsigned int nr_phy_chans, ++ unsigned int nr_requestors) + { + int ret; + unsigned int i; + struct pxad_chan *c; + + pdev->nr_chans = nr_phy_chans; ++ pdev->nr_requestors = nr_requestors; + INIT_LIST_HEAD(&pdev->slave.channels); + pdev->slave.device_alloc_chan_resources = pxad_alloc_chan_resources; + pdev->slave.device_free_chan_resources = pxad_free_chan_resources; +@@ -1382,7 +1388,7 @@ static int pxad_probe(struct platform_device *op) + const struct of_device_id *of_id; + struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev); + struct resource *iores; +- int ret, dma_channels = 0; ++ int ret, dma_channels = 0, nb_requestors = 0; + const enum dma_slave_buswidth widths = + DMA_SLAVE_BUSWIDTH_1_BYTE | DMA_SLAVE_BUSWIDTH_2_BYTES | + DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -1399,13 +1405,23 @@ static int pxad_probe(struct platform_device *op) + return PTR_ERR(pdev->base); + + of_id = of_match_device(pxad_dt_ids, &op->dev); +- if (of_id) ++ if (of_id) { + of_property_read_u32(op->dev.of_node, "#dma-channels", + &dma_channels); +- else if (pdata && pdata->dma_channels) ++ ret = of_property_read_u32(op->dev.of_node, "#dma-requests", ++ &nb_requestors); ++ if (ret) { ++ dev_warn(pdev->slave.dev, ++ "#dma-requests set to default 32 as missing in OF: %d", ++ ret); ++ nb_requestors = 32; ++ }; ++ } else if (pdata && pdata->dma_channels) { + dma_channels = pdata->dma_channels; +- else ++ nb_requestors = pdata->nb_requestors; ++ } else { + dma_channels = 32; /* default 32 channel */ ++ } + + dma_cap_set(DMA_SLAVE, pdev->slave.cap_mask); + dma_cap_set(DMA_MEMCPY, pdev->slave.cap_mask); +@@ -1422,7 +1438,7 @@ static int pxad_probe(struct platform_device *op) + pdev->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; + + pdev->slave.dev = &op->dev; +- ret = pxad_init_dmadev(op, pdev, dma_channels); ++ ret = pxad_init_dmadev(op, pdev, dma_channels, nb_requestors); + if (ret) { + dev_err(pdev->slave.dev, "unable to register\n"); + return ret; +@@ -1441,7 +1457,8 @@ static int pxad_probe(struct platform_device *op) + + platform_set_drvdata(op, pdev); + pxad_init_debugfs(pdev); +- dev_info(pdev->slave.dev, "initialized %d channels\n", dma_channels); ++ dev_info(pdev->slave.dev, "initialized %d channels on %d requestors\n", ++ dma_channels, nb_requestors); + return 0; + } + +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 9eee13e..d87a475 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, + u64 chan_off; + u64 dram_base = get_dram_base(pvt, range); + u64 hole_off = f10_dhar_offset(pvt); +- u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; ++ u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16; + + if (hi_rng) { + /* +diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c +index 01087a3..792bdae 100644 +--- a/drivers/edac/i7core_edac.c ++++ b/drivers/edac/i7core_edac.c +@@ -1866,7 +1866,7 @@ static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val, + + i7_dev = get_i7core_dev(mce->socketid); + if (!i7_dev) +- return NOTIFY_BAD; ++ return NOTIFY_DONE; + + mci = i7_dev->mci; + pvt = mci->pvt_info; +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index 429309c..3764922 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -1117,8 +1117,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", + n_tads, gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, +- (u32)TAD_SOCK(reg), +- (u32)TAD_CH(reg), ++ (u32)(1 << TAD_SOCK(reg)), ++ (u32)TAD_CH(reg) + 1, + (u32)TAD_TGT0(reg), + (u32)TAD_TGT1(reg), + (u32)TAD_TGT2(reg), +@@ -1396,7 +1396,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + } + + ch_way = TAD_CH(reg) + 1; +- sck_way = TAD_SOCK(reg) + 1; ++ sck_way = TAD_SOCK(reg); + + if (ch_way == 3) + idx = addr >> 6; +@@ -1435,7 +1435,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + switch(ch_way) { + case 2: + case 4: +- sck_xch = 1 << sck_way * (ch_way >> 1); ++ sck_xch = (1 << sck_way) * (ch_way >> 1); + break; + default: + sprintf(msg, "Invalid mirror set. Can't decode addr"); +@@ -1453,7 +1453,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + n_tads, + addr, + limit, +- (u32)TAD_SOCK(reg), ++ sck_way, + ch_way, + offset, + idx, +@@ -1468,18 +1468,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + offset, addr); + return -EINVAL; + } +- addr -= offset; +- /* Store the low bits [0:6] of the addr */ +- ch_addr = addr & 0x7f; +- /* Remove socket wayness and remove 6 bits */ +- addr >>= 6; +- addr = div_u64(addr, sck_xch); +-#if 0 +- /* Divide by channel way */ +- addr = addr / ch_way; +-#endif +- /* Recover the last 6 bits */ +- ch_addr |= addr << 6; ++ ++ ch_addr = addr - offset; ++ ch_addr >>= (6 + shiftup); ++ ch_addr /= sck_xch; ++ ch_addr <<= (6 + shiftup); ++ ch_addr |= addr & ((1 << (6 + shiftup)) - 1); + + /* + * Step 3) Decode rank +@@ -2260,7 +2254,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, + + mci = get_mci_for_node_id(mce->socketid); + if (!mci) +- return NOTIFY_BAD; ++ return NOTIFY_DONE; + pvt = mci->pvt_info; + + /* +diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c +index 9f9ea33..b6cb30d 100644 +--- a/drivers/extcon/extcon-max77843.c ++++ b/drivers/extcon/extcon-max77843.c +@@ -803,7 +803,7 @@ static int max77843_muic_probe(struct platform_device *pdev) + /* Clear IRQ bits before request IRQs */ + ret = regmap_bulk_read(max77843->regmap_muic, + MAX77843_MUIC_REG_INT1, info->status, +- MAX77843_MUIC_IRQ_NUM); ++ MAX77843_MUIC_STATUS_NUM); + if (ret) { + dev_err(&pdev->dev, "Failed to Clear IRQ bits\n"); + goto err_muic_irq; +diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c +index 027ca21..3b52677 100644 +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -180,6 +180,7 @@ static int generic_ops_register(void) + { + generic_ops.get_variable = efi.get_variable; + generic_ops.set_variable = efi.set_variable; ++ generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking; + generic_ops.get_next_variable = efi.get_next_variable; + generic_ops.query_variable_store = efi_query_variable_store; + +diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c +index 7f2ea21..6f182fd 100644 +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -202,29 +202,44 @@ static const struct variable_validate variable_validate[] = { + { NULL_GUID, "", NULL }, + }; + ++/* ++ * Check if @var_name matches the pattern given in @match_name. ++ * ++ * @var_name: an array of @len non-NUL characters. ++ * @match_name: a NUL-terminated pattern string, optionally ending in "*". A ++ * final "*" character matches any trailing characters @var_name, ++ * including the case when there are none left in @var_name. ++ * @match: on output, the number of non-wildcard characters in @match_name ++ * that @var_name matches, regardless of the return value. ++ * @return: whether @var_name fully matches @match_name. ++ */ + static bool + variable_matches(const char *var_name, size_t len, const char *match_name, + int *match) + { + for (*match = 0; ; (*match)++) { + char c = match_name[*match]; +- char u = var_name[*match]; + +- /* Wildcard in the matching name means we've matched */ +- if (c == '*') ++ switch (c) { ++ case '*': ++ /* Wildcard in @match_name means we've matched. */ + return true; + +- /* Case sensitive match */ +- if (!c && *match == len) +- return true; ++ case '\0': ++ /* @match_name has ended. Has @var_name too? */ ++ return (*match == len); + +- if (c != u) ++ default: ++ /* ++ * We've reached a non-wildcard char in @match_name. ++ * Continue only if there's an identical character in ++ * @var_name. ++ */ ++ if (*match < len && c == var_name[*match]) ++ continue; + return false; +- +- if (!c) +- return true; ++ } + } +- return true; + } + + bool +diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c +index 33a1f97..4ea71d5 100644 +--- a/drivers/gpio/gpio-bcm-kona.c ++++ b/drivers/gpio/gpio-bcm-kona.c +@@ -551,11 +551,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio) + /* disable interrupts and clear status */ + for (i = 0; i < kona_gpio->num_bank; i++) { + /* Unlock the entire bank first */ +- bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE); ++ bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE); + writel(0xffffffff, reg_base + GPIO_INT_MASK(i)); + writel(0xffffffff, reg_base + GPIO_INT_STATUS(i)); + /* Now re-lock the bank */ +- bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE); ++ bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE); + } + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index bb1099c..053fc2f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1673,6 +1673,7 @@ struct amdgpu_uvd { + struct amdgpu_bo *vcpu_bo; + void *cpu_addr; + uint64_t gpu_addr; ++ unsigned fw_version; + atomic_t handles[AMDGPU_MAX_UVD_HANDLES]; + struct drm_file *filp[AMDGPU_MAX_UVD_HANDLES]; + struct delayed_work idle_work; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +index 119cdc2..7ef2c13 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +@@ -194,12 +194,12 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector) + bpc = 8; + DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n", + connector->name, bpc); +- } else if (bpc > 8) { +- /* max_tmds_clock missing, but hdmi spec mandates it for deep color. */ +- DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n", +- connector->name); +- bpc = 8; + } ++ } else if (bpc > 8) { ++ /* max_tmds_clock missing, but hdmi spec mandates it for deep color. */ ++ DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n", ++ connector->name); ++ bpc = 8; + } + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +index 7b7f4ab..fe36caf 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +@@ -150,7 +150,7 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { +- vrefresh = amdgpu_crtc->hw_mode.vrefresh; ++ vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + break; + } + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +index e23843f..4488e82 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +@@ -303,7 +303,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file + fw_info.feature = adev->vce.fb_version; + break; + case AMDGPU_INFO_FW_UVD: +- fw_info.ver = 0; ++ fw_info.ver = adev->uvd.fw_version; + fw_info.feature = 0; + break; + case AMDGPU_INFO_FW_GMC: +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +index 064ebb3..89df787 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +@@ -52,7 +52,7 @@ struct amdgpu_hpd; + + #define AMDGPU_MAX_HPD_PINS 6 + #define AMDGPU_MAX_CRTCS 6 +-#define AMDGPU_MAX_AFMT_BLOCKS 7 ++#define AMDGPU_MAX_AFMT_BLOCKS 9 + + enum amdgpu_rmx_type { + RMX_OFF, +@@ -308,8 +308,8 @@ struct amdgpu_mode_info { + struct atom_context *atom_context; + struct card_info *atom_card_info; + bool mode_config_initialized; +- struct amdgpu_crtc *crtcs[6]; +- struct amdgpu_afmt *afmt[7]; ++ struct amdgpu_crtc *crtcs[AMDGPU_MAX_CRTCS]; ++ struct amdgpu_afmt *afmt[AMDGPU_MAX_AFMT_BLOCKS]; + /* DVI-I properties */ + struct drm_property *coherent_mode_property; + /* DAC enable load detect */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index b8fbbd7..73628c7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -540,6 +540,7 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, + if (!metadata_size) { + if (bo->metadata_size) { + kfree(bo->metadata); ++ bo->metadata = NULL; + bo->metadata_size = 0; + } + return 0; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +index 53f987a..3b35ad8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +@@ -156,6 +156,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) + DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n", + version_major, version_minor, family_id); + ++ adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) | ++ (family_id << 8)); ++ + bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8) + + AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE; + r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true, +@@ -273,6 +276,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev) + memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset, + (adev->uvd.fw->size) - offset); + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ + size = amdgpu_bo_size(adev->uvd.vcpu_bo); + size -= le32_to_cpu(hdr->ucode_size_bytes); + ptr = adev->uvd.cpu_addr; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +index a745eee..bb0da76 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +@@ -220,6 +220,7 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev) + if (i == AMDGPU_MAX_VCE_HANDLES) + return 0; + ++ cancel_delayed_work_sync(&adev->vce.idle_work); + /* TODO: suspending running encoding sessions isn't supported */ + return -EINVAL; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +index 1e0bba2..1cd6de5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c ++++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +@@ -298,6 +298,10 @@ bool amdgpu_atombios_encoder_mode_fixup(struct drm_encoder *encoder, + && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) + adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; + ++ /* vertical FP must be at least 1 */ ++ if (mode->crtc_vsync_start == mode->crtc_vdisplay) ++ adjusted_mode->crtc_vsync_start++; ++ + /* get the native mode for scaling */ + if (amdgpu_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + amdgpu_panel_mode_fixup(encoder, adjusted_mode); +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +index aa49154..9463007 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +@@ -3628,7 +3628,7 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned vm_id, uint64_t pd_addr) + { + int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); +- uint32_t seq = ring->fence_drv.sync_seq; ++ uint32_t seq = ring->fence_drv.sync_seq[ring->idx]; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +index 272110c..ea87033 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +@@ -898,14 +898,6 @@ static int gmc_v7_0_early_init(void *handle) + gmc_v7_0_set_gart_funcs(adev); + gmc_v7_0_set_irq_funcs(adev); + +- if (adev->flags & AMD_IS_APU) { +- adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; +- } else { +- u32 tmp = RREG32(mmMC_SEQ_MISC0); +- tmp &= MC_SEQ_MISC0__MT__MASK; +- adev->mc.vram_type = gmc_v7_0_convert_vram_type(tmp); +- } +- + return 0; + } + +@@ -926,6 +918,14 @@ static int gmc_v7_0_sw_init(void *handle) + if (r) + return r; + ++ if (adev->flags & AMD_IS_APU) { ++ adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; ++ } else { ++ u32 tmp = RREG32(mmMC_SEQ_MISC0); ++ tmp &= MC_SEQ_MISC0__MT__MASK; ++ adev->mc.vram_type = gmc_v7_0_convert_vram_type(tmp); ++ } ++ + r = amdgpu_irq_add_id(adev, 146, &adev->mc.vm_fault); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +index ba4ad00..0842308 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +@@ -852,14 +852,6 @@ static int gmc_v8_0_early_init(void *handle) + gmc_v8_0_set_gart_funcs(adev); + gmc_v8_0_set_irq_funcs(adev); + +- if (adev->flags & AMD_IS_APU) { +- adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; +- } else { +- u32 tmp = RREG32(mmMC_SEQ_MISC0); +- tmp &= MC_SEQ_MISC0__MT__MASK; +- adev->mc.vram_type = gmc_v8_0_convert_vram_type(tmp); +- } +- + return 0; + } + +@@ -870,6 +862,8 @@ static int gmc_v8_0_late_init(void *handle) + return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0); + } + ++#define mmMC_SEQ_MISC0_FIJI 0xA71 ++ + static int gmc_v8_0_sw_init(void *handle) + { + int r; +@@ -880,6 +874,19 @@ static int gmc_v8_0_sw_init(void *handle) + if (r) + return r; + ++ if (adev->flags & AMD_IS_APU) { ++ adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; ++ } else { ++ u32 tmp; ++ ++ if (adev->asic_type == CHIP_FIJI) ++ tmp = RREG32(mmMC_SEQ_MISC0_FIJI); ++ else ++ tmp = RREG32(mmMC_SEQ_MISC0); ++ tmp &= MC_SEQ_MISC0__MT__MASK; ++ adev->mc.vram_type = gmc_v8_0_convert_vram_type(tmp); ++ } ++ + r = amdgpu_irq_add_id(adev, 146, &adev->mc.vm_fault); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +index 2cf5018..b1c7a9b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c ++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +@@ -32,8 +32,8 @@ + #include "oss/oss_2_4_d.h" + #include "oss/oss_2_4_sh_mask.h" + +-#include "gmc/gmc_8_1_d.h" +-#include "gmc/gmc_8_1_sh_mask.h" ++#include "gmc/gmc_7_1_d.h" ++#include "gmc/gmc_7_1_sh_mask.h" + + #include "gca/gfx_8_0_d.h" + #include "gca/gfx_8_0_enum.h" +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +index c34c393..d5e19b5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +@@ -513,7 +513,7 @@ static int dbgdev_wave_control_set_registers( + union SQ_CMD_BITS *in_reg_sq_cmd, + union GRBM_GFX_INDEX_BITS *in_reg_gfx_index) + { +- int status; ++ int status = 0; + union SQ_CMD_BITS reg_sq_cmd; + union GRBM_GFX_INDEX_BITS reg_gfx_index; + struct HsaDbgWaveMsgAMDGen2 *pMsg; +diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c +index aeee083..aed2e3f 100644 +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -150,7 +150,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) + for (i = 0; i < state->num_connector; i++) { + struct drm_connector *connector = state->connectors[i]; + +- if (!connector) ++ if (!connector || !connector->funcs) + continue; + + /* +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index 24c5434..a02238c 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -3316,6 +3316,24 @@ int drm_mode_addfb2(struct drm_device *dev, + return 0; + } + ++struct drm_mode_rmfb_work { ++ struct work_struct work; ++ struct list_head fbs; ++}; ++ ++static void drm_mode_rmfb_work_fn(struct work_struct *w) ++{ ++ struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work); ++ ++ while (!list_empty(&arg->fbs)) { ++ struct drm_framebuffer *fb = ++ list_first_entry(&arg->fbs, typeof(*fb), filp_head); ++ ++ list_del_init(&fb->filp_head); ++ drm_framebuffer_remove(fb); ++ } ++} ++ + /** + * drm_mode_rmfb - remove an FB from the configuration + * @dev: drm device for the ioctl +@@ -3356,7 +3374,25 @@ int drm_mode_rmfb(struct drm_device *dev, + mutex_unlock(&dev->mode_config.fb_lock); + mutex_unlock(&file_priv->fbs_lock); + +- drm_framebuffer_unreference(fb); ++ /* ++ * we now own the reference that was stored in the fbs list ++ * ++ * drm_framebuffer_remove may fail with -EINTR on pending signals, ++ * so run this in a separate stack as there's no way to correctly ++ * handle this after the fb is already removed from the lookup table. ++ */ ++ if (atomic_read(&fb->refcount.refcount) > 1) { ++ struct drm_mode_rmfb_work arg; ++ ++ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); ++ INIT_LIST_HEAD(&arg.fbs); ++ list_add_tail(&fb->filp_head, &arg.fbs); ++ ++ schedule_work(&arg.work); ++ flush_work(&arg.work); ++ destroy_work_on_stack(&arg.work); ++ } else ++ drm_framebuffer_unreference(fb); + + return 0; + +@@ -3509,7 +3545,6 @@ out_err1: + return ret; + } + +- + /** + * drm_fb_release - remove and free the FBs on this file + * @priv: drm file for the ioctl +@@ -3524,6 +3559,9 @@ out_err1: + void drm_fb_release(struct drm_file *priv) + { + struct drm_framebuffer *fb, *tfb; ++ struct drm_mode_rmfb_work arg; ++ ++ INIT_LIST_HEAD(&arg.fbs); + + /* + * When the file gets released that means no one else can access the fb +@@ -3536,10 +3574,22 @@ void drm_fb_release(struct drm_file *priv) + * at it any more. + */ + list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { +- list_del_init(&fb->filp_head); ++ if (atomic_read(&fb->refcount.refcount) > 1) { ++ list_move_tail(&fb->filp_head, &arg.fbs); ++ } else { ++ list_del_init(&fb->filp_head); + +- /* This drops the fpriv->fbs reference. */ +- drm_framebuffer_unreference(fb); ++ /* This drops the fpriv->fbs reference. */ ++ drm_framebuffer_unreference(fb); ++ } ++ } ++ ++ if (!list_empty(&arg.fbs)) { ++ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); ++ ++ schedule_work(&arg.work); ++ flush_work(&arg.work); ++ destroy_work_on_stack(&arg.work); + } + } + +diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c +index 9535c5b..7e5a972 100644 +--- a/drivers/gpu/drm/drm_dp_helper.c ++++ b/drivers/gpu/drm/drm_dp_helper.c +@@ -178,7 +178,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, + { + struct drm_dp_aux_msg msg; + unsigned int retry; +- int err; ++ int err = 0; + + memset(&msg, 0, sizeof(msg)); + msg.address = offset; +@@ -186,6 +186,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, + msg.buffer = buffer; + msg.size = size; + ++ mutex_lock(&aux->hw_mutex); ++ + /* + * The specification doesn't give any recommendation on how often to + * retry native transactions. We used to retry 7 times like for +@@ -194,25 +196,24 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, + */ + for (retry = 0; retry < 32; retry++) { + +- mutex_lock(&aux->hw_mutex); + err = aux->transfer(aux, &msg); +- mutex_unlock(&aux->hw_mutex); + if (err < 0) { + if (err == -EBUSY) + continue; + +- return err; ++ goto unlock; + } + + + switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { + case DP_AUX_NATIVE_REPLY_ACK: + if (err < size) +- return -EPROTO; +- return err; ++ err = -EPROTO; ++ goto unlock; + + case DP_AUX_NATIVE_REPLY_NACK: +- return -EIO; ++ err = -EIO; ++ goto unlock; + + case DP_AUX_NATIVE_REPLY_DEFER: + usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100); +@@ -221,7 +222,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, + } + + DRM_DEBUG_KMS("too many retries, giving up\n"); +- return -EIO; ++ err = -EIO; ++ ++unlock: ++ mutex_unlock(&aux->hw_mutex); ++ return err; + } + + /** +@@ -543,9 +548,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) + int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz)); + + for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) { +- mutex_lock(&aux->hw_mutex); + ret = aux->transfer(aux, msg); +- mutex_unlock(&aux->hw_mutex); + if (ret < 0) { + if (ret == -EBUSY) + continue; +@@ -684,6 +687,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, + + memset(&msg, 0, sizeof(msg)); + ++ mutex_lock(&aux->hw_mutex); ++ + for (i = 0; i < num; i++) { + msg.address = msgs[i].addr; + drm_dp_i2c_msg_set_request(&msg, &msgs[i]); +@@ -738,6 +743,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, + msg.size = 0; + (void)drm_dp_i2c_do_msg(aux, &msg); + ++ mutex_unlock(&aux->hw_mutex); ++ + return err; + } + +diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c +index 39d7e2e..d268bf1 100644 +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1665,13 +1665,19 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb; + int len, ret, port_num; + ++ port = drm_dp_get_validated_port_ref(mgr, port); ++ if (!port) ++ return -EINVAL; ++ + port_num = port->port_num; + mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); + if (!mstb) { + mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); + +- if (!mstb) ++ if (!mstb) { ++ drm_dp_put_port(port); + return -EINVAL; ++ } + } + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); +@@ -1697,6 +1703,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, + kfree(txmsg); + fail_put: + drm_dp_put_mst_branch_device(mstb); ++ drm_dp_put_port(port); + return ret; + } + +@@ -1779,6 +1786,11 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) + req_payload.start_slot = cur_slots; + if (mgr->proposed_vcpis[i]) { + port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); ++ port = drm_dp_get_validated_port_ref(mgr, port); ++ if (!port) { ++ mutex_unlock(&mgr->payload_lock); ++ return -EINVAL; ++ } + req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; + } else { + port = NULL; +@@ -1804,6 +1816,9 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) + mgr->payloads[i].payload_state = req_payload.payload_state; + } + cur_slots += req_payload.num_slots; ++ ++ if (port) ++ drm_dp_put_port(port); + } + + for (i = 0; i < mgr->max_payloads; i++) { +@@ -2109,6 +2124,8 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr) + + if (mgr->mst_primary) { + int sret; ++ u8 guid[16]; ++ + sret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE); + if (sret != DP_RECEIVER_CAP_SIZE) { + DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n"); +@@ -2123,6 +2140,16 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr) + ret = -1; + goto out_unlock; + } ++ ++ /* Some hubs forget their guids after they resume */ ++ sret = drm_dp_dpcd_read(mgr->aux, DP_GUID, guid, 16); ++ if (sret != 16) { ++ DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n"); ++ ret = -1; ++ goto out_unlock; ++ } ++ drm_dp_check_mstb_guid(mgr->mst_primary, guid); ++ + ret = 0; + } else + ret = -1; +diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c +index 69cbab5..5ad0367 100644 +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1899,7 +1899,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, + int n, int width, int height) + { + int c, o; +- struct drm_device *dev = fb_helper->dev; + struct drm_connector *connector; + const struct drm_connector_helper_funcs *connector_funcs; + struct drm_encoder *encoder; +@@ -1918,7 +1917,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, + if (modes[n] == NULL) + return best_score; + +- crtcs = kzalloc(dev->mode_config.num_connector * ++ crtcs = kzalloc(fb_helper->connector_count * + sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); + if (!crtcs) + return best_score; +@@ -1964,7 +1963,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, + if (score > best_score) { + best_score = score; + memcpy(best_crtcs, crtcs, +- dev->mode_config.num_connector * ++ fb_helper->connector_count * + sizeof(struct drm_fb_helper_crtc *)); + } + } +diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +index 6b43ae3..1616af2 100644 +--- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c ++++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +@@ -72,7 +72,7 @@ static const char *const dsi_errors[] = { + "RX Prot Violation", + "HS Generic Write FIFO Full", + "LP Generic Write FIFO Full", +- "Generic Read Data Avail" ++ "Generic Read Data Avail", + "Special Packet Sent", + "Tearing Effect", + }; +diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c +index 0f42a27..80a1db0 100644 +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -812,6 +812,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ ++ preempt_disable_rt(); + + /* Get optional system timestamp before query. */ + if (stime) +@@ -863,6 +864,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, + *etime = ktime_get(); + + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ ++ preempt_enable_rt(); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index bc7b8fa..7e461dc 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -2838,7 +2838,14 @@ enum skl_disp_power_wells { + #define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998) + #define BXT_RP_STATE_CAP 0x138170 + +-#define INTERVAL_1_28_US(us) (((us) * 100) >> 7) ++/* ++ * Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS ++ * 8300) freezing up around GPU hangs. Looks as if even ++ * scheduling/timer interrupts start misbehaving if the RPS ++ * EI/thresholds are "bad", leading to a very sluggish or even ++ * frozen machine. ++ */ ++#define INTERVAL_1_28_US(us) roundup(((us) * 100) >> 7, 25) + #define INTERVAL_1_33_US(us) (((us) * 3) >> 2) + #define INTERVAL_0_833_US(us) (((us) * 6) / 5) + #define GT_INTERVAL_FROM_US(dev_priv, us) (IS_GEN9(dev_priv) ? \ +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index 6a2c76e..97d1ed2 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -248,8 +248,14 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, + pipe_config->has_pch_encoder = true; + + /* LPT FDI RX only supports 8bpc. */ +- if (HAS_PCH_LPT(dev)) ++ if (HAS_PCH_LPT(dev)) { ++ if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) { ++ DRM_DEBUG_KMS("LPT only supports 24bpp\n"); ++ return false; ++ } ++ + pipe_config->pipe_bpp = 24; ++ } + + /* FDI must always be 2.7 GHz */ + if (HAS_DDI(dev)) { +diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c +index 9e530a7..fc28c51 100644 +--- a/drivers/gpu/drm/i915/intel_csr.c ++++ b/drivers/gpu/drm/i915/intel_csr.c +@@ -180,7 +180,8 @@ struct stepping_info { + static const struct stepping_info skl_stepping_info[] = { + {'A', '0'}, {'B', '0'}, {'C', '0'}, + {'D', '0'}, {'E', '0'}, {'F', '0'}, +- {'G', '0'}, {'H', '0'}, {'I', '0'} ++ {'G', '0'}, {'H', '0'}, {'I', '0'}, ++ {'J', '0'}, {'K', '0'} + }; + + static struct stepping_info bxt_stepping_info[] = { +diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c +index 7e6158b..3c6b076 100644 +--- a/drivers/gpu/drm/i915/intel_ddi.c ++++ b/drivers/gpu/drm/i915/intel_ddi.c +@@ -464,9 +464,17 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, + } else if (IS_BROADWELL(dev)) { + ddi_translations_fdi = bdw_ddi_translations_fdi; + ddi_translations_dp = bdw_ddi_translations_dp; +- ddi_translations_edp = bdw_ddi_translations_edp; ++ ++ if (dev_priv->edp_low_vswing) { ++ ddi_translations_edp = bdw_ddi_translations_edp; ++ n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp); ++ } else { ++ ddi_translations_edp = bdw_ddi_translations_dp; ++ n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); ++ } ++ + ddi_translations_hdmi = bdw_ddi_translations_hdmi; +- n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp); ++ + n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); + n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); + hdmi_default_entry = 7; +@@ -3188,12 +3196,6 @@ void intel_ddi_get_config(struct intel_encoder *encoder, + intel_ddi_clock_get(encoder, pipe_config); + } + +-static void intel_ddi_destroy(struct drm_encoder *encoder) +-{ +- /* HDMI has nothing special to destroy, so we can go with this. */ +- intel_dp_encoder_destroy(encoder); +-} +- + static bool intel_ddi_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) + { +@@ -3212,7 +3214,8 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder, + } + + static const struct drm_encoder_funcs intel_ddi_funcs = { +- .destroy = intel_ddi_destroy, ++ .reset = intel_dp_encoder_reset, ++ .destroy = intel_dp_encoder_destroy, + }; + + static struct intel_connector * +@@ -3284,6 +3287,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) + intel_encoder->post_disable = intel_ddi_post_disable; + intel_encoder->get_hw_state = intel_ddi_get_hw_state; + intel_encoder->get_config = intel_ddi_get_config; ++ intel_encoder->suspend = intel_dp_encoder_suspend; + + intel_dig_port->port = port; + intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index f1c6c97..b32ff51 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -4447,7 +4447,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) + intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX); + + return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, +- &state->scaler_state.scaler_id, DRM_ROTATE_0, ++ &state->scaler_state.scaler_id, BIT(DRM_ROTATE_0), + state->pipe_src_w, state->pipe_src_h, + adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay); + } +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 78b8ec8..e55a82a 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -5035,7 +5035,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) + kfree(intel_dig_port); + } + +-static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) ++void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) + { + struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); + +@@ -5077,7 +5077,7 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) + edp_panel_vdd_schedule_off(intel_dp); + } + +-static void intel_dp_encoder_reset(struct drm_encoder *encoder) ++void intel_dp_encoder_reset(struct drm_encoder *encoder) + { + struct intel_dp *intel_dp; + +diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c +index 0639275..06bd925 100644 +--- a/drivers/gpu/drm/i915/intel_dp_mst.c ++++ b/drivers/gpu/drm/i915/intel_dp_mst.c +@@ -477,6 +477,8 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct intel_connector *intel_connector = to_intel_connector(connector); + struct drm_device *dev = connector->dev; + ++ intel_connector->unregister(intel_connector); ++ + /* need to nuke the connector */ + drm_modeset_lock_all(dev); + if (connector->state->crtc) { +@@ -490,11 +492,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + + WARN(ret, "Disabling mst crtc failed with %i\n", ret); + } +- drm_modeset_unlock_all(dev); + +- intel_connector->unregister(intel_connector); +- +- drm_modeset_lock_all(dev); + intel_connector_remove_from_fbdev(intel_connector); + drm_connector_cleanup(connector); + drm_modeset_unlock_all(dev); +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 0d00f07..f34a219 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -1204,6 +1204,8 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, + void intel_dp_start_link_train(struct intel_dp *intel_dp); + void intel_dp_stop_link_train(struct intel_dp *intel_dp); + void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); ++void intel_dp_encoder_reset(struct drm_encoder *encoder); ++void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder); + void intel_dp_encoder_destroy(struct drm_encoder *encoder); + int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc); + bool intel_dp_compute_config(struct intel_encoder *encoder, +diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c +index 4fd5fdf..c0c094d 100644 +--- a/drivers/gpu/drm/i915/intel_fbdev.c ++++ b/drivers/gpu/drm/i915/intel_fbdev.c +@@ -362,12 +362,12 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, + uint64_t conn_configured = 0, mask; + int pass = 0; + +- save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), ++ save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool), + GFP_KERNEL); + if (!save_enabled) + return false; + +- memcpy(save_enabled, enabled, dev->mode_config.num_connector); ++ memcpy(save_enabled, enabled, fb_helper->connector_count); + mask = (1 << fb_helper->connector_count) - 1; + retry: + for (i = 0; i < fb_helper->connector_count; i++) { +@@ -501,7 +501,7 @@ retry: + if (fallback) { + bail: + DRM_DEBUG_KMS("Not using firmware configuration\n"); +- memcpy(enabled, save_enabled, dev->mode_config.num_connector); ++ memcpy(enabled, save_enabled, fb_helper->connector_count); + kfree(save_enabled); + return false; + } +diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c +index e6c035b..4b8ed9f 100644 +--- a/drivers/gpu/drm/i915/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/intel_hdmi.c +@@ -1388,8 +1388,16 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) + hdmi_to_dig_port(intel_hdmi)); + } + +- if (!live_status) +- DRM_DEBUG_KMS("Live status not up!"); ++ if (!live_status) { ++ DRM_DEBUG_KMS("HDMI live status down\n"); ++ /* ++ * Live status register is not reliable on all intel platforms. ++ * So consider live_status only for certain platforms, for ++ * others, read EDID to determine presence of sink. ++ */ ++ if (INTEL_INFO(dev_priv)->gen < 7 || IS_IVYBRIDGE(dev_priv)) ++ live_status = true; ++ } + + intel_hdmi_unset_edid(connector); + +diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c +index d69547a..7058f75 100644 +--- a/drivers/gpu/drm/i915/intel_lrc.c ++++ b/drivers/gpu/drm/i915/intel_lrc.c +@@ -776,11 +776,11 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes) + if (unlikely(total_bytes > remain_usable)) { + /* + * The base request will fit but the reserved space +- * falls off the end. So only need to to wait for the +- * reserved size after flushing out the remainder. ++ * falls off the end. So don't need an immediate wrap ++ * and only need to effectively wait for the reserved ++ * size space from the start of ringbuffer. + */ + wait_bytes = remain_actual + ringbuf->reserved_size; +- need_wrap = true; + } else if (total_bytes > ringbuf->space) { + /* No wrapping required, just waiting. */ + wait_bytes = total_bytes; +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index f091ad1..62284e4 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3880,6 +3880,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); + ++ memset(active, 0, sizeof(*active)); ++ + active->pipe_enabled = intel_crtc->active; + + if (active->pipe_enabled) { +@@ -6620,6 +6622,12 @@ static void broadwell_init_clock_gating(struct drm_device *dev) + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + I915_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT); ++ /* ++ * Wait at least 100 clocks before re-enabling clock gating. See ++ * the definition of L3SQCREG1 in BSpec. ++ */ ++ POSTING_READ(GEN8_L3SQCREG1); ++ udelay(1); + I915_WRITE(GEN7_MISCCPCTL, misccpctl); + + /* +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c +index f6b2a81..9d48443 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -1922,6 +1922,17 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req, + return 0; + } + ++static void cleanup_phys_status_page(struct intel_engine_cs *ring) ++{ ++ struct drm_i915_private *dev_priv = to_i915(ring->dev); ++ ++ if (!dev_priv->status_page_dmah) ++ return; ++ ++ drm_pci_free(ring->dev, dev_priv->status_page_dmah); ++ ring->status_page.page_addr = NULL; ++} ++ + static void cleanup_status_page(struct intel_engine_cs *ring) + { + struct drm_i915_gem_object *obj; +@@ -1938,9 +1949,9 @@ static void cleanup_status_page(struct intel_engine_cs *ring) + + static int init_status_page(struct intel_engine_cs *ring) + { +- struct drm_i915_gem_object *obj; ++ struct drm_i915_gem_object *obj = ring->status_page.obj; + +- if ((obj = ring->status_page.obj) == NULL) { ++ if (obj == NULL) { + unsigned flags; + int ret; + +@@ -2134,7 +2145,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, + if (ret) + goto error; + } else { +- BUG_ON(ring->id != RCS); ++ WARN_ON(ring->id != RCS); + ret = init_phys_status_page(ring); + if (ret) + goto error; +@@ -2179,7 +2190,12 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) + if (ring->cleanup) + ring->cleanup(ring); + +- cleanup_status_page(ring); ++ if (I915_NEED_GFX_HWS(ring->dev)) { ++ cleanup_status_page(ring); ++ } else { ++ WARN_ON(ring->id != RCS); ++ cleanup_phys_status_page(ring); ++ } + + i915_cmd_parser_fini_ring(ring); + i915_gem_batch_pool_fini(&ring->batch_pool); +@@ -2341,11 +2357,11 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) + if (unlikely(total_bytes > remain_usable)) { + /* + * The base request will fit but the reserved space +- * falls off the end. So only need to to wait for the +- * reserved size after flushing out the remainder. ++ * falls off the end. So don't need an immediate wrap ++ * and only need to effectively wait for the reserved ++ * size space from the start of ringbuffer. + */ + wait_bytes = remain_actual + ringbuf->reserved_size; +- need_wrap = true; + } else if (total_bytes > ringbuf->space) { + /* No wrapping required, just waiting. */ + wait_bytes = total_bytes; +diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c +index 56dc132..8771d66 100644 +--- a/drivers/gpu/drm/i915/intel_sprite.c ++++ b/drivers/gpu/drm/i915/intel_sprite.c +@@ -38,6 +38,7 @@ + #include "intel_drv.h" + #include + #include "i915_drv.h" ++#include + + static bool + format_is_yuv(uint32_t format) +@@ -64,6 +65,8 @@ static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, + 1000 * adjusted_mode->crtc_htotal); + } + ++static DEFINE_LOCAL_IRQ_LOCK(pipe_update_lock); ++ + /** + * intel_pipe_update_start() - start update of a set of display registers + * @crtc: the crtc of which the registers are going to be updated +@@ -96,7 +99,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc) + min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); + max = vblank_start - 1; + +- local_irq_disable(); ++ local_lock_irq(pipe_update_lock); + + if (min <= 0 || max <= 0) + return; +@@ -126,11 +129,11 @@ void intel_pipe_update_start(struct intel_crtc *crtc) + break; + } + +- local_irq_enable(); ++ local_unlock_irq(pipe_update_lock); + + timeout = schedule_timeout(timeout); + +- local_irq_disable(); ++ local_lock_irq(pipe_update_lock); + } + + finish_wait(wq, &wait); +@@ -164,7 +167,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) + + trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); + +- local_irq_enable(); ++ local_unlock_irq(pipe_update_lock); + + if (crtc->debug.start_vbl_count && + crtc->debug.start_vbl_count != end_vbl_count) { +diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c +index 43cba12..cc91ae8 100644 +--- a/drivers/gpu/drm/i915/intel_uncore.c ++++ b/drivers/gpu/drm/i915/intel_uncore.c +@@ -1132,7 +1132,11 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) + } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + dev_priv->uncore.funcs.force_wake_get = + fw_domains_get_with_thread_status; +- dev_priv->uncore.funcs.force_wake_put = fw_domains_put; ++ if (IS_HASWELL(dev)) ++ dev_priv->uncore.funcs.force_wake_put = ++ fw_domains_put_with_fifo; ++ else ++ dev_priv->uncore.funcs.force_wake_put = fw_domains_put; + fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, + FORCEWAKE_MT, FORCEWAKE_ACK_HSW); + } else if (IS_IVYBRIDGE(dev)) { +diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c +index 7b990b4..5378bdc 100644 +--- a/drivers/gpu/drm/imx/imx-drm-core.c ++++ b/drivers/gpu/drm/imx/imx-drm-core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include